Project.Fengling.QoderVersion/docs/backend/后端功能概览.md
sam 056eb9b6f9 feat: 实现完整的前后端功能
- 后端新增管理员、商品、分类聚合模型
- 实现积分规则、礼品、订单、会员等完整功能
- 添加管理员认证和权限管理
- 完善数据库迁移和实体配置
- 前端管理后台实现登录、仪表盘、积分规则、礼品、订单、会员等页面
- 集成shadcn-vue UI组件库
- 添加前后端功能文档和截图
2026-02-11 21:36:37 +08:00

18 KiB
Raw Blame History

后端功能概览

本文档说明当前后端(Backend)已完成的主要功能与技术实现,便于后续开发和前后端联调。
最后更新时间2026-02-11


一、整体技术栈与架构

1.1 技术栈

  • .NET 10 - 最新的 .NET 运行时
  • EF Core + SQLite - 数据持久化(已从 PostgreSQL 迁移到 SQLite
  • CAP + NetCorePal - 分布式事务与集成事件框架
  • FastEndpoints - 高性能 API 端点框架
  • Hangfire - 后台任务调度
  • Redis - 分布式缓存与 CAP 消息存储
  • MediatR - CQRS 模式实现
  • Swashbuckle/Swagger - API 文档

1.2 架构风格

  • CleanDDD 分层结构Domain / Infrastructure / Web
  • 聚合根:统一继承 Entity<TId>, IAggregateRoot
  • 强类型 ID:所有实体 ID 使用 xxxId : IGuidStronglyTypedId
  • 领域事件 + 集成事件:解耦跨聚合、跨事务操作
  • CQRS:命令(Command)与查询(Query)分离,命令处理器操作仓储,查询直接访问 DbContext
  • 最终一致性:通过领域事件 → 集成事件 → 事件处理器实现

二、已完成的核心聚合与领域模型

2.1 会员聚合 (MemberAggregate)

  • 实体Member
  • 核心字段
    • 手机号、密码(加密)、昵称
    • 累计总积分 TotalPoints
    • 可用积分 AvailablePoints
    • 状态(正常/禁用)、注册时间
  • 值对象
    • MemberLevel:等级编码、名称、所需积分、积分倍率
  • 领域行为
    • AddPoints(amount, source, reason, relatedId, expiryDate) - 增加积分
    • ConsumePoints(amount, reason, orderId) - 消费积分
    • RefundPoints(amount, reason, orderId) - 退还积分
  • 领域事件
    • PointsAddedDomainEvent
    • PointsConsumedDomainEvent
    • PointsRefundedDomainEvent

2.2 营销码聚合 (MarketingCodeAggregate)

  • 实体MarketingCode
  • 核心字段
    • 营销码 Code(唯一)
    • 批次号 BatchNo
    • 是否已使用 IsUsed
    • 使用者会员ID、使用时间
    • 过期时间
  • 值对象
    • ProductInfo产品ID、产品名称、品类ID、品类名称
  • 领域行为
    • Use(memberId) - 使用营销码
  • 领域事件
    • MarketingCodeUsedDomainEvent

2.3 积分规则聚合 (PointsRuleAggregate)

  • 实体PointsRule
  • 核心字段
    • 规则名称、规则类型(产品/时间/会员等级)
    • 积分值、奖励倍数
    • 产品ID、品类ID、会员等级编码
    • 生效时间范围(开始/结束)
    • 是否激活
  • 领域行为
    • CalculatePoints(memberBonusRate) - 计算应得积分

2.4 积分交易聚合 (PointsTransactionAggregate)

  • 实体PointsTransaction
  • 核心字段
    • 会员ID、交易类型(获取/消费/退还/过期)
    • 积分数量、来源、原因描述
    • 关联ID(营销码ID/订单ID等)
    • 过期时间(仅获取类型有效)
    • 创建时间
  • 静态工厂方法
    • CreateEarnTransaction(...) - 创建获取积分记录
    • CreateConsumeTransaction(...) - 创建消费积分记录
    • CreateRefundTransaction(...) - 创建退还积分记录
    • CreateExpireTransaction(...) - 创建过期积分记录
  • 说明:通过集成事件异步创建,与会员聚合解耦

2.5 礼品聚合 (GiftAggregate)

  • 实体Gift
  • 核心字段
    • 礼品名称、类型(实物/虚拟/自有产品)
    • 描述、图片URL
    • 所需积分、总库存、可用库存
    • 每人限兑数量、是否上架、排序
    • 创建/更新时间
  • 领域行为
    • Update(...) - 更新礼品信息
    • AddStock(quantity) - 增加库存
    • ReserveStock(quantity) - 预留库存(下单时)
    • DeductStock(quantity) - 扣减总库存(发货时)
    • ReleaseStock(quantity) - 释放库存(订单取消时)
    • PutOnShelf() / PutOffShelf() - 上架/下架
  • 领域事件
    • GiftCreatedDomainEvent
    • GiftUpdatedDomainEvent
    • GiftStockChangedDomainEvent

2.6 兑换订单聚合 (RedemptionOrderAggregate)

  • 实体RedemptionOrder
  • 核心字段
    • 订单号、会员ID、礼品ID/名称/类型
    • 数量、消耗积分
    • 物流单号、取消原因
    • 状态(待处理/已发货/已送达/已完成/已取消)
    • 创建/更新时间
  • 值对象
    • Address:收货人姓名、电话、省市区、详细地址(实物礼品必填)
  • 领域行为
    • MarkAsDispatched(trackingNo) - 标记为已发货
    • MarkAsDelivered() - 标记为已送达
    • Complete() - 完成订单
    • Cancel(reason) - 取消订单
  • 领域事件
    • RedemptionOrderCreatedDomainEvent
    • RedemptionOrderDispatchedDomainEvent
    • RedemptionOrderDeliveredDomainEvent
    • RedemptionOrderCompletedDomainEvent
    • RedemptionOrderCancelledDomainEvent

三、核心业务流程

3.1 会员注册与登录

会员注册

  • 端点POST /api/members/register
  • 请求RegisterMemberRequest { Phone, Password, Nickname? }
  • 命令RegisterMemberCommand
  • 流程
    1. 校验手机号唯一性
    2. 密码加密存储
    3. 创建会员并设置初始等级
    4. 返回会员ID

会员登录

  • 端点POST /api/members/login
  • 请求LoginMemberRequest { Phone, Password }
  • 命令LoginMemberCommand
  • 流程
    1. 验证手机号和密码
    2. 返回会员信息和 TokenTODO: 完善 JWT 认证)

