菇太帷i Lv4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
在对“风控中枢平台”项目进行系统改造和新功能开发时,请严格遵循以下前端实现标准和规范:  

1. **架构与模块划分**:
* 遵循 Umi Max 的约定式路由和文件组织结构,确保路由清晰、可维护。
* 将大型模块(如客户管理、审批管理、系统管理)拆分为独立的子目录,并在每个子目录下管理其页面、组件、模型(如果使用 Umi Dva/Model)和Service层代码。
* 通用组件(如列表查询表单、表格工具栏、通用弹窗表单)应抽象到 `src/components/` 目录下,实现高复用性。

1. **UI/UX 规范(基于 Ant Design)**:
* **一致性**:所有页面和组件应严格遵循 Ant Design 官方设计规范和组件使用方式,确保视觉和交互风格统一。
* **通用查询与分页**:
* 所有列表页的查询条件默认为模糊查询,并自动去除首尾空格。
* 所有列表分页选项必须包含:10, 20, 50, 100, 200, 500 条/页,默认每页显示 20 条。
* 翻页时,页面标题应固定相对高度。
* **数据展示**:
* 所有金额字段必须带有单位(如“元”),0 值显示为“0.00”,并使用标准的金额样式(如“123,456.00”)。
* 所有时间字段,如果没有值则显示为“/”,并精确到年月日时分秒。
* **交互反馈**:
* 所有表单提交前必须进行前端校验。
* 所有与后端交互的操作(如提交、加载数据)必须有明确的加载状态(Loading)和反馈提示(使用 Ant Design 的 `message` 或 `notification` 组件)。

3. **数据管理与状态流**:
* 优先使用 Umi Max 提供的状态管理方案(如 Umi Dva/Model 或 Zustand 等),确保数据流清晰可追踪。
* 所有列表数据应支持分页、排序(如 PRO 文档未明确,可采用默认排序或根据业务需求预留)。
* 与后端接口交互时,统一封装请求服务,处理请求/响应拦截、错误处理等逻辑。

4. **Mock 数据集成**:
* 为所有接口(登录、客户管理、审批管理、系统管理等)设计并实现符合 PRO 文档数据结构的 Mock 数据。
* Mock 数据文件应位于 `mock/` 目录下,并确保 Umi Max Dev Server 能正确加载和响应。
* 开发阶段优先使用 Mock 数据进行前端功能验证,确保前后端分离开发的高效性。

5. **性能与体验**:
* 考虑组件的按需加载,优化首屏加载速度。
* 实现响应式设计,确保平台在不同屏幕尺寸下均能良好显示。
* 避免不必要的重渲染,提升页面流畅度。

6. **可扩展性与维护性**:
* 代码应遵循 TypeScript 规范,严格定义接口和类型。
* 注重代码的可读性和注释,关键业务逻辑应有清晰的注释说明。
* 组件化思维:将页面拆分成更小的、可复用的组件。

**请在开始具体模块的实现前,确认你已充分理解并准备好遵循上述所有规范。**

修改密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
FR-ID: FR-AUTH-003  

功能点名称: 修改密码

来源: 顶部菜单栏 -> 右上角头像下拉选项 -> 修改密码

用户故事 (User Story):
- 作为 已登录的平台用户
- 我想要 修改我的账户登录密码
- 以便于 增强账户的安全性

验收标准:
1. 用户点击顶部菜单栏右上角头像下拉选项中的"修改密码"按钮,弹出修改密码弹窗
2. 弹窗标题为"修改密码",包含以下字段:
- 原密码(必填,密码输入框)
- 新密码(必填,密码输入框)
- 确认新密码(必填,密码输入框)
3. 表单验证规则:
- 原密码:不能为空
- 新密码:长度不少于6位字符
- 确认新密码:必须与新密码完全一致
- 新密码不能与原密码相同
4. 点击"确认"按钮后:
- 表单验证通过:调用API修改密码
- API调用成功:显示"密码修改成功,请重新登录",关闭弹窗,跳转到登录页
- API调用失败:显示具体错误信息(如"原密码错误")
5. 点击"取消"按钮或弹窗关闭按钮:关闭弹窗,不执行任何操作
6. 错误提示信息:
- 原密码为空:"请输入原密码"
- 新密码长度不足:"新密码长度不能少于6位"
- 确认密码不一致:"两次输入的密码不一致"
- 新旧密码相同:"新密码不能与原密码相同"
- 原密码错误:"原密码错误,请重新输入"

UI组件/元素建议 (Ant Design 5.x):
- Dropdown, Menu(头像下拉菜单)
- Modal(弹窗容器,width: 400px)
- Form, Form.Item(表单容器和表单项)
- Input.Password(原密码、新密码、确认新密码输入框)
- Button(确认按钮 type="primary",取消按钮 type="default")
- Space(按钮间距)

数据交互 (Mock/API):
- 请求方式:PUT /api/user/password
- 请求体:
```json
{
"oldPassword": "string",
"newPassword": "string",
"confirmNewPassword": "string"
}
```
- 响应格式:
```json
{
"success": boolean,
"message": "string",
"data": null
}
```
- Mock数据响应示例:
- 成功:`{ "success": true, "message": "密码修改成功", "data": null }`
- 原密码错误:`{ "success": false, "message": "原密码错误", "data": null }`
- 系统错误:`{ "success": false, "message": "系统错误,请稍后重试", "data": null }`

技术实现要点:
1. 使用 Umi Max + TypeScript + Ant Design 5.x
2. 表单验证使用 Ant Design Form 的内置验证
3. 密码修改成功后清除本地存储的用户信息并跳转登录页
4. 遵循企业级UI标准,确保响应式设计
5. 添加适当的loading状态和错误处理

前置条件: 用户已登录系统

测试要点:
6. 验证所有表单验证规则是否正确触发
7. 验证API调用的成功和失败场景
8. 验证密码修改成功后的页面跳转
9. 验证弹窗的打开和关闭交互
10. 验证响应式布局在不同屏幕尺寸下的表现

根据上述描述改造项目的功能点,达到完美实现功能PRO文档对应的功能点

退出登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
FR-ID: FR-AUTH-004  

功能点名称: 退出登录

来源: 顶部菜单栏 -> 右上角头像下拉选项 -> 退出登录

用户故事 (User Story):

    *   作为 已登录的平台用户

    *   我想要 安全地退出我的账户

    *   以便于 保护我的账户信息不被未经授权访问

验收标准:

    *   用户点击顶部菜单栏右上角头像下拉选项中的“退出登录”.

    *   系统清除客户端存储的用户会话信息.

    *   系统将用户重定向到登录页面.

UI组件/元素建议 (Ant Design):

    *   Dropdown, Menu.

    *   Button.

数据交互 (Mock/API):

    *   前端发送: POST /api/logout

    *   后端响应: { success: boolean }

前置条件: 用户已登录.

备注/特殊逻辑: 无。


后续不需要创建测试页面了

客户管理列表查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
请实现客户管理模块的列表查询功能,严格遵循以下技术规范和业务需求:  

## 功能需求 (FR-CUST-001)

**功能点名称**: 客户管理列表查询
**来源**: 客户管理列表页面 (`src/pages/Customer/List/index.tsx`)

### 用户故事
- 作为 平台运营人员
- 我想要 根据公司名称、合作状态、开户状态和所属业务员查询客户列表
- 以便于 快速筛选和定位特定的客户信息

### 验收标准

#### 1. 查询表单设计
- **查询区域**: 包含4个查询项:公司名称、合作状态、开户状态、所属业务员
- **布局**: 使用响应式布局,查询表单在列表上方,支持收起/展开
- **按钮**: 查询按钮(type="primary")、重置按钮(type="default")

#### 2. 查询字段规格
- **公司名称**:
- 组件:Select with showSearch
- 支持模糊查询(filterOption)
- 默认值:"全部"
- 数据来源:从客户列表数据中提取唯一公司名称
- placeholder: "请选择公司名称"

- **合作状态**:
- 组件:Select
- 选项:全部、未开始、合作中、已终止
- 默认值:"全部"
- 枚举值:'', 'not_started', 'cooperating', 'terminated'

- **开户状态**:
- 组件:Select
- 选项:全部、待发起、待审批、审批通过、审批拒绝
- 默认值:"全部"
- 枚举值:'', 'pending_initiate', 'pending_approval', 'approved', 'rejected'

- **所属业务员**:
- 组件:Select with showSearch
- 支持模糊查询
- 默认值:"全部"
- 数据来源:从客户列表数据中提取唯一业务员信息
- placeholder: "请选择业务员"

#### 3. 交互逻辑
- **查询按钮**: 触发API请求,更新列表数据,显示loading状态
- **重置按钮**: 清空所有查询条件,重置为默认状态,重新加载列表
- **自动查询**: 表单字段变化时不自动查询,需点击查询按钮
- **查询历史**: 保持查询条件在页面刷新后仍然有效(可选)

### 技术实现要求

#### 1. 文件结构
```
src/pages/Customer/
├── List/
│ ├── index.tsx # 主列表页面
│ ├── components/
│ │ ├── SearchForm.tsx # 查询表单组件
│ │ └── CustomerTable.tsx # 客户列表表格组件
│ └── types.ts # TypeScript类型定义
```

#### 2. API接口规范
- **请求方式**: GET /api/customers
- **查询参数**:
```typescript
interface CustomerQueryParams {
companyName?: string;
cooperationStatus?: string;
accountStatus?: string;
salesman?: string;
page?: number;
pageSize?: number;
}
```
- **响应格式**:
```typescript
interface CustomerListResponse {
success: boolean;
data: {
list: Customer[];
total: number;
page: number;
pageSize: number;
};
message?: string;
}
```

#### 3. 数据模型
```typescript
interface Customer {
id: string;
companyName: string;
cooperationStatus: 'not_started' | 'cooperating' | 'terminated';
accountStatus: 'pending_initiate' | 'pending_approval' | 'approved' | 'rejected';
salesman: string;
salesmanId: string;
contactPerson: string;
contactPhone: string;
createTime: string;
updateTime: string;
}
```

#### 4. UI组件要求 (Ant Design 5.x)
- **Form**: 查询表单容器,layout="inline"或自定义响应式布局
- **Form.Item**: 表单项容器,正确的label和name属性
- **Select**: 下拉选择框,支持showSearch、filterOption、placeholder
- **Button**: 查询和重置按钮,正确的type和loading状态
- **Space**: 按钮间距控制

#### 5. Mock数据要求
- 在 `mock/customerAPI.ts` 中实现Mock接口
- 提供至少20条测试数据,包含各种状态组合
- 支持查询参数过滤逻辑
- 支持分页参数处理

