Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 50s
更新了前端构建产物包括JavaScript、CSS和HTML文件,主要涉及以下变更: 1. 新增了多个组件和工具函数,包括异常页面组件、iframe组件等 2. 更新了活动管理、产品管理、优惠券管理等业务模块 3. 优化了构建配置和依赖管理 4. 修复了一些样式和功能问题 5. 更新了测试相关文件 同时更新了部分后端服务接口和测试用例。这些变更主要是为了支持新功能和改进现有功能的用户体验。
143 lines
6.0 KiB
Markdown
143 lines
6.0 KiB
Markdown
## 项目架构对齐
|
||
- 后端框架:`gin`(`internal/pkg/core`),统一中间件与响应封装
|
||
- 路由分组:`internal/router/router.go` 下 APP 公开/鉴权分组可扩展 `products` 资源
|
||
- 鉴权:APP 端采用 `core.WrapAuthHandler(intc.AppTokenAuthVerify)`,`Authorization: Bearer <token>`
|
||
- ORM/DB:`gorm` + `gorm/gen`(`internal/repository/mysql/dao/Query`),读写分离 `GetDbR/GetDbW`
|
||
- Swagger:通过注释生成(`swaggo/swag`),挂载 `GET /swagger/*any`
|
||
- 商品相关模型:`product`(SPU)、`sku`、`category`、`spec`、`spec_option`、`product_spec`、`sku_spec_value`、推荐位 `recommendation_slot/item`
|
||
|
||
## 接口设计
|
||
### 1) 商品列表
|
||
- 路径:`GET /api/app/products`
|
||
- 鉴权:需要(App Token)
|
||
- 请求参数:
|
||
- `page`(默认1)`pageSize`(默认20,最大50)
|
||
- `categoryId`(可选)
|
||
- `priceMin`、`priceMax`(可选,闭区间)
|
||
- `salesMin`(可选)
|
||
- `inStock`(布尔,可选,默认true,仅展示可售)
|
||
- `sortBy`(`sales|price|createdAt`)`order`(`asc|desc`,默认 `desc`)
|
||
- 业务规则:只返回 `status=上架` 的 SPU;`inStock=true` 时需至少一个 SKU `stock-stock_locked>0`
|
||
- 响应结构:
|
||
```json
|
||
{
|
||
"total": 1234,
|
||
"currentPage": 1,
|
||
"pageSize": 20,
|
||
"list": [
|
||
{
|
||
"id": 1001,
|
||
"name": "羽绒服",
|
||
"mainImage": "https://.../xx.jpg",
|
||
"price": 299.00,
|
||
"sales": 5230,
|
||
"inStock": true,
|
||
"categoryId": 12
|
||
}
|
||
]
|
||
}
|
||
```
|
||
- 过滤/排序实现:
|
||
- 基于 `product` 表 `status/category_id/sales_count/created_at/price_min/price_max` 组合条件
|
||
- `inStock` 通过子查询/EXISTS 关联 `sku` 计算有效库存
|
||
|
||
### 2) 商品详情
|
||
- 路径:`GET /api/app/products/:id`
|
||
- 鉴权:需要(App Token)
|
||
- 业务规则:SPU `status=上架` 且可售;下架/缺货返回业务态错误码
|
||
- 响应结构:
|
||
```json
|
||
{
|
||
"id": 1001,
|
||
"name": "羽绒服",
|
||
"album": ["https://.../1.jpg", "https://.../2.jpg"],
|
||
"priceRange": {"min": 199.00, "max": 399.00},
|
||
"sales": 5230,
|
||
"stock": {"total": 235, "available": 220},
|
||
"specs": [
|
||
{"name": "颜色", "options": ["黑色", "白色"]},
|
||
{"name": "尺码", "options": ["M", "L", "XL"]}
|
||
],
|
||
"description": "高蓬松保暖...",
|
||
"service": ["7天无理由", "运费险"],
|
||
"recommendations": [
|
||
{"id": 1002, "name": "羽绒马甲", "mainImage": "...", "price": 199.00}
|
||
]
|
||
}
|
||
```
|
||
- 规格/相册/描述来源:
|
||
- 相册:`product.images_json` 或关联表(若存在),解析为数组
|
||
- 规格:`product_spec` + `spec` + `spec_option` 聚合;
|
||
- 描述/服务保障:从 `product` 富文本字段(或扩展表)读取
|
||
- 推荐逻辑:
|
||
- 优先使用 `recommendation_slot.scene='detail_related'` 的绑定数据
|
||
- 兜底:同类目类目内 `sales_count` Top N(去重当前商品)
|
||
|
||
## 路由与代码结构
|
||
- 路由注册:`internal/router/router.go`
|
||
- `appAuthGroup := router.Group("/api/app", core.WrapAuthHandler(intc.AppTokenAuthVerify))`
|
||
- `appAuthGroup.GET("/products", product.New(repo, logger).List)`
|
||
- `appAuthGroup.GET("/products/:id", product.New(repo, logger).Detail)`
|
||
- Handler:`internal/api/product/list_app.go`、`internal/api/product/detail_app.go`
|
||
- 统一入参校验、容错与错误码
|
||
- Service:`internal/service/product/service.go`
|
||
- 封装查询、库存计算、推荐聚合、缓存命中
|
||
- DAO查询:使用 `dao.Query` 与 `GetDbR`
|
||
- DTO:`internal/api/product/dto.go`(列表项与详情结构体)
|
||
|
||
## 鉴权与权限
|
||
- 使用现有 APP Token 验证中间件;Swagger `@Security LoginVerifyToken`
|
||
- 接口动作无需RBAC(面向APP用户),但保留限流与风控扩展点
|
||
|
||
## 性能与优化(500ms SLA)
|
||
- 索引:
|
||
- `product(status, category_id, sales_count, created_at)` 复合索引
|
||
- `sku(product_id, status)`、`sku(stock, stock_locked)` 参与计算库存
|
||
- 查询:
|
||
- 列表:单次查询 + `EXISTS` 子查询校验库存;分页使用 `LIMIT/OFFSET`(页码≤100)
|
||
- 详情:读取 SPU + 聚合 `SUM(stock-stock_locked)` + 规格与相册多表查询
|
||
- 缓存:
|
||
- 本地 TTL 缓存:
|
||
- 列表:键 `list:{filters}:{page}:{pageSize}`,TTL 30s,命中后直接返回
|
||
- 详情:键 `detail:{id}`,TTL 60s;库存变更事件可主动失效(后续扩展)
|
||
- 并发合并:使用 `singleflight` 避免热点详情击穿
|
||
- 传输:仅必要字段;GZIP 已由中间件统一处理
|
||
- 限流:`/products` 每用户每秒 ≤10(后续中间件实现,可选)
|
||
|
||
## 错误码与校验
|
||
- 下架:`PRODUCT_OFFSHELF`(HTTP 200,业务码),提示“商品已下架”
|
||
- 缺货:`PRODUCT_OUT_OF_STOCK`
|
||
- 参数错误:`INVALID_PARAM`(页码、价格区间校验)
|
||
- 统一响应封装沿用 `internal/pkg/core/context.go`
|
||
|
||
## Swagger文档
|
||
- 在两个 Handler 顶部添加注释:
|
||
- `@Summary`、`@Description`、`@Tags products`
|
||
- `@Param`(列出查询参数与类型)
|
||
- `@Success 200 {object} ListResp` / `DetailResp`
|
||
- `@Router /api/app/products [get]`、`/api/app/products/{id} [get]`
|
||
- `@Security LoginVerifyToken`
|
||
- 生成后可在 `http://127.0.0.1:9991/swagger/index.html` 查看
|
||
|
||
## 单元测试
|
||
- Handler:`httptest.NewServer` + 构造 `Authorization` 头,校验分页与过滤、错误码
|
||
- Service:使用内存/模拟 DAO(或事务性测试库)覆盖:库存计算、规格聚合、推荐兜底
|
||
- 覆盖率目标:核心逻辑 ≥70%
|
||
|
||
## 压力测试
|
||
- 工具:`hey` 或 `wrk`
|
||
- 示例:
|
||
- 列表:`hey -n 5000 -c 100 'http://localhost:9991/api/app/products?page=1&pageSize=20'`
|
||
- 详情:`wrk -t4 -c200 -d30s 'http://localhost:9991/api/app/products/1001'`
|
||
- 目标:P95 ≤ 500ms,错误率 < 0.1%
|
||
|
||
## 联调与交付
|
||
- 与前端约定字段与筛选参数;提供响应示例与错误码表
|
||
- 提供 Swagger 文档与可复用的 Postman/HTTP 文件
|
||
- 完成线上/测试环境联调回归
|
||
|
||
## 验收标准
|
||
- 两个接口完成并通过单元与压力测试
|
||
- Swagger 文档完整,含请求/响应示例
|
||
- P95 响应时间 ≤ 500ms(测试环境数据量下)
|
||
- 鉴权与状态校验生效;缓存命中率提升热点访问性能 |