HaniBlindBox/.kiro/specs/user-management-migration/design.md
2026-01-02 17:24:05 +08:00

12 KiB
Raw Blame History

Design Document: 用户管理系统迁移

Overview

本设计文档描述了用户管理系统从PHP迁移到.NET 8的技术方案。系统包括用户资产管理、VIP等级、优惠券、任务、推荐关系、排行榜、兑换码和福利屋等模块。

Architecture

系统架构

┌─────────────────────────────────────────────────────────────┐
│                      API Layer                               │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐│
│  │UserController│ │CouponController│ │WelfareController    ││
│  └─────────────┘ └─────────────┘ └─────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────┐
│                    Service Layer                             │
│  ┌───────────────┐ ┌───────────────┐ ┌───────────────────┐  │
│  │IAssetService  │ │ICouponService │ │IWelfareService    │  │
│  │IVipService    │ │ITaskService   │ │IRankService       │  │
│  │IInvitationSvc │ │IRedeemService │                       │
│  └───────────────┘ └───────────────┘ └───────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────┐
│                    Data Layer                                │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                  HoneyBoxDbContext                     │  │
│  │  ProfitMoney | ProfitIntegral | ProfitMoney2          │  │
│  │  UserCoupon | TaskList | UserTaskList                 │  │
│  │  UserVip | Order | OrderList | Goods | GoodsList      │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

Components and Interfaces

1. 资产服务接口 (IAssetService)

public interface IAssetService
{
    // 余额明细查询
    Task<PagedResult<AssetRecordDto>> GetMoneyRecordsAsync(int userId, int type, int page, int limit = 15);
    
    // 吧唧币明细查询
    Task<PagedResult<AssetRecordDto>> GetIntegralRecordsAsync(int userId, int type, int page, int limit = 15);
    
    // 积分明细查询
    Task<PagedResult<AssetRecordDto>> GetScoreRecordsAsync(int userId, int type, int page, int limit = 15);
    
    // 支付记录查询
    Task<PagedResult<AssetRecordDto>> GetPayRecordsAsync(int userId, int page, int limit = 15);
}

2. VIP服务接口 (IVipService)

public interface IVipService
{
    // 获取VIP信息
    Task<VipInfoResponse> GetVipInfoAsync(int userId);
    
    // 计算VIP等级
    Task<int> CalculateVipLevelAsync(int userId, int currentVip);
    
    // 获取VIP等级列表
    Task<List<VipLevelDto>> GetVipLevelsAsync();
}

3. 优惠券服务接口 (ICouponService)

public interface ICouponService
{
    // 获取优惠券列表
    Task<CouponListResponse> GetCouponListAsync(int userId, int status, int page, int limit = 15);
    
    // 获取优惠券详情
    Task<CouponDetailDto> GetCouponDetailAsync(int userId, int couponId);
    
    // 分享优惠券
    Task<bool> ShareCouponAsync(int userId, int couponId);
    
    // 领取优惠券
    Task<bool> ClaimCouponAsync(int userId, int couponId);
    
    // 计算合成
    Task<SynthesisCalculateResult> CalculateSynthesisAsync(int userId, string couponIds);
    
    // 执行合成
    Task<bool> SynthesisCouponsAsync(int userId, string couponIds);
}

4. 任务服务接口 (ITaskService)

public interface ITaskService
{
    // 获取任务列表
    Task<TaskListResponse> GetTaskListAsync(int userId, int type);
    
    // 领取任务奖励
    Task<bool> ClaimTaskRewardAsync(int userId, int taskListId);
}

5. 推荐服务接口 (IInvitationService)

public interface IInvitationService
{
    // 获取推荐信息
    Task<InvitationInfoResponse> GetInvitationInfoAsync(int userId, int page);
    
    // 绑定邀请码
    Task<bool> BindInviteCodeAsync(int userId, string inviteCode);
}

6. 排行榜服务接口 (IRankService)

public interface IRankService
{
    // 获取周榜
    Task<RankResponse> GetWeekRankAsync(int userId);
    
    // 获取月榜
    Task<RankResponse> GetMonthRankAsync(int userId);
}

7. 兑换码服务接口 (IRedeemService)

public interface IRedeemService
{
    // 使用兑换码
    Task<RedeemResult> UseRedeemCodeAsync(int userId, string code);
}

8. 福利屋服务接口 (IWelfareService)

public interface IWelfareService
{
    // 获取福利屋列表
    Task<PagedResult<WelfareItemDto>> GetWelfareListAsync(int userId, int type, int page, int limit = 15);
    
    // 获取福利屋详情
    Task<WelfareDetailResponse> GetWelfareDetailAsync(int userId, int goodsId);
    
    // 获取参与者列表
    Task<List<ParticipantDto>> GetParticipantsAsync(int goodsId);
    
    // 获取开奖记录
    Task<List<WinningRecordDto>> GetWinningRecordsAsync(int goodsId);
    
    // 获取用户参与记录
    Task<List<UserParticipationDto>> GetUserParticipationRecordsAsync(int userId);
    
