2026-05-27 18:07:55 +08:00
|
|
|
|
# API 接口文档
|
|
|
|
|
|
|
|
|
|
|
|
<cite>
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**本文档引用的文件**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/handler/share_code.go](file://internal/handler/share_code.go)
|
|
|
|
|
|
- [internal/handler/curve.go](file://internal/handler/curve.go)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go](file://internal/middleware/cache_control.go)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [pkg/encode/base64.go](file://pkg/encode/base64.go)
|
|
|
|
|
|
- [internal/config/config.go](file://internal/config/config.go)
|
|
|
|
|
|
- [README.md](file://README.md)
|
|
|
|
|
|
</cite>
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
1. [简介](#简介)
|
|
|
|
|
|
2. [项目结构](#项目结构)
|
|
|
|
|
|
3. [核心组件](#核心组件)
|
|
|
|
|
|
4. [架构总览](#架构总览)
|
|
|
|
|
|
5. [详细接口说明](#详细接口说明)
|
|
|
|
|
|
6. [依赖关系分析](#依赖关系分析)
|
|
|
|
|
|
7. [性能与可用性](#性能与可用性)
|
|
|
|
|
|
8. [故障排查指南](#故障排查指南)
|
|
|
|
|
|
9. [结论](#结论)
|
|
|
|
|
|
10. [附录](#附录)
|
|
|
|
|
|
|
|
|
|
|
|
## 简介
|
2026-06-22 13:35:37 +08:00
|
|
|
|
本文件为 Luxsin 应用 API 的完整接口文档,覆盖品牌管理、型号管理、设备上报、分享代码管理和等化曲线等接口。文档提供各接口的 HTTP 方法、URL 模式、请求参数、响应格式、错误处理、使用示例与最佳实践,并说明认证方式、速率限制策略、版本信息、客户端实现建议、调试与监控方法,以及向后兼容性与迁移注意事项。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
- 入口程序负责初始化配置、数据库、搜索引擎与缓存,构建路由并启动 HTTP 服务。
|
|
|
|
|
|
- 路由层按版本与业务域分组,注册各处理器。
|
|
|
|
|
|
- 处理器负责参数解析、调用仓储或搜索客户端、返回统一响应格式。
|
|
|
|
|
|
- 统一响应体封装了状态码、消息与数据字段,便于前端一致化处理。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- 中间件提供 CORS、日志、请求 ID 注入与缓存控制,便于跨域、可观测与追踪。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 搜索与缓存分别对接 Meilisearch 与 Redis,支撑型号检索与设备上报数据存储。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- **新增**:分享代码缓存层提供基于 Redis 的高效分享码管理,支持分布式锁与持久化队列。
|
|
|
|
|
|
- **新增**:等化曲线缓存层提供高性能的频响曲线数据缓存,支持独立存储 fr 数据优化。
|
|
|
|
|
|
- **新增**:S3 存储集成支持 CSV 数据读取,为等化曲线处理提供测量数据源。
|
|
|
|
|
|
- **新增**:缓存控制中间件提供针对不同接口的差异化缓存策略。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph TB
|
|
|
|
|
|
subgraph "服务进程"
|
|
|
|
|
|
MAIN["cmd/server/main.go<br/>启动与生命周期"]
|
|
|
|
|
|
ROUTER["internal/router/router.go<br/>路由注册"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "HTTP 层"
|
|
|
|
|
|
CORS["internal/middleware/cors.go<br/>CORS"]
|
|
|
|
|
|
LOGMW["internal/middleware/logger.go<br/>访问日志"]
|
|
|
|
|
|
RID["internal/middleware/request_id.go<br/>请求ID注入"]
|
2026-06-22 13:35:37 +08:00
|
|
|
|
CACHECTRL["internal/middleware/cache_control.go<br/>缓存控制"]
|
2026-05-27 18:07:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
subgraph "业务层"
|
|
|
|
|
|
HEALTH["internal/handler/health.go<br/>健康检查"]
|
|
|
|
|
|
BRAND["internal/handler/brand.go<br/>品牌列表"]
|
|
|
|
|
|
MODEL["internal/handler/model.go<br/>型号详情"]
|
|
|
|
|
|
MODELLIST["internal/handler/model_list.go<br/>型号检索"]
|
|
|
|
|
|
DEVICE["internal/handler/device.go<br/>设备上报"]
|
2026-06-22 13:35:37 +08:00
|
|
|
|
SHARECODE["internal/handler/share_code.go<br/>分享代码管理"]
|
|
|
|
|
|
CURVE["internal/handler/curve.go<br/>等化曲线"]
|
2026-05-27 18:07:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
subgraph "数据与外部服务"
|
|
|
|
|
|
RESP["internal/response/response.go<br/>统一响应"]
|
|
|
|
|
|
DB["MySQL(由配置驱动)"]
|
|
|
|
|
|
MS["Meilisearch(由配置驱动)"]
|
|
|
|
|
|
REDIS["Redis(由配置驱动)"]
|
2026-06-22 13:35:37 +08:00
|
|
|
|
S3["S3存储(由配置驱动)"]
|
2026-05-27 18:07:55 +08:00
|
|
|
|
end
|
|
|
|
|
|
MAIN --> ROUTER
|
2026-06-22 13:35:37 +08:00
|
|
|
|
ROUTER --> CORS --> LOGMW --> RID --> CACHECTRL
|
2026-05-27 18:07:55 +08:00
|
|
|
|
ROUTER --> HEALTH
|
|
|
|
|
|
ROUTER --> BRAND
|
|
|
|
|
|
ROUTER --> MODEL
|
|
|
|
|
|
ROUTER --> MODELLIST
|
|
|
|
|
|
ROUTER --> DEVICE
|
2026-06-22 13:35:37 +08:00
|
|
|
|
ROUTER --> SHARECODE
|
|
|
|
|
|
ROUTER --> CURVE
|
2026-05-27 18:07:55 +08:00
|
|
|
|
BRAND --> DB
|
|
|
|
|
|
MODEL --> DB
|
|
|
|
|
|
MODELLIST --> MS
|
|
|
|
|
|
DEVICE --> REDIS
|
2026-06-22 13:35:37 +08:00
|
|
|
|
SHARECODE --> REDIS
|
|
|
|
|
|
CURVE --> DB
|
|
|
|
|
|
CURVE --> S3
|
|
|
|
|
|
CURVE --> REDIS
|
2026-05-27 18:07:55 +08:00
|
|
|
|
HEALTH --> RESP
|
|
|
|
|
|
BRAND --> RESP
|
|
|
|
|
|
MODEL --> RESP
|
|
|
|
|
|
MODELLIST --> RESP
|
|
|
|
|
|
DEVICE --> RESP
|
2026-06-22 13:35:37 +08:00
|
|
|
|
SHARECODE --> RESP
|
|
|
|
|
|
CURVE --> RESP
|
2026-05-27 18:07:55 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**图表来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
|
|
|
|
|
|
- [README.md:1-127](file://README.md#L1-L127)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 核心组件
|
|
|
|
|
|
- 路由与中间件
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- 路由在 /api/v1 下提供健康检查,在 /audio 下提供品牌、型号、型号检索、设备上报、分享代码管理与等化曲线接口。
|
|
|
|
|
|
- 中间件链:恢复、请求 ID、日志、CORS、缓存控制。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 统一响应
|
|
|
|
|
|
- 所有接口返回统一结构,包含 code、message、data 字段;错误时 code 为非零。
|
|
|
|
|
|
- 搜索与缓存
|
|
|
|
|
|
- 型号检索通过 Meilisearch 客户端完成;设备上报通过 Redis Hash 存储。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- **新增**:分享代码管理通过 Redis 实现高效的数据结构,包括主数据、MAC 索引、待持久化队列等。
|
|
|
|
|
|
- **新增**:等化曲线缓存支持独立存储 fr 数据,避免重复存储,提升缓存效率。
|
|
|
|
|
|
- **新增**:缓存控制中间件为不同接口提供差异化缓存策略,包括品牌/型号列表、等化曲线和型号检索。
|
|
|
|
|
|
- 存储与集成
|
|
|
|
|
|
- **新增**:S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
|
|
|
|
|
|
- **新增**:等化曲线处理系统支持多种目标曲线的参数化 EQ 计算。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 编码扩展
|
|
|
|
|
|
- 支持 base64Resp 参数,将响应体 JSON 再做自定义 Base64 编码传输,便于某些网络环境或协议需求。
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
|
|
|
|
|
- [internal/router/router.go:14-82](file://internal/router/router.go#L14-L82)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
|
|
|
|
|
以下序列图展示一次典型请求从接入到响应的全链路:
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant C as "客户端"
|
|
|
|
|
|
participant G as "Gin 路由"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
participant MW as "中间件(CORS/日志/请求ID/缓存控制)"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
participant H as "处理器"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
participant S as "搜索/缓存/数据库/S3"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
C->>G : "HTTP 请求"
|
|
|
|
|
|
G->>MW : "中间件链"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
MW-->>G : "注入请求ID/日志/CORS/缓存控制"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
G->>H : "匹配路由并调用处理器"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
H->>S : "读取/写入(数据库/搜索/缓存/S3)"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
S-->>H : "结果/错误"
|
|
|
|
|
|
H-->>G : "统一响应体"
|
|
|
|
|
|
G-->>C : "HTTP 响应(JSON/可选base64)"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**图表来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go:11-17](file://internal/middleware/cache_control.go#L11-L17)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
|
|
|
|
|
|
|
|
|
|
|
|
## 详细接口说明
|
|
|
|
|
|
|
|
|
|
|
|
### 版本与基础信息
|
|
|
|
|
|
- 版本分组
|
|
|
|
|
|
- /api/v1:健康检查
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- /audio:品牌、型号、型号检索、设备上报、分享代码管理、等化曲线
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 认证方式
|
|
|
|
|
|
- 当前实现未内置鉴权逻辑,未发现显式的 Token/签名/密钥校验流程。
|
|
|
|
|
|
- 速率限制
|
|
|
|
|
|
- 当前实现未内置全局限流策略,如需请结合网关或中间件扩展。
|
|
|
|
|
|
- 基础响应结构
|
|
|
|
|
|
- 成功:code=0,message="ok",data 为业务数据
|
|
|
|
|
|
- 失败:code 非 0,message 为错误描述
|
|
|
|
|
|
- base64Resp
|
|
|
|
|
|
- 可选查询参数 base64Resp=true|1|空 时,将响应体 JSON 再进行自定义 Base64 编码返回;默认开启。
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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"
|
|
|
|
|
|
- 错误处理
|
|
|
|
|
|
- 无内部错误路径,始终返回成功
|
|
|
|
|
|
- 使用场景
|
|
|
|
|
|
- 服务存活探测、负载均衡探活
|
|
|
|
|
|
- 示例
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- curl: [README.md:89-103](file://README.md#L89-L103)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [internal/router/router.go:29](file://internal/router/router.go#L29)
|
|
|
|
|
|
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [README.md:89-103](file://README.md#L89-L103)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
### 品牌管理 /audio/getBrand
|
|
|
|
|
|
- 方法与路径
|
|
|
|
|
|
- GET /audio/getBrand
|
|
|
|
|
|
- 请求参数
|
|
|
|
|
|
- brandName: 可选,用于模糊过滤品牌名称
|
|
|
|
|
|
- base64Resp: 可选,是否对响应体进行二次 Base64 编码
|
|
|
|
|
|
- 响应数据
|
|
|
|
|
|
- 列表项包含品牌 id 与 name
|
|
|
|
|
|
- 错误处理
|
|
|
|
|
|
- 数据库查询异常:统一返回内部错误
|
|
|
|
|
|
- 编码异常:统一返回内部错误
|
|
|
|
|
|
- 使用场景
|
|
|
|
|
|
- 获取品牌列表,支持按名称模糊筛选
|
|
|
|
|
|
- 示例
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- curl: [README.md:107-113](file://README.md#L107-L113)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [README.md:107-113](file://README.md#L107-L113)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
### 型号管理 /audio/getModel
|
|
|
|
|
|
- 方法与路径
|
|
|
|
|
|
- GET /audio/getModel
|
|
|
|
|
|
- 请求参数
|
|
|
|
|
|
- brandName: 可选,按品牌过滤
|
|
|
|
|
|
- modelName: 可选,按型号名称模糊过滤
|
|
|
|
|
|
- base64Resp: 可选,是否对响应体进行二次 Base64 编码
|
|
|
|
|
|
- 响应数据
|
|
|
|
|
|
- 列表项包含 id、brand_name、name、form、rig、source、eq_key、create_at;部分字段可能为空
|
|
|
|
|
|
- 错误处理
|
|
|
|
|
|
- 数据库查询异常:统一返回内部错误
|
|
|
|
|
|
- 编码异常:统一返回内部错误
|
|
|
|
|
|
- 使用场景
|
|
|
|
|
|
- 获取指定品牌或型号的详细列表
|
|
|
|
|
|
- 示例
|
|
|
|
|
|
- 无直接示例,但可通过组合 brandName 与 modelName 参数实现不同维度查询
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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 的检索行为
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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 写入失败:返回内部错误
|
|
|
|
|
|
- 使用场景
|
|
|
|
|
|
- 客户端上报设备活跃信息,便于后续统计与分析
|
|
|
|
|
|
- 示例
|
|
|
|
|
|
- 无直接示例,可参考响应结构与参数说明
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
### 分享代码管理
|
|
|
|
|
|
|
|
|
|
|
|
#### 创建分享码 /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)
|
|
|
|
|
|
|
2026-05-27 18:07:55 +08:00
|
|
|
|
## 依赖关系分析
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
classDiagram
|
|
|
|
|
|
class Router {
|
2026-06-22 13:35:37 +08:00
|
|
|
|
+New(log, db, search, redis, eqCfg, s3, shareMax, shareTTL, env) Engine
|
2026-05-27 18:07:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
|
}
|
2026-06-22 13:35:37 +08:00
|
|
|
|
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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
}
|
2026-06-22 13:35:37 +08:00
|
|
|
|
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
|
2026-05-27 18:07:55 +08:00
|
|
|
|
}
|
2026-06-22 13:35:37 +08:00
|
|
|
|
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
|
2026-05-27 18:07:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
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
|
2026-06-22 13:35:37 +08:00
|
|
|
|
class Middleware_CacheControl
|
2026-05-27 18:07:55 +08:00
|
|
|
|
Router --> HealthHandler
|
|
|
|
|
|
Router --> BrandHandler
|
|
|
|
|
|
Router --> ModelHandler
|
|
|
|
|
|
Router --> ModelListHandler
|
|
|
|
|
|
Router --> DeviceHandler
|
2026-06-22 13:35:37 +08:00
|
|
|
|
Router --> ShareCodeHandler
|
|
|
|
|
|
Router --> CurveHandler
|
2026-05-27 18:07:55 +08:00
|
|
|
|
BrandHandler --> BrandRepository
|
|
|
|
|
|
ModelHandler --> ModelRepository
|
2026-06-22 13:35:37 +08:00
|
|
|
|
CurveHandler --> CurveRepository
|
2026-05-27 18:07:55 +08:00
|
|
|
|
ModelListHandler --> SearchClient
|
2026-06-22 13:35:37 +08:00
|
|
|
|
ShareCodeHandler --> ShareCodeCache
|
|
|
|
|
|
CurveHandler --> CurveCache
|
|
|
|
|
|
CurveHandler --> S3Storage
|
2026-05-27 18:07:55 +08:00
|
|
|
|
DeviceHandler --> Response
|
|
|
|
|
|
BrandHandler --> Response
|
|
|
|
|
|
ModelHandler --> Response
|
|
|
|
|
|
ModelListHandler --> Response
|
|
|
|
|
|
HealthHandler --> Response
|
2026-06-22 13:35:37 +08:00
|
|
|
|
ShareCodeHandler --> Response
|
|
|
|
|
|
CurveHandler --> Response
|
2026-05-27 18:07:55 +08:00
|
|
|
|
Router --> Middleware_CORS
|
|
|
|
|
|
Router --> Middleware_Logger
|
|
|
|
|
|
Router --> Middleware_RequestID
|
2026-06-22 13:35:37 +08:00
|
|
|
|
Router --> Middleware_CacheControl
|
2026-05-27 18:07:55 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**图表来源**
|
|
|
|
|
|
- [internal/router/router.go:22-82](file://internal/router/router.go#L22-L82)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/repository/curve.go:12-18](file://internal/repository/curve.go#L12-L18)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [internal/search/meilisearch.go:13-20](file://internal/search/meilisearch.go#L13-L20)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go:11-17](file://internal/middleware/cache_control.go#L11-L17)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 性能与可用性
|
|
|
|
|
|
- 并发与超时
|
|
|
|
|
|
- 服务器设置读/写超时与空闲超时,避免慢请求占用资源。
|
|
|
|
|
|
- 日志与追踪
|
|
|
|
|
|
- 中间件记录状态码、方法、路径、延迟、IP、请求 ID,便于定位问题。
|
|
|
|
|
|
- 缓存与搜索
|
|
|
|
|
|
- 型号检索使用 Meilisearch,具备高性能全文检索能力;设备上报使用 Redis Hash,适合高并发写入。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- **新增**:分享代码管理使用 Redis 复杂数据结构,包括 Hash、ZSET、SET、Lua 脚本,确保原子性和一致性。
|
|
|
|
|
|
- **新增**:等化曲线缓存支持独立存储 fr 数据,避免重复存储,提升缓存命中率和存储效率。
|
|
|
|
|
|
- **新增**:缓存控制中间件为不同接口提供差异化缓存策略,包括品牌/型号列表(300秒)、等化曲线(300秒)和型号检索(30秒)。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 响应体积控制
|
|
|
|
|
|
- base64Resp 可降低传输体积,但会增加 CPU 开销;建议在带宽受限或协议限制场景启用。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- 存储与集成
|
|
|
|
|
|
- **新增**:S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
|
|
|
|
|
|
- **新增**:等化曲线处理系统支持多种目标曲线的参数化 EQ 计算,具备智能缓存优化和 CSV 数据读取能力。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 建议
|
|
|
|
|
|
- 对高频接口增加本地缓存(如品牌/型号列表)与 CDN 加速静态资源。
|
|
|
|
|
|
- 对设备上报接口增加幂等与去重策略,避免重复写入。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- **新增**:分享代码接口建议增加速率限制,防止恶意创建大量分享码。
|
|
|
|
|
|
- **新增**:等化曲线接口建议增加缓存预热策略,提升首次访问性能。
|
|
|
|
|
|
- **新增**:S3 存储建议配置合适的超时和重试机制,确保 CSV 读取稳定性。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [internal/middleware/cache_control.go:5-19](file://internal/middleware/cache_control.go#L5-L19)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 故障排查指南
|
|
|
|
|
|
- 健康检查失败
|
|
|
|
|
|
- 检查 /api/v1/health 是否返回 status=up;若失败,查看服务日志与数据库连接状态。
|
|
|
|
|
|
- 品牌/型号接口异常
|
|
|
|
|
|
- 关注数据库连接与查询异常日志;确认 SQL 查询条件与参数传递正确。
|
|
|
|
|
|
- 型号检索失败
|
|
|
|
|
|
- 检查 Meilisearch 连接、索引配置与 API Key;确认关键词与返回字段。
|
|
|
|
|
|
- 设备上报失败
|
|
|
|
|
|
- 检查 Redis 连接与 HSET 写入;确认 mac 与 model 参数必填;关注 JSON 序列化错误。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- 分享代码接口异常
|
|
|
|
|
|
- **新增**:检查 Redis 连接与 Lua 脚本执行;确认分享码长度、字符集与 TTL 设置;验证 MAC 地址索引清理逻辑。
|
|
|
|
|
|
- **新增**:关注分布式锁获取与释放;检查持久化队列处理任务。
|
|
|
|
|
|
- **新增**:验证分享码有效性校验与设备型号限制。
|
|
|
|
|
|
- 等化曲线接口异常
|
|
|
|
|
|
- **新增**:检查 EQ API 调用与响应解析;确认 S3 CSV 读取权限;验证缓存结构与分布式锁。
|
|
|
|
|
|
- **新增**:关注 fr 数据独立存储与合并逻辑。
|
|
|
|
|
|
- **新增**:检查缓存控制中间件的缓存策略是否正确应用。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 统一错误响应
|
|
|
|
|
|
- 所有错误均通过统一响应体返回,code 非 0 表示失败,message 描述错误原因。
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [internal/response/response.go:23-37](file://internal/response/response.go#L23-L37)
|
|
|
|
|
|
|
|
|
|
|
|
## 结论
|
2026-06-22 13:35:37 +08:00
|
|
|
|
本项目采用清晰的分层架构与统一响应体设计,覆盖品牌、型号、检索、设备上报、分享代码管理与等化曲线等核心业务场景。当前未内置鉴权与限流机制,建议在生产环境中补充安全与容量治理措施。通过中间件与日志体系,系统具备良好的可观测性,便于运维与排障。
|
|
|
|
|
|
|
|
|
|
|
|
**新增功能总结**:
|
|
|
|
|
|
- 分享代码管理提供了完整的 EQ 数据分享解决方案,基于 Redis 的高效数据结构和分布式锁保证数据一致性。
|
|
|
|
|
|
- 等化曲线管理支持多种目标曲线的参数化 EQ 计算,具备智能缓存优化和 CSV 数据读取能力。
|
|
|
|
|
|
- S3 存储集成支持 CSV 数据读取,为 Eafonyoung 源的等化曲线处理提供测量数据。
|
|
|
|
|
|
- 缓存控制中间件提供针对不同接口的差异化缓存策略,提升系统性能与用户体验。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
## 附录
|
|
|
|
|
|
|
|
|
|
|
|
### 端到端调用流程(示例)
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant Client as "客户端"
|
|
|
|
|
|
participant Router as "路由"
|
|
|
|
|
|
participant Handler as "处理器"
|
|
|
|
|
|
participant DBMS as "数据库"
|
|
|
|
|
|
participant Search as "Meilisearch"
|
|
|
|
|
|
participant Cache as "Redis"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
participant S3 as "S3存储"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
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"
|
2026-06-22 13:35:37 +08:00
|
|
|
|
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"
|
2026-05-27 18:07:55 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**图表来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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)
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
|
|
|
|
|
### 配置与部署要点
|
|
|
|
|
|
- 环境变量
|
|
|
|
|
|
- APP_ENV、APP_HOST、APP_PORT、GIN_MODE 等;数据库、Meilisearch、Redis 配置通过独立模块加载。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- **新增**:SHARE_CODE_TTL_MIN 配置分享码有效期,支持分钟、小时、天格式。
|
|
|
|
|
|
- **新增**:SHARE_CODE_MAX_PER_MAC 配置同一 MAC 的最大分享码数量。
|
|
|
|
|
|
- **新增**:S3 配置包括 Bucket、Region、AccessKeyID、SecretAccessKey。
|
|
|
|
|
|
- **新增**:等化曲线配置包括 APIURL 和 ExternalAPIURL。
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- 启动与运行
|
|
|
|
|
|
- 支持开发与生产模式;生产模式下 Gin 运行模式切换为 Release。
|
|
|
|
|
|
- 健康检查
|
|
|
|
|
|
- 提供 /api/v1/health 作为探活端点。
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- 缓存控制
|
|
|
|
|
|
- **新增**:品牌/型号列表缓存控制: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
|
2026-05-27 18:07:55 +08:00
|
|
|
|
|
2026-06-22 13:35:37 +08:00
|
|
|
|
**章节来源**
|
2026-05-27 18:07:55 +08:00
|
|
|
|
- [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)
|
2026-06-22 13:35:37 +08:00
|
|
|
|
- [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}<br/>Hash<br/>TTL = SHARE_CODE_TTL_MIN"]
|
|
|
|
|
|
KEY1 --> FIELD1["mac_addr<br/>创建者 MAC 地址"]
|
|
|
|
|
|
KEY1 --> FIELD2["ip_addr<br/>创建者 IP"]
|
|
|
|
|
|
KEY1 --> FIELD3["model<br/>操作设备型号"]
|
|
|
|
|
|
KEY1 --> FIELD4["eq_data<br/>EQ 参数 JSON"]
|
|
|
|
|
|
KEY1 --> FIELD5["expire_at<br/>过期时间 (RFC3339)"]
|
|
|
|
|
|
KEY1 --> FIELD6["persisted<br/>是否已刷入 DB ('0'/'1')"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "MAC 索引"
|
|
|
|
|
|
KEY2["share:mac:{mac}<br/>ZSET<br/>TTL = SHARE_CODE_TTL_MIN"]
|
|
|
|
|
|
KEY2 --> MEMBER1["member = share_code"]
|
|
|
|
|
|
KEY2 --> SCORE1["score = expire_at unix timestamp"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "待持久化队列"
|
|
|
|
|
|
KEY3["share:pending<br/>SET<br/>无 TTL"]
|
|
|
|
|
|
KEY3 --> ITEM1["分享码列表"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "导入持久化队列"
|
|
|
|
|
|
KEY4["share:import:pending<br/>Hash<br/>TTL 12h"]
|
|
|
|
|
|
KEY4 --> FIELD7["field = {mac}:{code}<br/>幂等: 同 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}<br/>Hash<br/>键格式: 品牌 型号"]
|
|
|
|
|
|
KEY1 --> TARGET1["{target}<br/>目标曲线数据"]
|
|
|
|
|
|
KEY1 --> FR["__fr<br/>独立存储的 fr 数据"]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph "分布式锁"
|
|
|
|
|
|
KEY2["{brand} {name}:{target}:lock<br/>String<br/>TTL = 10s"]
|
|
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**图表来源**
|
|
|
|
|
|
- [internal/cache/curve_cache.go:18-148](file://internal/cache/curve_cache.go#L18-L148)
|