HaniBlindBox/.kiro/specs/user-management-frontend/design.md
2026-01-17 17:48:43 +08:00

501 lines
14 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.

# Design Document
## Overview
本设计文档描述了HoneyBox后台管理系统用户管理模块前端迁移的技术方案。该模块将老项目PHP ThinkPHP + Layui的用户管理前端页面迁移到新项目ASP.NET Core + Vue 3 + Element Plus
主要工作包括:
1. 创建Vue 3前端页面和组件
2. 实现API调用层
3. 补充缺失的后端API接口
4. 实现数据展示和交互功能
## Architecture
### 前端架构
```
admin-web/src/
├── api/
│ └── business/
│ └── user.ts # 用户管理API
├── views/
│ └── business/
│ └── user/
│ ├── index.vue # 用户列表主页面
│ ├── components/
│ │ ├── UserSearchForm.vue # 搜索表单组件
│ │ ├── UserTable.vue # 用户表格组件
│ │ ├── MoneyChangeDialog.vue # 资金变动对话框
│ │ ├── GiftCouponDialog.vue # 赠送优惠券对话框
│ │ ├── GiftCardDialog.vue # 赠送卡牌对话框
│ │ ├── UserBoxDialog.vue # 用户盒柜对话框
│ │ ├── UserOrderDialog.vue # 用户订单对话框
│ │ ├── UserTeamDialog.vue # 下级用户对话框
│ │ ├── MoneyDetailDialog.vue # 流水明细对话框
│ │ └── IpLogDialog.vue # IP登录历史对话框
│ ├── profit-loss.vue # 用户盈亏统计页面
│ ├── vip.vue # VIP等级管理页面
│ ├── invite-stats.vue # 用户邀请统计页面
│ └── login-stats.vue # 用户登录统计页面
└── router/
└── modules/
└── business.ts # 业务模块路由
```
### 后端架构
```
HoneyBox.Admin.Business/
├── Controllers/
│ └── UserController.cs # 用户管理控制器补充API
├── Services/
│ ├── UserBusinessService.cs # 用户业务服务(补充方法)
│ └── Interfaces/
│ └── IUserBusinessService.cs
└── Models/
└── User/
├── UserModels.cs # 用户相关模型
├── UserBoxModels.cs # 用户盒柜模型(新增)
├── UserOrderModels.cs # 用户订单模型(新增)
├── MoneyDetailModels.cs # 流水明细模型(新增)
└── StatsModels.cs # 统计相关模型(新增)
```
## Components and Interfaces
### 前端API接口定义
```typescript
// api/business/user.ts
// 用户列表查询参数
interface UserListQuery {
uid?: string
pid?: string
mobile?: string
nickname?: string
lastLoginIp?: string
startTime?: string
endTime?: string
page: number
pageSize: number
}
// 用户列表响应
interface UserListItem {
id: number
uid: string
nickname: string
headimg: string
mobile: string
money: number
integral: number
money2: number
status: number
istest: number
vipLevel: number
addtime: string
lastLoginTime: string
lastLoginIp: string
pidInfo: { id: number; uid: string; nickname: string } | null
// 消费统计
userHegui: number // 盒柜价值
userAllTotal: number // 总消费
userWeixinTotal: number // 微信支付
userUseMoney: number // 余额支付
userUseIntegral: number // 积分支付
userGoodslistMoney: number // 回收货币
userGoodslistMoney2: number // 发货价值
userGoodslistMoney3: number // 总出货价值
}
// 资金变动请求
interface MoneyChangeRequest {
type: 'money' | 'integral' | 'money2'
action: 'add' | 'sub'
amount: number
remark?: string
}
// 用户盒柜查询参数
interface UserBoxQuery {
userId: number
status?: number
goodslistTitle?: string
goodTitle?: string
startTime?: string
endTime?: string
page: number
pageSize: number
}
// 用户盒柜项
interface UserBoxItem {
goodslistTitle: string
goodslistMoney: number
goodslistPrice: number
goodslistImgurl: string
shangId: number
shangTitle: string
addtime: string
orderId: number
orderNum: string
goodsId: number
goodTitle: string
status: number
fhStatus: number | null
fhRemarks: string | null
}
// 流水明细查询参数
interface MoneyDetailQuery {
userId: number
type?: number
changeType?: 'add' | 'sub'
content?: string
startTime?: string
endTime?: string
page: number
pageSize: number
}
// 流水明细项
interface MoneyDetailItem {
id: number
changeMoney: number
money: number
type: number
content: string
other: string
addtime: string
}
// 用户盈亏列表查询
interface ProfitLossListQuery {
uid?: string
startTime?: string
endTime?: string
page: number
pageSize: number
}
// 用户盈亏项
interface ProfitLossItem {
userId: number
uid: string
nickname: string
headimg: string
mobile: string
money: number
integral: number
money2: number
orderCount: number
orderZheTotal: number
money1: number // RMB支付
money2Pay: number // 钻石支付
useMoney: number // 用户支付金额
fhMoney: number // 发货金额
bbMoney: number // 背包金额
syMoney: number // 剩余达达券
yueMoney: number // 盈亏金额
profitStatus: string // 盈利/亏损
}
// 用户邀请统计项
interface InviteStatsItem {
index: number
userId: number
uid: string
nickname: string
headimg: string
inviteNumber: number
sumOrder: number
sumPrice: number
countMobile: number
info: InviteUserInfo[]
}
// 登录统计数据
interface LoginStatsData {
labels: string[]
values: number[]
totalLogins: number
activeUsers?: number
}
```
### 后端API接口补充
```csharp
// UserController.cs 补充的API
// 获取用户盒柜列表
[HttpGet("{id:int}/box")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserBox(int id, [FromQuery] UserBoxQuery query);
// 获取用户订单列表
[HttpGet("{id:int}/orders")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserOrders(int id, [FromQuery] UserOrderQuery query);
// 获取用户余额流水明细
[HttpGet("{id:int}/money-detail")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserMoneyDetail(int id, [FromQuery] MoneyDetailQuery query);
// 获取用户积分流水明细
[HttpGet("{id:int}/integral-detail")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserIntegralDetail(int id, [FromQuery] MoneyDetailQuery query);
// 获取用户钻石流水明细
[HttpGet("{id:int}/score-detail")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserScoreDetail(int id, [FromQuery] MoneyDetailQuery query);
// 获取用户IP登录历史
[HttpGet("{id:int}/ip-logs")]
[BusinessPermission("user:view")]
Task<IActionResult> GetUserIpLogs(int id, [FromQuery] int page = 1, [FromQuery] int pageSize = 20);
// 获取用户邀请统计
[HttpGet("invite-stats")]
[BusinessPermission("user:view")]
Task<IActionResult> GetInviteStats([FromQuery] InviteStatsQuery query);
// 获取用户登录统计
[HttpGet("login-stats")]
[BusinessPermission("user:view")]
Task<IActionResult> GetLoginStats([FromQuery] LoginStatsQuery query);
// 获取用户盈亏列表
[HttpGet("profit-loss-list")]
[BusinessPermission("user:view")]
Task<IActionResult> GetProfitLossList([FromQuery] ProfitLossListQuery query);
// 绑定用户手机号
[HttpPut("{id:int}/mobile")]
[BusinessPermission("user:edit")]
Task<IActionResult> BindMobile(int id, [FromBody] BindMobileRequest request);
// 重置用户签到数据
[HttpPut("{id:int}/sign-reset")]
[BusinessPermission("user:edit")]
Task<IActionResult> ResetUserSign(int id);
// 清空用户UID
[HttpDelete("{id:int}/uid")]
[BusinessPermission("user:clear")]
Task<IActionResult> ClearUid(int id);
```
## Data Models
### 前端数据模型
用户列表数据流:
```
API Response -> UserListItem[] -> UserTable Component -> Display
```
资金变动数据流:
```
MoneyChangeDialog -> MoneyChangeRequest -> API -> Response -> Refresh List
```
### 后端数据模型补充
```csharp
// UserBoxModels.cs
public class UserBoxQuery
{
public int? Status { get; set; }
public string? GoodslistTitle { get; set; }
public string? GoodTitle { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 20;
}
public class UserBoxItem
{
public string GoodslistTitle { get; set; }
public decimal GoodslistMoney { get; set; }
public decimal GoodslistPrice { get; set; }
public string GoodslistImgurl { get; set; }
public int ShangId { get; set; }
public string ShangTitle { get; set; }
public DateTime Addtime { get; set; }
public int OrderId { get; set; }
public string OrderNum { get; set; }
public int GoodsId { get; set; }
public string GoodTitle { get; set; }
public int Status { get; set; }
public int? FhStatus { get; set; }
public string? FhRemarks { get; set; }
}
// MoneyDetailModels.cs
public class MoneyDetailQuery
{
public int? Type { get; set; }
public string? ChangeType { get; set; }
public string? Content { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 50;
}
public class MoneyDetailItem
{
public int Id { get; set; }
public decimal ChangeMoney { get; set; }
public decimal Money { get; set; }
public int Type { get; set; }
public string Content { get; set; }
public string? Other { get; set; }
public DateTime Addtime { get; set; }
}
// StatsModels.cs
public class LoginStatsQuery
{
public string Type { get; set; } = "day"; // day, week, month
public int? Year { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
public class LoginStatsResponse
{
public List<string> Labels { get; set; }
public List<int> Values { get; set; }
public int TotalLogins { get; set; }
public int? ActiveUsers { get; set; }
}
public class ProfitLossListQuery
{
public string? Uid { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 20;
}
public class ProfitLossItem
{
public int UserId { get; set; }
public string Uid { get; set; }
public string Nickname { get; set; }
public string Headimg { get; set; }
public string Mobile { get; set; }
public decimal Money { get; set; }
public decimal Integral { get; set; }
public decimal Money2 { get; set; }
public int OrderCount { get; set; }
public decimal OrderZheTotal { get; set; }
public decimal Money1 { get; set; }
public decimal Money2Pay { get; set; }
public decimal UseMoney { get; set; }
public decimal FhMoney { get; set; }
public decimal BbMoney { get; set; }
public decimal SyMoney { get; set; }
public decimal YueMoney { get; set; }
public string ProfitStatus { 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* 用户列表搜索请求当管理员输入搜索条件时API调用的查询参数应该与用户输入的搜索条件完全匹配。
**Validates: Requirements 1.2**
### Property 2: 分页参数正确传递
*For any* 分页请求当管理员点击分页控件时API调用的page和pageSize参数应该与用户选择的页码和每页数量一致。
**Validates: Requirements 1.4**
### Property 3: 资金变动参数验证
*For any* 资金变动请求,当操作类型为"扣除"且金额大于用户当前余额时,系统应该返回错误提示而不是执行扣除操作。
**Validates: Requirements 2.3**
### Property 4: 用户状态切换一致性
*For any* 用户状态变更操作封号操作应该将status设为0解封操作应该将status设为1且操作后用户列表应该显示正确的状态。
**Validates: Requirements 3.1, 3.2**
### Property 5: 盈亏计算正确性
*For any* 用户盈亏数据,盈亏金额应该等于:用户支付金额 - 发货金额 - 背包金额 - 剩余达达券,且盈亏状态应该根据盈亏金额正负正确显示。
**Validates: Requirements 6.4**
### Property 6: API响应格式一致性
*For any* 后端API响应响应格式应该符合统一的ApiResponse结构{ code: number, message: string, data: T }其中code为0表示成功。
**Validates: Requirements 10.1-10.10**
## Error Handling
### 前端错误处理
1. **网络错误**: 显示"网络连接失败"提示,允许用户重试
2. **401未授权**: 自动刷新token或跳转登录页
3. **403无权限**: 显示"没有操作权限"提示
4. **业务错误**: 显示后端返回的错误消息
5. **表单验证错误**: 在表单字段下方显示验证错误信息
### 后端错误处理
1. **参数验证失败**: 返回400状态码和验证错误详情
2. **资源不存在**: 返回404状态码和"用户不存在"消息
3. **业务规则违反**: 返回业务错误码和描述消息
4. **服务器错误**: 返回500状态码和通用错误消息
## Testing Strategy
### 单元测试
1. **前端组件测试**
- 测试搜索表单组件的参数收集
- 测试对话框组件的表单验证
- 测试表格组件的数据渲染
2. **后端服务测试**
- 测试UserBusinessService的各个方法
- 测试数据查询和计算逻辑
### 属性测试
使用属性测试验证以下属性:
- 搜索参数传递正确性
- 分页参数传递正确性
- 资金变动参数验证
- 盈亏计算正确性
- API响应格式一致性
### 集成测试
1. **API集成测试**
- 测试完整的API请求-响应流程
- 测试权限验证
2. **端到端测试**
- 测试用户列表页面的完整功能流程
- 测试资金变动的完整操作流程