From abd44fe467d0381c0dd65a43489155fd89f3c6a2 Mon Sep 17 00:00:00 2001 From: yangy Date: Fri, 20 Mar 2026 09:31:24 +0800 Subject: [PATCH] Refactor Docker setup and remove unused files - Updated docker-compose.yml to rename backend and frontend container names for clarity. - Added volume mappings for frontend and backend services to persist data. - Removed obsolete files related to frequency response extraction, including Python scripts and output data files. - Adjusted backend port configuration in main.py to align with new service architecture. - Enhanced logging for file upload paths in models.py for better traceability. --- DEPLOY.md | 257 ++ .../data/over-ear/Kennerton Arkona.csv | 55 + .../data/over-ear/SoftEars RSV MKII.csv | 480 +++ backend/main.py | 2 +- backend/routes/models.py | 9 +- docker-compose.yml | 13 +- extract_frequency_response.py | 120 - frequency_response.csv | 535 --- frequency_response_curve.png | Bin 84358 -> 0 bytes frequency_response_detailed.json | 3228 ----------------- frequency_response_points.csv | 535 --- frequency_response_points.json | 2150 ----------- frontend/build-and-deploy.bat | 47 + frontend/nginx.conf | 2 +- frontend/src/views/model/index.vue | 52 +- 15 files changed, 878 insertions(+), 6607 deletions(-) create mode 100644 DEPLOY.md create mode 100644 autoeq/measurements/Eafonyoung/data/over-ear/Kennerton Arkona.csv create mode 100644 autoeq/measurements/Eafonyoung/data/over-ear/SoftEars RSV MKII.csv delete mode 100644 extract_frequency_response.py delete mode 100644 frequency_response.csv delete mode 100644 frequency_response_curve.png delete mode 100644 frequency_response_detailed.json delete mode 100644 frequency_response_points.csv delete mode 100644 frequency_response_points.json create mode 100644 frontend/build-and-deploy.bat diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..6e632b1 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,257 @@ +# 前端部署指南 + +## 📦 部署方式 + +### 方式一:本地构建后上传(推荐) + +#### 1. 本地构建 + +**Windows:** +```bash +cd frontend +pnpm build +``` + +**或者使用脚本:** +```bash +cd frontend +.\build-and-deploy.bat +``` + +**Linux/Mac:** +```bash +cd frontend +pnpm build +``` + +构建完成后会在 `frontend/dist` 目录生成静态文件。 + +#### 2. 上传到服务器 + +将 `dist` 文件夹上传到服务器的指定目录,例如: +```bash +# 在服务器上创建目录 +sudo mkdir -p /data/project/dashboard/frontend/dist + +# 上传文件(使用 scp、rsync 或 FTP 工具) +# 示例:使用 scp +scp -r dist/* user@server:/data/project/dashboard/frontend/dist/ + +# 或使用 rsync(推荐) +rsync -avz --progress dist/ user@server:/data/project/dashboard/frontend/dist/ +``` + +#### 3. 修改 docker-compose.yml + +确保使用简单的 Nginx 配置(不构建镜像): + +```yaml +version: '3.8' + +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: audio-dashboard-backend + environment: + - DATABASE_HOST=${DATABASE_HOST:-localhost} + - DATABASE_PORT=${DATABASE_PORT:-3306} + - DATABASE_NAME=${DATABASE_NAME:-audio} + - DATABASE_USER=${DATABASE_USER:-root} + - DATABASE_PASSWORD=${DATABASE_PASSWORD:-root123} + - APP_NAME=${APP_NAME:-Audio Dashboard API} + - DEBUG=${DEBUG:-True} + - MEILISEARCH_URL=${MEILISEARCH_URL:-http://ec2-18-184-205-87.eu-central-1.compute.amazonaws.com:7700} + - MEILISEARCH_API_KEY=${MEILISEARCH_API_KEY:-young9#!UJsD219921031} + - MEILISEARCH_INDEX=${MEILISEARCH_INDEX:-models} + ports: + - "8083:8000" + restart: unless-stopped + networks: + - audio-network + + frontend: + image: nginx:alpine + container_name: audio-dashboard-frontend + ports: + - "8082:80" + volumes: + - ./frontend/dist:/usr/share/nginx/html:ro + - ./frontend/nginx.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - backend + restart: unless-stopped + networks: + - audio-network + +networks: + audio-network: + driver: bridge +``` + +#### 4. 启动服务 + +在服务器上执行: +```bash +cd /data/project/dashboard +docker compose up -d +``` + +#### 5. 查看日志 + +```bash +# 查看所有服务日志 +docker compose logs -f + +# 查看前端日志 +docker compose logs -f frontend + +# 查看后端日志 +docker compose logs -f backend +``` + +#### 6. 访问应用 + +- 前端地址:http://服务器 IP:8082 +- 后端 API:http://服务器 IP:8083 +- API 文档:http://服务器 IP:8083/docs + +--- + +### 方式二:使用 Docker 构建(备选) + +如果你想让 Docker 自动构建前端: + +1. 上传整个 `frontend` 目录到服务器 +2. 使用原始的 `docker-compose.yml`(包含 `build` 配置) +3. 执行 `docker compose build --no-cache frontend` +4. 执行 `docker compose up -d` + +--- + +## 🔄 更新部署 + +### 仅更新前端 + +```bash +# 1. 本地重新构建 +cd frontend +pnpm build + +# 2. 上传 dist 目录到服务器 +rsync -avz --progress dist/ user@server:/data/project/dashboard/frontend/dist/ + +# 3. 重启前端容器 +docker compose restart frontend +``` + +### 仅更新后端 + +```bash +# 1. 上传修改的后端文件到服务器 + +# 2. 重新构建后端镜像 +docker compose build --no-cache backend + +# 3. 重启后端容器 +docker compose up -d backend +``` + +--- + +## 📝 注意事项 + +1. **确保后端端口正确** + - 后端服务运行在 8083 端口 + - Nginx 配置中已设置代理到 `http://backend:8000`(容器内部) + +2. **文件权限** + - 确保 dist 目录有读取权限 + - Nginx 容器需要能读取 dist 目录中的文件 + +3. **跨域问题** + - Nginx 已配置 `/api` 代理,前端请求会自动转发到后端 + - 不需要额外配置 CORS + +4. **缓存问题** + - 静态资源已配置长期缓存(1 年) + - 更新后如果浏览器缓存未更新,可以强制刷新(Ctrl+F5) + +--- + +## 🛠️ 常见问题 + +### Q: 前端页面空白 +A: 打开浏览器控制台查看错误,可能是: +- 后端服务未启动 +- API 代理配置错误 +- 静态文件路径错误 + +### Q: API 请求失败 +A: 检查: +- 后端容器是否正常运行:`docker compose ps` +- 后端日志是否有错误:`docker compose logs backend` +- 网络连接是否正常 + +### Q: 如何停止服务 +A: +```bash +# 停止所有服务 +docker compose down + +# 停止并删除数据卷(谨慎使用) +docker compose down -v +``` + +### Q: 如何查看服务状态 +A: +```bash +# 查看运行状态 +docker compose ps + +# 查看磁盘使用 +docker system df +``` + +--- + +## 📂 目录结构 + +``` +/data/project/dashboard/ +├── docker-compose.yml # Docker 编排配置 +├── backend/ +│ ├── Dockerfile # 后端镜像配置 +│ ├── main.py # 后端主程序 +│ ├── requirements.txt # Python 依赖 +│ └── ... +└── frontend/ + ├── dist/ # 构建产物(上传到这里) + │ ├── index.html + │ ├── assets/ + │ └── ... + └── nginx.conf # Nginx 配置 +``` + +--- + +## 🚀 快速部署命令汇总 + +```bash +# 1. 本地构建 +cd frontend && pnpm build + +# 2. 上传到服务器 +rsync -avz --progress dist/ user@server:/data/project/dashboard/frontend/dist/ + +# 3. 在服务器上启动 +cd /data/project/dashboard +docker compose up -d + +# 4. 查看状态 +docker compose ps + +# 5. 查看日志 +docker compose logs -f +``` diff --git a/autoeq/measurements/Eafonyoung/data/over-ear/Kennerton Arkona.csv b/autoeq/measurements/Eafonyoung/data/over-ear/Kennerton Arkona.csv new file mode 100644 index 0000000..2e1231f --- /dev/null +++ b/autoeq/measurements/Eafonyoung/data/over-ear/Kennerton Arkona.csv @@ -0,0 +1,55 @@ +frequency,raw +20,94.5 +25,95 +30,95.3 +35,95.8 +40,96.2 +45,96.5 +50,96.8 +60,97.2 +70,97.5 +80,97.8 +90,98 +100,98.2 +120,98.3 +150,98.1 +200,97.8 +250,96.5 +300,94 +350,92.3 +400,93 +500,94.2 +600,94.5 +700,94.3 +800,94 +900,93.8 +1000,94 +1200,95 +1500,97 +2000,101 +2500,102.5 +3000,103.5 +3500,102.8 +4000,101.5 +4500,102 +5000,104 +5500,102.2 +6000,99 +6500,97.5 +7000,96 +7500,93.5 +8000,91 +8500,92 +9000,90.5 +9500,89 +10000,90.1 +11000,88.5 +12000,87 +13000,85.5 +14000,87 +15000,84 +16000,86 +17000,83.5 +18000,85 +19000,84.5 +20000,86.2 diff --git a/autoeq/measurements/Eafonyoung/data/over-ear/SoftEars RSV MKII.csv b/autoeq/measurements/Eafonyoung/data/over-ear/SoftEars RSV MKII.csv new file mode 100644 index 0000000..e067fc4 --- /dev/null +++ b/autoeq/measurements/Eafonyoung/data/over-ear/SoftEars RSV MKII.csv @@ -0,0 +1,480 @@ +frequency,raw +20.299999,94.996101 +20.6,95.066643 +20.9,95.144516 +21.200001,95.228432 +21.4,95.28511 +21.799999,95.395599 +22.0,95.44735 +22.4,95.541397 +22.700001,95.603294 +23.0,95.657913 +23.299999,95.705841 +23.6,95.748344 +24.0,95.799728 +24.299999,95.83725 +24.700001,95.88855 +25.0,95.928101 +25.4,95.980354 +25.799999,96.029633 +26.200001,96.075699 +26.5,96.109299 +26.9,96.154068 +27.200001,96.187393 +27.6,96.229897 +28.0,96.268608 +28.5,96.313004 +29.0,96.35788 +29.5,96.404785 +30.0,96.449615 +30.4,96.481842 +30.700001,96.504662 +31.1,96.53595 +31.5,96.569824 +32.0,96.613136 +32.5,96.648773 +33.0,96.66954 +33.5,96.678368 +34.0,96.686768 +34.5,96.704086 +35.0,96.728386 +35.5,96.749596 +36.0,96.763016 +36.5,96.77597 +37.0,96.797897 +37.5,96.824867 +38.200001,96.842056 +38.700001,96.834427 +39.5,96.834557 +40.0,96.855278 +40.599998,96.877174 +41.200001,96.872879 +41.799999,96.855865 +42.5,96.853706 +43.099998,96.868835 +43.700001,96.881042 +44.400002,96.883163 +45.0,96.888336 +45.5,96.900337 +46.200001,96.902153 +46.799999,96.865395 +47.5,96.821083 +48.200001,96.834366 +48.700001,96.846642 +49.400002,96.793259 +50.0,96.719086 +50.799999,96.712097 +51.5,96.75267 +52.200001,96.748764 +53.0,96.732452 +53.799999,96.722679 +54.5,96.680412 +55.200001,96.635139 +56.0,96.605072 +57.0,96.587227 +58.0,96.586639 +59.0,96.526726 +60.0,96.481766 +60.799999,96.455208 +61.5,96.424332 +62.200001,96.398727 +63.0,96.362335 +64.0,96.314461 +65.0,96.25618 +66.0,96.243065 +67.0,96.265198 +68.0,96.15934 +69.0,96.088623 +70.0,96.037971 +71.0,95.960304 +72.0,95.919785 +73.0,95.863098 +74.0,95.799225 +75.0,95.750603 +76.199997,95.699684 +77.5,95.599792 +78.800003,95.52874 +80.0,95.463959 +81.199997,95.383324 +82.5,95.290344 +83.800003,95.294746 +85.0,95.154205 +86.199997,95.096016 +87.5,94.958595 +88.5,94.94532 +90.0,94.850182 +91.199997,94.758141 +92.5,94.677185 +93.800003,94.581398 +95.0,94.52774 +96.199997,94.439606 +97.5,94.3405 +98.800003,94.273293 +100.0,94.210823 +101.5,94.103004 +103.0,93.990761 +104.400002,93.891739 +106.0,93.795929 +107.5,93.693459 +109.0,93.592987 +110.599998,93.479187 +112.0,93.409836 +113.800003,93.262932 +115.0,93.141464 +117.199997,93.067558 +118.0,92.995972 +120.599998,92.803932 +122.0,92.743256 +124.099998,92.59726 +125.0,92.540604 +126.5,92.447647 +128.0,92.344604 +131.5,92.12764 +132.0,92.110634 +134.0,91.977051 +136.0,91.843063 +138.0,91.72435 +140.0,91.589684 +143.0,91.426208 +145.0,91.302574 +147.5,91.157066 +150.0,91.001816 +152.5,90.854004 +155.0,90.720329 +157.5,90.600082 +160.0,90.478554 +162.5,90.335724 +165.0,90.196289 +167.5,90.089241 +170.0,89.958069 +172.5,89.833351 +175.0,89.7397 +177.5,89.604416 +180.0,89.515884 +182.5,89.376976 +185.0,89.426125 +187.5,89.251961 +190.0,89.108307 +192.5,89.001175 +195.0,88.904205 +197.5,88.808601 +200.0,88.763168 +203.0,88.642723 +206.0,88.559433 +209.0,88.452774 +212.0,88.358932 +214.0,88.309219 +218.0,88.216202 +220.0,88.160881 +224.0,88.068573 +227.0,87.994759 +230.0,87.933731 +233.0,87.860107 +236.0,87.798866 +240.0,87.742653 +243.0,87.699585 +247.0,87.637108 +250.0,87.597519 +254.0,87.542038 +258.0,87.476494 +262.0,87.440033 +265.0,87.400261 +269.0,87.334351 +272.0,87.310989 +276.0,87.292473 +280.0,87.264496 +285.0,87.263863 +290.0,87.266548 +295.0,87.188141 +300.0,87.176109 +304.0,87.145096 +307.0,87.125824 +311.0,87.111427 +315.0,87.108704 +320.0,87.119164 +325.0,87.080658 +330.0,87.079872 +335.0,87.058044 +340.0,87.032623 +345.0,87.043648 +350.0,87.030876 +355.0,87.016029 +360.0,87.01844 +365.0,86.999924 +370.0,87.012589 +375.0,86.993011 +382.0,87.009193 +387.0,87.001778 +395.0,86.987289 +400.0,86.977364 +406.0,86.983284 +412.0,86.974007 +418.0,86.966125 +425.0,86.966347 +431.0,86.957985 +437.0,86.954689 +444.0,86.947784 +450.0,86.95256 +455.0,86.937927 +462.0,86.934189 +468.0,86.928482 +475.0,86.908051 +482.0,86.917679 +487.0,86.908447 +494.0,86.876709 +500.0,86.874756 +508.0,86.866798 +515.0,86.86277 +522.0,86.8535 +530.0,86.835083 +538.0,86.826447 +545.0,86.822144 +552.0,86.788559 +560.0,86.786629 +570.0,86.775848 +580.0,86.74791 +590.0,86.721291 +600.0,86.71302 +608.0,86.705421 +615.0,86.688232 +622.0,86.67942 +630.0,86.652893 +640.0,86.638512 +650.0,86.616013 +660.0,86.596329 +670.0,86.581268 +680.0,86.549599 +690.0,86.539116 +700.0,86.521683 +710.0,86.506607 +720.0,86.48912 +730.0,86.48027 +740.0,86.460587 +750.0,86.443459 +762.0,86.429535 +775.0,86.411072 +788.0,86.399559 +800.0,86.402443 +812.0,86.396225 +825.0,86.386002 +838.0,86.378235 +850.0,86.385986 +862.0,86.399521 +875.0,86.406715 +885.0,86.422165 +900.0,86.44931 +912.0,86.474152 +925.0,86.521378 +938.0,86.552628 +950.0,86.598076 +962.0,86.651535 +975.0,86.715912 +988.0,86.783661 +1000.0,86.844574 +1015.0,86.926735 +1030.0,87.028801 +1044.0,87.128235 +1060.0,87.238464 +1075.0,87.344162 +1090.0,87.461327 +1106.0,87.568489 +1120.0,87.673401 +1138.0,87.804008 +1150.0,87.883133 +1172.0,88.03363 +1180.0,88.088539 +1206.0,88.236641 +1220.0,88.312088 +1241.0,88.43586 +1250.0,88.486343 +1265.0,88.571785 +1280.0,88.670998 +1315.0,88.8508 +1320.0,88.875412 +1340.0,88.940201 +1360.0,88.999283 +1380.0,89.053871 +1400.0,89.098251 +1430.0,89.157188 +1450.0,89.199142 +1475.0,89.242676 +1500.0,89.286354 +1525.0,89.335205 +1550.0,89.378242 +1575.0,89.429764 +1600.0,89.474205 +1625.0,89.52272 +1650.0,89.577255 +1675.0,89.632195 +1700.0,89.693855 +1725.0,89.760017 +1750.0,89.816727 +1775.0,89.886528 +1800.0,89.959686 +1825.0,90.042648 +1850.0,90.123505 +1875.0,90.203667 +1900.0,90.294113 +1925.0,90.382721 +1950.0,90.494263 +1975.0,90.591408 +2000.0,90.700439 +2030.0,90.839371 +2060.0,90.985733 +2090.0,91.134712 +2120.0,91.287323 +2140.0,91.396133 +2180.0,91.609131 +2200.0,91.724281 +2240.0,91.953598 +2270.0,92.138763 +2300.0,92.318275 +2330.0,92.505653 +2360.0,92.696831 +2400.0,92.956299 +2430.0,93.150742 +2470.0,93.42971 +2500.0,93.635712 +2540.0,93.918365 +2580.0,94.188286 +2620.0,94.461639 +2650.0,94.654587 +2690.0,94.908905 +2720.0,95.086823 +2760.0,95.316727 +2800.0,95.515236 +2850.0,95.725677 +2900.0,95.887955 +2950.0,95.993484 +3000.0,96.046974 +3040.0,96.048676 +3070.0,96.030228 +3110.0,95.976227 +3150.0,95.896194 +3200.0,95.762047 +3250.0,95.602325 +3300.0,95.413963 +3350.0,95.214676 +3400.0,94.994156 +3450.0,94.771378 +3500.0,94.543541 +3550.0,94.316582 +3600.0,94.091095 +3650.0,93.875275 +3700.0,93.670792 +3750.0,93.471527 +3820.0,93.215836 +3870.0,93.046844 +3950.0,92.80426 +4000.0,92.675789 +4060.0,92.53064 +4120.0,92.413155 +4180.0,92.315628 +4250.0,92.22007 +4310.0,92.165283 +4370.0,92.117958 +4440.0,92.088135 +4500.0,92.082939 +4550.0,92.086319 +4620.0,92.101715 +4680.0,92.123383 +4750.0,92.15094 +4820.0,92.170921 +4870.0,92.189308 +4940.0,92.197998 +5000.0,92.188568 +5080.0,92.153671 +5150.0,92.084801 +5220.0,91.980217 +5300.0,91.808426 +5380.0,91.583267 +5450.0,91.332947 +5520.0,91.054901 +5600.0,90.688499 +5700.0,90.191238 +5800.0,89.689796 +5900.0,89.193619 +6000.0,88.745461 +6080.0,88.44545 +6150.0,88.223404 +6220.0,88.072449 +6300.0,87.983315 +6400.0,88.038513 +6500.0,88.258636 +6600.0,88.673828 +6700.0,89.277138 +6800.0,89.994736 +6900.0,90.812706 +7000.0,91.655334 +7100.0,92.422348 +7200.0,93.065163 +7300.0,93.554398 +7400.0,93.869781 +7500.0,94.051048 +7620.0,94.133606 +7750.0,94.134773 +7880.0,94.078163 +8000.0,93.996819 +8120.0,93.842842 +8250.0,93.55722 +8380.0,93.095657 +8500.0,92.506248 +8620.0,91.770233 +8750.0,90.851151 +8850.0,90.088356 +9000.0,88.926773 +9120.0,88.03231 +9250.0,87.08622 +9380.0,86.190002 +9500.0,85.408005 +9620.0,84.679283 +9750.0,83.974007 +9880.0,83.324043 +10000.0,82.770538 +10150.0,82.18972 +10300.0,81.671303 +10440.0,81.212059 +10600.0,80.802132 +10750.0,80.494598 +10900.0,80.208961 +11060.0,80.017876 +11200.0,79.931107 +11380.0,79.841034 +11500.0,79.796036 +11720.0,79.817871 +11800.0,79.856346 +12060.0,80.02198 +12200.0,80.189079 +12410.0,80.481339 +12500.0,80.588593 +12650.0,80.695976 +12800.0,80.655846 +13150.0,80.27346 +13200.0,80.22419 +13400.0,79.997185 +13600.0,79.924744 +13800.0,79.958786 +14000.0,80.192818 +14300.0,80.744476 +14500.0,81.346573 +14750.0,82.150314 +15000.0,83.122765 +15250.0,84.026924 +15500.0,84.569672 +15750.0,84.863876 +16000.0,84.89698 +16250.0,83.962463 +16500.0,81.495934 +16750.0,78.037849 +17000.0,74.585602 +17250.0,70.568008 +17500.0,67.431458 +17750.0,65.128929 +18000.0,63.996498 +18250.0,64.06855 +18500.0,63.473297 +18750.0,61.851959 +19000.0,59.501434 +19250.0,64.244003 +19500.0,64.423065 +19750.0,61.971725 diff --git a/backend/main.py b/backend/main.py index 349d09a..422a5cb 100644 --- a/backend/main.py +++ b/backend/main.py @@ -72,6 +72,6 @@ if __name__ == "__main__": uvicorn.run( "main:app", host="0.0.0.0", - port=8002, + port=8083, reload=False ) diff --git a/backend/routes/models.py b/backend/routes/models.py index 1e9878b..1027603 100644 --- a/backend/routes/models.py +++ b/backend/routes/models.py @@ -22,9 +22,13 @@ MEILISEARCH_API_KEY = os.getenv("MEILISEARCH_API_KEY", "") MEILISEARCH_INDEX = os.getenv("MEILISEARCH_INDEX", "models") # 文件上传配置 -UPLOAD_FOLDER = Path(__file__).parent.parent.parent / "autoeq" / "measurements" +UPLOAD_FOLDER = Path("/data/project/autoeq/measurements") ALLOWED_EXTENSIONS = {'.csv', '.txt', '.json'} +# 记录上传路径配置 +logger.info(f"UPLOAD_FOLDER configured as: {UPLOAD_FOLDER}") +logger.info(f"UPLOAD_FOLDER absolute path: {UPLOAD_FOLDER.absolute()}") + @router.get("/", response_model=ApiResponse) def get_models( @@ -104,6 +108,7 @@ def create_model( measurement_filename = None if measurement_file and measurement_file.filename: logger.info(f"Uploading measurement file: {measurement_file.filename}") + logger.info(f"UPLOAD_FOLDER is: {UPLOAD_FOLDER}") # 验证文件扩展名 file_ext = os.path.splitext(measurement_file.filename)[1].lower() if file_ext not in ALLOWED_EXTENSIONS: @@ -112,10 +117,12 @@ def create_model( # 创建保存路径:autoeq/measurements/{source}/data/{form}/{filename} save_dir = UPLOAD_FOLDER / source / "data" / form + logger.info(f"Creating directory: {save_dir}") save_dir.mkdir(parents=True, exist_ok=True) # 保存文件(保留原文件名) file_path = save_dir / measurement_file.filename + logger.info(f"Saving file to: {file_path}") with open(file_path, "wb") as buffer: shutil.copyfileobj(measurement_file.file, buffer) diff --git a/docker-compose.yml b/docker-compose.yml index 119de93..6af669a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: context: ./backend dockerfile: Dockerfile - container_name: audio-dashboard-backend + container_name: dashboard-backend environment: - DATABASE_HOST=${DATABASE_HOST:-localhost} - DATABASE_PORT=${DATABASE_PORT:-3306} @@ -22,14 +22,17 @@ services: restart: unless-stopped networks: - audio-network + volumes: + - /data/project/autoeq/measurements:/data/project/autoeq/measurements frontend: - build: - context: ./frontend - dockerfile: Dockerfile - container_name: audio-dashboard-frontend + image: nginx:alpine + container_name: dashboard-frontend ports: - "8082:80" + volumes: + - /data/project/dashboard/frontend/dist:/usr/share/nginx/html:ro + - /data/project/dashboard/frontend/nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - backend restart: unless-stopped diff --git a/extract_frequency_response.py b/extract_frequency_response.py deleted file mode 100644 index 829a6d1..0000000 --- a/extract_frequency_response.py +++ /dev/null @@ -1,120 +0,0 @@ -import cv2 -import numpy as np -import matplotlib.pyplot as plt -import json - -# 读取图片 -img_path = r"C:\Users\yangy\.cursor\projects\h-soft-projects-luxsin-dashboard/assets/c__Users_yangy_AppData_Roaming_Cursor_User_workspaceStorage_b134a9df77916b35c1e5b1ece8dc14fe_images_Arcona-avg-0b78da44-4aaa-465b-9b2b-fba051a28742.png" -img = cv2.imread(img_path) -img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) -img_copy = img.copy() -gray = cv2.cvtColor(img_copy, cv2.COLOR_RGB2GRAY) - -print(f"图片尺寸:{img_copy.shape}") -height, width = gray.shape - -# 定义图表区域(排除顶部标题和底部图例) -# 根据图片估算:顶部约 5%,底部约 8% -chart_top = int(height * 0.05) -chart_bottom = int(height * 0.92) -chart_left = int(width * 0.02) -chart_right = int(width * 0.98) - -# 裁剪出图表区域 -chart_roi = gray[chart_top:chart_bottom, chart_left:chart_right] - -# 使用阈值提取白色线条 -_, thresh = cv2.threshold(chart_roi, 200, 255, cv2.THRESH_BINARY) - -# 形态学操作,连接断开的线条 -kernel = np.ones((3,3), np.uint8) -dilated_thresh = cv2.dilate(thresh, kernel, iterations=2) -eroded_thresh = cv2.erode(dilated_thresh, kernel, iterations=1) - -# 查找轮廓 -contours, _ = cv2.findContours(eroded_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - -# 找到最大的连续轮廓(应该是频响曲线) -largest_contour = None -max_area = 0 - -for contour in contours: - area = cv2.contourArea(contour) - if area > max_area: - max_area = area - largest_contour = contour - -print(f"最大轮廓面积:{max_area}") - -# 提取频响曲线上的点 -frequency_points = [] - -if largest_contour is not None: - # 对于每个 x 坐标,找到对应的 y 坐标(取平均值) - x_coords = {} - - for point in largest_contour: - x, y = point[0] - # 转换回原图坐标 - global_x = int(x) + chart_left - global_y = int(y) + chart_top - - if global_x not in x_coords: - x_coords[global_x] = [] - x_coords[global_x].append(global_y) - - # 对每个 x,计算平均 y 值 - for x in sorted(x_coords.keys()): - y_values = x_coords[x] - avg_y = sum(y_values) // len(y_values) - frequency_points.append([int(x), int(avg_y)]) - - print(f"提取的频响曲线点数:{len(frequency_points)}") - - # 创建可视化结果 - result = img_copy.copy() - - # 绘制检测到的点 - for i, (x, y) in enumerate(frequency_points): - cv2.circle(result, (x, y), 1, (255, 0, 0), -1) - - # 显示结果 - plt.figure(figsize=(20, 10)) - plt.imshow(result) - plt.title(f'Extracted Frequency Response Curve ({len(frequency_points)} points)') - plt.axis('off') - plt.tight_layout() - plt.show() - - # 保存点到 JSON 文件 - output_data = { - "frequency_points": frequency_points, - "chart_area": { - "top": int(chart_top), - "bottom": int(chart_bottom), - "left": int(chart_left), - "right": int(chart_right) - }, - "image_size": { - "width": int(width), - "height": int(height) - } - } - - with open('frequency_response_points.json', 'w', encoding='utf-8') as f: - json.dump(output_data, f, ensure_ascii=False, indent=2) - - print(f"\n频响点位已保存到 frequency_response_points.json") - print(f"\n前 50 个点的坐标 (x, y):") - for i, point in enumerate(frequency_points[:50]): - print(f"{i+1}: {point}") - - # 也保存为 CSV 格式,方便查看 - with open('frequency_response_points.csv', 'w', encoding='utf-8') as f: - f.write("index,x,y\n") - for i, point in enumerate(frequency_points): - f.write(f"{i+1},{point[0]},{point[1]}\n") - - print(f"\n点位也已保存到 frequency_response_points.csv") -else: - print("未找到频响曲线") diff --git a/frequency_response.csv b/frequency_response.csv deleted file mode 100644 index f358881..0000000 --- a/frequency_response.csv +++ /dev/null @@ -1,535 +0,0 @@ -index,pixel_x,pixel_y,frequency_hz,db_value -1,278,236,122.58,99.03 -2,284,237,127.86,98.93 -3,285,236,128.76,99.03 -4,286,236,129.67,99.03 -5,287,238,130.58,98.83 -6,288,239,131.5,98.73 -7,289,236,132.43,99.03 -8,290,237,133.36,98.93 -9,295,237,138.13,98.93 -10,296,237,139.11,98.93 -11,297,238,140.09,98.83 -12,323,238,168.17,98.83 -13,324,237,169.36,98.93 -14,325,237,170.55,98.93 -15,334,238,181.69,98.83 -16,335,239,182.97,98.73 -17,339,240,188.18,98.63 -18,340,239,189.51,98.73 -19,341,239,190.85,98.73 -20,342,241,192.19,98.53 -21,343,242,193.55,98.43 -22,344,240,194.91,98.63 -23,345,241,196.29,98.53 -24,346,240,197.67,98.63 -25,347,241,199.07,98.53 -26,348,243,200.47,98.33 -27,349,242,201.88,98.43 -28,350,242,203.31,98.43 -29,352,244,206.18,98.23 -30,353,243,207.64,98.33 -31,354,243,209.1,98.33 -32,358,245,215.06,98.12 -33,359,244,216.58,98.23 -34,360,244,218.11,98.23 -35,361,246,219.65,98.02 -36,362,245,221.19,98.12 -37,363,245,222.75,98.12 -38,364,247,224.32,97.92 -39,365,248,225.91,97.82 -40,366,245,227.5,98.12 -41,367,247,229.1,97.92 -42,368,247,230.72,97.92 -43,369,248,232.35,97.82 -44,370,250,233.99,97.62 -45,371,248,235.64,97.82 -46,372,249,237.3,97.72 -47,373,249,238.97,97.72 -48,374,250,240.66,97.62 -49,375,250,242.35,97.62 -50,376,251,244.06,97.52 -51,377,251,245.78,97.52 -52,378,252,247.52,97.42 -53,379,252,249.26,97.42 -54,380,253,251.02,97.32 -55,381,253,252.79,97.32 -56,382,253,254.57,97.32 -57,383,255,256.37,97.12 -58,384,257,258.18,96.92 -59,385,255,260.0,97.12 -60,386,257,261.83,96.92 -61,387,259,263.68,96.71 -62,388,257,265.54,96.92 -63,389,257,267.41,96.92 -64,390,262,269.29,96.41 -65,391,262,271.19,96.41 -66,392,260,273.11,96.61 -67,393,260,275.03,96.61 -68,397,268,282.87,95.81 -69,398,266,284.87,96.01 -70,399,265,286.88,96.11 -71,408,278,305.6,94.8 -72,409,276,307.76,95.0 -73,410,275,309.93,95.1 -74,413,282,316.53,94.4 -75,414,282,318.77,94.4 -76,415,280,321.01,94.6 -77,416,282,323.28,94.4 -78,417,284,325.56,94.19 -79,418,283,327.85,94.29 -80,419,283,330.16,94.29 -81,420,284,332.49,94.19 -82,421,284,334.84,94.19 -83,422,285,337.2,94.09 -84,423,284,339.58,94.19 -85,424,285,341.97,94.09 -86,426,287,346.81,93.89 -87,427,288,349.26,93.79 -88,429,288,354.2,93.79 -89,430,287,356.7,93.89 -90,433,285,364.3,94.09 -91,434,284,366.87,94.19 -92,435,285,369.45,94.09 -93,436,284,372.06,94.19 -94,437,286,374.68,93.99 -95,438,284,377.33,94.19 -96,439,283,379.99,94.29 -97,440,283,382.67,94.29 -98,441,281,385.37,94.5 -99,442,282,388.08,94.4 -100,443,280,390.82,94.6 -101,444,281,393.58,94.5 -102,446,280,399.15,94.6 -103,447,278,401.96,94.8 -104,448,278,404.8,94.8 -105,449,278,407.65,94.8 -106,450,277,410.52,94.9 -107,451,279,413.42,94.7 -108,452,277,416.34,94.9 -109,453,276,419.27,95.0 -110,454,277,422.23,94.9 -111,455,275,425.21,95.1 -112,456,275,428.2,95.1 -113,457,275,431.22,95.1 -114,458,273,434.26,95.3 -115,459,276,437.33,95.0 -116,460,274,440.41,95.2 -117,461,272,443.52,95.4 -118,462,273,446.64,95.3 -119,463,272,449.79,95.4 -120,464,274,452.97,95.2 -121,465,272,456.16,95.4 -122,466,273,459.38,95.3 -123,467,270,462.62,95.6 -124,468,270,465.88,95.6 -125,469,269,469.16,95.71 -126,470,269,472.47,95.71 -127,471,268,475.8,95.81 -128,472,268,479.16,95.81 -129,473,267,482.54,95.91 -130,474,267,485.94,95.91 -131,475,268,489.37,95.81 -132,476,266,492.82,96.01 -133,477,264,496.3,96.21 -134,478,264,499.8,96.21 -135,479,264,503.32,96.21 -136,480,263,506.87,96.31 -137,481,263,510.44,96.31 -138,482,262,514.04,96.41 -139,483,262,517.67,96.41 -140,484,260,521.32,96.61 -141,485,261,524.99,96.51 -142,486,260,528.7,96.61 -143,487,260,532.43,96.61 -144,488,258,536.18,96.81 -145,489,259,539.96,96.71 -146,490,258,543.77,96.81 -147,491,260,547.6,96.61 -148,492,258,551.47,96.81 -149,493,256,555.35,97.02 -150,494,259,559.27,96.71 -151,495,257,563.21,96.92 -152,496,256,567.19,97.02 -153,497,257,571.19,96.92 -154,499,255,579.27,97.12 -155,500,255,583.36,97.12 -156,501,256,587.47,97.02 -157,502,254,591.61,97.22 -158,503,254,595.78,97.22 -159,504,255,599.99,97.12 -160,506,253,608.48,97.32 -161,507,253,612.77,97.32 -162,508,254,617.09,97.22 -163,513,253,639.16,97.32 -164,514,252,643.66,97.42 -165,519,252,666.68,97.42 -166,520,251,671.38,97.52 -167,537,251,756.58,97.52 -168,538,252,761.91,97.42 -169,541,253,778.14,97.32 -170,542,254,783.63,97.22 -171,543,251,789.16,97.52 -172,544,252,794.72,97.42 -173,545,254,800.33,97.22 -174,546,255,805.97,97.12 -175,547,252,811.66,97.42 -176,548,254,817.38,97.22 -177,549,256,823.14,97.02 -178,550,254,828.95,97.22 -179,551,255,834.79,97.12 -180,552,254,840.68,97.22 -181,553,256,846.61,97.02 -182,555,257,858.59,96.92 -183,556,259,864.65,96.71 -184,557,258,870.74,96.81 -185,558,258,876.88,96.81 -186,559,259,883.07,96.71 -187,560,259,889.3,96.71 -188,561,259,895.57,96.71 -189,562,261,901.88,96.51 -190,563,263,908.24,96.31 -191,564,262,914.65,96.41 -192,565,262,921.1,96.41 -193,566,263,927.59,96.31 -194,567,263,934.13,96.31 -195,568,266,940.72,96.01 -196,569,265,947.36,96.11 -197,570,267,954.04,95.91 -198,571,265,960.76,96.11 -199,572,266,967.54,96.01 -200,573,265,974.36,96.11 -201,574,267,981.23,95.91 -202,575,267,988.15,95.91 -203,576,268,995.12,95.81 -204,577,270,1002.14,95.6 -205,578,267,1009.21,95.91 -206,579,268,1016.32,95.81 -207,580,270,1023.49,95.6 -208,581,269,1030.71,95.71 -209,582,269,1037.98,95.71 -210,583,271,1045.3,95.5 -211,584,272,1052.67,95.4 -212,585,269,1060.09,95.71 -213,586,271,1067.57,95.5 -214,587,271,1075.1,95.5 -215,588,272,1082.68,95.4 -216,589,274,1090.31,95.2 -217,590,271,1098.0,95.5 -218,591,272,1105.74,95.4 -219,595,272,1137.27,95.4 -220,596,271,1145.29,95.5 -221,597,272,1153.36,95.4 -222,598,271,1161.5,95.5 -223,599,271,1169.69,95.5 -224,600,270,1177.94,95.6 -225,601,270,1186.24,95.6 -226,602,269,1194.61,95.71 -227,603,269,1203.03,95.71 -228,604,268,1211.52,95.81 -229,605,270,1220.06,95.6 -230,606,268,1228.66,95.81 -231,607,266,1237.33,96.01 -232,608,269,1246.05,95.71 -233,609,268,1254.84,95.81 -234,610,266,1263.69,96.01 -235,611,266,1272.6,96.01 -236,612,267,1281.58,95.91 -237,613,265,1290.61,96.11 -238,614,265,1299.71,96.11 -239,615,266,1308.88,96.01 -240,617,264,1327.41,96.21 -241,618,264,1336.77,96.21 -242,619,265,1346.19,96.11 -243,628,263,1434.08,96.31 -244,629,262,1444.2,96.41 -245,630,265,1454.38,96.11 -246,631,264,1464.64,96.21 -247,632,262,1474.97,96.41 -248,633,261,1485.37,96.51 -249,634,264,1495.84,96.21 -250,635,262,1506.39,96.41 -251,636,260,1517.01,96.61 -252,637,261,1527.71,96.51 -253,638,260,1538.48,96.61 -254,639,262,1549.33,96.41 -255,640,260,1560.26,96.61 -256,641,258,1571.26,96.81 -257,642,259,1582.34,96.71 -258,643,258,1593.5,96.81 -259,644,260,1604.74,96.61 -260,645,258,1616.06,96.81 -261,646,256,1627.45,97.02 -262,647,257,1638.93,96.92 -263,648,256,1650.49,97.02 -264,649,258,1662.13,96.81 -265,650,256,1673.85,97.02 -266,651,254,1685.65,97.22 -267,652,255,1697.54,97.12 -268,653,254,1709.51,97.22 -269,654,254,1721.56,97.22 -270,655,253,1733.7,97.32 -271,656,253,1745.93,97.32 -272,657,252,1758.24,97.42 -273,658,252,1770.64,97.42 -274,659,251,1783.13,97.52 -275,660,251,1795.7,97.52 -276,661,250,1808.37,97.62 -277,662,250,1821.12,97.62 -278,663,249,1833.96,97.72 -279,664,249,1846.89,97.72 -280,665,248,1859.92,97.82 -281,666,248,1873.03,97.82 -282,667,247,1886.24,97.92 -283,668,249,1899.54,97.72 -284,669,248,1912.94,97.82 -285,674,246,1981.35,98.02 -286,676,248,2009.39,97.82 -287,677,242,2023.56,98.43 -288,679,242,2052.2,98.43 -289,681,239,2081.25,98.73 -290,683,236,2110.71,99.03 -291,685,233,2140.58,99.33 -292,687,232,2170.88,99.44 -293,688,226,2186.19,100.04 -294,690,228,2217.13,99.84 -295,692,221,2248.51,100.54 -296,694,223,2280.33,100.34 -297,696,216,2312.61,101.05 -298,698,218,2345.34,100.85 -299,699,213,2361.88,101.35 -300,700,213,2378.54,101.35 -301,701,213,2395.31,101.35 -302,702,213,2412.2,101.35 -303,703,214,2429.21,101.25 -304,704,214,2446.34,101.25 -305,705,213,2463.59,101.35 -306,706,213,2480.97,101.35 -307,708,210,2516.08,101.65 -308,711,207,2569.69,101.96 -309,712,207,2587.81,101.96 -310,717,200,2680.35,102.66 -311,718,197,2699.25,102.96 -312,719,199,2718.29,102.76 -313,720,197,2737.46,102.96 -314,721,195,2756.76,103.17 -315,722,195,2776.2,103.17 -316,726,197,2855.35,102.96 -317,727,194,2875.48,103.27 -318,728,195,2895.76,103.17 -319,729,195,2916.18,103.17 -320,730,201,2936.74,102.56 -321,731,198,2957.45,102.86 -322,733,198,2999.31,102.86 -323,734,198,3020.46,102.86 -324,736,196,3063.22,103.06 -325,738,195,3106.57,103.17 -326,740,188,3150.54,103.87 -327,741,188,3172.76,103.87 -328,743,186,3217.66,104.07 -329,744,186,3240.35,104.07 -330,745,185,3263.21,104.17 -331,746,187,3286.22,103.97 -332,748,187,3332.73,103.97 -333,749,188,3356.23,103.87 -334,750,186,3379.9,104.07 -335,751,186,3403.73,104.07 -336,752,186,3427.74,104.07 -337,760,198,3625.96,102.86 -338,763,197,3703.21,102.96 -339,774,213,4000.82,101.35 -340,776,214,4057.45,101.25 -341,777,218,4086.06,100.85 -342,778,214,4114.87,101.25 -343,779,219,4143.89,100.75 -344,780,223,4173.11,100.34 -345,781,220,4202.54,100.65 -346,782,222,4232.18,100.44 -347,783,222,4262.02,100.44 -348,784,225,4292.08,100.14 -349,785,224,4322.35,100.24 -350,787,223,4383.52,100.34 -351,789,227,4445.57,99.94 -352,790,226,4476.92,100.04 -353,791,227,4508.49,99.94 -354,792,227,4540.28,99.94 -355,793,232,4572.3,99.44 -356,794,232,4604.54,99.44 -357,795,231,4637.02,99.54 -358,796,230,4669.72,99.64 -359,797,231,4702.65,99.54 -360,799,231,4769.21,99.54 -361,800,230,4802.84,99.64 -362,801,233,4836.71,99.33 -363,802,232,4870.82,99.44 -364,805,232,4974.59,99.44 -365,806,233,5009.67,99.33 -366,808,230,5080.58,99.64 -367,810,227,5152.49,99.94 -368,811,226,5188.82,100.04 -369,812,220,5225.41,100.65 -370,813,212,5262.26,101.45 -371,814,204,5299.37,102.26 -372,815,197,5336.74,102.96 -373,816,192,5374.38,103.47 -374,817,191,5412.28,103.57 -375,818,186,5450.44,104.07 -376,820,186,5527.59,104.07 -377,821,190,5566.57,103.67 -378,822,189,5605.82,103.77 -379,823,192,5645.35,103.47 -380,824,195,5685.17,103.17 -381,825,198,5725.26,102.86 -382,826,201,5765.63,102.56 -383,827,205,5806.29,102.16 -384,828,208,5847.24,101.85 -385,829,212,5888.47,101.45 -386,830,215,5930.0,101.15 -387,831,218,5971.81,100.85 -388,832,222,6013.93,100.44 -389,833,225,6056.34,100.14 -390,834,229,6099.05,99.74 -391,835,231,6142.06,99.54 -392,836,234,6185.37,99.23 -393,837,237,6228.99,98.93 -394,838,239,6272.92,98.73 -395,839,241,6317.15,98.53 -396,840,243,6361.7,98.33 -397,841,245,6406.56,98.12 -398,842,244,6451.74,98.23 -399,843,249,6497.24,97.72 -400,845,249,6589.2,97.72 -401,850,259,6824.83,96.71 -402,851,259,6872.96,96.71 -403,852,258,6921.43,96.81 -404,853,258,6970.24,96.81 -405,854,259,7019.39,96.71 -406,856,258,7118.74,96.81 -407,857,261,7168.94,96.51 -408,859,254,7270.41,97.22 -409,861,256,7373.31,97.02 -410,864,248,7530.41,97.82 -411,865,249,7583.51,97.72 -412,866,244,7636.99,98.23 -413,867,245,7690.84,98.12 -414,868,243,7745.08,98.33 -415,869,241,7799.7,98.53 -416,870,238,7854.7,98.83 -417,871,233,7910.09,99.33 -418,872,228,7965.87,99.84 -419,873,222,8022.05,100.44 -420,874,213,8078.62,101.35 -421,875,224,8135.59,100.24 -422,877,217,8250.74,100.95 -423,878,221,8308.92,100.54 -424,879,225,8367.52,100.14 -425,880,230,8426.52,99.64 -426,881,233,8485.95,99.33 -427,882,236,8545.79,99.03 -428,883,239,8606.06,98.73 -429,884,241,8666.75,98.53 -430,885,244,8727.86,98.23 -431,886,247,8789.41,97.92 -432,887,250,8851.39,97.62 -433,888,254,8913.81,97.22 -434,889,259,8976.67,96.71 -435,890,264,9039.98,96.21 -436,891,269,9103.73,95.71 -437,892,273,9167.93,95.3 -438,893,277,9232.58,94.9 -439,894,282,9297.69,94.4 -440,895,286,9363.25,93.99 -441,896,292,9429.28,93.39 -442,897,298,9495.78,92.78 -443,898,304,9562.74,92.18 -444,899,310,9630.18,91.57 -445,901,302,9766.48,92.38 -446,902,313,9835.35,91.27 -447,903,304,9904.71,92.18 -448,904,306,9974.56,91.98 -449,906,302,10115.73,92.38 -450,907,304,10187.07,92.18 -451,908,309,10258.91,91.67 -452,909,313,10331.26,91.27 -453,910,318,10404.11,90.77 -454,911,319,10477.48,90.67 -455,912,319,10551.37,90.67 -456,914,322,10700.71,90.36 -457,915,317,10776.17,90.87 -458,916,317,10852.16,90.87 -459,917,313,10928.69,91.27 -460,918,309,11005.76,91.67 -461,919,304,11083.37,92.18 -462,920,299,11161.53,92.68 -463,921,294,11240.24,93.19 -464,922,288,11319.51,93.79 -465,923,282,11399.33,94.4 -466,924,276,11479.72,95.0 -467,925,269,11560.68,95.71 -468,926,262,11642.2,96.41 -469,927,256,11724.3,97.02 -470,928,253,11806.98,97.32 -471,929,253,11890.24,97.32 -472,934,248,12315.45,97.82 -473,935,248,12402.29,97.82 -474,936,248,12489.75,97.82 -475,937,245,12577.83,98.12 -476,938,242,12666.53,98.43 -477,939,239,12755.85,98.73 -478,940,236,12845.81,99.03 -479,941,233,12936.4,99.33 -480,942,230,13027.62,99.64 -481,943,229,13119.49,99.74 -482,945,233,13305.18,99.33 -483,946,232,13399.01,99.44 -484,947,238,13493.5,98.83 -485,948,249,13588.66,97.72 -486,949,262,13684.48,96.41 -487,950,278,13780.98,94.8 -488,951,296,13878.17,92.98 -489,952,314,13976.04,91.17 -490,953,324,14074.59,90.16 -491,954,309,14173.85,91.67 -492,955,343,14273.8,88.25 -493,956,329,14374.46,89.66 -494,957,315,14475.83,91.07 -495,958,304,14577.91,92.18 -496,959,296,14680.71,92.98 -497,960,298,14784.24,92.78 -498,962,293,14993.49,93.29 -499,963,290,15099.23,93.59 -500,964,297,15205.71,92.88 -501,965,299,15312.94,92.68 -502,966,302,15420.92,92.38 -503,967,305,15529.67,92.08 -504,968,309,15639.19,91.67 -505,969,315,15749.47,91.07 -506,970,322,15860.54,90.36 -507,971,330,15972.39,89.56 -508,972,339,16085.02,88.65 -509,973,344,16198.45,88.15 -510,974,352,16312.68,87.34 -511,975,345,16427.72,88.04 -512,976,352,16543.57,87.34 -513,977,350,16660.23,87.54 -514,978,349,16777.72,87.64 -515,981,345,17135.18,88.04 -516,982,345,17256.01,88.04 -517,983,343,17377.7,88.25 -518,984,338,17500.25,88.75 -519,985,333,17623.66,89.25 -520,986,327,17747.94,89.86 -521,987,322,17873.1,90.36 -522,988,317,17999.14,90.87 -523,990,324,18253.89,90.16 -524,991,314,18382.62,91.17 -525,992,323,18512.25,90.26 -526,993,329,18642.8,89.66 -527,994,337,18774.27,88.85 -528,995,345,18906.67,88.04 -529,996,352,19039.99,87.34 -530,998,342,19309.48,88.35 -531,999,348,19445.65,87.74 -532,1000,343,19582.78,88.25 -533,1001,335,19720.88,89.05 -534,1002,337,19859.95,88.85 diff --git a/frequency_response_curve.png b/frequency_response_curve.png deleted file mode 100644 index 2359a91ba735e063759777877ac9401a886ebbb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84358 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 +echo ================================================ +echo 前端项目构建和部署脚本 +echo ================================================ +echo. + +cd /d "%~dp0" + +echo [1/3] 清理旧的构建文件... +if exist dist ( + rmdir /s /q dist + echo 已删除旧的 dist 目录 +) +echo. + +echo [2/3] 安装依赖并构建项目... +call pnpm install +if errorlevel 1 ( + echo. + echo ❌ 依赖安装失败,请检查网络连接 + pause + exit /b 1 +) + +call pnpm build +if errorlevel 1 ( + echo. + echo ❌ 构建失败,请检查错误信息 + pause + exit /b 1 +) +echo. + +echo [3/3] 构建完成! +echo. +echo ================================================ +echo 构建产物位置:%~dp0dist +echo ================================================ +echo. +echo 下一步操作: +echo 1. 将 dist 文件夹上传到服务器 +echo 2. 在服务器上运行:docker compose up -d +echo 3. 访问:http://服务器 IP:8082 +echo. +echo 文件已准备就绪,按任意键继续... +pause >nul diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 8666971..406f682 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -8,7 +8,7 @@ server { gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - # API proxy to backend + # API proxy to backend (使用后端容器名和端口) location /api { proxy_pass http://backend:8000; proxy_set_header Host $host; diff --git a/frontend/src/views/model/index.vue b/frontend/src/views/model/index.vue index bb74dd8..e22ced2 100644 --- a/frontend/src/views/model/index.vue +++ b/frontend/src/views/model/index.vue @@ -380,44 +380,34 @@ const handleDelete = (row) => { // 提交表单 const handleSubmit = async () => { if (!formRef.value) return - + await formRef.value.validate(async (valid) => { if (valid) { submitLoading.value = true try { - // 如果有文件,使用 FormData 上传 + // 始终使用 FormData 格式提交(后端需要 form-data) + const formDataUpload = new FormData() + formDataUpload.append('brand_name', formData.brand_name) + formDataUpload.append('name', formData.name) + formDataUpload.append('form', formData.form) + formDataUpload.append('rig', formData.rig) + formDataUpload.append('source', formData.source) + formDataUpload.append('eq_key', formData.eq_key || '') + + // 如果有文件,添加到 FormData if (uploadedFile.value) { - const formDataUpload = new FormData() - formDataUpload.append('brand_name', formData.brand_name) - formDataUpload.append('name', formData.name) - formDataUpload.append('form', formData.form) - formDataUpload.append('rig', formData.rig) - formDataUpload.append('source', formData.source) - formDataUpload.append('eq_key', formData.eq_key || '') formDataUpload.append('measurement_file', uploadedFile.value) - - const api = formData.id ? updateModel : createModel - const res = await api(formDataUpload, { isFormData: true }) - - if (res.code === 1) { - ElMessage.success(formData.id ? '更新成功' : '创建成功') - dialogVisible.value = false - loadData() - } else { - ElMessage.error(res.msg || '操作失败') - } + } + + const api = formData.id ? updateModel : createModel + const res = await api(formDataUpload, { isFormData: true }) + + if (res.code === 1) { + ElMessage.success(formData.id ? '更新成功' : '创建成功') + dialogVisible.value = false + loadData() } else { - // 没有文件,使用普通 JSON 提交 - const api = formData.id ? updateModel : createModel - const res = await api(formData) - - if (res.code === 1) { - ElMessage.success(formData.id ? '更新成功' : '创建成功') - dialogVisible.value = false - loadData() - } else { - ElMessage.error(res.msg || '操作失败') - } + ElMessage.error(res.msg || '操作失败') } } catch (error) { console.error('操作失败:', error)