#### 6. 状态管理
- 使用React hooks管理组件状态
- 查询条件状态独立管理
- Loading状态正确显示
- 错误处理和用户提示

### 遵循项目规范
- **代码规范**: 严格使用TypeScript,遵循ESLint规则
- **UI规范**: 遵循企业级UI标准,响应式设计
- **分页规范**: 使用项目统一的分页配置 [10,20,50,100,200,500],默认20条
- **查询规范**: 模糊查询使用trim()处理,空值处理
- **错误处理**: 统一的错误提示和异常处理

### 实现步骤建议
1. 先创建TypeScript类型定义
2. 实现Mock数据和API接口
3. 创建查询表单组件
4. 创建客户列表表格组件
5. 集成到主页面并测试
6. 优化用户体验和错误处理

请按照以上规范完整实现客户管理列表查询功能,确保代码质量和用户体验符合项目标准。

客户管理列表展示优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
FR-ID: FR-CUST-002  

功能点名称: 客户管理列表展示优化

来源: 客户管理列表页面 (`src/pages/Customer/List/index.tsx`)

用户故事 (User Story):
- 作为 平台运营人员
- 我想要 在客户管理列表中查看客户的关键信息,并能快速进行编辑操作
- 以便于 高效概览客户状态并进行后续管理操作

验收标准:

1. **列表列配置要求**:
- 必须包含以下列(按顺序):"公司名称"、"法人姓名"、"法人联系方式"、"余额(元)"、"合作状态"、"开户状态"、"所属业务员"、"创建时间"、"操作"
- 所有列都应有合适的宽度设置,确保内容完整显示
- "余额(元)"列需要格式化显示(如:123,456.00 元),并使用醒目颜色
- "合作状态"和"开户状态"使用Tag组件,不同状态显示不同颜色

2. **交互功能要求**:
- 点击"公司名称"可跳转到客户详情页面 (`/customer/detail/{id}`)
- "操作"列包含"编辑"按钮,点击后打开编辑弹窗或跳转到编辑页面
- 表格支持排序功能(至少支持创建时间、余额排序)
- 表格支持状态筛选功能

3. **数据展示要求**:
- 创建时间格式化为 YYYY-MM-DD HH:mm:ss
- 法人联系方式需要脱敏处理(如:138****8000)
- 空值字段显示为 "/"
- 支持响应式布局,在小屏幕设备上正常显示

UI组件/元素建议 (Ant Design 5.x):
- Table(主表格组件,配置scroll、pagination等属性)
- Button(type="link" 用于公司名称链接,type="default" 用于编辑按钮)
- Tag(用于状态显示,配置不同color属性)
- Tooltip(用于长文本内容的悬浮提示)
- Space(用于操作按钮的间距控制)

数据交互 (Mock/API):
- **请求**: GET /api/customers
- **查询参数**: page, pageSize, 以及FR-CUST-001中定义的查询条件
- **响应格式**:
```typescript
{
success: boolean;
data: {
list: Customer[];
total: number;
page: number;
pageSize: number;
};
message?: string;
}
```

技术实现要求:
1. 基于FR-CUST-001已实现的CustomerTable组件进行优化
2. 确保与现有查询功能完全兼容
3. 更新Customer接口,添加legalRepresentative(法人姓名)字段
4. 在Mock数据中补充法人姓名信息
5. 优化表格列配置,确保所有必需列都正确显示
6. 实现公司名称点击跳转功能
7. 完善编辑按钮的交互逻辑

前置条件:
- 用户已登录并访问客户管理列表页面
- FR-CUST-001客户管理列表查询功能已实现

备注/特殊逻辑:
- 此功能是对FR-CUST-001的增强,需要保持向后兼容
- 法人联系方式脱敏规则:手机号显示前3位和后4位,中间用****替代
- 余额显示需要考虑负数情况,负数用红色显示

新增客户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
FR-ID: FR-CUST-003  

功能点名称: 新增客户

来源: 客户管理列表页面 (`src/pages/Customer/List/index.tsx`) -> 新增客户按钮

用户故事 (User Story):
- 作为 平台运营人员
- 我想要 通过表单添加新的客户信息,并能选择立即发起开户审批或仅保存客户资料
- 以便于 拓展客户群体和规范化管理客户资料

验收标准:

1. **弹窗触发与基本信息**:
- 点击客户列表页面的"新增客户"按钮,弹出新增客户Modal弹窗
- 弹窗标题为"新增客户",宽度建议800px,支持拖拽和键盘ESC关闭
- 表单采用垂直布局,字段分组展示,提供清晰的视觉层次

2. **必填字段验证规则**:
- **公司名称**:必填,1-20个字符,不能包含特殊符号,支持中英文
- **法人姓名**:必填,1-20个字符,仅支持中文姓名格式
- **法人联系方式**:必填,严格11位数字手机号格式验证(1开头)
- **法人邮箱**:必填,标准邮箱格式验证(支持常见邮箱后缀)
- **业务场景**:必填,下拉选择(选项:风险评估、合规审查、反欺诈、其他)
- **所在地址**:必填,1-50个字符,支持详细地址格式
- **经营内容**:必填,1-200个字符,使用TextArea组件
- **所属业务员**:必填,下拉选择,数据来源于现有业务员列表

3. **文件上传要求**:
- **营业执照**:必填,仅支持图片格式(jpg, jpeg, png),单文件最大5MB
- **合同文件**:非必填,仅支持PDF格式,单文件最大10MB
- **其他材料**:非必填,支持图片格式,最多上传3个文件,每个最大5MB
- 所有上传组件需要显示上传进度、文件预览和删除功能

4. **操作按钮逻辑**:
- **发起开户审批**按钮(type="primary"):
* 触发完整表单验证,所有必填字段通过后提交
* 调用API创建客户记录,action参数为'submit_for_approval'
* 成功后显示"开户审批已发起"消息,关闭弹窗,刷新客户列表
* 新客户的开户状态为"待审批",合作状态为"未开始"
* 同时在【审批管理-开户审批】模块创建审批记录

- **保存**按钮(type="default"):
* 触发表单验证,仅保存客户基本信息
* 调用API创建客户记录,action参数为'save'
* 成功后显示"客户信息已保存"消息,关闭弹窗,刷新客户列表
* 新客户的开户状态为"待发起",合作状态为"未开始"

- **取消**按钮:关闭弹窗,不保存任何数据,如有未保存内容需二次确认

5. **数据流转逻辑**:
- 发起开户审批后,在【审批管理-开户审批】列表新增一条"待审批"记录
- 审批通过且开通产品后,法人可使用联系方式登录【风盾SaaS平台】
- 默认登录密码规则:法人姓名首字母小写 + 手机号后6位(如:张三 + 13812345678 → zs345678)

技术实现要求:

1. **组件结构**:
- 基于现有的CreateForm组件进行增强(`src/pages/Customer/List/components/CreateForm.tsx`)
- 使用Ant Design 5.x的Modal、Form、Input、Select、Upload等组件
- 表单布局使用Form.Item,合理设置label和验证规则

2. **API接口规范**:
- **请求方式**:POST /api/customers
- **请求体**:
```typescript
interface CreateCustomerRequest {
companyName: string;
legalRepresentative: string;
legalRepresentativePhone: string;
legalRepresentativeEmail: string;
businessScenario: string;
address: string;
businessContent: string;
salesmanId: string;
contractFile?: File;
businessLicense: File;
otherMaterials?: File[];
action: 'submit_for_approval' | 'save';
}
```
- **响应格式**:
```typescript
interface CreateCustomerResponse {
success: boolean;
message: string;
data?: {
customerId: string;
approvalId?: string; // 仅当action为submit_for_approval时返回
};
}
```

3. **表单验证规则**:
- 使用Ant Design Form的rules属性进行前端验证
- 手机号验证:/^1[3-9]\d{9}$/
- 邮箱验证:标准邮箱正则表达式
- 文件上传验证:文件类型、大小、数量限制

4. **Mock数据要求**:
- 在`mock/customerAPI.ts`中实现POST /api/customers接口
- 模拟文件上传处理逻辑
- 根据action参数返回不同的响应
- 模拟业务场景和业务员下拉选项数据

5. **状态管理**:
- 表单提交loading状态
- 文件上传进度显示
- 错误处理和用户友好提示
- 表单重置和数据清理

6. **用户体验优化**:
- 表单字段分组,提供清晰的视觉层次
- 实时表单验证反馈
- 文件上传拖拽支持
- 操作确认和成功反馈

前置条件:
- 用户已登录并访问客户管理列表页面
- FR-CUST-001和FR-CUST-002功能已实现
- 现有CreateForm组件需要根据新需求进行重构

备注/特殊逻辑:
- 此功能需要与【审批管理】模块联动,确保数据一致性
- 法人联系方式和邮箱将作为风盾SaaS平台的登录凭证
- 文件上传需要考虑安全性,进行文件类型和内容验证
- 业务场景选项可能需要根据实际业务需求调整
- 需要考虑表单数据的临时保存和恢复功能

客户详情页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
FR-ID: FR-CUST-004  

功能点名称: 客户详情页面展示

来源: 客户管理列表 -> 点击公司名称

用户故事 (User Story):

    *   作为 平台运营人员

    *   我想要 查看客户的详细信息,并能进行充值、新增产品、终止/恢复合作等操作

    *   以便于 全面管理客户生命周期

验收标准:

    *   客户详情页右上角展示“充值”、“新增产品”、“终止合作(恢复合作)”功能按键.

    *   页面包含5个tab切换:基础信息、开户审批记录、产品信息、充值记录、提现记录.

UI组件/元素建议 (Ant Design):

    *   Button (for 充值, 新增产品, 终止/恢复合作).

    *   Tabs.

数据交互 (Mock/API):

    *   前端发送: GET /api/customers/{id}

    *   后端响应: { data: CustomerDetail }

前置条件: 用户已登录,并访问客户管理列表页面。

备注/特殊逻辑: 各个子功能点在后续详细描述。

客户充值功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
FR-ID: FR-CUST-005  

功能点名称: 客户充值功能

来源: 客户详情页面 -> 右上角"充值"按钮

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 为合作中的客户进行充值操作
* 以便于 客户能够继续使用平台产品和服务

验收标准:

**权限控制:**
* 仅当客户合作状态为"cooperating"(合作中)且有开通的产品时,才允许充值
* 如果客户没有开通产品,点击充值按钮时提示:"请先开通产品"
* 如果客户合作状态不是"合作中",充值按钮应为禁用状态

