Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 50s
更新了前端构建产物包括JavaScript、CSS和HTML文件,主要涉及以下变更: 1. 新增了多个组件和工具函数,包括异常页面组件、iframe组件等 2. 更新了活动管理、产品管理、优惠券管理等业务模块 3. 优化了构建配置和依赖管理 4. 修复了一些样式和功能问题 5. 更新了测试相关文件 同时更新了部分后端服务接口和测试用例。这些变更主要是为了支持新功能和改进现有功能的用户体验。
6.0 KiB
6.0 KiB
项目架构对齐
- 后端框架:
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时需至少一个 SKUstock-stock_locked>0 - 响应结构:
{
"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=上架且可售;下架/缺货返回业务态错误码 - 响应结构:
{
"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_countTop N(去重当前商品)
- 优先使用
路由与代码结构
- 路由注册:
internal/router/router.goappAuthGroup := 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避免热点详情击穿
- 本地 TTL 缓存:
- 传输:仅必要字段;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(测试环境数据量下)
- 鉴权与状态校验生效;缓存命中率提升热点访问性能