339 lines
15 KiB
Markdown
339 lines
15 KiB
Markdown
# 项目概述
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [README.md](file://README.md)
|
||
- [DEPLOY.md](file://DEPLOY.md)
|
||
- [backend/README.md](file://backend/README.md)
|
||
- [frontend/README.md](file://frontend/README.md)
|
||
- [backend/package.json](file://backend/package.json)
|
||
- [frontend/package.json](file://frontend/package.json)
|
||
- [backend/src/app.js](file://backend/src/app.js)
|
||
- [backend/src/config/env.js](file://backend/src/config/env.js)
|
||
- [backend/src/models/index.js](file://backend/src/models/index.js)
|
||
- [backend/src/models/Brand.js](file://backend/src/models/Brand.js)
|
||
- [backend/src/models/Model.js](file://backend/src/models/Model.js)
|
||
- [backend/src/routes/brands.js](file://backend/src/routes/brands.js)
|
||
- [backend/src/routes/models.js](file://backend/src/routes/models.js)
|
||
- [backend/src/routes/ota.js](file://backend/src/routes/ota.js)
|
||
- [backend/src/routes/shareCodeLogs.js](file://backend/src/routes/shareCodeLogs.js)
|
||
- [frontend/src/main.js](file://frontend/src/main.js)
|
||
- [frontend/src/router/index.js](file://frontend/src/router/index.js)
|
||
- [docker-compose.yml](file://docker-compose.yml)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖关系分析](#依赖关系分析)
|
||
7. [性能考虑](#性能考虑)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本项目是一个面向“耳机品牌与型号管理”的全栈平台,采用前后端分离架构:前端使用 Vue 3 + Element Plus + Vue Router + Vite,后端使用 Express + Sequelize + MySQL,配合 Nginx 代理与 Docker Compose 进行部署。系统围绕四大核心业务展开:
|
||
- 品牌管理:对耳机品牌进行增删改查与分页检索
|
||
- 型号配置:管理型号元数据、频响测量文件上传与存储、EQ 缓存与 Meilisearch 搜索索引
|
||
- OTA 固件升级:支持 X8/X9 设备的升级包上传、版本管理与设备端“最新版本检查”
|
||
- 用户权限管理:基于 JWT 的登录认证、超级管理员可见的账号管理
|
||
- 分享码日志追踪:记录导入/导出等动作的 MAC 地址、分享码、IP、过期时间等审计信息
|
||
|
||
项目具备清晰的开发与生产部署流程,支持本地开发与 Docker 一键编排部署,便于团队协作与持续交付。
|
||
|
||
## 项目结构
|
||
项目采用多模块组织方式,前后端独立仓库,通过 Docker Compose 在同一网络中协同工作。根目录提供统一的环境变量与部署脚本,后端负责 API 服务与数据库交互,前端负责用户界面与路由导航。
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "前端"
|
||
FE_MAIN["frontend/src/main.js"]
|
||
FE_ROUTER["frontend/src/router/index.js"]
|
||
end
|
||
subgraph "后端"
|
||
BE_APP["backend/src/app.js"]
|
||
BE_ENV["backend/src/config/env.js"]
|
||
BE_MODELS["backend/src/models/index.js"]
|
||
BE_BRANDS["backend/src/routes/brands.js"]
|
||
BE_MODELS["backend/src/routes/models.js"]
|
||
BE_OTA["backend/src/routes/ota.js"]
|
||
BE_SHARE["backend/src/routes/shareCodeLogs.js"]
|
||
end
|
||
subgraph "基础设施"
|
||
DOCKER["docker-compose.yml"]
|
||
end
|
||
FE_MAIN --> FE_ROUTER
|
||
FE_ROUTER --> |"HTTP 请求"| BE_APP
|
||
BE_APP --> BE_ENV
|
||
BE_APP --> BE_MODELS
|
||
BE_MODELS --> BE_BRANDS
|
||
BE_MODELS --> BE_MODELS
|
||
BE_MODELS --> BE_OTA
|
||
BE_MODELS --> BE_SHARE
|
||
DOCKER --> FE_MAIN
|
||
DOCKER --> BE_APP
|
||
```
|
||
|
||
图表来源
|
||
- [frontend/src/main.js:1-26](file://frontend/src/main.js#L1-L26)
|
||
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
||
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
|
||
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
|
||
- [backend/src/models/index.js:1-8](file://backend/src/models/index.js#L1-L8)
|
||
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
|
||
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
|
||
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
|
||
- [backend/src/routes/shareCodeLogs.js:1-88](file://backend/src/routes/shareCodeLogs.js#L1-L88)
|
||
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
|
||
|
||
章节来源
|
||
- [README.md:1-94](file://README.md#L1-L94)
|
||
- [DEPLOY.md:1-269](file://DEPLOY.md#L1-L269)
|
||
- [backend/README.md:1-99](file://backend/README.md#L1-L99)
|
||
- [frontend/README.md:1-149](file://frontend/README.md#L1-L149)
|
||
|
||
## 核心组件
|
||
- 前端框架与生态
|
||
- Vue 3 + Composition API、Vue Router 4、Element Plus UI 组件库、Axios HTTP 客户端、Vite 构建工具
|
||
- 提供品牌/型号/OTA/分享码日志/账号管理等页面与路由守卫
|
||
- 后端框架与生态
|
||
- Express Web 框架、Sequelize ORM、MySQL 数据库、JWT 认证中间件、Multer 文件上传、Winston 日志
|
||
- 提供品牌、型号、OTA、分享码日志等业务路由与数据模型
|
||
- 基础设施与部署
|
||
- Docker Compose 编排:Nginx 前端静态站点 + Node.js 后端 API + MySQL 数据持久化
|
||
- 环境变量集中管理,支持 Meilisearch、S3、Redis、OTA 存储等外部服务集成
|
||
|
||
章节来源
|
||
- [frontend/package.json:1-24](file://frontend/package.json#L1-L24)
|
||
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
|
||
- [frontend/src/main.js:1-26](file://frontend/src/main.js#L1-L26)
|
||
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
||
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
|
||
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
|
||
|
||
## 架构总览
|
||
系统采用“前端 Nginx + 后端 Express + 数据库/缓存/对象存储”三层架构。前端通过 Nginx 将 /api 前缀代理至后端服务,后端通过 Sequelize 访问 MySQL,结合 Redis、S3、Meilisearch 实现缓存、文件存储与搜索索引能力。
|
||
|
||
```mermaid
|
||
graph TB
|
||
Client["浏览器客户端"] --> Nginx["Nginx 反向代理<br/>前端静态资源与 /api 代理"]
|
||
Nginx --> Express["Express 后端 API<br/>JWT 认证 + 路由层"]
|
||
Express --> Sequelize["Sequelize ORM"]
|
||
Sequelize --> MySQL["MySQL 数据库"]
|
||
Express --> Redis["Redis 缓存<br/>EQ 缓存键/字段"]
|
||
Express --> S3["S3 对象存储<br/>频响文件/OTA 包"]
|
||
Express --> Meili["Meilisearch<br/>型号搜索索引"]
|
||
```
|
||
|
||
图表来源
|
||
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
|
||
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
|
||
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
|
||
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
|
||
|
||
## 详细组件分析
|
||
|
||
### 品牌管理(Brand)
|
||
- 数据模型:品牌表包含自增主键与唯一名称
|
||
- 路由接口:支持分页、模糊查询、创建、更新、删除
|
||
- 关键流程:参数校验、重复性检查、日志记录、统一响应封装
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant R as "品牌路由"
|
||
participant M as "品牌模型"
|
||
participant L as "日志"
|
||
C->>R : "GET /api/brands/?skip&limit&name"
|
||
R->>M : "findAndCountAll(where, offset, limit)"
|
||
M-->>R : "rows, count"
|
||
R->>L : "info(...)"
|
||
R-->>C : "ApiResponse.success({items,total,skip,limit})"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/src/routes/brands.js:14-40](file://backend/src/routes/brands.js#L14-L40)
|
||
- [backend/src/models/Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
|
||
|
||
章节来源
|
||
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
|
||
- [backend/src/models/Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
|
||
|
||
### 型号配置(Model)
|
||
- 数据模型:型号表包含品牌名、型号名、形式、阻抗、来源、EQ 键、创建时间等字段
|
||
- 路由接口:支持分页、过滤、排序、上传频响文件(CSV/TXT/JSON)、S3 存储、Meilisearch 推送/查询、Redis EQ 缓存读取
|
||
- 关键流程:TXT 转 CSV、文件类型校验、S3 上传、Meilisearch 文档管理、缓存键/字段读取
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入 /api/models/"]) --> Parse["解析查询参数<br/>skip, limit, brand_name, name, sort"]
|
||
Parse --> BuildWhere["构造 where 条件"]
|
||
BuildWhere --> Count["统计总数"]
|
||
Count --> Find["分页查询记录"]
|
||
Find --> Found{"是否有记录?"}
|
||
Found -- 否 --> NoData["返回无数据响应"]
|
||
Found -- 是 --> MapItems["映射字段为返回结构"]
|
||
MapItems --> Done["返回成功响应"]
|
||
```
|
||
|
||
图表来源
|
||
- [backend/src/routes/models.js:133-181](file://backend/src/routes/models.js#L133-L181)
|
||
|
||
章节来源
|
||
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
|
||
- [backend/src/models/Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
|
||
|
||
### OTA 固件升级(OTA)
|
||
- 数据模型:OTA 记录包含版本号/名称、下载地址、MD5、强制标志、设备型号/硬件版本、有效期、状态等
|
||
- 路由接口:上传升级包(X8 上传至 S3,X9 本地存储)、设备端“最新版本检查”、后台版本管理 CRUD
|
||
- 关键流程:文件内容读取与 MD5 校验、S3/X9 存储策略、版本冲突检测、统一响应封装
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Dev as "设备端"
|
||
participant API as "OTA 路由"
|
||
participant DB as "OTA 模型"
|
||
Dev->>API : "GET /api/ota/latest/check?currentVerCode&model&hw"
|
||
API->>DB : "findOne({where : status=1, verCode>current, model, hw})"
|
||
DB-->>API : "最新 OTA 记录"
|
||
API-->>Dev : "ApiResponse.success(OTA 信息)"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/src/routes/ota.js:68-102](file://backend/src/routes/ota.js#L68-L102)
|
||
|
||
章节来源
|
||
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
|
||
|
||
### 分享码日志追踪(ShareCodeLog)
|
||
- 数据模型:记录导入/导出动作的 MAC 地址、分享码、IP、EQ 数据、过期时间、创建时间
|
||
- 路由接口:支持按 MAC/分享码/IP/动作/时间范围过滤,分页排序
|
||
- 关键流程:条件拼装、范围查询、统一响应封装
|
||
|
||
章节来源
|
||
- [backend/src/routes/shareCodeLogs.js:1-88](file://backend/src/routes/shareCodeLogs.js#L1-L88)
|
||
|
||
### 用户权限与前端路由
|
||
- 前端路由守卫:登录态校验、Token 过期处理、超级管理员可见区域
|
||
- 登录页面与重定向:未登录访问受保护路由自动跳转登录页,已登录访问 /login 自动跳首页
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Enter(["进入页面"]) --> NeedAuth{"是否需要登录?"}
|
||
NeedAuth -- 否 --> Allow["放行"]
|
||
NeedAuth -- 是 --> HasToken{"是否存在有效 Token?"}
|
||
HasToken -- 否 --> RedirectLogin["清除无效状态并跳转登录页"]
|
||
HasToken -- 是 --> SuperAdmin{"是否为超级管理员?"}
|
||
SuperAdmin -- 否 --> Deny["跳回首页"]
|
||
SuperAdmin -- 是 --> Allow
|
||
```
|
||
|
||
图表来源
|
||
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
||
|
||
章节来源
|
||
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
||
|
||
## 依赖关系分析
|
||
- 前端依赖:Vue 3、Element Plus、Vue Router、Axios、Vite
|
||
- 后端依赖:Express、Sequelize、MySQL、JWT、Multer、Axios、Winston、ioredis、@aws-sdk
|
||
- 部署依赖:Docker、Docker Compose、Nginx、Node.js
|
||
|
||
```mermaid
|
||
graph LR
|
||
FE_PKG["frontend/package.json"] --> FE_DEPS["Vue/ElementPlus/VueRouter/Axios/Vite"]
|
||
BE_PKG["backend/package.json"] --> BE_DEPS["Express/Sequelize/MySQL/JWT/Multer/AWS SDK/Winston/ioredis"]
|
||
COMPOSE["docker-compose.yml"] --> INFRA["Nginx/Node/MySQL/网络卷"]
|
||
```
|
||
|
||
图表来源
|
||
- [frontend/package.json:1-24](file://frontend/package.json#L1-L24)
|
||
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
|
||
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
|
||
|
||
章节来源
|
||
- [frontend/package.json:1-24](file://frontend/package.json#L1-L24)
|
||
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
|
||
- [docker-compose.yml:1-46](file://docker-compose.yml#L1-L46)
|
||
|
||
## 性能考虑
|
||
- 前端
|
||
- 使用 Vite 构建与热更新,减少开发等待时间
|
||
- Element Plus 组件按需加载,避免不必要的包体积
|
||
- 后端
|
||
- 分页查询限制每页最大条数,避免大结果集导致内存压力
|
||
- 文件上传使用内存存储(Multer memoryStorage),建议在高并发场景结合 CDN/S3
|
||
- Meilisearch 推送批量处理,避免频繁小请求
|
||
- 基础设施
|
||
- Docker 日志轮转,防止磁盘爆满
|
||
- Nginx 代理静态资源与 API,提升并发与缓存效率
|
||
|
||
## 故障排查指南
|
||
- 前端页面空白
|
||
- 检查前端构建产物是否上传至 Nginx 目录
|
||
- 查看浏览器控制台 404 或 API 错误
|
||
- 使用 docker logs frontend 定位问题
|
||
- API 请求失败
|
||
- 确认后端容器状态为 running
|
||
- 查看 docker logs backend,关注数据库、Redis、Meilisearch 连接错误
|
||
- 确认 Nginx 代理目标为 http://backend:8000
|
||
- 后端构建失败(Node/pnpm 版本)
|
||
- 后端镜像基于 node:22-alpine,确保上传 package.json 与 pnpm-lock.yaml
|
||
- 修改 .env 不生效
|
||
- 通过 docker compose up -d --force-recreate 使新环境变量生效
|
||
- 停止服务
|
||
- 使用 docker compose down 停止所有容器
|
||
|
||
章节来源
|
||
- [DEPLOY.md:226-256](file://DEPLOY.md#L226-L256)
|
||
|
||
## 结论
|
||
本项目以清晰的前后端分离架构与完善的部署方案,提供了耳机品牌与型号管理所需的完整能力:品牌与型号的精细化管理、频响文件与 EQ 缓存的高效利用、OTA 升级包的统一管控、用户权限与分享码审计。通过 Docker Compose 一键编排,既满足本地开发的灵活性,也保障了生产环境的稳定性与可扩展性。
|
||
|
||
## 附录
|
||
|
||
### 快速开始(系统要求)
|
||
- 前端
|
||
- Node.js(与 package.json 中固定版本一致)、pnpm
|
||
- 浏览器访问 http://localhost:3000
|
||
- 后端
|
||
- Node.js(与 package.json 中固定版本一致)、pnpm
|
||
- MySQL 数据库(表结构由 Sequelize 自动同步)
|
||
- 可选:Redis、Meilisearch、S3 凭据(用于高级功能)
|
||
|
||
章节来源
|
||
- [frontend/README.md:36-71](file://frontend/README.md#L36-L71)
|
||
- [backend/README.md:32-59](file://backend/README.md#L32-L59)
|
||
- [DEPLOY.md:259-269](file://DEPLOY.md#L259-L269)
|
||
|
||
### 快速开始(安装步骤)
|
||
- 本地开发
|
||
- 后端:根目录创建 .env,cd backend && pnpm install && pnpm start
|
||
- 前端:cd frontend && pnpm install && pnpm dev
|
||
- 访问 http://localhost:3000(/api 代理至 8083)
|
||
- Docker 部署
|
||
- 本地构建前端:cd frontend && pnpm build
|
||
- 上传脚本:./scripts/upload.sh all
|
||
- 服务器:cd /data/project/dashboard && docker compose build --no-cache backend && docker compose up -d
|
||
- 访问 http://服务器IP:8082(前端)与 http://服务器IP:8083(后端 API)
|
||
|
||
章节来源
|
||
- [DEPLOY.md:49-118](file://DEPLOY.md#L49-L118)
|
||
- [frontend/README.md:36-71](file://frontend/README.md#L36-L71)
|
||
|
||
### 快速开始(基本使用)
|
||
- 品牌管理:在“品牌管理”页面进行新增/编辑/删除与分页查询
|
||
- 型号管理:在“型号管理”页面上传频响文件、查看/编辑型号信息、推送至搜索索引
|
||
- OTA 管理:在“OTA 管理”页面上传升级包、设置版本与有效期、设备端查询最新版本
|
||
- 分享码日志:在“分享日志”页面筛选导入/导出记录,审计 MAC/IP/过期时间
|
||
- 账号管理:仅超级管理员可见,用于用户管理
|
||
|
||
章节来源
|
||
- [frontend/src/router/index.js:26-54](file://frontend/src/router/index.js#L26-L54)
|
||
- [backend/src/routes/brands.js:14-40](file://backend/src/routes/brands.js#L14-L40)
|
||
- [backend/src/routes/models.js:133-181](file://backend/src/routes/models.js#L133-L181)
|
||
- [backend/src/routes/ota.js:107-143](file://backend/src/routes/ota.js#L107-L143)
|
||
- [backend/src/routes/shareCodeLogs.js:14-84](file://backend/src/routes/shareCodeLogs.js#L14-L84) |