3.2 扫码获取积分流程

使用营销码

  • 端点POST /api/marketing-codes/scan
  • 请求UseMarketingCodeRequest { Code, MemberId }
  • 命令UseMarketingCodeCommand

完整流程

1. UseMarketingCodeCommand
   ├─ 校验营销码存在且未使用
   ├─ 校验未过期
   ├─ 关联会员并标记为已使用
   └─ 发布 MarketingCodeUsedDomainEvent

2. MarketingCodeUsedDomainEvent
   └─ MarketingCodeUsedDomainEventHandlerForEarnPoints
      ├─ 加载会员聚合
      ├─ 匹配积分规则(IPointsRuleRepository.GetEffectiveRulesAsync)
      ├─ 计算应得积分和过期时间
      ├─ 调用 Member.AddPoints(...)
      ├─ 更新会员聚合
      └─ 发布 PointsAddedDomainEvent

3. PointsAddedDomainEvent
   └─ PointsAddedToPointsEarnedConverter (集成事件转换器)
      └─ 发布 PointsEarnedIntegrationEvent

4. PointsEarnedIntegrationEvent
   └─ PointsEarnedIntegrationEventHandler
      ├─ 幂等性检查(基于 RelatedId)
      ├─ 创建 PointsTransaction.CreateEarnTransaction(...)
      └─ 保存到积分交易表

3.3 礼品兑换流程

