Files
dashboard/.qoder/repowiki/zh/content/核心功能模块/型号管理.md
T

476 lines
24 KiB
Markdown
Raw Normal View History

2026-06-30 14:46:52 +08:00
# 型号管理
<cite>
**本文引用的文件**
- [Model.js](file://backend/src/models/Model.js)
- [Brand.js](file://backend/src/models/Brand.js)
- [model.js](file://backend/src/validators/model.js)
- [models.js](file://backend/src/routes/models.js)
2026-07-09 10:33:19 +08:00
- [squiglink.js](file://backend/src/services/squiglink.js)
2026-06-30 14:46:52 +08:00
- [measurementStorage.js](file://backend/src/services/measurementStorage.js)
- [eqCacheStorage.js](file://backend/src/services/eqCacheStorage.js)
- [curveClient.js](file://backend/src/services/curveClient.js)
2026-07-20 18:39:33 +08:00
- [index.vue](file://frontend/src/views/headphone/model/index.vue)
- [ModelFormDialog.vue](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue)
- [model.js](file://frontend/src/service/api/model.ts)
2026-06-30 14:46:52 +08:00
</cite>
2026-07-09 10:33:19 +08:00
## 更新摘要
**变更内容**
2026-07-20 18:39:33 +08:00
- 耳机模型表单对话框得到增强,包含17行新增和9行删除,改进了耳机模型选择和配置界面
- 优化了前端交互体验,提升了用户操作流畅度
- 增强了表单验证和错误处理机制
2026-07-09 10:33:19 +08:00
2026-06-30 14:46:52 +08:00
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
2026-07-09 10:33:19 +08:00
本文件围绕"型号管理"功能进行系统性说明,涵盖型号的 CRUD 操作、技术规格管理、测量数据存储与检索、与品牌模型的一对一关联关系,以及**新增的squig.link集成服务**。文档基于实际代码库实现,提供接口调用流程、数据验证规则、存储策略与常见问题的解决方案,并给出面向初学者与高级开发者的分层解读。
2026-06-30 14:46:52 +08:00
## 项目结构
2026-07-09 10:33:19 +08:00
型号管理功能由前端视图、API 客户端与后端路由/模型/服务共同组成,形成"前端交互—HTTP 请求—后端路由—数据模型—外部存储—squig.link集成"的完整链路。
2026-06-30 14:46:52 +08:00
```mermaid
graph TB
2026-07-20 18:39:33 +08:00
FE["前端视图<br/>frontend/src/views/headphone/model/index.vue"] --> API["API 客户端<br/>frontend/src/service/api/model.ts"]
2026-06-30 14:46:52 +08:00
API --> ROUTER["后端路由<br/>backend/src/routes/models.js"]
ROUTER --> MODEL["型号模型<br/>backend/src/models/Model.js"]
ROUTER --> VALIDATOR["型号验证器<br/>backend/src/validators/model.js"]
ROUTER --> MSVC["频响存储服务<br/>backend/src/services/measurementStorage.js"]
ROUTER --> ESVC["EQ 缓存服务<br/>backend/src/services/eqCacheStorage.js"]
ROUTER --> CSVC["曲线校验服务<br/>backend/src/services/curveClient.js"]
2026-07-09 10:33:19 +08:00
ROUTER --> SSVC["squig.link集成服务<br/>backend/src/services/squiglink.js"]
2026-06-30 14:46:52 +08:00
ROUTER --> BRAND["品牌模型<br/>backend/src/models/Brand.js"]
```
2026-07-09 10:33:19 +08:00
**图表来源**
2026-07-20 18:39:33 +08:00
- [index.vue:1-1226](file://frontend/src/views/headphone/model/index.vue#L1-L1226)
- [model.js:1-165](file://frontend/src/service/api/model.ts#L1-L165)
2026-07-09 10:33:19 +08:00
- [models.js:1-659](file://backend/src/routes/models.js#L1-L659)
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
- [measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
2026-07-09 10:33:19 +08:00
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
2026-07-09 10:33:19 +08:00
**章节来源**
2026-07-20 18:39:33 +08:00
- [index.vue:1-1226](file://frontend/src/views/headphone/model/index.vue#L1-L1226)
- [model.js:1-165](file://frontend/src/service/api/model.ts#L1-L165)
2026-07-09 10:33:19 +08:00
- [models.js:1-659](file://backend/src/routes/models.js#L1-L659)
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
- [measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
2026-07-09 10:33:19 +08:00
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
## 核心组件
- 型号模型:定义型号的数据结构与约束,包括品牌名称、型号名称、形式、阻抗、来源、EQ 键等字段。
- 品牌模型:与型号存在一对一关联,型号通过品牌名称进行关联。
- 型号验证器:使用 Zod 对创建/更新请求体进行严格校验。
2026-07-09 10:33:19 +08:00
- 型号路由:提供列表查询、详情查看、新增、更新、删除、搜索推送、频响 CSV 查看、EQ 缓存查看、**squig.link数据抓取**等接口。
- **squig.link集成服务**:支持从外部频率响应数据源自动获取数据,包括URL解析、数据抓取、格式转换、品牌/型号解析等功能。
2026-06-30 14:46:52 +08:00
- 测量存储服务:负责将频响 CSV/文本文件上传至 S3,并支持按路径键读取。
- EQ 缓存服务:通过 Redis 提供型号 EQ 数据的哈希字段列表与具体值读取。
- 曲线校验服务:对接外部曲线 API,校验型号的 parametric_eq 数据有效性。
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
2026-07-09 10:33:19 +08:00
- [models.js:133-659](file://backend/src/routes/models.js#L133-L659)
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
2026-06-30 14:46:52 +08:00
- [measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
## 架构总览
型号管理的端到端流程如下:
- 前端通过 API 客户端发起请求,后端路由接收并进行鉴权与参数校验。
2026-07-09 10:33:19 +08:00
- 路由根据业务逻辑调用模型层与服务层,完成数据库读写、外部存储交互、第三方校验以及**squig.link数据抓取**。
- 前端渲染结果,支持批量推送至搜索引擎、查看频响 CSV、查看 EQ 缓存等,**以及从squig.link直接导入数据**。
2026-06-30 14:46:52 +08:00
```mermaid
sequenceDiagram
participant U as "用户"
participant FE as "前端视图"
participant API as "API 客户端"
participant RT as "后端路由(models.js)"
participant MD as "型号模型(Model.js)"
2026-07-09 10:33:19 +08:00
participant SS as "squig.link服务(squiglink.js)"
2026-06-30 14:46:52 +08:00
participant MS as "频响存储(measurementStorage.js)"
participant ES as "EQ 缓存(eqCacheStorage.js)"
participant CS as "曲线校验(curveClient.js)"
U->>FE : 打开型号页面
2026-07-09 10:33:19 +08:00
FE->>API : 发起列表/详情/新增/更新/删除/抓取请求
2026-06-30 14:46:52 +08:00
API->>RT : HTTP 请求
alt 查询列表/详情
RT->>MD : 读取数据库
MD-->>RT : 返回数据
else 新增/更新
RT->>MD : 写入数据库
MD-->>RT : 返回新记录
2026-07-09 10:33:19 +08:00
opt 上传频响文件或squig.link数据
RT->>SS : 抓取squig.link数据可选
SS-->>RT : 返回CSV内容和元数据
2026-06-30 14:46:52 +08:00
RT->>MS : 上传CSV/文本至S3
MS-->>RT : 返回S3 Key
end
else 删除
RT->>ES : 从搜索引擎删除文档
RT->>MD : 删除数据库记录
end
RT-->>API : 返回响应
API-->>FE : 渲染结果
```
2026-07-09 10:33:19 +08:00
**图表来源**
- [models.js:133-659](file://backend/src/routes/models.js#L133-L659)
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
2026-07-09 10:33:19 +08:00
- [squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310)
2026-06-30 14:46:52 +08:00
- [measurementStorage.js:61-108](file://backend/src/services/measurementStorage.js#L61-L108)
- [eqCacheStorage.js:24-66](file://backend/src/services/eqCacheStorage.js#L24-L66)
- [curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
2026-07-20 18:39:33 +08:00
- [index.vue:714-1063](file://frontend/src/views/headphone/model/index.vue#L714-L1063)
- [model.js:13-165](file://frontend/src/service/api/model.ts#L13-L165)
2026-06-30 14:46:52 +08:00
## 详细组件分析
### 型号数据模型与品牌关联
- 型号模型包含主键、品牌名称、型号名称、形式、阻抗、来源、EQ 键、创建时间等字段。
- 品牌模型包含主键与唯一约束的品牌名称。
- 关联关系:前端在新增型号时会检查品牌是否存在,若不存在则自动创建;后端在新增/更新时也通过品牌名称进行一致性校验。
```mermaid
erDiagram
BRAND {
int id PK
string name UK
}
MODEL {
int id PK
string brand_name
string name
string form
string rig
string source
string eq_key
datetime create_at
}
BRAND ||--o{ MODEL : "拥有多个型号"
```
2026-07-09 10:33:19 +08:00
**图表来源**
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
### 型号验证器与参数规范
- 创建验证器:要求品牌名称与型号名称非空且长度不超过 100;其他字段可选且可为空。
- 更新验证器:允许部分字段可选更新,其余规则与创建一致。
- 返回值:验证通过后进入业务流程,失败则返回错误信息。
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
### 型号 CRUD 与查询接口
- 列表查询:支持按品牌名称、型号名称模糊过滤,支持按 id 或创建时间排序,支持分页与跳过。
- 详情查看:按 id 获取单条型号信息。
2026-07-09 10:33:19 +08:00
- 新增:支持上传频响文件(CSV/TXT/JSON)或**squiglink_csv参数**,自动转换 TXT 为 CSV;若存在同品牌同型号则拒绝重复创建。
2026-06-30 14:46:52 +08:00
- 更新:支持部分字段更新;若上传新文件,需提供来源与形式字段;更新后写入数据库并可重新上传频响文件。
- 删除:删除前尝试从搜索引擎删除文档,再删除数据库记录。
2026-07-09 10:33:19 +08:00
**章节来源**
- [models.js:133-659](file://backend/src/routes/models.js#L133-L659)
2026-06-30 14:46:52 +08:00
### 技术规格管理
- 形式字段:支持入耳式、头戴式、耳塞式等枚举值映射。
- 阻抗字段:用于记录典型阻抗值。
- 来源字段:标识型号数据来源(如 Eafonyoung)。
- EQ 键字段:用于关联 EQ 缓存的键名。
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
2026-07-20 18:39:33 +08:00
- [index.vue:226-250](file://frontend/src/views/headphone/model/index.vue#L226-L250)
2026-06-30 14:46:52 +08:00
### 测量数据存储与检索
- 文件类型:支持 CSV、TXT、JSONTXT 将被转换为 CSV。
- 上传流程:后端接收 multipart/form-data,校验扩展名,必要时转换格式,然后上传至 S3。
- 下载流程:仅对特定来源(如 Eafonyoung)开放,需具备形式字段以定位 S3 Key。
- S3 Key 构造规则:按来源、形式、品牌首字母与品牌+型号文件名组织路径。
```mermaid
flowchart TD
Start(["上传入口"]) --> CheckExt["校验文件扩展名"]
CheckExt --> ExtOK{"扩展名有效?"}
ExtOK --> |否| ErrExt["返回错误:不支持的文件格式"]
ExtOK --> |是| Convert["如为TXT则转换为CSV"]
Convert --> BuildKey["构建S3 Key"]
BuildKey --> Put["上传至S3"]
Put --> Done(["完成"])
ErrExt --> Done
```
2026-07-09 10:33:19 +08:00
**图表来源**
2026-06-30 14:46:52 +08:00
- [models.js:59-68](file://backend/src/routes/models.js#L59-L68)
- [models.js:307-335](file://backend/src/routes/models.js#L307-L335)
- [measurementStorage.js:48-79](file://backend/src/services/measurementStorage.js#L48-L79)
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [models.js:59-68](file://backend/src/routes/models.js#L59-L68)
- [models.js:307-335](file://backend/src/routes/models.js#L307-L335)
- [measurementStorage.js:48-79](file://backend/src/services/measurementStorage.js#L48-L79)
### EQ 缓存与频响 CSV 查看
- EQ 缓存:通过 Redis 哈希存储型号的 EQ 数据,提供字段列表与单字段值读取。
- 频响 CSV:仅对特定来源开放,按来源、形式、品牌、型号拼接 S3 Key 并读取内容。
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [models.js:183-278](file://backend/src/routes/models.js#L183-L278)
- [eqCacheStorage.js:24-66](file://backend/src/services/eqCacheStorage.js#L24-L66)
- [measurementStorage.js:87-108](file://backend/src/services/measurementStorage.js#L87-L108)
### 搜索引擎推送与校验
- 校验:对选中型号调用曲线校验服务,确保 parametric_eq 结构有效。
- 推送:将型号文档推送到搜索引擎,支持批量与进度反馈。
```mermaid
sequenceDiagram
participant FE as "前端"
participant API as "API 客户端"
participant RT as "后端路由(models.js)"
participant CS as "曲线校验(curveClient.js)"
FE->>API : 选择型号并点击推送
API->>RT : POST /models/push-to-search/validate
loop 对每个型号
RT->>CS : fetchAndValidateCurve(brand,name,form)
CS-->>RT : [ok, reason]
end
alt 全部通过
API->>RT : POST /models/push-to-search
RT-->>API : 返回推送结果
else 部分失败
RT-->>API : 返回错误列表
end
```
2026-07-09 10:33:19 +08:00
**图表来源**
2026-06-30 14:46:52 +08:00
- [models.js:466-514](file://backend/src/routes/models.js#L466-L514)
- [models.js:516-566](file://backend/src/routes/models.js#L516-L566)
- [curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
2026-07-20 18:39:33 +08:00
- [index.vue:1117-1220](file://frontend/src/views/headphone/model/index.vue#L1117-L1220)
2026-06-30 14:46:52 +08:00
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [models.js:466-514](file://backend/src/routes/models.js#L466-L514)
- [models.js:516-566](file://backend/src/routes/models.js#L516-L566)
- [curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
2026-07-20 18:39:33 +08:00
- [index.vue:1117-1220](file://frontend/src/views/headphone/model/index.vue#L1117-L1220)
2026-06-30 14:46:52 +08:00
2026-07-09 10:33:19 +08:00
### Squig.link集成服务与自动数据抓取
**新增功能**:型号管理现已集成squig.link外部数据源,支持从分享链接自动抓取频响数据。
#### 核心特性
- **URL解析**:支持标准squig.link分享URL格式,自动提取baseURL和share参数
- **数据抓取**:自动获取phone_book.json清单,匹配目标文件
- **格式转换**:将TXT格式频响数据转换为CSV格式
- **品牌/型号解析**:从文件名自动解析品牌和型号信息
- **佩戴方式检测**:通过squigsites.json配置自动识别入耳式/头戴式/耳塞式
- **多候选处理**:当存在多个匹配文件时,提供候选列表供用户选择
#### 技术实现
- **squigsites.json缓存**1小时内存缓存,减少外部请求
- **并行处理**:同时获取phone_book和检测佩戴方式,提升响应速度
- **智能匹配**:精确匹配失败时进行模糊搜索,提高成功率
- **容错机制**:多种TXT文件后缀尝试,确保数据完整性
```mermaid
flowchart TD
Start(["squig.link抓取开始"]) --> ParseURL["解析分享URL"]
ParseURL --> GetPhoneBook["获取phone_book.json"]
GetPhoneBook --> MatchFile["匹配目标文件"]
MatchFile --> ExactMatch{"精确匹配?"}
ExactMatch --> |是| DownloadTXT["下载TXT文件"]
ExactMatch --> |否| FuzzySearch["模糊搜索候选"]
FuzzySearch --> Multiple{"多个候选?"}
Multiple --> |是| ShowCandidates["显示候选列表"]
Multiple --> |否| DownloadTXT
ShowCandidates --> UserSelect["用户选择文件"]
UserSelect --> DownloadTXT
DownloadTXT --> ConvertCSV["转换为CSV"]
ConvertCSV --> DetectForm["检测佩戴方式"]
DetectForm --> ParseBrand["解析品牌/型号"]
ParseBrand --> ReturnData["返回抓取结果"]
```
**图表来源**
- [squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310)
- [squiglink.js:148-207](file://backend/src/services/squiglink.js#L148-L207)
- [squiglink.js:216-247](file://backend/src/services/squiglink.js#L216-L247)
#### 前端集成
- **导入界面**:在型号表单中新增squig.link导入区域
- **实时抓取**:输入URL后自动抓取数据,无需手动提交
- **候选选择**:当存在多个匹配文件时,弹出选择对话框
- **自动填充**:成功抓取后自动填充品牌、型号、佩戴方式等字段
#### 后端API
- **POST /api/models/squiglink-fetch**:处理squig.link数据抓取请求
- **支持参数**share_url(必需)、selected_file(可选)
- **返回数据**:CSV内容、品牌/型号、佩戴方式、数据URL、候选列表
**章节来源**
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
- [models.js:307-369](file://backend/src/routes/models.js#L307-L369)
2026-07-20 18:39:33 +08:00
- [ModelFormDialog.vue:16-46](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue#L16-L46)
- [ModelFormDialog.vue:289-332](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue#L289-L332)
- [model.js:152-165](file://frontend/src/service/api/model.ts#L152-L165)
2026-07-09 10:33:19 +08:00
2026-06-30 14:46:52 +08:00
### 前端交互与使用示例
- 列表查询:支持品牌名称与型号名称模糊搜索、排序与分页。
- 详情查看:点击更多操作可查看推送状态、EQ 缓存、CSV 内容。
2026-07-09 10:33:19 +08:00
- 参数配置:新增/编辑对话框支持品牌选择、型号输入、形式、阻抗、来源与频响文件上传,**以及squig.link分享链接导入**。
2026-06-30 14:46:52 +08:00
- 批量推送:勾选多条后执行推送流程,包含校验与进度提示。
2026-07-09 10:33:19 +08:00
- **squig.link导入**:在表单中输入squig.link分享链接,自动抓取频响数据并填充表单字段。
2026-06-30 14:46:52 +08:00
2026-07-09 10:33:19 +08:00
**章节来源**
2026-07-20 18:39:33 +08:00
- [index.vue:1-1226](file://frontend/src/views/headphone/model/index.vue#L1-L1226)
- [ModelFormDialog.vue:1-555](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue#L1-L555)
- [model.js:1-165](file://frontend/src/service/api/model.ts#L1-L165)
2026-06-30 14:46:52 +08:00
## 依赖关系分析
- 前端依赖:Element Plus 组件库、Vue 3、axios 请求封装。
- 后端依赖:Express 路由、Sequelize ORM、Zod 验证、Multer 文件上传、Axios 第三方调用、AWS SDK S3 访问、Redis 客户端。
2026-07-09 10:33:19 +08:00
- 外部服务:Meilisearch(搜索引擎)、Luxsin 曲线 API、S3 存储、**squig.link外部数据源**。
2026-06-30 14:46:52 +08:00
```mermaid
graph LR
2026-07-20 18:39:33 +08:00
FE["前端(index.vue)"] --> API["API(model.ts)"]
2026-06-30 14:46:52 +08:00
API --> RT["路由(models.js)"]
RT --> MD["模型(Model.js)"]
RT --> VAL["验证器(model.js)"]
RT --> MS["S3(measurementStorage.js)"]
RT --> ES["Redis(eqCacheStorage.js)"]
RT --> CS["曲线(curveClient.js)"]
2026-07-09 10:33:19 +08:00
RT --> SS["squig.link(squiglink.js)"]
2026-06-30 14:46:52 +08:00
RT --> BR["品牌(Brand.js)"]
```
2026-07-09 10:33:19 +08:00
**图表来源**
2026-07-20 18:39:33 +08:00
- [index.vue:1-1226](file://frontend/src/views/headphone/model/index.vue#L1-L1226)
- [model.js:1-165](file://frontend/src/service/api/model.ts#L1-L165)
2026-07-09 10:33:19 +08:00
- [models.js:1-659](file://backend/src/routes/models.js#L1-L659)
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
- [measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
2026-07-09 10:33:19 +08:00
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
2026-07-09 10:33:19 +08:00
**章节来源**
2026-07-20 18:39:33 +08:00
- [index.vue:1-1226](file://frontend/src/views/headphone/model/index.vue#L1-L1226)
- [model.js:1-165](file://frontend/src/service/api/model.ts#L1-L165)
2026-07-09 10:33:19 +08:00
- [models.js:1-659](file://backend/src/routes/models.js#L1-L659)
2026-06-30 14:46:52 +08:00
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
- [model.js:1-22](file://backend/src/validators/model.js#L1-L22)
- [measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
2026-07-09 10:33:19 +08:00
- [squiglink.js:1-322](file://backend/src/services/squiglink.js#L1-L322)
2026-06-30 14:46:52 +08:00
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
## 性能考虑
- 分页与排序:列表查询支持分页与排序,建议前端设置合理页大小与排序字段,避免一次性加载过多数据。
- 文件上传:上传 TXT 时会进行转换,建议控制文件大小与格式,减少不必要的转换开销。
- 搜索推送:批量推送包含校验步骤,建议分批处理并监控进度,避免超时。
- 缓存与存储:EQ 缓存通过 Redis 快速读取字段列表,避免大对象传输;S3 读取采用流式读取,注意网络抖动与超时配置。
2026-07-09 10:33:19 +08:00
- **squig.link抓取**squigsites.json采用1小时缓存,减少外部请求;并行处理phone_book获取和佩戴方式检测,提升响应速度。
2026-06-30 14:46:52 +08:00
## 故障排查指南
- 参数验证失败
- 现象:创建/更新返回参数错误。
- 排查:检查品牌名称与型号名称长度、必填字段是否缺失;确认前端表单规则与后端验证器一致。
- 参考
- [model.js:3-19](file://backend/src/validators/model.js#L3-L19)
- [models.js:307-361](file://backend/src/routes/models.js#L307-L361)
- 重复型号
2026-07-09 10:33:19 +08:00
- 现象:新增时报"该品牌下型号名称已存在"。
2026-06-30 14:46:52 +08:00
- 排查:确认数据库中是否已存在相同品牌+型号组合;更新时注意品牌与型号变更后的冲突检测。
- 参考
- [models.js:312-317](file://backend/src/routes/models.js#L312-L317)
- [models.js:380-388](file://backend/src/routes/models.js#L380-L388)
- 不支持的文件格式
2026-07-09 10:33:19 +08:00
- 现象:上传文件返回"不支持的文件格式"。
2026-06-30 14:46:52 +08:00
- 排查:确认扩展名为 CSV/TXT/JSONTXT 会被转换为 CSV。
- 参考
2026-07-20 18:39:33 +08:00
- [models.js:320-325](file://backend/src/routes/models.js#L320-325)
2026-06-30 14:46:52 +08:00
- [models.js:59-68](file://backend/src/routes/models.js#L59-L68)
- S3 读取失败
2026-07-09 10:33:19 +08:00
- 现象:查看 CSV 时提示"S3 上未找到该型号的频响文件"或读取失败。
2026-06-30 14:46:52 +08:00
- 排查:确认来源为 Eafonyoung、具备形式字段、S3 Key 构造正确;检查桶权限与区域配置。
- 参考
- [models.js:255-258](file://backend/src/routes/models.js#L255-L258)
- [measurementStorage.js:87-108](file://backend/src/services/measurementStorage.js#L87-L108)
- 推送失败
- 现象:推送至搜索引擎失败或校验未通过。
- 排查:检查型号的佩戴方式是否为入耳式或头戴式;确认曲线接口可用与响应格式正确。
- 参考
- [models.js:466-514](file://backend/src/routes/models.js#L466-L514)
- [curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
2026-07-09 10:33:19 +08:00
- **squig.link抓取失败**
- 现象:输入squig.link分享链接后无法抓取数据。
- 排查:确认URL格式正确、网络连接正常、目标文件存在于phone_book中;检查squigsites.json缓存是否过期;查看后端日志获取详细错误信息。
- 参考
- [models.js:307-369](file://backend/src/routes/models.js#L307-L369)
- [squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310)
2026-07-20 18:39:33 +08:00
- [ModelFormDialog.vue:289-332](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue#L289-L332)
2026-06-30 14:46:52 +08:00
2026-07-09 10:33:19 +08:00
**章节来源**
2026-06-30 14:46:52 +08:00
- [model.js:3-19](file://backend/src/validators/model.js#L3-L19)
- [models.js:312-317](file://backend/src/routes/models.js#L312-L317)
2026-07-20 18:39:33 +08:00
- [models.js:320-325](file://backend/src/routes/models.js#L320-325)
2026-06-30 14:46:52 +08:00
- [models.js:255-258](file://backend/src/routes/models.js#L255-L258)
- [measurementStorage.js:87-108](file://backend/src/services/measurementStorage.js#L87-L108)
- [models.js:466-514](file://backend/src/routes/models.js#L466-L514)
- [curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
2026-07-09 10:33:19 +08:00
- [models.js:307-369](file://backend/src/routes/models.js#L307-L369)
- [squiglink.js:261-310](file://backend/src/services/squiglink.js#L261-L310)
2026-07-20 18:39:33 +08:00
- [ModelFormDialog.vue:289-332](file://frontend/src/views/headphone/model/components/ModelFormDialog.vue#L289-L332)
2026-06-30 14:46:52 +08:00
## 结论
2026-07-09 10:33:19 +08:00
型号管理功能通过清晰的前后端职责划分与严格的参数验证,实现了从基础 CRUD 到技术规格管理、测量数据存储与搜索引擎推送的完整闭环。**新增的squig.link集成服务进一步增强了数据获取能力,支持从外部频率响应数据源自动抓取数据,显著提升了用户体验**。借助 Redis 与 S3 的高效读写能力,以及第三方曲线校验服务,系统在保证数据一致性的同时提升了用户体验与可维护性。建议在生产环境中进一步完善日志与监控,优化批量推送的并发与重试策略,并持续关注外部依赖的稳定性。
2026-06-30 14:46:52 +08:00
## 附录
- 常用接口清单
- 列表查询:GET /api/models/
- 详情查看:GET /api/models/:id
- 新增:POST /api/models/
- 更新:PUT /api/models/:id
- 删除:DELETE /api/models/:id
- 查看 EQ 缓存:GET /api/models/:id/eq-cache
- 查看 EQ 缓存字段:GET /api/models/:id/eq-cache/field?key=...
- 查看搜索引擎推送:GET /api/models/:id/meilisearch
- 查看频响 CSVGET /api/models/:id/measurement
- 校验推送:POST /api/models/push-to-search/validate
- 推送:POST /api/models/push-to-search
2026-07-09 10:33:19 +08:00
- **squig.link数据抓取**POST /api/models/squiglink-fetch
2026-06-30 14:46:52 +08:00
2026-07-09 10:33:19 +08:00
**章节来源**
- [models.js:133-659](file://backend/src/routes/models.js#L133-L659)
2026-07-20 18:39:33 +08:00
- [model.js:13-165](file://frontend/src/service/api/model.ts#L13-L165)