2026-06-30 14:46:52 +08:00
|
|
|
|
# 核心功能模块
|
|
|
|
|
|
|
|
|
|
|
|
<cite>
|
|
|
|
|
|
**本文引用的文件**
|
|
|
|
|
|
- [backend/src/app.js](file://backend/src/app.js)
|
|
|
|
|
|
- [backend/src/routes/index.js](file://backend/src/routes/index.js)
|
|
|
|
|
|
- [backend/src/middleware/auth.js](file://backend/src/middleware/auth.js)
|
|
|
|
|
|
- [backend/src/utils/response.js](file://backend/src/utils/response.js)
|
|
|
|
|
|
- [backend/src/utils/jwt.js](file://backend/src/utils/jwt.js)
|
|
|
|
|
|
- [backend/src/utils/password.js](file://backend/src/utils/password.js)
|
|
|
|
|
|
- [backend/src/models/index.js](file://backend/src/models/index.js)
|
|
|
|
|
|
- [backend/src/models/DashboardUser.js](file://backend/src/models/DashboardUser.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/models/Ota.js](file://backend/src/models/Ota.js)
|
|
|
|
|
|
- [backend/src/models/ShareCodeLog.js](file://backend/src/models/ShareCodeLog.js)
|
|
|
|
|
|
- [backend/src/routes/auth.js](file://backend/src/routes/auth.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)
|
|
|
|
|
|
- [backend/src/services/curveClient.js](file://backend/src/services/curveClient.js)
|
|
|
|
|
|
- [backend/src/services/measurementStorage.js](file://backend/src/services/measurementStorage.js)
|
|
|
|
|
|
- [backend/src/services/eqCacheStorage.js](file://backend/src/services/eqCacheStorage.js)
|
|
|
|
|
|
- [backend/src/services/otaStorage.js](file://backend/src/services/otaStorage.js)
|
|
|
|
|
|
- [backend/src/validators/ota.js](file://backend/src/validators/ota.js)
|
|
|
|
|
|
- [frontend/src/router/index.js](file://frontend/src/router/index.js)
|
|
|
|
|
|
- [frontend/src/utils/auth.js](file://frontend/src/utils/auth.js)
|
|
|
|
|
|
- [frontend/src/views/brand/index.vue](file://frontend/src/views/brand/index.vue)
|
|
|
|
|
|
- [frontend/src/views/model/index.vue](file://frontend/src/views/model/index.vue)
|
|
|
|
|
|
- [frontend/src/views/ota/index.vue](file://frontend/src/views/ota/index.vue)
|
|
|
|
|
|
- [frontend/src/views/share-code/log.vue](file://frontend/src/views/share-code/log.vue)
|
|
|
|
|
|
- [frontend/src/views/system/users/index.vue](file://frontend/src/views/system/users/index.vue)
|
|
|
|
|
|
</cite>
|
|
|
|
|
|
|
2026-07-10 11:25:45 +08:00
|
|
|
|
## 更新摘要
|
|
|
|
|
|
**变更内容**
|
|
|
|
|
|
- OTA固件管理功能已更新以支持beta版本特性
|
|
|
|
|
|
- 版本唯一性规则从'verCode + model'变更为'verCode + model + beta'组合
|
|
|
|
|
|
- 允许同一设备型号下存在多个不同beta状态的固件版本
|
|
|
|
|
|
- 前端界面新增beta状态筛选和显示功能
|
|
|
|
|
|
|
2026-06-30 14:46:52 +08:00
|
|
|
|
## 目录
|
|
|
|
|
|
1. [简介](#简介)
|
|
|
|
|
|
2. [项目结构](#项目结构)
|
|
|
|
|
|
3. [核心组件](#核心组件)
|
|
|
|
|
|
4. [架构总览](#架构总览)
|
|
|
|
|
|
5. [详细组件分析](#详细组件分析)
|
|
|
|
|
|
6. [依赖分析](#依赖分析)
|
|
|
|
|
|
7. [性能考虑](#性能考虑)
|
|
|
|
|
|
8. [故障排查指南](#故障排查指南)
|
|
|
|
|
|
9. [结论](#结论)
|
|
|
|
|
|
10. [附录](#附录)
|
|
|
|
|
|
|
|
|
|
|
|
## 简介
|
|
|
|
|
|
本文件聚焦于 Dashboard 后端与前端的核心功能模块,系统性阐述用户认证、品牌管理、型号管理、OTA 固件管理、用户权限管理以及分享码日志管理的实现原理、调用关系、接口定义、领域模型与使用模式。文档同时给出配置项、参数与返回值说明,解释前后端交互与各模块间的耦合关系,并提供常见问题与排障建议。
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
后端采用 Express + Sequelize 架构,路由按功能域拆分,中间件统一处理鉴权与请求体限制,模型定义集中在 models 目录并通过入口聚合导出。前端基于 Vue Router 实现页面级权限控制与导航。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph TB
|
|
|
|
|
|
subgraph "后端"
|
|
|
|
|
|
APP["应用入口<br/>backend/src/app.js"]
|
|
|
|
|
|
ROUTES_IDX["路由汇总<br/>backend/src/routes/index.js"]
|
|
|
|
|
|
AUTH_MW["鉴权中间件<br/>backend/src/middleware/auth.js"]
|
|
|
|
|
|
MODELS_IDX["模型聚合<br/>backend/src/models/index.js"]
|
|
|
|
|
|
MODELS["模型定义<br/>Brand/Model/Ota/ShareCodeLog/DashboardUser"]
|
|
|
|
|
|
ROUTERS["功能路由<br/>auth/brands/models/ota/shareCodeLogs"]
|
|
|
|
|
|
SERVICES["服务层<br/>curveClient/measurementStorage/eqCacheStorage/otaStorage"]
|
|
|
|
|
|
VALIDATORS["参数校验<br/>backend/src/validators/ota.js"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "前端"
|
|
|
|
|
|
ROUTER["路由配置<br/>frontend/src/router/index.js"]
|
|
|
|
|
|
VIEWS["页面视图<br/>brand/model/ota/share-code/system/users"]
|
|
|
|
|
|
UTILS_AUTH["前端鉴权工具<br/>frontend/src/utils/auth.js"]
|
|
|
|
|
|
end
|
|
|
|
|
|
APP --> ROUTES_IDX --> ROUTERS
|
|
|
|
|
|
ROUTERS --> AUTH_MW
|
|
|
|
|
|
ROUTERS --> MODELS
|
|
|
|
|
|
ROUTERS --> SERVICES
|
|
|
|
|
|
ROUTERS --> VALIDATORS
|
|
|
|
|
|
MODELS --> MODELS_IDX
|
|
|
|
|
|
ROUTER --> VIEWS
|
|
|
|
|
|
ROUTER --> UTILS_AUTH
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
|
|
|
|
|
|
- [backend/src/routes/index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/models/index.js:1-8](file://backend/src/models/index.js#L1-L8)
|
|
|
|
|
|
- [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/routes/index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
## 核心组件
|
|
|
|
|
|
- 用户认证与权限
|
|
|
|
|
|
- 后端通过 JWT 进行身份签发与校验,提供登录、获取当前用户、修改密码接口,并在路由层统一挂载鉴权中间件。
|
|
|
|
|
|
- 前端路由守卫根据 Token 与角色(超级管理员)决定页面访问权限。
|
|
|
|
|
|
- 品牌管理
|
|
|
|
|
|
- 提供品牌列表、详情、创建、更新、删除接口,支持模糊搜索与分页。
|
|
|
|
|
|
- 型号管理
|
|
|
|
|
|
- 支持型号增删改查、频响文件上传(CSV/TXT/JSON)、S3 存储、Meilisearch 推送与校验、Redis EQ 缓存读取。
|
|
|
|
|
|
- OTA 固件管理
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- 支持 X8/X9 设备固件包上传(S3 或本地),设备端"最新版本检查"接口,后台管理列表与编辑。
|
|
|
|
|
|
- **新增**:支持beta版本管理,允许同一设备型号下存在多个不同beta状态的固件版本。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 分享码日志管理
|
|
|
|
|
|
- 提供分享码导出/导入日志的查询接口,支持多维过滤与排序。
|
|
|
|
|
|
- 权限模型
|
|
|
|
|
|
- DashboardUser 模型包含用户名、密码哈希、超级管理员标识与状态;路由中间件提供 requireSuperAdmin 守卫。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/models/DashboardUser.js:1-58](file://backend/src/models/DashboardUser.js#L1-L58)
|
|
|
|
|
|
- [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)
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- [backend/src/routes/ota.js:1-295](file://backend/src/routes/ota.js#L1-L295)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/shareCodeLogs.js:1-88](file://backend/src/routes/shareCodeLogs.js#L1-L88)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
|
|
|
|
|
后端启动流程:加载环境变量 → 初始化 Express 应用 → 注册 CORS、JSON 解析、Body 限制中间件 → 注册路由 → 同步数据库并创建超级管理员 → 启动 HTTP 服务。前端路由守卫在进入受保护页面前校验 Token 与角色。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant Client as "客户端"
|
|
|
|
|
|
participant Front as "前端路由"
|
|
|
|
|
|
participant AuthAPI as "后端认证路由"
|
|
|
|
|
|
participant JWT as "JWT 工具"
|
|
|
|
|
|
participant DB as "数据库"
|
|
|
|
|
|
Client->>Front : 访问受保护页面
|
|
|
|
|
|
Front->>Front : 校验 Token 与角色
|
|
|
|
|
|
alt Token 缺失/过期
|
|
|
|
|
|
Front-->>Client : 重定向到登录页
|
|
|
|
|
|
else 已登录
|
|
|
|
|
|
Front->>AuthAPI : 请求 /api/auth/me
|
|
|
|
|
|
AuthAPI->>DB : 查询用户信息
|
|
|
|
|
|
DB-->>AuthAPI : 返回用户记录
|
|
|
|
|
|
AuthAPI-->>Front : 返回用户信息
|
|
|
|
|
|
Front-->>Client : 渲染目标页面
|
|
|
|
|
|
end
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:66-77](file://backend/src/routes/auth.js#L66-L77)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:3-26](file://backend/src/middleware/auth.js#L3-L26)
|
|
|
|
|
|
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/app.js:42-59](file://backend/src/app.js#L42-L59)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
## 详细组件分析
|
|
|
|
|
|
|
|
|
|
|
|
### 用户认证系统
|
|
|
|
|
|
- 登录流程
|
|
|
|
|
|
- 前端提交用户名与密码,后端校验账号是否存在且启用,验证密码哈希,更新最近登录时间,签发 Access Token 并返回用户信息。
|
|
|
|
|
|
- 当前用户
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- 需携带有效 Token 调用"获取当前用户",后端返回用户基础信息。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 修改密码
|
|
|
|
|
|
- 需携带有效 Token,校验旧密码,长度不少于 6 位,成功后更新密码哈希。
|
|
|
|
|
|
- 鉴权中间件
|
|
|
|
|
|
- 从 Authorization 头解析 Bearer Token,解码后注入 req.user(包含 id、username、is_super_admin),异常时返回 401/403。
|
|
|
|
|
|
- 前端路由守卫
|
|
|
|
|
|
- 在进入受保护路由前检查 Token 是否存在与未过期;若目标页面要求超级管理员,则进一步校验角色。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant FE as "前端"
|
|
|
|
|
|
participant AuthR as "认证路由"
|
|
|
|
|
|
participant MW as "鉴权中间件"
|
|
|
|
|
|
participant JWTU as "JWT 工具"
|
|
|
|
|
|
participant PWD as "密码工具"
|
|
|
|
|
|
participant DB as "数据库"
|
|
|
|
|
|
FE->>AuthR : POST /api/auth/login
|
|
|
|
|
|
AuthR->>DB : 查询用户
|
|
|
|
|
|
DB-->>AuthR : 用户记录
|
|
|
|
|
|
AuthR->>PWD : 校验密码
|
|
|
|
|
|
PWD-->>AuthR : 校验结果
|
|
|
|
|
|
AuthR->>JWTU : 生成 Access Token
|
|
|
|
|
|
JWTU-->>AuthR : Token
|
|
|
|
|
|
AuthR-->>FE : {access_token, user}
|
|
|
|
|
|
FE->>AuthR : GET /api/auth/me (携带 Token)
|
|
|
|
|
|
AuthR->>MW : 中间件校验
|
|
|
|
|
|
MW->>JWTU : 解码 Token
|
|
|
|
|
|
JWTU-->>MW : Payload
|
|
|
|
|
|
MW-->>AuthR : 注入 req.user
|
|
|
|
|
|
AuthR->>DB : 查询用户
|
|
|
|
|
|
DB-->>AuthR : 用户信息
|
|
|
|
|
|
AuthR-->>FE : 用户信息
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:24-77](file://backend/src/routes/auth.js#L24-L77)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:3-26](file://backend/src/middleware/auth.js#L3-L26)
|
|
|
|
|
|
- [backend/src/utils/jwt.js](file://backend/src/utils/jwt.js)
|
|
|
|
|
|
- [backend/src/utils/password.js](file://backend/src/utils/password.js)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
|
|
|
|
|
|
|
|
|
|
|
### 品牌管理
|
|
|
|
|
|
- 功能点
|
|
|
|
|
|
- 列表查询:支持按名称模糊搜索、分页(skip/limit,最大 1000)。
|
|
|
|
|
|
- 详情查询:按 ID 获取品牌。
|
|
|
|
|
|
- 创建:名称必填且唯一。
|
|
|
|
|
|
- 更新:名称必填且唯一(排除自身 ID)。
|
|
|
|
|
|
- 删除:级联删除。
|
|
|
|
|
|
- 关键参数
|
|
|
|
|
|
- 查询:name、skip、limit。
|
|
|
|
|
|
- 新增/更新:name。
|
|
|
|
|
|
- 返回值
|
|
|
|
|
|
- 统一 ApiResponse 包裹,成功时返回 items/total/skip/limit 或单项数据。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
Start(["发起请求"]) --> Parse["解析查询参数<br/>name/skip/limit"]
|
|
|
|
|
|
Parse --> BuildWhere["构建查询条件"]
|
|
|
|
|
|
BuildWhere --> Find["findAndCountAll/findByPk"]
|
|
|
|
|
|
Find --> Found{"是否找到数据?"}
|
|
|
|
|
|
Found -- 否 --> NoData["返回 noData(empty)"]
|
|
|
|
|
|
Found -- 是 --> Map["映射为 {id,name}"]
|
|
|
|
|
|
Map --> Success["返回 success(items,total,skip,limit)"]
|
|
|
|
|
|
NoData --> End(["结束"])
|
|
|
|
|
|
Success --> End
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/brands.js:14-40](file://backend/src/routes/brands.js#L14-L40)
|
|
|
|
|
|
- [backend/src/routes/brands.js:42-57](file://backend/src/routes/brands.js#L42-L57)
|
|
|
|
|
|
- [backend/src/routes/brands.js:59-81](file://backend/src/routes/brands.js#L59-L81)
|
|
|
|
|
|
- [backend/src/routes/brands.js:83-123](file://backend/src/routes/brands.js#L83-L123)
|
|
|
|
|
|
- [backend/src/routes/brands.js:125-144](file://backend/src/routes/brands.js#L125-L144)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
|
|
|
|
|
|
|
|
|
|
|
|
### 型号管理
|
|
|
|
|
|
- 功能点
|
|
|
|
|
|
- 列表查询:支持按品牌名/型号名模糊搜索、排序(id/create_at asc/desc)。
|
|
|
|
|
|
- 详情查询:按 ID 获取型号。
|
|
|
|
|
|
- 创建:支持上传频响文件(CSV/TXT/JSON),TXT 自动转换为 CSV;S3 保存;写入数据库。
|
|
|
|
|
|
- 更新:支持上传新频响文件;字段可部分更新;名称组合唯一性校验。
|
|
|
|
|
|
- 删除:先从 Meilisearch 删除文档,再删除数据库记录。
|
|
|
|
|
|
- Meilisearch 集成:提供校验与推送接口,支持批量校验与推送。
|
|
|
|
|
|
- EQ 缓存:读取 Redis 中指定型号的缓存键与字段值。
|
|
|
|
|
|
- 测量数据:仅允许查看来源为特定值的型号的 S3 CSV 内容。
|
|
|
|
|
|
- 关键参数
|
|
|
|
|
|
- 查询:brand_name、name、sort_by、sort_order、skip、limit。
|
|
|
|
|
|
- 创建/更新:brand_name、name、form、rig、source、eq_key、measurement_file。
|
|
|
|
|
|
- Meilisearch:model_id。
|
|
|
|
|
|
- EQ 缓存:model_id、key。
|
|
|
|
|
|
- S3:model_id。
|
|
|
|
|
|
- 返回值
|
|
|
|
|
|
- 统一 ApiResponse 包裹,成功时返回 items/total/skip/limit、单条记录或任务信息。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant FE as "前端"
|
|
|
|
|
|
participant ModelR as "型号路由"
|
|
|
|
|
|
participant S3 as "测量存储服务"
|
|
|
|
|
|
participant MS as "Meilisearch"
|
|
|
|
|
|
participant EC as "EQ 缓存服务"
|
|
|
|
|
|
participant DB as "数据库"
|
|
|
|
|
|
FE->>ModelR : POST /api/models/ (multipart/form-data)
|
|
|
|
|
|
ModelR->>S3 : 上传频响文件至 S3
|
|
|
|
|
|
S3-->>ModelR : 返回 S3 Key
|
|
|
|
|
|
ModelR->>DB : 写入型号记录
|
|
|
|
|
|
DB-->>ModelR : 返回新建记录
|
|
|
|
|
|
ModelR-->>FE : 返回新建型号信息
|
|
|
|
|
|
FE->>ModelR : GET /api/models/ : model_id/meilisearch
|
|
|
|
|
|
ModelR->>MS : 查询文档
|
|
|
|
|
|
MS-->>ModelR : 文档或 404
|
|
|
|
|
|
ModelR-->>FE : 返回 pushed/document
|
|
|
|
|
|
FE->>ModelR : GET /api/models/ : model_id/eq-cache/field?key=...
|
|
|
|
|
|
ModelR->>EC : 读取字段值
|
|
|
|
|
|
EC-->>ModelR : 字段值
|
|
|
|
|
|
ModelR-->>FE : 返回字段值
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/models.js:307-361](file://backend/src/routes/models.js#L307-L361)
|
|
|
|
|
|
- [backend/src/routes/models.js:225-244](file://backend/src/routes/models.js#L225-L244)
|
|
|
|
|
|
- [backend/src/routes/models.js:183-223](file://backend/src/routes/models.js#L183-L223)
|
|
|
|
|
|
- [backend/src/services/measurementStorage.js](file://backend/src/services/measurementStorage.js)
|
|
|
|
|
|
- [backend/src/services/eqCacheStorage.js](file://backend/src/services/eqCacheStorage.js)
|
|
|
|
|
|
- [backend/src/services/curveClient.js](file://backend/src/services/curveClient.js)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
|
|
|
|
|
|
|
|
|
|
|
|
### OTA 固件管理
|
|
|
|
|
|
- 功能点
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- 设备端"最新版本检查":无需登录,按当前版本号、设备型号与硬件版本筛选可用升级包。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 后台上传固件包:支持 X8(S3)、X9(本地);自动计算 MD5,返回下载地址与存储键。
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- 后台管理:列表查询、详情、创建、更新(版本号+型号+灰度状态唯一性校验)、删除。
|
|
|
|
|
|
- **新增**:Beta版本支持,允许同一设备型号下存在多个不同beta状态的固件版本。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 关键参数
|
|
|
|
|
|
- 最新版本检查:currentVerCode、model、hw。
|
|
|
|
|
|
- 上传:model、package_file。
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- 列表:verCode、verName、model、status、beta、skip、limit。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 创建/更新:verCode、verName、url、md5、force、desc、model、hw、target、beta、startTime、endTime、status。
|
|
|
|
|
|
- 返回值
|
|
|
|
|
|
- 统一 ApiResponse 包裹,成功时返回列表、单条记录或上传结果。
|
|
|
|
|
|
|
2026-07-10 11:25:45 +08:00
|
|
|
|
**更新** 版本唯一性规则已从'verCode + model'组合变更为'verCode + model + beta'组合,允许同一设备型号下存在多个不同beta状态的固件版本。
|
|
|
|
|
|
|
2026-06-30 14:46:52 +08:00
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant Device as "设备端"
|
|
|
|
|
|
participant OTAR as "OTA 路由"
|
|
|
|
|
|
participant DB as "数据库"
|
|
|
|
|
|
participant OtaSvc as "OTA 存储服务"
|
|
|
|
|
|
Device->>OTAR : GET /api/ota/latest/check?currentVerCode&model&hw
|
|
|
|
|
|
OTAR->>DB : 查询可用升级包
|
|
|
|
|
|
DB-->>OTAR : 返回最新记录
|
|
|
|
|
|
OTAR-->>Device : 返回升级包信息
|
|
|
|
|
|
Admin->>OTAR : POST /api/ota/upload-package
|
|
|
|
|
|
OTAR->>OtaSvc : 校验并保存升级包
|
|
|
|
|
|
OtaSvc-->>OTAR : 返回 md5/filename/url/s3_key
|
|
|
|
|
|
OTAR-->>Admin : 返回上传结果
|
2026-07-10 11:25:45 +08:00
|
|
|
|
Admin->>OTAR : POST /api/ota/ (含beta字段)
|
|
|
|
|
|
OTAR->>DB : 检查verCode+model+beta唯一性
|
|
|
|
|
|
DB-->>OTAR : 唯一性检查结果
|
|
|
|
|
|
OTAR-->>Admin : 创建结果
|
2026-06-30 14:46:52 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/ota.js:68-102](file://backend/src/routes/ota.js#L68-L102)
|
|
|
|
|
|
- [backend/src/routes/ota.js:24-66](file://backend/src/routes/ota.js#L24-L66)
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- [backend/src/routes/ota.js:107-145](file://backend/src/routes/ota.js#L107-L145)
|
|
|
|
|
|
- [backend/src/routes/ota.js:165-196](file://backend/src/routes/ota.js#L165-L196)
|
|
|
|
|
|
- [backend/src/routes/ota.js:198-250](file://backend/src/routes/ota.js#L198-L250)
|
|
|
|
|
|
- [backend/src/routes/ota.js:252-271](file://backend/src/routes/ota.js#L252-L271)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/services/otaStorage.js](file://backend/src/services/otaStorage.js)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- [backend/src/routes/ota.js:1-295](file://backend/src/routes/ota.js#L1-L295)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
### 用户权限管理
|
|
|
|
|
|
- 角色模型
|
|
|
|
|
|
- DashboardUser 模型包含 is_super_admin 字段用于区分超级管理员。
|
|
|
|
|
|
- 路由守卫
|
|
|
|
|
|
- authMiddleware:校验 Token 并注入用户信息。
|
|
|
|
|
|
- requireSuperAdmin:仅超级管理员可访问。
|
|
|
|
|
|
- 前端页面守卫
|
|
|
|
|
|
- 路由 meta.requiresSuperAdmin 控制页面是否仅超级管理员可见。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
Enter["进入受保护路由"] --> CheckAuth{"是否需要登录?"}
|
|
|
|
|
|
CheckAuth -- 是 --> TokenCheck["校验 Token 与过期"]
|
|
|
|
|
|
TokenCheck --> RoleCheck{"是否需要超级管理员?"}
|
|
|
|
|
|
RoleCheck -- 是 --> SuperAdminCheck["校验 is_super_admin"]
|
|
|
|
|
|
SuperAdminCheck --> Allowed["放行"]
|
|
|
|
|
|
RoleCheck -- 否 --> Allowed
|
|
|
|
|
|
TokenCheck --> |失败| Redirect["重定向到登录页"]
|
|
|
|
|
|
CheckAuth -- 否 --> Allowed
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/middleware/auth.js:28-33](file://backend/src/middleware/auth.js#L28-L33)
|
|
|
|
|
|
- [frontend/src/router/index.js:75-79](file://frontend/src/router/index.js#L75-L79)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/models/DashboardUser.js:1-58](file://backend/src/models/DashboardUser.js#L1-L58)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
### 分享码日志管理
|
|
|
|
|
|
- 功能点
|
|
|
|
|
|
- 列表查询:支持按 MAC 地址、分享码、操作类型(export/import)、IP 地址、时间范围过滤与排序。
|
|
|
|
|
|
- 关键参数
|
|
|
|
|
|
- 查询:mac_addr、share_code、action、ip_addr、start_at、end_at、sort_by、sort_order、skip、limit。
|
|
|
|
|
|
- 返回值
|
|
|
|
|
|
- 统一 ApiResponse 包裹,成功时返回 items/total/skip/limit。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
Start(["发起请求"]) --> Parse["解析查询参数<br/>mac_addr/share_code/action/ip_addr/start_at/end_at"]
|
|
|
|
|
|
Parse --> BuildWhere["构建 where 条件"]
|
|
|
|
|
|
BuildWhere --> Sort["设置排序字段与方向"]
|
|
|
|
|
|
Sort --> Paginate["分页 skip/limit"]
|
|
|
|
|
|
Paginate --> Query["查询总数与列表"]
|
|
|
|
|
|
Query --> Found{"是否有数据?"}
|
|
|
|
|
|
Found -- 否 --> NoData["返回 noData(empty)"]
|
|
|
|
|
|
Found -- 是 --> Map["映射字段"]
|
|
|
|
|
|
Map --> Success["返回 success(items,total,skip,limit)"]
|
|
|
|
|
|
NoData --> End(["结束"])
|
|
|
|
|
|
Success --> End
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/shareCodeLogs.js:14-84](file://backend/src/routes/shareCodeLogs.js#L14-L84)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/shareCodeLogs.js:1-88](file://backend/src/routes/shareCodeLogs.js#L1-L88)
|
|
|
|
|
|
|
|
|
|
|
|
## 依赖分析
|
|
|
|
|
|
- 组件耦合
|
|
|
|
|
|
- 路由层依赖中间件(鉴权)、模型(Sequelize)、服务层(存储/缓存/外部服务)、验证器(Zod)与响应封装。
|
|
|
|
|
|
- 前端路由依赖鉴权工具与页面视图,页面视图通过 API 适配器与后端交互。
|
|
|
|
|
|
- 外部依赖
|
|
|
|
|
|
- 数据库:MySQL/PostgreSQL(通过 Sequelize)。
|
|
|
|
|
|
- 存储:S3(对象存储)、本地文件系统(X9 包)。
|
|
|
|
|
|
- 搜索:Meilisearch。
|
|
|
|
|
|
- 缓存:Redis(EQ 缓存)。
|
|
|
|
|
|
- 循环依赖
|
|
|
|
|
|
- 未见明显循环依赖;路由通过中间件与模型解耦。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph LR
|
|
|
|
|
|
Routes["路由层"] --> MW["鉴权中间件"]
|
|
|
|
|
|
Routes --> Models["模型层"]
|
|
|
|
|
|
Routes --> Services["服务层"]
|
|
|
|
|
|
Routes --> Validators["验证器"]
|
|
|
|
|
|
FrontRoutes["前端路由"] --> Views["页面视图"]
|
|
|
|
|
|
Views --> APIs["API 适配器"]
|
|
|
|
|
|
Services --> Storage["S3/本地"]
|
|
|
|
|
|
Services --> Search["Meilisearch"]
|
|
|
|
|
|
Services --> Cache["Redis"]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/models/index.js:1-8](file://backend/src/models/index.js#L1-L8)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
|
|
- [backend/src/models/index.js:1-8](file://backend/src/models/index.js#L1-L8)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
|
|
|
|
|
|
|
|
|
|
|
## 性能考虑
|
|
|
|
|
|
- 分页与限制
|
|
|
|
|
|
- 列表接口统一限制每页最大数量,避免一次性返回过多数据。
|
|
|
|
|
|
- 查询优化
|
|
|
|
|
|
- 型号与分享码日志模型建立索引(如 mac_addr、share_code、create_at),提升过滤查询性能。
|
|
|
|
|
|
- 外部服务超时
|
|
|
|
|
|
- Meilisearch 请求设置超时,防止阻塞。
|
|
|
|
|
|
- 缓存利用
|
|
|
|
|
|
- EQ 缓存通过 Redis 减少重复计算与数据库压力。
|
|
|
|
|
|
- 文件上传
|
|
|
|
|
|
- 使用内存存储配合 Multer,大文件场景建议调整策略或引入流式处理。
|
|
|
|
|
|
|
|
|
|
|
|
## 故障排查指南
|
|
|
|
|
|
- 登录失败
|
|
|
|
|
|
- 检查用户名/密码是否为空、账号是否存在且启用、密码哈希是否匹配。
|
|
|
|
|
|
- Token 相关
|
|
|
|
|
|
- 401 未登录/无效凭证:确认 Authorization 头格式与签名有效性;检查过期时间。
|
|
|
|
|
|
- 403 需要超级管理员权限:确认 is_super_admin 标记。
|
|
|
|
|
|
- 品牌/型号操作
|
|
|
|
|
|
- 名称唯一性冲突:确保品牌名或型号组合唯一。
|
|
|
|
|
|
- 文件格式不支持:仅允许 CSV/TXT/JSON,TXT 将被自动转换为 CSV。
|
|
|
|
|
|
- OTA 上传
|
|
|
|
|
|
- 仅支持指定设备型号;S3 未配置或上传失败会返回明确错误。
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- **新增**:版本唯一性冲突检查包含beta状态,确保verCode+model+beta组合唯一。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- Meilisearch 集成
|
|
|
|
|
|
- 推送/删除失败:检查服务可达性与 API Key;关注返回的任务 UID。
|
|
|
|
|
|
- 分享码日志
|
|
|
|
|
|
- 时间范围查询:确保传入合法日期字符串。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:24-64](file://backend/src/routes/auth.js#L24-L64)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:3-26](file://backend/src/middleware/auth.js#L3-L26)
|
|
|
|
|
|
- [backend/src/routes/brands.js:62-80](file://backend/src/routes/brands.js#L62-L80)
|
|
|
|
|
|
- [backend/src/routes/models.js:319-335](file://backend/src/routes/models.js#L319-L335)
|
|
|
|
|
|
- [backend/src/routes/ota.js:27-58](file://backend/src/routes/ota.js#L27-L58)
|
2026-07-10 11:25:45 +08:00
|
|
|
|
- [backend/src/routes/ota.js:176-183](file://backend/src/routes/ota.js#L176-L183)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/models.js:543-561](file://backend/src/routes/models.js#L543-L561)
|
|
|
|
|
|
- [backend/src/routes/shareCodeLogs.js:37-48](file://backend/src/routes/shareCodeLogs.js#L37-L48)
|
|
|
|
|
|
|
|
|
|
|
|
## 结论
|
2026-07-10 11:25:45 +08:00
|
|
|
|
本系统围绕"认证—权限—数据模型—业务路由—服务集成"的清晰分层组织,通过统一的响应封装与中间件机制保障了接口一致性与安全性。品牌、型号、OTA、分享码日志等核心功能均具备完善的 CRUD、校验与外部集成能力,适合在生产环境中稳定运行。**新增的beta版本支持功能进一步增强了OTA固件管理的灵活性,允许在同一设备型号下管理多个不同灰度状态的版本**。建议持续完善监控与告警、日志分级与外部服务降级策略,以进一步提升稳定性与可观测性。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 附录
|
|
|
|
|
|
- 前端页面与路由对应关系
|
|
|
|
|
|
- 品牌管理:/brand → [frontend/src/views/brand/index.vue](file://frontend/src/views/brand/index.vue)
|
|
|
|
|
|
- 型号管理:/model → [frontend/src/views/model/index.vue](file://frontend/src/views/model/index.vue)
|
|
|
|
|
|
- OTA 管理:/ota → [frontend/src/views/ota/index.vue](file://frontend/src/views/ota/index.vue)
|
|
|
|
|
|
- 分享日志:/share-code/log → [frontend/src/views/share-code/log.vue](file://frontend/src/views/share-code/log.vue)
|
|
|
|
|
|
- 账号管理(超级管理员):/system/users → [frontend/src/views/system/users/index.vue](file://frontend/src/views/system/users/index.vue)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/router/index.js:26-54](file://frontend/src/router/index.js#L26-L54)
|