- 新增 .dockerignore 文件,忽略多种临时及中间文件 - 新增 .gitattributes 文件,配置文本文件换行及合并行为 - 新增详细的 .gitignore 文件,排除多种开发及生成文件 - 新增 VS Code C# 代码片段,提升开发效率 - 添加 Directory.Build.props,统一 MSBuild 配置和代码分析规则 - 添加空的 Directory.Build.targets,预留构建任务扩展位置 - 添加 Directory.Packages.props,实现依赖包版本集中管理和声明
195 lines
7.8 KiB
Markdown
195 lines
7.8 KiB
Markdown
## 后端功能概览
|
||
|
||
> 本文档简要说明当前后端(Backend)已完成的主要功能与技术实现,便于后续开发和前后端联调。
|
||
|
||
---
|
||
|
||
## 一、整体技术栈与架构
|
||
|
||
- **技术栈**
|
||
- .NET 10
|
||
- EF Core + SQLite
|
||
- CAP + NetCorePal 集成事件
|
||
- FastEndpoints 用于 API 端点
|
||
|
||
- **架构风格**
|
||
- CleanDDD 分层结构:Domain / Infrastructure / Web
|
||
- 聚合根统一继承 `Entity<TId>, IAggregateRoot`
|
||
- 使用强类型 ID(`xxxId : IGuidStronglyTypedId`)
|
||
- 领域事件 + 集成事件 解耦跨聚合、跨事务操作
|
||
- 命令(Command)与查询(Query)各自独立,命令处理器只操作仓储,不显式保存事务
|
||
|
||
---
|
||
|
||
## 二、已完成的核心聚合与领域模型
|
||
|
||
- **会员聚合(MemberAggregate)**
|
||
- 会员注册、登录
|
||
- 基本信息:手机号、密码(加密后存储)、昵称
|
||
- 会员等级值对象(Level):等级编码、名称、所需积分、积分倍率
|
||
- 积分账户:累计积分、可用积分
|
||
|
||
- **营销码聚合(MarketingCodeAggregate)**
|
||
- 一物一码:唯一营销码与产品信息绑定
|
||
- 状态管理:未使用/已使用
|
||
- 使用营销码会发布 `MarketingCodeUsedDomainEvent`
|
||
|
||
- **积分规则聚合(PointsRuleAggregate)**
|
||
- 支持按产品 / 类目 / 会员等级 / 时间区间配置规则
|
||
- 可以计算应得积分(当前实现为“取匹配规则中的最高值”)
|
||
|
||
- **积分交易聚合(PointsTransactionAggregate)**
|
||
- 已从会员聚合中拆分为独立聚合
|
||
- 支持四类交易:获取(Earn)、消费(Consume)、退还(Refund)、过期(Expire)
|
||
- 通过集成事件异步创建记录(详见第四节)
|
||
|
||
- **礼品聚合(GiftAggregate)**
|
||
- 礼品基本信息:名称、类型(实物/虚拟/自有产品)、描述、图片
|
||
- 业务字段:所需积分、总库存、可用库存、每人限兑数量、是否上架、排序
|
||
- 领域行为:
|
||
- `Update(...)` 更新礼品信息
|
||
- `AddStock(...)` 增加库存
|
||
- `ReserveStock(...)` 下单时预留库存
|
||
- `DeductStock(...)` 发货时扣减总库存
|
||
- `ReleaseStock(...)` 订单取消时释放库存
|
||
- `PutOnShelf/PutOffShelf` 上/下架
|
||
|
||
- **兑换订单聚合(RedemptionOrderAggregate)**
|
||
- 基本字段:订单号、会员ID、礼品ID/名称/类型、数量、消耗积分
|
||
- 收货地址值对象(Address) 用于实物礼品
|
||
- 状态机:Pending → Dispatched → Delivered → Completed / Cancelled
|
||
- 领域行为:`MarkAsDispatched`、`MarkAsDelivered`、`Complete`、`Cancel`
|
||
- 领域事件:
|
||
- `RedemptionOrderCreatedDomainEvent`(创建订单)
|
||
- `RedemptionOrderDispatchedDomainEvent`(发货)
|
||
- `RedemptionOrderCancelledDomainEvent`(取消)
|
||
- 其他状态事件(已送达、完成)
|
||
|
||
---
|
||
|
||
## 三、会员与积分业务流程
|
||
|
||
- **会员注册 / 登录**
|
||
- 命令:
|
||
- `RegisterMemberCommand`:校验手机号唯一性,保存会员
|
||
- `LoginMemberCommand`:验证手机号+密码
|
||
- 端点(示例):
|
||
- `POST /api/members/register`
|
||
- `POST /api/members/login`
|
||
|
||
- **扫码使用营销码 → 发放积分**
|
||
- 命令:`UseMarketingCodeCommand`
|
||
- 校验营销码是否存在、是否可用
|
||
- 关联会员后标记营销码为已使用
|
||
- 更新由 `IMarketingCodeRepository` 完成
|
||
- 领域事件:`MarketingCodeUsedDomainEvent`
|
||
- 领域事件处理器:`MarketingCodeUsedDomainEventHandlerForEarnPoints`
|
||
- 加载会员
|
||
- 通过 `IPointsRuleRepository.GetEffectiveRulesAsync` 匹配积分规则
|
||
- 计算应得积分 + 过期时间
|
||
- 调用 `Member.AddPoints(...)`
|
||
- 更新会员(不会在此处创建积分交易记录)
|
||
|
||
---
|
||
|
||
## 四、积分交易与集成事件流程
|
||
|
||
- **领域事件 → 集成事件**
|
||
- 会员增加积分时发布 `PointsAddedDomainEvent`
|
||
- Web 层有对应的集成事件转换器(IIntegrationEventConverter):
|
||
- `PointsAddedToPointsEarnedConverter` 等
|
||
- 集成事件定义(实现 `IIntegrationEvent`):
|
||
- `PointsEarnedIntegrationEvent`
|
||
- `PointsConsumedIntegrationEvent`
|
||
- `PointsRefundedIntegrationEvent`
|
||
- `PointsExpiredIntegrationEvent`
|
||
- 集成事件只携带 **ID 和必要基础字段**(MemberId, Amount, RelatedId, ExpiryDate 等), 不包含聚合对象。
|
||
|
||
- **集成事件处理器(IIntegrationEventHandler)**
|
||
- 在 Web 层实现, 通过 `ApplicationDbContext` 读写积分交易表:
|
||
- 收到 Earn/Consume/Refund/Expire 事件
|
||
- 基于 `RelatedId` 或批次ID 做幂等性检查
|
||
- 调用 `PointsTransaction.CreateXxxTransaction(...)` 创建交易聚合
|
||
- 保存到 `PointsTransactions` 表
|
||
|
||
- **事务与一致性**
|
||
- 积分变更(会员聚合) 与 积分交易记录(PointsTransaction 聚合) 处于不同事务
|
||
- 通过领域事件 → 集成事件 → 处理器链路实现最终一致性
|
||
|
||
---
|
||
|
||
## 五、礼品与积分商城功能
|
||
|
||
- **礼品管理(管理端)**
|
||
- 命令(Commands):
|
||
- `CreateGiftCommand`:创建礼品
|
||
- `UpdateGiftCommand`:更新礼品信息
|
||
- `PutOnShelfCommand` / `PutOffShelfCommand`:上/下架
|
||
- `AddGiftStockCommand`:增加库存
|
||
- 查询(Queries):
|
||
- `GetGiftsQuery`:按类型/是否上架筛选列表
|
||
- `GetGiftByIdQuery`:礼品详情
|
||
- 仓储:`IGiftRepository` + `GiftRepository`
|
||
- 端点(Endpoints):
|
||
- `POST /api/admin/gifts`
|
||
- `PUT /api/admin/gifts/{GiftId}`
|
||
- `POST /api/admin/gifts/{GiftId}/putonshelf`
|
||
- `POST /api/admin/gifts/{GiftId}/putoffshelf`
|
||
- `POST /api/admin/gifts/{GiftId}/addstock`
|
||
- `GET /api/admin/gifts`
|
||
- `GET /api/admin/gifts/{GiftId}`
|
||
|
||
- **会员端积分商城**
|
||
- 礼品浏览与详情:
|
||
- `GET /api/gifts`:仅返回已上架礼品
|
||
- `GET /api/gifts/{GiftId}`:礼品详情
|
||
- 兑换礼品(创建兑换订单):
|
||
- 命令:`CreateRedemptionOrderCommand`
|
||
- 校验礼品存在且已上架
|
||
- 校验库存及每人限兑数量(通过 `IRedemptionOrderRepository.GetMemberRedemptionCountAsync`)
|
||
- 校验会员可用积分是否足够
|
||
- 调用会员聚合 `ConsumePoints` 扣减积分并更新会员
|
||
- 构造收货地址(实物礼品必须提供地址)
|
||
- 创建兑换订单聚合 `RedemptionOrder`
|
||
- 使用仓储 `IRedemptionOrderRepository.AddAsync` 持久化
|
||
- 端点:`POST /api/gifts/redeem`
|
||
- 会员查询自己的兑换订单:
|
||
- 查询:`GetRedemptionOrdersQuery` / `GetRedemptionOrderByIdQuery`
|
||
- 端点:
|
||
- `GET /api/redemption-orders/my`(按会员+状态过滤)
|
||
- `GET /api/redemption-orders/{OrderId}`
|
||
|
||
- **后台兑换订单管理(管理端)**
|
||
- 列表/详情:同上查询, 管理端端点前缀 `/api/admin/redemption-orders`
|
||
- 状态流转命令:
|
||
- `MarkOrderAsDispatchedCommand`:发货
|
||
- `CompleteOrderCommand`:完成
|
||
- `CancelOrderCommand`:取消
|
||
- 对应端点:
|
||
- `POST /api/admin/redemption-orders/{OrderId}/dispatch`
|
||
- `POST /api/admin/redemption-orders/{OrderId}/complete`
|
||
- `POST /api/admin/redemption-orders/{OrderId}/cancel`
|
||
|
||
- **兑换订单相关领域事件处理器**
|
||
- `RedemptionOrderCreatedDomainEventHandler`:
|
||
- 加载礼品聚合
|
||
- 调用 `Gift.ReserveStock(...)` 预留库存
|
||
- 调用仓储 `UpdateAsync` 持久化
|
||
- `RedemptionOrderCancelledDomainEventHandler`:
|
||
- 释放库存 `Gift.ReleaseStock(...)`
|
||
- `RedemptionOrderDispatchedDomainEventHandler`:
|
||
- 发货后扣减总库存 `Gift.DeductStock(...)`
|
||
|
||
---
|
||
|
||
## 六、当前状态与后续工作建议
|
||
|
||
- **当前状态**
|
||
- 后端项目可以成功编译(`dotnet build`);存在若干 Sonar 质量规则警告(主要是 TODO/异常处理提示), 不影响运行
|
||
- 会员、营销码、积分规则、积分交易、礼品、兑换订单等核心领域模型和主要业务流程已经打通
|
||
|
||
- **后续可选工作**
|
||
- 增加更多查询(如礼品统计、积分流水查询分页等)
|
||
- 完善认证鉴权(从 JWT 中获取当前登录会员ID, 替换临时 MemberId 参数)
|
||
- 根据前端实际需要, 补充 DTO 字段或调整 API 结构
|