From af4b68c2dd4cc34b07fe727184d17eb0990c0ba7 Mon Sep 17 00:00:00 2001 From: zpc Date: Mon, 9 Feb 2026 08:35:43 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8FAPI=E5=BC=80=E5=8F=91=E8=A7=84=E5=88=92=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 miniapp-api spec (requirements, design, tasks) - 添加 API开发任务清单,包含页面-API对照验证 - 规划28个待开发接口,按P0/P1/P2优先级排列 --- .kiro/specs/miniapp-api/design.md | 1199 +++++++++++++++++++++++ .kiro/specs/miniapp-api/requirements.md | 200 ++++ .kiro/specs/miniapp-api/tasks.md | 268 +++++ docs/API开发任务清单.md | 751 ++++++++++++++ 4 files changed, 2418 insertions(+) create mode 100644 .kiro/specs/miniapp-api/design.md create mode 100644 .kiro/specs/miniapp-api/requirements.md create mode 100644 .kiro/specs/miniapp-api/tasks.md create mode 100644 docs/API开发任务清单.md diff --git a/.kiro/specs/miniapp-api/design.md b/.kiro/specs/miniapp-api/design.md new file mode 100644 index 0000000..679d6ea --- /dev/null +++ b/.kiro/specs/miniapp-api/design.md @@ -0,0 +1,1199 @@ +# Design Document: 小程序API开发 + +## Overview + +本设计文档描述学业邑规划(MiAssessment)微信小程序后端API的技术实现方案。系统采用分层架构,遵循.NET Web API最佳实践,实现28个API接口,覆盖8个业务模块。 + +### 技术栈 +- 后端框架:.NET 10 Web API (C#) +- 数据库:SQL Server 2022 +- ORM:Entity Framework Core +- 缓存:Redis +- 接口风格:RPC风格(仅GET/POST请求) + +### 模块优先级 +- P0(核心):首页模块、测评模块、订单模块 +- P1(重要):业务详情模块、规划师模块、分销模块 +- P2(辅助):系统模块、团队模块 + +## Architecture + +### 系统架构图 + +```mermaid +graph TB + subgraph "小程序端" + MP[微信小程序] + end + + subgraph "API层" + HC[HomeController] + BC[BusinessController] + AC[AssessmentController] + OC[OrderController] + PC[PlannerController] + IC[InviteController] + SC[SystemController] + TC[TeamController] + end + + subgraph "服务层" + HS[HomeService] + BS[BusinessService] + AS[AssessmentService] + OS[OrderService] + PS[PlannerService] + IS[InviteService] + SS[SystemService] + TS[TeamService] + end + + subgraph "数据层" + DB[(SQL Server)] + Redis[(Redis Cache)] + end + + MP --> HC & BC & AC & OC & PC & IC & SC & TC + HC --> HS + BC --> BS + AC --> AS + OC --> OS + PC --> PS + IC --> IS + SC --> SS + TC --> TS + HS & BS & AS & OS & PS & IS & SS & TS --> DB + HS & BS & SS & TS --> Redis +``` + +### 项目结构 + +``` +server/MiAssessment/src/MiAssessment.Api/ +├── Controllers/ +│ ├── HomeController.cs # 首页模块 +│ ├── BusinessController.cs # 业务详情模块 +│ ├── AssessmentController.cs # 测评模块 +│ ├── OrderController.cs # 订单模块 +│ ├── PlannerController.cs # 规划师模块 +│ ├── InviteController.cs # 分销模块 +│ ├── SystemController.cs # 系统模块 +│ └── TeamController.cs # 团队模块 + +server/MiAssessment/src/MiAssessment.Core/ +├── Interfaces/ +│ ├── IHomeService.cs +│ ├── IBusinessService.cs +│ ├── IAssessmentService.cs +│ ├── IOrderService.cs +│ ├── IPlannerService.cs +│ ├── IInviteService.cs +│ ├── ISystemService.cs +│ └── ITeamService.cs +├── Services/ +│ ├── HomeService.cs +│ ├── BusinessService.cs +│ ├── AssessmentService.cs +│ ├── OrderService.cs +│ ├── PlannerService.cs +│ ├── InviteService.cs +│ ├── SystemService.cs +│ └── TeamService.cs + +server/MiAssessment/src/MiAssessment.Model/ +├── Models/ +│ ├── Home/ +│ ├── Business/ +│ ├── Assessment/ +│ ├── Order/ +│ ├── Planner/ +│ ├── Invite/ +│ ├── System/ +│ └── Team/ +├── Entities/ +│ ├── Banner.cs +│ ├── Promotion.cs +│ ├── BusinessPage.cs +│ ├── Planner.cs +│ ├── PlannerBooking.cs +│ ├── InviteCode.cs +│ ├── Commission.cs +│ └── Withdrawal.cs +``` + +## Components and Interfaces + +### 1. 首页模块 (HomeController / IHomeService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/home")] +public class HomeController : ControllerBase +{ + /// + /// 获取Banner列表 + /// GET /api/home/getBannerList + /// + [HttpGet("getBannerList")] + Task>> GetBannerList(); + + /// + /// 获取测评入口列表 + /// GET /api/home/getAssessmentList + /// + [HttpGet("getAssessmentList")] + Task>> GetAssessmentList(); + + /// + /// 获取宣传图列表 + /// GET /api/home/getPromotionList + /// + [HttpGet("getPromotionList")] + Task>> GetPromotionList(); +} +``` + +#### 服务接口 + +```csharp +public interface IHomeService +{ + Task> GetBannerListAsync(); + Task> GetAssessmentListAsync(); + Task> GetPromotionListAsync(); +} +``` + +### 2. 业务详情模块 (BusinessController / IBusinessService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/business")] +public class BusinessController : ControllerBase +{ + /// + /// 获取业务详情 + /// GET /api/business/getDetail?id=1 + /// + [HttpGet("getDetail")] + Task> GetDetail([FromQuery] long id); +} +``` + +#### 服务接口 + +```csharp +public interface IBusinessService +{ + Task GetDetailAsync(long id); +} +``` + +### 3. 测评模块 (AssessmentController / IAssessmentService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/assessment")] +public class AssessmentController : ControllerBase +{ + /// + /// 获取测评介绍 + /// GET /api/assessment/getIntro?typeId=1 + /// + [HttpGet("getIntro")] + Task> GetIntro([FromQuery] long typeId); + + /// + /// 获取题目列表 + /// GET /api/assessment/getQuestionList?typeId=1 + /// + [HttpGet("getQuestionList")] + [Authorize] + Task>> GetQuestionList([FromQuery] long typeId); + + /// + /// 提交测评答案 + /// POST /api/assessment/submitAnswers + /// + [HttpPost("submitAnswers")] + [Authorize] + Task> SubmitAnswers([FromBody] SubmitAnswersRequest request); + + /// + /// 查询报告生成状态 + /// GET /api/assessment/getResultStatus?recordId=1 + /// + [HttpGet("getResultStatus")] + [Authorize] + Task> GetResultStatus([FromQuery] long recordId); + + /// + /// 获取测评结果 + /// GET /api/assessment/getResult?recordId=1 + /// + [HttpGet("getResult")] + [Authorize] + Task> GetResult([FromQuery] long recordId); + + /// + /// 验证邀请码 + /// POST /api/assessment/verifyInviteCode + /// + [HttpPost("verifyInviteCode")] + [Authorize] + Task> VerifyInviteCode([FromBody] VerifyInviteCodeRequest request); + + /// + /// 获取往期测评列表 + /// GET /api/assessment/getHistoryList?page=1&pageSize=20 + /// + [HttpGet("getHistoryList")] + [Authorize] + Task>> GetHistoryList([FromQuery] int page = 1, [FromQuery] int pageSize = 20); +} +``` + +#### 服务接口 + +```csharp +public interface IAssessmentService +{ + Task GetIntroAsync(long typeId); + Task> GetQuestionListAsync(long typeId); + Task SubmitAnswersAsync(long userId, SubmitAnswersRequest request); + Task GetResultStatusAsync(long userId, long recordId); + Task GetResultAsync(long userId, long recordId); + Task VerifyInviteCodeAsync(string code); + Task> GetHistoryListAsync(long userId, int page, int pageSize); +} +``` + +### 4. 订单模块 (OrderController / IOrderService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/order")] +public class OrderController : ControllerBase +{ + /// + /// 获取订单列表 + /// GET /api/order/getList?page=1&pageSize=20&orderType=1 + /// + [HttpGet("getList")] + [Authorize] + Task>> GetList([FromQuery] int page = 1, [FromQuery] int pageSize = 20, [FromQuery] int? orderType = null); + + /// + /// 获取订单详情 + /// GET /api/order/getDetail?orderId=1 + /// + [HttpGet("getDetail")] + [Authorize] + Task> GetDetail([FromQuery] long orderId); + + /// + /// 创建订单 + /// POST /api/order/create + /// + [HttpPost("create")] + [Authorize] + Task> Create([FromBody] CreateOrderRequest request); + + /// + /// 发起支付 + /// POST /api/order/pay + /// + [HttpPost("pay")] + [Authorize] + Task> Pay([FromBody] PayRequest request); + + /// + /// 查询支付结果 + /// GET /api/order/getPayResult?orderId=1 + /// + [HttpGet("getPayResult")] + [Authorize] + Task> GetPayResult([FromQuery] long orderId); +} +``` + +#### 服务接口 + +```csharp +public interface IOrderService +{ + Task> GetListAsync(long userId, int page, int pageSize, int? orderType); + Task GetDetailAsync(long userId, long orderId); + Task CreateAsync(long userId, CreateOrderRequest request); + Task PayAsync(long userId, long orderId); + Task GetPayResultAsync(long userId, long orderId); +} +``` + +### 5. 规划师模块 (PlannerController / IPlannerService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/planner")] +public class PlannerController : ControllerBase +{ + /// + /// 获取规划师列表 + /// GET /api/planner/getList + /// + [HttpGet("getList")] + Task>> GetList(); +} +``` + +#### 服务接口 + +```csharp +public interface IPlannerService +{ + Task> GetListAsync(); +} +``` + +### 6. 分销模块 (InviteController / IInviteService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/invite")] +public class InviteController : ControllerBase +{ + /// + /// 获取邀请信息 + /// GET /api/invite/getInfo + /// + [HttpGet("getInfo")] + [Authorize] + Task> GetInfo(); + + /// + /// 生成邀请二维码 + /// GET /api/invite/getQrcode + /// + [HttpGet("getQrcode")] + [Authorize] + Task> GetQrcode(); + + /// + /// 获取邀请记录 + /// GET /api/invite/getRecordList?page=1&pageSize=20 + /// + [HttpGet("getRecordList")] + [Authorize] + Task>> GetRecordList([FromQuery] int page = 1, [FromQuery] int pageSize = 20); + + /// + /// 获取佣金信息 + /// GET /api/invite/getCommission + /// + [HttpGet("getCommission")] + [Authorize] + Task> GetCommission(); + + /// + /// 申请提现 + /// POST /api/invite/applyWithdraw + /// + [HttpPost("applyWithdraw")] + [Authorize] + Task> ApplyWithdraw([FromBody] ApplyWithdrawRequest request); + + /// + /// 获取提现记录 + /// GET /api/invite/getWithdrawList?page=1&pageSize=20 + /// + [HttpGet("getWithdrawList")] + [Authorize] + Task>> GetWithdrawList([FromQuery] int page = 1, [FromQuery] int pageSize = 20); +} +``` + +#### 服务接口 + +```csharp +public interface IInviteService +{ + Task GetInfoAsync(long userId); + Task GetQrcodeAsync(long userId); + Task> GetRecordListAsync(long userId, int page, int pageSize); + Task GetCommissionAsync(long userId); + Task ApplyWithdrawAsync(long userId, decimal amount); + Task> GetWithdrawListAsync(long userId, int page, int pageSize); +} +``` + +### 7. 系统模块 (SystemController / ISystemService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/system")] +public class SystemController : ControllerBase +{ + /// + /// 获取用户协议 + /// GET /api/system/getAgreement + /// + [HttpGet("getAgreement")] + Task> GetAgreement(); + + /// + /// 获取隐私政策 + /// GET /api/system/getPrivacy + /// + [HttpGet("getPrivacy")] + Task> GetPrivacy(); + + /// + /// 获取关于我们 + /// GET /api/system/getAbout + /// + [HttpGet("getAbout")] + Task> GetAbout(); +} +``` + +#### 服务接口 + +```csharp +public interface ISystemService +{ + Task GetAgreementAsync(); + Task GetPrivacyAsync(); + Task GetAboutAsync(); +} +``` + +### 8. 团队模块 (TeamController / ITeamService) + +#### 控制器接口 + +```csharp +[ApiController] +[Route("api/team")] +public class TeamController : ControllerBase +{ + /// + /// 获取团队介绍 + /// GET /api/team/getInfo + /// + [HttpGet("getInfo")] + Task> GetInfo(); +} +``` + +#### 服务接口 + +```csharp +public interface ITeamService +{ + Task GetInfoAsync(); +} +``` + +## Data Models + +### 实体类 (Entities) + +#### Banner.cs +```csharp +[Table("banners")] +public class Banner +{ + [Key] + public long Id { get; set; } + public string? Title { get; set; } + [Required] + public string ImageUrl { get; set; } = null!; + public int LinkType { get; set; } // 0无 1内部页面 2外部链接 3小程序 + public string? LinkUrl { get; set; } + public string? AppId { get; set; } + public int Sort { get; set; } + public int Status { get; set; } // 0禁用 1启用 + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### Promotion.cs +```csharp +[Table("promotions")] +public class Promotion +{ + [Key] + public long Id { get; set; } + public string? Title { get; set; } + [Required] + public string ImageUrl { get; set; } = null!; + public int Position { get; set; } // 1首页底部 2团队页 + public int Sort { get; set; } + public int Status { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### BusinessPage.cs +```csharp +[Table("business_pages")] +public class BusinessPage +{ + [Key] + public long Id { get; set; } + public string? Title { get; set; } + [Required] + public string ImageUrl { get; set; } = null!; + public bool ShowButton { get; set; } + public string? ButtonText { get; set; } + public string? ButtonLink { get; set; } + public int Sort { get; set; } + public int Status { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### Planner.cs +```csharp +[Table("planners")] +public class Planner +{ + [Key] + public long Id { get; set; } + [Required] + public string Name { get; set; } = null!; + [Required] + public string Avatar { get; set; } = null!; + public string? Introduction { get; set; } + public decimal Price { get; set; } + public int Sort { get; set; } + public int Status { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### InviteCode.cs +```csharp +[Table("invite_codes")] +public class InviteCode +{ + [Key] + public long Id { get; set; } + [Required] + public string Code { get; set; } = null!; + public string? BatchNo { get; set; } + public long? AssignUserId { get; set; } + public DateTime? AssignTime { get; set; } + public long? UseUserId { get; set; } + public long? UseOrderId { get; set; } + public DateTime? UseTime { get; set; } + public int Status { get; set; } // 1未分配 2已分配 3已使用 + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### Commission.cs +```csharp +[Table("commissions")] +public class Commission +{ + [Key] + public long Id { get; set; } + public long UserId { get; set; } + public long FromUserId { get; set; } + public long OrderId { get; set; } + public decimal OrderAmount { get; set; } + public decimal CommissionRate { get; set; } + public decimal CommissionAmount { get; set; } + public int Level { get; set; } // 1直接下级 2间接下级 + public int Status { get; set; } // 1待结算 2已结算 + public DateTime? SettleTime { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +#### Withdrawal.cs +```csharp +[Table("withdrawals")] +public class Withdrawal +{ + [Key] + public long Id { get; set; } + [Required] + public string WithdrawalNo { get; set; } = null!; + public long UserId { get; set; } + public decimal Amount { get; set; } + public decimal BeforeBalance { get; set; } + public decimal AfterBalance { get; set; } + public int Status { get; set; } // 1申请中 2提现中 3已提现 4已取消 + public long? AuditUserId { get; set; } + public DateTime? AuditTime { get; set; } + public string? AuditRemark { get; set; } + public DateTime? PayTime { get; set; } + public string? PayTransactionId { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public bool IsDeleted { get; set; } +} +``` + +### DTO模型 + +#### Home模块 +```csharp +public class BannerDto +{ + public long Id { get; set; } + public string? Title { get; set; } + public string ImageUrl { get; set; } = null!; + public int LinkType { get; set; } + public string? LinkUrl { get; set; } + public string? AppId { get; set; } +} + +public class AssessmentTypeDto +{ + public long Id { get; set; } + public string Name { get; set; } = null!; + public string Code { get; set; } = null!; + public string ImageUrl { get; set; } = null!; + public decimal Price { get; set; } + public int Status { get; set; } +} + +public class PromotionDto +{ + public long Id { get; set; } + public string? Title { get; set; } + public string ImageUrl { get; set; } = null!; +} +``` + +#### Business模块 +```csharp +public class BusinessDetailDto +{ + public long Id { get; set; } + public string? Title { get; set; } + public string ImageUrl { get; set; } = null!; + public bool ShowButton { get; set; } + public string? ButtonText { get; set; } + public string? ButtonLink { get; set; } +} +``` + +#### Assessment模块 +```csharp +public class AssessmentIntroDto +{ + public string Content { get; set; } = null!; + public string ContentType { get; set; } = null!; + public decimal Price { get; set; } +} + +public class QuestionDto +{ + public long Id { get; set; } + public int QuestionNo { get; set; } + public string Content { get; set; } = null!; +} + +public class SubmitAnswersRequest +{ + public long RecordId { get; set; } + public List Answers { get; set; } = new(); +} + +public class AnswerItem +{ + public long QuestionId { get; set; } + public int AnswerValue { get; set; } +} + +public class SubmitAnswersResponse +{ + public bool Success { get; set; } + public int EstimatedTime { get; set; } +} + +public class ResultStatusDto +{ + public int Status { get; set; } + public bool IsCompleted { get; set; } +} + +public class VerifyInviteCodeRequest +{ + public string Code { get; set; } = null!; +} + +public class VerifyInviteCodeResponse +{ + public bool IsValid { get; set; } + public string? ErrorMessage { get; set; } + public long? InviteCodeId { get; set; } +} + +public class AssessmentHistoryDto +{ + public long Id { get; set; } + public string OrderNo { get; set; } = null!; + public string AssessmentName { get; set; } = null!; + public int Status { get; set; } + public string StatusText { get; set; } = null!; + public string TestDate { get; set; } = null!; +} +``` + +#### Order模块 +```csharp +public class OrderItemDto +{ + public long Id { get; set; } + public string OrderNo { get; set; } = null!; + public int OrderType { get; set; } + public string ProductName { get; set; } = null!; + public decimal Amount { get; set; } + public int Status { get; set; } + public string StatusText { get; set; } = null!; + public string CreateTime { get; set; } = null!; + public long? AssessmentRecordId { get; set; } +} + +public class CreateOrderRequest +{ + public int OrderType { get; set; } + public long ProductId { get; set; } + public AssessmentInfoDto? AssessmentInfo { get; set; } + public PlannerInfoDto? PlannerInfo { get; set; } + public long? InviteCodeId { get; set; } +} + +public class AssessmentInfoDto +{ + public string Name { get; set; } = null!; + public string Phone { get; set; } = null!; + public int Gender { get; set; } + public int Age { get; set; } + public int EducationStage { get; set; } + public string Province { get; set; } = null!; + public string City { get; set; } = null!; + public string District { get; set; } = null!; +} + +public class CreateOrderResponse +{ + public long OrderId { get; set; } + public string OrderNo { get; set; } = null!; + public decimal PayAmount { get; set; } + public bool NeedPay { get; set; } + public long? AssessmentRecordId { get; set; } +} + +public class PayRequest +{ + public long OrderId { get; set; } +} + +public class PayResponse +{ + public string TimeStamp { get; set; } = null!; + public string NonceStr { get; set; } = null!; + public string Package { get; set; } = null!; + public string SignType { get; set; } = null!; + public string PaySign { get; set; } = null!; +} + +public class PayResultDto +{ + public bool IsPaid { get; set; } + public int Status { get; set; } + public long? AssessmentRecordId { get; set; } +} +``` + +#### Invite模块 +```csharp +public class InviteInfoDto +{ + public string InviteUrl { get; set; } = null!; + public string InviteCode { get; set; } = null!; + public decimal WithdrawnAmount { get; set; } + public decimal PendingAmount { get; set; } + public int InviteCount { get; set; } +} + +public class QrcodeDto +{ + public string QrcodeUrl { get; set; } = null!; +} + +public class InviteRecordDto +{ + public long UserId { get; set; } + public string Nickname { get; set; } = null!; + public string Avatar { get; set; } = null!; + public string Uid { get; set; } = null!; + public string RegisterDate { get; set; } = null!; + public decimal Commission { get; set; } +} + +public class CommissionInfoDto +{ + public decimal TotalIncome { get; set; } + public decimal WithdrawnAmount { get; set; } + public decimal PendingAmount { get; set; } +} + +public class ApplyWithdrawRequest +{ + public decimal Amount { get; set; } +} + +public class ApplyWithdrawResponse +{ + public bool Success { get; set; } + public string? ErrorMessage { get; set; } + public string? WithdrawalNo { get; set; } +} + +public class WithdrawRecordDto +{ + public long Id { get; set; } + public string WithdrawalNo { get; set; } = null!; + public decimal Amount { get; set; } + public int Status { get; set; } + public string StatusText { get; set; } = null!; + public string CreateTime { get; set; } = null!; + public string? PayTime { get; set; } +} +``` + +#### System模块 +```csharp +public class AgreementDto +{ + public string Content { get; set; } = null!; +} + +public class PrivacyDto +{ + public string Content { get; set; } = null!; +} + +public class AboutDto +{ + public string Content { get; set; } = null!; + public string Version { get; set; } = null!; +} +``` + +#### Team模块 +```csharp +public class TeamInfoDto +{ + public List Images { get; set; } = new(); +} +``` + + + +## 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* 列表查询接口(Banner、测评类型、宣传图、题目、规划师),返回的所有记录都应满足指定的过滤条件(Status、Position、IsDeleted等),且不包含任何不满足条件的记录。 + +**Validates: Requirements 1.1, 1.2, 1.3, 3.2, 10.1, 15.1** + +### Property 2: 列表查询排序正确性 + +*For any* 需要排序的列表查询接口,返回的记录应按指定字段(Sort、QuestionNo等)正确排序,相邻记录的排序字段值应满足排序规则。 + +**Validates: Requirements 1.1, 3.2, 10.1** + +### Property 3: 分页查询一致性 + +*For any* 分页查询接口,返回的记录数不应超过pageSize,total应等于满足条件的总记录数,且遍历所有页面应能获取所有满足条件的记录。 + +**Validates: Requirements 6.1, 7.1, 12.1, 13.5, 16.4** + +### Property 4: 用户数据隔离 + +*For any* 需要用户认证的查询接口(订单、测评记录、邀请记录等),返回的数据应只属于当前登录用户,不应包含其他用户的数据。 + +**Validates: Requirements 4.3, 4.5, 6.1, 7.1, 7.2, 7.3** + +### Property 5: 订单创建完整性 + +*For any* 订单创建请求,成功创建后应同时存在订单记录和关联记录(测评记录或规划预约),且关联记录的OrderId应指向新创建的订单。 + +**Validates: Requirements 8.1, 8.2** + +### Property 6: 邀请码使用一次性 + +*For any* 有效的邀请码,使用后其状态应变为"已使用",且不能被再次使用;对于已使用的邀请码,验证接口应返回"已被使用"错误。 + +**Validates: Requirements 5.1, 5.3, 5.4, 8.3** + +### Property 7: 提现余额一致性 + +*For any* 提现申请,提现后用户余额应等于提现前余额减去提现金额,且提现记录中的BeforeBalance和AfterBalance应正确记录变化。 + +**Validates: Requirements 13.1** + +### Property 8: 响应格式一致性 + +*For any* API接口调用,响应应包含code、message、data三个字段,成功时code=0,失败时code!=0且message包含错误信息。 + +**Validates: Requirements 16.1, 16.2, 16.3** + +### Property 9: 测评答案提交状态变更 + +*For any* 有效的测评答案提交,提交后测评记录的状态应从"待测评"或"测评中"变为"生成中",且答案数量应等于题目数量。 + +**Validates: Requirements 4.1, 4.2** + +### Property 10: 订单事务回滚 + +*For any* 订单创建过程中发生的错误,数据库中不应存在部分创建的订单或关联记录,所有操作应完全回滚。 + +**Validates: Requirements 8.4** + +## Error Handling + +### 错误码定义 + +| 错误码 | 说明 | 使用场景 | +|--------|------|----------| +| 0 | 成功 | 所有成功响应 | +| -1 | 未登录 | Token无效或未提供 | +| 1001 | 参数错误 | 请求参数验证失败 | +| 1002 | 未登录 | 需要认证但未提供Token | +| 1003 | 登录已过期 | Token已过期 | +| 1004 | 无权限 | 访问非本人数据 | +| 2001 | 业务错误 | 通用业务逻辑错误 | +| 2002 | 数据不存在 | 查询的记录不存在 | +| 2003 | 状态错误 | 操作的记录状态不允许 | +| 2004 | 邀请码无效 | 邀请码不存在或已使用 | +| 2005 | 余额不足 | 提现金额超过可用余额 | +| 5000 | 系统错误 | 未预期的系统异常 | + +### 错误处理策略 + +#### 参数验证错误 +```csharp +// 在控制器层进行参数验证 +if (string.IsNullOrWhiteSpace(request.Code)) +{ + return ApiResponse.Fail("邀请码不能为空", 1001); +} +``` + +#### 业务逻辑错误 +```csharp +// 在服务层抛出业务异常 +if (inviteCode == null) +{ + throw new BusinessException("邀请码有误,请重新输入", 2004); +} + +if (inviteCode.Status == 3) +{ + throw new BusinessException("邀请码已被使用", 2004); +} +``` + +#### 权限验证错误 +```csharp +// 验证数据归属 +if (record.UserId != userId) +{ + return ApiResponse.Fail("无权限访问", 1004); +} +``` + +#### 事务回滚 +```csharp +using var transaction = await _dbContext.Database.BeginTransactionAsync(); +try +{ + // 多表操作 + await _dbContext.SaveChangesAsync(); + await transaction.CommitAsync(); +} +catch (Exception ex) +{ + await transaction.RollbackAsync(); + _logger.LogError(ex, "创建订单失败"); + throw; +} +``` + +### 全局异常处理 + +```csharp +public class GlobalExceptionMiddleware +{ + public async Task InvokeAsync(HttpContext context) + { + try + { + await _next(context); + } + catch (BusinessException ex) + { + await HandleBusinessExceptionAsync(context, ex); + } + catch (Exception ex) + { + _logger.LogError(ex, "系统异常"); + await HandleSystemExceptionAsync(context, ex); + } + } +} +``` + +## Testing Strategy + +### 测试框架 + +- 单元测试:xUnit + Moq +- 属性测试:FsCheck +- 集成测试:WebApplicationFactory + +### 单元测试 + +单元测试用于验证具体的业务逻辑和边界条件: + +1. **服务层测试**:验证业务逻辑正确性 +2. **边界条件测试**:验证错误处理逻辑 +3. **数据验证测试**:验证参数验证逻辑 + +### 属性测试 + +属性测试用于验证通用属性在各种输入下都成立: + +```csharp +/// +/// Property 1: 列表查询过滤正确性 +/// **Feature: miniapp-api, Property 1: 列表查询过滤正确性** +/// **Validates: Requirements 1.1, 1.2, 1.3, 3.2, 10.1, 15.1** +/// +[Property(MaxTest = 100)] +public Property BannerListOnlyReturnsEnabledRecords() +{ + return Prop.ForAll( + Arb.From>(), + banners => + { + // Arrange: 设置测试数据 + // Act: 调用服务方法 + // Assert: 验证返回结果只包含Status=1的记录 + }); +} + +/// +/// Property 3: 分页查询一致性 +/// **Feature: miniapp-api, Property 3: 分页查询一致性** +/// **Validates: Requirements 6.1, 7.1, 12.1, 13.5, 16.4** +/// +[Property(MaxTest = 100)] +public Property PaginationReturnsCorrectCount() +{ + return Prop.ForAll( + Arb.From().Filter(x => x > 0 && x <= 100), + Arb.From().Filter(x => x > 0 && x <= 50), + (page, pageSize) => + { + // 验证分页返回的记录数不超过pageSize + }); +} + +/// +/// Property 7: 提现余额一致性 +/// **Feature: miniapp-api, Property 7: 提现余额一致性** +/// **Validates: Requirements 13.1** +/// +[Property(MaxTest = 100)] +public Property WithdrawDeductsCorrectAmount() +{ + return Prop.ForAll( + Arb.From().Filter(x => x >= 1 && x <= 10000), + Arb.From().Filter(x => x >= 1 && x <= 10000), + (balance, withdrawAmount) => + { + // 验证提现后余额 = 提现前余额 - 提现金额 + }); +} +``` + +### 集成测试 + +集成测试用于验证API端到端的正确性: + +```csharp +public class HomeControllerTests : IClassFixture> +{ + [Fact] + public async Task GetBannerList_ReturnsOnlyEnabledBanners() + { + // Arrange + var client = _factory.CreateClient(); + + // Act + var response = await client.GetAsync("/api/home/getBannerList"); + + // Assert + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync>>(); + Assert.Equal(0, result.Code); + } +} +``` + +### 测试覆盖要求 + +| 测试类型 | 覆盖范围 | 最低要求 | +|----------|----------|----------| +| 单元测试 | 服务层方法 | 80% | +| 属性测试 | 核心业务属性 | 10个属性 | +| 集成测试 | API接口 | 所有28个接口 | + +### 关键测试场景 + +| 场景 | 测试点 | +|------|--------| +| 订单创建 | 测评订单、规划订单、使用邀请码、事务回滚 | +| 提交答案 | 完整答案、部分答案、重复提交、权限验证 | +| 申请提现 | 余额充足、余额不足、最低金额、非整数金额 | +| 分页查询 | 首页、末页、空数据、超出范围 | +| 认证授权 | 无Token、过期Token、无效Token | diff --git a/.kiro/specs/miniapp-api/requirements.md b/.kiro/specs/miniapp-api/requirements.md new file mode 100644 index 0000000..49d586e --- /dev/null +++ b/.kiro/specs/miniapp-api/requirements.md @@ -0,0 +1,200 @@ +# Requirements Document + +## Introduction + +本文档定义了学业邑规划(MiAssessment)微信小程序后端API的开发需求。系统基于多元智能理论,提供学业规划测评服务,包含首页展示、测评流程、订单管理、学业规划预约、分销系统等核心功能模块。 + +技术栈:.NET 10 Web API (C#) + SQL Server 2022 + Entity Framework Core + Redis + +## Glossary + +- **API_System**: 小程序后端API系统,负责处理所有小程序端的请求 +- **Home_Module**: 首页模块,提供Banner、测评入口、宣传图等首页内容 +- **Assessment_Module**: 测评模块,处理测评介绍、题目获取、答案提交、结果查询等 +- **Order_Module**: 订单模块,处理订单创建、支付、查询等 +- **Planner_Module**: 规划师模块,提供规划师列表和预约功能 +- **Invite_Module**: 分销模块,处理邀请、佣金、提现等分销业务 +- **System_Module**: 系统模块,提供协议、隐私政策、关于我们等系统配置 +- **Team_Module**: 团队模块,提供团队介绍内容 +- **Business_Module**: 业务详情模块,提供业务介绍页内容 +- **User**: 小程序用户 +- **Partner**: 合伙人用户,拥有邀请下级和获取佣金的权限 +- **Invite_Code**: 邀请码,合伙人用于免费测评的凭证 + +## Requirements + +### Requirement 1: 首页模块 (Home_Module) + +**User Story:** As a 用户, I want to 查看首页内容, so that I can 了解平台信息并快速进入测评流程。 + +#### Acceptance Criteria + +1. WHEN 用户请求Banner列表 THEN THE Home_Module SHALL 返回所有启用状态的Banner记录,按Sort降序排列 +2. WHEN 用户请求测评入口列表 THEN THE Home_Module SHALL 返回所有未删除的测评类型,包含状态信息(已上线/即将上线) +3. WHEN 用户请求宣传图列表 THEN THE Home_Module SHALL 返回首页位置(Position=1)且启用状态的宣传图 +4. THE Home_Module SHALL 对所有首页接口不要求用户登录认证 + +### Requirement 2: 业务详情模块 (Business_Module) + +**User Story:** As a 用户, I want to 查看业务详情页, so that I can 了解具体业务介绍并参与业务流程。 + +#### Acceptance Criteria + +1. WHEN 用户请求业务详情 THEN THE Business_Module SHALL 根据ID返回业务页面内容,包含背景图和参与按钮配置 +2. THE Business_Module SHALL 对业务详情接口不要求用户登录认证 + +### Requirement 3: 测评模块 - 测评介绍与题目 (Assessment_Module) + +**User Story:** As a 用户, I want to 获取测评介绍和题目, so that I can 了解测评内容并完成答题。 + +#### Acceptance Criteria + +1. WHEN 用户请求测评介绍 THEN THE Assessment_Module SHALL 根据typeId返回测评类型的介绍内容和价格 +2. WHEN 已登录用户请求题目列表 THEN THE Assessment_Module SHALL 根据typeId返回所有启用的题目,按QuestionNo排序 +3. THE Assessment_Module SHALL 对测评介绍接口不要求登录,对题目列表接口要求登录认证 + +### Requirement 4: 测评模块 - 答案提交与结果 (Assessment_Module) + +**User Story:** As a 用户, I want to 提交测评答案并查看结果, so that I can 获得测评报告。 + +#### Acceptance Criteria + +1. WHEN 已登录用户提交测评答案 THEN THE Assessment_Module SHALL 验证记录归属当前用户,保存答案并更新记录状态为"生成中" +2. WHEN 已登录用户查询报告状态 THEN THE Assessment_Module SHALL 返回测评记录的当前状态和是否完成标识 +3. WHEN 已登录用户请求测评结果 THEN THE Assessment_Module SHALL 验证记录归属且已完成,返回完整的报告数据结构 +4. IF 用户提交的答案数量与题目数量不匹配 THEN THE Assessment_Module SHALL 返回错误提示 +5. IF 用户请求的测评记录不属于当前用户 THEN THE Assessment_Module SHALL 返回无权限错误 + +### Requirement 5: 测评模块 - 邀请码验证 (Assessment_Module) + +**User Story:** As a 用户, I want to 使用邀请码免费测评, so that I can 无需支付即可完成测评。 + +#### Acceptance Criteria + +1. WHEN 用户提交邀请码验证请求 THEN THE Assessment_Module SHALL 检查邀请码是否存在且未使用 +2. IF 邀请码不存在 THEN THE Assessment_Module SHALL 返回"邀请码有误,请重新输入" +3. IF 邀请码已被使用 THEN THE Assessment_Module SHALL 返回"邀请码已被使用" +4. WHEN 邀请码验证通过 THEN THE Assessment_Module SHALL 返回邀请码ID供后续订单使用 + +### Requirement 6: 测评模块 - 往期测评 (Assessment_Module) + +**User Story:** As a 用户, I want to 查看往期测评记录, so that I can 回顾历史测评结果。 + +#### Acceptance Criteria + +1. WHEN 已登录用户请求往期测评列表 THEN THE Assessment_Module SHALL 返回该用户的测评记录,支持分页 +2. THE Assessment_Module SHALL 返回测评记录的状态(生成中/已完成)和基本信息 + +### Requirement 7: 订单模块 - 订单查询 (Order_Module) + +**User Story:** As a 用户, I want to 查看我的订单, so that I can 了解订单状态和详情。 + +#### Acceptance Criteria + +1. WHEN 已登录用户请求订单列表 THEN THE Order_Module SHALL 返回该用户的订单,支持按类型筛选和分页 +2. WHEN 已登录用户请求订单详情 THEN THE Order_Module SHALL 返回订单完整信息,包含关联的测评记录或规划预约 +3. IF 用户请求的订单不属于当前用户 THEN THE Order_Module SHALL 返回无权限错误 + +### Requirement 8: 订单模块 - 订单创建 (Order_Module) + +**User Story:** As a 用户, I want to 创建测评或规划订单, so that I can 购买服务。 + +#### Acceptance Criteria + +1. WHEN 用户创建测评订单 THEN THE Order_Module SHALL 创建订单记录和测评记录,关联用户基本信息 +2. WHEN 用户创建规划订单 THEN THE Order_Module SHALL 创建订单记录和规划预约记录 +3. WHEN 用户使用邀请码创建订单 THEN THE Order_Module SHALL 将订单金额设为0并标记邀请码已使用 +4. IF 创建订单过程中发生错误 THEN THE Order_Module SHALL 回滚所有数据库操作 +5. THE Order_Module SHALL 使用数据库事务确保多表操作的数据一致性 + +### Requirement 9: 订单模块 - 支付流程 (Order_Module) + +**User Story:** As a 用户, I want to 支付订单, so that I can 完成购买流程。 + +#### Acceptance Criteria + +1. WHEN 用户发起支付请求 THEN THE Order_Module SHALL 调用微信支付统一下单接口并返回支付参数 +2. WHEN 用户查询支付结果 THEN THE Order_Module SHALL 返回订单的支付状态 +3. IF 订单已支付或已取消 THEN THE Order_Module SHALL 拒绝重复支付请求 + +### Requirement 10: 规划师模块 (Planner_Module) + +**User Story:** As a 用户, I want to 查看规划师并预约, so that I can 获得学业规划服务。 + +#### Acceptance Criteria + +1. WHEN 用户请求规划师列表 THEN THE Planner_Module SHALL 返回所有启用的规划师,按Sort排序 +2. THE Planner_Module SHALL 对规划师列表接口不要求用户登录认证 +3. WHEN 用户预约规划师 THEN THE Planner_Module SHALL 复用订单创建流程(orderType=2) + +### Requirement 11: 分销模块 - 邀请信息 (Invite_Module) + +**User Story:** As a 合伙人, I want to 查看邀请信息和生成二维码, so that I can 邀请新用户。 + +#### Acceptance Criteria + +1. WHEN 合伙人请求邀请信息 THEN THE Invite_Module SHALL 返回用户邀请码、余额、邀请人数等信息 +2. WHEN 合伙人请求生成二维码 THEN THE Invite_Module SHALL 调用微信小程序码接口生成带参数二维码 +3. THE Invite_Module SHALL 对所有分销接口要求用户登录认证 + +### Requirement 12: 分销模块 - 邀请记录与佣金 (Invite_Module) + +**User Story:** As a 合伙人, I want to 查看邀请记录和佣金, so that I can 了解分销收益。 + +#### Acceptance Criteria + +1. WHEN 合伙人请求邀请记录 THEN THE Invite_Module SHALL 返回直属下级用户列表及贡献佣金,支持分页 +2. WHEN 合伙人请求佣金信息 THEN THE Invite_Module SHALL 返回累计收益、已提现、待提现金额 + +### Requirement 13: 分销模块 - 提现功能 (Invite_Module) + +**User Story:** As a 合伙人, I want to 申请提现, so that I can 获得佣金收益。 + +#### Acceptance Criteria + +1. WHEN 合伙人申请提现 THEN THE Invite_Module SHALL 验证余额充足后创建提现记录并扣减用户余额 +2. IF 提现金额超过可提现余额 THEN THE Invite_Module SHALL 返回"超出待提现金额"错误 +3. IF 提现金额小于最低限额(1元) THEN THE Invite_Module SHALL 返回错误提示 +4. IF 提现金额不是整数 THEN THE Invite_Module SHALL 返回错误提示 +5. WHEN 合伙人请求提现记录 THEN THE Invite_Module SHALL 返回提现记录列表,支持分页 + +### Requirement 14: 系统模块 (System_Module) + +**User Story:** As a 用户, I want to 查看系统配置内容, so that I can 了解用户协议、隐私政策等信息。 + +#### Acceptance Criteria + +1. WHEN 用户请求用户协议 THEN THE System_Module SHALL 从配置表读取并返回用户协议内容 +2. WHEN 用户请求隐私政策 THEN THE System_Module SHALL 从配置表读取并返回隐私政策内容 +3. WHEN 用户请求关于我们 THEN THE System_Module SHALL 从配置表读取并返回关于我们内容和版本号 +4. THE System_Module SHALL 对所有系统配置接口不要求用户登录认证 + +### Requirement 15: 团队模块 (Team_Module) + +**User Story:** As a 用户, I want to 查看团队介绍, so that I can 了解团队信息。 + +#### Acceptance Criteria + +1. WHEN 用户请求团队介绍 THEN THE Team_Module SHALL 返回团队位置(Position=2)的宣传图列表 +2. THE Team_Module SHALL 对团队介绍接口不要求用户登录认证 + +### Requirement 16: API响应规范 + +**User Story:** As a 开发者, I want to 统一的API响应格式, so that I can 方便地处理接口返回。 + +#### Acceptance Criteria + +1. THE API_System SHALL 对所有接口返回统一的JSON响应格式:{code, message, data} +2. WHEN 请求成功 THEN THE API_System SHALL 返回code=0 +3. WHEN 请求失败 THEN THE API_System SHALL 返回非0错误码和错误信息 +4. THE API_System SHALL 对分页接口返回统一的分页响应格式:{list, total, page, pageSize, totalPages} + +### Requirement 17: 认证与授权 + +**User Story:** As a 系统管理员, I want to 保护需要登录的接口, so that I can 确保数据安全。 + +#### Acceptance Criteria + +1. WHEN 未登录用户访问需要认证的接口 THEN THE API_System SHALL 返回未授权错误(code=-1或1002) +2. WHEN 用户Token过期 THEN THE API_System SHALL 返回登录过期错误(code=1003) +3. THE API_System SHALL 使用Bearer Token方式进行认证 diff --git a/.kiro/specs/miniapp-api/tasks.md b/.kiro/specs/miniapp-api/tasks.md new file mode 100644 index 0000000..1e421d3 --- /dev/null +++ b/.kiro/specs/miniapp-api/tasks.md @@ -0,0 +1,268 @@ +# Implementation Plan: 小程序API开发 + +## Overview + +本任务清单将小程序API开发分为8个模块,按P0→P1→P2优先级顺序实现。每个模块包含实体类、DTO、服务接口、服务实现、控制器的开发任务。 + +## Tasks + +- [ ] 1. 项目基础设施搭建 + - [ ] 1.1 创建新增实体类文件 + - 在 `MiAssessment.Model/Entities/` 目录创建 Banner.cs, Promotion.cs, BusinessPage.cs, Planner.cs, PlannerBooking.cs, InviteCode.cs, Commission.cs, Withdrawal.cs + - 配置 `[Table]` 特性映射到数据库表 + - _Requirements: 1.1, 2.1, 10.1, 11.1, 13.1_ + + - [ ] 1.2 创建DTO模型文件 + - 在 `MiAssessment.Model/Models/` 目录按模块创建子目录和DTO类 + - 包含 Home/, Business/, Assessment/, Order/, Planner/, Invite/, System/, Team/ 目录 + - _Requirements: 16.1, 16.4_ + + - [ ] 1.3 更新DbContext注册实体 + - 在 ApiDbContext 中添加新实体的 DbSet 属性 + - _Requirements: 1.1, 2.1, 10.1, 11.1_ + +- [ ] 2. 首页模块 (P0) + - [ ] 2.1 创建 IHomeService 接口 + - 定义 GetBannerListAsync, GetAssessmentListAsync, GetPromotionListAsync 方法 + - _Requirements: 1.1, 1.2, 1.3_ + + - [ ] 2.2 实现 HomeService 服务 + - 实现Banner列表查询,过滤Status=1且未删除,按Sort降序 + - 实现测评类型列表查询,过滤未删除记录 + - 实现宣传图列表查询,过滤Position=1且Status=1 + - _Requirements: 1.1, 1.2, 1.3_ + + - [ ] 2.3 编写 HomeService 属性测试 + - **Property 1: 列表查询过滤正确性** + - **Validates: Requirements 1.1, 1.2, 1.3** + + - [ ] 2.4 创建 HomeController 控制器 + - 实现 GET /api/home/getBannerList + - 实现 GET /api/home/getAssessmentList + - 实现 GET /api/home/getPromotionList + - 所有接口不需要 [Authorize] 特性 + - _Requirements: 1.1, 1.2, 1.3, 1.4_ + + - [ ] 2.5 注册首页模块依赖注入 + - 在 Program.cs 中注册 IHomeService 和 HomeService + - _Requirements: 1.1_ + +- [ ] 3. Checkpoint - 首页模块验证 + - 确保首页模块所有接口可正常调用,返回格式正确 + - 确保所有测试通过,如有问题请询问用户 + +- [ ] 4. 测评模块 (P0) + - [ ] 4.1 创建 IAssessmentService 接口 + - 定义测评介绍、题目列表、答案提交、结果查询、邀请码验证、往期测评等方法 + - _Requirements: 3.1, 3.2, 4.1, 4.2, 4.3, 5.1, 6.1_ + + - [ ] 4.2 实现 AssessmentService - 查询功能 + - 实现 GetIntroAsync: 根据typeId查询测评介绍 + - 实现 GetQuestionListAsync: 根据typeId查询启用题目,按QuestionNo排序 + - 实现 GetResultStatusAsync: 查询测评记录状态 + - 实现 GetHistoryListAsync: 分页查询用户测评记录 + - _Requirements: 3.1, 3.2, 4.2, 6.1, 6.2_ + + - [ ] 4.3 编写测评查询属性测试 + - **Property 2: 列表查询排序正确性** + - **Property 3: 分页查询一致性** + - **Validates: Requirements 3.2, 6.1** + + - [ ] 4.4 实现 AssessmentService - 邀请码验证 + - 实现 VerifyInviteCodeAsync: 验证邀请码存在性和使用状态 + - 返回正确的错误信息(不存在/已使用) + - _Requirements: 5.1, 5.2, 5.3, 5.4_ + + - [ ] 4.5 编写邀请码验证属性测试 + - **Property 6: 邀请码使用一次性** + - **Validates: Requirements 5.1, 5.3, 5.4** + + - [ ] 4.6 实现 AssessmentService - 答案提交 + - 实现 SubmitAnswersAsync: 验证记录归属,保存答案,更新状态 + - 验证答案数量与题目数量匹配 + - _Requirements: 4.1, 4.4_ + + - [ ] 4.7 编写答案提交属性测试 + - **Property 9: 测评答案提交状态变更** + - **Validates: Requirements 4.1, 4.2** + + - [ ] 4.8 实现 AssessmentService - 结果查询 + - 实现 GetResultAsync: 验证记录归属和完成状态,组装报告数据 + - 组装八大智能、个人特质、细分能力等多层嵌套数据 + - _Requirements: 4.3, 4.5_ + + - [ ] 4.9 编写结果查询属性测试 + - **Property 4: 用户数据隔离** + - **Validates: Requirements 4.3, 4.5** + + - [ ] 4.10 创建 AssessmentController 控制器 + - 实现所有7个测评接口 + - getIntro 不需要认证,其他接口需要 [Authorize] + - _Requirements: 3.1, 3.2, 3.3, 4.1, 4.2, 4.3, 5.1, 6.1_ + + - [ ] 4.11 注册测评模块依赖注入 + - _Requirements: 3.1_ + +- [ ] 5. Checkpoint - 测评模块验证 + - 确保测评模块所有接口可正常调用 + - 确保认证逻辑正确(getIntro无需认证,其他需要) + - 确保所有测试通过,如有问题请询问用户 + +- [ ] 6. 订单模块 (P0) + - [ ] 6.1 创建 IOrderService 接口 + - 定义订单列表、详情、创建、支付、支付结果查询方法 + - _Requirements: 7.1, 7.2, 8.1, 9.1, 9.2_ + + - [ ] 6.2 实现 OrderService - 查询功能 + - 实现 GetListAsync: 分页查询用户订单,支持类型筛选 + - 实现 GetDetailAsync: 查询订单详情,关联测评记录或规划预约 + - 实现 GetPayResultAsync: 查询订单支付状态 + - _Requirements: 7.1, 7.2, 7.3, 9.2_ + + - [ ] 6.3 编写订单查询属性测试 + - **Property 3: 分页查询一致性** + - **Property 4: 用户数据隔离** + - **Validates: Requirements 7.1, 7.2, 7.3** + + - [ ] 6.4 实现 OrderService - 订单创建 + - 实现 CreateAsync: 使用事务创建订单和关联记录 + - 支持测评订单(创建assessment_record)和规划订单(创建planner_booking) + - 支持邀请码抵扣(金额设为0,标记邀请码已使用) + - _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5_ + + - [ ] 6.5 编写订单创建属性测试 + - **Property 5: 订单创建完整性** + - **Property 10: 订单事务回滚** + - **Validates: Requirements 8.1, 8.2, 8.3, 8.4** + + - [ ] 6.6 实现 OrderService - 支付功能 + - 实现 PayAsync: 调用已有的PayService发起微信支付 + - 验证订单状态(待支付才能发起支付) + - _Requirements: 9.1, 9.3_ + + - [ ] 6.7 创建 OrderController 控制器 + - 实现所有5个订单接口,全部需要 [Authorize] + - _Requirements: 7.1, 7.2, 8.1, 9.1, 9.2_ + + - [ ] 6.8 注册订单模块依赖注入 + - _Requirements: 7.1_ + +- [ ] 7. Checkpoint - P0核心模块验证 + - 确保首页、测评、订单三个核心模块全部可用 + - 验证完整的测评购买流程:首页→测评介绍→创建订单→支付→答题→查看结果 + - 确保所有测试通过,如有问题请询问用户 + +- [ ] 8. 业务详情模块 (P1) + - [ ] 8.1 创建 IBusinessService 接口和 BusinessService 实现 + - 实现 GetDetailAsync: 根据ID查询业务页面详情 + - _Requirements: 2.1_ + + - [ ] 8.2 创建 BusinessController 控制器 + - 实现 GET /api/business/getDetail,不需要认证 + - _Requirements: 2.1, 2.2_ + + - [ ] 8.3 注册业务详情模块依赖注入 + - _Requirements: 2.1_ + +- [ ] 9. 规划师模块 (P1) + - [ ] 9.1 创建 IPlannerService 接口和 PlannerService 实现 + - 实现 GetListAsync: 查询启用的规划师,按Sort排序 + - _Requirements: 10.1_ + + - [ ] 9.2 编写规划师列表属性测试 + - **Property 1: 列表查询过滤正确性** + - **Property 2: 列表查询排序正确性** + - **Validates: Requirements 10.1** + + - [ ] 9.3 创建 PlannerController 控制器 + - 实现 GET /api/planner/getList,不需要认证 + - _Requirements: 10.1, 10.2_ + + - [ ] 9.4 注册规划师模块依赖注入 + - _Requirements: 10.1_ + +- [ ] 10. 分销模块 (P1) + - [ ] 10.1 创建 IInviteService 接口 + - 定义邀请信息、二维码、邀请记录、佣金、提现等方法 + - _Requirements: 11.1, 11.2, 12.1, 12.2, 13.1, 13.5_ + + - [ ] 10.2 实现 InviteService - 查询功能 + - 实现 GetInfoAsync: 返回用户邀请码、余额、邀请人数 + - 实现 GetQrcodeAsync: 调用微信小程序码接口生成二维码 + - 实现 GetRecordListAsync: 分页查询直属下级用户 + - 实现 GetCommissionAsync: 返回累计收益、已提现、待提现 + - 实现 GetWithdrawListAsync: 分页查询提现记录 + - _Requirements: 11.1, 11.2, 12.1, 12.2, 13.5_ + + - [ ] 10.3 编写分销查询属性测试 + - **Property 3: 分页查询一致性** + - **Validates: Requirements 12.1, 13.5** + + - [ ] 10.4 实现 InviteService - 提现功能 + - 实现 ApplyWithdrawAsync: 验证余额,创建提现记录,扣减余额 + - 验证提现金额≥1元且为整数 + - 使用事务确保数据一致性 + - _Requirements: 13.1, 13.2, 13.3, 13.4_ + + - [ ] 10.5 编写提现属性测试 + - **Property 7: 提现余额一致性** + - **Validates: Requirements 13.1** + + - [ ] 10.6 创建 InviteController 控制器 + - 实现所有6个分销接口,全部需要 [Authorize] + - _Requirements: 11.1, 11.2, 11.3, 12.1, 12.2, 13.1, 13.5_ + + - [ ] 10.7 注册分销模块依赖注入 + - _Requirements: 11.1_ + +- [ ] 11. Checkpoint - P1重要模块验证 + - 确保业务详情、规划师、分销三个模块全部可用 + - 验证分销流程:查看邀请信息→生成二维码→查看邀请记录→申请提现 + - 确保所有测试通过,如有问题请询问用户 + +- [ ] 12. 系统模块 (P2) + - [ ] 12.1 创建 ISystemService 接口和 SystemService 实现 + - 实现 GetAgreementAsync: 从configs表读取用户协议 + - 实现 GetPrivacyAsync: 从configs表读取隐私政策 + - 实现 GetAboutAsync: 从configs表读取关于我们和版本号 + - _Requirements: 14.1, 14.2, 14.3_ + + - [ ] 12.2 编写系统配置属性测试 + - **Property 8: 响应格式一致性** + - **Validates: Requirements 14.1, 14.2, 14.3, 16.1, 16.2, 16.3** + + - [ ] 12.3 创建 SystemController 控制器 + - 实现所有3个系统接口,不需要认证 + - _Requirements: 14.1, 14.2, 14.3, 14.4_ + + - [ ] 12.4 注册系统模块依赖注入 + - _Requirements: 14.1_ + +- [ ] 13. 团队模块 (P2) + - [ ] 13.1 创建 ITeamService 接口和 TeamService 实现 + - 实现 GetInfoAsync: 查询Position=2的宣传图列表 + - _Requirements: 15.1_ + + - [ ] 13.2 编写团队模块属性测试 + - **Property 1: 列表查询过滤正确性** + - **Validates: Requirements 15.1** + + - [ ] 13.3 创建 TeamController 控制器 + - 实现 GET /api/team/getInfo,不需要认证 + - _Requirements: 15.1, 15.2_ + + - [ ] 13.4 注册团队模块依赖注入 + - _Requirements: 15.1_ + +- [ ] 14. Final Checkpoint - 全部模块验证 + - 确保所有28个API接口可正常调用 + - 验证认证逻辑:需要认证的接口返回401,不需要认证的接口正常返回 + - 验证响应格式统一性 + - 确保所有测试通过,如有问题请询问用户 + +## Notes + +- 开发顺序按P0→P1→P2优先级进行 +- 每个模块完成后进行Checkpoint验证 +- 属性测试使用FsCheck框架,每个测试运行100次迭代 +- 所有接口遵循RPC风格,仅使用GET和POST请求 diff --git a/docs/API开发任务清单.md b/docs/API开发任务清单.md new file mode 100644 index 0000000..3ca3b1b --- /dev/null +++ b/docs/API开发任务清单.md @@ -0,0 +1,751 @@ +# 学业邑规划 - 小程序 API 开发任务清单 + +本文档列出了小程序后端 API 的开发任务,按模块和优先级组织。 + +--- + +## 〇、需求与设计图对照验证 + +### 0.1 页面-API 对照表 + +| 页面 | 设计图 | 需求章节 | 所需API | 状态 | +|------|--------|----------|---------|------| +| 首页 | 首页.png | 二、首页 | getBannerList, getAssessmentList, getPromotionList | ✅ 已规划 | +| 团队页 | 团队.png | 四、团队页 | getTeamInfo | ✅ 已规划 | +| 我的页 | 我的-登录页.png | 七、我的页 | getProfile | ✅ 已有 | +| 登录页 | 登录页.png | 七、我的页 | login | ✅ 已有 | +| 个人资料 | 个人资料.png | 八、个人信息页 | getProfile, updateProfile, updateAvatar | ✅ 已有 | +| 测评-信息填写 | 测评-个人信息填写.png | 五.1 基本信息填写 | getIntro, verifyInviteCode, createOrder, pay | ✅ 已规划 | +| 测评-答题 | 测评-题目.png | 五.2 答题页 | getQuestionList, submitAnswers | ✅ 已规划 | +| 测评-生成中 | 测评-等待测评.png | 五.3 测评生成中 | getResultStatus | ✅ 已规划 | +| 测评-结果 | - | 五.4 测评结果页 | getResult | ✅ 已规划 | +| 我的订单 | 我的订单.png | 九、我的订单页 | getOrderList, getOrderDetail | ✅ 已规划 | +| 往期测评 | 往期测评-空状态.png | 十、往期测评页 | getHistoryList | ✅ 已规划 | +| 学业规划-规划师 | 学业规划.png | 六.1 规划师选择 | getPlannerList | ✅ 已规划 | +| 学业规划-预约 | 学业规划2.png | 六.2 规划时间预约 | createOrder (orderType=2), pay | ✅ 已规划 | +| 邀请新用户 | 邀请新用户.png | 十一、邀请新用户 | getInviteInfo, getQrcode, getRecordList, getCommission, applyWithdraw, getWithdrawList | ✅ 已规划 | +| 关于页 | 关于.png | 十二、关于页 | getAbout | ✅ 已规划 | +| 用户协议 | 用户/隐私协议.png | 十三、用户协议 | getAgreement | ✅ 已规划 | +| 隐私政策 | 用户/隐私协议.png | 十三、隐私政策 | getPrivacy | ✅ 已规划 | +| 业务详情页 | 业务详情页.png | 三、介绍详情页 | **需补充** | ⚠️ 缺失 | + +### 0.2 需求功能点验证 + +| 需求点 | 需求描述 | 对应API | 状态 | +|--------|----------|---------|------| +| Banner跳转 | 点击可跳转到指定页面 | getBannerList (含linkType, linkUrl) | ✅ | +| 测评入口状态 | 即将上线提示"该测评暂未开放" | getAssessmentList (含status字段) | ✅ | +| 邀请码验证 | 验证邀请码是否存在/已使用 | verifyInviteCode | ✅ | +| 微信支付 | 拉起微信支付 | createOrder + pay | ✅ | +| 题目未答检测 | 提交时检测未选题目 | 前端逻辑,无需API | ✅ | +| 报告轮询 | 等待报告生成 | getResultStatus | ✅ | +| 保存PDF | 保存测评报告到本地 | getResult (前端生成PDF) | ✅ | +| 订单状态 | 待测评/测评中/已测评/退款 | getOrderList (含status) | ✅ | +| 合伙人权限 | 邀请新用户入口仅合伙人可见 | getProfile (含userLevel) | ✅ | +| 佣金规则 | 40%/30%+10%分成 | 后端计算逻辑 | ✅ | +| 提现规则 | 最低1元,整数 | applyWithdraw | ✅ | +| 联系我们 | 跳转小程序客服 | 前端调用wx.openCustomerServiceChat | ✅ | + +### 0.3 发现的遗漏项 + +#### ⚠️ 需要补充的API + +1. **业务详情页接口** - 需求第三章 + - 接口:`GET /api/business/getDetail?id=1` + - 功能:获取业务介绍页内容(背景长图、是否有参与按钮) + - 来源:Banner跳转到业务详情页 + +2. **发送短信验证码** - 如果支持手机号验证码登录 + - 接口:`POST /api/sms/sendCode` + - 功能:发送短信验证码 + - 说明:当前登录方式为微信授权,如需支持验证码登录则需要 + +### 0.4 已有接口确认(无需开发) + +以下接口在 AuthController/UserController 中已实现: +- `POST /api/login` - 微信登录 ✅ +- `GET /api/user/getProfile` - 获取用户信息 ✅ +- `POST /api/user/updateProfile` - 更新用户信息 ✅ +- `POST /api/user/updateAvatar` - 更新头像 ✅ +- `POST /api/logout` - 退出登录 ✅ +- `POST /api/refresh` - 刷新Token ✅ + +--- + +## 一、开发概述 + +### 1.1 项目位置 +- 控制器:`server/MiAssessment/src/MiAssessment.Api/Controllers/` +- 服务接口:`server/MiAssessment/src/MiAssessment.Core/Interfaces/` +- 服务实现:`server/MiAssessment/src/MiAssessment.Core/Services/` +- 数据模型:`server/MiAssessment/src/MiAssessment.Model/Models/` +- 实体类:`server/MiAssessment/src/MiAssessment.Model/Entities/` + +### 1.2 已完成模块 +| 模块 | 控制器 | 状态 | +|------|--------|------| +| 认证 | AuthController | ✅ 已完成 | +| 用户 | UserController | ✅ 已完成 | +| 地址 | AddressController | ✅ 已完成 | +| 配置 | ConfigController | ✅ 已完成 | +| 支付 | PayController | ✅ 已完成 | +| 通知 | NotifyController | ✅ 已完成 | + +### 1.3 待开发模块 +| 模块 | 控制器 | 优先级 | 接口数 | +|------|--------|--------|--------| +| 首页 | HomeController | P0 | 3 | +| 测评 | AssessmentController | P0 | 7 | +| 订单 | OrderController | P0 | 5 | +| 业务详情 | BusinessController | P1 | 1 | +| 规划师 | PlannerController | P1 | 2 | +| 分销 | InviteController | P1 | 6 | +| 系统 | SystemController | P2 | 3 | +| 团队 | TeamController | P2 | 1 | + +--- + +## 二、代码规范参考 + +### 2.1 控制器模板 +```csharp +[ApiController] +[Route("api")] +public class XxxController : ControllerBase +{ + private readonly IXxxService _xxxService; + private readonly ILogger _logger; + + public XxxController(IXxxService xxxService, ILogger logger) + { + _xxxService = xxxService; + _logger = logger; + } + + /// + /// 接口描述 + /// + [HttpGet("actionName")] + [Authorize] // 需要登录的接口 + public async Task> ActionName([FromQuery] Request request) + { + // 实现 + } +} +``` + +### 2.2 响应格式 +- 成功:`ApiResponse.Success(data, "message")` +- 失败:`ApiResponse.Fail("error message")` +- 未授权:`ApiResponse.Unauthorized()` + +--- + +## 三、开发任务详情 + +### 3.1 首页模块 (HomeController) - P0 + +#### 任务 H-1:获取 Banner 列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/home/getBannerList` | +| 认证 | 否 | +| 数据库表 | banners | +| 实体类 | Banner.cs | +| DTO | BannerDto.cs | +| 服务接口 | IHomeService.GetBannerListAsync() | +| 业务逻辑 | 查询 Status=1 且未删除的记录,按 Sort 降序 | + +#### 任务 H-2:获取测评入口列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/home/getAssessmentList` | +| 认证 | 否 | +| 数据库表 | assessment_types | +| 实体类 | AssessmentType.cs(已存在) | +| DTO | AssessmentTypeDto.cs | +| 服务接口 | IHomeService.GetAssessmentListAsync() | +| 业务逻辑 | 查询未删除的记录,按 Sort 降序 | + +#### 任务 H-3:获取宣传图列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/home/getPromotionList` | +| 认证 | 否 | +| 数据库表 | promotions | +| 实体类 | Promotion.cs | +| DTO | PromotionDto.cs | +| 服务接口 | IHomeService.GetPromotionListAsync() | +| 业务逻辑 | 查询 Position=1, Status=1 且未删除的记录 | + +--- + +### 3.2 业务详情模块 (BusinessController) - P1 + +#### 任务 B-1:获取业务详情 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/business/getDetail?id=1` | +| 认证 | 否 | +| 数据库表 | business_pages(需新建)或复用 banners | +| 实体类 | BusinessPage.cs | +| DTO | BusinessDetailDto.cs | +| 服务接口 | IBusinessService.GetDetailAsync(id) | +| 业务逻辑 | 根据ID获取业务介绍页内容(背景图、是否显示参与按钮、跳转链接) | +| 需求来源 | 需求文档第三章"介绍详情页" | + +**说明**:此接口用于 Banner 跳转到业务介绍页时获取详情内容。 + +--- + +### 3.3 测评模块 (AssessmentController) - P0 + +#### 任务 A-1:获取测评介绍 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/assessment/getIntro?typeId=1` | +| 认证 | 否 | +| 数据库表 | assessment_types | +| DTO | AssessmentIntroDto.cs | +| 服务接口 | IAssessmentService.GetIntroAsync(typeId) | +| 业务逻辑 | 根据 typeId 查询测评类型的介绍内容和价格 | + +#### 任务 A-2:获取题目列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/assessment/getQuestionList?typeId=1` | +| 认证 | 是 | +| 数据库表 | questions | +| 实体类 | Question.cs(已存在) | +| DTO | QuestionDto.cs | +| 服务接口 | IAssessmentService.GetQuestionListAsync(typeId) | +| 业务逻辑 | 根据 typeId 查询启用的题目,按 QuestionNo 排序 | + +#### 任务 A-3:提交测评答案 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/assessment/submitAnswers` | +| 认证 | 是 | +| 数据库表 | assessment_answers, assessment_records | +| 实体类 | AssessmentAnswer.cs, AssessmentRecord.cs | +| 请求模型 | SubmitAnswersRequest.cs | +| 响应模型 | SubmitAnswersResponse.cs | +| 服务接口 | IAssessmentService.SubmitAnswersAsync(userId, request) | +| 业务逻辑 | 1. 验证记录归属当前用户
2. 保存答案到 assessment_answers
3. 更新记录状态为"生成中"
4. 触发报告生成(异步) | + +#### 任务 A-4:查询报告生成状态 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/assessment/getResultStatus?recordId=1` | +| 认证 | 是 | +| 数据库表 | assessment_records | +| DTO | ResultStatusDto.cs | +| 服务接口 | IAssessmentService.GetResultStatusAsync(userId, recordId) | +| 业务逻辑 | 查询记录状态,返回是否完成 | + +#### 任务 A-5:获取测评结果 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/assessment/getResult?recordId=1` | +| 认证 | 是 | +| 数据库表 | assessment_records, assessment_results, report_categories, report_conclusions | +| DTO | AssessmentResultDto.cs(复杂结构) | +| 服务接口 | IAssessmentService.GetResultAsync(userId, recordId) | +| 业务逻辑 | 1. 验证记录归属且已完成
2. 组装完整报告数据 | +| 复杂度 | 高 - 需要组装多层嵌套数据 | + +#### 任务 A-6:验证邀请码 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/assessment/verifyInviteCode` | +| 认证 | 是 | +| 数据库表 | invite_codes | +| 实体类 | InviteCode.cs | +| 请求模型 | VerifyInviteCodeRequest.cs | +| 响应模型 | VerifyInviteCodeResponse.cs | +| 服务接口 | IAssessmentService.VerifyInviteCodeAsync(code) | +| 业务逻辑 | 验证邀请码是否存在且未使用 | + +#### 任务 A-7:获取往期测评列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/assessment/getHistoryList?page=1&pageSize=20` | +| 认证 | 是 | +| 数据库表 | assessment_records, orders | +| DTO | AssessmentHistoryDto.cs | +| 服务接口 | IAssessmentService.GetHistoryListAsync(userId, page, pageSize) | +| 业务逻辑 | 分页查询用户的测评记录 | + +--- + +### 3.4 订单模块 (OrderController) - P0 + +#### 任务 O-1:获取订单列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/order/getList?page=1&pageSize=20&orderType=1` | +| 认证 | 是 | +| 数据库表 | orders | +| 实体类 | Order.cs(已存在) | +| DTO | OrderItemDto.cs | +| 服务接口 | IOrderService.GetListAsync(userId, page, pageSize, orderType) | +| 业务逻辑 | 分页查询用户订单,支持按类型筛选 | + +#### 任务 O-2:获取订单详情 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/order/getDetail?orderId=1` | +| 认证 | 是 | +| 数据库表 | orders, assessment_records, planner_bookings | +| DTO | OrderDetailDto.cs | +| 服务接口 | IOrderService.GetDetailAsync(userId, orderId) | +| 业务逻辑 | 查询订单详情,关联测评记录或规划预约 | + +#### 任务 O-3:创建订单 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/order/create` | +| 认证 | 是 | +| 数据库表 | orders, assessment_records, planner_bookings, invite_codes | +| 请求模型 | CreateOrderRequest.cs | +| 响应模型 | CreateOrderResponse.cs | +| 服务接口 | IOrderService.CreateAsync(userId, request) | +| 业务逻辑 | 1. 创建订单记录
2. 根据类型创建测评记录或规划预约
3. 处理邀请码(如有) | +| 复杂度 | 高 - 涉及多表操作和事务 | + +#### 任务 O-4:发起支付 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/order/pay` | +| 认证 | 是 | +| 数据库表 | orders | +| 请求模型 | PayRequest.cs | +| 响应模型 | PayResponse.cs(微信支付参数) | +| 服务接口 | IOrderService.PayAsync(userId, orderId) | +| 业务逻辑 | 调用微信支付统一下单接口 | +| 依赖 | 已有 PayController/PayService | + +#### 任务 O-5:查询支付结果 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/order/getPayResult?orderId=1` | +| 认证 | 是 | +| 数据库表 | orders | +| DTO | PayResultDto.cs | +| 服务接口 | IOrderService.GetPayResultAsync(userId, orderId) | +| 业务逻辑 | 查询订单支付状态 | + +--- + +### 3.5 规划师模块 (PlannerController) - P1 + +#### 任务 P-1:获取规划师列表 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/planner/getList` | +| 认证 | 否 | +| 数据库表 | planners | +| 实体类 | Planner.cs | +| DTO | PlannerDto.cs | +| 服务接口 | IPlannerService.GetListAsync() | +| 业务逻辑 | 查询启用的规划师,按 Sort 排序 | + +#### 任务 P-2:预约规划 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/planner/book` | +| 认证 | 是 | +| 说明 | 复用订单创建接口,orderType=2 | + +--- + +### 3.6 分销模块 (InviteController) - P1 + +#### 任务 I-1:获取邀请信息 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/invite/getInfo` | +| 认证 | 是 | +| 数据库表 | users | +| DTO | InviteInfoDto.cs | +| 服务接口 | IInviteService.GetInfoAsync(userId) | +| 业务逻辑 | 返回用户邀请码、余额、邀请人数等 | + +#### 任务 I-2:生成邀请二维码 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/invite/getQrcode` | +| 认证 | 是 | +| DTO | QrcodeDto.cs | +| 服务接口 | IInviteService.GetQrcodeAsync(userId) | +| 业务逻辑 | 调用微信小程序码接口生成带参数二维码 | +| 依赖 | 微信 API | + +#### 任务 I-3:获取邀请记录 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/invite/getRecordList?page=1&pageSize=20` | +| 认证 | 是 | +| 数据库表 | users, commissions | +| DTO | InviteRecordDto.cs | +| 服务接口 | IInviteService.GetRecordListAsync(userId, page, pageSize) | +| 业务逻辑 | 查询下级用户列表及贡献佣金 | + +#### 任务 I-4:获取佣金信息 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/invite/getCommission` | +| 认证 | 是 | +| 数据库表 | users | +| DTO | CommissionInfoDto.cs | +| 服务接口 | IInviteService.GetCommissionAsync(userId) | +| 业务逻辑 | 返回累计收益、已提现、待提现 | + +#### 任务 I-5:申请提现 +| 项目 | 内容 | +|------|------| +| 接口 | `POST /api/invite/applyWithdraw` | +| 认证 | 是 | +| 数据库表 | withdrawals, users | +| 实体类 | Withdrawal.cs | +| 请求模型 | ApplyWithdrawRequest.cs | +| 响应模型 | ApplyWithdrawResponse.cs | +| 服务接口 | IInviteService.ApplyWithdrawAsync(userId, amount) | +| 业务逻辑 | 1. 验证余额充足
2. 创建提现记录
3. 扣减用户余额 | + +#### 任务 I-6:获取提现记录 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/invite/getWithdrawList?page=1&pageSize=20` | +| 认证 | 是 | +| 数据库表 | withdrawals | +| DTO | WithdrawRecordDto.cs | +| 服务接口 | IInviteService.GetWithdrawListAsync(userId, page, pageSize) | +| 业务逻辑 | 分页查询用户提现记录 | + +--- + +### 3.7 系统模块 (SystemController) - P2 + +#### 任务 S-1:获取用户协议 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/system/getAgreement` | +| 认证 | 否 | +| 数据库表 | configs | +| DTO | AgreementDto.cs | +| 服务接口 | ISystemService.GetAgreementAsync() | +| 业务逻辑 | 从配置表读取用户协议内容 | + +#### 任务 S-2:获取隐私政策 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/system/getPrivacy` | +| 认证 | 否 | +| 数据库表 | configs | +| DTO | PrivacyDto.cs | +| 服务接口 | ISystemService.GetPrivacyAsync() | +| 业务逻辑 | 从配置表读取隐私政策内容 | + +#### 任务 S-3:获取关于我们 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/system/getAbout` | +| 认证 | 否 | +| 数据库表 | configs | +| DTO | AboutDto.cs | +| 服务接口 | ISystemService.GetAboutAsync() | +| 业务逻辑 | 从配置表读取关于我们内容和版本号 | + +--- + +### 3.8 团队模块 (TeamController) - P2 + +#### 任务 T-1:获取团队介绍 +| 项目 | 内容 | +|------|------| +| 接口 | `GET /api/team/getInfo` | +| 认证 | 否 | +| 数据库表 | promotions | +| DTO | TeamInfoDto.cs | +| 服务接口 | ITeamService.GetInfoAsync() | +| 业务逻辑 | 查询 Position=2 的宣传图列表 | + +--- + +## 四、开发顺序建议 + +### 第一阶段:核心流程 (P0) +1. **首页模块** - 简单,快速完成 + - H-1 Banner 列表 + - H-2 测评入口列表 + - H-3 宣传图列表 + +2. **订单模块** - 支付流程核心 + - O-3 创建订单(最复杂,优先) + - O-1 订单列表 + - O-2 订单详情 + - O-4 发起支付 + - O-5 支付结果 + +3. **测评模块** - 业务核心 + - A-1 测评介绍 + - A-2 题目列表 + - A-6 验证邀请码 + - A-3 提交答案 + - A-4 报告状态 + - A-7 往期列表 + - A-5 测评结果(最复杂) + +### 第二阶段:分销功能 (P1) +4. **规划师模块** + - P-1 规划师列表 + +5. **分销模块** + - I-1 邀请信息 + - I-4 佣金信息 + - I-3 邀请记录 + - I-5 申请提现 + - I-6 提现记录 + - I-2 邀请二维码 + +### 第三阶段:辅助功能 (P2) +6. **系统模块** + - S-1 用户协议 + - S-2 隐私政策 + - S-3 关于我们 + +7. **团队模块** + - T-1 团队介绍 + +--- + +## 五、需要新建的文件清单 + +### 5.1 实体类 (Entities) + +| 文件 | 对应表 | 说明 | +|------|--------|------| +| Banner.cs | banners | 轮播图 | +| Promotion.cs | promotions | 宣传图 | +| Planner.cs | planners | 规划师 | +| PlannerBooking.cs | planner_bookings | 规划预约 | +| InviteCode.cs | invite_codes | 邀请码 | +| Commission.cs | commissions | 佣金记录 | +| Withdrawal.cs | withdrawals | 提现记录 | + +### 5.2 DTO 模型 (Models) + +#### Home 模块 +- `Models/Home/BannerDto.cs` +- `Models/Home/AssessmentTypeDto.cs` +- `Models/Home/PromotionDto.cs` + +#### Assessment 模块 +- `Models/Assessment/AssessmentIntroDto.cs` +- `Models/Assessment/QuestionDto.cs` +- `Models/Assessment/SubmitAnswersRequest.cs` +- `Models/Assessment/SubmitAnswersResponse.cs` +- `Models/Assessment/ResultStatusDto.cs` +- `Models/Assessment/AssessmentResultDto.cs` +- `Models/Assessment/VerifyInviteCodeRequest.cs` +- `Models/Assessment/VerifyInviteCodeResponse.cs` +- `Models/Assessment/AssessmentHistoryDto.cs` + +#### Order 模块 +- `Models/Order/OrderItemDto.cs` +- `Models/Order/OrderDetailDto.cs` +- `Models/Order/CreateOrderRequest.cs` +- `Models/Order/CreateOrderResponse.cs` +- `Models/Order/PayRequest.cs` +- `Models/Order/PayResponse.cs` +- `Models/Order/PayResultDto.cs` + +#### Planner 模块 +- `Models/Planner/PlannerDto.cs` + +#### Invite 模块 +- `Models/Invite/InviteInfoDto.cs` +- `Models/Invite/QrcodeDto.cs` +- `Models/Invite/InviteRecordDto.cs` +- `Models/Invite/CommissionInfoDto.cs` +- `Models/Invite/ApplyWithdrawRequest.cs` +- `Models/Invite/ApplyWithdrawResponse.cs` +- `Models/Invite/WithdrawRecordDto.cs` + +#### System 模块 +- `Models/System/AgreementDto.cs` +- `Models/System/PrivacyDto.cs` +- `Models/System/AboutDto.cs` + +#### Team 模块 +- `Models/Team/TeamInfoDto.cs` + +### 5.3 服务接口 (Interfaces) +- `IHomeService.cs` +- `IAssessmentService.cs` +- `IOrderService.cs`(扩展已有) +- `IPlannerService.cs` +- `IInviteService.cs` +- `ISystemService.cs` +- `ITeamService.cs` + +### 5.4 服务实现 (Services) +- `HomeService.cs` +- `AssessmentService.cs` +- `OrderService.cs`(扩展已有) +- `PlannerService.cs` +- `InviteService.cs` +- `SystemService.cs` +- `TeamService.cs` + +### 5.5 控制器 (Controllers) +- `HomeController.cs` +- `AssessmentController.cs` +- `OrderController.cs` +- `PlannerController.cs` +- `InviteController.cs` +- `SystemController.cs` +- `TeamController.cs` + +--- + +## 六、复杂任务说明 + +### 6.1 创建订单 (O-3) +这是最复杂的接口,需要处理: +1. 测评订单:创建 order + assessment_record +2. 规划订单:创建 order + planner_booking +3. 邀请码处理:验证并标记使用 +4. 事务管理:确保数据一致性 + +```csharp +// 伪代码 +public async Task CreateAsync(int userId, CreateOrderRequest request) +{ + using var transaction = await _dbContext.Database.BeginTransactionAsync(); + try + { + // 1. 创建订单 + var order = new Order { ... }; + + // 2. 根据类型创建关联记录 + if (request.OrderType == 1) // 测评 + { + var record = new AssessmentRecord { ... }; + } + else // 规划 + { + var booking = new PlannerBooking { ... }; + } + + // 3. 处理邀请码 + if (request.InviteCodeId.HasValue) + { + // 标记邀请码已使用 + // 订单金额设为0 + } + + await transaction.CommitAsync(); + return new CreateOrderResponse { ... }; + } + catch + { + await transaction.RollbackAsync(); + throw; + } +} +``` + +### 6.2 获取测评结果 (A-5) +需要组装复杂的嵌套数据结构: +1. 基本信息(来自 assessment_record) +2. 八大智能分析(来自 assessment_result + report_category) +3. 个人特质分析 +4. 40项细分能力 +5. 其他分析模块 + +建议: +- 分步骤查询,避免复杂 JOIN +- 使用 AutoMapper 简化映射 +- 考虑缓存已生成的报告 + +### 6.3 提交测评答案 (A-3) +需要处理: +1. 批量保存答案(80道题) +2. 更新记录状态 +3. 触发报告生成(可异步) + +报告生成逻辑: +1. 根据答案计算各分类得分 +2. 计算排名和星级 +3. 匹配结论内容 +4. 保存到 assessment_result + +--- + +## 七、测试要点 + +### 7.1 单元测试 +- 服务层方法的业务逻辑测试 +- 边界条件测试(空数据、分页边界等) + +### 7.2 集成测试 +- API 端到端测试 +- 数据库事务测试 + +### 7.3 关键测试场景 +| 场景 | 测试点 | +|------|--------| +| 创建订单 | 测评订单、规划订单、使用邀请码 | +| 提交答案 | 完整答案、部分答案、重复提交 | +| 申请提现 | 余额充足、余额不足、最低金额 | +| 分页查询 | 首页、末页、空数据 | + +--- + +## 八、注意事项 + +1. **认证**:需要登录的接口添加 `[Authorize]` 特性 +2. **软删除**:查询时过滤 `IsDeleted = false` +3. **分页**:使用统一的分页响应格式 +4. **日志**:关键操作记录日志 +5. **异常**:使用 try-catch 包装,返回友好错误信息 +6. **事务**:多表操作使用事务 +7. **验证**:参数验证在控制器层完成 + +--- + +## 九、进度跟踪 + +| 任务ID | 任务名称 | 状态 | 负责人 | 完成日期 | +|--------|----------|------|--------|----------| +| H-1 | Banner 列表 | ⬜ 待开发 | | | +| H-2 | 测评入口列表 | ⬜ 待开发 | | | +| H-3 | 宣传图列表 | ⬜ 待开发 | | | +| B-1 | 业务详情 | ⬜ 待开发 | | | +| A-1 | 测评介绍 | ⬜ 待开发 | | | +| A-2 | 题目列表 | ⬜ 待开发 | | | +| A-3 | 提交答案 | ⬜ 待开发 | | | +| A-4 | 报告状态 | ⬜ 待开发 | | | +| A-5 | 测评结果 | ⬜ 待开发 | | | +| A-6 | 验证邀请码 | ⬜ 待开发 | | | +| A-7 | 往期列表 | ⬜ 待开发 | | | +| O-1 | 订单列表 | ⬜ 待开发 | | | +| O-2 | 订单详情 | ⬜ 待开发 | | | +| O-3 | 创建订单 | ⬜ 待开发 | | | +| O-4 | 发起支付 | ⬜ 待开发 | | | +| O-5 | 支付结果 | ⬜ 待开发 | | | +| P-1 | 规划师列表 | ⬜ 待开发 | | | +| I-1 | 邀请信息 | ⬜ 待开发 | | | +| I-2 | 邀请二维码 | ⬜ 待开发 | | | +| I-3 | 邀请记录 | ⬜ 待开发 | | | +| I-4 | 佣金信息 | ⬜ 待开发 | | | +| I-5 | 申请提现 | ⬜ 待开发 | | | +| I-6 | 提现记录 | ⬜ 待开发 | | | +| S-1 | 用户协议 | ⬜ 待开发 | | | +| S-2 | 隐私政策 | ⬜ 待开发 | | | +| S-3 | 关于我们 | ⬜ 待开发 | | | +| T-1 | 团队介绍 | ⬜ 待开发 | | | + +**状态说明**:⬜ 待开发 | 🔄 开发中 | ✅ 已完成 | ❌ 已取消