14 KiB
Design Document
Overview
本设计文档描述了HoneyBox后台管理系统用户管理模块前端迁移的技术方案。该模块将老项目(PHP ThinkPHP + Layui)的用户管理前端页面迁移到新项目(ASP.NET Core + Vue 3 + Element Plus)。
主要工作包括:
- 创建Vue 3前端页面和组件
- 实现API调用层
- 补充缺失的后端API接口
- 实现数据展示和交互功能
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接口定义
// 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接口补充
// 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
后端数据模型补充
// 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
前端错误处理
- 网络错误: 显示"网络连接失败"提示,允许用户重试
- 401未授权: 自动刷新token或跳转登录页
- 403无权限: 显示"没有操作权限"提示
- 业务错误: 显示后端返回的错误消息
- 表单验证错误: 在表单字段下方显示验证错误信息
后端错误处理
- 参数验证失败: 返回400状态码和验证错误详情
- 资源不存在: 返回404状态码和"用户不存在"消息
- 业务规则违反: 返回业务错误码和描述消息
- 服务器错误: 返回500状态码和通用错误消息
Testing Strategy
单元测试
-
前端组件测试
- 测试搜索表单组件的参数收集
- 测试对话框组件的表单验证
- 测试表格组件的数据渲染
-
后端服务测试
- 测试UserBusinessService的各个方法
- 测试数据查询和计算逻辑
属性测试
使用属性测试验证以下属性:
- 搜索参数传递正确性
- 分页参数传递正确性
- 资金变动参数验证
- 盈亏计算正确性
- API响应格式一致性
集成测试
-
API集成测试
- 测试完整的API请求-响应流程
- 测试权限验证
-
端到端测试
- 测试用户列表页面的完整功能流程
- 测试资金变动的完整操作流程