创建兑换订单

  • 端点POST /api/gifts/redeem
  • 请求CreateRedemptionOrderCommand { MemberId, GiftId, Quantity, ShippingAddress? }

完整流程

1. CreateRedemptionOrderCommand
   ├─ 校验礼品存在且已上架
   ├─ 校验库存充足
   ├─ 校验限兑数量(IRedemptionOrderRepository.GetMemberRedemptionCountAsync)
   ├─ 校验会员积分充足
   ├─ 调用 Member.ConsumePoints(...) 扣减积分
   ├─ 更新会员聚合 → 发布 PointsConsumedDomainEvent
   ├─ 构造收货地址(实物礼品必填)
   ├─ 创建 RedemptionOrder 聚合
   └─ 发布 RedemptionOrderCreatedDomainEvent

2. PointsConsumedDomainEvent
   └─ PointsConsumedToPointsConsumedIntegrationEventConverter
      └─ 发布 PointsConsumedIntegrationEvent
         └─ 创建消费积分交易记录

3. RedemptionOrderCreatedDomainEvent
   └─ RedemptionOrderCreatedDomainEventHandler
      ├─ 加载礼品聚合
      ├─ 调用 Gift.ReserveStock(quantity)
      └─ 更新礼品聚合(预留库存)

订单状态流转

订单发货: POST /api/admin/redemption-orders/{OrderId}/dispatch
├─ MarkOrderAsDispatchedCommand
├─ Order.MarkAsDispatched(trackingNo)
├─ 发布 RedemptionOrderDispatchedDomainEvent
└─ RedemptionOrderDispatchedDomainEventHandler
   └─ Gift.DeductStock(quantity) 扣减总库存

订单取消: POST /api/admin/redemption-orders/{OrderId}/cancel
├─ CancelOrderCommand
├─ Order.Cancel(reason)
├─ 发布 RedemptionOrderCancelledDomainEvent
├─ RedemptionOrderCancelledDomainEventHandler
│  └─ Gift.ReleaseStock(quantity) 释放库存
└─ 退还积分(TODO: 待实现)

四、积分交易与集成事件架构

4.1 领域事件与集成事件流转

领域事件 (Domain Events)

在会员聚合中发布,用于触发同一事务内或跨事务的业务逻辑:

  • PointsAddedDomainEvent - 会员增加积分时
  • PointsConsumedDomainEvent - 会员消费积分时
  • PointsRefundedDomainEvent - 积分退还时
  • PointsExpiredDomainEvent - 积分过期时

集成事件 (Integration Events)

实现 IIntegrationEvent 接口,通过 CAP 框架发布和消费:

  • PointsEarnedIntegrationEvent - 对应 Earn 交易
  • PointsConsumedIntegrationEvent - 对应 Consume 交易
  • PointsRefundedIntegrationEvent - 对应 Refund 交易
  • PointsExpiredIntegrationEvent - 对应 Expire 交易

集成事件转换器 (IIntegrationEventConverter)

将领域事件转换为集成事件:

  • PointsAddedToPointsEarnedConverter
  • PointsConsumedToPointsConsumedIntegrationEventConverter
  • PointsRefundedToPointsRefundedIntegrationEventConverter
  • PointsExpiredToPointsExpiredIntegrationEventConverter

4.2 集成事件处理器

位于 Web 层,通过 ApplicationDbContext 操作积分交易表:

// 示例:处理获取积分集成事件
public class PointsEarnedIntegrationEventHandler : IIntegrationEventHandler<PointsEarnedIntegrationEvent>
{
    public async Task Handle(PointsEarnedIntegrationEvent @event, CancellationToken cancellationToken)
    {
        // 1. 幂等性检查:基于 RelatedId 查询是否已存在
        var exists = await dbContext.PointsTransactions
            .AnyAsync(x => x.RelatedId == @event.RelatedId, cancellationToken);
        
        if (exists) return; // 已处理过,跳过
        
        // 2. 创建积分交易记录
        var transaction = PointsTransaction.CreateEarnTransaction(
            memberId: new MemberId(@event.MemberId),
            amount: @event.Amount,
            source: @event.Source,
            reason: @event.Reason,
            relatedId: @event.RelatedId,
            expiryDate: @event.ExpiryDate
        );
        
        // 3. 保存到数据库
        await dbContext.PointsTransactions.AddAsync(transaction, cancellationToken);
        await dbContext.SaveChangesAsync(cancellationToken);
    }
}

