Compare commits
10 Commits
b3b331c86c
...
6483a651c4
| Author | SHA1 | Date | |
|---|---|---|---|
| 6483a651c4 | |||
| e1df332a5b | |||
| d75e6a9594 | |||
| c102714f92 | |||
| 50178923f8 | |||
| b3c973df2d | |||
| d813b68eed | |||
| 3b6220cd53 | |||
| 5fc10468cf | |||
| ae8057b7a6 |
@@ -17,7 +17,11 @@
|
|||||||
"Bash(cd:*)",
|
"Bash(cd:*)",
|
||||||
"mcp__zai-mcp-server__extract_text_from_screenshot",
|
"mcp__zai-mcp-server__extract_text_from_screenshot",
|
||||||
"Bash(npx openspec validate:*)",
|
"Bash(npx openspec validate:*)",
|
||||||
"Bash(npx openspec show:*)"
|
"Bash(npx openspec show:*)",
|
||||||
|
"Bash(mvn test:*)",
|
||||||
|
"Bash(mvn install:*)",
|
||||||
|
"Bash(mvn clean install:*)",
|
||||||
|
"mcp__web-reader__webReader"
|
||||||
],
|
],
|
||||||
"additionalDirectories": [
|
"additionalDirectories": [
|
||||||
"d:\\利率定价\\loan-pricing-892\\loan-pricing-892-v2.0"
|
"d:\\利率定价\\loan-pricing-892\\loan-pricing-892-v2.0"
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ GET /loanPricing/workflow/20250119143025123
|
|||||||
"collType": "一类",
|
"collType": "一类",
|
||||||
"collThirdParty": "false",
|
"collThirdParty": "false",
|
||||||
"loanRate": "4.35",
|
"loanRate": "4.35",
|
||||||
|
"executeRate": "4.20",
|
||||||
"custName": "某某科技有限公司",
|
"custName": "某某科技有限公司",
|
||||||
"idType": "统一社会信用代码",
|
"idType": "统一社会信用代码",
|
||||||
"isInclusiveFinance": "true",
|
"isInclusiveFinance": "true",
|
||||||
@@ -325,6 +326,66 @@ GET /loanPricing/workflow/20250119143025123
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 4. 设定执行利率
|
||||||
|
|
||||||
|
为利率定价流程设定或更新最终执行利率。
|
||||||
|
|
||||||
|
**接口地址:** `PUT /loanPricing/workflow/{serialNum}/executeRate`
|
||||||
|
|
||||||
|
**权限要求:** 无特殊权限要求
|
||||||
|
|
||||||
|
**路径参数:**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|-----------|--------|----|--------|
|
||||||
|
| serialNum | String | 是 | 业务方流水号 |
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|-------------|--------|----|---------|
|
||||||
|
| executeRate | String | 是 | 执行利率(%) |
|
||||||
|
|
||||||
|
**请求示例:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PUT /loanPricing/workflow/20250119143025123/executeRate
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"executeRate": "4.20"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应示例:**
|
||||||
|
|
||||||
|
成功 (200):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "操作成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
失败 (记录不存在):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 500,
|
||||||
|
"msg": "设定失败"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**说明:**
|
||||||
|
|
||||||
|
- 该接口支持多次设定/更新执行利率
|
||||||
|
- 更新成功后会自动记录 `updateBy` 和 `updateTime`
|
||||||
|
- 如果指定的 `serialNum` 不存在,返回"设定失败"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 错误码说明
|
## 错误码说明
|
||||||
|
|
||||||
| 错误码 | 说明 |
|
| 错误码 | 说明 |
|
||||||
|
|||||||
45
openspec/changes/add-execute-rate-ui/proposal.md
Normal file
45
openspec/changes/add-execute-rate-ui/proposal.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 提案: 添加执行利率设定前端功能
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
后端已经实现了执行利率设定接口 `PUT /loanPricing/workflow/{serialNum}/executeRate`,并且详情接口 `GET /loanPricing/workflow/{serialNum}` 已经返回 `executeRate` 字段。但前端缺少相应的 UI 交互功能,业务人员无法通过界面设定执行利率。
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
|
||||||
|
1. 议价池组件中只显示议价池数据,没有执行利率输入框
|
||||||
|
2. 前端缺少调用设定执行利率接口的 API 方法
|
||||||
|
3. 用户无法通过界面设定或更新执行利率
|
||||||
|
|
||||||
|
## 提案概述
|
||||||
|
|
||||||
|
在流程详情页面的议价池组件中添加执行利率设定功能,允许业务人员输入执行利率并提交。
|
||||||
|
|
||||||
|
### 功能范围
|
||||||
|
|
||||||
|
1. **API 方法**
|
||||||
|
- 在 `ruoyi-ui/src/api/loanPricing/workflow.js` 中添加 `setExecuteRate` 方法
|
||||||
|
|
||||||
|
2. **议价池组件更新**
|
||||||
|
- 在 `BargainingPoolDisplay.vue` 中添加执行利率输入框和提交按钮
|
||||||
|
- 添加执行利率显示/编辑状态的切换
|
||||||
|
- 支持显示已设定的执行利率值
|
||||||
|
- 添加表单验证(利率格式)
|
||||||
|
|
||||||
|
3. **详情页面更新**
|
||||||
|
- 在 `detail.vue` 中传递 `executeRate` 和 `serialNum` 给议价池组件
|
||||||
|
- 添加提交成功后刷新详情的处理
|
||||||
|
|
||||||
|
## 影响范围
|
||||||
|
|
||||||
|
- 前端 API: `ruoyi-ui/src/api/loanPricing/workflow.js`
|
||||||
|
- 前端组件: `ruoyi-ui/src/views/loanPricing/workflow/components/BargainingPoolDisplay.vue`
|
||||||
|
- 前端页面: `ruoyi-ui/src/views/loanPricing/workflow/detail.vue`
|
||||||
|
- 规范: `loan-pricing-workflow-ui` (添加新需求)
|
||||||
|
|
||||||
|
## 设计考虑
|
||||||
|
|
||||||
|
1. **UI 位置**: 在议价池组件中添加新行,保持与现有议价池数据显示的一致性
|
||||||
|
2. **输入验证**: 利率格式验证(数字,可含小数点,范围合理)
|
||||||
|
3. **状态管理**: 编辑/查看状态切换,提交成功后显示最新值
|
||||||
|
4. **用户反馈**: 提交成功/失败的提示消息
|
||||||
|
5. **权限控制**: 后端接口无需特殊权限,前端暂不添加权限控制
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: 执行利率设定
|
||||||
|
|
||||||
|
系统 SHALL 在流程详情页面的议价池组件中提供执行利率设定功能,允许用户输入并提交执行利率。
|
||||||
|
|
||||||
|
#### Scenario: 显示未设定的执行利率
|
||||||
|
|
||||||
|
- **WHEN** 用户在流程详情页面查看议价池组件,且该流程尚未设定执行利率
|
||||||
|
- **THEN** 系统在议价池组件中显示"执行利率"行,当前值显示为"-"
|
||||||
|
|
||||||
|
#### Scenario: 显示已设定的执行利率
|
||||||
|
|
||||||
|
- **WHEN** 用户在流程详情页面查看议价池组件,且该流程已设定执行利率
|
||||||
|
- **THEN** 系统在议价池组件中显示"执行利率"行,显示当前设定的执行利率值
|
||||||
|
|
||||||
|
#### Scenario: 进入编辑模式
|
||||||
|
|
||||||
|
- **WHEN** 用户在议价池组件中点击"执行利率"行的编辑按钮
|
||||||
|
- **THEN** 系统切换到编辑模式,显示输入框(预填充当前值或空)、提交按钮和取消按钮
|
||||||
|
|
||||||
|
#### Scenario: 提交执行利率成功
|
||||||
|
|
||||||
|
- **WHEN** 用户在编辑模式下输入有效的执行利率值并点击提交按钮
|
||||||
|
- **THEN** 系统调用 `PUT /loanPricing/workflow/{serialNum}/executeRate` 接口,成功后更新显示值为新设定的利率,显示成功提示消息,并退出编辑模式
|
||||||
|
|
||||||
|
#### Scenario: 提交执行利率失败
|
||||||
|
|
||||||
|
- **WHEN** 用户在编辑模式下提交执行利率,但后端接口返回错误
|
||||||
|
- **THEN** 系统保持编辑模式,显示错误提示消息
|
||||||
|
|
||||||
|
#### Scenario: 取消编辑
|
||||||
|
|
||||||
|
- **WHEN** 用户在编辑模式下点击取消按钮
|
||||||
|
- **THEN** 系统退出编辑模式,恢复显示模式,显示原来的执行利率值
|
||||||
|
|
||||||
|
#### Scenario: 输入验证
|
||||||
|
|
||||||
|
- **WHEN** 用户在编辑模式下输入非法的执行利率值(非数字、超出合理范围)
|
||||||
|
- **THEN** 系统在提交前进行验证,显示错误提示,阻止提交
|
||||||
|
|
||||||
|
#### Scenario: API 接口调用
|
||||||
|
|
||||||
|
- **WHEN** 用户提交执行利率
|
||||||
|
- **THEN** 前端调用 `setExecuteRate(serialNum, executeRate)` API 方法,该方法发送 `PUT /loanPricing/workflow/{serialNum}/executeRate` 请求
|
||||||
85
openspec/changes/add-execute-rate-ui/tasks.md
Normal file
85
openspec/changes/add-execute-rate-ui/tasks.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# 实施任务
|
||||||
|
|
||||||
|
## 任务清单
|
||||||
|
|
||||||
|
1. **添加 API 方法**
|
||||||
|
- 文件: `ruoyi-ui/src/api/loanPricing/workflow.js`
|
||||||
|
- 操作: 添加 `setExecuteRate(serialNum, executeRate)` 方法
|
||||||
|
- 请求: `PUT /loanPricing/workflow/{serialNum}/executeRate`
|
||||||
|
- 验证: 方法添加成功
|
||||||
|
|
||||||
|
2. **更新议价池组件 - Props**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/components/BargainingPoolDisplay.vue`
|
||||||
|
- 操作: 添加 `executeRate` 和 `serialNum` props
|
||||||
|
- 验证: props 定义成功
|
||||||
|
|
||||||
|
3. **更新议价池组件 - UI**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/components/BargainingPoolDisplay.vue`
|
||||||
|
- 操作: 在 el-descriptions 中添加"执行利率"行,包含:
|
||||||
|
- 显示模式: 显示当前执行利率值(若无则显示"-")
|
||||||
|
- 编辑模式: 输入框 + 提交按钮 + 取消按钮
|
||||||
|
- 编辑按钮: 在显示模式下点击进入编辑模式
|
||||||
|
- 验证: UI 更新成功
|
||||||
|
|
||||||
|
4. **更新议价池组件 - 数据和逻辑**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/components/BargainingPoolDisplay.vue`
|
||||||
|
- 操作:
|
||||||
|
- 添加 `isEditing` 状态变量
|
||||||
|
- 添加 `tempExecuteRate` 临时输入值
|
||||||
|
- 添加 `handleEdit` 方法进入编辑模式
|
||||||
|
- 添加 `handleSubmit` 方法调用 API 并处理响应
|
||||||
|
- 添加 `handleCancel` 方法取消编辑
|
||||||
|
- 添加输入验证(数字格式、范围检查)
|
||||||
|
- 验证: 逻辑实现完整
|
||||||
|
|
||||||
|
5. **更新议价池组件 - API 调用**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/components/BargainingPoolDisplay.vue`
|
||||||
|
- 操作: 引入 `setExecuteRate` API 方法
|
||||||
|
- 验证: 引入成功
|
||||||
|
|
||||||
|
6. **更新详情页面 - 传递 Props**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/detail.vue`
|
||||||
|
- 操作: 在 BargainingPoolDisplay 组件上传递:
|
||||||
|
- `:execute-rate="workflowDetail.executeRate"`
|
||||||
|
- `:serial-num="workflowDetail.serialNum"`
|
||||||
|
- `@execute-rate-updated="handleExecuteRateUpdated"`
|
||||||
|
- 验证: props 传递正确
|
||||||
|
|
||||||
|
7. **前端功能验证**
|
||||||
|
- 操作:
|
||||||
|
- 启动前端服务
|
||||||
|
- 打开流程详情页面
|
||||||
|
- 测试首次设定执行利率
|
||||||
|
- 测试更新已设定的执行利率
|
||||||
|
- 测试输入验证
|
||||||
|
- 测试取消编辑
|
||||||
|
- 验证:
|
||||||
|
- 未设定时显示"-"
|
||||||
|
- 已设定时显示当前值
|
||||||
|
- 点击编辑按钮进入编辑模式
|
||||||
|
- 输入框显示当前值
|
||||||
|
- 提交成功后显示新值并显示成功提示
|
||||||
|
- 取消编辑恢复显示模式
|
||||||
|
- 输入非法值时显示错误提示
|
||||||
|
|
||||||
|
## 依赖关系
|
||||||
|
|
||||||
|
- 任务 1 必须首先执行(API 方法)
|
||||||
|
- 任务 2-5 依次执行(Props -> UI -> 数据逻辑 -> API 调用)
|
||||||
|
- 任务 6 依赖任务 2
|
||||||
|
- 任务 7 在所有代码任务完成后执行
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
- [x] API 方法 `setExecuteRate` 添加成功
|
||||||
|
- [x] 议价池组件添加 `executeRate` 和 `serialNum` props
|
||||||
|
- [x] 议价池组件显示执行利率行
|
||||||
|
- [x] 未设定时显示"-"
|
||||||
|
- [x] 已设定时显示当前值
|
||||||
|
- [x] 编辑按钮切换到编辑模式
|
||||||
|
- [x] 输入框显示当前值
|
||||||
|
- [x] 提交按钮调用 API 成功
|
||||||
|
- [x] 提交成功后更新显示并显示成功提示
|
||||||
|
- [x] 取消按钮恢复显示模式
|
||||||
|
- [x] 输入验证正确工作
|
||||||
|
- [x] 详情页面正确传递 props
|
||||||
153
openspec/changes/add-execute-rate/design.md
Normal file
153
openspec/changes/add-execute-rate/design.md
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
# 设计文档: 执行利率设定接口
|
||||||
|
|
||||||
|
## 数据库设计
|
||||||
|
|
||||||
|
### 表结构变更
|
||||||
|
|
||||||
|
**表名**: `loan_pricing_workflow`
|
||||||
|
|
||||||
|
**新增字段**:
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 可空 | 默认值 | 说明 |
|
||||||
|
|--------------|-------------|----|------|---------|
|
||||||
|
| execute_rate | varchar(20) | 是 | NULL | 执行利率(%) |
|
||||||
|
|
||||||
|
**DDL**:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE `loan_pricing_workflow`
|
||||||
|
ADD COLUMN `execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)' AFTER `loan_rate`;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口设计
|
||||||
|
|
||||||
|
### 设定执行利率接口
|
||||||
|
|
||||||
|
**请求方式**: `PUT /loanPricing/workflow/{serialNum}/executeRate`
|
||||||
|
|
||||||
|
**权限要求**: 无特殊权限要求(与查询接口一致)
|
||||||
|
|
||||||
|
**路径参数**:
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|-----------|--------|----|--------|
|
||||||
|
| serialNum | String | 是 | 业务方流水号 |
|
||||||
|
|
||||||
|
**请求体**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"executeRate": "4.20"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|-------------|--------|----|----------------------|
|
||||||
|
| executeRate | String | 是 | 执行利率,字符串格式(如 "4.20") |
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
|
||||||
|
成功 (200):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "设定成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
失败 (404):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "记录不存在"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
失败 (500):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 500,
|
||||||
|
"msg": "设定失败"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码设计
|
||||||
|
|
||||||
|
### Entity 层
|
||||||
|
|
||||||
|
**LoanPricingWorkflow.java**
|
||||||
|
|
||||||
|
```java
|
||||||
|
/** 执行利率(%) */
|
||||||
|
private String executeRate;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service 层
|
||||||
|
|
||||||
|
**ILoanPricingWorkflowService.java**
|
||||||
|
|
||||||
|
```java
|
||||||
|
/**
|
||||||
|
* 设定执行利率
|
||||||
|
* @param serialNum 业务方流水号
|
||||||
|
* @param executeRate 执行利率
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
boolean setExecuteRate(String serialNum, String executeRate);
|
||||||
|
```
|
||||||
|
|
||||||
|
**LoanPricingWorkflowServiceImpl.java**
|
||||||
|
|
||||||
|
- 实现上述方法
|
||||||
|
- 根据 `serialNum` 更新记录的 `execute_rate` 字段
|
||||||
|
- MyBatis Plus 会自动填充 `update_by` 和 `update_time`
|
||||||
|
|
||||||
|
### Controller 层
|
||||||
|
|
||||||
|
**LoanPricingWorkflowController.java**
|
||||||
|
|
||||||
|
```java
|
||||||
|
/**
|
||||||
|
* 设定执行利率
|
||||||
|
*/
|
||||||
|
@Operation(summary = "设定执行利率")
|
||||||
|
@Log(title = "利率定价流程", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/{serialNum}/executeRate")
|
||||||
|
public AjaxResult setExecuteRate(
|
||||||
|
@Parameter(description = "业务方流水号")
|
||||||
|
@PathVariable("serialNum") String serialNum,
|
||||||
|
@RequestBody Map<String, String> request)
|
||||||
|
{
|
||||||
|
String executeRate = request.get("executeRate");
|
||||||
|
boolean success = loanPricingWorkflowService.setExecuteRate(serialNum, executeRate);
|
||||||
|
return success ? success() : error("设定失败");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### VO 层变更
|
||||||
|
|
||||||
|
**LoanPricingWorkflowVO.java**
|
||||||
|
|
||||||
|
- 添加 `executeRate` 字段到 VO,确保详情接口返回执行利率
|
||||||
|
|
||||||
|
## 数据校验
|
||||||
|
|
||||||
|
1. **记录存在性**: 根据 `serialNum` 查询记录,不存在则返回 404
|
||||||
|
2. **更新结果检查**: 检查更新操作影响行数,0 行表示记录不存在
|
||||||
|
3. **格式校验**: 执行利率为字符串格式,前端传递格式化后的值(如 "4.20")
|
||||||
|
|
||||||
|
## 事务处理
|
||||||
|
|
||||||
|
- 使用 MyBatis Plus 的 `updateById` 方法,自动处理事务
|
||||||
|
- 更新失败时抛出异常,由全局异常处理器处理
|
||||||
|
|
||||||
|
## 日志记录
|
||||||
|
|
||||||
|
- 使用 `@Log` 注解记录操作日志
|
||||||
|
- 日志类型: `BusinessType.UPDATE`
|
||||||
|
- 自动记录操作人和操作时间
|
||||||
63
openspec/changes/add-execute-rate/proposal.md
Normal file
63
openspec/changes/add-execute-rate/proposal.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# 提案: 添加执行利率设定接口
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
当前利率定价流程已有测算利率(模型输出计算得到),但缺少最终执行利率的设定功能。业务人员需要根据模型测算结果和实际情况,手动设定最终执行的贷款利率。
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
|
||||||
|
1. 数据库表中没有存储执行利率的字段
|
||||||
|
2. 后端缺少设定执行利率的接口
|
||||||
|
3. API 文档需要更新
|
||||||
|
|
||||||
|
## 提案概述
|
||||||
|
|
||||||
|
为利率定价流程添加执行利率设定功能,允许业务人员为流程记录设定/更新最终执行利率。
|
||||||
|
|
||||||
|
### 功能范围
|
||||||
|
|
||||||
|
1. **数据库变更**
|
||||||
|
- 在 `loan_pricing_workflow` 表中添加 `execute_rate` 字段
|
||||||
|
|
||||||
|
2. **后端接口**
|
||||||
|
- 新增 `PUT /loanPricing/workflow/{serialNum}/executeRate` 接口
|
||||||
|
- 支持设定和更新执行利率
|
||||||
|
- 无需特殊权限控制(与查询接口保持一致)
|
||||||
|
- 可多次修改执行利率
|
||||||
|
|
||||||
|
3. **API 文档更新**
|
||||||
|
- 在 `doc/api/loan-pricing-workflow-api.md` 中添加新接口文档
|
||||||
|
|
||||||
|
## 影响范围
|
||||||
|
|
||||||
|
- 数据库: `loan_pricing_workflow` 表
|
||||||
|
- 后端:
|
||||||
|
- Entity: `LoanPricingWorkflow.java`
|
||||||
|
- Service: `ILoanPricingWorkflowService.java` 及实现类
|
||||||
|
- Controller: `LoanPricingWorkflowController.java`
|
||||||
|
- 文档: `doc/api/loan-pricing-workflow-api.md`
|
||||||
|
|
||||||
|
## 设计考虑
|
||||||
|
|
||||||
|
1. **字段类型**: 使用 `varchar(20)` 类型,与 `loan_rate` 保持一致
|
||||||
|
2. **可空性**: 允许为 NULL,未设定时返回 null
|
||||||
|
3. **可修改性**: 允许多次修改,记录 `update_by` 和 `update_time`
|
||||||
|
4. **权限控制**: 暂不加独立权限,所有登录用户可操作(后续可根据需要添加)
|
||||||
|
5. **接口语义**: 使用 PUT 语义表示更新资源
|
||||||
|
|
||||||
|
## 替代方案
|
||||||
|
|
||||||
|
### 方案 A: 添加专门的审批流程(未采纳)
|
||||||
|
|
||||||
|
- **优点**: 流程更规范,支持审批
|
||||||
|
- **缺点**: 实现复杂度高,当前需求不明确
|
||||||
|
|
||||||
|
### 方案 B: 在创建接口中直接支持(未采纳)
|
||||||
|
|
||||||
|
- **优点**: 减少接口数量
|
||||||
|
- **缺点**: 业务上执行利率是在查看测算结果后设定的,与创建分离更合理
|
||||||
|
|
||||||
|
### 方案 C: 独立的设定接口(采纳)
|
||||||
|
|
||||||
|
- **优点**: 职责清晰,实现简单,支持多次修改
|
||||||
|
- **缺点**: 无明显缺点
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# loan-pricing-workflow Delta
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: 执行利率设定
|
||||||
|
|
||||||
|
系统 SHALL 提供设定执行利率的接口,允许业务人员为利率定价流程设定或更新最终执行利率。
|
||||||
|
|
||||||
|
#### Scenario: 设定执行利率
|
||||||
|
|
||||||
|
- **WHEN** 业务人员对已存在的利率定价流程调用设定执行利率接口,提供有效的业务方流水号和执行利率值
|
||||||
|
- **THEN** 系统更新该流程记录的执行利率字段,返回成功响应,并自动记录更新者和更新时间
|
||||||
|
|
||||||
|
#### Scenario: 更新已有执行利率
|
||||||
|
|
||||||
|
- **WHEN** 业务人员对已设定执行利率的流程再次调用设定接口
|
||||||
|
- **THEN** 系统覆盖更新执行利率为新的值
|
||||||
|
|
||||||
|
#### Scenario: 设定不存在的流程
|
||||||
|
|
||||||
|
- **WHEN** 业务人员提供的业务方流水号不存在
|
||||||
|
- **THEN** 系统返回"记录不存在"的错误信息
|
||||||
|
|
||||||
|
#### Scenario: 执行利率在详情中返回
|
||||||
|
|
||||||
|
- **WHEN** 业务人员查询流程详情
|
||||||
|
- **THEN** 系统在响应数据中包含 `executeRate` 字段(如果已设定则返回值,否则返回 null)
|
||||||
77
openspec/changes/add-execute-rate/tasks.md
Normal file
77
openspec/changes/add-execute-rate/tasks.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# 实施任务
|
||||||
|
|
||||||
|
## 任务清单
|
||||||
|
|
||||||
|
1. **添加数据库字段**
|
||||||
|
- 文件: 创建 SQL 迁移脚本 `sql/add_execute_rate_field.sql`
|
||||||
|
- 操作: 在 `loan_pricing_workflow` 表中添加 `execute_rate` 字段
|
||||||
|
-
|
||||||
|
DDL: `ALTER TABLE loan_pricing_workflow ADD COLUMN execute_rate varchar(20) DEFAULT NULL COMMENT '执行利率(%)' AFTER loan_rate;`
|
||||||
|
- 验证: 字段添加成功
|
||||||
|
|
||||||
|
2. **更新 Entity 类**
|
||||||
|
- 文件: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java`
|
||||||
|
- 操作: 添加 `executeRate` 字段及注释
|
||||||
|
- 验证: 字段添加成功,位于 `loanRate` 字段之后
|
||||||
|
|
||||||
|
3. **更新 VO 类**
|
||||||
|
- 文件: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/vo/LoanPricingWorkflowVO.java`
|
||||||
|
- 操作: 添加 `executeRate` 字段及注释
|
||||||
|
- 验证: 字段添加成功
|
||||||
|
|
||||||
|
4. **更新 Service 接口**
|
||||||
|
- 文件: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java`
|
||||||
|
- 操作: 添加 `setExecuteRate(String serialNum, String executeRate)` 方法声明
|
||||||
|
- 验证: 方法添加成功
|
||||||
|
|
||||||
|
5. **实现 Service 方法**
|
||||||
|
- 文件: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java`
|
||||||
|
- 操作: 实现 `setExecuteRate` 方法
|
||||||
|
- 逻辑: 根据 serialNum 查询记录,更新 execute_rate 字段
|
||||||
|
- 验证: 方法实现完成
|
||||||
|
|
||||||
|
6. **添加 Controller 接口**
|
||||||
|
- 文件: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java`
|
||||||
|
- 操作: 添加 `PUT /{serialNum}/executeRate` 接口方法
|
||||||
|
- 验证: 接口添加成功,添加 Swagger 注解
|
||||||
|
|
||||||
|
7. **更新 API 文档**
|
||||||
|
- 文件: `doc/api/loan-pricing-workflow-api.md`
|
||||||
|
- 操作: 在接口列表中添加"设定执行利率"接口文档
|
||||||
|
- 内容: 接口地址、请求参数、响应示例、说明
|
||||||
|
- 验证: 文档更新完整
|
||||||
|
|
||||||
|
8. **后端编译验证**
|
||||||
|
- 操作: 运行 `mvn clean compile` 或 IDE 编译
|
||||||
|
- 验证: 编译成功无错误
|
||||||
|
|
||||||
|
9. **接口功能验证**
|
||||||
|
- 操作:
|
||||||
|
- 启动后端服务
|
||||||
|
- 调用 `PUT /loanPricing/workflow/{serialNum}/executeRate` 接口
|
||||||
|
- 调用 `GET /loanPricing/workflow/{serialNum}` 接口验证返回值
|
||||||
|
- 验证:
|
||||||
|
- 设定执行利率成功
|
||||||
|
- 再次设定可覆盖更新
|
||||||
|
- 不存在的 serialNum 返回 404
|
||||||
|
- 详情接口正确返回 executeRate
|
||||||
|
|
||||||
|
## 依赖关系
|
||||||
|
|
||||||
|
- 任务 1 必须首先执行(数据库字段)
|
||||||
|
- 任务 2、3 可并行执行(Entity 和 VO)
|
||||||
|
- 任务 4、5 依次执行(Service 接口 -> 实现)
|
||||||
|
- 任务 6 依赖任务 5
|
||||||
|
- 任务 7 可在任务 6 完成后执行
|
||||||
|
- 任务 8、9 依次执行
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
- [x] 数据库字段 `execute_rate` 添加成功
|
||||||
|
- [x] Entity 和 VO 类添加 `executeRate` 字段
|
||||||
|
- [x] Service 接口和实现方法添加成功
|
||||||
|
- [x] Controller 接口添加成功并编译通过
|
||||||
|
- [x] API 文档更新完整
|
||||||
|
- [x] 接口调用成功,执行利率正确保存
|
||||||
|
- [x] 详情接口正确返回 `executeRate`
|
||||||
|
- [x] 不存在的记录返回 404
|
||||||
61
openspec/changes/adjust-model-output-columns/proposal.md
Normal file
61
openspec/changes/adjust-model-output-columns/proposal.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# 提案: 将模型输出展示组件改为三列布局
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
当前 `ModelOutputDisplay.vue` 组件中所有 `el-descriptions` 使用 `:column="2"` 两列布局展示模型输出字段。
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
|
||||||
|
两列布局导致垂直空间占用较多,用户需要滚动更多才能查看完整信息。三列布局可以更好地利用屏幕宽度(特别是在桌面端),减少垂直滚动需求。
|
||||||
|
|
||||||
|
## 提案概述
|
||||||
|
|
||||||
|
将 `ModelOutputDisplay.vue` 组件中所有 `el-descriptions` 的 `:column` 属性从 `2` 修改为 `3`。
|
||||||
|
|
||||||
|
### 影响范围
|
||||||
|
|
||||||
|
- 前端: `ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue`
|
||||||
|
|
||||||
|
### 具体修改点
|
||||||
|
|
||||||
|
需要修改以下位置的 `:column` 属性:
|
||||||
|
|
||||||
|
#### 个人客户模型输出
|
||||||
|
1. 基本信息 (line 11): `:column="2"` → `:column="3"`
|
||||||
|
2. 忠诚度分析 (line 22): `:column="2"` → `:column="3"`
|
||||||
|
3. 贡献度分析 (line 35): `:column="2"` → `:column="3"`
|
||||||
|
4. 关联度分析 (line 45): `:column="2"` → `:column="3"`
|
||||||
|
5. 贷款特征 (line 65): `:column="2"` → `:column="3"`
|
||||||
|
6. 风险度分析 (line 81): `:column="2"` → `:column="3"`
|
||||||
|
7. 测算结果 (line 93): `:column="2"` → `:column="3"`
|
||||||
|
|
||||||
|
#### 企业客户模型输出
|
||||||
|
8. 基本信息 (line 104): `:column="2"` → `:column="3"`
|
||||||
|
9. 忠诚度分析 (line 115): `:column="2"` → `:column="3"`
|
||||||
|
10. 贡献度分析 (line 126): `:column="2"` → `:column="3"`
|
||||||
|
11. 关联度分析 (line 136): `:column="2"` → `:column="3"`
|
||||||
|
12. 企业类别 (line 155): `:column="2"` → `:column="3"`
|
||||||
|
13. 贷款特征 (line 167): `:column="2"` → `:column="3"`
|
||||||
|
14. 风险度分析 (line 180): `:column="2"` → `:column="3"`
|
||||||
|
15. 测算结果 (line 192): `:column="2"` → `:column="3"`
|
||||||
|
|
||||||
|
## 设计考虑
|
||||||
|
|
||||||
|
1. **空间利用**: 三列布局可以减少约 33% 的垂直空间占用
|
||||||
|
2. **可读性**: Element UI 的 `el-descriptions` 组件会自动调整标签宽度,三列布局在标准桌面显示器(1920px 宽度)下可读性良好
|
||||||
|
3. **兼容性**: `el-descriptions` 组件原生支持多列布局,无需额外样式调整
|
||||||
|
4. **响应式**: 在小屏幕设备上,Element UI 会自动调整布局,无需额外处理
|
||||||
|
|
||||||
|
## 替代方案
|
||||||
|
|
||||||
|
### 方案 A: 保持两列布局 (未采纳)
|
||||||
|
- **优点**: 标签内容空间更充足
|
||||||
|
- **缺点**: 垂直空间占用大,需要更多滚动
|
||||||
|
|
||||||
|
### 方案 B: 使用四列布局 (未采纳)
|
||||||
|
- **优点**: 垂直空间占用最少
|
||||||
|
- **缺点**: 标签内容可能被压缩,影响可读性
|
||||||
|
|
||||||
|
### 方案 C: 改为三列布局 (采纳)
|
||||||
|
- **优点**: 平衡空间利用率和可读性
|
||||||
|
- **缺点**: 无明显缺点
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# loan-pricing-workflow-ui Delta
|
||||||
|
|
||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: 模型输出展示布局
|
||||||
|
|
||||||
|
模型输出组件 SHALL 使用三列布局展示字段信息,以提高空间利用率。
|
||||||
|
|
||||||
|
#### Scenario: 查看个人客户模型输出三列布局
|
||||||
|
- **WHEN** 用户在流程详情页查看个人客户记录的模型输出信息
|
||||||
|
- **THEN** 系统在所有模型输出 Tab(基本信息、忠诚度分析、贡献度分析、关联度分析、贷款特征、风险度分析、测算结果)中使用三列布局展示字段
|
||||||
|
|
||||||
|
#### Scenario: 查看企业客户模型输出三列布局
|
||||||
|
- **WHEN** 用户在流程详情页查看企业客户记录的模型输出信息
|
||||||
|
- **THEN** 系统在所有模型输出 Tab(基本信息、忠诚度分析、贡献度分析、关联度分析、企业类别、贷款特征、风险度分析、测算结果)中使用三列布局展示字段
|
||||||
36
openspec/changes/adjust-model-output-columns/tasks.md
Normal file
36
openspec/changes/adjust-model-output-columns/tasks.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# 实施任务
|
||||||
|
|
||||||
|
## 任务清单
|
||||||
|
|
||||||
|
1. **修改 ModelOutputDisplay.vue 组件列数配置**
|
||||||
|
- 文件: `ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue`
|
||||||
|
- 操作: 将所有 `el-descriptions` 的 `:column="2"` 修改为 `:column="3"`
|
||||||
|
- 涉及行数: 11, 22, 35, 45, 65, 81, 93, 104, 115, 126, 136, 155, 167, 180, 192
|
||||||
|
- 验证: 确认所有 15 处 `el-descriptions` 的 `:column` 属性已修改为 `3`
|
||||||
|
|
||||||
|
2. **前端构建验证**
|
||||||
|
- 操作: 运行 `cd ruoyi-ui && npm run build:prod`
|
||||||
|
- 验证: 构建成功无错误
|
||||||
|
|
||||||
|
3. **功能验证**
|
||||||
|
- 操作:
|
||||||
|
- 启动前端开发服务器 `npm run dev`
|
||||||
|
- 访问流程详情页,选择个人客户记录,验证模型输出显示为三列
|
||||||
|
- 选择企业客户记录,验证模型输出显示为三列
|
||||||
|
- 验证:
|
||||||
|
- 个人客户所有 7 个 Tab 的字段展示均为三列布局
|
||||||
|
- 企业客户所有 8 个 Tab 的字段展示均为三列布局
|
||||||
|
- 标签和值内容正常显示,无溢出或错位
|
||||||
|
|
||||||
|
## 依赖关系
|
||||||
|
|
||||||
|
- 任务 1 必须首先完成
|
||||||
|
- 任务 2 和任务 3 可并行执行
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
- [x] 所有 `el-descriptions` 的 `:column` 属性值均为 `3`
|
||||||
|
- [x] 前端构建成功
|
||||||
|
- [x] 个人客户模型输出所有 Tab 正确显示为三列
|
||||||
|
- [x] 企业客户模型输出所有 Tab 正确显示为三列
|
||||||
|
- [x] 字段标签和内容显示正常,无布局问题
|
||||||
@@ -25,9 +25,9 @@ spring:
|
|||||||
druid:
|
druid:
|
||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
url: jdbc:mysql://116.62.17.81:40627/loan-pricing-892?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
url: jdbc:mysql://116.62.17.81:3306/loan-pricing?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
username: root
|
username: root
|
||||||
password: 123456
|
password: Kfcx@1234
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
# 从数据源开关/默认关闭
|
# 从数据源开关/默认关闭
|
||||||
@@ -84,11 +84,11 @@ spring:
|
|||||||
# 地址
|
# 地址
|
||||||
host: 116.62.17.81
|
host: 116.62.17.81
|
||||||
# 端口,默认为6379
|
# 端口,默认为6379
|
||||||
port: 44565
|
port: 6379
|
||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 0
|
database: 0
|
||||||
# 密码
|
# 密码
|
||||||
password: 123456
|
password: Kfcx@1234
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
lettuce:
|
lettuce:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.ruoyi.common.core.page.PageDomain;
|
|||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.page.TableSupport;
|
import com.ruoyi.common.core.page.TableSupport;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow;
|
import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow;
|
||||||
import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO;
|
import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO;
|
||||||
import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService;
|
import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService;
|
||||||
@@ -20,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 利率定价流程Controller
|
* 利率定价流程Controller
|
||||||
*
|
*
|
||||||
@@ -80,4 +81,19 @@ public class LoanPricingWorkflowController extends BaseController
|
|||||||
}
|
}
|
||||||
return success(workflow);
|
return success(workflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设定执行利率
|
||||||
|
*/
|
||||||
|
@Operation(summary = "设定执行利率")
|
||||||
|
@Log(title = "利率定价流程", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/{serialNum}/executeRate")
|
||||||
|
public AjaxResult setExecuteRate(
|
||||||
|
@Parameter(description = "业务方流水号")
|
||||||
|
@PathVariable("serialNum") String serialNum,
|
||||||
|
@RequestBody Map<String, String> request) {
|
||||||
|
String executeRate = request.get("executeRate");
|
||||||
|
boolean success = loanPricingWorkflowService.setExecuteRate(serialNum, executeRate);
|
||||||
|
return success ? success() : error("设定失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.ruoyi.loanpricing.domain.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -99,6 +98,11 @@ public class LoanPricingWorkflow implements Serializable
|
|||||||
@NotBlank(message = "贷款利率不能为空")
|
@NotBlank(message = "贷款利率不能为空")
|
||||||
private String loanRate;
|
private String loanRate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行利率(%)
|
||||||
|
*/
|
||||||
|
private String executeRate;
|
||||||
|
|
||||||
/** 客户名称 */
|
/** 客户名称 */
|
||||||
private String custName;
|
private String custName;
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,13 @@ public interface ILoanPricingWorkflowService
|
|||||||
* @return 利率定价流程
|
* @return 利率定价流程
|
||||||
*/
|
*/
|
||||||
public LoanPricingWorkflowVO selectLoanPricingBySerialNum(String serialNum);
|
public LoanPricingWorkflowVO selectLoanPricingBySerialNum(String serialNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设定执行利率
|
||||||
|
*
|
||||||
|
* @param serialNum 业务方流水号
|
||||||
|
* @param executeRate 执行利率
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public boolean setExecuteRate(String serialNum, String executeRate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
|||||||
// 按创建者筛选
|
// 按创建者筛选
|
||||||
if (StringUtils.hasText(loanPricingWorkflow.getCreateBy()))
|
if (StringUtils.hasText(loanPricingWorkflow.getCreateBy()))
|
||||||
{
|
{
|
||||||
wrapper.eq(LoanPricingWorkflow::getCreateBy, loanPricingWorkflow.getCreateBy());
|
wrapper.like(LoanPricingWorkflow::getCreateBy, loanPricingWorkflow.getCreateBy());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按客户名称模糊查询
|
// 按客户名称模糊查询
|
||||||
@@ -162,9 +162,32 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
|||||||
// 按机构号筛选
|
// 按机构号筛选
|
||||||
if (StringUtils.hasText(loanPricingWorkflow.getOrgCode()))
|
if (StringUtils.hasText(loanPricingWorkflow.getOrgCode()))
|
||||||
{
|
{
|
||||||
wrapper.eq(LoanPricingWorkflow::getOrgCode, loanPricingWorkflow.getOrgCode());
|
wrapper.like(LoanPricingWorkflow::getOrgCode, loanPricingWorkflow.getOrgCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设定执行利率
|
||||||
|
*
|
||||||
|
* @param serialNum 业务方流水号
|
||||||
|
* @param executeRate 执行利率
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public boolean setExecuteRate(String serialNum, String executeRate) {
|
||||||
|
LambdaQueryWrapper<LoanPricingWorkflow> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(LoanPricingWorkflow::getSerialNum, serialNum);
|
||||||
|
LoanPricingWorkflow workflow = loanPricingWorkflowMapper.selectOne(wrapper);
|
||||||
|
|
||||||
|
if (workflow == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
workflow.setExecuteRate(executeRate);
|
||||||
|
int result = loanPricingWorkflowMapper.updateById(workflow);
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VUE_APP_TITLE = 上虞利率定价系统
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
ENV = 'development'
|
ENV = 'development'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VUE_APP_TITLE = 上虞利率定价系统
|
||||||
|
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
ENV = 'production'
|
ENV = 'production'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VUE_APP_TITLE = 上虞利率定价系统
|
||||||
|
|
||||||
BABEL_ENV = production
|
BABEL_ENV = production
|
||||||
|
|
||||||
|
|||||||
@@ -25,3 +25,12 @@ export function createWorkflow(data) {
|
|||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设定执行利率
|
||||||
|
export function setExecuteRate(serialNum, executeRate) {
|
||||||
|
return request({
|
||||||
|
url: '/loanPricing/workflow/' + serialNum + '/executeRate',
|
||||||
|
method: 'put',
|
||||||
|
data: { executeRate: executeRate }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,13 +12,15 @@
|
|||||||
<template v-if="device!=='mobile'">
|
<template v-if="device!=='mobile'">
|
||||||
<search id="header-search" class="right-menu-item" />
|
<search id="header-search" class="right-menu-item" />
|
||||||
|
|
||||||
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
<!-- 源码地址按钮已隐藏 -->
|
||||||
|
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip> -->
|
||||||
|
|
||||||
<el-tooltip content="文档地址" effect="dark" placement="bottom">
|
<!-- 文档地址按钮已隐藏 -->
|
||||||
|
<!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip> -->
|
||||||
|
|
||||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||||
|
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ export const constantRoutes = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: 'index',
|
||||||
component: () => import('@/views/index'),
|
component: () => import('@/views/loanPricing/workflow/index'),
|
||||||
name: 'Index',
|
name: 'LoanPricingWorkflow',
|
||||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
meta: { title: '流程列表', icon: 'dashboard', affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
|||||||
<div slot="header" class="card-header">
|
<div slot="header" class="card-header">
|
||||||
<span class="card-title">议价池</span>
|
<span class="card-title">议价池</span>
|
||||||
</div>
|
</div>
|
||||||
<el-descriptions :column="4" border size="small">
|
<el-descriptions :column="2" border size="small">
|
||||||
<el-descriptions-item label="网点议价池">
|
<el-descriptions-item label="网点议价池">
|
||||||
{{ displayBranchPool }}
|
{{ displayBranchPool }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|||||||
@@ -28,6 +28,25 @@
|
|||||||
<el-descriptions-item label="测算利率">
|
<el-descriptions-item label="测算利率">
|
||||||
<span class="calculate-rate">{{ getCalculateRate() }}</span> %
|
<span class="calculate-rate">{{ getCalculateRate() }}</span> %
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<!-- 执行利率输入区域 -->
|
||||||
|
<el-descriptions-item label="执行利率" :class="'execute-rate-item'">
|
||||||
|
<div class="execute-rate-input-wrapper">
|
||||||
|
<el-input
|
||||||
|
v-model="executeRateInput"
|
||||||
|
class="execute-rate-input"
|
||||||
|
placeholder="请输入执行利率"
|
||||||
|
>
|
||||||
|
<template slot="append">%</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleSetExecuteRate"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,7 +134,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getWorkflow } from "@/api/loanPricing/workflow"
|
import { getWorkflow, setExecuteRate } from "@/api/loanPricing/workflow"
|
||||||
import ModelOutputDisplay from "./components/ModelOutputDisplay.vue"
|
import ModelOutputDisplay from "./components/ModelOutputDisplay.vue"
|
||||||
import BargainingPoolDisplay from "./components/BargainingPoolDisplay.vue"
|
import BargainingPoolDisplay from "./components/BargainingPoolDisplay.vue"
|
||||||
|
|
||||||
@@ -132,7 +151,16 @@ export default {
|
|||||||
retailOutput: null,
|
retailOutput: null,
|
||||||
corpOutput: null,
|
corpOutput: null,
|
||||||
bargainingPool: null,
|
bargainingPool: null,
|
||||||
activeTab: 'basic'
|
activeTab: 'basic',
|
||||||
|
executeRateInput: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'workflowDetail.executeRate': {
|
||||||
|
handler(newVal) {
|
||||||
|
this.executeRateInput = newVal || ''
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -202,6 +230,35 @@ export default {
|
|||||||
return this.corpOutput.calculateRate || '-'
|
return this.corpOutput.calculateRate || '-'
|
||||||
}
|
}
|
||||||
return '-'
|
return '-'
|
||||||
|
},
|
||||||
|
/** 设定执行利率 */
|
||||||
|
handleSetExecuteRate() {
|
||||||
|
// 验证输入
|
||||||
|
const value = this.executeRateInput
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
this.$modal.msgError("请输入执行利率")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证是否为有效数字
|
||||||
|
const numValue = parseFloat(value)
|
||||||
|
if (isNaN(numValue)) {
|
||||||
|
this.$modal.msgError("请输入有效的数字")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (numValue < 0 || numValue > 100) {
|
||||||
|
this.$modal.msgError("执行利率必须在 0 到 100 之间")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 API
|
||||||
|
setExecuteRate(this.workflowDetail.serialNum, value.toString()).then(() => {
|
||||||
|
this.$modal.msgSuccess("执行利率设定成功")
|
||||||
|
// 重新获取详情数据
|
||||||
|
this.getDetail()
|
||||||
|
}).catch(error => {
|
||||||
|
this.$modal.msgError("设定失败:" + (error.msg || error.message || "未知错误"))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,6 +314,18 @@ export default {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行利率输入区域
|
||||||
|
.execute-rate-input-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.execute-rate-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 利率值样式
|
// 利率值样式
|
||||||
.rate-value {
|
.rate-value {
|
||||||
color: #67c23a;
|
color: #67c23a;
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['loanPricing:workflow:create']"
|
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@@ -65,7 +64,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-view"
|
icon="el-icon-view"
|
||||||
@click="handleView(scope.row)"
|
@click="handleView(scope.row)"
|
||||||
v-hasPermi="['loanPricing:workflow:query']"
|
|
||||||
>查看</el-button>
|
>查看</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -85,7 +83,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listWorkflow } from "@/api/loanPricing/workflow"
|
import {listWorkflow} from "@/api/loanPricing/workflow"
|
||||||
import WorkflowCreateDialog from "./components/WorkflowCreateDialog"
|
import WorkflowCreateDialog from "./components/WorkflowCreateDialog"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
<pane size="84">
|
<pane size="84">
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
<el-form-item label="用户名称" prop="userName">
|
<el-form-item label="柜员号" prop="userName">
|
||||||
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.userName" placeholder="请输入柜员号" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="手机号码" prop="phonenumber">
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="50" align="center" />
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns.userId.visible" />
|
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns.userId.visible" />
|
||||||
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns.userName.visible" :show-overflow-tooltip="true" />
|
<el-table-column label="柜员号" align="center" key="userName" prop="userName" v-if="columns.userName.visible" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns.nickName.visible" :show-overflow-tooltip="true" />
|
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns.nickName.visible" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns.deptName.visible" :show-overflow-tooltip="true" />
|
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns.deptName.visible" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns.phonenumber.visible" width="120" />
|
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns.phonenumber.visible" width="120" />
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="归属部门" prop="deptId">
|
<el-form-item label="归属部门" prop="deptId">
|
||||||
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" />
|
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" @input="handleDeptChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -123,8 +123,8 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
|
<el-form-item v-if="form.userId == undefined" label="柜员号" prop="userName">
|
||||||
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
|
<el-input v-model="form.userName" placeholder="请输入柜员号" maxlength="30" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@@ -279,7 +279,7 @@ export default {
|
|||||||
// 列信息
|
// 列信息
|
||||||
columns: {
|
columns: {
|
||||||
userId: { label: '用户编号', visible: true },
|
userId: { label: '用户编号', visible: true },
|
||||||
userName: { label: '用户名称', visible: true },
|
userName: { label: '柜员号', visible: true },
|
||||||
nickName: { label: '用户昵称', visible: true },
|
nickName: { label: '用户昵称', visible: true },
|
||||||
deptName: { label: '部门', visible: true },
|
deptName: { label: '部门', visible: true },
|
||||||
phonenumber: { label: '手机号码', visible: true },
|
phonenumber: { label: '手机号码', visible: true },
|
||||||
@@ -289,12 +289,15 @@ export default {
|
|||||||
// 表单校验
|
// 表单校验
|
||||||
rules: {
|
rules: {
|
||||||
userName: [
|
userName: [
|
||||||
{ required: true, message: "用户名称不能为空", trigger: "blur" },
|
{ required: true, message: "柜员号不能为空", trigger: "blur" },
|
||||||
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
|
{ min: 2, max: 20, message: '柜员号长度必须介于 2 和 20 之间', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
nickName: [
|
nickName: [
|
||||||
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
|
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
|
deptId: [
|
||||||
|
{ required: true, message: "归属部门不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
||||||
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
|
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
|
||||||
@@ -370,6 +373,10 @@ export default {
|
|||||||
this.queryParams.deptId = data.id
|
this.queryParams.deptId = data.id
|
||||||
this.handleQuery()
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
|
// 归属部门选择变化事件
|
||||||
|
handleDeptChange() {
|
||||||
|
this.$refs.form.validateField('deptId')
|
||||||
|
},
|
||||||
// 用户状态修改
|
// 用户状态修改
|
||||||
handleStatusChange(row) {
|
handleStatusChange(row) {
|
||||||
let text = row.status === "0" ? "启用" : "停用"
|
let text = row.status === "0" ? "启用" : "停用"
|
||||||
|
|||||||
5
sql/add_execute_rate_field.sql
Normal file
5
sql/add_execute_rate_field.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- 为 loan_pricing_workflow 表添加执行利率字段
|
||||||
|
-- 执行日期: 2025-01-22
|
||||||
|
|
||||||
|
ALTER TABLE `loan_pricing_workflow`
|
||||||
|
ADD COLUMN `execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)' AFTER `loan_rate`;
|
||||||
@@ -25,6 +25,7 @@ CREATE TABLE `loan_pricing_workflow` (
|
|||||||
`coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一线/一类/二类',
|
`coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一线/一类/二类',
|
||||||
`coll_third_party` varchar(10) DEFAULT NULL COMMENT '抵质押物是否三方所有: true/false',
|
`coll_third_party` varchar(10) DEFAULT NULL COMMENT '抵质押物是否三方所有: true/false',
|
||||||
`loan_rate` varchar(20) NOT NULL COMMENT '贷款利率',
|
`loan_rate` varchar(20) NOT NULL COMMENT '贷款利率',
|
||||||
|
`execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)',
|
||||||
`cust_name` varchar(100) DEFAULT NULL COMMENT '客户名称',
|
`cust_name` varchar(100) DEFAULT NULL COMMENT '客户名称',
|
||||||
`id_type` varchar(50) DEFAULT NULL COMMENT '证件类型',
|
`id_type` varchar(50) DEFAULT NULL COMMENT '证件类型',
|
||||||
`is_inclusive_finance` varchar(10) DEFAULT NULL COMMENT '是否普惠小微借款人: true/false',
|
`is_inclusive_finance` varchar(10) DEFAULT NULL COMMENT '是否普惠小微借款人: true/false',
|
||||||
|
|||||||
141
test-execute-rate-api.sh
Normal file
141
test-execute-rate-api.sh
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 利率定价流程执行利率接口测试脚本
|
||||||
|
# 测试环境: http://localhost:8080
|
||||||
|
|
||||||
|
BASE_URL="http://localhost:8080"
|
||||||
|
LOGIN_URL="${BASE_URL}/login"
|
||||||
|
WORKFLOW_URL="${BASE_URL}/loanPricing/workflow"
|
||||||
|
|
||||||
|
# 测试账号
|
||||||
|
USERNAME="admin"
|
||||||
|
PASSWORD="admin123"
|
||||||
|
|
||||||
|
# 测试流水号(从数据库获取)
|
||||||
|
SERIAL_NUM="20260121170730386"
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "利率定价流程执行利率接口测试"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤1: 登录获取 Token (使用测试接口,无需验证码)
|
||||||
|
echo -e "${YELLOW}步骤1: 登录获取 Token (使用测试接口)${NC}"
|
||||||
|
LOGIN_RESPONSE=$(curl -s -X POST "${BASE_URL}/login/test" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"username\":\"${USERNAME}\",\"password\":\"${PASSWORD}\"}")
|
||||||
|
|
||||||
|
TOKEN=$(echo $LOGIN_RESPONSE | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
echo -e "${RED}登录失败,无法获取 Token${NC}"
|
||||||
|
echo "响应: $LOGIN_RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}登录成功,Token: ${TOKEN:0:20}...${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤2: 查询当前流程详情
|
||||||
|
echo -e "${YELLOW}步骤2: 查询流程详情 (GET ${WORKFLOW_URL}/${SERIAL_NUM})${NC}"
|
||||||
|
DETAILS_RESPONSE=$(curl -s -X GET "${WORKFLOW_URL}/${SERIAL_NUM}" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}")
|
||||||
|
|
||||||
|
echo "$DETAILS_RESPONSE" | python -m json.tool 2>/dev/null || echo "$DETAILS_RESPONSE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤3: 设定执行利率
|
||||||
|
echo -e "${YELLOW}步骤3: 设定执行利率 (PUT ${WORKFLOW_URL}/${SERIAL_NUM}/executeRate)${NC}"
|
||||||
|
SET_RATE_RESPONSE=$(curl -s -X PUT "${WORKFLOW_URL}/${SERIAL_NUM}/executeRate" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"executeRate":"4.20"}')
|
||||||
|
|
||||||
|
echo "$SET_RATE_RESPONSE" | python -m json.tool 2>/dev/null || echo "$SET_RATE_RESPONSE"
|
||||||
|
|
||||||
|
# 检查响应
|
||||||
|
CODE=$(echo $SET_RATE_RESPONSE | grep -o '"code":[0-9]*' | cut -d':' -f2)
|
||||||
|
if [ "$CODE" = "200" ]; then
|
||||||
|
echo -e "${GREEN}✓ 设定执行利率成功${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 设定执行利率失败${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤4: 再次查询详情验证 executeRate 字段
|
||||||
|
echo -e "${YELLOW}步骤4: 再次查询详情验证 executeRate 字段${NC}"
|
||||||
|
DETAILS_RESPONSE2=$(curl -s -X GET "${WORKFLOW_URL}/${SERIAL_NUM}" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}")
|
||||||
|
|
||||||
|
echo "$DETAILS_RESPONSE2" | python -m json.tool 2>/dev/null || echo "$DETAILS_RESPONSE2"
|
||||||
|
|
||||||
|
# 检查 executeRate 字段
|
||||||
|
EXECUTE_RATE=$(echo $DETAILS_RESPONSE2 | grep -o '"executeRate":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
if [ "$EXECUTE_RATE" = "4.20" ]; then
|
||||||
|
echo -e "${GREEN}✓ executeRate 字段正确返回: ${EXECUTE_RATE}${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ executeRate 字段值不正确${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤5: 更新执行利率(验证可修改)
|
||||||
|
echo -e "${YELLOW}步骤5: 更新执行利率为 3.85${NC}"
|
||||||
|
UPDATE_RATE_RESPONSE=$(curl -s -X PUT "${WORKFLOW_URL}/${SERIAL_NUM}/executeRate" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"executeRate":"3.85"}')
|
||||||
|
|
||||||
|
echo "$UPDATE_RATE_RESPONSE" | python -m json.tool 2>/dev/null || echo "$UPDATE_RATE_RESPONSE"
|
||||||
|
|
||||||
|
CODE=$(echo $UPDATE_RATE_RESPONSE | grep -o '"code":[0-9]*' | cut -d':' -f2)
|
||||||
|
if [ "$CODE" = "200" ]; then
|
||||||
|
echo -e "${GREEN}✓ 更新执行利率成功${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 更新执行利率失败${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤6: 测试不存在的流水号
|
||||||
|
echo -e "${YELLOW}步骤6: 测试不存在的流水号 (404场景)${NC}"
|
||||||
|
NOT_FOUND_RESPONSE=$(curl -s -X PUT "${WORKFLOW_URL}/99999999999999999/executeRate" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"executeRate":"4.20"}')
|
||||||
|
|
||||||
|
echo "$NOT_FOUND_RESPONSE" | python -m json.tool 2>/dev/null || echo "$NOT_FOUND_RESPONSE"
|
||||||
|
|
||||||
|
CODE=$(echo $NOT_FOUND_RESPONSE | grep -o '"code":[0-9]*' | cut -d':' -f2)
|
||||||
|
MSG=$(echo $NOT_FOUND_RESPONSE | grep -o '"msg":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
if [ "$CODE" != "200" ]; then
|
||||||
|
echo -e "${GREEN}✓ 不存在的流水号正确返回错误: ${MSG}${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 应该返回错误但返回了成功${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 步骤7: 测试空值
|
||||||
|
echo -e "${YELLOW}步骤7: 测试设定空值${NC}"
|
||||||
|
NULL_RATE_RESPONSE=$(curl -s -X PUT "${WORKFLOW_URL}/${SERIAL_NUM}/executeRate" \
|
||||||
|
-H "Authorization: Bearer ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"executeRate":null}')
|
||||||
|
|
||||||
|
echo "$NULL_RATE_RESPONSE" | python -m json.tool 2>/dev/null || echo "$NULL_RATE_RESPONSE"
|
||||||
|
|
||||||
|
CODE=$(echo $NULL_RATE_RESPONSE | grep -o '"code":[0-9]*' | cut -d':' -f2)
|
||||||
|
if [ "$CODE" = "200" ]; then
|
||||||
|
echo -e "${GREEN}✓ 空值设定成功${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}空值设定响应: ${MSG}${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "测试完成"
|
||||||
|
echo "=========================================="
|
||||||
Reference in New Issue
Block a user