HaniBlindBox/docs/API迁移详细文档/阶段4-商品系统.md
2026-01-02 15:46:56 +08:00

730 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 阶段4商品系统
## 阶段概述
**时间**: 3周
**目标**: 实现完整的商品管理系统,包括商品列表、详情、分类、库存管理、收藏等功能
**优先级**: P1 (高优先级)
## 详细任务清单
### 4.1 商品基础数据模型 (3天)
#### 任务描述
设计和实现商品相关的数据模型和基础服务
#### 具体工作
- [ ] 设计商品主表数据模型
- [ ] 设计商品列表(奖品)数据模型
- [ ] 设计商品分类数据模型
- [ ] 设计商品扩展配置模型
- [ ] 实现基础的商品服务接口
#### 数据模型设计
```csharp
// 商品主表
public class Goods
{
public int Id { get; set; }
public string Title { get; set; }
public string ImgUrl { get; set; }
public string ImgUrlDetail { get; set; }
public decimal Price { get; set; }
public int Type { get; set; }
public int Stock { get; set; }
public int SaleStock { get; set; }
public int Status { get; set; }
public int LockIs { get; set; }
public int IsShouZhe { get; set; }
public int NewIs { get; set; }
public decimal UnlockAmount { get; set; }
public int QuanjuXiangou { get; set; }
public int DailyXiangou { get; set; }
public DateTime? SaleTime { get; set; }
public int Sort { get; set; }
public DateTime AddTime { get; set; }
}
// 商品奖品列表
public class GoodsList
{
public int Id { get; set; }
public int GoodsId { get; set; }
public int Num { get; set; }
public int ShangId { get; set; }
public string Title { get; set; }
public int Stock { get; set; }
public int SurplusStock { get; set; }
public string ImgUrl { get; set; }
public int GoodsType { get; set; }
public decimal Price { get; set; }
public decimal ScMoney { get; set; }
public decimal RealPro { get; set; }
public int GoodsListId { get; set; }
public DateTime? SaleTime { get; set; }
public int Sort { get; set; }
}
// 商品类型配置
public class GoodsType
{
public int Id { get; set; }
public int Value { get; set; }
public string CornerText { get; set; }
public int PayWechat { get; set; }
public int PayBalance { get; set; }
public int PayCurrency { get; set; }
public int PayCurrency2 { get; set; }
public int PayCoupon { get; set; }
public int IsDeduction { get; set; }
}
// 商品扩展配置
public class GoodsExtend
{
public int Id { get; set; }
public int GoodsId { get; set; }
public int PayWechat { get; set; }
public int PayBalance { get; set; }
public int PayCurrency { get; set; }
public int PayCurrency2 { get; set; }
public int PayCoupon { get; set; }
public int IsDeduction { get; set; }
}
```
### 4.2 商品列表查询 (4天)
#### 任务描述
实现商品列表查询功能,支持分类筛选、分页、缓存等
#### 具体工作
- [ ] 实现商品列表查询接口
- [ ] 实现分类筛选功能
- [ ] 实现商品状态过滤
- [ ] 添加Redis缓存机制
- [ ] 实现参与次数统计
#### 核心接口实现
##### 商品列表接口
```http
GET /api/v1/goods
Authorization: Bearer {token}
Query Parameters:
- type: 商品类型 (-1=全部, 1=一番赏, 2=无限赏, 3=擂台赏, 5=积分赏, 6=全局赏, 7=福利盲盒, 8=领主赏, 9=连击赏, 10=商品赏, 11=其他, 12=其他, 15=其他, 16=其他)
- page: 页码默认1
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"data": [
{
"id": 123,
"title": "商品标题",
"imgurl": "https://example.com/goods.jpg",
"price": "10.00",
"type": 1,
"type_text": "一番赏",
"stock": 100,
"sale_stock": 80,
"status": 1,
"lock_is": 0,
"is_shou_zhe": 0,
"new_is": 1,
"join_count": 150,
"need_draw_num": 0
}
],
"last_page": 5
}
}
```
#### 技术实现要点
```csharp
// 商品服务接口
public interface IGoodsService
{
Task<PagedResult<GoodsListDto>> GetGoodsListAsync(GoodsQueryDto query, int userId);
Task<GoodsDetailDto> GetGoodsDetailAsync(int goodsId, int goodsNum, int userId);
Task<List<GoodsChildrenDto>> GetGoodsChildrenAsync(int goodsId, int goodsNum, int goodsListId);
}
// 商品查询DTO
public class GoodsQueryDto
{
public int Type { get; set; } = -1;
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 15;
}
// 商品列表DTO
public class GoodsListDto
{
public int Id { get; set; }
public string Title { get; set; }
public string ImgUrl { get; set; }
public decimal Price { get; set; }
public int Type { get; set; }
public string TypeText { get; set; }
public int Stock { get; set; }
public int SaleStock { get; set; }
public int Status { get; set; }
public int LockIs { get; set; }
public int IsShouZhe { get; set; }
public int NewIs { get; set; }
public int JoinCount { get; set; }
public int NeedDrawNum { get; set; }
}
```
### 4.3 商品详情查询 (4天)
#### 任务描述
实现商品详情查询功能,包括奖品列表、概率计算、锁箱信息等
#### 具体工作
- [ ] 实现商品详情查询接口
- [ ] 实现奖品列表查询
- [ ] 实现概率计算逻辑
- [ ] 实现锁箱状态查询
- [ ] 实现参与用户统计
#### 核心接口实现
##### 商品详情接口
```http
GET /api/v1/goods/{goodsId}/detail
Authorization: Bearer {token}
Query Parameters:
- goods_num: 箱号默认0自动选择
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"goods": {
"id": 123,
"title": "商品标题",
"imgurl_detail": "https://example.com/detail.jpg",
"price": "10.00",
"type": 1,
"type_text": "一番赏",
"stock": 100,
"sale_stock": 80,
"surplus_stock": 20,
"goodslist_stock": 100,
"goodslist_surplus_stock": 20,
"lock_is": 0,
"status": 1,
"addtime": "01-15",
"num": 1,
"collection_is": 0,
"three_time": 3,
"five_time": 5
},
"lock_info": {
"lock_is": 0,
"goods_lock_user_nickname": "",
"goods_lock_user_headimg": "",
"goods_lock_surplus_time": 0
},
"join_user": [
"https://example.com/avatar1.jpg",
"https://example.com/avatar2.jpg"
],
"join_count": 150,
"goodslist": [
{
"id": 456,
"shang_id": 10,
"shang_info": {
"id": 10,
"title": "A赏",
"color": "#FF0000"
},
"title": "奖品标题",
"stock": 10,
"surplus_stock": 5,
"imgurl": "https://example.com/prize.jpg",
"goods_type": 1,
"price": "100.00",
"sc_money": "0.00",
"sale_time": "2024-01-15",
"pro": "概率10%",
"children": false
}
],
"limitInfo": {
"canPurchase": true,
"dailyLimit": 10,
"dailyUsed": 3,
"globalLimit": 100,
"globalUsed": 50
}
}
}
```
##### 商品子奖品接口
```http
GET /api/v1/goods/{goodsId}/children
Authorization: Bearer {token}
Query Parameters:
- goods_num: 箱号
- goods_list_id: 父奖品ID
Response:
{
"status": 1,
"msg": "请求成功",
"data": [
{
"id": 789,
"shang_id": 38,
"title": "子奖品",
"stock": 5,
"surplus_stock": 3,
"imgurl": "https://example.com/child_prize.jpg",
"goods_type": 1,
"price": "50.00",
"real_pro": 20.5,
"pro": "概率20.5%",
"pro_num": 20.5
}
]
}
```
### 4.4 商品扩展配置 (2天)
#### 任务描述
实现商品扩展配置查询,包括支付方式、抵扣设置等
#### 具体工作
- [ ] 实现商品扩展配置查询接口
- [ ] 实现默认配置获取逻辑
- [ ] 实现配置继承机制
#### 核心接口实现
##### 商品扩展配置接口
```http
GET /api/v1/goods/{goodsId}/extend
Authorization: Bearer {token}
Query Parameters:
- goods_type: 商品类型
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"goods_id": 123,
"pay_wechat": 1,
"pay_balance": 1,
"pay_currency": 1,
"pay_currency2": 1,
"pay_coupon": 1,
"is_deduction": 1
}
}
```
### 4.5 商品箱号管理 (3天)
#### 任务描述
实现商品箱号查询和管理功能
#### 具体工作
- [ ] 实现箱号列表查询接口
- [ ] 实现箱号详情查询接口
- [ ] 实现箱号排序功能
- [ ] 实现余量统计功能
#### 核心接口实现
##### 箱号列表接口
```http
GET /api/v1/goods/{goodsId}/boxes
Authorization: Bearer {token}
Response:
{
"status": 1,
"msg": "请求成功",
"data": [
{
"title": "1-10",
"page_no": 0
},
{
"title": "11-20",
"page_no": 1
}
]
}
```
##### 箱号详情接口
```http
GET /api/v1/goods/{goodsId}/boxes/detail
Authorization: Bearer {token}
Query Parameters:
- page_no: 页码
- sort: 排序方式 (0=箱号, 1=箱号高, 2=余量高)
Response:
{
"status": 1,
"msg": "请求成功",
"data": [
{
"num": 1,
"surplus_all_stock": 15,
"goodslist": [
{
"shang_id": 10,
"shang_info": {
"title": "A赏",
"color": "#FF0000"
},
"stock": 10,
"surplus_stock": 5
}
]
}
]
}
```
### 4.6 商品收藏功能 (2天)
#### 任务描述
实现商品收藏和取消收藏功能
#### 具体工作
- [ ] 设计收藏数据模型
- [ ] 实现收藏状态查询
- [ ] 实现收藏操作接口
- [ ] 实现收藏列表查询
#### 核心接口实现
##### 收藏/取消收藏接口
```http
POST /api/v1/goods/{goodsId}/collect
Authorization: Bearer {token}
Content-Type: application/json
Request:
{
"goods_num": 1,
"action": "add" // add=收藏, remove=取消收藏
}
Response:
{
"status": 1,
"msg": "收藏成功"
}
```
##### 收藏列表接口
```http
GET /api/v1/user/collections
Authorization: Bearer {token}
Query Parameters:
- page: 页码
- limit: 每页数量
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"data": [
{
"id": 123,
"goods_id": 456,
"goods_num": 1,
"goods_title": "商品标题",
"goods_imgurl": "https://example.com/goods.jpg",
"goods_price": "10.00",
"collect_time": "2024-01-01 12:00:00"
}
],
"last_page": 3
}
}
```
### 4.7 商品奖品统计 (1天)
#### 任务描述
实现商品奖品数量和内容统计功能
#### 具体工作
- [ ] 实现奖品数量统计接口
- [ ] 实现奖品内容查询接口
#### 核心接口实现
##### 商品奖品数量统计接口
```http
POST /api/v1/goods/prize-count
Authorization: Bearer {token}
Request:
{
"goods_id": 1001
}
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"total_count": 100,
"surplus_count": 50,
"category_count": [
{
"shang_id": 10,
"shang_title": "A赏",
"total": 10,
"surplus": 5
}
]
}
}
```
##### 商品奖品内容接口
```http
POST /api/v1/goods/prize-content
Authorization: Bearer {token}
Request:
{
"goods_id": 1001,
"num": 0
}
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"goods_list": [
{
"id": 456,
"title": "奖品标题",
"imgurl": "https://example.com/prize.jpg",
"price": "100.00",
"stock": 10,
"surplus_stock": 5
}
]
}
}
```
### 4.8 中奖记录查询 (3天)
#### 任务描述
实现商品中奖记录查询功能
#### 具体工作
- [ ] 实现中奖记录查询接口
- [ ] 实现奖品分类筛选
- [ ] 实现中奖统计功能
- [ ] 优化查询性能
#### 核心接口实现
##### 中奖记录接口
```http
GET /api/v1/goods/{goodsId}/prize-logs
Authorization: Bearer {token}
Query Parameters:
- goods_num: 箱号
- shang_id: 奖品分类ID0=全部
Response:
{
"status": 1,
"msg": "请求成功",
"data": {
"category": [
{
"shang_id": 0,
"shang_title": "全部"
},
{
"shang_id": 10,
"shang_title": "A赏"
}
],
"data": [
{
"user_id": 123,
"user_info": {
"nickname": "用户昵称",
"headimg": "https://example.com/avatar.jpg"
},
"goodslist_title": "奖品标题",
"goodslist_imgurl": "https://example.com/prize.jpg",
"shang_id": 10,
"shang_title": "A赏",
"shang_color": "#FF0000",
"prize_num": 1,
"addtime": "2024-01-01 12:00:00"
}
],
"last_page": 5
}
}
```
## 缓存策略设计
### Redis缓存键设计
```csharp
// 商品列表缓存
public static class CacheKeys
{
public const string GoodsList = "goods_list_{0}_{1}_{2}"; // type_userId_page
public const string GoodsDetail = "goods_detail_{0}_{1}"; // goodsId_goodsNum
public const string GoodsJoinCount = "order_goods_count:{0}"; // goodsId
public const string GoodsBoxes = "goods_boxes_{0}"; // goodsId
// 缓存过期时间
public static readonly TimeSpan GoodsListExpiry = TimeSpan.FromSeconds(30);
public static readonly TimeSpan GoodsDetailExpiry = TimeSpan.FromMinutes(5);
public static readonly TimeSpan JoinCountExpiry = TimeSpan.FromMinutes(5);
}
```
### 缓存更新策略
```csharp
public class GoodsCacheService
{
public async Task InvalidateGoodsCache(int goodsId)
{
// 清除相关缓存
await _redis.DeleteAsync($"goods_detail_{goodsId}_*");
await _redis.DeleteAsync($"order_goods_count:{goodsId}");
await _redis.DeleteAsync("goods_list_*");
}
public async Task UpdateJoinCount(int goodsId)
{
var key = $"order_goods_count:{goodsId}";
await _redis.IncrementAsync(key);
await _redis.ExpireAsync(key, CacheKeys.JoinCountExpiry);
}
}
```
## 性能优化方案
### 数据库查询优化
```sql
-- 商品列表查询索引
CREATE INDEX idx_goods_status_type_sort ON goods(status, type, sort DESC, id DESC);
CREATE INDEX idx_goods_unlock_amount ON goods(unlock_amount);
-- 商品奖品查询索引
CREATE INDEX idx_goodslist_goods_num ON goods_list(goods_id, num, shang_id);
CREATE INDEX idx_goodslist_surplus ON goods_list(goods_id, surplus_stock);
-- 订单统计查询索引
CREATE INDEX idx_orderlist_goods_count ON order_list(goods_id, num, shang_id, order_type);
```
### 批量查询优化
```csharp
public async Task<List<GoodsListDto>> GetGoodsListWithJoinCountAsync(List<int> goodsIds)
{
// 批量查询商品信息
var goods = await _context.Goods
.Where(g => goodsIds.Contains(g.Id))
.ToListAsync();
// 批量查询参与次数
var joinCounts = await GetBatchJoinCountsAsync(goodsIds);
// 组装结果
return goods.Select(g => new GoodsListDto
{
// ... 其他属性
JoinCount = joinCounts.GetValueOrDefault(g.Id, 0)
}).ToList();
}
```
## 验收标准
### 功能验收
- [ ] 商品列表查询功能正常,支持分类筛选
- [ ] 商品详情查询功能正常,包含完整奖品信息
- [ ] 商品箱号管理功能正常
- [ ] 商品收藏功能正常
- [ ] 中奖记录查询功能正常
- [ ] 商品扩展配置查询正常
- [ ] 商品奖品数量统计正常
- [ ] 商品奖品内容查询正常
### 性能验收
- [ ] 商品列表接口响应时间 < 300ms
- [ ] 商品详情接口响应时间 < 500ms
- [ ] 缓存命中率 > 80%
- [ ] 支持并发查询 > 100 QPS
### 数据准确性验收
- [ ] 商品库存计算准确
- [ ] 奖品概率计算正确
- [ ] 参与次数统计准确
- [ ] 收藏状态同步正确
## 风险点和注意事项
### 技术风险
1. **缓存一致性**: 商品信息更新时的缓存同步
2. **查询性能**: 大量商品和奖品数据的查询优化
3. **概率计算**: 复杂的概率计算逻辑准确性
4. **并发访问**: 高并发下的数据一致性
### 解决方案
1. **缓存策略**: 合理的缓存过期时间和更新机制
2. **数据库优化**: 适当的索引和查询优化
3. **单元测试**: 概率计算逻辑的充分测试
4. **监控告警**: 关键接口的性能监控
## 下一阶段准备
### 为阶段5准备的内容
- [ ] 订单数据模型设计
- [ ] 购物车功能基础
- [ ] 库存扣减机制
- [ ] 订单状态管理
### 交接文档
- [ ] 商品系统架构说明
- [ ] 概率计算规则文档
- [ ] 缓存策略说明
- [ ] 数据库索引优化指南
---
**阶段4完成标志**: 商品系统功能完整,包括商品查询、详情展示、收藏管理、中奖记录等功能正常运行,性能和数据准确性达到要求。