**弹窗展示:**
* 点击"充值"按钮,弹出充值Modal弹窗,标题为"充值"
* 弹窗宽度建议600px,支持destroyOnClose

**表单字段(只读信息):**
* 公司名称:Input组件,disabled状态,显示客户公司名称
* 法人姓名:Input组件,disabled状态,显示法人姓名
* 法人手机号:Input组件,disabled状态,显示法人联系方式
* 余额:Input组件,disabled状态,显示当前余额(格式:"{amount} 元")

**表单字段(可编辑):**
* 充值方式:Select组件,必填,下拉选项包括:
- bank_transfer: "网银"
- wechat: "微信"
- alipay: "支付宝"
* 充值金额:InputNumber组件,必填,最小值0.01,精度2位小数,后缀"元"
* 赠送金额:InputNumber组件,非必填,最小值0,精度2位小数,后缀"元"
* 充值业务员:Select组件,必填,从【系统管理-成员管理】中获取在职状态为"开启"的成员数据
* 付款凭证:Upload组件,必填,支持图片和文件格式,最大文件数1个,显示上传loading状态
* 充值备注:Input.TextArea组件,非必填,最大长度200字符,显示字符计数

**表单验证规则:**
* 充值金额:必填,数值类型,大于0,错误提示"充值金额需大于0"
* 赠送金额:可选,数值类型,大于等于0,错误提示"赠送金额需大于等于0"
* 充值业务员:必填,错误提示"请选择充值业务员"
* 付款凭证:必填,错误提示"请上传付款凭证"

**操作按钮:**
* "确定"按钮:type="primary",点击时先进行表单验证
* "取消"按钮:type="default",点击时关闭弹窗并重置表单

**操作逻辑:**
* 点击"确定":
1. 表单验证通过后,显示loading状态
2. 调用充值API接口
3. 成功后显示message提示:"充值成功,待审批"
4. 关闭弹窗并重置表单
5. 刷新客户详情数据(更新余额显示)
6. 自动切换到"充值记录"Tab页
7. 在【审批管理-充值审批】中新增一条待审批记录
8. 在【客户详情-充值记录】中新增一条待审批记录
* 点击"取消":关闭弹窗并重置表单,不进行任何数据操作

**数据同步要求:**
* 充值成功后,客户余额应更新为:原余额 + 充值金额 + 赠送金额
* 充值记录应同步到风盾SaaS平台的账单中心
* 审批通过后,充值结果状态更新为"已到账"
* 审批拒绝后,充值结果状态更新为"未到账"

UI组件/元素 (Ant Design 5.x):
* Modal - 充值弹窗容器
* Form, Form.Item - 表单容器和表单项
* Input - 只读信息展示
* InputNumber - 金额输入
* Select - 下拉选择
* Upload - 文件上传
* Button - 操作按钮
* message - 操作反馈提示

数据交互 (Mock/API):
* 请求接口: POST /api/customers/{id}/recharge
* 请求体:
```typescript
{
rechargeMethod: 'bank_transfer' | 'wechat' | 'alipay',
rechargeAmount: number,
giftAmount?: number,
rechargeStaff: string, // 业务员ID
paymentVoucher: File,
rechargeRemark?: string
}
```
* 响应格式:
```typescript
{
success: boolean,
message: string,
data?: {
rechargeId: string,
status: 'pending_approval'
}
}
```

前置条件:
* 用户已登录且有充值权限
* 客户合作状态为"cooperating"(合作中)
* 客户已开通至少一个产品
* 客户开户状态为"approved"(审批通过)

技术实现要求:
* 严格遵循已建立的前端实现标准和规范
* 使用TypeScript进行类型定义
* 实现完整的表单验证和错误处理
* 确保与现有的客户详情页面(FR-CUST-004)无缝集成
* Mock数据应包含完整的业务员列表和充值记录数据

测试要点:
* 权限控制逻辑正确性
* 表单验证完整性
* 文件上传功能
* 数据同步准确性
* 用户交互体验

客户新增产品功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
FR-ID: FR-CUST-006  

功能点名称: 客户新增产品功能

来源: 客户详情页面 -> 右上角"新增产品"按钮

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 为合作中的客户开通新的产品服务
* 以便于 扩展客户可用的服务范围并增加业务收入

验收标准:

**权限控制:**
* 仅当客户合作状态为"cooperating"(合作中)时,才允许新增产品
* 如果客户合作状态不是"合作中",新增产品按钮应为禁用状态
* 点击禁用状态的按钮时提示:"合作状态为合作中后才可新增产品"

**弹窗展示:**
* 点击"新增产品"按钮,弹出新增产品Modal弹窗,标题为"新增产品"
* 弹窗宽度建议600px,支持destroyOnClose

**表单字段:**
* 产品名称:Select组件,必填,下拉选项包括:
- "loan_financial_overdue": "贷款金融探查逾期"
- "loan_sirius_premium": "贷款天狼星至臻版"
- "loan_universal_ziwei": "贷款通用紫微星"
- "lease_sirius_premium": "租赁天狼星至臻版"
- "lease_sirius_standard": "租赁天狼星普通版"
- "lease_universal_ziwei": "租赁通用紫微星"
- "love_guide": "恋爱秘籍"
- "employment_check": "入职检测"
- "universal_ziwei": "通用紫微星"
* 接入方式:Select组件,必填,下拉选项包括:
- "API": "API"
- "platform": "风控平台"
* 计费方式:Select组件,必填,默认值"per_call",禁用状态,显示"按次收费"
* 产品价格(元/次):InputNumber组件,必填,最小值0.01,精度2位小数,后缀"元/次"
* 申请备注:Input.TextArea组件,非必填,最大长度200字符,显示字符计数

**表单验证规则:**
* 产品名称:必填,错误提示"请选择产品名称"
* 接入方式:必填,错误提示"请选择接入方式"
* 产品价格:必填,数值类型,大于0,错误提示"产品价格需大于0"

**操作按钮:**
* "确定"按钮:type="primary",点击时先进行表单验证
* "取消"按钮:type="default",点击时关闭弹窗并重置表单

**操作逻辑:**
* 点击"确定":
1. 表单验证通过后,显示loading状态
2. 调用新增产品API接口
3. 成功后显示message提示:"添加成功,待审批"
4. 关闭弹窗并重置表单
5. 自动切换到"产品信息"Tab页
6. 刷新产品信息列表数据
7. 在【审批管理-产品审批】中新增一条待审批记录
8. 在【客户详情-产品信息】中新增一条记录,状态为"待审批",调用状态默认为"已开启"
* 点击"取消":关闭弹窗并重置表单,不进行任何数据操作

**数据同步要求:**
* 新增产品成功后,产品记录应同步到审批管理系统
* 审批通过后,产品状态更新为"已开通",客户可正常使用该产品
* 审批拒绝后,产品状态更新为"已拒绝"

UI组件/元素 (Ant Design 5.x):
* Modal - 新增产品弹窗容器
* Form, Form.Item - 表单容器和表单项
* Select - 下拉选择
* InputNumber - 价格输入
* Input.TextArea - 备注输入
* Button - 操作按钮
* message - 操作反馈提示

数据交互 (Mock/API):
* 请求接口: POST /api/customers/{id}/products
* 请求体:
```typescript
{
productName: string, // 产品名称枚举值
accessMethod: 'API' | 'platform', // 接入方式
billingMethod: 'per_call', // 计费方式,固定值
price: number, // 产品价格
applyRemark?: string // 申请备注
}
```
* 响应格式:
```typescript
{
success: boolean,
message: string,
data?: {
productId: string,
status: 'pending_approval'
}
}
```

前置条件:
* 用户已登录且有新增产品权限
* 客户合作状态为"cooperating"(合作中)
* 客户开户状态为"approved"(审批通过)

技术实现要求:
* 严格遵循已建立的前端实现标准和规范
* 使用TypeScript进行类型定义
* 实现完整的表单验证和错误处理
* 确保与现有的客户详情页面(FR-CUST-004)和充值功能(FR-CUST-005)无缝集成
* Mock数据应包含完整的产品列表和审批记录数据

测试要点:
* 权限控制逻辑正确性
* 表单验证完整性
* 产品枚举选项正确性
* 数据同步准确性
* Tab页面切换功能
* 用户交互体验

备注/特殊逻辑:
* 产品名称为固定的9个枚举项,不可自定义
* 接入方式只有API和风控平台两种选择
* 计费方式当前只支持按次收费,未来可能扩展其他计费方式
* 产品价格支持小数点后两位,最小值0.01元
* 申请备注为可选字段,用于记录特殊需求或说明

终止/恢复客户合作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
FR-ID: FR-CUST-007  

功能点名称: 终止/恢复客户合作

来源: 客户详情页 -> 终止合作/恢复合作按钮

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 终止或恢复客户的合作关系
* 以便于 管理客户的业务状态和控制商户账号访问权限

验收标准:

**权限控制:**
* 仅当合作状态为"合作中"且开户状态为"审批通过"时,才显示并允许点击"终止合作"按钮
* 当条件不满足时,按钮应为禁用状态,鼠标悬停显示提示"开户审批通过后才可终止"
* 当合作状态为"已终止"时,显示"恢复合作"按钮

**终止合作流程:**
* 点击"终止合作"按钮,使用 Ant Design 的 Popconfirm 组件弹出确认提示:"确定要终止与该客户的合作吗?终止后商户将无法登录风盾SaaS平台。"
* 确认框包含"确定"(danger类型)和"取消"按钮
* 点击"确定"后:
- 发送API请求更新合作状态
- 显示Loading状态
- 成功后:合作状态变更为"已终止",按钮文案变为"恢复合作"
- 显示成功提示:"客户合作已终止,商户账号已禁用"

**恢复合作流程:**
* 点击"恢复合作"按钮,弹出确认提示:"确定要恢复与该客户的合作吗?恢复后商户可正常登录风盾SaaS平台。"
* 点击"确定"后:
- 发送API请求更新合作状态
- 显示Loading状态
- 成功后:合作状态变更为"合作中",按钮文案变为"终止合作"
- 显示成功提示:"客户合作已恢复,商户账号已启用"

**错误处理:**
* API调用失败时,显示具体错误信息
* 网络异常时,显示"网络异常,请稍后重试"

UI组件/元素 (Ant Design 5.x):
* Button组件:根据合作状态动态显示文案和样式
- 终止合作:danger类型,红色按钮
- 恢复合作:primary类型,蓝色按钮
* Popconfirm组件:用于确认操作
* message组件:用于成功/失败提示
* Tooltip组件:用于禁用状态的提示信息

