# API 接口文档
**本文档引用的文件**
- [cmd/server/main.go](file://cmd/server/main.go)
- [internal/router/router.go](file://internal/router/router.go)
- [internal/handler/health.go](file://internal/handler/health.go)
- [internal/handler/brand.go](file://internal/handler/brand.go)
- [internal/handler/model.go](file://internal/handler/model.go)
- [internal/handler/model_list.go](file://internal/handler/model_list.go)
- [internal/handler/device.go](file://internal/handler/device.go)
- [internal/handler/share_code.go](file://internal/handler/share_code.go)
- [internal/handler/curve.go](file://internal/handler/curve.go)
- [internal/response/response.go](file://internal/response/response.go)
- [internal/middleware/cors.go](file://internal/middleware/cors.go)
- [internal/middleware/logger.go](file://internal/middleware/logger.go)
- [internal/middleware/request_id.go](file://internal/middleware/request_id.go)
- [internal/middleware/cache_control.go](file://internal/middleware/cache_control.go)
- [internal/search/meilisearch.go](file://internal/search/meilisearch.go)
- [internal/repository/brand.go](file://internal/repository/brand.go)
- [internal/repository/model.go](file://internal/repository/model.go)
- [internal/cache/share_code_cache.go](file://internal/cache/share_code_cache.go)
- [internal/cache/curve_cache.go](file://internal/cache/curve_cache.go)
- [internal/model/share_code.go](file://internal/model/share_code.go)
- [internal/config/share_code_ttl.go](file://internal/config/share_code_ttl.go)
- [internal/config/s3.go](file://internal/config/s3.go)
- [internal/config/equalize.go](file://internal/config/equalize.go)
- [internal/storage/s3.go](file://internal/storage/s3.go)
- [internal/task/share_code_persist.go](file://internal/task/share_code_persist.go)
- [internal/task/device_persist.go](file://internal/task/device_persist.go)
- [pkg/encode/base64.go](file://pkg/encode/base64.go)
- [internal/config/config.go](file://internal/config/config.go)
- [README.md](file://README.md)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细接口说明](#详细接口说明)
6. [依赖关系分析](#依赖关系分析)
7. [性能与可用性](#性能与可用性)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件为 Luxsin 应用 API 的完整接口文档,覆盖品牌管理、型号管理、设备上报、分享代码管理和等化曲线等接口。文档提供各接口的 HTTP 方法、URL 模式、请求参数、响应格式、错误处理、使用示例与最佳实践,并说明认证方式、速率限制策略、版本信息、客户端实现建议、调试与监控方法,以及向后兼容性与迁移注意事项。
## 项目结构
- 入口程序负责初始化配置、数据库、搜索引擎与缓存,构建路由并启动 HTTP 服务。
- 路由层按版本与业务域分组,注册各处理器。
- 处理器负责参数解析、调用仓储或搜索客户端、返回统一响应格式。
- 统一响应体封装了状态码、消息与数据字段,便于前端一致化处理。
- 中间件提供 CORS、日志、请求 ID 注入与缓存控制,便于跨域、可观测与追踪。
- 搜索与缓存分别对接 Meilisearch 与 Redis,支撑型号检索与设备上报数据存储。
- **新增**:分享代码缓存层提供基于 Redis 的高效分享码管理,支持分布式锁与持久化队列。
- **新增**:等化曲线缓存层提供高性能的频响曲线数据缓存,支持独立存储 fr 数据优化。
- **新增**:S3 存储集成支持 CSV 数据读取,为等化曲线处理提供测量数据源。
- **新增**:缓存控制中间件提供针对不同接口的差异化缓存策略。
```mermaid
graph TB
subgraph "服务进程"
MAIN["cmd/server/main.go
启动与生命周期"]
ROUTER["internal/router/router.go
路由注册"]
end
subgraph "HTTP 层"
CORS["internal/middleware/cors.go
CORS"]
LOGMW["internal/middleware/logger.go
访问日志"]
RID["internal/middleware/request_id.go
请求ID注入"]
CACHECTRL["internal/middleware/cache_control.go
缓存控制"]
end
subgraph "业务层"
HEALTH["internal/handler/health.go
健康检查"]
BRAND["internal/handler/brand.go
品牌列表"]
MODEL["internal/handler/model.go
型号详情"]
MODELLIST["internal/handler/model_list.go
型号检索"]
DEVICE["internal/handler/device.go
设备上报"]
SHARECODE["internal/handler/share_code.go
分享代码管理"]
CURVE["internal/handler/curve.go
等化曲线"]
end
subgraph "数据与外部服务"
RESP["internal/response/response.go
统一响应"]
DB["MySQL(由配置驱动)"]
MS["Meilisearch(由配置驱动)"]
REDIS["Redis(由配置驱动)"]
S3["S3存储(由配置驱动)"]
end
MAIN --> ROUTER
ROUTER --> CORS --> LOGMW --> RID --> CACHECTRL
ROUTER --> HEALTH
ROUTER --> BRAND
ROUTER --> MODEL
ROUTER --> MODELLIST
ROUTER --> DEVICE
ROUTER --> SHARECODE
ROUTER --> CURVE
BRAND --> DB
MODEL --> DB
MODELLIST --> MS
DEVICE --> REDIS
SHARECODE --> REDIS
CURVE --> DB
CURVE --> S3
CURVE --> REDIS
HEALTH --> RESP
BRAND --> RESP
MODEL --> RESP
MODELLIST --> RESP
DEVICE --> RESP
SHARECODE --> RESP
CURVE --> RESP
```
**图表来源**
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/device.go:26-85](file://internal/handler/device.go#L26-L85)
- [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383)
- [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
**章节来源**
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
- [README.md:1-127](file://README.md#L1-L127)
## 核心组件
- 路由与中间件
- 路由在 /api/v1 下提供健康检查,在 /audio 下提供品牌、型号、型号检索、设备上报、分享代码管理与等化曲线接口。
- 中间件链:恢复、请求 ID、日志、CORS、缓存控制。
- 统一响应
- 所有接口返回统一结构,包含 code、message、data 字段;错误时 code 为非零。
- 搜索与缓存
- 型号检索通过 Meilisearch 客户端完成;设备上报通过 Redis Hash 存储。
- **新增**:分享代码管理通过 Redis 实现高效的数据结构,包括主数据、MAC 索引、待持久化队列等。
- **新增**:等化曲线缓存支持独立存储 fr 数据,避免重复存储,提升缓存效率。
- **新增**:缓存控制中间件为不同接口提供差异化缓存策略,包括品牌/型号列表、等化曲线和型号检索。
- 存储与集成
- **新增**:S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
- **新增**:等化曲线处理系统支持多种目标曲线的参数化 EQ 计算。
- 编码扩展
- 支持 base64Resp 参数,将响应体 JSON 再做自定义 Base64 编码传输,便于某些网络环境或协议需求。
**章节来源**
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
- [internal/search/meilisearch.go:17-46](file://internal/search/meilisearch.go#L17-L46)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
- [internal/cache/share_code_cache.go:33-353](file://internal/cache/share_code_cache.go#L33-L353)
- [internal/cache/curve_cache.go:18-148](file://internal/cache/curve_cache.go#L18-L148)
- [internal/storage/s3.go:15-57](file://internal/storage/s3.go#L15-L57)
## 架构总览
以下序列图展示一次典型请求从接入到响应的全链路:
```mermaid
sequenceDiagram
participant C as "客户端"
participant G as "Gin 路由"
participant MW as "中间件(CORS/日志/请求ID/缓存控制)"
participant H as "处理器"
participant S as "搜索/缓存/数据库/S3"
C->>G : "HTTP 请求"
G->>MW : "中间件链"
MW-->>G : "注入请求ID/日志/CORS/缓存控制"
G->>H : "匹配路由并调用处理器"
H->>S : "读取/写入(数据库/搜索/缓存/S3)"
S-->>H : "结果/错误"
H-->>G : "统一响应体"
G-->>C : "HTTP 响应(JSON/可选base64)"
```
**图表来源**
- [internal/router/router.go:27-38](file://internal/router/router.go#L27-L38)
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
- [internal/middleware/cache_control.go:11-17](file://internal/middleware/cache_control.go#L11-L17)
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/device.go:26-85](file://internal/handler/device.go#L26-L85)
- [internal/handler/share_code.go:40-125](file://internal/handler/share_code.go#L40-L125)
- [internal/handler/curve.go:56-127](file://internal/handler/curve.go#L56-127)
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
## 详细接口说明
### 版本与基础信息
- 版本分组
- /api/v1:健康检查
- /audio:品牌、型号、型号检索、设备上报、分享代码管理、等化曲线
- 认证方式
- 当前实现未内置鉴权逻辑,未发现显式的 Token/签名/密钥校验流程。
- 速率限制
- 当前实现未内置全局限流策略,如需请结合网关或中间件扩展。
- 基础响应结构
- 成功:code=0,message="ok",data 为业务数据
- 失败:code 非 0,message 为错误描述
- base64Resp
- 可选查询参数 base64Resp=true|1|空 时,将响应体 JSON 再进行自定义 Base64 编码返回;默认开启。
**章节来源**
- [internal/router/router.go:27-38](file://internal/router/router.go#L27-L38)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
### 健康检查 /api/v1/health
- 方法与路径
- GET /api/v1/health
- 请求参数
- 无
- 响应
- data.status = "up"
- 错误处理
- 无内部错误路径,始终返回成功
- 使用场景
- 服务存活探测、负载均衡探活
- 示例
- curl: [README.md:89-103](file://README.md#L89-L103)
**章节来源**
- [internal/router/router.go:29](file://internal/router/router.go#L29)
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
- [README.md:89-103](file://README.md#L89-L103)
### 品牌管理 /audio/getBrand
- 方法与路径
- GET /audio/getBrand
- 请求参数
- brandName: 可选,用于模糊过滤品牌名称
- base64Resp: 可选,是否对响应体进行二次 Base64 编码
- 响应数据
- 列表项包含品牌 id 与 name
- 错误处理
- 数据库查询异常:统一返回内部错误
- 编码异常:统一返回内部错误
- 使用场景
- 获取品牌列表,支持按名称模糊筛选
- 示例
- curl: [README.md:107-113](file://README.md#L107-L113)
**章节来源**
- [internal/router/router.go:34](file://internal/router/router.go#L34)
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/repository/brand.go:20-51](file://internal/repository/brand.go#L20-L51)
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
- [README.md:107-113](file://README.md#L107-L113)
### 型号管理 /audio/getModel
- 方法与路径
- GET /audio/getModel
- 请求参数
- brandName: 可选,按品牌过滤
- modelName: 可选,按型号名称模糊过滤
- base64Resp: 可选,是否对响应体进行二次 Base64 编码
- 响应数据
- 列表项包含 id、brand_name、name、form、rig、source、eq_key、create_at;部分字段可能为空
- 错误处理
- 数据库查询异常:统一返回内部错误
- 编码异常:统一返回内部错误
- 使用场景
- 获取指定品牌或型号的详细列表
- 示例
- 无直接示例,但可通过组合 brandName 与 modelName 参数实现不同维度查询
**章节来源**
- [internal/router/router.go:35](file://internal/router/router.go#L35)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/repository/model.go:20-95](file://internal/repository/model.go#L20-L95)
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
### 型号检索 /audio/modelList
- 方法与路径
- GET /audio/modelList
- 请求参数
- key: 必填,检索关键词
- count: 可选,最大返回条数,默认 100
- base64Resp: 可选,是否对响应体进行二次 Base64 编码
- 响应数据
- 列表项包含 rig、form、name、brand_name、source、eq_key 等字段
- 错误处理
- 搜索异常:统一返回内部错误
- 编码异常:统一返回内部错误
- 使用场景
- 基于关键词的型号检索,适用于推荐、搜索框等
- 示例
- 无直接示例,但可参考 Meilisearch 的检索行为
**章节来源**
- [internal/router/router.go:36](file://internal/router/router.go#L36)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/search/meilisearch.go:22-46](file://internal/search/meilisearch.go#L22-L46)
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
### 设备上报 /audio/reportDevInfo
- 方法与路径
- GET /audio/reportDevInfo
- 请求参数
- mac: 必填,设备 MAC 地址
- model: 必填,设备型号
- ver: 可选,版本号
- X-Forwarded-For: 可选,客户端 IP(由代理注入)
- 响应
- 成功:code=200,msg="操作成功"
- 参数缺失:code=400,msg="参数校验失败"
- 系统错误:code=500,msg="系统错误"
- 存储行为
- 将设备信息以 JSON 形式写入 Redis Hash,键为 devices,field 为 mac
- 错误处理
- 参数校验失败:返回业务错误
- JSON 序列化失败:返回内部错误
- Redis 写入失败:返回内部错误
- 使用场景
- 客户端上报设备活跃信息,便于后续统计与分析
- 示例
- 无直接示例,可参考响应结构与参数说明
**章节来源**
- [internal/router/router.go:37](file://internal/router/router.go#L37)
- [internal/handler/device.go:26-85](file://internal/handler/device.go#L26-L85)
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
### 分享代码管理
#### 创建分享码 /audio/shareCreate
- 方法与路径
- POST /audio/shareCreate
- 请求头
- Content-Type: application/json
- 请求参数(JSON Body)
- mac: 必填,设备 MAC 地址
- model: 必填,设备型号,取值 Luxsin-X9 或 Luxsin-X8
- eq_data: 必填,EQ 数据(JSON 格式)
- 响应数据
- share_code: 5 位分享码
- expire_at: 过期时间
- eq_data: EQ 数据
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- model 参数无效:code=400,msg="model 参数无效"
- eq_data 格式错误:code=400,msg="eq_data 格式错误"
- 超过最大分享码数量:code=0,msg="已有未过期的分享码,请稍后再试"
- 系统错误:code=500,msg="系统错误"
- 使用场景
- 用户导出自己的 EQ 数据为分享码
- 示例
- curl: `curl -X POST http://localhost:8080/audio/shareCreate -H "Content-Type: application/json" -d '{"mac":"XX:XX:XX:XX:XX:XX","model":"Luxsin-X9","eq_data":{"parametric_eq":[{"band":1,"gain":0.0,"freq":100.0,"q":0.7}]}}'`
#### 查询未过期分享码 /audio/shareList
- 方法与路径
- GET /audio/shareList
- 请求参数
- mac: 必填,设备 MAC 地址
- 响应数据
- share_codes: 分享码列表,每项包含 share_code、expire_at、eq_data
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- 系统错误:code=500,msg="系统错误"
- 使用场景
- 查询某设备尚未过期的所有分享码
- 示例
- curl: `curl "http://localhost:8080/audio/shareList?mac=XX:XX:XX:XX:XX:XX"`
#### 查询分享码(预览)/audio/shareQuery
- 方法与路径
- GET /audio/shareQuery
- 请求参数
- shareCode: 必填,5 位分享码
- 响应数据
- eq_data: EQ 数据
- expire_at: 过期时间
- model: 设备型号
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- 分享码无效或已过期:code=0,msg="分享码无效或已过期"
- 系统错误:code=500,msg="系统错误"
- 使用场景
- 预览他人分享的 EQ 数据,不记录导入
- 示例
- curl: `curl "http://localhost:8080/audio/shareQuery?shareCode=ABCDE"`
#### 导入分享码 /audio/shareAccept
- 方法与路径
- GET /audio/shareAccept
- 请求参数
- mac: 必填,设备 MAC 地址
- model: 必填,设备型号,取值 Luxsin-X9 或 Luxsin-X8
- shareCode: 必填,5 位分享码
- 响应数据
- eq_data: EQ 数据
- model: 设备型号
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- model 参数无效:code=400,msg="model 参数无效"
- 分享码无效或已过期:code=0,msg="分享码无效或已过期"
- 系统错误:code=500,msg="系统错误"
- 使用场景
- 导入他人分享的 EQ 数据
- 示例
- curl: `curl "http://localhost:8080/audio/shareAccept?mac=XX:XX:XX:XX:XX:XX&model=Luxsin-X9&shareCode=ABCDE"`
#### 删除分享码 /audio/shareDelete
- 方法与路径
- GET /audio/shareDelete
- 请求参数
- mac: 必填,设备 MAC 地址
- shareCode: 必填,5 位分享码
- 响应
- 成功:code=200,msg="操作成功"
- 无权删除:code=0,msg="无权删除该分享码"
- 分享码无效或已过期:code=0,msg="分享码无效或已过期"
- 系统错误:code=500,msg="系统错误"
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- 系统错误:code=500,msg="系统错误"
- 使用场景
- 删除自己创建的分享码
- 示例
- curl: `curl "http://localhost:8080/audio/shareDelete?mac=XX:XX:XX:XX:XX:XX&shareCode=ABCDE"`
**章节来源**
- [internal/router/router.go:73-77](file://internal/router/router.go#L73-L77)
- [internal/handler/share_code.go:40-383](file://internal/handler/share_code.go#L40-L383)
- [internal/cache/share_code_cache.go:142-331](file://internal/cache/share_code_cache.go#L142-L331)
- [internal/model/share_code.go:10-12](file://internal/model/share_code.go#L10-L12)
- [internal/config/share_code_ttl.go:15-59](file://internal/config/share_code_ttl.go#L15-L59)
### 等化曲线管理
#### 获取机型默认曲线 /audio/modelCurve
- 方法与路径
- GET /audio/modelCurve
- 请求参数
- brand: 必填,品牌名称
- name: 必填,型号名称
- base64Resp: 可选,是否返回 base64 编码响应
- 响应数据
- fr: 频响曲线数据(fr 字段)
- 错误处理
- 参数校验失败:code=400,msg="参数校验失败"
- 无曲线数据:code=0,msg="无曲线数据"
- 系统错误:code=500,msg="获取曲线数据失败"
- 使用场景
- 获取指定机型的默认频响曲线数据
- 示例
- curl: `curl "http://localhost:8080/audio/modelCurve?brand=Sony&name=WH-1000XM4&base64Resp=true"`
#### 获取目标曲线参数化 EQ /audio/getCurve
- 方法与路径
- GET /audio/getCurve
- 请求参数
- brand: 必填,品牌名称
- name: 必填,型号名称
- target: 必填,目标曲线名称
- base64Resp: 可选,是否返回 base64 编码响应
- 响应数据
- parametric_eq: 参数化 EQ 数据
- 错误处理
- 参数校验失败:code=400,msg="brand、name和target参数不能为空"
- 无曲线数据:code=0,msg="无曲线数据"
- 系统错误:code=500,msg="获取曲线数据失败"
- 使用场景
- 根据机型和目标曲线计算并返回参数化 EQ 数据
- 示例
- curl: `curl "http://localhost:8080/audio/getCurve?brand=Sony&name=WH-1000XM4&target=Harman%20over-ear%202018&base64Resp=true"`
**章节来源**
- [internal/router/router.go:70-71](file://internal/router/router.go#L70-L71)
- [internal/handler/curve.go:56-198](file://internal/handler/curve.go#L56-L198)
- [internal/cache/curve_cache.go:27-148](file://internal/cache/curve_cache.go#L27-L148)
## 依赖关系分析
```mermaid
classDiagram
class Router {
+New(log, db, search, redis, eqCfg, s3, shareMax, shareTTL, env) Engine
}
class HealthHandler
class BrandHandler {
-repo BrandRepository
+GetBrand(c)
}
class ModelHandler {
-repo ModelRepository
+GetModel(c)
}
class ModelListHandler {
-search SearchClient
+ModelList(c)
}
class DeviceHandler {
-redis RedisClient
+ReportDevInfo(c)
}
class ShareCodeHandler {
-cache ShareCodeCache
+ExportShareCode(c)
+ListShareCodesByMac(c)
+QueryShareCode(c)
+ImportShareCode(c)
+DeleteShareCode(c)
}
class CurveHandler {
-repo CurveRepository
-cache CurveCache
+s3 S3Storage
+ModelCurve(c)
+GetCurve(c)
}
class BrandRepository
class ModelRepository
class CurveRepository
class SearchClient
class ShareCodeCache {
+Create(ctx, mac, ip, model, eq) *ShareCodeData
+Get(ctx, code) *ShareCodeData
+ListByMac(ctx, mac) []*ShareCodeData
+Delete(ctx, mac, code) ShareDeleteResult
}
class CurveCache {
+Get(ctx, brand, name, target) string
+Set(ctx, brand, name, target, data) error
+GetFR(ctx, brand, name) string
+GetWithFR(ctx, brand, name, target) string
+AcquireLock(ctx, brand, name, target) bool
+ReleaseLock(ctx, brand, name, target) error
}
class S3Storage {
+GetObject(ctx, key) []byte
}
class Response {
+OK(c, data)
+Fail(c, httpStatus, code, msg)
+BadRequest(c, msg)
+InternalError(c, msg)
}
class Middleware_CORS
class Middleware_Logger
class Middleware_RequestID
class Middleware_CacheControl
Router --> HealthHandler
Router --> BrandHandler
Router --> ModelHandler
Router --> ModelListHandler
Router --> DeviceHandler
Router --> ShareCodeHandler
Router --> CurveHandler
BrandHandler --> BrandRepository
ModelHandler --> ModelRepository
CurveHandler --> CurveRepository
ModelListHandler --> SearchClient
ShareCodeHandler --> ShareCodeCache
CurveHandler --> CurveCache
CurveHandler --> S3Storage
DeviceHandler --> Response
BrandHandler --> Response
ModelHandler --> Response
ModelListHandler --> Response
HealthHandler --> Response
ShareCodeHandler --> Response
CurveHandler --> Response
Router --> Middleware_CORS
Router --> Middleware_Logger
Router --> Middleware_RequestID
Router --> Middleware_CacheControl
```
**图表来源**
- [internal/router/router.go:22-82](file://internal/router/router.go#L22-L82)
- [internal/handler/health.go:8-18](file://internal/handler/health.go#L8-L18)
- [internal/handler/brand.go:14-24](file://internal/handler/brand.go#L14-L24)
- [internal/handler/model.go:14-24](file://internal/handler/model.go#L14-L24)
- [internal/handler/model_list.go:14-24](file://internal/handler/model_list.go#L14-L24)
- [internal/handler/device.go:14-24](file://internal/handler/device.go#L14-L24)
- [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383)
- [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582)
- [internal/repository/brand.go:12-18](file://internal/repository/brand.go#L12-L18)
- [internal/repository/model.go:12-18](file://internal/repository/model.go#L12-L18)
- [internal/repository/curve.go:12-18](file://internal/repository/curve.go#L12-L18)
- [internal/search/meilisearch.go:13-20](file://internal/search/meilisearch.go#L13-L20)
- [internal/cache/share_code_cache.go:128-331](file://internal/cache/share_code_cache.go#L128-L331)
- [internal/cache/curve_cache.go:18-148](file://internal/cache/curve_cache.go#L18-L148)
- [internal/storage/s3.go:15-57](file://internal/storage/s3.go#L15-L57)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
- [internal/middleware/cache_control.go:11-17](file://internal/middleware/cache_control.go#L11-L17)
## 性能与可用性
- 并发与超时
- 服务器设置读/写超时与空闲超时,避免慢请求占用资源。
- 日志与追踪
- 中间件记录状态码、方法、路径、延迟、IP、请求 ID,便于定位问题。
- 缓存与搜索
- 型号检索使用 Meilisearch,具备高性能全文检索能力;设备上报使用 Redis Hash,适合高并发写入。
- **新增**:分享代码管理使用 Redis 复杂数据结构,包括 Hash、ZSET、SET、Lua 脚本,确保原子性和一致性。
- **新增**:等化曲线缓存支持独立存储 fr 数据,避免重复存储,提升缓存命中率和存储效率。
- **新增**:缓存控制中间件为不同接口提供差异化缓存策略,包括品牌/型号列表(300秒)、等化曲线(300秒)和型号检索(30秒)。
- 响应体积控制
- base64Resp 可降低传输体积,但会增加 CPU 开销;建议在带宽受限或协议限制场景启用。
- 存储与集成
- **新增**:S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
- **新增**:等化曲线处理系统支持多种目标曲线的参数化 EQ 计算,具备智能缓存优化和 CSV 数据读取能力。
- 建议
- 对高频接口增加本地缓存(如品牌/型号列表)与 CDN 加速静态资源。
- 对设备上报接口增加幂等与去重策略,避免重复写入。
- **新增**:分享代码接口建议增加速率限制,防止恶意创建大量分享码。
- **新增**:等化曲线接口建议增加缓存预热策略,提升首次访问性能。
- **新增**:S3 存储建议配置合适的超时和重试机制,确保 CSV 读取稳定性。
**章节来源**
- [cmd/server/main.go:66-72](file://cmd/server/main.go#L66-L72)
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
- [internal/search/meilisearch.go:22-46](file://internal/search/meilisearch.go#L22-L46)
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
- [internal/cache/share_code_cache.go:33-353](file://internal/cache/share_code_cache.go#L33-L353)
- [internal/cache/curve_cache.go:18-148](file://internal/cache/curve_cache.go#L18-L148)
- [internal/storage/s3.go:15-57](file://internal/storage/s3.go#L15-L57)
## 故障排查指南
- 健康检查失败
- 检查 /api/v1/health 是否返回 status=up;若失败,查看服务日志与数据库连接状态。
- 品牌/型号接口异常
- 关注数据库连接与查询异常日志;确认 SQL 查询条件与参数传递正确。
- 型号检索失败
- 检查 Meilisearch 连接、索引配置与 API Key;确认关键词与返回字段。
- 设备上报失败
- 检查 Redis 连接与 HSET 写入;确认 mac 与 model 参数必填;关注 JSON 序列化错误。
- 分享代码接口异常
- **新增**:检查 Redis 连接与 Lua 脚本执行;确认分享码长度、字符集与 TTL 设置;验证 MAC 地址索引清理逻辑。
- **新增**:关注分布式锁获取与释放;检查持久化队列处理任务。
- **新增**:验证分享码有效性校验与设备型号限制。
- 等化曲线接口异常
- **新增**:检查 EQ API 调用与响应解析;确认 S3 CSV 读取权限;验证缓存结构与分布式锁。
- **新增**:关注 fr 数据独立存储与合并逻辑。
- **新增**:检查缓存控制中间件的缓存策略是否正确应用。
- 统一错误响应
- 所有错误均通过统一响应体返回,code 非 0 表示失败,message 描述错误原因。
**章节来源**
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
- [internal/handler/brand.go:30-35](file://internal/handler/brand.go#L30-L35)
- [internal/handler/model.go:31-36](file://internal/handler/model.go#L31-L36)
- [internal/handler/model_list.go:37-42](file://internal/handler/model_list.go#L37-L42)
- [internal/handler/device.go:61-78](file://internal/handler/device.go#L61-L78)
- [internal/handler/share_code.go:40-383](file://internal/handler/share_code.go#L40-L383)
- [internal/handler/curve.go:56-582](file://internal/handler/curve.go#L56-L582)
- [internal/response/response.go:23-37](file://internal/response/response.go#L23-L37)
## 结论
本项目采用清晰的分层架构与统一响应体设计,覆盖品牌、型号、检索、设备上报、分享代码管理与等化曲线等核心业务场景。当前未内置鉴权与限流机制,建议在生产环境中补充安全与容量治理措施。通过中间件与日志体系,系统具备良好的可观测性,便于运维与排障。
**新增功能总结**:
- 分享代码管理提供了完整的 EQ 数据分享解决方案,基于 Redis 的高效数据结构和分布式锁保证数据一致性。
- 等化曲线管理支持多种目标曲线的参数化 EQ 计算,具备智能缓存优化和 CSV 数据读取能力。
- S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
- 缓存控制中间件提供针对不同接口的差异化缓存策略,提升系统性能与用户体验。
## 附录
### 端到端调用流程(示例)
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Router as "路由"
participant Handler as "处理器"
participant DBMS as "数据库"
participant Search as "Meilisearch"
participant Cache as "Redis"
participant S3 as "S3存储"
Client->>Router : "GET /audio/getBrand?brandName=sony"
Router->>Handler : "GetBrand"
Handler->>DBMS : "查询品牌列表"
DBMS-->>Handler : "品牌列表"
Handler-->>Router : "统一响应"
Router-->>Client : "JSON/可选base64"
Client->>Router : "GET /audio/modelList?key=wha&count=50"
Router->>Handler : "ModelList"
Handler->>Search : "关键词检索"
Search-->>Handler : "检索结果"
Handler-->>Router : "统一响应"
Router-->>Client : "JSON/可选base64"
Client->>Router : "GET /audio/reportDevInfo?mac=xx&model=yy&ver=v1"
Router->>Handler : "ReportDevInfo"
Handler->>Cache : "HSET devices : mac -> JSON"
Cache-->>Handler : "写入成功"
Handler-->>Router : "统一响应"
Router-->>Client : "JSON"
Client->>Router : "POST /audio/shareCreate"
Router->>Handler : "ExportShareCode"
Handler->>Cache : "Lua脚本创建分享码"
Cache-->>Handler : "原子写入成功"
Handler-->>Router : "统一响应"
Router-->>Client : "JSON"
Client->>Router : "GET /audio/getCurve?brand=Sony&name=WH-1000XM4&target=Harman%20over-ear%202018"
Router->>Handler : "GetCurve"
Handler->>Cache : "检查缓存"
alt 缓存命中
Cache-->>Handler : "parametric_eq数据"
else 缓存未命中
Handler->>S3 : "读取CSV数据"
S3-->>Handler : "测量数据"
Handler->>Handler : "调用EQ API"
Handler->>Cache : "写入缓存"
end
Handler-->>Router : "统一响应"
Router-->>Client : "JSON/可选base64"
```
**图表来源**
- [internal/router/router.go:34-37](file://internal/router/router.go#L34-L37)
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/device.go:26-85](file://internal/handler/device.go#L26-L85)
- [internal/handler/share_code.go:40-125](file://internal/handler/share_code.go#L40-L125)
- [internal/handler/curve.go:56-198](file://internal/handler/curve.go#L56-L198)
- [internal/repository/brand.go:20-51](file://internal/repository/brand.go#L20-L51)
- [internal/search/meilisearch.go:22-46](file://internal/search/meilisearch.go#L22-L46)
- [internal/cache/share_code_cache.go:142-174](file://internal/cache/share_code_cache.go#L142-L174)
- [internal/cache/curve_cache.go:27-102](file://internal/cache/curve_cache.go#L27-L102)
### 配置与部署要点
- 环境变量
- APP_ENV、APP_HOST、APP_PORT、GIN_MODE 等;数据库、Meilisearch、Redis 配置通过独立模块加载。
- **新增**:SHARE_CODE_TTL_MIN 配置分享码有效期,支持分钟、小时、天格式。
- **新增**:SHARE_CODE_MAX_PER_MAC 配置同一 MAC 的最大分享码数量。
- **新增**:S3 配置包括 Bucket、Region、AccessKeyID、SecretAccessKey。
- **新增**:等化曲线配置包括 APIURL 和 ExternalAPIURL。
- 启动与运行
- 支持开发与生产模式;生产模式下 Gin 运行模式切换为 Release。
- 健康检查
- 提供 /api/v1/health 作为探活端点。
- 缓存控制
- **新增**:品牌/型号列表缓存控制:public, max-age=300, s-maxage=1800, stale-while-revalidate=60
- **新增**:等化曲线缓存控制:public, max-age=300, s-maxage=3600, stale-while-revalidate=120
- **新增**:型号检索缓存控制:public, max-age=30, s-maxage=300, stale-while-revalidate=30
**章节来源**
- [internal/config/config.go:18-64](file://internal/config/config.go#L18-L64)
- [cmd/server/main.go:28-30](file://cmd/server/main.go#L28-L30)
- [README.md:89-103](file://README.md#L89-L103)
- [internal/config/share_code_ttl.go:15-59](file://internal/config/share_code_ttl.go#L15-L59)
- [internal/config/s3.go:12-37](file://internal/config/s3.go#L12-L37)
- [internal/config/equalize.go:12-34](file://internal/config/equalize.go#L12-L34)
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
### 分享代码缓存结构说明
```mermaid
graph TB
subgraph "Redis 数据结构"
subgraph "分享码主数据"
KEY1["share:{code}
Hash
TTL = SHARE_CODE_TTL_MIN"]
KEY1 --> FIELD1["mac_addr
创建者 MAC 地址"]
KEY1 --> FIELD2["ip_addr
创建者 IP"]
KEY1 --> FIELD3["model
操作设备型号"]
KEY1 --> FIELD4["eq_data
EQ 参数 JSON"]
KEY1 --> FIELD5["expire_at
过期时间 (RFC3339)"]
KEY1 --> FIELD6["persisted
是否已刷入 DB ('0'/'1')"]
end
subgraph "MAC 索引"
KEY2["share:mac:{mac}
ZSET
TTL = SHARE_CODE_TTL_MIN"]
KEY2 --> MEMBER1["member = share_code"]
KEY2 --> SCORE1["score = expire_at unix timestamp"]
end
subgraph "待持久化队列"
KEY3["share:pending
SET
无 TTL"]
KEY3 --> ITEM1["分享码列表"]
end
subgraph "导入持久化队列"
KEY4["share:import:pending
Hash
TTL 12h"]
KEY4 --> FIELD7["field = {mac}:{code}
幂等: 同 MAC+code 只保留一条"]
KEY4 --> FIELD8["value = JSON payload"]
end
end
```
**图表来源**
- [internal/cache/share_code_cache.go:3-32](file://internal/cache/share_code_cache.go#L3-L32)
### 等化曲线缓存结构说明
```mermaid
graph TB
subgraph "Redis 缓存结构"
subgraph "曲线数据缓存"
KEY1["{brand} {name}
Hash
键格式: 品牌 型号"]
KEY1 --> TARGET1["{target}
目标曲线数据"]
KEY1 --> FR["__fr
独立存储的 fr 数据"]
end
subgraph "分布式锁"
KEY2["{brand} {name}:{target}:lock
String
TTL = 10s"]
end
end
```
**图表来源**
- [internal/cache/curve_cache.go:18-148](file://internal/cache/curve_cache.go#L18-L148)