4.3 事务与一致性保证

最终一致性

  • 会员积分变更(会员聚合)和 积分交易记录PointsTransaction 聚合)处于不同事务
  • 通过 领域事件 → 集成事件 → 事件处理器 链路实现最终一致性
  • CAP 框架保证集成事件至少一次送达

幂等性保证

  • 基于 RelatedId营销码ID、订单ID等进行幂等性检查
  • 防止重复消费导致的数据不一致

五、API 端点一览

5.1 会员模块 (Members)

端点 方法 说明 认证
/api/members/register POST 会员注册 匿名
/api/members/login POST 会员登录 匿名
/api/members/{MemberId} GET 获取会员信息 需要

5.2 营销码模块 (MarketingCodes)

端点 方法 说明 认证
/api/marketing-codes/scan POST 扫码使用营销码 匿名
/api/admin/marketing-codes/generate POST 批量生成营销码(管理端) 需要

5.3 礼品模块 (Gifts)

会员端

端点 方法 说明 认证
/api/gifts GET 获取上架礼品列表 匿名
/api/gifts/{GiftId} GET 获取礼品详情 匿名
/api/gifts/redeem POST 兑换礼品 需要

管理端

端点 方法 说明 认证
/api/admin/gifts POST 创建礼品 需要
/api/admin/gifts/{GiftId} PUT 更新礼品信息 需要
/api/admin/gifts/{GiftId}/putonshelf POST 上架礼品 需要
/api/admin/gifts/{GiftId}/putoffshelf POST 下架礼品 需要
/api/admin/gifts/{GiftId}/addstock POST 增加库存 需要
/api/admin/gifts GET 获取礼品列表(支持筛选) 需要
/api/admin/gifts/{GiftId} GET 获取礼品详情 需要

5.4 兑换订单模块 (RedemptionOrders)

会员端

端点 方法 说明 认证
/api/redemption-orders/my GET 获取我的兑换订单列表 需要
/api/redemption-orders/{OrderId} GET 获取订单详情 需要

管理端

端点 方法 说明 认证
/api/admin/redemption-orders GET 获取兑换订单列表 需要
/api/admin/redemption-orders/{OrderId} GET 获取订单详情 需要
/api/admin/redemption-orders/{OrderId}/dispatch POST 标记为已发货 需要
/api/admin/redemption-orders/{OrderId}/complete POST 完成订单 需要
/api/admin/redemption-orders/{OrderId}/cancel POST 取消订单 需要

5.5 积分规则模块 (PointsRules)

端点 方法 说明 认证
/api/admin/points-rules POST 创建积分规则(管理端) 需要

5.6 通用端点

端点 方法 说明 认证
/api/hello GET 健康检查 匿名
/swagger GET API 文档 匿名

注意

  • 所有端点返回统一的 ResponseData<T> 格式
  • 强类型IDMemberId, GiftId)在 Swagger 中映射为字符串类型
  • 当前 JWT 认证尚未完全实现,部分端点暂时从请求参数获取 MemberId

六、数据库设计

6.1 数据库信息

  • 数据库类型SQLite
  • 数据库文件app.db(开发环境)
  • 迁移工具EF Core Migrations
  • 最新迁移20260211044819_Init

6.2 核心数据表

Members - 会员表

主要字段Id, Phone(唯一), Password, Nickname, Status, TotalPoints, AvailablePoints, LevelCode, LevelName, BonusRate, RequiredPoints, RegisteredAt

MarketingCodes - 营销码表

主要字段Id, Code(唯一), BatchNo, IsUsed, UsedByMemberId, UsedAt, ExpiryDate, ProductId, ProductName, CategoryId, CategoryName

PointsRules - 积分规则表