数据交互 (Mock/API):
* **请求接口:** PUT /api/customers/{customerId}/cooperation-status
* **请求参数:**
```typescript
{
status: 'terminated' | 'cooperating',
reason?: string // 可选的操作原因
}
```
* **响应格式:**
```typescript
{
success: boolean,
message: string,
data?: {
customerId: string,
cooperationStatus: 'terminated' | 'cooperating',
updatedAt: string
}
}
```

Mock数据要求:
* 模拟成功和失败场景
* 包含不同客户状态的测试数据
* 响应时间模拟(500-1000ms)

技术实现要求:
* 严格遵循TypeScript类型定义
* 使用Umi Max的请求封装
* 实现乐观更新:先更新UI,API失败时回滚
* 按钮状态管理:loading、disabled等状态
* 与客户详情页其他数据保持同步

前置条件:
* 客户必须存在且数据完整
* 用户具有客户管理权限
* 客户合作状态为"合作中"且开户状态为"审批通过"才能执行终止操作

测试要点:
* 权限控制验证
* 状态变更的UI同步
* 错误场景处理
* 按钮状态切换
* 提示信息准确性

客户基础信息展示与编辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
FR-ID: FR-CUST-008  

功能点名称: 客户基础信息展示与编辑

来源: 客户详情页 -> 基础信息Tab

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 查看和修改客户的基础信息
* 以便于 维护客户资料的准确性和完整性

验收标准:

**信息展示规范:**
* 基础信息字段展示:公司名称、法人姓名、法人联系方式、法人邮箱、业务场景、所在地址、经营内容、所属业务员、合同状态、营业执照、其他材料
* 合同状态为"已上传"时显示"查看合同"链接,为"未上传"时显示"未上传"文本
* "是否允许C端用户查看报告详情"开关根据权限配置展示,默认为关闭状态
* 营业执照和其他材料文件显示为只读状态(置灰不可编辑)
* 所有金额字段格式为"123,456.00 元",时间字段空值显示为"/"

**权限控制:**
* 仅当开户状态为"待发起"或"审批拒绝"时,右上角显示"编辑"按钮
* 当条件不满足时,按钮为禁用状态,鼠标悬停显示提示"仅待发起或审批拒绝状态可编辑"
* 开户状态为"审批通过"时,显示"开发资料"按钮

**编辑模式功能:**
* 点击"编辑"按钮,页面切换为编辑模式,显示表单组件
* 可编辑字段:公司名称、法人姓名、法人联系方式、法人邮箱、业务场景、所在地址、经营内容、合同文件上传、C端报告查看权限开关
* 不可编辑字段:所属业务员(置灰显示)、营业执照、其他材料
* 表单验证规则:
- 公司名称:必填,最大50字符
- 法人姓名:必填,最大20字符
- 法人联系方式:必填,11位手机号格式验证
- 法人邮箱:必填,邮箱格式验证
- 业务场景:必填,最大200字符
- 所在地址:必填,最大100字符
- 经营内容:必填,最大500字符

**操作按钮功能:**
* 编辑模式右上角显示三个按钮:"发起开户审批"、"保存"、"取消"
* "发起开户审批"按钮:
- 触发表单验证,验证通过后提交数据
- 客户信息更新,开户状态变更为"待审批",合作状态变更为"合作中"
- 成功提示:"开户审批已发起,请等待审批结果"
- 页面跳转到开户审批记录Tab
* "保存"按钮:
- 触发表单验证,验证通过后保存数据
- 客户信息更新,开户状态保持"待发起",合作状态保持"未开始"
- 成功提示:"客户信息已保存"
- 退出编辑模式,返回展示模式
* "取消"按钮:
- 不保存任何修改,退出编辑模式
- 表单数据重置为原始值

**业务逻辑:**
* 法人联系方式修改后,该客户需要使用新的手机号登录风盾SaaS平台
* C端报告查看权限开启后,C端用户付费完成后可查看详细报告内容
* 合同文件上传支持PDF、DOC、DOCX格式,最大10MB

UI组件/元素 (Ant Design 5.x):
* Descriptions组件:用于信息展示模式
* Form组件:用于编辑模式
* Button组件:编辑、发起开户审批、保存、取消按钮
* Input、Select、Upload组件:表单输入控件
* Switch组件:C端报告查看权限开关
* Tooltip组件:禁用状态提示信息
* message组件:操作成功/失败提示

数据交互 (Mock/API):
* **获取基础信息**: GET /api/customers/{id}/basic-info
* **更新基础信息**: PUT /api/customers/{id}/basic-info
```typescript
Body: {
companyName?: string,
legalRepresentative?: string,
legalRepresentativePhone?: string,
legalRepresentativeEmail?: string,
businessScenario?: string,
address?: string,
businessContent?: string,
contractFile?: File,
allowCEndUserViewReport?: boolean,
action: 'submit_for_approval' | 'save'
}
```
* **响应格式**:
```typescript
{
success: boolean,
message: string,
data?: {
customerId: string,
accountStatus: string,
cooperationStatus: string,
updatedAt: string
}
}
```

Mock数据要求:
* 模拟成功和失败场景
* 包含表单验证错误的测试数据
* 响应时间模拟(300-800ms)
* 文件上传进度模拟

技术实现要求:
* 严格遵循TypeScript类型定义
* 使用Umi Max的请求封装
* 实现表单数据的双向绑定
* 支持文件上传进度显示
* 与客户详情页其他Tab数据保持同步

前置条件:
* 用户已登录且具有客户管理权限
* 客户数据存在且完整
* 用户已访问客户详情页

测试要点:
* 权限控制验证(不同开户状态下的按钮显示)
* 表单验证规则测试
* 文件上传功能测试
* 数据保存和提交流程测试
* 错误场景处理测试
* 页面状态切换测试

查看开发资料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
FR-ID: FR-CUST-009  

功能点名称: 查看开发资料

来源: 客户详情页 -> 基础信息Tab -> 开发资料按钮

用户故事 (User Story):
* 作为 平台技术人员或运营人员
* 我想要 查看客户的开发资料(测试环境和生产环境接口地址)
* 以便于 进行技术对接或提供技术支持

验收标准:

**按钮显示与权限控制:**
* 开发资料按钮位于基础信息Tab右上角操作区域,在编辑按钮的右侧
* 仅当客户开户状态为"审批通过"时,才显示"开发资料"按钮
* 当开户状态不是"审批通过"时,按钮完全隐藏(不显示禁用状态)
* 按钮样式使用默认类型,图标为FileTextOutlined

**弹窗交互:**
* 点击"开发资料"按钮,弹出Modal弹窗
* 弹窗标题为"开发资料"
* 弹窗宽度为600px,无底部操作按钮(footer设为null)
* 点击弹窗右上角关闭按钮(×)或点击遮罩层空白处,弹窗关闭

**弹窗内容展示:**
* 使用Descriptions组件展示开发资料信息
* 字段包括:
- 测试环境:显示测试环境API接口地址
- 生产环境:显示生产环境API接口地址
* 接口地址使用<code>标签包裹,便于复制
* 所有内容为只读展示,不可编辑

**数据格式要求:**
* 测试环境地址格式:https://api-test.example.com/v1
* 生产环境地址格式:https://api.example.com/v1
* 地址应为完整的可访问URL

UI组件/元素 (Ant Design 5.x):
* Button组件:开发资料按钮
* Modal组件:弹窗容器
* Descriptions组件:信息展示
* 图标:FileTextOutlined

数据交互 (Mock/API):
* **请求接口:** GET /api/customers/{customerId}/developer-materials
* **请求参数:** 无
* **响应格式:**
```typescript
{
success: boolean,
message: string,
data: {
testEnvironment: string,
productionEnvironment: string
}
}
```

Mock数据要求:
* 模拟成功响应场景
* 提供真实格式的API地址示例
* 响应时间模拟(200-500ms)

技术实现要求:
* 严格遵循TypeScript类型定义
* 使用Umi Max的请求封装
* 按钮状态基于客户开户状态动态控制
* 弹窗状态管理使用useState
* 与现有BasicInfo组件集成

前置条件:
* 客户必须存在且数据完整
* 用户具有客户管理权限
* 客户开户状态为"审批通过"

测试要点:
* 权限控制验证(不同开户状态下的按钮显示/隐藏)
* 弹窗打开和关闭交互
* 开发资料数据正确展示
* 接口地址格式验证
* 响应式布局适配

备注/特殊逻辑:
* 开发资料为Mock数据,实际项目中应从后端获取真实的环境配置
* 该功能已在FR-CUST-008的BasicInfo组件中预留了实现位置
* 需要完善现有的handleViewDevMaterial函数和相关Modal内容

客户开户审批记录列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
FR-ID: FR-CUST-010  

功能点名称: 客户开户审批记录列表

来源: 客户详情页 -> 开户审批记录tab

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 查看客户的所有开户审批记录
* 以便于 追溯开户流程和审批结果