    // 获取用户中奖记录
    Task<List<UserWinningDto>> GetUserWinningRecordsAsync(int userId);
}

Data Models

资产记录DTO

public class AssetRecordDto
{
    public string ChangeMoney { get; set; }
    public string Content { get; set; }
    public string AddTime { get; set; }
}

VIP信息响应

public class VipInfoResponse
{
    public VipUserInfoDto Userinfo { get; set; }
    public List<VipLevelDto> Data { get; set; }
}

public class VipUserInfoDto
{
    public string Nickname { get; set; }
    public string Headimg { get; set; }
    public int Vip { get; set; }
    public string UpgradeMoney { get; set; }
    public int LastVip { get; set; }
    public decimal JinDu { get; set; }
    public string Notice { get; set; }
}

优惠券DTO

public class CouponDto
{
    public int Id { get; set; }
    public int Status { get; set; }
    public int Level { get; set; }
    public string LevelText { get; set; }
    public string LevelImg { get; set; }
    public string Title { get; set; }
    public string Num { get; set; }
    public int KlNum { get; set; }
    public int KlNum2 { get; set; }
    public int YiLing { get; set; }
}

任务DTO

public class TaskDto
{
    public int Id { get; set; }
    public int Type { get; set; }
    public int Cate { get; set; }
    public string Title { get; set; }
    public int Number { get; set; }
    public int ZNumber { get; set; }
    public int IsComplete { get; set; }
    public int Percentage { get; set; }
    public int YwcCount { get; set; }
}

排行榜DTO

public class RankItemDto
{
    public int Rank { get; set; }
    public int UserId { get; set; }
    public string Nickname { get; set; }
    public string Headimg { get; set; }
    public decimal OrderTotal { get; set; }
    public string PrizeTitle { get; set; }
    public string PrizeImgurl { get; set; }
}

Correctness Properties

A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.

Property 1: 资产记录分页一致性

For any asset record query with pagination, the returned last_page value SHALL correctly reflect the total number of pages based on total records and page size.

Validates: Requirements 1.1, 1.2, 1.3, 1.4, 1.6

Property 2: VIP等级计算正确性

For any user with total consumption amount X, the calculated VIP level SHALL be the highest level whose condition is less than or equal to X.

Validates: Requirements 2.1, 2.2

Property 3: VIP升级进度计算

For any user not at maximum VIP level, the upgrade progress percentage SHALL equal (current_consumption / next_level_threshold) * 100.

Validates: Requirements 2.4

Property 4: 优惠券等级映射

For any coupon with level L, the level_text and level_img SHALL correctly map to: 1=特级赏券, 2=终极赏券, 3=高级赏券, 4=普通赏券.

Validates: Requirements 3.3

Property 5: 优惠券领取随机金额

For any coupon claim, the random amount SHALL be between minimum (1) and remaining pool, and the sum of all claimed amounts SHALL not exceed the original coupon value.

Validates: Requirements 6.1

Property 6: 优惠券合成损耗

For any coupon synthesis, the new coupon value SHALL equal sum of original values minus 10% loss.

Validates: Requirements 7.2

Property 7: 任务周期计算

For any daily task, the progress SHALL only count activities within current day (00:00:00 to 23:59:59). For any weekly task, the progress SHALL only count activities within current week (Monday 00:00:00 to Sunday 23:59:59).

Validates: Requirements 8.2, 8.3

Property 8: 排行榜排序正确性

For any ranking query, the returned list SHALL be sorted by consumption amount in descending order, with ties broken by user_id in ascending order.

Validates: Requirements 10.1, 10.2

Property 9: 福利屋解锁金额验证

For any welfare house with unlock_amount > 0, only users whose total consumption >= unlock_amount SHALL be able to view the activity.

Validates: Requirements 12.3, 13.1

Error Handling

通用错误处理

错误场景 错误码 错误消息
参数缺失 0 缺少必要参数
数据不存在 0 数据不存在/参数错误
未授权 -1 请先登录
业务限制 2222 具体业务提示

优惠券特殊错误

错误场景 错误码 错误消息
领取自己的券 2222 请勿开启自己的劵
已领取过 2222 你已经领取过了
已被领完 2222 来晚了, 已经被人领完了
达到每日上限 0 每天最多领取N次
特级/终极券不能合成 0 特级,终极赏券不能合成
超过合成数量限制 0 最多只能20个合成

Testing Strategy

单元测试

  • 测试各服务的核心业务逻辑
  • 测试边界条件和错误处理
  • 使用Mock隔离外部依赖

属性测试

使用FsCheck进行属性测试验证以下属性

  • VIP等级计算正确性
  • 优惠券合成损耗计算
  • 任务周期边界计算
  • 排行榜排序正确性

集成测试

  • 测试完整的API请求响应流程
  • 测试数据库事务一致性
  • 测试Redis缓存行为

测试配置

// 属性测试配置
[Property(MaxTest = 100)]
public Property VipLevelCalculation_ShouldBeCorrect()
{
    return Prop.ForAll<decimal>(consumption =>
    {
        var level = CalculateVipLevel(consumption);
        // 验证等级正确性
    });
}