# 核心功能模块
**本文引用的文件**
- [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)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件聚焦于 Dashboard 后端与前端的核心功能模块,系统性阐述用户认证、品牌管理、型号管理、OTA 固件管理、用户权限管理以及分享码日志管理的实现原理、调用关系、接口定义、领域模型与使用模式。文档同时给出配置项、参数与返回值说明,解释前后端交互与各模块间的耦合关系,并提供常见问题与排障建议。
## 项目结构
后端采用 Express + Sequelize 架构,路由按功能域拆分,中间件统一处理鉴权与请求体限制,模型定义集中在 models 目录并通过入口聚合导出。前端基于 Vue Router 实现页面级权限控制与导航。
```mermaid
graph TB
subgraph "后端"
APP["应用入口
backend/src/app.js"]
ROUTES_IDX["路由汇总
backend/src/routes/index.js"]
AUTH_MW["鉴权中间件
backend/src/middleware/auth.js"]
MODELS_IDX["模型聚合
backend/src/models/index.js"]
MODELS["模型定义
Brand/Model/Ota/ShareCodeLog/DashboardUser"]
ROUTERS["功能路由
auth/brands/models/ota/shareCodeLogs"]
SERVICES["服务层
curveClient/measurementStorage/eqCacheStorage/otaStorage"]
VALIDATORS["参数校验
backend/src/validators/ota.js"]
end
subgraph "前端"
ROUTER["路由配置
frontend/src/router/index.js"]
VIEWS["页面视图
brand/model/ota/share-code/system/users"]
UTILS_AUTH["前端鉴权工具
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 固件管理
- 支持 X8/X9 设备固件包上传(S3 或本地),设备端“最新版本检查”接口,后台管理列表与编辑。
- 分享码日志管理
- 提供分享码导出/导入日志的查询接口,支持多维过滤与排序。
- 权限模型
- 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)
- [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)
- [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 并返回用户信息。
- 当前用户
- 需携带有效 Token 调用“获取当前用户”,后端返回用户基础信息。
- 修改密码
- 需携带有效 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["解析查询参数
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 固件管理
- 功能点
- 设备端“最新版本检查”:无需登录,按当前版本号、设备型号与硬件版本筛选可用升级包。
- 后台上传固件包:支持 X8(S3)、X9(本地);自动计算 MD5,返回下载地址与存储键。
- 后台管理:列表查询、详情、创建、更新(版本号+型号唯一性校验)、删除。
- 关键参数
- 最新版本检查:currentVerCode、model、hw。
- 上传:model、package_file。
- 列表:verCode、verName、model、status、skip、limit。
- 创建/更新:verCode、verName、url、md5、force、desc、model、hw、target、beta、startTime、endTime、status。
- 返回值
- 统一 ApiResponse 包裹,成功时返回列表、单条记录或上传结果。
```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 : 返回上传结果
```
图表来源
- [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)
- [backend/src/routes/ota.js:107-143](file://backend/src/routes/ota.js#L107-L143)
- [backend/src/routes/ota.js:162-194](file://backend/src/routes/ota.js#L162-L194)
- [backend/src/routes/ota.js:196-247](file://backend/src/routes/ota.js#L196-L247)
- [backend/src/routes/ota.js:249-268](file://backend/src/routes/ota.js#L249-L268)
- [backend/src/services/otaStorage.js](file://backend/src/services/otaStorage.js)
章节来源
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
### 用户权限管理
- 角色模型
- 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["解析查询参数
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 未配置或上传失败会返回明确错误。
- 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)
- [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)
## 结论
本系统围绕“认证—权限—数据模型—业务路由—服务集成”的清晰分层组织,通过统一的响应封装与中间件机制保障了接口一致性与安全性。品牌、型号、OTA、分享码日志等核心功能均具备完善的 CRUD、校验与外部集成能力,适合在生产环境中稳定运行。建议持续完善监控与告警、日志分级与外部服务降级策略,以进一步提升稳定性与可观测性。
## 附录
- 前端页面与路由对应关系
- 品牌管理:/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)