主要字段Id, RuleName, RuleType, PointsValue, BonusMultiplier, ProductId, CategoryId, MemberLevelCode, StartDate, EndDate, IsActive

PointsTransactions - 积分交易表

主要字段Id, MemberId, Type, Amount, Source, Reason, RelatedId, ExpiryDate, CreatedAt

重要索引

  • IX_PointsTransactions_MemberId - 会员积分查询
  • IX_PointsTransactions_RelatedId - 幂等性检查(非唯一)
  • IX_PointsTransactions_Type - 按类型筛选
  • IX_PointsTransactions_CreatedAt - 时间排序

Gifts - 礼品表

主要字段Id, Name, Type, Description, ImageUrl, RequiredPoints, TotalStock, AvailableStock, LimitPerMember, IsOnShelf, SortOrder, CreatedAt, UpdatedAt

RedemptionOrders - 兑换订单表

主要字段Id, OrderNo(唯一), MemberId, GiftId, GiftName, GiftType, Quantity, ConsumedPoints, Status, TrackingNo, CancelReason, ReceiverName, ReceiverPhone, Province, City, District, DetailAddress, CreatedAt, UpdatedAt

6.3 数据表关系说明

  • 所有表使用 GUIDVersion 7作为主键
  • 使用软删除(Deleted 字段)
  • 使用行版本(RowVersion)实现乐观并发控制
  • 积分交易表与会员表通过 MemberId 关联,但不设置外键(最终一致性)
  • 兑换订单表包含礼品快照信息,减少关联查询

七、当前状态与后续建议

7.1 当前状态

已完成功能

  • 后端项目成功编译和运行(dotnet build & dotnet run
  • 数据库迁移已修复SQLite 切换完成EF Core 模型与迁移一致)
  • Swagger API 文档正常生成Schema 冲突已解决)
  • 会员、营销码、积分规则、积分交易、礼品、兑换订单等核心领域模型完整
  • 扫码获取积分、礼品兑换等主要业务流程已打通
  • 集成事件架构实现(领域事件 → 集成事件 → 事件处理器)

⚠️ 已知问题

  • 存在若干 Sonar 质量规则警告TODO 注释、异常处理建议等),不影响运行
  • JWT 认证尚未完全实现,部分端点暂时从请求参数获取 MemberId
  • 订单取消后的积分退还逻辑待完善

7.2 后续建议

短期优化

  1. 完善认证鉴权

    • 实现完整的 JWT Token 认证流程
    • 从 Token 中获取当前登录会员ID
    • 添加基于角色的权限控制(会员端/管理端)
  2. 补充查询功能

    • 会员积分流水查询(分页、筛选)
    • 礼品库存统计和销售报表
    • 订单统计和数据分析
  3. 完善业务逻辑

    • 实现订单取消后的积分退还
    • 添加积分过期处理定时任务
    • 完善会员等级自动升级逻辑

长期规划

  • 根据前端实际需求调整 API 结构和 DTO 字段
  • 增加单元测试和集成测试覆盖率
  • 性能优化和缓存策略
  • 监控和日志完善

八、开发与部署

8.1 本地开发

# 启动基础设施Redis
cd Backend/scripts
./init-infrastructure.sh  # Linux/Mac
./init-infrastructure.ps1 # Windows

# 运行后端
cd Backend/src/Fengling.Backend.Web
dotnet run

# 访问 Swagger 文档
http://localhost:5511/swagger

8.2 数据库迁移

# 添加新迁移
cd Backend/src/Fengling.Backend.Infrastructure
dotnet ef migrations add MigrationName

# 应用迁移(自动在启动时执行)
dotnet ef database update

8.3 项目结构

Backend/
├── src/
│   ├── Fengling.Backend.Domain/         # 领域层:聚合、实体、值对象、领域事件
│   ├── Fengling.Backend.Infrastructure/ # 基础设施层:数据库、仓储实现
│   └── Fengling.Backend.Web/            # 应用层API端点、命令查询、事件处理器
├── test/                                # 测试项目
└── scripts/                             # 基础设施脚本