# 型号管理页面 **本文档引用的文件** - [frontend/src/views/model/index.vue](file://frontend/src/views/model/index.vue) - [frontend/src/views/model/composables/useModelList.js](file://frontend/src/views/model/composables/useModelList.js) - [frontend/src/views/model/components/ModelFormDialog.vue](file://frontend/src/views/model/components/ModelFormDialog.vue) - [frontend/src/views/model/components/CsvViewerDialog.vue](file://frontend/src/views/model/components/CsvViewerDialog.vue) - [frontend/src/views/model/components/EqCacheDialog.vue](file://frontend/src/views/model/components/EqCacheDialog.vue) - [frontend/src/views/model/components/PushProgressDialog.vue](file://frontend/src/views/model/components/PushProgressDialog.vue) - [frontend/src/views/model/components/PushViewDialog.vue](file://frontend/src/views/model/components/PushViewDialog.vue) - [frontend/src/api/model.js](file://frontend/src/api/model.js) - [backend/src/routes/models.js](file://backend/src/routes/models.js) - [backend/src/models/Model.js](file://backend/src/models/Model.js) - [backend/src/validators/model.js](file://backend/src/validators/model.js) - [frontend/src/api/brand.js](file://frontend/src/api/brand.js) - [backend/src/models/Brand.js](file://backend/src/models/Brand.js) - [backend/src/routes/brands.js](file://backend/src/routes/brands.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/squiglink.js](file://backend/src/services/squiglink.js) - [frontend/src/utils/request.js](file://frontend/src/utils/request.js) - [frontend/src/router/index.js](file://frontend/src/router/index.js) ## 更新摘要 **变更内容** - 新增useModelList组合式函数,提供统一的数据管理与状态控制 - 新增5个专用对话框组件,增强用户体验和功能完整性 - 新增squig.link外部数据导入功能,支持从第三方网站抓取频响数据 - 增强型号表单的复杂处理能力,支持文件上传、品牌自动创建等功能 - 完善批量操作的进度跟踪与错误处理机制 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向"型号管理页面"的技术实现与使用说明,覆盖以下关键能力: - 型号列表展示、搜索过滤、排序与分页 - 型号详情查看与参数配置 - 型号表单的数据结构、字段验证与复杂表单处理(含频响文件上传) - 型号与品牌的关联关系、级联数据管理与外键约束处理 - 型号参数的动态配置、数据格式验证与存储优化 - 批量操作(复制、推送搜索)的实现方案 - **新增**:squig.link外部数据导入功能 - **新增**:组合式函数useModelList的状态管理 - **新增**:5个专用对话框组件的完整功能 ## 项目结构 型号管理页面位于前端单页应用中,后端提供 REST 接口与数据模型支撑,前端通过 API 模块与后端交互。系统现已包含完整的对话框组件体系和组合式函数支持。 ```mermaid graph TB subgraph "前端" FE_Model["型号视图
frontend/src/views/model/index.vue"] FE_useModelList["组合式函数
useModelList.js"] FE_API_Model["型号 API
frontend/src/api/model.js"] FE_API_Brand["品牌 API
frontend/src/api/brand.js"] FE_Request["请求封装
frontend/src/utils/request.js"] FE_Router["路由
frontend/src/router/index.js"] FE_Components["对话框组件
components/"] FE_ModelFormDialog["ModelFormDialog.vue"] FE_CsvViewerDialog["CsvViewerDialog.vue"] FE_EqCacheDialog["EqCacheDialog.vue"] FE_PushProgressDialog["PushProgressDialog.vue"] FE_PushViewDialog["PushViewDialog.vue"] end subgraph "后端" BE_Routes_Models["型号路由
backend/src/routes/models.js"] BE_Models_Model["型号模型
backend/src/models/Model.js"] BE_Validators_Model["型号校验器
backend/src/validators/model.js"] BE_Routes_Brands["品牌路由
backend/src/routes/brands.js"] BE_Models_Brand["品牌模型
backend/src/models/Brand.js"] BE_Services_Measure["频响存储服务
backend/src/services/measurementStorage.js"] BE_Services_EQ["EQ 缓存服务
backend/src/services/eqCacheStorage.js"] BE_Services_Squiglink["squig.link 服务
backend/src/services/squiglink.js"] end FE_Model --> FE_useModelList FE_Model --> FE_API_Model FE_Model --> FE_API_Brand FE_useModelList --> FE_API_Model FE_useModelList --> FE_API_Brand FE_API_Model --> FE_Request FE_API_Brand --> FE_Request FE_Router --> FE_Model FE_Model --> FE_Components FE_Components --> FE_ModelFormDialog FE_Components --> FE_CsvViewerDialog FE_Components --> FE_EqCacheDialog FE_Components --> FE_PushProgressDialog FE_Components --> FE_PushViewDialog FE_API_Model --> BE_Routes_Models FE_API_Brand --> BE_Routes_Brands BE_Routes_Models --> BE_Models_Model BE_Routes_Models --> BE_Validators_Model BE_Routes_Models --> BE_Services_Measure BE_Routes_Models --> BE_Services_EQ BE_Routes_Models --> BE_Services_Squiglink BE_Routes_Brands --> BE_Models_Brand ``` **图表来源** - [frontend/src/views/model/index.vue:1-533](file://frontend/src/views/model/index.vue#L1-L533) - [frontend/src/views/model/composables/useModelList.js:1-191](file://frontend/src/views/model/composables/useModelList.js#L1-L191) - [frontend/src/views/model/components/ModelFormDialog.vue:1-555](file://frontend/src/views/model/components/ModelFormDialog.vue#L1-L555) - [frontend/src/views/model/components/CsvViewerDialog.vue:1-50](file://frontend/src/views/model/components/CsvViewerDialog.vue#L1-L50) - [frontend/src/views/model/components/EqCacheDialog.vue:1-306](file://frontend/src/views/model/components/EqCacheDialog.vue#L1-L306) - [frontend/src/views/model/components/PushProgressDialog.vue:1-303](file://frontend/src/views/model/components/PushProgressDialog.vue#L1-L303) - [frontend/src/views/model/components/PushViewDialog.vue:1-60](file://frontend/src/views/model/components/PushViewDialog.vue#L1-L60) **章节来源** - [frontend/src/views/model/index.vue:1-533](file://frontend/src/views/model/index.vue#L1-L533) - [frontend/src/views/model/composables/useModelList.js:1-191](file://frontend/src/views/model/composables/useModelList.js#L1-L191) - [backend/src/routes/models.js:1-659](file://backend/src/routes/models.js#L1-L659) ## 核心组件 - **组合式函数**:useModelList提供统一的数据加载、搜索、排序、分页和状态管理功能 - **主视图组件**:型号管理页面的核心容器,协调各对话框组件和业务逻辑 - **对话框组件族**: - ModelFormDialog:完整的型号表单对话框,支持文件上传和squig.link导入 - CsvViewerDialog:CSV频响数据查看对话框 - EqCacheDialog:EQ缓存查看对话框,支持JSON树形展示 - PushProgressDialog:推送进度跟踪对话框 - PushViewDialog:推送状态查看对话框 - **API模块**:封装所有型号相关的HTTP请求,包括新增的squig.link导入功能 - **后端路由**:提供完整的REST接口,包括squig.link数据抓取功能 - **服务层**:频响文件上传、EQ缓存读取、squig.link数据抓取等服务 **章节来源** - [frontend/src/views/model/composables/useModelList.js:1-191](file://frontend/src/views/model/composables/useModelList.js#L1-L191) - [frontend/src/views/model/components/ModelFormDialog.vue:1-555](file://frontend/src/views/model/components/ModelFormDialog.vue#L1-L555) - [frontend/src/views/model/components/CsvViewerDialog.vue:1-50](file://frontend/src/views/model/components/CsvViewerDialog.vue#L1-L50) - [frontend/src/views/model/components/EqCacheDialog.vue:1-306](file://frontend/src/views/model/components/EqCacheDialog.vue#L1-L306) - [frontend/src/views/model/components/PushProgressDialog.vue:1-303](file://frontend/src/views/model/components/PushProgressDialog.vue#L1-L303) - [frontend/src/views/model/components/PushViewDialog.vue:1-60](file://frontend/src/views/model/components/PushViewDialog.vue#L1-L60) - [frontend/src/api/model.js:1-165](file://frontend/src/api/model.js#L1-L165) ## 架构总览 型号管理页面采用现代化的Vue 3 Composition API架构,结合Element Plus组件库和Axios进行数据交互。系统支持完整的数据流:从组合式函数的状态管理到对话框组件的用户交互,再到后端服务的业务处理。 ```mermaid sequenceDiagram participant U as "用户" participant V as "型号视图
index.vue" participant CM as "组合式函数
useModelList" participant MD as "ModelFormDialog" participant API as "API 模块
model.js" participant R as "后端路由
models.js" participant S as "服务层
squiglink.js" U->>V : 打开型号管理页面 V->>CM : 初始化状态管理 CM->>API : 加载品牌列表 API->>R : GET /api/models/ R->>S : 调用squig.link服务 S-->>R : 返回数据 R-->>API : 品牌数据 API-->>CM : 品牌选项 CM-->>V : 渲染界面 U->>MD : 点击"新型号" MD->>API : 上传文件或导入squig.link API->>R : POST /api/models/squiglink-fetch R->>S : 抓取外部数据 S-->>R : 返回CSV内容 R-->>API : 处理结果 API-->>MD : 成功响应 MD-->>V : 关闭对话框并刷新 ``` **图表来源** - [frontend/src/views/model/index.vue:227-434](file://frontend/src/views/model/index.vue#L227-L434) - [frontend/src/views/model/composables/useModelList.js:31-191](file://frontend/src/views/model/composables/useModelList.js#L31-L191) - [frontend/src/views/model/components/ModelFormDialog.vue:158-464](file://frontend/src/views/model/components/ModelFormDialog.vue#L158-L464) - [frontend/src/api/model.js:157-165](file://frontend/src/api/model.js#L157-L165) - [backend/src/routes/models.js:307-369](file://backend/src/routes/models.js#L307-L369) - [backend/src/services/squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310) **章节来源** - [frontend/src/views/model/index.vue:227-434](file://frontend/src/views/model/index.vue#L227-L434) - [frontend/src/views/model/composables/useModelList.js:31-191](file://frontend/src/views/model/composables/useModelList.js#L31-L191) ## 详细组件分析 ### useModelList组合式函数 useModelList是型号管理页面的核心状态管理函数,提供统一的数据操作接口。 **核心功能** - **数据加载**:统一处理型号列表的加载、搜索、排序和分页 - **状态管理**:维护表格数据、选中行、品牌选项等状态 - **搜索过滤**:支持品牌名称和型号名称的模糊搜索 - **排序控制**:支持按ID和创建时间的升序/降序排序 - **分页处理**:支持不同页面大小的分页控制 - **批量操作**:提供复制功能和格式化工具方法 **状态属性** - `loading`: 数据加载状态 - `tableData`: 当前表格数据 - `selectedRows`: 选中的行数据 - `selectedIds`: 选中行的ID数组 - `brandOptions`: 品牌下拉选项 - `sortBy`: 排序字段 - `sortOrder`: 排序顺序 - `searchForm`: 搜索表单数据 - `pagination`: 分页配置 **方法功能** - `loadData()`: 加载型号列表数据 - `loadBrands()`: 加载品牌选项 - `handleSearch()`: 执行搜索 - `handleReset()`: 重置搜索条件 - `handleSortChange()`: 处理排序变更 - `handleSizeChange()`: 处理页面大小变更 - `handlePageChange()`: 处理页码变更 - `handleSelectionChange()`: 处理选择变更 - `handleCopyName()`: 复制单个型号 - `handleCopyBrand()`: 复制品牌名称 - `handleCopySelectedNames()`: 复制选中型号 - `formatDateTime()`: 格式化日期时间 - `formatFormLabel()`: 格式化佩戴方式 **章节来源** - [frontend/src/views/model/composables/useModelList.js:1-191](file://frontend/src/views/model/composables/useModelList.js#L1-L191) ### ModelFormDialog型号表单对话框 ModelFormDialog是完整的型号创建和编辑对话框,支持复杂的表单处理和外部数据导入。 **核心特性** - **squig.link导入**:支持从第三方网站抓取频响数据 - **文件上传**:支持CSV、TXT、JSON格式的频响文件上传 - **品牌自动创建**:当品牌不存在时自动创建新品牌 - **文件名智能解析**:根据文件名自动解析品牌和型号 - **表单验证**:完整的字段验证和错误处理 - **多步骤提交**:支持单次提交和连续提交模式 **squig.link导入流程** 1. 用户输入squig.link分享链接 2. 系统抓取phone_book.json获取可用文件列表 3. 自动匹配或让用户选择目标文件 4. 下载TXT频响文件并转换为CSV格式 5. 自动填充表单字段(品牌、型号、佩戴方式等) **文件上传处理** - 支持multipart/form-data格式 - 自动检测文件扩展名并验证格式 - TXT文件自动转换为CSV格式 - 上传成功后与型号记录关联 **章节来源** - [frontend/src/views/model/components/ModelFormDialog.vue:1-555](file://frontend/src/views/model/components/ModelFormDialog.vue#L1-L555) - [backend/src/routes/models.js:307-499](file://backend/src/routes/models.js#L307-L499) - [backend/src/services/squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310) ### 对话框组件体系 系统包含5个专用对话框组件,每个组件都有明确的功能边界和使用场景。 **CsvViewerDialog** - 功能:查看CSV频响数据内容 - 特点:支持S3 Key显示和只读文本区域 - 适用:仅限特定来源的型号查看 **EqCacheDialog** - 功能:查看EQ缓存的Redis数据 - 特点:支持JSON树形结构展示,可展开查看嵌套数据 - 适用:调试和分析EQ参数配置 **PushProgressDialog** - 功能:跟踪批量推送的进度 - 特点:显示校验和推送两个阶段的状态,支持错误详情 - 适用:批量型号推送操作 **PushViewDialog** - 功能:查看推送状态和文档详情 - 特点:简洁的信息展示,支持加载状态 - 适用:查看单个型号的推送结果 **章节来源** - [frontend/src/views/model/components/CsvViewerDialog.vue:1-50](file://frontend/src/views/model/components/CsvViewerDialog.vue#L1-L50) - [frontend/src/views/model/components/EqCacheDialog.vue:1-306](file://frontend/src/views/model/components/EqCacheDialog.vue#L1-L306) - [frontend/src/views/model/components/PushProgressDialog.vue:1-303](file://frontend/src/views/model/components/PushProgressDialog.vue#L1-L303) - [frontend/src/views/model/components/PushViewDialog.vue:1-60](file://frontend/src/views/model/components/PushViewDialog.vue#L1-L60) ### 型号数据模型与表单结构 - **数据模型字段** - 主键:自增整型 ID - 品牌名称:字符串,最大 100 字符,必填 - 型号名称:字符串,最大 100 字符,必填 - 形式:字符串,最大 100 字符,可空(入耳式/头戴式/耳塞式) - 阻抗:字符串,最大 100 字符,可空 - 来源:字符串,最大 100 字符,可空 - EQ 键:字符串,最大 255 字符,可空 - 创建时间:日期,默认当前时间 - **表单字段与验证** - 品牌名称:必填 - 型号名称:必填,长度 1-100 - 形式:可选枚举值 - 阻抗:可选 - 来源:可选 - 频响文件:可选上传,支持 CSV/TXT/JSON,TXT 自动转换为 CSV - **复杂表单处理** - 文件上传采用 multipart/form-data - 新增时若品牌不存在,先尝试创建品牌再保存型号 - 文件名解析:优先按品牌接口返回的品牌名进行最长前缀匹配,否则按首个空格拆分 **章节来源** - [backend/src/models/Model.js:1-53](file://backend/src/models/Model.js#L1-L53) - [backend/src/validators/model.js:1-22](file://backend/src/validators/model.js#L1-L22) - [frontend/src/views/model/components/ModelFormDialog.vue:196-214](file://frontend/src/views/model/components/ModelFormDialog.vue#L196-L214) ### 品牌关联与外键约束 - **品牌模型** - 主键:自增整型 ID - 名称:唯一、非空、最大 100 字符 - **型号与品牌的关系** - 前端通过品牌下拉选择型号所属品牌 - 后端在新增/编辑时检查品牌是否存在,不存在则创建 - 当前模型字段为字符串类型的"品牌名称",未建立显式的外键约束 - **级联与一致性** - 若后续迁移为外键关联,建议在数据库层面添加约束,并在删除品牌时处理级联或阻止删除 **章节来源** - [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) ### 搜索过滤、排序与分页 - **搜索条件** - 品牌名称(模糊匹配) - 型号名称(模糊匹配) - **排序** - 支持按 ID 与创建时间排序,升序/降序切换 - **分页** - 页面大小:10/20/50/100 - 当前页变更时重置为第一页并重新加载 - **后端实现** - 使用 Sequelize 查询构建 where 条件与 order 排序 - 限制每页最大 1000 条,总数统计用于分页控件 **章节来源** - [frontend/src/views/model/composables/useModelList.js:18-27](file://frontend/src/views/model/composables/useModelList.js#L18-L27) - [frontend/src/views/model/composables/useModelList.js:87-111](file://frontend/src/views/model/composables/useModelList.js#L87-L111) - [backend/src/routes/models.js:133-181](file://backend/src/routes/models.js#L133-L181) ### 批量操作与推送搜索 - **批量复制** - 支持复制所选项的"品牌+型号"文本 - **推送搜索** - 校验:对选中型号调用曲线校验服务,返回校验失败项 - 推送:将型号数据批量写入 Meilisearch 索引 - 进度弹窗:显示校验与推送步骤状态、当前处理项与错误明细 - **多媒体资源** - 查看 EQ 缓存:读取 Redis Hash 字段,支持展开查看 JSON 结构 - 查看 CSV:仅支持来源为特定值的型号,按佩戴方式拼接 S3 Key 并读取 ```mermaid sequenceDiagram participant U as "用户" participant V as "型号视图" participant PP as "PushProgressDialog" participant API as "API 模块" participant R as "后端路由" participant C as "曲线校验服务" participant MS as "Meilisearch" U->>V : 选择多个型号并点击"推送搜索" V->>PP : 打开进度对话框 PP->>API : validatePushToMeilisearch(ids) API->>R : POST /api/models/push-to-search/validate R->>C : 校验曲线数据 C-->>R : 校验结果 R-->>API : 校验错误列表或通过 API-->>PP : 显示校验结果 U->>PP : 确认推送 PP->>API : pushToMeilisearch(ids) API->>R : POST /api/models/push-to-search R->>MS : 写入索引 MS-->>R : 任务 UID R-->>API : 推送结果 API-->>PP : 关闭进度弹窗并刷新 ``` **图表来源** - [frontend/src/views/model/index.vue:402-428](file://frontend/src/views/model/index.vue#L402-L428) - [frontend/src/views/model/components/PushProgressDialog.vue:117-195](file://frontend/src/views/model/components/PushProgressDialog.vue#L117-L195) - [frontend/src/api/model.js:128-150](file://frontend/src/api/model.js#L128-L150) - [backend/src/routes/models.js:466-566](file://backend/src/routes/models.js#L466-L566) **章节来源** - [frontend/src/views/model/index.vue:402-428](file://frontend/src/views/model/index.vue#L402-L428) - [frontend/src/views/model/components/PushProgressDialog.vue:117-195](file://frontend/src/views/model/components/PushProgressDialog.vue#L117-L195) - [frontend/src/api/model.js:128-150](file://frontend/src/api/model.js#L128-L150) ### 频响文件上传与存储优化 - **支持格式** - CSV、TXT、JSON - TXT 自动转换为 CSV(保留频率与幅度列) - **存储路径** - S3 Key 规则:autoeq/measurements/{source}/data/{form}/{brandFirstChar}/{brand model}.csv - 上传成功后将 S3 Key 与型号记录关联 - **读取与展示** - 仅对特定来源与完整字段的型号允许读取 S3 中的 CSV 内容 - 提供弹窗展示 CSV 文本内容 **章节来源** - [backend/src/routes/models.js:59-68](file://backend/src/routes/models.js#L59-L68) - [backend/src/services/measurementStorage.js:48-108](file://backend/src/services/measurementStorage.js#L48-L108) - [frontend/src/views/model/components/CsvViewerDialog.vue:1-50](file://frontend/src/views/model/components/CsvViewerDialog.vue#L1-L50) ### EQ缓存查看与动态配置 - **Redis Key 规则**:{品牌名称} {型号名称} - **功能** - 列出可用的 Hash Key - 展示指定 Key 的 JSON 值(带层级与图标) - 支持加载状态指示与空状态提示 - **适用场景** - 动态配置 EQ 参数、调试频响数据结构 **章节来源** - [backend/src/services/eqCacheStorage.js:24-66](file://backend/src/services/eqCacheStorage.js#L24-L66) - [frontend/src/views/model/components/EqCacheDialog.vue:1-306](file://frontend/src/views/model/components/EqCacheDialog.vue#L1-L306) ### 表单字段解析与文件名智能填充 - **文件名预处理**:去除扩展名、合并多余空格 - **品牌解析策略** - 优先使用品牌接口返回的品牌名进行最长前缀匹配(支持多词品牌) - 回退为"第一个空格"左侧为品牌、右侧为型号 - **默认阻抗**:新增时若未填写,按规则自动填充 **章节来源** - [frontend/src/views/model/components/ModelFormDialog.vue:233-265](file://frontend/src/views/model/components/ModelFormDialog.vue#L233-L265) ### Squig.link外部数据导入 **新增功能**:系统现在支持从squig.link网站导入频响数据。 **工作原理** - **URL解析**:解析squig.link分享URL,提取基础URL和分享参数 - **清单获取**:获取phone_book.json文件,列出所有可用的测量数据 - **文件匹配**:根据分享参数精确匹配或模糊匹配目标文件 - **数据抓取**:下载TXT频响文件并转换为CSV格式 - **信息提取**:从文件名解析品牌和型号信息 - **自动填充**:自动填充表单字段(品牌、型号、佩戴方式等) **支持的URL格式** - `https://theaudiostore.squig.link/?share=Nostalgia_Audio_Camelot` - `https://squig.link/?share=Moondrop_Chu_2` **章节来源** - [frontend/src/api/model.js:157-165](file://frontend/src/api/model.js#L157-L165) - [backend/src/routes/models.js:307-369](file://backend/src/routes/models.js#L307-L369) - [backend/src/services/squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310) ## 依赖关系分析 - **前端依赖** - Element Plus UI 组件库 - Axios 请求封装 - Vue 3 Composition API(组合式函数) - vue-json-pretty JSON展示组件 - **后端依赖** - Express 路由 - Sequelize ORM - AWS SDK(S3) - Redis 客户端 - Meilisearch 客户端 - axios(外部数据抓取) ```mermaid graph LR FE_View["前端视图
index.vue"] --> FE_useModelList["组合式函数
useModelList.js"] FE_useModelList --> FE_API["前端 API
model.js/brand.js"] FE_API --> FE_Request["请求封装
request.js"] FE_API --> BE_Routes["后端路由
models.js/brands.js"] BE_Routes --> BE_Models["数据模型
Model.js/Brand.js"] BE_Routes --> BE_Services["服务层
measurementStorage.js/eqCacheStorage.js/squiglink.js"] BE_Routes --> S3["S3 存储"] BE_Routes --> Redis["Redis 缓存"] BE_Routes --> MS["Meilisearch"] ``` **图表来源** - [frontend/src/views/model/index.vue:227-434](file://frontend/src/views/model/index.vue#L227-L434) - [frontend/src/views/model/composables/useModelList.js:1-191](file://frontend/src/views/model/composables/useModelList.js#L1-L191) - [frontend/src/api/model.js:1-165](file://frontend/src/api/model.js#L1-L165) - [backend/src/routes/models.js:1-659](file://backend/src/routes/models.js#L1-L659) **章节来源** - [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91) - [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72) ## 性能考虑 - **分页与排序** - 后端限制每页最大 1000 条,避免一次性传输大量数据 - 排序字段限定为 ID 与创建时间,减少复杂索引需求 - **文件上传** - 仅允许特定格式,TXT 自动转换降低客户端处理成本 - S3 上传采用内存存储,注意控制文件大小与并发 - **缓存与索引** - EQ 缓存仅列出 Hash Key,避免一次性返回大体积 JSON - 推送搜索采用异步任务与进度弹窗,提升用户体验 - **squig.link抓取** - 使用内存缓存squigsites.json,减少外部请求频率 - 并行处理多项操作,提高响应速度 **章节来源** - [backend/src/services/squiglink.js:33-48](file://backend/src/services/squiglink.js#L33-L48) ## 故障排查指南 - **登录与鉴权** - 401:令牌失效或缺失,自动跳转登录页 - 403:无权限执行操作 - **网络与超时** - 请求超时:检查后端服务与网络连通性 - 响应错误:查看控制台日志与消息提示 - **品牌与型号** - 品牌名称重复:确保品牌唯一性 - 型号重复:同一品牌下型号名称唯一 - **文件上传** - 不支持的文件格式:确认扩展名为 CSV/TXT/JSON - TXT 转换失败:检查文件内容格式是否符合预期 - **S3 与 Redis** - 读取失败:确认 S3 Key 是否正确、对象是否存在 - 缓存为空:确认型号 EQ 缓存是否已生成 - **squig.link导入** - URL格式错误:确认使用标准的squig.link分享链接 - 数据抓取失败:检查网络连接和目标网站可用性 - 文件匹配失败:确认分享参数与目标文件名匹配 **章节来源** - [frontend/src/utils/request.js:27-69](file://frontend/src/utils/request.js#L27-L69) - [backend/src/routes/brands.js:59-81](file://backend/src/routes/brands.js#L59-L81) - [backend/src/routes/models.js:371-499](file://backend/src/routes/models.js#L371-L499) - [backend/src/services/measurementStorage.js:87-108](file://backend/src/services/measurementStorage.js#L87-L108) - [backend/src/services/eqCacheStorage.js:47-66](file://backend/src/services/eqCacheStorage.js#L47-L66) - [backend/src/services/squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310) ## 结论 型号管理页面经过重构后,现已成为一个功能完整、架构清晰的现代化管理系统。通过useModelList组合式函数实现了状态管理的统一化,通过5个专用对话框组件提供了丰富的用户交互体验,通过squig.link导入功能扩展了数据来源的多样性。 系统的主要优势包括: - **模块化设计**:组合式函数和对话框组件的分离提高了代码的可维护性 - **用户体验优化**:完整的进度跟踪和错误处理提升了用户满意度 - **数据来源多样化**:支持本地文件上传和外部网站数据导入 - **扩展性强**:基于Vue 3 Composition API的设计便于功能扩展 建议在后续版本中继续完善: - 添加更多外部数据源的支持 - 增强数据验证和错误恢复机制 - 优化大数据量场景下的性能表现 ## 附录 - **API 一览** - 获取型号列表:GET /api/models/ - 获取单个型号:GET /api/models/:id - 创建型号:POST /api/models/ - 更新型号:PUT /api/models/:id - 删除型号:DELETE /api/models/:id - 推送搜索校验:POST /api/models/push-to-search/validate - 推送搜索:POST /api/models/push-to-search - 查看 Meilisearch 推送:GET /api/models/:id/meilisearch - 查看频响 CSV:GET /api/models/:id/measurement - 查看 EQ 缓存:GET /api/models/:id/eq-cache - 查看 EQ 缓存字段:GET /api/models/:id/eq-cache/field?key=... - 获取品牌列表:GET /api/brands/ - 获取单个品牌:GET /api/brands/:id - 创建品牌:POST /api/brands/ - 更新品牌:PUT /api/brands/:id - 删除品牌:DELETE /api/brands/:id - **新增**:squig.link数据抓取:POST /api/models/squiglink-fetch **章节来源** - [frontend/src/api/model.js:1-165](file://frontend/src/api/model.js#L1-L165) - [frontend/src/api/brand.js:1-66](file://frontend/src/api/brand.js#L1-L66) - [backend/src/routes/models.js:133-659](file://backend/src/routes/models.js#L133-L659) - [backend/src/routes/brands.js:14-147](file://backend/src/routes/brands.js#L14-L147)