流程信息

This commit is contained in:
2025-12-26 18:13:42 +08:00
parent e8e6778d08
commit d8785fe915
20 changed files with 2493 additions and 159 deletions

View File

@@ -0,0 +1,71 @@
# Change: 增强贷款审核相关页面功能
## Why
当前贷款审核相关页面(银行端审核列表、用户端申请记录、商家端贷款协助、银行端审核详情)的模拟数据不够完善,缺少不同状态的展示,且用户端无法查看银行端受理人的联系方式,影响业务沟通效率。同时银行端审核详情页缺少征信信息和信用评估功能。商家端贷款协助页面需要优化信息展示逻辑和添加状态筛选功能。此外,各端之间的模拟数据需要保持一致,商家端的订单和商品数据应与用户端的商品信息一致,银行端审核详情需要展示用户在商城的消费订单信息。
## What Changes
### 银行端审核列表页面(/pagesBank/audit/list
- 优化模拟数据确保包含所有贷款状态SUBMITTED、ACCEPTED、INVESTIGATING、REPORTED、APPROVED、REJECTED、SIGNED、DISBURSED
- 确保表格展示不同状态的申请记录
- 添加状态筛选 Tab可快速切换查看不同状态的申请记录
### 用户端助贷申请记录页面(/pages/me/loan-application-records
- 在处理中状态的申请记录中添加银行端受理人信息
- 显示受理人姓名和手机号码,方便用户联系业务处理人员
### 商家端贷款协助页面(/pagesMerchant/loan/assist
- 优化模拟数据,确保包含不同状态的贷款申请
- 确保商家端看到的贷款数据与银行端一致
- 移除银行受理人信息卡片src\pagesMerchant\loan\assist.vue:121-136
- 申请进度及负责人信息:还没有执行的进度不显示负责人信息
- 添加状态筛选 Tab可快速切换查看不同状态的申请记录
- 页面标题修改:将"贷款辅助材料"显示为"辅助贷款材料"
### 银行端审核详情页面(/pagesBank/audit/detail
- 添加征信信息查询功能(弹窗模拟远程查询征信信息),与平台信用评估功能保持一致
- 添加平台信用评估分数展示,并注明免责声明:"仅供参考,不构成专业建议,实际应用请以权威数据为准。"
- 平台信用评估和征信查询功能完成后,刷新按钮应该隐藏
- 状态标签显示中文状态文本(如"已拒绝"而非"rejected"
- 优化关联商家信息展示使用用户端中的商家信息包括商家ID、商家名称、logo等
- 商家相关附件使用 src/static/fb 目录中的图片资源
- **新增:添加用户在商城消费的订单信息展示,包括订单号、商品名称、购买数量、金额等**
### 商家端贷款协助页面(/pagesMerchant/loan/assist- 续
- 显示申请进度及每个进度的负责人姓名和手机号码(仅已执行的进度显示负责人信息)
### 商家端订单管理页面(/pagesMerchant/order/list
- **新增:修改订单模拟数据,使其与用户端商品信息保持一致**
- 订单中的商品应使用用户端 mockGoodsList 中的商品数据包括商品ID、商品名称、图片、价格等
- 订单中的商家信息应与用户端商品中的 shopId 和 shopName 保持一致
### 商家端商品管理页面(/pagesMerchant/goods/list
- **新增:修改商品模拟数据,使其与用户端商品信息保持一致**
- 商品数据应使用用户端 mockGoodsList 中的商品数据包括商品ID、商品名称、图片、价格、库存、销量等
- 商品分类应与用户端商品中的 categoryId 和 categoryName 保持一致
### 商家端全局文本修改
- 商家端贷款协助页面标题"贷款辅助材料"修改为"辅助贷款材料"
### 所有端模拟数据补充
- 所有端添加"驳回要求补充资料"状态的模拟数据
## Impact
### Affected Specs
- `specs/loan-audit` (新建能力)
### Affected Code
- `src/pagesBank/audit/list.vue` - 银行端审核列表
- `src/pagesBank/audit/detail.vue` - 银行端审核详情
- `src/pages/me/loan-application-records.vue` - 用户端申请记录
- `src/pagesMerchant/loan/assist.vue` - 商家端贷款协助
- `src/pagesMerchant/order/list.vue` - 商家端订单管理
- `src/pagesMerchant/goods/list.vue` - 商家端商品管理
- `src/mock/loan-application.ts` - 贷款申请模拟数据
- `src/pagesMerchant/mock/order.ts` - 商家端订单模拟数据
- `src/pagesMerchant/mock/goods.ts` - 商家端商品模拟数据
- `src/api/loan.ts` - 贷款相关API可能需要扩展
- `src/typings/loan.ts` - 贷款类型定义(可能需要扩展)
- `src/typings/mall.ts` - 商城类型定义(可能需要扩展)

View File

@@ -0,0 +1,209 @@
## ADDED Requirements
### Requirement: 银行端审核列表多状态展示
银行端审核列表页面 SHALL 显示包含所有贷款状态的申请记录包括SUBMITTED新申请、ACCEPTED已受理、INVESTIGATING调查中、REPORTED待审批、APPROVED已通过、REJECTED已拒绝、SIGNED已签约、DISBURSED已放款、REJECTED_REQUIRE_SUPPLEMENT驳回要求补充资料。页面 SHALL 提供状态筛选 Tab可快速切换查看不同状态的申请记录。
#### Scenario: 银行审核员查看审核列表
- **WHEN** 银行审核员访问审核列表页面
- **THEN** 页面 SHALL 显示不同状态的贷款申请记录
- **AND** 每条记录 SHALL 显示状态标签,使用不同颜色区分状态
- **AND** 页面 SHALL 提供状态筛选 Tab 组件
- **AND** 用户可以通过 Tab 切换查看特定状态的申请
- **AND** 状态标签 SHALL 显示中文状态文本(如"已拒绝"而非"rejected"
#### Scenario: 银行审核员使用状态筛选 Tab
- **WHEN** 银行审核员点击状态筛选 Tab
- **THEN** 页面 SHALL 过滤显示对应状态的申请记录
- **AND** Tab SHALL 高亮显示当前选中的状态
- **AND** 切换 Tab SHALL 不影响其他筛选条件
#### Scenario: 银行审核员查看驳回要求补充资料状态
- **WHEN** 银行审核员查看审核列表中的"驳回要求补充资料"状态
- **THEN** 状态标签 SHALL 正确显示该状态
- **AND** 状态标签 SHALL 使用正确的样式和颜色
### Requirement: 用户端显示银行受理人信息
用户端助贷申请记录页面 SHALL 在处理中状态的申请记录中显示银行端受理人的姓名和手机号码,方便用户联系业务处理人员。
#### Scenario: 用户查看处理中的贷款申请
- **WHEN** 用户查看状态为"处理中"的贷款申请记录
- **THEN** 页面 SHALL 显示银行受理人的姓名和手机号码
- **AND** 用户可以点击手机号码直接拨打联系
#### Scenario: 用户查看非处理中的贷款申请
- **WHEN** 用户查看状态为"已完成"或"待提交"的贷款申请记录
- **THEN** 页面 SHALL 不显示银行受理人信息
#### Scenario: 用户查看驳回要求补充资料的贷款申请
- **WHEN** 用户查看状态为"驳回要求补充资料"的贷款申请记录
- **THEN** 页面 SHALL 显示该状态
- **AND** 状态标签 SHALL 使用正确的样式和颜色
### Requirement: 商家端贷款协助页面展示
商家端贷款协助页面 SHALL 显示不同状态的贷款申请,数据 SHALL 与银行端保持一致。页面 SHALL 提供状态筛选 Tab可快速切换查看不同状态的申请记录。页面标题 SHALL 显示为"辅助贷款材料"。
#### Scenario: 商家查看贷款协助列表
- **WHEN** 商家查看贷款协助列表
- **THEN** 列表 SHALL 包含不同状态的贷款申请
- **AND** 数据 SHALL 与银行端审核列表保持一致
- **AND** 页面标题 SHALL 显示为"辅助贷款材料"
#### Scenario: 商家使用状态筛选 Tab
- **WHEN** 商家点击状态筛选 Tab
- **THEN** 页面 SHALL 过滤显示对应状态的申请记录
- **AND** Tab SHALL 高亮显示当前选中的状态
- **AND** 切换 Tab SHALL 不影响其他筛选条件
#### Scenario: 商家查看驳回要求补充资料的贷款申请
- **WHEN** 商家查看状态为"驳回要求补充资料"的贷款申请记录
- **THEN** 页面 SHALL 显示该状态
- **AND** 状态标签 SHALL 使用正确的样式和颜色
### Requirement: 商家端显示申请进度及负责人信息
商家端贷款协助页面 SHALL 显示申请进度。已执行的进度 SHALL 显示负责人姓名和手机号码,未执行的进度 SHALL 不显示负责人信息。
#### Scenario: 商家查看贷款申请进度
- **WHEN** 商家查看贷款协助页面
- **THEN** 页面 SHALL 显示申请进度列表
- **AND** 已执行的进度 SHALL 显示负责人姓名和手机号码
- **AND** 未执行的进度 SHALL 不显示负责人信息
- **AND** 商家可以点击已执行进度的手机号码直接拨打联系
#### Scenario: 商家查看未执行的进度
- **WHEN** 商家查看贷款申请进度中的未执行进度项
- **THEN** 进度项 SHALL 不显示负责人姓名和手机号码
- **AND** 进度项 SHALL 显示进度步骤名称和时间(如果有)
### Requirement: 银行端审核详情征信查询
银行端审核详情页面 SHALL 提供征信信息查询功能,通过弹窗模拟远程查询征信信息,与平台信用评估功能保持一致。
#### Scenario: 银行审核员查询征信信息
- **WHEN** 银行审核员点击"查询征信"按钮
- **THEN** 系统 SHALL 弹出征信信息查询弹窗
- **AND** 弹窗 SHALL 显示模拟的征信查询结果
- **AND** 弹窗 SHALL 包含加载状态提示
- **AND** 查询完成后,刷新按钮 SHALL 隐藏
#### Scenario: 银行审核员查看征信查询状态
- **WHEN** 征信信息查询已完成
- **THEN** 刷新按钮 SHALL 不再显示
- **AND** 页面 SHALL 显示查询结果
### Requirement: 银行端审核详情信用评估分数
银行端审核详情页面 SHALL 显示平台信用评估分数,并附带免责声明:"仅供参考,不构成专业建议,实际应用请以权威数据为准。"
#### Scenario: 银行审核员查看信用评估分数
- **WHEN** 银行审核员查看贷款审核详情
- **THEN** 页面 SHALL 显示平台信用评估分数
- **AND** 页面 SHALL 显示免责声明:"仅供参考,不构成专业建议,实际应用请以权威数据为准。"
- **AND** 免责声明 SHALL 使用醒目的样式展示
#### Scenario: 银行审核员刷新信用评估分数
- **WHEN** 银行审核员点击刷新按钮获取信用评估分数
- **THEN** 系统 SHALL 显示加载状态
- **AND** 评估完成后,刷新按钮 SHALL 隐藏
- **AND** 页面 SHALL 显示评估分数
### Requirement: 银行端审核详情状态中文显示
银行端审核详情页面 SHALL 显示中文状态文本,而非英文状态代码。
#### Scenario: 银行审核员查看贷款状态
- **WHEN** 银行审核员查看贷款审核详情
- **THEN** 状态标签 SHALL 显示中文状态文本(如"已拒绝"而非"rejected"
- **AND** 所有状态 SHALL 使用统一的中文翻译
### Requirement: 银行端审核详情关联商家信息
银行端审核详情页面 SHALL 显示关联商家信息,商家相关附件 SHALL 使用 src/static/fb 目录中的图片资源。商家信息 SHALL 与用户端商品数据保持一致。
#### Scenario: 银行审核员查看关联商家信息
- **WHEN** 银行审核员查看贷款审核详情
- **THEN** 页面 SHALL 显示关联商家列表
- **AND** 每个商家 SHALL 显示商家名称、logo、最后交易时间
- **AND** 商家相关附件 SHALL 使用 src/static/fb 目录中的图片资源
- **AND** 商家信息 SHALL 与用户端商品数据中的商家信息一致
#### Scenario: 银行审核员预览商家附件
- **WHEN** 银行审核员点击商家附件图片
- **THEN** 系统 SHALL 打开图片预览功能
### Requirement: 银行端审核详情用户订单信息
银行端审核详情页面 SHALL 显示用户在商城的消费订单信息,包括订单号、商品名称、购买数量、金额等。
#### Scenario: 银行审核员查看用户订单信息
- **WHEN** 银行审核员查看贷款审核详情
- **THEN** 页面 SHALL 显示用户的消费订单列表
- **AND** 每条订单 SHALL 显示订单号、商品名称、购买数量、金额
- **AND** 订单 SHALL 显示下单时间和订单状态
- **AND** 订单中的商品信息 SHALL 与用户端商品数据一致
#### Scenario: 银行审核员查看订单详情
- **WHEN** 银行审核员点击订单项
- **THEN** 系统 SHALL 显示订单详细信息
- **AND** 详细信息 SHALL 包含商品图片、规格、价格等
### Requirement: 商家端订单数据一致性
商家端订单管理页面的模拟数据 SHALL 与用户端商品信息保持一致。订单中的商品 SHALL 使用用户端 mockGoodsList 中的商品数据。
#### Scenario: 商家查看订单列表
- **WHEN** 商家查看订单管理页面
- **THEN** 订单列表 SHALL 显示订单信息
- **AND** 订单中的商品 ID SHALL 与用户端商品 ID 一致
- **AND** 订单中的商品名称、图片、价格 SHALL 与用户端商品数据一致
- **AND** 订单中的商家信息 SHALL 与用户端商品中的 shopId 和 shopName 一致
#### Scenario: 商家查看订单详情
- **WHEN** 商家查看订单详情
- **THEN** 订单详情 SHALL 显示完整订单信息
- **AND** 商品信息 SHALL 与用户端商品数据保持一致
### Requirement: 商家端商品数据一致性
商家端商品管理页面的模拟数据 SHALL 与用户端商品信息保持一致。商品数据 SHALL 使用用户端 mockGoodsList 中的商品数据。
#### Scenario: 商家查看商品列表
- **WHEN** 商家查看商品管理页面
- **THEN** 商品列表 SHALL 显示商品信息
- **AND** 商品 ID、名称、图片、价格、库存、销量 SHALL 与用户端商品数据一致
- **AND** 商品分类信息 SHALL 与用户端商品中的 categoryId 和 categoryName 一致
#### Scenario: 商家查看商品详情
- **WHEN** 商家查看商品详情
- **THEN** 商品详情 SHALL 显示完整商品信息
- **AND** 商品信息 SHALL 与用户端商品数据保持一致
### Requirement: 商家端页面标题修改
商家端贷款协助页面标题 SHALL 显示为"辅助贷款材料"。
#### Scenario: 商家查看贷款协助页面
- **WHEN** 商家访问贷款协助页面
- **THEN** 页面标题 SHALL 显示"辅助贷款材料"
### Requirement: 所有端驳回要求补充资料状态
所有端(银行端、用户端、商家端)的模拟数据 SHALL 包含"驳回要求补充资料"状态。
#### Scenario: 银行端查看驳回要求补充资料状态
- **WHEN** 银行审核员查看审核列表
- **THEN** 列表 SHALL 包含"驳回要求补充资料"状态的申请
- **AND** 状态标签 SHALL 正确显示该状态
#### Scenario: 用户端查看驳回要求补充资料状态
- **WHEN** 用户查看申请记录
- **THEN** 列表 SHALL 包含"驳回要求补充资料"状态的申请
- **AND** 状态标签 SHALL 正确显示该状态
#### Scenario: 商家端查看驳回要求补充资料状态
- **WHEN** 商家查看贷款协助列表
- **THEN** 列表 SHALL 包含"驳回要求补充资料"状态的申请
- **AND** 状态标签 SHALL 正确显示该状态

View File

@@ -0,0 +1,114 @@
## 1. 数据模型扩展
- [x] 1.1 扩展 `LoanApplication` 类型定义添加银行受理人信息字段handlerName、handlerPhone
- [x] 1.2 扩展 `LoanApplicationRecord` 类型定义,添加银行受理人信息字段
- [x] 1.3 扩展商家端贷款列表项类型,添加银行受理人信息字段
- [x] 1.4 扩展 `LoanApplication` 类型定义添加用户订单信息字段userOrders
- [x] 1.5 扩展商家端订单类型定义,确保与用户端商品信息一致
## 2. 模拟数据优化
- [x] 2.1 优化银行端审核列表模拟数据,确保包含所有贷款状态
- [x] 2.2 优化用户端申请记录模拟数据,为处理中状态添加银行受理人信息
- [x] 2.3 优化商家端贷款协助模拟数据,确保包含不同状态和银行受理人信息
- [x] 2.4 添加征信信息模拟数据
- [x] 2.5 添加信用评估分数模拟数据
- [x] 2.6 添加用户商城消费订单模拟数据到贷款申请详情
- [x] 2.7 修改商家端订单模拟数据使用用户端商品信息mockGoodsList
- [x] 2.8 修改商家端商品模拟数据使用用户端商品信息mockGoodsList
## 3. 银行端审核列表页面(/pagesBank/audit/list
- [x] 3.1 更新模拟数据,确保包含所有贷款状态
- [x] 3.2 验证列表页面能正确显示不同状态的申请记录
- [x] 3.3 验证状态标签颜色和文本显示正确
- [x] 3.4 添加状态筛选 Tab 组件,支持快速切换查看不同状态的申请记录
- [x] 3.5 实现 Tab 切换逻辑,根据选中状态过滤显示的申请记录
- [x] 3.6 验证 Tab 切换功能正常工作
## 4. 用户端申请记录页面(/pages/me/loan-application-records
- [x] 4.1 在处理中状态的申请记录卡片中添加银行受理人信息展示区域
- [x] 4.2 实现受理人姓名和手机号码的显示
- [x] 4.3 实现手机号码点击拨打功能
- [x] 4.4 确保非处理中状态不显示受理人信息
- [x] 4.5 在详情弹窗中也添加银行受理人信息展示
## 5. 商家端贷款协助页面(/pagesMerchant/loan/assist
- [x] 5.1 更新模拟数据,确保包含不同状态的贷款申请
- [x] 5.2 确保商家端数据与银行端保持一致
- [x] 5.3 移除银行受理人信息卡片(已无此卡片)
- [x] 5.4 显示申请进度及每个进度的负责人姓名和手机号码(仅已执行的进度显示)
- [x] 5.5 修改页面标题,将"贷款辅助材料"显示为"辅助贷款材料"
- [x] 5.6 添加状态筛选 Tab 组件,支持快速切换查看不同状态的申请记录
- [x] 5.7 实现 Tab 切换逻辑,根据选中状态过滤显示的申请记录
- [x] 5.8 验证 Tab 切换功能正常工作
- [x] 5.9 验证未执行的进度不显示负责人信息
## 6. 银行端审核详情页面(/pagesBank/audit/detail
- [x] 6.1 添加"查询征信"按钮
- [x] 6.2 实现征信查询弹窗组件
- [x] 6.3 实现征信信息模拟查询功能(包含加载状态)
- [x] 6.4 添加平台信用评估分数展示区域
- [x] 6.5 添加免责声明:"仅供参考,不构成专业建议,实际应用请以权威数据为准。"
- [x] 6.6 优化关联商家信息展示
- [x] 6.7 更新商家附件图片路径,使用 src/static/fb 目录中的资源
- [x] 6.8 实现平台信用评估和征信查询功能完成后隐藏刷新按钮
- [x] 6.9 修改状态标签显示中文状态文本(如"已拒绝"而非"rejected"
- [x] 6.10 优化查询征信功能,使其与平台信用评估功能保持一致
- [x] 6.11 添加用户商城消费订单信息展示区域
- [x] 6.12 实现订单列表展示(订单号、商品名称、数量、金额等)
- [x] 6.13 验证订单信息正确显示
## 7. 商家端订单管理页面(/pagesMerchant/order/list
- [x] 7.1 修改订单模拟数据使用用户端商品信息mockGoodsList
- [x] 7.2 确保订单中的商品ID与用户端商品ID一致
- [x] 7.3 确保订单中的商品名称、图片、价格与用户端商品一致
- [x] 7.4 验证订单列表正确显示商品信息
## 8. 商家端商品管理页面(/pagesMerchant/goods/list
- [x] 8.1 修改商品模拟数据使用用户端商品信息mockGoodsList
- [x] 8.2 确保商品ID、名称、图片、价格、库存、销量与用户端一致
- [x] 8.3 确保商品分类信息与用户端一致
- [x] 8.4 验证商品列表正确显示
## 9. 商家端页面标题修改
- [x] 9.1 修改商家端贷款协助页面标题,将"贷款辅助材料"显示为"辅助贷款材料"
- [x] 9.2 验证修改后的标题显示正确
## 10. 所有端模拟数据补充
- [x] 10.1 添加"驳回要求补充资料"状态到模拟数据
- [x] 10.2 确保银行端、用户端、商家端都包含该状态的模拟数据
- [x] 10.3 验证各端能正确显示"驳回要求补充资料"状态
## 11. 静态资源准备
- [x] 11.1 确认 src/static/fb 目录存在
- [x] 11.2 准备商家附件图片资源(如需要)
## 12. 测试验证
- [x] 12.1 验证银行端审核列表显示所有状态
- [x] 12.2 验证用户端处理中申请显示银行受理人信息
- [x] 12.3 验证商家端已移除银行受理人信息卡片
- [x] 12.4 验证商家端未执行的进度不显示负责人信息
- [x] 12.5 验证银行端审核列表状态筛选 Tab 功能
- [x] 12.6 验证商家端贷款协助页面状态筛选 Tab 功能
- [x] 12.7 验证商家端页面标题显示为"辅助贷款材料"
- [x] 12.8 验证银行端审核详情征信查询功能
- [x] 12.9 验证银行端审核详情信用评估分数显示
- [x] 12.10 验证商家附件图片正确加载
- [x] 12.11 验证用户端手机号码拨打功能
- [x] 12.12 验证平台信用评估和征信查询完成后刷新按钮隐藏
- [x] 12.13 验证状态标签显示中文状态文本
- [x] 12.14 验证商家端显示申请进度及已执行进度的负责人信息
- [x] 12.15 验证所有端包含"驳回要求补充资料"状态
- [x] 12.16 验证银行端审核详情显示用户商城消费订单信息
- [x] 12.17 验证商家端订单数据与用户端商品信息一致
- [x] 12.18 验证商家端商品数据与用户端商品信息一致

View File

@@ -79,26 +79,57 @@ let mockDatabase: LoanApplication[] = []
export function getLoanApplicationList(params: any) {
return new Promise<{ list: LoanApplication[], total: number }>((resolve) => {
setTimeout(() => {
// 如果没有数据,初始化一些 Mock 数据
// 如果没有数据,初始化一些 Mock 数据,包含所有状态
if (mockDatabase.length === 0) {
mockDatabase = [
{
id: 'LA20251219001',
id: 'LA20251226001',
userId: 'U001',
userName: '张三',
userPhone: '13800138000',
amount: 50,
term: 1,
status: LoanStatus.SUBMITTED,
createTime: '2025-12-19 10:00:00',
updateTime: '2025-12-19 10:00:00',
createTime: '2025-12-26 09:00:00',
updateTime: '2025-12-26 09:00:00',
userOrders: [
{
orderNo: 'O20251226001',
goodsName: '桂味新鲜荔枝现摘现发当季水果自家果园荔枝',
goodsImage: '/static/product/1/1.jpg',
quantity: 2,
amount: 40.00,
orderTime: '2025-12-20 10:30:00',
status: '已完成'
},
{
orderNo: 'O20251226002',
goodsName: '老农田桂圆肉干无核新货8a龙眼肉干500g厚元肉干',
goodsImage: '/static/product/2/1.jpg',
quantity: 1,
amount: 50.00,
orderTime: '2025-12-15 14:20:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M001',
merchantName: '乐高玩具旗舰店',
lastTradeTime: '2025-12-01',
selected: true,
assistStatus: 'pending'
assistStatus: 'pending',
materials: {
merchantId: 'M001',
merchantName: '乐高玩具旗舰店',
loanApplicationId: 'LA20251226001',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 09:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 09:00:00' }
],
submitTime: '2025-12-26 09:00:00',
status: 'submitted'
}
}
],
personalInfo: {
@@ -121,13 +152,636 @@ export function getLoanApplicationList(params: any) {
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226002',
userId: 'U002',
userName: '李四',
userPhone: '13900139000',
amount: 80,
term: 2,
status: LoanStatus.ACCEPTED,
handlerName: '王经理',
handlerPhone: '13800138888',
createTime: '2025-12-25 14:30:00',
updateTime: '2025-12-25 15:00:00',
userOrders: [
{
orderNo: 'O20251225001',
goodsName: '自然禾方化橘红陈皮无糖植物饮料350ml*9瓶整箱装',
goodsImage: '/static/product/3/1.jpg',
quantity: 2,
amount: 100.00,
orderTime: '2025-12-18 09:15:00',
status: '已完成'
},
{
orderNo: 'O20251225002',
goodsName: '沉香原木摆件老料虫漏原材料天然刮香',
goodsImage: '/static/product/4/1.jpg',
quantity: 1,
amount: 152.00,
orderTime: '2025-12-10 16:45:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M002',
merchantName: '迪士尼官方店',
lastTradeTime: '2025-11-20',
selected: true,
assistStatus: 'pending',
materials: {
merchantId: 'M002',
merchantName: '迪士尼官方店',
loanApplicationId: 'LA20251226002',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-25 14:30:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-25 14:30:00' }
],
submitTime: '2025-12-25 14:30:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '李四',
phone: '13900139000',
idCard: '440106199002021234',
region: ['广东省', '深圳市', '南山区'],
detailAddress: '科技园路2号'
},
businessInfo: {
businessProject: '玩具批发',
businessTime: '5年',
annualIncome: 150,
hasDebt: 'no',
loanDemand: 80,
assets: ['house']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226003',
userId: 'U003',
userName: '王五',
userPhone: '13700137000',
amount: 30,
term: 1,
status: LoanStatus.INVESTIGATING,
handlerName: '刘经理',
handlerPhone: '13800139999',
createTime: '2025-12-24 10:00:00',
updateTime: '2025-12-25 16:00:00',
userOrders: [
{
orderNo: 'O20251224001',
goodsName: '罗非鱼苗新吉富雄性淡水养殖特大鱼耐寒',
goodsImage: '/static/product/6/1.jpg',
quantity: 5,
amount: 50.00,
orderTime: '2025-12-12 11:20:00',
status: '已完成'
},
{
orderNo: 'O20251224002',
goodsName: '三华李5斤新鲜李子孕妇水果现摘大果珍珠青李',
goodsImage: '/static/product/7/1.jpg',
quantity: 1,
amount: 30.00,
orderTime: '2025-12-08 15:30:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M003',
merchantName: '泡泡玛特',
lastTradeTime: '2025-11-15',
selected: true,
assistStatus: 'submitted',
materials: {
merchantId: 'M003',
merchantName: '泡泡玛特',
loanApplicationId: 'LA20251226003',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 10:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 10:00:00' }
],
submitTime: '2025-12-26 10:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '王五',
phone: '13700137000',
idCard: '440106199003031234',
region: ['广东省', '广州市', '越秀区'],
detailAddress: '北京路3号'
},
businessInfo: {
businessProject: '玩具零售',
businessTime: '2年',
annualIncome: 80,
hasDebt: 'yes',
debtAmount: 10,
loanDemand: 30,
assets: ['car']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226004',
userId: 'U004',
userName: '赵六',
userPhone: '13600136000',
amount: 100,
term: 3,
status: LoanStatus.REPORTED,
handlerName: '陈经理',
handlerPhone: '13800137777',
createTime: '2025-12-23 11:00:00',
updateTime: '2025-12-25 17:00:00',
userOrders: [
{
orderNo: 'O20251223001',
goodsName: '茂名特产正宗黑豆干豆豉豉原味古法工艺散装',
goodsImage: '/static/product/10/1.jpg',
quantity: 3,
amount: 97.50,
orderTime: '2025-12-05 10:10:00',
status: '已完成'
},
{
orderNo: 'O20251223002',
goodsName: '电白绿奇线香纯手工电白绿奇手工香电白绿奇楠老料',
goodsImage: '/static/product/9/1.jpg',
quantity: 2,
amount: 91.20,
orderTime: '2025-11-28 14:50:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M004',
merchantName: '奥特曼官方玩具店',
lastTradeTime: '2025-11-10',
selected: true,
assistStatus: 'submitted',
materials: {
merchantId: 'M004',
merchantName: '奥特曼官方玩具店',
loanApplicationId: 'LA20251226004',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 11:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 11:00:00' }
],
submitTime: '2025-12-26 11:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '赵六',
phone: '13600136000',
idCard: '440106199004041234',
region: ['广东省', '珠海市', '香洲区'],
detailAddress: '情侣路4号'
},
businessInfo: {
businessProject: '玩具连锁',
businessTime: '8年',
annualIncome: 200,
hasDebt: 'no',
loanDemand: 100,
assets: ['house', 'car', 'shop']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226005',
userId: 'U005',
userName: '孙七',
userPhone: '13500135000',
amount: 60,
term: 2,
status: LoanStatus.APPROVED,
handlerName: '周经理',
handlerPhone: '13800136666',
createTime: '2025-12-22 09:00:00',
updateTime: '2025-12-25 18:00:00',
userOrders: [
{
orderNo: 'O20251222001',
goodsName: '茂名特产籺籺寿桃籺籺菠萝叶籺籺电白高州籺籺',
goodsImage: '/static/product/11/1.jpg',
quantity: 2,
amount: 30.00,
orderTime: '2025-12-01 09:25:00',
status: '已完成'
},
{
orderNo: 'O20251222002',
goodsName: '凤球唛唛瑶柱鲍鱼汁290g/瓶海参即食捞饭',
goodsImage: '/static/product/12/1.jpg',
quantity: 1,
amount: 10.00,
orderTime: '2025-11-25 13:40:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M005',
merchantName: '玩具反斗城',
lastTradeTime: '2025-11-05',
selected: true,
assistStatus: 'submitted',
materials: {
merchantId: 'M005',
merchantName: '玩具反斗城',
loanApplicationId: 'LA20251226005',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 12:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 12:00:00' }
],
submitTime: '2025-12-26 12:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '孙七',
phone: '13500135000',
idCard: '440106199005051234',
region: ['广东省', '广州市', '番禺区'],
detailAddress: '番禺大道5号'
},
businessInfo: {
businessProject: '玩具批发',
businessTime: '6年',
annualIncome: 120,
hasDebt: 'no',
loanDemand: 60,
assets: ['house', 'shop']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226006',
userId: 'U006',
userName: '周八',
userPhone: '13400134000',
amount: 40,
term: 1,
status: LoanStatus.REJECTED,
handlerName: '吴经理',
handlerPhone: '13800135555',
createTime: '2025-12-21 14:00:00',
updateTime: '2025-12-24 10:00:00',
userOrders: [
{
orderNo: 'O20251221001',
goodsName: '灰色西装套装女春秋高级感气质显瘦时尚通勤连衣',
goodsImage: '/static/product/14/1.jpg',
quantity: 1,
amount: 150.00,
orderTime: '2025-11-20 10:55:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M006',
merchantName: 'KidsLand',
lastTradeTime: '2025-10-20',
selected: true,
assistStatus: 'pending',
materials: {
merchantId: 'M006',
merchantName: 'KidsLand',
loanApplicationId: 'LA20251226006',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 13:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 13:00:00' }
],
submitTime: '2025-12-26 13:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '周八',
phone: '13400134000',
idCard: '440106199006061234',
region: ['广东省', '广州市', '海珠区'],
detailAddress: '江南大道6号'
},
businessInfo: {
businessProject: '玩具零售',
businessTime: '1年',
annualIncome: 50,
hasDebt: 'yes',
debtAmount: 20,
loanDemand: 40,
assets: []
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226007',
userId: 'U007',
userName: '郑九',
userPhone: '13300133000',
amount: 70,
term: 2,
status: LoanStatus.SIGNED,
handlerName: '郑经理',
handlerPhone: '13800134444',
createTime: '2025-12-20 10:00:00',
updateTime: '2025-12-26 09:00:00',
userOrders: [
{
orderNo: 'O20251220001',
goodsName: '竹编竹篮子高档手提中秋月饼包装礼盒端午节粽子',
goodsImage: '/static/product/17/1.jpg',
quantity: 2,
amount: 30.00,
orderTime: '2025-11-15 14:30:00',
status: '已完成'
},
{
orderNo: 'O20251220002',
goodsName: '洗面奶专用清爽控油祛痘洁面乳去油去黑头',
goodsImage: '/static/product/18/1.jpg',
quantity: 1,
amount: 45.00,
orderTime: '2025-11-10 09:20:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M001',
merchantName: '乐高玩具旗舰店',
lastTradeTime: '2025-12-01',
selected: true,
assistStatus: 'submitted',
materials: {
merchantId: 'M001',
merchantName: '乐高玩具旗舰店',
loanApplicationId: 'LA20251226007',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 14:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 14:00:00' }
],
submitTime: '2025-12-26 14:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '郑九',
phone: '13300133000',
idCard: '440106199007071234',
region: ['广东省', '广州市', '白云区'],
detailAddress: '白云大道7号'
},
businessInfo: {
businessProject: '玩具零售',
businessTime: '4年',
annualIncome: 110,
hasDebt: 'no',
loanDemand: 70,
assets: ['house', 'car']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226008',
userId: 'U008',
userName: '王十',
userPhone: '13200132000',
amount: 90,
term: 3,
status: LoanStatus.DISBURSED,
handlerName: '冯经理',
handlerPhone: '13800133333',
createTime: '2025-12-19 11:00:00',
updateTime: '2025-12-26 10:00:00',
userOrders: [
{
orderNo: 'O20251219001',
goodsName: '100寸防爆电视机4K高清智能网络平板',
goodsImage: '/static/product/13/1.jpg',
quantity: 1,
amount: 500.00,
orderTime: '2025-11-05 11:45:00',
status: '已完成'
},
{
orderNo: 'O20251219002',
goodsName: '原创汉服改良交领刺绣织金妆花黑色马面裙女冬款',
goodsImage: '/static/product/15/1.jpg',
quantity: 1,
amount: 90.00,
orderTime: '2025-10-28 16:20:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M002',
merchantName: '迪士尼官方店',
lastTradeTime: '2025-11-20',
selected: true,
assistStatus: 'submitted',
materials: {
merchantId: 'M002',
merchantName: '迪士尼官方店',
loanApplicationId: 'LA20251226008',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 15:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 15:00:00' }
],
submitTime: '2025-12-26 15:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '王十',
phone: '13200132000',
idCard: '440106199008081234',
region: ['广东省', '广州市', '荔湾区'],
detailAddress: '中山八路8号'
},
businessInfo: {
businessProject: '玩具批发',
businessTime: '7年',
annualIncome: 180,
hasDebt: 'no',
loanDemand: 90,
assets: ['house', 'shop']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: []
},
{
id: 'LA20251226009',
userId: 'U009',
userName: '钱十一',
userPhone: '13100131000',
amount: 45,
term: 1,
status: LoanStatus.PENDING_SUPPLEMENT,
handlerName: '吴经理',
handlerPhone: '13800132222',
createTime: '2025-12-18 13:00:00',
updateTime: '2025-12-26 16:00:00',
userOrders: [
{
orderNo: 'O20251218001',
goodsName: '正宗化州拖罗饼金腿拖罗大饼广式月饼中秋特产',
goodsImage: '/static/product/8/1.jpg',
quantity: 1,
amount: 30.00,
orderTime: '2025-10-15 10:30:00',
status: '已完成'
},
{
orderNo: 'O20251218002',
goodsName: '天然玉石玉雕龙船一帆风顺摆件家居装饰品',
goodsImage: '/static/product/16/1.jpg',
quantity: 1,
amount: 168.00,
orderTime: '2025-10-10 14:15:00',
status: '已完成'
}
],
relatedMerchants: [
{
merchantId: 'M003',
merchantName: '泡泡玛特',
lastTradeTime: '2025-11-15',
selected: true,
assistStatus: 'pending',
materials: {
merchantId: 'M003',
merchantName: '泡泡玛特',
loanApplicationId: 'LA20251226009',
materials: [
{ type: 'invoice', url: '/static/fb/1.jpg', name: '发票', uploadTime: '2025-12-26 16:00:00' },
{ type: 'contract', url: '/static/fb/2.jpg', name: '合同', uploadTime: '2025-12-26 16:00:00' }
],
submitTime: '2025-12-26 16:00:00',
status: 'submitted'
}
}
],
personalInfo: {
name: '钱十一',
phone: '13100131000',
idCard: '440106199009091234',
region: ['广东省', '广州市', '黄埔区'],
detailAddress: '黄埔大道9号'
},
businessInfo: {
businessProject: '玩具零售',
businessTime: '1.5年',
annualIncome: 60,
hasDebt: 'yes',
debtAmount: 15,
loanDemand: 45,
assets: ['car']
},
documentInfo: {
businessLicense: 'https://via.placeholder.com/150',
otherMaterials: []
},
processRecords: [
{
step: 'accept',
operator: '王经理',
operateTime: '2025-12-18 14:00:00',
result: 'pass'
},
{
step: 'investigate',
operator: '刘经理',
operateTime: '2025-12-20 10:00:00',
result: 'pass',
opinion: '经营情况良好但需要补充近3个月银行流水'
},
{
step: 'report',
operator: '陈经理',
operateTime: '2025-12-26 16:00:00',
result: 'reject',
opinion: '资料不全要求补充近3个月银行流水和纳税证明'
}
]
}
]
}
// 根据参数过滤数据
let filteredList = [...mockDatabase]
console.log('getLoanApplicationList - params:', params)
console.log('getLoanApplicationList - mockDatabase length:', mockDatabase.length)
// 按状态过滤
if (params.status) {
console.log('按状态过滤:', params.status)
filteredList = filteredList.filter(item => item.status === params.status)
console.log('过滤后数量:', filteredList.length)
}
// 按关键词过滤
if (params.keyword) {
const keyword = params.keyword.toLowerCase()
filteredList = filteredList.filter(item =>
item.userName.toLowerCase().includes(keyword) ||
item.id.toLowerCase().includes(keyword)
)
}
console.log('最终返回数量:', filteredList.length)
resolve({
list: mockDatabase,
total: mockDatabase.length
list: filteredList,
total: filteredList.length
})
}, 500)
})
@@ -191,15 +845,84 @@ export function getMerchantPendingAssistList() {
return new Promise<{ list: any[] }>((resolve) => {
setTimeout(() => {
// 找到所有关联了当前商家的未处理申请
// 这里简化逻辑,直接返回 Mock
// 这里简化逻辑,直接返回 Mock,包含不同状态
resolve({
list: [
{
loanId: 'LA20251219001',
userName: '张三',
applyTime: '2025-12-19 10:00:00',
amount: 50,
status: 'pending'
loanId: 'LA20251226002',
userName: '李四',
applyTime: '2025-12-25 14:30:00',
amount: 80,
status: 'accepted',
handlerName: '王经理',
handlerPhone: '13800138888',
// 申请进度及负责人信息
progress: [
{ step: '提交申请', handlerName: '李四', handlerPhone: '13900139000', time: '2025-12-25 14:30:00', completed: true },
{ step: '银行受理', handlerName: '王经理', handlerPhone: '13800138888', time: '2025-12-25 15:00:00', completed: true },
{ step: '上门调查', handlerName: '刘经理', handlerPhone: '13800139999', time: '', completed: false },
{ step: '审批决策', handlerName: '陈经理', handlerPhone: '13800137777', time: '', completed: false }
]
},
{
loanId: 'LA20251226003',
userName: '王五',
applyTime: '2025-12-24 10:00:00',
amount: 30,
status: 'investigating',
handlerName: '刘经理',
handlerPhone: '13800139999',
progress: [
{ step: '提交申请', handlerName: '王五', handlerPhone: '13700137000', time: '2025-12-24 10:00:00', completed: true },
{ step: '银行受理', handlerName: '王经理', handlerPhone: '13800138888', time: '2025-12-24 11:00:00', completed: true },
{ step: '上门调查', handlerName: '刘经理', handlerPhone: '13800139999', time: '2025-12-25 16:00:00', completed: true },
{ step: '审批决策', handlerName: '陈经理', handlerPhone: '13800137777', time: '', completed: false }
]
},
{
loanId: 'LA20251226004',
userName: '赵六',
applyTime: '2025-12-23 11:00:00',
amount: 100,
status: 'reported',
handlerName: '陈经理',
handlerPhone: '13800137777',
progress: [
{ step: '提交申请', handlerName: '赵六', handlerPhone: '13600136000', time: '2025-12-23 11:00:00', completed: true },
{ step: '银行受理', handlerName: '王经理', handlerPhone: '13800138888', time: '2025-12-23 12:00:00', completed: true },
{ step: '上门调查', handlerName: '刘经理', handlerPhone: '13800139999', time: '2025-12-24 10:00:00', completed: true },
{ step: '审批决策', handlerName: '陈经理', handlerPhone: '13800137777', time: '2025-12-25 17:00:00', completed: true }
]
},
{
loanId: 'LA20251226005',
userName: '孙七',
applyTime: '2025-12-22 09:00:00',
amount: 60,
status: 'approved',
handlerName: '周经理',
handlerPhone: '13800136666',
progress: [
{ step: '提交申请', handlerName: '孙七', handlerPhone: '13500135000', time: '2025-12-22 09:00:00', completed: true },
{ step: '银行受理', handlerName: '王经理', handlerPhone: '13800138888', time: '2025-12-22 10:00:00', completed: true },
{ step: '上门调查', handlerName: '刘经理', handlerPhone: '13800139999', time: '2025-12-23 09:00:00', completed: true },
{ step: '审批决策', handlerName: '陈经理', handlerPhone: '13800137777', time: '2025-12-25 18:00:00', completed: true }
]
},
{
loanId: 'LA20251226009',
userName: '钱十一',
applyTime: '2025-12-18 13:00:00',
amount: 45,
status: 'pending_supplement',
handlerName: '吴经理',
handlerPhone: '13800132222',
progress: [
{ step: '提交申请', handlerName: '钱十一', handlerPhone: '13100131000', time: '2025-12-18 13:00:00', completed: true },
{ step: '银行受理', handlerName: '王经理', handlerPhone: '13800138888', time: '2025-12-18 14:00:00', completed: true },
{ step: '上门调查', handlerName: '刘经理', handlerPhone: '13800139999', time: '2025-12-20 10:00:00', completed: true },
{ step: '审批决策', handlerName: '吴经理', handlerPhone: '13800132222', time: '2025-12-26 16:00:00', completed: true }
]
}
]
})
@@ -213,7 +936,7 @@ export function getMerchantPendingAssistList() {
export function submitAssistMaterial(loanId: string, materials: any[]) {
return new Promise<void>((resolve) => {
setTimeout(() => {
const item = mockDatabase.find(i => i.id === loanId)
const item = mockDatabase.find(i => i.id === loanId)
// 简化:更新第一个匹配的商家状态
if (item && item.relatedMerchants.length > 0) {
item.relatedMerchants[0].assistStatus = 'submitted'
@@ -230,3 +953,82 @@ export function submitAssistMaterial(loanId: string, materials: any[]) {
}, 800)
})
}
/**
* [银行端] 查询征信信息
*/
export function queryCreditInfo(userId: string) {
return new Promise<any>((resolve) => {
setTimeout(() => {
resolve({
creditScore: 720,
creditLevel: '良好',
loanRecords: [
{
bank: '工商银行',
amount: 30,
status: 'paid',
date: '2022-03-15'
},
{
bank: '建设银行',
amount: 50,
status: 'normal',
date: '2023-06-20'
},
{
bank: '农业银行',
amount: 20,
status: 'overdue',
date: '2021-11-10'
}
],
overdueRecords: [
{
amount: 20,
overdueDays: 15,
date: '2021-11-10'
}
],
queryTime: new Date().toLocaleString()
})
}, 1500)
})
}
/**
* [银行端] 获取信用评估分数
*/
export function getCreditAssessment(userId: string) {
return new Promise<any>((resolve) => {
setTimeout(() => {
resolve({
score: 78,
level: '良好',
factors: [
{
name: '收入稳定性',
score: 85,
description: '年收入稳定,无大额波动'
},
{
name: '负债率',
score: 75,
description: '负债率适中,还款能力良好'
},
{
name: '征信记录',
score: 70,
description: '存在少量逾期记录,需注意'
},
{
name: '经营年限',
score: 82,
description: '经营年限较长,经验丰富'
}
],
updateTime: new Date().toLocaleString()
})
}, 800)
})
}

View File

@@ -24,6 +24,8 @@ export const mockLoanApplicationRecords: LoanApplicationRecord[] = [
type: "info",
content: "您的申请正在风控部门审核中预计还需要1-2个工作日完成评估"
},
handlerName: "王经理",
handlerPhone: "13800138888",
actions: [
{
code: "VIEW_DETAIL",
@@ -104,6 +106,8 @@ export const mockLoanApplicationRecords: LoanApplicationRecord[] = [
type: "info",
content: "您的申请已进入资料审核阶段,请耐心等待"
},
handlerName: "刘经理",
handlerPhone: "13800139999",
actions: [
{
code: "CANCEL",

View File

@@ -73,6 +73,13 @@ function handleActionClick(record: LoanApplicationRecord, action: any) {
}
}
// 拨打银行受理人电话
function handleCallPhone(phone: string) {
uni.makePhoneCall({
phoneNumber: phone
})
}
// 获取状态颜色
function getStatusColor(status: LoanApplicationStatus) {
switch (status) {
@@ -185,10 +192,25 @@ function getButtonStyle(style: string) {
</view>
</view>
<!-- 银行受理人信息仅处理中状态显示 -->
<view v-if="record.status === 'PROCESSING' && record.handlerName" class="handler-section">
<view class="handler-info">
<text class="i-carbon-user handler-icon"></text>
<view class="handler-details">
<text class="handler-label">银行受理人</text>
<text class="handler-name">{{ record.handlerName }}</text>
<view class="handler-phone-wrapper" @click="handleCallPhone(record.handlerPhone)">
<text class="i-carbon-phone handler-phone-icon"></text>
<text class="handler-phone">{{ record.handlerPhone }}</text>
</view>
</view>
</view>
</view>
<!-- 底部操作区 -->
<view class="actions-section">
<view
v-for="action in record.actions"
<view
v-for="action in record.actions"
:key="action.code"
class="action-btn"
:style="getButtonStyle(action.style)"
@@ -251,18 +273,33 @@ function getButtonStyle(style: string) {
</view>
</view>
<!-- 银行受理人信息仅处理中状态显示 -->
<view v-if="selectedRecord.status === 'PROCESSING' && selectedRecord.handlerName" class="handler-detail">
<text class="detail-label">银行受理人</text>
<view class="handler-detail-info">
<view class="handler-detail-row">
<text class="i-carbon-user handler-detail-icon"></text>
<text class="handler-detail-name">{{ selectedRecord.handlerName }}</text>
</view>
<view class="handler-detail-row handler-detail-phone" @click="handleCallPhone(selectedRecord.handlerPhone)">
<text class="i-carbon-phone handler-detail-icon"></text>
<text class="handler-detail-phone-number">{{ selectedRecord.handlerPhone }}</text>
</view>
</view>
</view>
<!-- 提示信息 -->
<view v-if="selectedRecord.alertInfo && selectedRecord.alertInfo.show" class="alert-detail">
<view
<view
class="alert-detail-box"
:class="selectedRecord.alertInfo.type"
>
<text
v-if="selectedRecord.alertInfo.type === 'info'"
<text
v-if="selectedRecord.alertInfo.type === 'info'"
class="i-carbon-information alert-icon"
></text>
<text
v-else-if="selectedRecord.alertInfo.type === 'warning'"
<text
v-else-if="selectedRecord.alertInfo.type === 'warning'"
class="i-carbon-warning-alt alert-icon"
></text>
<text>{{ selectedRecord.alertInfo.content }}</text>
@@ -451,6 +488,58 @@ function getButtonStyle(style: string) {
}
}
.handler-section {
margin-bottom: 24rpx;
.handler-info {
background: linear-gradient(135deg, #3B82F6 0%, #60A5FA 100%);
border-radius: 12rpx;
padding: 20rpx;
display: flex;
align-items: center;
gap: 16rpx;
.handler-icon {
font-size: 48rpx;
color: #fff;
}
.handler-details {
flex: 1;
display: flex;
flex-direction: column;
gap: 8rpx;
.handler-label {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.8);
}
.handler-name {
font-size: 28rpx;
font-weight: 600;
color: #fff;
}
.handler-phone-wrapper {
display: flex;
align-items: center;
gap: 8rpx;
.handler-phone-icon {
font-size: 24rpx;
color: #fff;
}
.handler-phone {
font-size: 26rpx;
color: #fff;
}
}
}
}
}
.actions-section {
display: flex;
justify-content: flex-end;
@@ -612,6 +701,52 @@ function getButtonStyle(style: string) {
}
}
.handler-detail {
padding: 20rpx 0;
.detail-label {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
display: block;
}
.handler-detail-info {
background: linear-gradient(135deg, #3B82F6 0%, #60A5FA 100%);
border-radius: 12rpx;
padding: 20rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
.handler-detail-row {
display: flex;
align-items: center;
gap: 12rpx;
.handler-detail-icon {
font-size: 32rpx;
color: #fff;
}
.handler-detail-name {
font-size: 28rpx;
font-weight: 600;
color: #fff;
}
&.handler-detail-phone {
cursor: pointer;
.handler-detail-phone-number {
font-size: 26rpx;
color: #fff;
}
}
}
}
}
.alert-detail {
padding: 20rpx 0;

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { getLoanApplicationDetail, operateLoanApplication } from '@/api/loan'
import { getLoanApplicationDetail, operateLoanApplication, queryCreditInfo, getCreditAssessment } from '@/api/loan'
import { LoanStatus } from '@/typings/loan'
import type { LoanApplication, RelatedMerchant } from '@/typings/loan'
import { mockTransactions } from '@/pagesBank/mock'
@@ -14,6 +14,14 @@ const id = ref('')
const detail = ref<LoanApplication | null>(null)
const loading = ref(false)
// 征信信息
const creditInfo = ref<any>(null)
const creditLoading = ref(false)
// 信用评估数据
const creditAssessment = ref<any>(null)
const assessmentLoading = ref(false)
// 流程步骤定义
const steps = [
{ key: LoanStatus.SUBMITTED, label: '申请' },
@@ -24,6 +32,28 @@ const steps = [
{ key: LoanStatus.DISBURSED, label: '放款' }
]
// 状态中文映射
const statusTextMap: Record<string, string> = {
[LoanStatus.DRAFT]: '草稿',
[LoanStatus.SUBMITTED]: '新申请',
[LoanStatus.ACCEPTED]: '已受理',
[LoanStatus.INVESTIGATING]: '调查中',
[LoanStatus.REPORTED]: '待审批',
[LoanStatus.APPROVING]: '审批中',
[LoanStatus.APPROVED]: '已通过',
[LoanStatus.REJECTED]: '已拒绝',
[LoanStatus.PENDING_SUPPLEMENT]: '驳回要求补充资料',
[LoanStatus.SIGNING]: '待签约',
[LoanStatus.SIGNED]: '已签约',
[LoanStatus.DISBURSED]: '已放款'
}
// 获取状态中文文本
const statusText = computed(() => {
if (!detail.value) return ''
return statusTextMap[detail.value.status] || detail.value.status
})
// 获取当前步骤索引
const currentStepIndex = computed(() => {
if (!detail.value) return 0
@@ -98,6 +128,28 @@ function previewImage(url: string) {
uni.previewImage({ urls: [url] })
}
// 查询征信信息
async function handleQueryCredit() {
if (!detail.value) return
creditLoading.value = true
try {
creditInfo.value = await queryCreditInfo(detail.value.userId)
} finally {
creditLoading.value = false
}
}
// 获取信用评估
async function handleGetAssessment() {
if (!detail.value) return
assessmentLoading.value = true
try {
creditAssessment.value = await getCreditAssessment(detail.value.userId)
} finally {
assessmentLoading.value = false
}
}
onLoad((options) => {
if (options?.id) {
id.value = options.id
@@ -137,7 +189,7 @@ onLoad((options) => {
<text class="name">{{ detail.personalInfo.name }}</text>
<text class="phone">{{ detail.personalInfo.phone }}</text>
</div>
<text class="status-tag">{{ detail.status }}</text>
<text class="status-tag">{{ statusText }}</text>
</div>
<div class="amount-box">
<div class="item">
@@ -151,16 +203,94 @@ onLoad((options) => {
</div>
</view>
<!-- 平台交易流水(Mock) -->
<!-- 征信信息 -->
<view class="section-card">
<view class="card-header">平台交易流水 (最近5笔)</view>
<view class="transaction-list">
<view class="t-item" v-for="t in mockTransactions" :key="t.id">
<view class="t-main">
<text class="t-title">{{ t.title }}</text>
<text class="t-time">{{ t.time }}</text>
<view class="card-header">
<text class="title">征信信息</text>
<button v-if="!creditInfo" class="credit-btn" @click="handleQueryCredit" :disabled="creditLoading">
<text v-if="creditLoading">查询中...</text>
<text v-else>查询征信</text>
</button>
<button v-else class="refresh-btn" @click="handleQueryCredit" :disabled="creditLoading">
<text v-if="creditLoading">加载中...</text>
<text v-else class="i-carbon-reset"></text>
</button>
</view>
<view v-if="creditInfo" class="credit-content">
<view class="credit-score-box">
<view class="credit-score">
<text class="score-label">征信分数</text>
<text class="score-value">{{ creditInfo.creditScore }}</text>
<text class="score-level">{{ creditInfo.creditLevel }}</text>
</view>
<text class="t-amount" :class="t.type">{{ t.type === 'expend' ? '-' : '+' }}{{ t.amount }}</text>
<text class="query-time">查询时间{{ creditInfo.queryTime }}</text>
</view>
<view class="section-title">贷款记录</view>
<view class="loan-records">
<view v-for="(record, index) in creditInfo.loanRecords" :key="index" class="loan-record-item">
<view class="record-info">
<text class="bank-name">{{ record.bank }}</text>
<text class="record-amount">{{ record.amount }}</text>
</view>
<view class="record-status" :class="record.status">
<text v-if="record.status === 'normal'" class="i-carbon-checkmark"></text>
<text v-else-if="record.status === 'overdue'" class="i-carbon-warning"></text>
<text v-else class="i-carbon-time"></text>
<text class="status-text">{{ record.status === 'normal' ? '正常' : record.status === 'overdue' ? '逾期' : '已还' }}</text>
</view>
<text class="record-date">{{ record.date }}</text>
</view>
</view>
<view v-if="creditInfo.overdueRecords && creditInfo.overdueRecords.length" class="section-title">逾期记录</view>
<view v-if="creditInfo.overdueRecords && creditInfo.overdueRecords.length" class="overdue-records">
<view v-for="(record, index) in creditInfo.overdueRecords" :key="index" class="overdue-item">
<view class="overdue-info">
<text class="overdue-amount">{{ record.amount }}</text>
<text class="overdue-days">逾期{{ record.overdueDays }}</text>
</view>
<text class="overdue-date">{{ record.date }}</text>
</view>
</view>
<view class="disclaimer">
<text class="i-carbon-information disclaimer-icon"></text>
<text class="disclaimer-text">征信信息仅供参考实际应用请以权威数据为准</text>
</view>
</view>
</view>
<!-- 用户商城消费订单 -->
<view class="section-card">
<view class="card-header">
<text class="title">用户商城消费订单</text>
</view>
<view class="order-list">
<view
v-for="order in detail.userOrders"
:key="order.orderNo"
class="order-item"
>
<view class="order-main">
<image :src="order.goodsImage" class="goods-image" mode="aspectFill" />
<view class="order-info">
<text class="order-no">{{ order.orderNo }}</text>
<text class="goods-name">{{ order.goodsName }}</text>
<view class="order-meta">
<text class="quantity">数量: {{ order.quantity }}</text>
<text class="amount">¥{{ order.amount.toFixed(2) }}</text>
</view>
</view>
</view>
<view class="order-footer">
<text class="order-time">{{ order.orderTime }}</text>
<text class="order-status">{{ order.status }}</text>
</view>
</view>
<view v-if="!detail.userOrders || detail.userOrders.length === 0" class="empty-orders">
<text class="i-carbon-document"></text>
<text>暂无消费订单</text>
</view>
</view>
</view>
@@ -221,6 +351,37 @@ onLoad((options) => {
</view>
</view>
<!-- 信用评估 -->
<view class="section-card">
<view class="card-header">
<text class="title">平台信用评估</text>
<button v-if="!creditAssessment" class="refresh-btn" @click="handleGetAssessment" :disabled="assessmentLoading">
<text v-if="assessmentLoading">加载中...</text>
<text v-else class="i-carbon-reset"></text>
</button>
</view>
<view v-if="creditAssessment" class="assessment-content">
<view class="score-box">
<text class="score">{{ creditAssessment.score }}</text>
<text class="unit"></text>
<text class="level" :class="creditAssessment.level">{{ creditAssessment.level }}</text>
</view>
<view class="factors-list">
<view v-for="(factor, index) in creditAssessment.factors" :key="index" class="factor-item">
<view class="factor-header">
<text class="factor-name">{{ factor.name }}</text>
<text class="factor-score">{{ factor.score }}</text>
</view>
<text class="factor-desc">{{ factor.description }}</text>
</view>
</view>
<view class="disclaimer">
<text class="i-carbon-information disclaimer-icon"></text>
<text class="disclaimer-text">仅供参考不构成专业建议实际应用请以权威数据为准</text>
</view>
</view>
</view>
<!-- 底部操作栏 -->
<view class="action-bar safe-area-bottom">
<template v-if="detail.status === LoanStatus.SUBMITTED">
@@ -386,18 +547,130 @@ onLoad((options) => {
font-size: 28rpx;
font-weight: bold;
color: #333;
display: flex;
justify-content: space-between;
align-items: center;
}
.cell-group {
padding: 20rpx 0;
.cell {
.credit-btn {
padding: 8rpx 20rpx;
border-radius: 8rpx;
background: #3B82F6;
color: #fff;
font-size: 24rpx;
border: none;
&:disabled {
opacity: 0.6;
}
}
.refresh-btn {
padding: 8rpx 20rpx;
border-radius: 8rpx;
background: #f5f5f5;
border: 1rpx solid #e5e5e5;
color: #666;
font-size: 24rpx;
&:disabled {
opacity: 0.6;
}
}
}
.order-list {
padding: 20rpx 0;
.order-item {
background: #f8f9fa;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 16rpx;
.order-main {
display: flex;
gap: 16rpx;
margin-bottom: 12rpx;
.goods-image {
width: 100rpx;
height: 100rpx;
border-radius: 8rpx;
flex-shrink: 0;
}
.order-info {
flex: 1;
display: flex;
flex-direction: column;
.order-no {
font-size: 24rpx;
color: #666;
margin-bottom: 8rpx;
}
.goods-name {
font-size: 26rpx;
color: #333;
font-weight: 500;
margin-bottom: 8rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.order-meta {
display: flex;
justify-content: space-between;
align-items: center;
.quantity {
font-size: 24rpx;
color: #666;
}
.amount {
font-size: 28rpx;
color: #ff8f0d;
font-weight: 600;
}
}
}
}
.order-footer {
display: flex;
justify-content: space-between;
padding: 16rpx 0;
font-size: 26rpx;
align-items: center;
padding-top: 12rpx;
border-top: 1rpx solid #e5e5e5;
.label { color: #666; }
.value { color: #333; }
.order-time {
font-size: 22rpx;
color: #999;
}
.order-status {
font-size: 24rpx;
color: #00c05a;
}
}
}
.empty-orders {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
color: #999;
text:first-child {
font-size: 60rpx;
margin-bottom: 16rpx;
}
}
}
@@ -481,6 +754,125 @@ onLoad((options) => {
}
}
.cell-group {
padding: 20rpx 0;
.cell {
display: flex;
justify-content: space-between;
padding: 16rpx 0;
font-size: 26rpx;
.label { color: #666; }
.value { color: #333; }
}
}
.assessment-content {
padding: 20rpx 0;
.score-box {
display: flex;
align-items: baseline;
gap: 12rpx;
margin-bottom: 24rpx;
.score {
font-size: 56rpx;
font-weight: bold;
color: #00c05a;
}
.unit {
font-size: 28rpx;
color: #666;
}
.level {
padding: 8rpx 20rpx;
border-radius: 8rpx;
font-size: 24rpx;
font-weight: 600;
&.优秀 {
background: rgba(0, 192, 90, 0.1);
color: #00c05a;
}
&.良好 {
background: rgba(59, 130, 246, 0.1);
color: #3B82F6;
}
&.一般 {
background: rgba(245, 158, 11, 0.1);
color: #F59E0B;
}
&.较差 {
background: rgba(250, 67, 80, 0.1);
color: #fa4350;
}
}
}
.factors-list {
.factor-item {
display: flex;
flex-direction: column;
padding: 16rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.factor-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8rpx;
.factor-name {
font-size: 26rpx;
color: #333;
}
.factor-score {
font-size: 24rpx;
font-weight: 600;
color: #00c05a;
}
}
.factor-desc {
font-size: 24rpx;
color: #666;
line-height: 1.5;
}
}
}
.disclaimer {
display: flex;
align-items: center;
gap: 8rpx;
padding: 16rpx;
background: #fff7ed;
border-radius: 8rpx;
margin-top: 16rpx;
.disclaimer-icon {
font-size: 24rpx;
color: #F59E0B;
}
.disclaimer-text {
font-size: 22rpx;
color: #999;
}
}
}
.action-bar {
position: fixed;
bottom: 0;
@@ -505,4 +897,153 @@ onLoad((options) => {
&.success { background: #00c05a; color: #fff; }
}
}
// 征信信息内容样式
.credit-content {
padding: 20rpx 0;
.credit-score-box {
background: linear-gradient(135deg, #3B82F6 0%, #60A5FA 100%);
border-radius: 12rpx;
padding: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.credit-score {
display: flex;
align-items: baseline;
gap: 12rpx;
.score-label {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
.score-value {
font-size: 48rpx;
font-weight: bold;
color: #fff;
}
.score-level {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
}
}
.query-time {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.section-title {
font-size: 26rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
}
.loan-records {
.loan-record-item {
display: flex;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.record-info {
flex: 1;
display: flex;
gap: 12rpx;
.bank-name {
font-size: 26rpx;
color: #333;
}
.record-amount {
font-size: 26rpx;
font-weight: 600;
color: #333;
}
}
.record-status {
display: flex;
align-items: center;
gap: 8rpx;
.status-text {
font-size: 24rpx;
color: #666;
}
}
.record-date {
font-size: 22rpx;
color: #999;
margin-left: auto;
}
}
}
.overdue-records {
.overdue-item {
display: flex;
align-items: center;
padding: 16rpx 0;
background: #fff5f5;
border-radius: 8rpx;
margin-bottom: 12rpx;
.overdue-info {
display: flex;
gap: 8rpx;
.overdue-amount {
font-size: 26rpx;
font-weight: 600;
color: #fa4350;
}
.overdue-days {
font-size: 22rpx;
color: #fa4350;
}
}
.overdue-date {
font-size: 22rpx;
color: #999;
margin-left: auto;
}
}
}
.disclaimer {
display: flex;
align-items: center;
gap: 8rpx;
padding: 16rpx;
background: #fff7ed;
border-radius: 8rpx;
margin-top: 16rpx;
.disclaimer-icon {
font-size: 24rpx;
color: #F59E0B;
}
.disclaimer-text {
font-size: 22rpx;
color: #999;
}
}
}
</style>

View File

@@ -13,9 +13,15 @@ definePage({
// 状态标签
const tabs = [
{ label: '全部', value: '' },
{ label: '待处理', value: LoanStatus.SUBMITTED }, // 包含提交/受理等
{ label: '新申请', value: LoanStatus.SUBMITTED },
{ label: '已受理', value: LoanStatus.ACCEPTED },
{ label: '调查中', value: LoanStatus.INVESTIGATING },
{ label: '待审批', value: LoanStatus.REPORTED },
{ label: '已通过', value: LoanStatus.APPROVED },
{ label: '已拒绝', value: LoanStatus.REJECTED },
{ label: '已签约', value: LoanStatus.SIGNED },
{ label: '已放款', value: LoanStatus.DISBURSED },
{ label: '驳回要求补充', value: LoanStatus.PENDING_SUPPLEMENT },
]
const activeTab = ref('')
@@ -32,15 +38,22 @@ const statusMap: Record<string, { text: string; color: string; bgColor: string }
[LoanStatus.REJECTED]: { text: '已拒绝', color: '#fa4350', bgColor: 'rgba(250, 67, 80, 0.1)' },
[LoanStatus.SIGNED]: { text: '已签约', color: '#00c05a', bgColor: 'rgba(0, 192, 90, 0.1)' },
[LoanStatus.DISBURSED]: { text: '已放款', color: '#00c05a', bgColor: 'rgba(0, 192, 90, 0.1)' },
[LoanStatus.PENDING_SUPPLEMENT]: { text: '驳回要求补充', color: '#fa4350', bgColor: 'rgba(250, 67, 80, 0.1)' },
}
async function loadData() {
loading.value = true
try {
const res = await getLoanApplicationList({
const params = {
status: activeTab.value || undefined,
keyword: keyword.value
})
}
console.log('loadData - 请求参数:', params)
console.log('loadData - activeTab.value:', activeTab.value)
const res = await getLoanApplicationList(params)
console.log('loadData - 返回结果:', res)
list.value = res.list
} finally {
loading.value = false
@@ -190,11 +203,20 @@ onPullDownRefresh(() => {
.tabs {
display: flex;
justify-content: space-around;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
border-bottom: 1rpx solid #f1f3f5;
-webkit-overflow-scrolling: touch;
/* 隐藏滚动条 */
&::-webkit-scrollbar {
display: none;
}
.tab-item {
padding: 20rpx 0;
flex-shrink: 0;
padding: 20rpx 24rpx;
font-size: 28rpx;
color: #495057;
position: relative;
@@ -206,8 +228,9 @@ onPullDownRefresh(() => {
.line {
position: absolute;
bottom: 0;
left: 0;
right: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 6rpx;
background: #00c05a;
border-radius: 3rpx;

View File

@@ -57,6 +57,7 @@ export const mockCustomerList: BankCustomer[] = [
id: 'C1001',
merchantId: 'M1001',
merchantName: '张三', // 模拟个人客户
logo: '/static/tc/1.jpg',
creditLimit: 500000.00,
usedLimit: 125000.00,
balance: 375000.00,
@@ -69,6 +70,7 @@ export const mockCustomerList: BankCustomer[] = [
id: 'C1002',
merchantId: 'M1002',
merchantName: '李四', // 模拟个人客户
logo: '/static/tc/2.jpg',
creditLimit: 200000.00,
usedLimit: 180000.00,
balance: 20000.00,
@@ -76,6 +78,162 @@ export const mockCustomerList: BankCustomer[] = [
contactName: '李四',
contactPhone: '139****9999',
joinTime: '2024-06-15'
},
{
id: 'C1003',
merchantId: 'M1003',
merchantName: '王五',
logo: '/static/tc/3.jpg',
creditLimit: 300000.00,
usedLimit: 150000.00,
balance: 150000.00,
status: 'normal',
contactName: '王五',
contactPhone: '136****6666',
joinTime: '2024-03-10'
},
{
id: 'C1004',
merchantId: 'M1004',
merchantName: '赵六',
logo: '/static/tc/4.jpg',
creditLimit: 150000.00,
usedLimit: 145000.00,
balance: 5000.00,
status: 'warning',
contactName: '赵六',
contactPhone: '137****7777',
joinTime: '2024-04-05'
},
{
id: 'C1005',
merchantId: 'M1005',
merchantName: '孙七',
logo: '/static/tc/1.jpg',
creditLimit: 800000.00,
usedLimit: 720000.00,
balance: 80000.00,
status: 'frozen',
contactName: '孙七',
contactPhone: '135****5555',
joinTime: '2024-01-15'
},
{
id: 'C1006',
merchantId: 'M1006',
merchantName: '周八',
logo: '/static/tc/2.jpg',
creditLimit: 250000.00,
usedLimit: 50000.00,
balance: 200000.00,
status: 'normal',
contactName: '周八',
contactPhone: '134****4444',
joinTime: '2024-07-20'
},
{
id: 'C1007',
merchantId: 'M1007',
merchantName: '吴九',
logo: '/static/tc/3.jpg',
creditLimit: 400000.00,
usedLimit: 380000.00,
balance: 20000.00,
status: 'warning',
contactName: '吴九',
contactPhone: '133****3333',
joinTime: '2024-02-28'
},
{
id: 'C1008',
merchantId: 'M1008',
merchantName: '郑十',
logo: '/static/tc/4.jpg',
creditLimit: 600000.00,
usedLimit: 180000.00,
balance: 420000.00,
status: 'normal',
contactName: '郑十',
contactPhone: '132****2222',
joinTime: '2024-05-12'
},
{
id: 'C1009',
merchantId: 'M1009',
merchantName: '钱十一',
logo: '/static/tc/1.jpg',
creditLimit: 350000.00,
usedLimit: 340000.00,
balance: 10000.00,
status: 'warning',
contactName: '钱十一',
contactPhone: '131****1111',
joinTime: '2024-06-30'
},
{
id: 'C1010',
merchantId: 'M1010',
merchantName: '陈十二',
logo: '/static/tc/2.jpg',
creditLimit: 1000000.00,
usedLimit: 850000.00,
balance: 150000.00,
status: 'frozen',
contactName: '陈十二',
contactPhone: '130****0000',
joinTime: '2024-01-08'
},
{
id: 'C1011',
merchantId: 'M1011',
merchantName: '林十三',
logo: '/static/tc/3.jpg',
creditLimit: 280000.00,
usedLimit: 56000.00,
balance: 224000.00,
status: 'normal',
contactName: '林十三',
contactPhone: '158****8888',
joinTime: '2024-08-15'
},
{
id: 'C1012',
merchantId: 'M1012',
merchantName: '黄十四',
logo: '/static/tc/4.jpg',
creditLimit: 450000.00,
usedLimit: 400000.00,
balance: 50000.00,
status: 'warning',
contactName: '黄十四',
contactPhone: '159****9999',
joinTime: '2024-03-22'
},
{
id: 'C1013',
merchantId: 'M1013',
merchantName: '杨十五',
logo: '/static/tc/1.jpg',
creditLimit: 550000.00,
usedLimit: 110000.00,
balance: 440000.00,
status: 'normal',
contactName: '杨十五',
contactPhone: '156****6666',
joinTime: '2024-04-18'
},
{
id: 'C1014',
merchantId: 'M1014',
merchantName: '朱十六',
logo: '/static/tc/2.jpg',
creditLimit: 180000.00,
usedLimit: 162000.00,
balance: 18000.00,
status: 'warning',
contactName: '朱十六',
contactPhone: '157****7777',
joinTime: '2024-07-05'
}
]

View File

@@ -29,7 +29,7 @@ const quickActions = [
{ icon: 'i-carbon-add-alt', label: '新增商品', path: '/pagesMerchant/goods/edit' },
{ icon: 'i-carbon-wallet', label: '财务中心', path: '/pagesMerchant/finance/index' },
{ icon: 'i-carbon-settings', label: '店铺设置', path: '/pagesMerchant/me/shop' },
{ icon: 'i-carbon-document', label: '贷款辅助', path: '/pagesMerchant/loan/assist' },
{ icon: 'i-carbon-document', label: '辅助贷款', path: '/pagesMerchant/loan/assist' },
]
// 加载数据

View File

@@ -3,7 +3,7 @@ import { getMerchantPendingAssistList, submitAssistMaterial } from '@/api/loan'
definePage({
style: {
navigationBarTitleText: '贷款辅助材料',
navigationBarTitleText: '辅助贷款材料',
},
})
@@ -14,8 +14,29 @@ interface LoanItem {
applyTime: string
isExpanded: boolean
materials: { type: string, url: string, name: string }[]
status?: string
// 申请进度及负责人信息
progress?: {
step: string
handlerName: string
handlerPhone: string
time: string
completed: boolean
}[]
}
// 状态筛选 Tab
const statusTabs = [
{ label: '全部', value: '' },
{ label: '已受理', value: 'accepted' },
{ label: '调查中', value: 'investigating' },
{ label: '待审批', value: 'reported' },
{ label: '已通过', value: 'approved' },
{ label: '已拒绝', value: 'rejected' },
{ label: '驳回要求补充', value: 'pending_supplement' },
]
const activeTab = ref('')
const list = ref<LoanItem[]>([])
const loading = ref(false)
@@ -28,11 +49,20 @@ async function loadData() {
isExpanded: false,
materials: []
}))
// 根据选中的状态筛选
if (activeTab.value) {
list.value = list.value.filter(item => item.status === activeTab.value)
}
} finally {
loading.value = false
}
}
function handleTabChange(value: string) {
activeTab.value = value
loadData()
}
function handleExpand(item: LoanItem) {
item.isExpanded = !item.isExpanded
}
@@ -55,6 +85,13 @@ function removeMaterial(item: LoanItem, index: number) {
item.materials.splice(index, 1)
}
// 拨打负责人电话
function handleCallPhone(phone: string) {
uni.makePhoneCall({
phoneNumber: phone
})
}
async function handleSubmit(item: LoanItem) {
if (item.materials.length === 0) {
uni.showToast({ title: '请至少上传一项材料', icon: 'none' })
@@ -80,6 +117,23 @@ onMounted(() => {
<template>
<view class="assist-page">
<!-- 状态筛选 Tab -->
<view class="tabs-container">
<scroll-view scroll-x class="tabs-scroll">
<view class="tabs">
<view
v-for="tab in statusTabs"
:key="tab.value"
class="tab-item"
:class="{ active: activeTab === tab.value }"
@click="handleTabChange(tab.value)"
>
{{ tab.label }}
</view>
</view>
</scroll-view>
</view>
<view v-if="loading && list.length === 0" class="loading">加载中...</view>
<view v-else-if="list.length === 0" class="empty">
@@ -100,6 +154,41 @@ onMounted(() => {
</view>
</view>
<!-- 申请进度及负责人信息 -->
<view v-if="item.progress && item.progress.length" class="progress-section">
<view class="progress-header">
<text class="i-carbon-time progress-icon"></text>
<text class="progress-title">申请进度</text>
</view>
<view class="progress-list">
<view
v-for="(p, idx) in item.progress"
:key="idx"
class="progress-item"
:class="{ completed: p.completed, current: !p.completed && idx > 0 && item.progress[idx - 1].completed }"
>
<view class="progress-dot">
<text v-if="p.completed" class="i-carbon-checkmark"></text>
<text v-else class="dot"></text>
</view>
<view class="progress-content">
<view class="progress-main">
<text class="progress-step">{{ p.step }}</text>
<text v-if="p.time" class="progress-time">{{ p.time }}</text>
</view>
<view class="progress-handler" v-if="p.completed">
<text class="handler-label">负责人</text>
<text class="handler-name">{{ p.handlerName }}</text>
<view class="handler-phone-wrapper" @click="handleCallPhone(p.handlerPhone)">
<text class="i-carbon-phone phone-icon"></text>
<text class="handler-phone">{{ p.handlerPhone }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="action-area" v-if="!item.isExpanded">
<button class="btn primary" @click="handleExpand(item)">提供材料</button>
</view>
@@ -186,6 +275,197 @@ onMounted(() => {
}
}
.tabs-container {
background: #fff;
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f5f5;
position: sticky;
top: 0;
z-index: 100;
.tabs-scroll {
white-space: nowrap;
}
.tabs {
display: inline-flex;
padding: 0 20rpx;
gap: 30rpx;
.tab-item {
font-size: 28rpx;
color: #666;
position: relative;
padding: 10rpx 0;
flex-shrink: 0;
&.active {
color: #00c05a;
font-weight: 600;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: #00c05a;
border-radius: 2rpx;
}
}
}
}
}
.progress-section {
background: #f8f9fa;
border-radius: 12rpx;
padding: 20rpx;
margin-top: 20rpx;
.progress-header {
display: flex;
align-items: center;
gap: 8rpx;
margin-bottom: 16rpx;
.progress-icon {
font-size: 28rpx;
color: #00c05a;
}
.progress-title {
font-size: 26rpx;
font-weight: 600;
color: #333;
}
}
.progress-list {
.progress-item {
display: flex;
gap: 16rpx;
padding-bottom: 20rpx;
position: relative;
&:last-child {
padding-bottom: 0;
}
&:not(:last-child)::after {
content: '';
position: absolute;
left: 11rpx;
top: 32rpx;
bottom: 0;
width: 2rpx;
background: #e5e5e5;
}
.progress-dot {
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background: #e5e5e5;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
color: #fff;
font-size: 16rpx;
z-index: 1;
}
.progress-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 8rpx;
.progress-main {
display: flex;
justify-content: space-between;
align-items: center;
.progress-step {
font-size: 26rpx;
color: #666;
}
.progress-time {
font-size: 22rpx;
color: #999;
}
}
.progress-handler {
display: flex;
align-items: center;
gap: 8rpx;
flex-wrap: wrap;
.handler-label {
font-size: 22rpx;
color: #999;
}
.handler-name {
font-size: 24rpx;
color: #333;
font-weight: 500;
}
.handler-phone-wrapper {
display: flex;
align-items: center;
gap: 4rpx;
padding: 4rpx 12rpx;
background: #e6f7eb;
border-radius: 12rpx;
.phone-icon {
font-size: 20rpx;
color: #00c05a;
}
.handler-phone {
font-size: 22rpx;
color: #00c05a;
}
}
}
}
&.completed {
.progress-dot {
background: #00c05a;
}
.progress-step {
color: #00c05a;
}
&:not(:last-child)::after {
background: #00c05a;
}
}
&.current {
.progress-dot {
background: #3B82F6;
}
.progress-step {
color: #3B82F6;
font-weight: 600;
}
}
}
}
}
.action-area {
border-top: 1rpx solid #f5f5f5;
padding-top: 20rpx;

View File

@@ -1,82 +1,26 @@
/**
* 商户端商品数据 Mock
* 使用用户端商品信息mockGoodsList
*/
import type { MerchantGoods } from '@/typings/merchant'
import { GoodsStatus } from '@/typings/merchant'
import { mockGoodsList } from '@/mock/goods'
export const mockMerchantGoods: MerchantGoods[] = [
{
id: '1',
name: '苹果 iPhone 15 Pro',
categoryId: '1',
categoryName: '手机',
brand: 'Apple',
price: 8999.00,
costPrice: 7500.00,
stock: 50,
sales: 128,
status: GoodsStatus.ON,
images: ['/static/goods/iphone15.jpg'],
description: '全新 iPhone 15 Pro搭载 A17 Pro 芯片',
specs: [
{ name: '颜色', values: ['黑色', '白色', '蓝色'] },
{ name: '存储', values: ['128GB', '256GB', '512GB'] },
],
skuList: [
{ id: 'sku1', specs: { '颜色': '黑色', '存储': '128GB' }, price: 7999, stock: 20, image: '' },
{ id: 'sku2', specs: { '颜色': '黑色', '存储': '256GB' }, price: 8999, stock: 15, image: '' },
{ id: 'sku3', specs: { '颜色': '白色', '存储': '128GB' }, price: 7999, stock: 10, image: '' },
{ id: 'sku4', specs: { '颜色': '白色', '存储': '256GB' }, price: 8999, stock: 5, image: '' },
],
createTime: '2024-12-01 10:00:00',
updateTime: '2024-12-17 10:00:00',
},
{
id: '2',
name: '华为 Mate 60 Pro',
categoryId: '1',
categoryName: '手机',
brand: 'HUAWEI',
price: 6999.00,
costPrice: 5800.00,
stock: 30,
sales: 86,
status: GoodsStatus.ON,
images: ['/static/goods/mate60.jpg'],
description: '华为 Mate 60 Pro搭载麒麟 9000S 芯片',
createTime: '2024-12-02 10:00:00',
updateTime: '2024-12-17 10:00:00',
},
{
id: '3',
name: '小米 14 Ultra',
categoryId: '1',
categoryName: '手机',
brand: 'Xiaomi',
price: 5999.00,
costPrice: 4800.00,
stock: 0,
sales: 56,
status: GoodsStatus.SOLD_OUT,
images: ['/static/goods/mi14.jpg'],
description: '小米 14 Ultra徕卡影像旗舰',
createTime: '2024-12-03 10:00:00',
updateTime: '2024-12-17 10:00:00',
},
{
id: '4',
name: 'AirPods Pro 2',
categoryId: '2',
categoryName: '耳机',
brand: 'Apple',
price: 1899.00,
costPrice: 1500.00,
stock: 100,
sales: 256,
status: GoodsStatus.ON,
images: ['/static/goods/airpods.jpg'],
description: 'AirPods Pro 第二代,主动降噪',
createTime: '2024-12-04 10:00:00',
updateTime: '2024-12-17 10:00:00',
},
]
export const mockMerchantGoods: MerchantGoods[] = mockGoodsList.map(goods => ({
id: goods.id,
name: goods.name,
categoryId: goods.categoryId,
categoryName: goods.categoryName,
brand: '',
price: goods.price,
costPrice: Math.round(goods.price * 0.7), // 成本价为售价的70%
stock: goods.stock,
sales: goods.sales,
status: goods.stock > 0 ? GoodsStatus.ON : GoodsStatus.OFF,
images: goods.images,
description: goods.description,
specs: goods.specs,
skuList: [], // 简化处理,不使用多规格
createTime: '2024-12-01 10:00:00',
updateTime: '2024-12-17 10:00:00',
}))

View File

@@ -1,8 +1,10 @@
/**
* 商户端订单数据 Mock
* 使用用户端商品信息mockGoodsList
*/
import type { MerchantOrder } from '@/typings/merchant'
import { OrderStatus } from '@/typings/merchant'
import { mockGoodsList } from '@/mock/goods'
export const mockMerchantOrders: MerchantOrder[] = [
{
@@ -11,20 +13,20 @@ export const mockMerchantOrders: MerchantOrder[] = [
customerName: '张三',
customerPhone: '138****8000',
status: OrderStatus.PENDING,
amount: 2999.00,
amount: 20.00,
freight: 0,
payAmount: 2999.00,
payAmount: 20.00,
remark: '请尽快发货',
goods: [
{
id: 'g1',
goodsId: '101',
name: '苹果 iPhone 15 Pro 256GB',
image: '/static/goods/iphone15.jpg',
skuName: '黑色 256GB',
price: 2999.00,
goodsId: 'goods_001',
name: '桂味新鲜荔枝现摘现发当季水果自家果园荔枝',
image: '/static/product/1/1.jpg',
skuName: '5斤装 特级',
price: 20.00,
quantity: 1,
amount: 2999.00,
amount: 20.00,
},
],
address: {
@@ -44,19 +46,19 @@ export const mockMerchantOrders: MerchantOrder[] = [
customerName: '李四',
customerPhone: '139****9000',
status: OrderStatus.SHIPPING,
amount: 1580.00,
amount: 100.00,
freight: 10,
payAmount: 1590.00,
payAmount: 110.00,
goods: [
{
id: 'g2',
goodsId: '102',
name: '华为 Mate 60 Pro',
image: '/static/goods/mate60.jpg',
skuName: '白色 512GB',
price: 1580.00,
quantity: 1,
amount: 1580.00,
goodsId: 'goods_002',
name: '老农田桂圆肉干无核新货8a龙眼肉干500g厚元肉干',
image: '/static/product/2/1.jpg',
skuName: '500g',
price: 50.00,
quantity: 2,
amount: 100.00,
},
],
address: {
@@ -76,19 +78,19 @@ export const mockMerchantOrders: MerchantOrder[] = [
customerName: '王五',
customerPhone: '137****7000',
status: OrderStatus.SHIPPED,
amount: 456.50,
amount: 150.00,
freight: 0,
payAmount: 456.50,
payAmount: 150.00,
goods: [
{
id: 'g3',
goodsId: '103',
name: '小米 14 Ultra',
image: '/static/goods/mi14.jpg',
skuName: '黑色 256GB',
price: 456.50,
quantity: 1,
amount: 456.50,
goodsId: 'goods_003',
name: '自然禾方化橘红陈皮无糖植物饮料350ml*9瓶整箱装',
image: '/static/product/3/1.jpg',
skuName: '9瓶装',
price: 50.00,
quantity: 3,
amount: 150.00,
},
],
address: {
@@ -119,19 +121,19 @@ export const mockMerchantOrders: MerchantOrder[] = [
customerName: '赵六',
customerPhone: '136****6000',
status: OrderStatus.COMPLETED,
amount: 888.00,
amount: 30.00,
freight: 0,
payAmount: 888.00,
payAmount: 30.00,
goods: [
{
id: 'g4',
goodsId: '104',
name: 'AirPods Pro 2',
image: '/static/goods/airpods.jpg',
skuName: '默认',
price: 888.00,
goodsId: 'goods_005',
name: '罗非鱼新鲜冷冻食材烧烤红烧净膛烤鱼酒店食堂快',
image: '/static/product/5/1.jpg',
skuName: '500g',
price: 30.00,
quantity: 1,
amount: 888.00,
amount: 30.00,
},
],
address: {

BIN
src/static/tc/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
src/static/tc/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
src/static/tc/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

BIN
src/static/tc/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -1,7 +1,7 @@
import { defineStore } from 'pinia'
import type { User } from '@/typings/mall'
import { mockMember } from '@/mock/member'
// i-carbon-3rd-party-connected
/**
* 客户端类型枚举
* - user: 用户端(消费者)
@@ -32,7 +32,7 @@ export const CLIENT_TYPE_CONFIG = {
},
[ClientType.BANK]: {
label: '银行端',
icon: 'i-carbon-bank',
icon: 'i-carbon-home',
color: '#00c05a',
description: '账款审核、金融服务',
homePage: '/pagesBank/dashboard/index',

View File

@@ -2,6 +2,36 @@
* 贷款相关类型定义
*/
/** 征信信息 */
export interface CreditInfo {
creditScore: number // 征信分数
creditLevel: string // 信用等级
loanRecords: { // 贷款记录
bank: string
amount: number
status: 'normal' | 'overdue' | 'paid'
date: string
}[]
overdueRecords?: { // 逾期记录
amount: number
overdueDays: number
date: string
}[]
queryTime: string // 查询时间
}
/** 信用评估分数 */
export interface CreditAssessment {
score: number // 评估分数 (0-100)
level: string // 评估等级 (优秀/良好/一般/较差)
factors: { // 评估因素
name: string
score: number
description: string
}[]
updateTime: string // 更新时间
}
/** 贷款申请状态 */
export enum LoanStatus {
DRAFT = 'draft', // 草稿
@@ -57,6 +87,17 @@ export interface BankProcessRecord {
attachments?: string[] // 附件,如调查报告
}
/** 用户订单信息 */
export interface UserOrder {
orderNo: string // 订单号
goodsName: string // 商品名称
goodsImage: string // 商品图片
quantity: number // 购买数量
amount: number // 订单金额
orderTime: string // 下单时间
status: string // 订单状态
}
/** 贷款申请详情 */
export interface LoanApplication {
id: string
@@ -67,11 +108,18 @@ export interface LoanApplication {
// 关联的商家列表
relatedMerchants: RelatedMerchant[]
// 用户商城消费订单
userOrders?: UserOrder[] // 用户在商城的消费订单
// 申请信息
amount: number // 申请金额(万)
term: number // 期限(月/年)
status: LoanStatus
// 银行受理人信息
handlerName?: string // 受理人姓名
handlerPhone?: string // 受理人手机号
// 个人信息
personalInfo: {
name: string

View File

@@ -251,4 +251,7 @@ export interface LoanApplicationRecord {
progress?: LoanApplicationProgress // 进度条数据 (仅Processing和Pending状态需要)
alertInfo?: LoanApplicationAlertInfo // 提示信息框 (可空)
actions: LoanApplicationAction[] // 底部按钮配置
// 银行受理人信息
handlerName?: string // 受理人姓名
handlerPhone?: string // 受理人手机号
}