验收标准:
* 列表数据来源于新增客户保存并开户审批后,【审批管理-开户审批记录】和【客户详情-开户审批记录】新增的数据
* 列表包含以下字段:
- 公司名称 (companyName)
- 申请时间 (applyTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为 "/"
- 审批人 (approver)
- 审批状态 (approvalStatus) - 枚举值:pending(待审批)、approved(审批通过)、rejected(审批拒绝)
- 审批时间 (approvalTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为 "/"
- 审批备注 (approvalRemark)
* 审批状态为"rejected"时,状态列前面展示红色"❗️"标识,鼠标悬停展示拒绝原因(rejectionReason)
* 表格支持分页,分页选项:[10,20,50,100,200,500],默认20条/页
* 表格头部固定(sticky header)
* 支持按申请时间倒序排列(最新的在前)
* 空数据状态使用 Ant Design Empty 组件

UI组件/元素建议 (Ant Design):
* Table - 主表格组件
* Tooltip - 用于显示拒绝原因
* Empty - 空数据状态
* Pagination - 分页组件

数据交互 (Mock/API):
* 前端发送: GET /api/customers/{customerId}/account-approval-records?page={page}&pageSize={pageSize}
* 后端响应格式:
```typescript
{
success: boolean;
message: string;
data: {
records: ApprovalRecord[];
total: number;
current: number;
pageSize: number;
}
}

interface ApprovalRecord {
id: string;
companyName: string;
applyTime: string;
approver: string;
approvalStatus: 'pending' | 'approved' | 'rejected';
approvalTime: string;
approvalRemark: string;
rejectionReason?: string; // 仅当 approvalStatus 为 'rejected' 时存在
}
```

技术实现要求:
* 使用 TypeScript 严格类型定义
* 组件位置:src/pages/customer/detail/components/AccountApprovalRecords.tsx
* Mock 数据位置:mock/customer.ts
* 遵循 Umi Max 约定式路由和组件规范
* 实现响应式设计,确保在不同屏幕尺寸下正常显示
* 添加适当的 loading 状态和错误处理

前置条件:
* 用户已登录
* 用户已访问客户详情页
* 客户ID有效且存在

测试要点:
* 验证不同审批状态的正确显示
* 验证拒绝状态的红色标识和 Tooltip 功能
* 验证分页功能正常工作
* 验证空数据状态显示
* 验证时间格式显示正确
* 验证响应式布局在不同屏幕尺寸下的表现

备注/特殊逻辑:
* 该组件作为客户详情页的子组件,需要接收 customerId 作为 props
* 审批记录数据与审批管理模块共享,确保数据一致性

客户产品信息列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
FR-ID: FR-CUST-011  

功能点名称: 客户产品信息列表

来源: 客户详情页 -> 产品信息tab

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 查看客户已开通的产品信息,并能进行编辑和启用/禁用操作
* 以便于 管理客户的产品服务状态

验收标准:
* 列表数据来源于客户新增产品后的记录,展示所有产品(包括不同审批状态)
* 列表包含以下字段:
- 产品名称 (productName) - 可点击查看详情,使用Button type="link"
- 接入方式 (accessMethod) - 枚举值:API、风控平台
- 产品价格 (price) - 格式:123.00 元/次
- 产品审批状态 (approvalStatus) - 枚举值:pending_approval(待审批)、approved(审批通过)、rejected(审批拒绝)
- 调用状态 (callStatus) - 枚举值:enabled(已开启)、disabled(已禁用),使用Switch组件
- 更新时间 (updateTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为"/"
- 操作列 - 包含"编辑"按钮
* 调用状态开关规则:
- 仅当产品审批状态为"approved"时才可操作
- 审批通过的产品默认调用状态为"enabled"
- 需要根据用户权限控制,无权限时开关置灰不可操作
- 禁用后该产品不可调用
* 更新时间显示逻辑:
- 首次创建时显示创建时间
- 编辑后显示最后更新时间
* 编辑功能:
- 点击"编辑"按钮弹出Modal编辑弹窗
- 弹窗字段包括:
* 产品名称(只读,置灰显示)
* 接入方式(只读,置灰显示)
* 产品价格(可编辑,InputNumber组件,单位:元/次,必填,最小值0.01)
* 产品审批状态(只读显示)
* 调用状态(Radio.Group组件,选项:开启/禁用,权限控制同列表)
* 操作人(只读显示当前操作用户)
* 审批时间(只读显示)
* 审批记录(只读显示审批备注)
- 弹窗底部按钮:"确定"、"取消"
* 编辑提交逻辑:
- 点击"确定":提交价格和调用状态修改
- 如果价格有变更,需要重新审批,状态变为"待审批"
- 如果仅修改调用状态,立即生效
- 点击"取消":关闭弹窗,不保存修改
* 表格支持分页,分页选项:[10,20,50,100,200,500],默认20条/页
* 表格头部固定(sticky header)
* 空数据状态使用 Ant Design Empty 组件

UI组件/元素建议 (Ant Design):
* Table - 主表格组件
* Switch - 调用状态开关
* Button - 产品名称链接(type="link")、编辑按钮(type="default")
* Modal - 编辑弹窗
* Form, Form.Item - 编辑表单
* InputNumber - 价格输入
* Radio.Group - 调用状态选择
* Tag - 审批状态标签
* Empty - 空数据状态
* Tooltip - 权限提示

数据交互 (Mock/API):
* 前端发送: GET /api/customers/{customerId}/products?page={page}&pageSize={pageSize}
* 后端响应格式:
```typescript
{
success: boolean;
message: string;
data: {
list: ProductInfo[];
total: number;
current: number;
pageSize: number;
}
}

interface ProductInfo {
id: string;
productName: string;
accessMethod: 'API' | 'platform';
price: number;
priceUnit: string; // "元/次"
approvalStatus: 'pending_approval' | 'approved' | 'rejected';
callStatus: 'enabled' | 'disabled';
updateTime: string;
applyRemark?: string;
approveRemark?: string;
operator?: string;
approveTime?: string;
approvalRecord?: string;
}
```

* 编辑产品: PUT /api/customers/{customerId}/products/{productId}
* 请求体:
```typescript
{
price?: number;
callStatus?: 'enabled' | 'disabled';
}
```
* 响应格式:
```typescript
{
success: boolean;
message: string;
data?: {
productId: string;
approvalStatus: string;
updatedAt: string;
}
}
```

技术实现要求:
* 使用 TypeScript 严格类型定义
* 组件位置:src/pages/Customer/Detail/components/ProductList.tsx(更新现有组件)
* Mock 数据位置:mock/customerAPI.ts(扩展现有API)
* 遵循 Umi Max 约定式路由和组件规范
* 实现响应式设计,确保在不同屏幕尺寸下正常显示
* 添加适当的 loading 状态和错误处理
* 权限控制基于用户角色和客户状态

前置条件:
* 用户已登录
* 用户已访问客户详情页
* 客户ID有效且存在
* 客户已有产品记录(通过新增产品功能添加)

测试要点:
* 验证不同审批状态的产品正确显示
* 验证调用状态开关的权限控制和交互
* 验证编辑弹窗的表单验证和提交
* 验证价格修改后的审批状态变化
* 验证分页功能正常工作
* 验证空数据状态显示
* 验证时间格式和价格格式显示正确
* 验证响应式布局在不同屏幕尺寸下的表现

备注/特殊逻辑:
* 该组件需要与现有的ProductList组件集成或替换
* 产品数据与新增产品功能共享,确保数据一致性
* 调用状态的权限控制需要与用户权限系统集成
* 价格修改触发重新审批的业务逻辑需要与审批管理模块协调

客户充值记录列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
FR-ID: FR-CUST-012  

功能点名称: 客户充值记录列表

来源: 客户详情页 -> 充值记录tab

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 查看客户的所有充值记录
* 以便于 审计客户的资金流入情况和充值审批状态

验收标准:
* 列表数据来源于客户充值申请后的记录,展示所有充值记录(包括不同审批状态)
* 列表包含以下字段:
- 充值单号 (rechargeNumber) - 系统自动生成,格式:RCH_YYYYMMDD_XXXXX
- 充值方式 (rechargeMethod) - 枚举值:bank_transfer(银行转账)、wechat(微信支付)、alipay(支付宝)
- 充值金额 (rechargeAmount) - 格式:123,456.00 元
- 赠送金额 (giftAmount) - 格式:123,456.00 元,无赠送显示"0.00 元"
- 付款凭证 (paymentVoucher) - 可点击查看/下载,使用Button type="link"
- 充值状态 (status) - 枚举值:pending_approval(待审批)、success(充值成功)、failed(充值失败)
- 充值人员 (rechargeStaff) - 显示操作人员姓名
- 申请时间 (createTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为"/"
- 审批时间 (approveTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为"/"
- 充值备注 (rechargeRemark) - 申请时填写的备注,空值显示为"/"
- 审批备注 (approveRemark) - 审批人员填写的备注,空值显示为"/"
* 充值状态显示规则:
- pending_approval:蓝色processing标签,显示"待审批"
- success:绿色success标签,显示"充值成功"
- failed:红色error标签,显示"充值失败"
* 表格支持分页,分页选项:[10,20,50,100,200,500],默认20条/页
* 表格头部固定(sticky header)
* 支持按申请时间倒序排列(最新的在前)
* 空数据状态使用 Ant Design Empty 组件

UI组件/元素建议 (Ant Design):
* Table - 主表格组件
* Tag - 充值状态标签
* Button - 付款凭证查看链接(type="link")
* Empty - 空数据状态
* Pagination - 分页组件

数据交互 (Mock/API):
* 前端发送: GET /api/customers/{customerId}/recharge-records?page={page}&pageSize={pageSize}
* 后端响应格式:
```typescript
{
success: boolean;
message: string;
data: {
list: RechargeRecord[];
total: number;
current: number;
pageSize: number;
}
}

interface RechargeRecord {
id: string;
rechargeNumber: string;
customerId: string;
rechargeMethod: 'bank_transfer' | 'wechat' | 'alipay';
rechargeAmount: number;
giftAmount: number;
paymentVoucher: string;
rechargeStaff: string;
rechargeStaffId: string;
status: 'pending_approval' | 'success' | 'failed';
rechargeRemark?: string;
approveRemark?: string;
createTime: string;
approveTime?: string;
}
```

技术实现要求:
* 使用 TypeScript 严格类型定义
* 组件位置:src/pages/Customer/Detail/components/RechargeRecord.tsx(更新现有组件)
* Mock 数据位置:mock/customerAPI.ts(扩展现有API)
* 遵循 Umi Max 约定式路由和组件规范
* 实现响应式设计,确保在不同屏幕尺寸下正常显示
* 添加适当的 loading 状态和错误处理

前置条件:
* 用户已登录
* 用户已访问客户详情页
* 客户ID有效且存在
* 客户已有充值记录(通过充值功能添加)

测试要点:
* 验证不同充值状态的记录正确显示
* 验证充值状态标签的颜色和文本
* 验证付款凭证的查看功能
* 验证分页功能正常工作
* 验证空数据状态显示
* 验证金额格式和时间格式显示正确
* 验证响应式布局在不同屏幕尺寸下的表现

备注/特殊逻辑:
* 该组件需要与现有的RechargeRecord组件集成或替换
* 充值记录数据与充值功能共享,确保数据一致性
* 付款凭证查看功能需要支持图片预览或文件下载
* 充值金额和赠送金额需要使用项目标准的金额格式化函数

客户提现记录列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
FR-ID: FR-CUST-013  

功能点名称: 客户提现记录列表

来源: 客户详情页 -> 提现记录tab

用户故事 (User Story):
* 作为 平台运营人员
* 我想要 查看客户的所有提现记录
* 以便于 审计客户的资金流出情况和提现审批状态

验收标准:
* 列表数据来源于商户在【风盾SaaS平台】发起的提现申请记录,展示所有提现记录(包括不同审批状态)
* 列表包含以下字段:
- 提现单号 (withdrawalNumber) - 系统自动生成,格式:WTH_YYYYMMDD_XXXXX
- 提现金额 (withdrawalAmount) - 格式:123,456.00 元
- 收款银行 (bankName) - 显示银行名称
- 收款账户 (bankAccount) - 默认脱敏显示(如:****1234),点击眼睛图标可切换显示/隐藏完整信息
- 提现状态 (status) - 枚举值:pending_approval(待审批)、approved(已打款)、rejected(已拒绝)
- 申请时间 (createTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为"/"
- 审批时间 (approveTime) - 格式:YYYY-MM-DD HH:mm:ss,空值显示为"/",默认为"/",审批后更新
- 提现备注 (withdrawalRemark) - 申请时填写的备注,空值显示为"/"
* 提现状态显示规则:
- pending_approval:蓝色processing标签,显示"待审批"
- approved:绿色success标签,显示"已打款"
- rejected:红色error标签,显示"已拒绝"
* 收款账户脱敏规则:
- 默认显示:保留后四位,前面用星号替代(如:****1234)
- 点击眼睛图标:显示完整账户信息
- 再次点击眼睛图标:恢复脱敏显示
* 表格支持分页,分页选项:[10,20,50,100,200,500],默认20条/页
* 表格头部固定(sticky header)
* 支持按申请时间倒序排列(最新的在前)
* 空数据状态使用 Ant Design Empty 组件

UI组件/元素建议 (Ant Design):
* Table - 主表格组件
* Tag - 提现状态标签
* Button - 收款账户查看/隐藏按钮(type="link")
* Icon - 眼睛图标(EyeOutlined/EyeInvisibleOutlined)
* Empty - 空数据状态
* Pagination - 分页组件

数据交互 (Mock/API):
* 前端发送: GET /api/customers/{customerId}/withdrawal-records?page={page}&pageSize={pageSize}
* 后端响应格式:
```typescript
{
success: boolean;
message: string;
data: {
list: WithdrawalRecord[];
total: number;
current: number;
pageSize: number;
}
}

interface WithdrawalRecord {
id: string;
withdrawalNumber: string;
customerId: string;
withdrawalAmount: number;
bankName: string;
bankAccount: string;
status: 'pending_approval' | 'approved' | 'rejected';
withdrawalRemark?: string;
createTime: string;
approveTime?: string;
}
```

技术实现要求:
* 使用 TypeScript 严格类型定义
* 组件位置:src/pages/Customer/Detail/components/WithdrawRecord.tsx(更新现有组件)
* Mock 数据位置:mock/customerAPI.ts(扩展现有API)
* 遵循 Umi Max 约定式路由和组件规范
* 实现响应式设计,确保在不同屏幕尺寸下正常显示
* 添加适当的 loading 状态和错误处理

前置条件:
* 用户已登录
* 用户已访问客户详情页
* 客户ID有效且存在
* 客户已有提现记录(通过风盾SaaS平台发起)

测试要点:
* 验证不同提现状态的记录正确显示
* 验证提现状态标签的颜色和文本
* 验证收款账户的脱敏/显示切换功能
* 验证分页功能正常工作
* 验证空数据状态显示
* 验证金额格式和时间格式显示正确
* 验证响应式布局在不同屏幕尺寸下的表现

备注/特殊逻辑:
* 该组件需要与现有的WithdrawRecord组件集成或替换
* 提现记录数据与审批管理模块的打款审批功能共享,确保数据一致性
* 收款账户脱敏功能需要考虑安全性,避免敏感信息泄露
* 提现金额需要使用项目标准的金额格式化函数

开户审批查询功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
请实现审批管理模块中的开户审批查询功能。这是审批管理模块的第一个功能点,需要严格遵循风控中枢平台的前端实现标准,结合功能PRO文档完美实现功能点。  

## 功能需求详情

**FR-ID**: FR-APPROVAL-001
**功能点名称**: 开户审批查询功能
**页面路径**: `src/pages/Approval/Account/index.tsx`
**来源**: 审批管理 -> 开户审批页面

## 用户故事
作为平台审批人员,我想要根据公司名称、申请人、审批时间和审批状态查询开户审批记录,以便快速定位需要处理或查看的审批事项。

## 详细验收标准

### 查询表单要求
1. **查询区域布局**: 使用 Ant Design Form 组件,采用响应式布局,查询条件水平排列
2. **查询字段**:
- **公司名称**: Select组件,支持模糊搜索,数据来源于客户管理列表,使用`showSearch`和`filterOption`
- **申请人**: Select组件,支持模糊搜索,数据来源于系统管理-成员管理列表中在职状态为"开启"的成员
- **审批时间**: DatePicker.RangePicker组件,支持选择开始时间和结束时间
- **审批状态**: Select组件,选项包括:全部(默认)、待审批、审批通过、审批拒绝
3. **操作按钮**:
- "查询"按钮(type="primary"):触发查询并刷新列表
- "重置"按钮:清空所有查询条件,恢复默认状态并刷新列表

### 技术实现要求
1. **组件结构**:
- 查询表单组件:`src/pages/Approval/Account/components/SearchForm.tsx`
- 主页面:`src/pages/Approval/Account/index.tsx`
2. **状态管理**: 使用 useState 管理查询条件和列表数据
3. **数据处理**:
- 查询条件使用 `trim()` 去除首尾空格
- 时间格式转换为 YYYY-MM-DD HH:mm:ss 格式
4. **Mock数据**: 在 `mock/approvalAPI.ts` 中实现对应的Mock接口

### API接口规范
- **请求方式**: GET
- **接口路径**: `/api/approvals/account`
- **查询参数**:
```typescript
{
companyName?: string;
applicant?: string;
approvalStartTime?: string;
approvalEndTime?: string;
approvalStatus?: string;
page?: number;
pageSize?: number;
}
```
- **响应格式**:
```typescript
{
success: boolean;
message: string;
data: {
list: ApprovalRecord[];
total: number;
page: number;
pageSize: number;
}
}
```

### 遵循的平台标准
1. **分页配置**: 使用 `PAGINATION_CONFIG` 常量中的标准配置
2. **表单验证**: 遵循前端校验规范
3. **加载状态**: 使用 Ant Design 的 loading 状态
4. **错误处理**: 使用 message 组件显示错误信息
5. **TypeScript**: 严格类型定义,定义相关接口类型

### 前置条件
- 用户已登录并具有审批管理权限
- 页面路由已正确配置
- 相关Mock数据已准备

请按照以下步骤实现:
1. 首先使用 `codebase-retrieval` 工具了解现有的审批管理相关代码
2. 制定详细的实现计划
3. 创建必要的组件和Mock数据
4. 实现查询功能并确保符合所有标准
5. 建议编写测试用例验证功能

开户审批列表展示与操作功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
**FR-ID**: FR-APPROVAL-002  
**功能点名称**: 开户审批列表展示与操作功能
**页面路径**: `src/pages/Approval/Account/index.tsx`(基于已实现的FR-APPROVAL-001查询功能进行扩展)
**来源**: 审批管理 -> 开户审批页面

## 用户故事
作为平台审批人员,我想要查看开户审批记录的完整详情,并能够对待审批的记录进行审批通过或拒绝操作,以便及时、准确地处理客户的开户申请。

## 详细验收标准

### 列表展示要求
1. **列表项字段**:审批单号、公司名称、申请人、申请时间、审批人、审批时间、审批状态、审批备注、操作项
2. **审批状态可视化**:
- 待审批:蓝色 `processing` 标签
- 审批通过:绿色 `success` 标签
- 审批拒绝:红色 `error` 标签 + 红色"❗️"图标 + Tooltip显示拒绝原因
3. **数据展示规范**:
- 审批备注无数据时显示"-"
- 时间格式:YYYY-MM-DD HH:mm:ss,空值显示"/"
- 仅待审批状态的记录显示审批操作按钮

### 操作功能要求
1. **详情查看**:
- 触发:点击"详情"按钮
- 展示:Modal弹窗,包含审批单号、客户ID、公司名称、法人姓名、法人联系方式、申请时间、审批状态、合同信息
- 合同信息:如有合同URL则显示"查看合同"链接,否则显示"未提供"
- 关闭:点击"关闭"按钮

2. **审批通过操作**:
- 触发:点击"审批通过"按钮(仅待审批状态显示)
- 弹窗:Modal标题"审批通过",包含确认文案和备注输入框
- 备注:非必填,最大200字符,带字符计数
- 按钮:底部"确定"、"取消"按钮
- 确定逻辑:调用审批通过API,成功后刷新列表,显示成功提示
- 数据同步:更新【审批管理-开户审批】、【客户管理】、【客户详情-开户审批记录】状态

3. **审批拒绝操作**:
- 触发:点击"审批拒绝"按钮(仅待审批状态显示)
- 弹窗:Modal标题"审批拒绝",包含确认文案和备注输入框
- 备注:必填,最大200字符,带字符计数和必填验证
- 按钮:底部"确定"、"取消"按钮
- 确定逻辑:调用审批拒绝API,成功后刷新列表,显示警告提示
- 数据同步:更新相关模块状态,记录拒绝原因

### 技术实现要求
1. **组件结构**:
- 基于已实现的查询功能(FR-APPROVAL-001)进行扩展
- 复用现有的表格列配置和分页逻辑
- 新增详情Modal和审批操作Modal组件

2. **UI组件规范**:
- 使用Ant Design 5.x组件:Table、Button、Modal、Form、Input.TextArea、Tag、Tooltip、Descriptions
- 遵循项目统一的样式和交互规范
- 确保响应式设计和加载状态处理

3. **API接口**:
- 复用现有:`GET /api/approvals/account`(已实现)
- 新增:`POST /api/approvals/account/{id}/approve` - Body: `{ remark?: string }`
- 新增:`POST /api/approvals/account/{id}/reject` - Body: `{ remark: string }`
- 响应格式:`{ success: boolean, message: string, data?: any }`

4. **Mock数据扩展**:
- 基于现有`mock/approvalAPI.ts`进行扩展
- 确保审批操作后数据状态正确更新
- 模拟真实的审批流程和状态变化

### 前置条件
- 用户已登录并具有审批管理权限
- FR-APPROVAL-001开户审批查询功能已正常运行
- 相关Mock数据和API接口已配置

### 验证要点
1. 列表展示:审批状态正确显示,拒绝状态有红色标识和Tooltip
2. 详情查看:弹窗信息完整准确,合同链接功能正常
3. 审批操作:通过/拒绝流程完整,表单验证有效
4. 数据同步:操作后列表状态实时更新
5. 用户体验:加载状态、错误处理、成功提示完善

### 扩展说明
此功能是在FR-APPROVAL-001查询功能基础上的增强,主要新增审批操作能力,需要保持与现有代码的一致性和兼容性。

产品审批查询功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
**FR-ID**: FR-APPROVAL-003  
**功能点名称**: 产品审批查询功能
**页面路径**: `src/pages/Approval/Product/index.tsx`
**来源**: 审批管理 -> 产品审批页面

## 用户故事
作为平台审批人员,我想要根据公司名称、产品名称、接入方式、申请人、审批时间和审批状态查询产品审批记录,以便快速定位需要处理或查看的产品开通审批事项。

## 详细验收标准

### 查询表单要求
1. **查询区域布局**: 使用 Ant Design Form 组件,采用响应式布局,查询条件水平排列
2. **查询字段**:
- **公司名称**: Select组件,支持模糊搜索,数据来源于客户管理列表,使用`showSearch`和`filterOption`
- **产品名称**: Select组件,支持模糊搜索,使用Mock数据(包括:身份认证、银行卡验证、手机号验证、邮箱验证、人脸识别、活体检测、OCR识别、风险评估、反欺诈检测)
- **接入方式**: Select组件,选项包括:全部(默认)、API、风控平台,单选项
- **申请人**: Select组件,支持模糊搜索,数据来源于系统管理-成员管理列表中在职状态为"开启"的成员
- **审批时间**: DatePicker.RangePicker组件,支持选择开始时间和结束时间
- **审批状态**: Select组件,选项包括:全部(默认)、待审批、审批通过、审批拒绝
3. **操作按钮**:
- "查询"按钮(type="primary"):触发查询并刷新列表
- "重置"按钮:清空所有查询条件,恢复默认状态并刷新列表

### 技术实现要求
1. **组件结构**:
- 查询表单组件:`src/pages/Approval/Product/components/SearchForm.tsx`
- 主页面:`src/pages/Approval/Product/index.tsx`
2. **状态管理**: 使用 useState 管理查询条件和列表数据
3. **数据处理**:
- 查询条件使用 `trim()` 去除首尾空格
- 时间格式转换为 YYYY-MM-DD HH:mm:ss 格式
4. **Mock数据**: 在 `mock/approvalAPI.ts` 中扩展实现产品审批相关的Mock接口

### API接口规范
- **请求方式**: GET
- **接口路径**: `/api/approvals/product`
- **查询参数**:
```typescript
{
companyName?: string;
productName?: string;
accessMethod?: string;
applicant?: string;
approvalStartTime?: string;
approvalEndTime?: string;
approvalStatus?: string;
page?: number;
pageSize?: number;
}
```
- **响应格式**:
```typescript
{
success: boolean;
message: string;
data: {
list: ProductApprovalRecord[];
total: number;
page: number;
pageSize: number;
}
}
```

### 遵循的平台标准
1. **分页配置**: 使用 `PAGINATION_CONFIG` 常量中的标准配置
2. **表单验证**: 遵循前端校验规范
3. **加载状态**: 使用 Ant Design 的 loading 状态
4. **错误处理**: 使用 message 组件显示错误信息
5. **TypeScript**: 严格类型定义,定义相关接口类型
6. **常量管理**: 在 `src/constants/index.ts` 中添加产品相关的枚举和配置

### 数据类型定义要求
需要在 `src/pages/Approval/Product/types.ts` 中定义:
```typescript
export interface ProductApprovalRecord {
id: string;
approvalNumber: string;
customerId: string;
companyName: string;
productName: string;
accessMethod: 'API' | '风控平台';
applicant: string;
applicantId: string;
applyTime: string;
approver?: string;
approverId?: string;
approvalTime?: string;
approvalStatus: 'pending_approval' | 'approved' | 'rejected';
approvalRemark?: string;
rejectionReason?: string;
}

export interface ProductApprovalQueryParams {
companyName?: string;
productName?: string;
accessMethod?: string;
applicant?: string;
approvalStartTime?: string;
approvalEndTime?: string;
approvalStatus?: string;
page?: number;
pageSize?: number;
}
```

### 前置条件
- 用户已登录并具有审批管理权限
- 页面路由已正确配置
- 相关Mock数据已准备
- 复用现有的审批管理基础设施(常量、工具函数等)

请按照以下步骤实现:
1. 首先使用 `codebase-retrieval` 工具了解现有的审批管理代码结构
2. 制定详细的实现计划
3. 创建必要的组件、类型定义和Mock数据
4. 实现查询功能并确保符合所有标准
5. 建议编写测试用例验证功能

### 特殊说明
- 此功能是审批管理模块的第二个查询功能,应与FR-APPROVAL-001和FR-APPROVAL-002保持一致的代码风格和架构模式
- 产品名称暂时使用Mock数据,后续可能需要与产品管理模块集成
- 需要确保与现有审批管理功能的UI/UX一致性

产品审批列表展示与操作功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
**FR-ID**: FR-APPROVAL-004  
**功能点名称**: 产品审批列表展示与操作功能
**页面路径**: `src/pages/Approval/Product/index.tsx`(基于已实现的FR-APPROVAL-003查询功能进行扩展)
**来源**: 审批管理 -> 产品审批页面

## 用户故事
作为平台审批人员,我想要查看产品审批记录的完整详情,并能够对待审批的记录进行审批通过或拒绝操作,以便及时、准确地处理客户的产品开通申请。

## 详细验收标准

### 列表展示要求
1. **列表项字段**:审批单号、公司名称、产品名称、接入方式、申请人、申请时间、审批人、审批时间、审批状态、审批备注、操作项
2. **审批状态可视化**:
- 待审批:蓝色 `processing` 标签
- 审批通过:绿色 `success` 标签
- 审批拒绝:红色 `error` 标签 + 红色"❗️"图标 + Tooltip显示拒绝原因
3. **数据展示规范**:
- 审批备注无数据时显示"-"
- 时间格式:YYYY-MM-DD HH:mm:ss,空值显示"/"
- 仅待审批状态的记录显示审批操作按钮

### 操作功能要求
1. **详情查看**:
- 触发:点击"详情"按钮
- 展示:Modal弹窗,包含审批单号、公司名称、产品名称、接入方式、申请人、申请时间、审批状态、产品描述、配置详情、申请备注
- 关闭:点击"关闭"按钮

2. **审批通过操作**:
- 触发:点击"审批通过"按钮(仅待审批状态显示)
- 弹窗:Modal标题"审批通过",包含确认文案和备注输入框
- 备注:非必填,最大200字符,带字符计数
- 按钮:底部"确定"、"取消"按钮
- 确定逻辑:调用审批通过API,成功后刷新列表,显示成功提示
- 数据同步:更新【审批管理-产品审批】、【客户管理】、【客户详情-产品信息列表】状态

3. **审批拒绝操作**:
- 触发:点击"审批拒绝"按钮(仅待审批状态显示)
- 弹窗:Modal标题"审批拒绝",包含确认文案和备注输入框
- 备注:必填,最大200字符,带字符计数和必填验证
- 按钮:底部"确定"、"取消"按钮
- 确定逻辑:调用审批拒绝API,成功后刷新列表,显示警告提示
- 数据同步:更新相关模块状态,记录拒绝原因

### 技术实现要求
1. **组件结构**:
- 基于已实现的查询功能(FR-APPROVAL-003)进行扩展
- 复用现有的表格列配置和分页逻辑
- 新增详情Modal和审批操作Modal组件

2. **UI组件规范**:
- 使用Ant Design 5.x组件:Table、Button、Modal、Form、Input.TextArea、Tag、Tooltip、Descriptions
- 遵循项目统一的样式和交互规范
- 确保响应式设计和加载状态处理

3. **API接口**:
- 复用现有:`GET /api/approvals/product`(已实现)
- 新增:`POST /api/approvals/product/{id}/approve` - Body: `{ remark?: string }`
- 新增:`POST /api/approvals/product/{id}/reject` - Body: `{ remark: string }`
- 响应格式:`{ success: boolean, message: string, data?: any }`

4. **Mock数据扩展**:
- 基于现有`mock/approvalAPI.ts`进行扩展
- 确保审批操作后数据状态正确更新
- 模拟真实的审批流程和状态变化

### 前置条件
- 用户已登录并具有审批管理权限
- FR-APPROVAL-003产品审批查询功能已正常运行
- 相关Mock数据和API接口已配置

### 验证要点
1. 列表展示:审批状态正确显示,拒绝状态有红色标识和Tooltip
2. 详情查看:弹窗信息完整准确,产品配置信息正常显示
3. 审批操作:通过/拒绝流程完整,表单验证有效
4. 数据同步:操作后列表状态实时更新
5. 用户体验:加载状态、错误处理、成功提示完善

### 扩展说明
此功能是在FR-APPROVAL-003查询功能基础上的增强,主要新增审批操作能力,需要保持与现有代码的一致性和兼容性,并与FR-APPROVAL-001和FR-APPROVAL-002的开户审批功能保持相同的架构模式和UI/UX标准。

充值审批查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
**FR-ID: FR-APPROVAL-005**  

**功能点名称**: 充值审批查询

**来源**: 审批管理 -> 充值审批页面

**用户故事 (User Story)**:
- 作为 平台审批人员
- 我想要 根据公司名称、申请人、审批时间和审批状态查询充值审批记录
- 以便于 快速定位和处理充值审批事项

**验收标准**:

**查询表单要求**:
- 查询区域包含"公司名称"、"申请人"、"审批时间"、"审批状态"四个查询项
- "公司名称"为下拉选择框,数据源来自【客户管理列表】的公司名称,支持模糊搜索和输入过滤
- "申请人"为下拉选择框,数据源来自【系统管理-成员管理】列表的成员名称,支持模糊搜索和输入过滤
- "审批时间"使用日期范围选择器,支持选择开始时间和结束时间
- "审批状态"为下拉选择框,选项包括:全部(默认)、待审批、未到账、已到账
- 点击"查询"按钮,根据表单条件发送API请求并刷新下方列表数据
- 点击"重置"按钮,清空所有查询条件并重新加载默认状态的列表数据

**技术实现要求**:
- 遵循Umi Max + Ant Design 5.x + TypeScript规范
- 组件位置:`src/pages/approval/recharge/components/SearchForm.tsx`
- 所有查询条件支持模糊查询,字符串字段自动执行`trim()`处理
- 使用严格的TypeScript接口定义查询参数和响应数据结构
- 集成现有的审批管理模块设计模式和PAGINATION_CONFIG常量

**UI组件规范 (Ant Design 5.x)**:
- `Form` + `Form.Item` 构建查询表单
- `Select` 组件用于公司名称、申请人、审批状态选择,启用`showSearch`和`filterOption`
- `DatePicker.RangePicker` 用于审批时间范围选择
- `Button` 组件用于查询和重置操作,查询按钮为primary类型

**数据交互规范**:
- **API接口**: `GET /api/approvals/recharge`
- **请求参数**:
```typescript
interface RechargeApprovalQueryParams {
companyName?: string;
applicant?: string;
approvalStartTime?: string; // YYYY-MM-DD格式
approvalEndTime?: string; // YYYY-MM-DD格式
approvalStatus?: 'pending_approval' | 'not_arrived' | 'arrived' | '';
page?: number;
pageSize?: number;
}
```
- **响应格式**:
```typescript
interface ApiResponse<T> {
success: boolean;
message: string;
data: {
list: T[];
total: number;
page: number;
pageSize: number;
};
}
```
- **Mock数据**: 在`mock/approvalAPI.ts`中实现,确保数据结构与客户管理和成员管理模块保持一致性

**前置条件**:
- 用户已登录并具有审批管理权限
- 用户已访问充值审批页面

**集成要求**:
- 与现有审批管理模块的SearchForm组件设计模式保持一致
- 确保与客户管理和系统管理模块的数据源联动正确
- 遵循项目统一的错误处理和Loading状态管理规范

**备注**:
- 该组件作为充值审批页面的查询功能组件,需要与列表展示组件协同工作
- 查询结果应支持标准分页配置:[10,20,50,100,200,500],默认20条/页

充值审批列表展示与操作功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
**FR-ID: FR-APPROVAL-006**  

**功能点名称**: 充值审批列表展示与操作功能

**来源**: 审批管理 -> 充值审批页面

**用户故事 (User Story)**:
- 作为 平台审批人员
- 我想要 查看充值审批记录的完整列表,并能对每条记录进行详情查看、审批通过或审批拒绝操作
- 以便于 及时、准确地处理客户的充值申请,确保资金安全和业务流程顺畅

**验收标准**:

**列表展示要求**:
- 表格列包括:审批单号、充值单号、公司名称、充值金额、赠送金额、支付方式、付款凭证、申请人、申请时间、审批人、审批时间、审批状态、充值备注、审批备注、操作
- 充值金额和赠送金额使用`formatAmount()`函数格式化,显示为"123,456.00 元"
- 时间字段使用`formatTime()`函数格式化,格式为YYYY-MM-DD HH:mm:ss,空值显示"/"
- 付款凭证显示为可点击的链接,点击后在新窗口预览图片
- 充值备注和审批备注无数据时显示"-"
- 支持标准分页配置:[10,20,50,100,200,500],默认20条/页
- 表头固定,支持横向滚动

**审批状态可视化要求**:
- 审批状态包括:待审批(蓝色processing标签)、已到账(绿色success标签)、未到账(橙色warning标签)
- 审批状态为"未到账"时,在状态标签前显示红色"❗️"图标
- 鼠标悬停在"❗️"图标上时,使用Tooltip显示详细的审批备注信息
- 使用RECHARGE_APPROVAL_STATUS_TEXT常量进行状态文本映射

**操作功能要求**:
- 操作列包含"详情"、"审批通过"、"审批拒绝"三个按钮
- 只有审批状态为"待审批"的记录才显示"审批通过"和"审批拒绝"按钮
- 所有记录都显示"详情"按钮

**详情查看功能**:
- 点击"详情"按钮:打开Modal弹窗,标题为"充值审批详情"
- 弹窗内容使用Descriptions组件展示:审批单号、充值单号、公司名称、充值金额、赠送金额、支付方式、申请人、申请时间、审批状态、充值备注、付款凭证(支持图片预览)
- 如果有审批信息,还需显示:审批人、审批时间、审批备注
- 弹窗底部只有"关闭"按钮

**审批通过功能**:
- 点击"审批通过"按钮:打开Modal弹窗,标题为"审批通过"
- 弹窗内容:确认文案 + 备注输入框(非必填,最大200字符,显示字符计数)
- 确认文案格式:确定要通过客户 "{公司名称}" 金额为 {formatAmount(充值金额)} 元的充值申请吗?
- 弹窗底部:"确定"和"取消"按钮,"确定"按钮支持loading状态
- 点击"确定":调用审批通过API,成功后显示成功消息,关闭弹窗,刷新列表数据

**审批拒绝功能**:
- 点击"审批拒绝"按钮:打开Modal弹窗,标题为"审批拒绝"
- 弹窗内容:确认文案 + 备注输入框(必填,最大200字符,显示字符计数)
- 确认文案格式:确定要拒绝客户 "{公司名称}" 金额为 {formatAmount(充值金额)} 元的充值申请吗?
- 备注输入框验证规则:必填,最大200字符,错误提示"拒绝时必须填写备注"
- 弹窗底部:"确定"和"取消"按钮,"确定"按钮支持loading状态
- 点击"确定":调用审批拒绝API,成功后显示警告消息,关闭弹窗,刷新列表数据

**技术实现要求**:
- 遵循Umi Max + Ant Design 5.x + TypeScript规范
- 组件位置:更新现有的`src/pages/Approval/Recharge/index.tsx`
- 使用严格的TypeScript接口定义所有数据结构
- 集成FR-APPROVAL-005已实现的查询功能
- 使用PAGINATION_CONFIG常量配置分页
- 所有操作都要有完整的错误处理和loading状态

**UI组件规范 (Ant Design 5.x)**:
- `Table` 组件展示列表,配置sticky表头和横向滚动
- `Button` 组件用于操作按钮,使用合适的type和icon
- `Modal` 组件用于详情和审批弹窗
- `Descriptions` 组件用于详情展示
- `Form` + `Input.TextArea` 用于备注输入
- `Tag` 组件用于状态显示
- `Tooltip` 组件用于状态提示
- `Image` 组件用于付款凭证预览

**数据交互规范**:
- **获取列表**: 复用FR-APPROVAL-005的`GET /api/approvals/recharge`接口
- **审批通过**: `POST /api/approvals/recharge/{id}/approve`,请求体:`{ remark?: string }`
- **审批拒绝**: `POST /api/approvals/recharge/{id}/reject`,请求体:`{ remark: string }`
- **响应格式**: 统一使用`{ success: boolean; message: string; data?: any }`格式
- **Mock数据**: 在`mock/approvalAPI.ts`中实现,确保与FR-APPROVAL-005的数据结构一致

**数据同步要求**:
- 审批操作成功后,需要同步更新以下模块的数据状态:
- 审批管理-充值审批列表
- 客户管理列表中的相关客户信息
- 客户详情页面的充值记录列表
- 模拟同步到账单中心的账户余额(审批通过时)

**前置条件**:
- 用户已登录并具有审批管理权限
- 用户已访问充值审批页面
- FR-APPROVAL-005充值审批查询功能已实现

**集成要求**:
- 与FR-APPROVAL-005的查询功能无缝集成
- 保持与其他审批管理模块(开户审批、产品审批)的一致性
- 遵循项目统一的错误处理和消息提示规范
- 确保响应式设计,适配不同屏幕尺寸

**备注**:
- 该功能是FR-APPROVAL-005查询功能的扩展,需要在现有基础上增加列表展示和操作功能
- 审批操作涉及多个模块的数据同步,需要确保数据一致性
- 付款凭证预览功能需要处理图片加载失败的情况

打款审批查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
**FR-ID: FR-APPROVAL-007**  

**功能点名称**: 打款审批查询

**来源**: 审批管理 -> 打款审批页面

**用户故事 (User Story)**:
- 作为 平台审批人员
- 我想要 根据公司名称、申请人、审批时间和审批状态查询打款审批记录
- 以便于 快速定位和处理客户的提现打款审批事项

**验收标准**:

**查询表单要求**:
- 查询区域包含"公司名称"、"申请人"、"审批时间"、"审批状态"四个查询项
- "公司名称"为下拉选择框,数据源来自【客户管理列表】的公司名称,支持模糊搜索和输入过滤
- "申请人"为下拉选择框,数据源来自【系统管理-成员管理】列表的成员名称,支持模糊搜索和输入过滤
- "审批时间"使用日期范围选择器,支持选择开始时间和结束时间
- "审批状态"为下拉选择框,选项包括:全部(默认)、待审批、已打款、已拒绝
- 点击"查询"按钮,根据表单条件发送API请求并刷新下方列表数据
- 点击"重置"按钮,清空所有查询条件并重新加载默认状态的列表数据

**技术实现要求**:
- 遵循Umi Max + Ant Design 5.x + TypeScript规范
- 组件位置:`src/pages/Approval/Payment/components/SearchForm.tsx`
- 所有查询条件支持模糊查询,字符串字段自动执行`trim()`处理
- 使用严格的TypeScript接口定义查询参数和响应数据结构
- 集成现有的审批管理模块设计模式和PAGINATION_CONFIG常量

**UI组件规范 (Ant Design 5.x)**:
- `Form` + `Form.Item` 构建查询表单
- `Select` 组件用于公司名称、申请人、审批状态选择,启用`showSearch`和`filterOption`
- `DatePicker.RangePicker` 用于审批时间范围选择
- `Button` 组件用于查询和重置操作,查询按钮为primary类型

**数据交互规范**:
- **API接口**: `GET /api/approvals/payment`
- **请求参数**:
```typescript
interface PaymentApprovalQueryParams {
companyName?: string;
applicant?: string;
approvalStartTime?: string; // YYYY-MM-DD格式
approvalEndTime?: string; // YYYY-MM-DD格式
approvalStatus?: 'pending_approval' | 'approved' | 'rejected' | '';
page?: number;
pageSize?: number;
}
```
- **响应格式**:
```typescript
interface ApiResponse<T> {
success: boolean;
message: string;
data: {
list: T[];
total: number;
page: number;
pageSize: number;
};
}
```
- **Mock数据**: 在`mock/approvalAPI.ts`中实现,确保数据结构与客户管理和成员管理模块保持一致性

**前置条件**:
- 用户已登录并具有审批管理权限
- 用户已访问打款审批页面

**集成要求**:
- 与现有审批管理模块的SearchForm组件设计模式保持一致
- 确保与客户管理和系统管理模块的数据源联动正确
- 遵循项目统一的错误处理和Loading状态管理规范

**备注**:
- 该组件作为打款审批页面的查询功能组件,需要与列表展示组件协同工作
- 查询结果应支持标准分页配置:[10,20,50,100,200,500],默认20条/页
- 与FR-APPROVAL-005充值审批查询功能保持相同的实现模式和代码结构
  • 标题:
  • 作者: 菇太帷i
  • 创建于 : 2025-09-18 06:39:53
  • 更新于 : 2025-09-18 06:39:53
  • 链接: https://blog.gutawei.com/2025/09/18/outsourcing/风控中枢/对话记录/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论