From bc7011313ffa3359765708ef7a5f61d9e4f9f759 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Mon, 2 Feb 2026 15:25:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=B1=BB=E5=9E=8B=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 6 +- .skills/fix-mysql-comments.md | 135 +++ doc/api/loan-pricing-workflow-api.md | 151 +++- doc/corp.csv | 15 + doc/field-mapping-analysis.md | 127 +++ doc/implementation-report.md | 161 ++++ doc/person.csv | 12 + ...5-02-02-customer-type-based-detail-view.md | 854 ++++++++++++++++++ doc/workflow-create-ui-design.md | 216 +++++ .../design.md | 360 ++++++++ .../proposal.md | 83 ++ .../corporate-loan-pricing-creation/spec.md | 105 +++ .../personal-loan-pricing-creation/spec.md | 98 ++ .../split-pricing-creation-interface/tasks.md | 149 +++ .../LoanPricingWorkflowController.java | 25 +- .../dto/CorporateLoanPricingCreateDTO.java | 64 ++ .../dto/PersonalLoanPricingCreateDTO.java | 55 ++ .../domain/entity/LoanPricingWorkflow.java | 31 +- .../service/ILoanPricingWorkflowService.java | 16 +- .../impl/LoanPricingWorkflowServiceImpl.java | 30 +- .../util/LoanPricingConverter.java | 65 ++ ruoyi-ui/src/api/loanPricing/workflow.js | 15 +- .../components/CorporateCreateDialog.vue | 319 +++++++ .../components/CorporateWorkflowDetail.vue | 324 +++++++ .../components/CustomerTypeSelector.vue | 105 +++ .../components/PersonalCreateDialog.vue | 270 ++++++ .../components/PersonalWorkflowDetail.vue | 322 +++++++ .../components/WorkflowCreateDialog.vue | 320 ------- .../src/views/loanPricing/workflow/detail.vue | 348 +------ .../src/views/loanPricing/workflow/index.vue | 36 +- sql/add_missing_fields.sql | 33 + sql/fix_all_comments.sql | 45 + sql/fix_comments.sql | 51 ++ sql/fix_comments_utf8.sql | 6 + sql/fix_loan_rate_nullable.sql | 8 + test_api/test_corporate_create.http | 224 +++++ test_api/test_corporate_create.sh | 311 +++++++ test_api/test_personal_create.http | 196 ++++ test_api/test_personal_create.sh | 281 ++++++ 39 files changed, 5253 insertions(+), 719 deletions(-) create mode 100644 .skills/fix-mysql-comments.md create mode 100644 doc/corp.csv create mode 100644 doc/field-mapping-analysis.md create mode 100644 doc/implementation-report.md create mode 100644 doc/person.csv create mode 100644 doc/plans/2025-02-02-customer-type-based-detail-view.md create mode 100644 doc/workflow-create-ui-design.md create mode 100644 openspec/changes/split-pricing-creation-interface/design.md create mode 100644 openspec/changes/split-pricing-creation-interface/proposal.md create mode 100644 openspec/changes/split-pricing-creation-interface/specs/corporate-loan-pricing-creation/spec.md create mode 100644 openspec/changes/split-pricing-creation-interface/specs/personal-loan-pricing-creation/spec.md create mode 100644 openspec/changes/split-pricing-creation-interface/tasks.md create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java create mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue create mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue create mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/CustomerTypeSelector.vue create mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue create mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue delete mode 100644 ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue create mode 100644 sql/add_missing_fields.sql create mode 100644 sql/fix_all_comments.sql create mode 100644 sql/fix_comments.sql create mode 100644 sql/fix_comments_utf8.sql create mode 100644 sql/fix_loan_rate_nullable.sql create mode 100644 test_api/test_corporate_create.http create mode 100644 test_api/test_corporate_create.sh create mode 100644 test_api/test_personal_create.http create mode 100644 test_api/test_personal_create.sh diff --git a/.claude/settings.local.json b/.claude/settings.local.json index b923224..f1ce6e7 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -21,7 +21,11 @@ "Bash(mvn test:*)", "Bash(mvn install:*)", "Bash(mvn clean install:*)", - "mcp__web-reader__webReader" + "mcp__web-reader__webReader", + "Skill(openspec:apply)", + "Skill(superpowers:brainstorming)", + "Skill(superpowers:writing-plans)", + "Skill(superpowers:executing-plans)" ], "additionalDirectories": [ "d:\\利率定价\\loan-pricing-892\\loan-pricing-892-v2.0" diff --git a/.skills/fix-mysql-comments.md b/.skills/fix-mysql-comments.md new file mode 100644 index 0000000..42f9771 --- /dev/null +++ b/.skills/fix-mysql-comments.md @@ -0,0 +1,135 @@ +# 修复MySQL数据库注释乱码 + +## 问题描述 + +MySQL数据库表和字段的中文注释显示为乱码,在Navicat等数据库管理工具中查看时出现 `??` 或其他乱码字符。 + +## 诊断方法 + +```bash +# 检查字段注释的十六进制编码 +mysql -h -P -u -p "" -e " +SELECT COLUMN_NAME, HEX(COLUMN_COMMENT) as comment_hex +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA='' AND TABLE_NAME=''; +" +``` + +**判断标准:** + +- ✅ 正确的UTF-8中文:以 `E4`-`E9` 开头(如 `E698AF` = `是`) +- ❌ 错误编码:以 `C3` 开头(表示双重编码问题) + +## 解决方案 + +### 方法1:创建UTF-8编码的SQL文件(推荐) + +1. **创建SQL文件**,确保保存为UTF-8编码: + +```sql +-- fix_comments.sql +USE ``; +SET NAMES utf8mb4; + +ALTER TABLE `` COMMENT = '正确的中文注释'; + +ALTER TABLE `` + MODIFY COLUMN `column1` varchar(50) DEFAULT NULL COMMENT '字段1中文注释', + MODIFY COLUMN `column2` varchar(50) DEFAULT NULL COMMENT '字段2中文注释', + -- ... 更多字段 +``` + +2. **使用utf8mb4字符集执行**: + +```bash +mysql -h -P -u -p \ + --default-character-set=utf8mb4 "" < fix_comments.sql +``` + +### 方法2:验证SQL文件编码 + +```bash +# 检查文件是否为UTF-8编码 +file fix_comments.sql +# 应该输出: Unicode text, UTF-8 text +``` + +### 方法3:通过heredoc创建SQL文件(跨平台) + +```bash +cat > fix_comments.sql << 'SQLEOF' +USE `your_database`; +SET NAMES utf8mb4; +ALTER TABLE your_table MODIFY COLUMN your_column varchar(10) DEFAULT NULL COMMENT '正确的中文注释'; +SQLEOF +``` + +## 验证修复结果 + +```bash +# 查看表注释 +mysql -h -u -p "" -e " +SELECT table_name, HEX(table_comment) as comment_hex +FROM information_schema.tables +WHERE table_schema='' AND table_name=''; +" + +# 查看字段注释 +mysql -h -u -p "" -e " +SELECT COLUMN_NAME, COLUMN_COMMENT +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA='' AND TABLE_NAME='' +ORDER BY ORDINAL_POSITION; +" + +# 检查是否还有乱码字段(C3开头) +mysql -h -u -p "" -e " +SELECT COUNT(*) as bad_comments +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA='' AND TABLE_NAME='' +AND HEX(COLUMN_COMMENT) REGEXP '^C3'; +" +``` + +## 常见错误及原因 + +| 错误现象 | 原因 | 解决方案 | +|----------------------|----------------------------|-----------------------| +| `C3A6CB9C...` (C3开头) | 双重编码:UTF-8被当作GBK处理后再转UTF-8 | 使用UTF-8文件 + utf8mb4执行 | +| Windows命令行显示乱码 | 终端编码问题,数据库实际正确 | 用HEX()验证实际存储 | +| SQL文件执行后仍乱码 | 文件未保存为UTF-8 | 用`file`命令检查编码 | + +## 最佳实践 + +1. **所有SQL文件使用UTF-8编码保存** +2. **始终使用 `--default-character-set=utf8mb4` 参数** +3. **在SQL开头添加 `SET NAMES utf8mb4;`** +4. **用HEX()验证而非肉眼判断** +5. **批量修复时用脚本生成SQL文件** + +## 示例:批量生成修复SQL + +```bash +#!/bin/bash +# 为指定表生成修复SQL + +DB_NAME="your_database" +TABLE_NAME="your_table" + +cat > fix_${TABLE_NAME}_comments.sql << SQLEOF +USE \`${DB_NAME}\`; +SET NAMES utf8mb4; + +ALTER TABLE \`${TABLE_NAME}\` + COMMENT = '表的中文名称'; + +ALTER TABLE \`${TABLE_NAME}\` + MODIFY COLUMN \`id\` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + MODIFY COLUMN \`name\` varchar(100) DEFAULT NULL COMMENT '名称', + -- 添加更多字段... +SQLEOF + +# 执行修复 +mysql -h localhost -u root -p${DB_PASS} \ + --default-character-set=utf8mb4 "${DB_NAME}" < fix_${TABLE_NAME}_comments.sql +``` diff --git a/doc/api/loan-pricing-workflow-api.md b/doc/api/loan-pricing-workflow-api.md index 03564d9..b437778 100644 --- a/doc/api/loan-pricing-workflow-api.md +++ b/doc/api/loan-pricing-workflow-api.md @@ -14,56 +14,43 @@ ## 接口列表 -### 1. 发起利率定价流程 +### 1. 发起个人客户利率定价流程 -创建新的利率定价申请。 +创建个人客户的利率定价申请。 -**接口地址:** `POST /loanPricing/workflow/create` +**接口地址:** `POST /loanPricing/workflow/create/personal` **权限要求:** `loanPricing:workflow:create` **请求参数:** -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| orgCode | String | 是 | 机构编码,固定值: 931000 | -| runType | String | 是 | 运行模式,固定值: 1(同步) | -| custIsn | String | 是 | 客户内码 | -| custType | String | 是 | 客户类型,可选值: 个人/企业 | -| guarType | String | 是 | 担保方式,可选值: 信用/保证/抵押/质押 | -| midPerQuickPay | String | 否 | 中间业务_个人_快捷支付,值: true/false | -| midPerEleDdc | String | 否 | 中间业务_个人_电费代扣,值: true/false | -| midEntEleDdc | String | 否 | 中间业务_企业_电费代扣,值: true/false | -| midEntWaterDdc | String | 否 | 中间业务_企业_水费代扣,值: true/false | -| applyAmt | String | 是 | 申请金额,单位: 元 | -| isCleanEnt | String | 否 | 净身企业,值: true/false | -| hasSettleAcct | String | 否 | 开立基本结算账户,值: true/false | -| isManufacturing | String | 否 | 制造业企业,值: true/false | -| isAgriGuar | String | 否 | 省农担担保贷款,值: true/false | -| isTaxA | String | 否 | 是否纳税信用等级A级,值: true/false | -| isAgriLeading | String | 否 | 是否县级及以上农业龙头企业,值: true/false | -| loanPurpose | String | 否 | 贷款用途,可选值: consumer/business | -| bizProof | String | 否 | 是否有经营佐证,值: true/false | -| collType | String | 否 | 抵质押类型,可选值: 一线/一类/二类 | -| collThirdParty | String | 否 | 抵质押物是否三方所有,值: true/false | -| loanRate | String | 是 | 贷款利率 | -| custName | String | 否 | 客户名称 | -| idType | String | 否 | 证件类型 | -| isInclusiveFinance | String | 否 | 是否普惠小微借款人,值: true/false | +| 参数名 | 类型 | 必填 | 说明 | +|----------------|--------|----|--------------------------| +| custIsn | String | 是 | 客户内码 | +| custName | String | 否 | 客户名称 | +| idType | String | 否 | 证件类型 | +| idNum | String | 否 | 证件号码 | +| guarType | String | 是 | 担保方式,可选值: 信用/保证/抵押/质押 | +| applyAmt | String | 是 | 申请金额,单位: 元 | +| bizProof | String | 否 | 是否有经营佐证,值: true/false | +| loanLoop | String | 否 | 循环功能,值: true/false | +| collType | String | 否 | 抵质押类型,可选值: 一线/一类/二类 | +| collThirdParty | String | 否 | 抵质押物是否三方所有,值: true/false | **请求示例:** ```json { - "orgCode": "931000", - "runType": "1", "custIsn": "CUST001", - "custType": "企业", + "custName": "张三", + "idType": "身份证", + "idNum": "110101199001011234", "guarType": "抵押", - "applyAmt": "1000000", - "loanRate": "4.35", - "custName": "某某科技有限公司", - "loanPurpose": "business" + "applyAmt": "500000", + "bizProof": "true", + "loanLoop": "false", + "collType": "一类", + "collThirdParty": "false" } ``` @@ -80,11 +67,11 @@ "orgCode": "931000", "runType": "1", "custIsn": "CUST001", - "custType": "企业", + "custType": "个人", "guarType": "抵押", - "applyAmt": "1000000", - "loanRate": "4.35", - "custName": "某某科技有限公司", + "applyAmt": "500000", + "custName": "张三", + "idType": "身份证", "createTime": "2025-01-19 14:30:25", "createBy": "admin" } @@ -93,7 +80,79 @@ --- -### 2. 查询利率定价流程列表 +### 2. 发起企业客户利率定价流程 + +创建企业客户的利率定价申请。 + +**接口地址:** `POST /loanPricing/workflow/create/corporate` + +**权限要求:** `loanPricing:workflow:create` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|---------------------|--------|----|--------------------------| +| custIsn | String | 是 | 客户内码 | +| custName | String | 否 | 客户名称 | +| idType | String | 否 | 证件类型 | +| idNum | String | 否 | 证件号码 | +| guarType | String | 是 | 担保方式,可选值: 信用/保证/抵押/质押 | +| applyAmt | String | 是 | 申请金额,单位: 元 | +| loanTerm | String | 否 | 贷款期限(月) | +| isAgriGuar | String | 否 | 省农担担保贷款,值: true/false | +| isGreenLoan | String | 否 | 绿色贷款,值: true/false | +| isTechEnt | String | 否 | 科技型企业,值: true/false | +| isTradeConstruction | String | 否 | 贸易和建筑业企业标识,值: true/false | +| collType | String | 否 | 抵质押类型,可选值: 一线/一类/二类 | +| collThirdParty | String | 否 | 抵质押物是否三方所有,值: true/false | + +**请求示例:** + +```json +{ + "custIsn": "CORP001", + "custName": "某某科技有限公司", + "idType": "统一社会信用代码", + "idNum": "91110000100000000X", + "guarType": "抵押", + "applyAmt": "1000000", + "loanTerm": "36", + "isAgriGuar": "false", + "isGreenLoan": "true", + "isTechEnt": "true", + "isTradeConstruction": "false", + "collType": "一类", + "collThirdParty": "false" +} +``` + +**响应示例:** + +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "id": 2, + "modelOutputId": 101, + "serialNum": "20250119143125456", + "orgCode": "931000", + "runType": "1", + "custIsn": "CORP001", + "custType": "企业", + "guarType": "抵押", + "applyAmt": "1000000", + "custName": "某某科技有限公司", + "idType": "统一社会信用代码", + "createTime": "2025-01-19 14:31:25", + "createBy": "admin" + } +} +``` + +--- + +### 3. 查询利率定价流程列表 分页查询利率定价流程记录,支持多条件筛选。 @@ -150,7 +209,7 @@ GET /loanPricing/workflow/list?pageNum=1&pageSize=10&custName=科技 --- -### 3. 查看利率定价流程详情 +### 4. 查看利率定价流程详情 根据业务方流水号查询流程的完整信息,包括模型输出字段。 @@ -326,7 +385,7 @@ GET /loanPricing/workflow/20250119143025123 --- -### 4. 设定执行利率 +### 5. 设定执行利率 为利率定价流程设定或更新最终执行利率。 @@ -440,12 +499,6 @@ PUT /loanPricing/workflow/20250119143025123/executeRate | 一类 | 一类抵押 | | 二类 | 二类抵押 | -### 运行模式 (runType) - -| 值 | 说明 | -|----|------| -| 1 | 同步运行 | - --- ## 在线文档 diff --git a/doc/corp.csv b/doc/corp.csv new file mode 100644 index 0000000..4e83672 --- /dev/null +++ b/doc/corp.csv @@ -0,0 +1,15 @@ +中文名,字段名,备注 +客户内码,custIsn, +客户类型,custType,企业 +担保方式,guarType,"可选值:信用,保证,抵押,质押" +客户名称,custName, +证件类型,idType, +证件号码,idNum, +贸易和建筑业企业,,抵(质)押类:贸易和建筑业企业上调20BP +省农担担保贷款,isAgriGuar,省农担担保贷款下调40个BP +绿色贷款,isGreenLoan,绿色贷款或科技型企业最多下降5BP +科技型企业,isTechEnt,绿色贷款或科技型企业最多下降5BP +贷款期限,loanTerm, +申请金额,applyAmt,单位:元 +抵质押类型,collType, +抵质押物是否三方所有,collThirdParty, diff --git a/doc/field-mapping-analysis.md b/doc/field-mapping-analysis.md new file mode 100644 index 0000000..b78c203 --- /dev/null +++ b/doc/field-mapping-analysis.md @@ -0,0 +1,127 @@ +# 字段匹配分析报告 + +## 概述 + +本报告对比了 `person.csv`、`corp.csv` 中定义的字段与数据库表 `loan_pricing_workflow` 的实际字段,识别出需要添加的字段。 + +--- + +## 个人客户字段对比 + +| CSV字段名 | 中文名 | CSV要求 | 数据库字段 | 匹配状态 | +|----------------|------------|--------------------|------------------|---------| +| custIsn | 客户内码 | 必填 | cust_isn | ✅ 匹配 | +| custType | 客户类型 | 固定值"个人" | cust_type | ✅ 匹配 | +| guarType | 担保方式 | 必填,可选值:信用/保证/抵押/质押 | guar_type | ✅ 匹配 | +| custName | 客户名称 | 可选 | cust_name | ✅ 匹配 | +| idType | 证件类型 | 可选 | id_type | ✅ 匹配 | +| idNum | 证件号码 | 可选 | **❌ 缺失** | ⚠️ 需要添加 | +| applyAmt | 申请金额 | 必填,单位:元 | apply_amt | ✅ 匹配 | +| bizProof | 是否有经营佐证 | 可选 | biz_proof | ✅ 匹配 | +| loanLoop | 循环功能 | 可选 | **❌ 缺失** | ⚠️ 需要添加 | +| collType | 抵质押类型 | 可选 | coll_type | ✅ 匹配 | +| collThirdParty | 抵质押物是否三方所有 | 可选 | coll_third_party | ✅ 匹配 | + +### 个人客户缺失字段 + +| 字段名 | 中文名 | 类型 | 说明 | +|-----------|------|--------------|-------------------------| +| id_num | 证件号码 | varchar(100) | 存储个人身份证号或其他证件号码 | +| loan_loop | 循环功能 | varchar(10) | 贷款合同是否开通循环功能,true/false | + +--- + +## 企业客户字段对比 + +| CSV字段名 | 中文名 | CSV要求 | 数据库字段 | 匹配状态 | +|----------------|------------|-----------------------|------------------|---------| +| custIsn | 客户内码 | 必填 | cust_isn | ✅ 匹配 | +| custType | 客户类型 | 固定值"企业" | cust_type | ✅ 匹配 | +| guarType | 担保方式 | 必填,可选值:信用/保证/抵押/质押 | guar_type | ✅ 匹配 | +| custName | 客户名称 | 可选 | cust_name | ✅ 匹配 | +| idType | 证件类型 | 可选 | id_type | ✅ 匹配 | +| idNum | 证件号码 | 可选 | **❌ 缺失** | ⚠️ 需要添加 | +| (无字段名) | 贸易和建筑业企业 | 抵(质)押类:贸易和建筑业企业上调20BP | **❌ 缺失** | ⚠️ 需要添加 | +| isAgriGuar | 省农担担保贷款 | 省农担担保贷款下调40个BP | is_agri_guar | ✅ 匹配 | +| isGreenLoan | 绿色贷款 | 绿色贷款或科技型企业最多下降5BP | **❌ 缺失** | ⚠️ 需要添加 | +| isTechEnt | 科技型企业 | 绿色贷款或科技型企业最多下降5BP | **❌ 缺失** | ⚠️ 需要添加 | +| loanTerm | 贷款期限 | 可选 | **❌ 缺失** | ⚠️ 需要添加 | +| applyAmt | 申请金额 | 必填,单位:元 | apply_amt | ✅ 匹配 | +| collType | 抵质押类型 | 可选 | coll_type | ✅ 匹配 | +| collThirdParty | 抵质押物是否三方所有 | 可选 | coll_third_party | ✅ 匹配 | + +### 企业客户缺失字段 + +| 字段名 | 中文名 | 类型 | 说明 | +|-----------------------|------------|--------------|----------------------------------| +| id_num | 证件号码 | varchar(100) | 存储企业统一社会信用代码或其他证件号码 | +| is_trade_construction | 贸易和建筑业企业标识 | varchar(10) | 抵(质)押类:贸易和建筑业企业上调20BP,true/false | +| is_green_loan | 绿色贷款 | varchar(10) | 绿色贷款标识,true/false | +| is_tech_ent | 科技型企业 | varchar(10) | 科技型企业标识,true/false | +| loan_term | 贷款期限 | varchar(50) | 贷款期限,单位:月/年 | + +--- + +## 数据库变更 SQL + +```sql +-- 添加缺失的字段到 loan_pricing_workflow 表 + +-- 个人和企业共同需要的字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码' AFTER `id_type`; + +-- 个人客户专用字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false' AFTER `biz_proof`; + +-- 企业客户专用字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_trade_construction` varchar(10) DEFAULT NULL COMMENT '贸易和建筑业企业标识: true/false(抵质押类上调20BP)' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_green_loan` varchar(10) DEFAULT NULL COMMENT '绿色贷款: true/false' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_tech_ent` varchar(10) DEFAULT NULL COMMENT '科技型企业: true/false' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_term` varchar(50) DEFAULT NULL COMMENT '贷款期限' AFTER `apply_amt`; +``` + +--- + +## Entity 类更新 + +`LoanPricingWorkflow.java` 需要添加以下属性: + +```java +/** 证件号码 */ +private String idNum; + +/** 循环功能: true/false */ +private String loanLoop; + +/** 贸易和建筑业企业标识: true/false */ +private String isTradeConstruction; + +/** 绿色贷款: true/false */ +private String isGreenLoan; + +/** 科技型企业: true/false */ +private String isTechEnt; + +/** 贷款期限 */ +private String loanTerm; +``` + +--- + +## 建议行动 + +1. **立即执行**:添加缺失的数据库字段 +2. **更新 Entity**:在 `LoanPricingWorkflow` 实体类中添加对应的属性 +3. **更新 Proposal**:在 `split-pricing-creation-interface` 的 tasks.md 中添加数据库变更任务 +4. **测试验证**:确保新字段可以正确存储和检索数据 + +--- + +## 总结 + +- **个人客户缺失字段**:2 个(id_num, loan_loop) +- **企业客户缺失字段**:5 个(id_num, is_trade_construction, is_green_loan, is_tech_ent, loan_term) +- **共同缺失字段**:1 个(id_num) +- **总计需要添加**:6 个新字段 + +数据库和实体类需要同步更新,才能支持新的个人和企业发起接口。 diff --git a/doc/implementation-report.md b/doc/implementation-report.md new file mode 100644 index 0000000..fe58cf5 --- /dev/null +++ b/doc/implementation-report.md @@ -0,0 +1,161 @@ +# 利率定价接口拆分实施报告 + +## 实施摘要 + +本次实施成功将原有的统一利率定价发起接口拆分为两个独立的接口: + +- **个人客户发起接口**: `POST /loanPricing/workflow/create/personal` +- **企业客户发起接口**: `POST /loanPricing/workflow/create/corporate` + +## 已完成的任务 + +### ✅ 数据库变更 + +- **文件**: `sql/add_missing_fields.sql` +- **新增字段**: + - `id_num` (varchar(100)) - 证件号码 + - `loan_loop` (varchar(10)) - 循环功能(个人专用) + - `is_trade_construction` (varchar(10)) - 贸易和建筑业企业标识(企业专用) + - `is_green_loan` (varchar(10)) - 绿色贷款(企业专用) + - `is_tech_ent` (varchar(10)) - 科技型企业(企业专用) + - `loan_term` (varchar(50)) - 贷款期限(企业专用) + +> **注意**: SQL 脚本已创建,需手动执行到数据库 + +### ✅ Entity 类更新 + +- **文件**: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java` +- 添加了 6 个新属性 + +### ✅ DTO 类创建 + +1. **PersonalLoanPricingCreateDTO.java** - 个人客户发起 DTO + - 包含个人特有字段:bizProof、loanLoop + - 字段验证:custIsn、guarType、applyAmt 必填 + - 担保方式枚举验证 + +2. **CorporateLoanPricingCreateDTO.java** - 企业客户发起 DTO + - 包含企业特有字段:isAgriGuar、isGreenLoan、isTechEnt、isTradeConstruction、loanTerm + - 字段验证:custIsn、guarType、applyAmt 必填 + - 担保方式枚举验证 + +### ✅ 转换器工具类 + +- **文件**: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java` +- 实现 DTO 到 Entity 的转换 +- 自动设置 custType 为"个人"或"企业" + +### ✅ Service 层更新 + +- **接口**: `ILoanPricingWorkflowService.java` + - 新增: `createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto)` + - 新增: `createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto)` + +- **实现**: `LoanPricingWorkflowServiceImpl.java` + - 实现了两个新方法,复用现有的 createLoanPricing 逻辑 + +### ✅ Controller 层更新 + +- **文件**: `LoanPricingWorkflowController.java` +- 新增接口: + - `POST /loanPricing/workflow/create/personal` + - `POST /loanPricing/workflow/create/corporate` +- 保留了原有接口,保持向后兼容 + +### ✅ HTTP 测试脚本 + +1. **test_personal_create.http** - 个人客户接口测试 + - 成功场景测试 + - 3 个缺少必填字段的失败场景 + - 担保方式枚举验证测试 + - 抵质押信息测试 + - 最小必填字段测试 + +2. **test_corporate_create.http** - 企业客户接口测试 + - 成功场景测试 + - 3 个缺少必填字段的失败场景 + - 担保方式枚举验证测试 + - 企业特有字段测试(省农担、绿色贷款、科技企业、贸易建筑) + - 最小必填字段测试 + +3. **test_backward_compatibility.http** - 向后兼容性测试 + - 原有接口个人客户测试 + - 原有接口企业客户测试 + +## 待完成任务 + +### ⏳ 需要手动执行的步骤 + +1. **执行数据库迁移脚本** + ```bash + # 在 MySQL 中执行 + source sql/add_missing_fields.sql + ``` + +2. **执行 HTTP 测试脚本** + - 使用 IntelliJ IDEA 打开 `test_api/` 目录下的 .http 文件 + - 逐一执行测试用例 + - 验证返回结果 + +3. **启动应用并验证** + ```bash + # 启动后端应用 + mvn spring-boot:run + ``` + - 访问 Swagger UI: `http://localhost:8080/swagger-ui.html` + - 验证新接口文档显示正确 + +## 接口使用说明 + +### 个人客户发起接口 + +**端点**: `POST /loanPricing/workflow/create/personal` + +**请求示例**: + +```json +{ + "custIsn": "TEST001", + "custName": "张三", + "idType": "身份证", + "idNum": "110101199001011234", + "guarType": "信用", + "applyAmt": "500000", + "bizProof": "true", + "loanLoop": "false" +} +``` + +### 企业客户发起接口 + +**端点**: `POST /loanPricing/workflow/create/corporate` + +**请求示例**: + +```json +{ + "custIsn": "CORP001", + "custName": "测试科技有限公司", + "idType": "统一社会信用代码", + "idNum": "91110000100000000X", + "guarType": "抵押", + "applyAmt": "1000000", + "loanTerm": "36", + "isAgriGuar": "false", + "isGreenLoan": "true", + "isTechEnt": "true" +} +``` + +## 验证清单 + +- [x] 数据库迁移脚本已创建 +- [x] Entity 类已更新 +- [x] DTO 类已创建 +- [x] 转换器已创建 +- [x] Service 接口和实现已更新 +- [x] Controller 接口已添加 +- [x] HTTP 测试脚本已生成 +- [ ] 数据库迁移脚本已执行 +- [ ] 测试脚本已执行并通过 +- [ ] Swagger 文档已验证 diff --git a/doc/person.csv b/doc/person.csv new file mode 100644 index 0000000..27a0a50 --- /dev/null +++ b/doc/person.csv @@ -0,0 +1,12 @@ +中文名,字段名,备注 +客户内码,custIsn, +客户类型,custType,个人 +担保方式,guarType,"可选值:信用,保证,抵押,质押" +客户名称,custName, +证件类型,idType, +证件号码,idNum, +申请金额,applyAmt,单位:元 +是否有经营佐证,bizProof,个人经营性贷款提供的经营佐证包括:借款人或其配偶为法定代表人、实际经营者、股东的企业(个体工商户)营业执照或企查查、企信宝查档资料。 +循环功能,loanLoop,贷款合同是否开通循环功能 +抵质押类型,collType, +抵质押物是否三方所有,collThirdParty, diff --git a/doc/plans/2025-02-02-customer-type-based-detail-view.md b/doc/plans/2025-02-02-customer-type-based-detail-view.md new file mode 100644 index 0000000..f521a6e --- /dev/null +++ b/doc/plans/2025-02-02-customer-type-based-detail-view.md @@ -0,0 +1,854 @@ +# 根据客户类型动态展示流程详情实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**目标:** 创建两个独立的详情组件(个人客户和企业客户),根据客户类型动态渲染不同的字段展示。 + +**架构:** 将现有的单一详情页面拆分为两个独立组件(PersonalWorkflowDetail.vue 和 CorporateWorkflowDetail.vue),父组件 +detail.vue 作为容器负责数据获取和根据 custType 动态分发渲染。 + +**技术栈:** Vue 2.6.12, Element UI 2.15.14, Vue Router 3.4.9 + +--- + +## Task 1: 创建个人客户详情组件 PersonalWorkflowDetail.vue + +**文件:** + +- 创建: `ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue` + +**Step 1: 创建组件基础结构** + +```vue + + + + + +``` + +**Step 2: 验证组件语法正确** + +检查: 在浏览器开发工具中确认无语法错误 + +--- + +## Task 2: 创建企业客户详情组件 CorporateWorkflowDetail.vue + +**文件:** + +- 创建: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue` + +**Step 1: 创建组件基础结构** + +```vue + + + + + +``` + +**Step 2: 验证组件语法正确** + +检查: 在浏览器开发工具中确认无语法错误 + +--- + +## Task 3: 修改 detail.vue 为容器组件 + +**文件:** + +- 修改: `ruoyi-ui/src/views/loanPricing/workflow/detail.vue` + +**Step 1: 替换为容器组件结构** + +将整个文件内容替换为: + +```vue + + + + + +``` + +**Step 2: 验证修改正确** + +检查: 在浏览器中访问详情页,确认根据客户类型正确渲染对应组件 + +--- + +## Task 4: 测试验证 + +**Step 1: 测试个人客户详情页** + +1. 在列表页点击个人客户记录的"查看"按钮 +2. 确认页面正确显示 PersonalWorkflowDetail 组件 +3. 确认所有个人客户字段正确显示 +4. 确认模型输出正确展示(retailOutput) +5. 测试执行利率设定功能 + +**Step 2: 测试企业客户详情页** + +1. 在列表页点击企业客户记录的"查看"按钮 +2. 确认页面正确显示 CorporateWorkflowDetail 组件 +3. 确认所有企业客户字段正确显示 +4. 确认模型输出正确展示(corpOutput) +5. 测试执行利率设定功能 + +**Step 3: 响应式布局测试** + +1. 调整浏览器窗口宽度到小于992px +2. 确认布局自动切换为单列垂直布局 +3. 确认所有内容正常显示 + +--- + +## Task 5: 提交代码 + +**Step 1: 添加文件到 Git** + +```bash +git add ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue +git add ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue +git add ruoyi-ui/src/views/loanPricing/workflow/detail.vue +``` + +**Step 2: 提交变更** + +```bash +git commit -m "feat: 根据客户类型动态展示流程详情 + +- 创建 PersonalWorkflowDetail.vue 个人客户详情组件 +- 创建 CorporateWorkflowDetail.vue 企业客户详情组件 +- 修改 detail.vue 为容器组件,根据 custType 动态渲染 +- 个人客户展示:基本信息(客户内码、证件信息)+ 业务信息(担保方式、经营佐证、循环功能等) +- 企业客户展示:基本信息(客户内码、证件信息、贷款期限)+ 业务信息(省农担担保、绿色贷款、科技型企业等) +- 两个组件完全独立,各自实现格式化和计算方法 +- 支持响应式布局,小屏幕自动切换为单列布局" +``` + +--- + +## 相关文档 + +- 字段定义参考: `doc/person.csv` 和 `doc/corp.csv` +- API 文档: `doc/api/loan-pricing-workflow-api.md` +- 原详情页面: `ruoyi-ui/src/views/loanPricing/workflow/detail.vue` (修改前) diff --git a/doc/workflow-create-ui-design.md b/doc/workflow-create-ui-design.md new file mode 100644 index 0000000..3172618 --- /dev/null +++ b/doc/workflow-create-ui-design.md @@ -0,0 +1,216 @@ +# 利率定价创建流程前端重构设计文档 + +## 设计概述 + +本文档描述利率定价创建流程的前端重构设计,将原有的单一表单拆分为个人客户和企业客户两个独立的创建流程。 + +## 设计日期 + +2026-02-02 + +--- + +## 一、交互流程 + +### 用户操作步骤 + +1. **点击「新增」按钮** → 弹出「选择客户类型」对话框 +2. **选择客户类型** → 打开对应的创建表单对话框 +3. **填写表单并提交** → 调用对应的 API 接口 +4. **成功/失败处理** + - 成功:关闭对话框,刷新列表,显示成功提示 + - 失败:保留表单数据,显示后端错误信息 + +--- + +## 二、组件结构 + +### 文件组织 + +``` +ruoyi-ui/src/ +├── views/loanPricing/workflow/ +│ ├── index.vue (修改) +│ └── components/ +│ ├── CustomerTypeSelector.vue (新增) +│ ├── WorkflowCreateDialog.vue (删除) +│ ├── PersonalCreateDialog.vue (新增) +│ └── CorporateCreateDialog.vue (新增) +└── api/loanPricing/ + └── workflow.js (修改) +``` + +### 组件职责 + +| 组件 | 职责 | +|-----------------------|-----------| +| CustomerTypeSelector | 客户类型选择对话框 | +| PersonalCreateDialog | 个人客户创建表单 | +| CorporateCreateDialog | 企业客户创建表单 | + +--- + +## 三、表单字段设计 + +### 个人客户表单字段 + +| 分组 | 字段 | 类型 | 必填 | 说明 | +|-------|----------------|--------|----|------------| +| 基本信息 | custIsn | String | 是 | 客户内码 | +| 基本信息 | custName | String | 是 | 客户名称 | +| 基本信息 | idType | String | 是 | 证件类型 | +| 基本信息 | idNum | String | 是 | 证件号码 | +| 贷款信息 | guarType | String | 是 | 担保方式 | +| 贷款信息 | applyAmt | String | 是 | 申请金额(元) | +| 贷款信息 | bizProof | String | 是 | 是否有经营佐证 | +| 贷款信息 | loanLoop | String | 是 | 循环功能 | +| 抵质押信息 | collType | String | 是 | 抵质押类型 | +| 抵质押信息 | collThirdParty | String | 是 | 抵质押物是否三方所有 | + +### 企业客户表单字段 + +| 分组 | 字段 | 类型 | 必填 | 说明 | +|-------|---------------------|--------|----|------------| +| 基本信息 | custIsn | String | 是 | 客户内码 | +| 基本信息 | custName | String | 是 | 客户名称 | +| 基本信息 | idType | String | 是 | 证件类型 | +| 基本信息 | idNum | String | 是 | 证件号码 | +| 贷款信息 | guarType | String | 是 | 担保方式 | +| 贷款信息 | applyAmt | String | 是 | 申请金额(元) | +| 贷款信息 | loanTerm | String | 是 | 贷款期限(月) | +| 企业标识 | isAgriGuar | String | 是 | 省农担担保贷款 | +| 企业标识 | isGreenLoan | String | 是 | 绿色贷款 | +| 企业标识 | isTechEnt | String | 是 | 科技型企业 | +| 企业标识 | isTradeConstruction | String | 是 | 贸易和建筑业企业 | +| 抵质押信息 | collType | String | 是 | 抵质押类型 | +| 抵质押信息 | collThirdParty | String | 是 | 抵质押物是否三方所有 | + +--- + +## 四、API 接口设计 + +### 新增接口函数 + +```javascript +// 创建个人客户利率定价流程 +export function createPersonalWorkflow(data) { + return request({ + url: '/loanPricing/workflow/create/personal', + method: 'post', + data: data + }) +} + +// 创建企业客户利率定价流程 +export function createCorporateWorkflow(data) { + return request({ + url: '/loanPricing/workflow/create/corporate', + method: 'post', + data: data + }) +} +``` + +### 数据转换规则 + +开关字段在提交时需要转换为字符串 `"true"/"false"`: + +```javascript +bizProof: this.form.bizProof ? 'true' : 'false' +``` + +--- + +## 五、验证规则 + +### 个人客户验证规则 + +| 字段 | 验证规则 | +|----------------|------------------------| +| custIsn | 必填,长度 1-50 字符 | +| custName | 必填,长度 1-100 字符 | +| idType | 必填 | +| idNum | 必填,身份证格式 15/18 位 | +| guarType | 必填 | +| applyAmt | 必填,正数,最大值 999999999.99 | +| bizProof | 必填(开关值,默认 "false") | +| loanLoop | 必填(开关值,默认 "false") | +| collType | 必填 | +| collThirdParty | 必填(开关值,默认 "false") | + +### 企业客户验证规则 + +| 字段 | 验证规则 | +|---------------------|------------------------| +| custIsn | 必填,长度 1-50 字符 | +| custName | 必填,长度 1-100 字符 | +| idType | 必填 | +| idNum | 必填,统一社会信用代码 18 位 | +| guarType | 必填 | +| applyAmt | 必填,正数,最大值 999999999.99 | +| loanTerm | 必填,正整数,范围 1-360 | +| isAgriGuar | 必填(开关值,默认 "false") | +| isGreenLoan | 必填(开关值,默认 "false") | +| isTechEnt | 必填(开关值,默认 "false") | +| isTradeConstruction | 必填(开关值,默认 "false") | +| collType | 必填 | +| collThirdParty | 必填(开关值,默认 "false") | + +--- + +## 六、UI 样式规范 + +### 对话框规范 + +| 对话框类型 | 宽度 | 说明 | +|--------|-------|------| +| 客户类型选择 | 500px | 居中显示 | +| 表单对话框 | 900px | 两列布局 | + +### 表单布局 + +- 分组:使用 `el-divider` 分隔,带标题 +- 字段:两列布局(`el-col :span="12"`) +- 必填标识:红色星号 +- 按钮:右下角,「确定」(主按钮)、「取消」 + +### 响应式处理 + +- 当屏幕宽度 < 768px 时,表单字段改为单列布局 + +--- + +## 七、错误处理 + +| 场景 | 处理方式 | +|--------|--------------------| +| 前端验证失败 | 阻止提交,高亮错误字段 | +| 网络错误 | 显示网络错误提示,保留表单 | +| 后端业务错误 | 显示后端返回的 `msg`,保留表单 | +| 成功 | 关闭对话框,刷新列表,显示成功提示 | + +--- + +## 八、数据字典 + +### 担保方式 (guarType) + +| 值 | 说明 | +|----|------| +| 信用 | 信用贷款 | +| 保证 | 保证贷款 | +| 抵押 | 抵押贷款 | +| 质押 | 质押贷款 | + +### 抵质押类型 (collType) + +| 值 | 说明 | +|----|------| +| 一线 | 一线抵押 | +| 一类 | 一类抵押 | +| 二类 | 二类抵押 | + +### 证件类型 (idType) + +- 个人:身份证 +- 企业:统一社会信用代码 diff --git a/openspec/changes/split-pricing-creation-interface/design.md b/openspec/changes/split-pricing-creation-interface/design.md new file mode 100644 index 0000000..0bbadf5 --- /dev/null +++ b/openspec/changes/split-pricing-creation-interface/design.md @@ -0,0 +1,360 @@ +# Design: 拆分个人和企业利率定价发起接口 + +## 数据库变更 + +### 缺失字段分析 + +经过对比 `person.csv` 和 `corp.csv` 中定义的字段与现有数据库表 `loan_pricing_workflow`,发现以下字段缺失: + +#### 个人客户缺失字段 + +| 字段名 | 中文名 | 类型 | 说明 | +|-----------|------|--------------|-------------------------| +| id_num | 证件号码 | varchar(100) | 存储个人身份证号或其他证件号码 | +| loan_loop | 循环功能 | varchar(10) | 贷款合同是否开通循环功能,true/false | + +#### 企业客户缺失字段 + +| 字段名 | 中文名 | 类型 | 说明 | +|-----------------------|------------|--------------|----------------------------------| +| id_num | 证件号码 | varchar(100) | 存储企业统一社会信用代码或其他证件号码 | +| is_trade_construction | 贸易和建筑业企业标识 | varchar(10) | 抵(质)押类:贸易和建筑业企业上调20BP,true/false | +| is_green_loan | 绿色贷款 | varchar(10) | 绿色贷款标识,true/false | +| is_tech_ent | 科技型企业 | varchar(10) | 科技型企业标识,true/false | +| loan_term | 贷款期限 | varchar(50) | 贷款期限,单位:月/年 | + +### 数据库迁移 SQL + +```sql +-- 添加缺失的字段到 loan_pricing_workflow 表 + +-- 个人和企业共同需要的字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码' AFTER `id_type`; + +-- 个人客户专用字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false' AFTER `biz_proof`; + +-- 企业客户专用字段 +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_trade_construction` varchar(10) DEFAULT NULL COMMENT '贸易和建筑业企业标识: true/false(抵质押类上调20BP)' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_green_loan` varchar(10) DEFAULT NULL COMMENT '绿色贷款: true/false' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_tech_ent` varchar(10) DEFAULT NULL COMMENT '科技型企业: true/false' AFTER `is_agri_guar`; +ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_term` varchar(50) DEFAULT NULL COMMENT '贷款期限' AFTER `apply_amt`; +``` + +### Entity 类更新 + +`LoanPricingWorkflow.java` 需要添加以下属性: + +```java +/** 证件号码 */ +private String idNum; + +/** 循环功能: true/false */ +private String loanLoop; + +/** 贸易和建筑业企业标识: true/false */ +private String isTradeConstruction; + +/** 绿色贷款: true/false */ +private String isGreenLoan; + +/** 科技型企业: true/false */ +private String isTechEnt; + +/** 贷款期限 */ +private String loanTerm; +``` + +## 架构设计 + +### 1. DTO 结构设计 + +#### PersonalLoanPricingCreateDTO(个人客户发起DTO) + +```java +@Data +public class PersonalLoanPricingCreateDTO { + @NotBlank(message = "客户内码不能为空") + private String custIsn; + + @NotBlank(message = "客户类型不能为空") + private String custType; // 固定值 "个人" + + @NotBlank(message = "担保方式不能为空") + private String guarType; // 可选值:信用,保证,抵押,质押 + + private String custName; + private String idType; + private String idNum; + + @NotBlank(message = "申请金额不能为空") + private String applyAmt; // 单位:元 + + private String bizProof; // 是否有经营佐证 + private String loanLoop; // 循环功能 + + private String collType; // 抵质押类型 + private String collThirdParty; // 抵质押物是否三方所有 +} +``` + +#### CorporateLoanPricingCreateDTO(企业客户发起DTO) + +```java +@Data +public class CorporateLoanPricingCreateDTO { + @NotBlank(message = "客户内码不能为空") + private String custIsn; + + @NotBlank(message = "客户类型不能为空") + private String custType; // 固定值 "企业" + + @NotBlank(message = "担保方式不能为空") + private String guarType; // 可选值:信用,保证,抵押,质押 + + private String custName; + private String idType; + private String idNum; + + @NotBlank(message = "申请金额不能为空") + private String applyAmt; // 单位:元 + + private String isAgriGuar; // 省农担担保贷款 + private String isGreenLoan; // 绿色贷款 + private String isTechEnt; // 科技型企业 + private String loanTerm; // 贷款期限 + + private String collType; // 抵质押类型 + private String collThirdParty; // 抵质押物是否三方所有 +} +``` + +### 2. 接口设计 + +#### Controller 层 + +```java +@RestController +@RequestMapping("/loanPricing/workflow") +public class LoanPricingWorkflowController extends BaseController { + + // 原有接口(保留) + @PostMapping("/create") + public AjaxResult create(@Validated @RequestBody LoanPricingWorkflow loanPricingWorkflow) + + // 新增:个人客户发起接口 + @PostMapping("/create/personal") + public AjaxResult createPersonal(@Validated @RequestBody PersonalLoanPricingCreateDTO dto) + + // 新增:企业客户发起接口 + @PostMapping("/create/corporate") + public AjaxResult createCorporate(@Validated @RequestBody CorporateLoanPricingCreateDTO dto) +} +``` + +#### Service 层接口 + +```java +public interface ILoanPricingWorkflowService { + // 原有方法(保留兼容) + LoanPricingWorkflow createLoanPricing(LoanPricingWorkflow loanPricingWorkflow); + + // 新增:个人客户发起 + LoanPricingWorkflow createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto); + + // 新增:企业客户发起 + LoanPricingWorkflow createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto); +} +``` + +### 3. 字段映射关系 + +| 字段类别 | 个人字段 | 企业字段 | +|------|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| 共同字段 | custIsn, custType, guarType, custName, idType, idNum, applyAmt, collType, collThirdParty | | +| 个人特有 | bizProof(是否有经营佐证), loanLoop(循环功能) | | +| 企业特有 | | isAgriGuar(省农担担保贷款), isGreenLoan(绿色贷款), isTechEnt(科技型企业), isTradeConstruction(贸易和建筑业企业), loanTerm(贷款期限) | + +### 4. 实现细节 + +#### DTO 转 Entity 转换器 + +创建一个转换工具类,将 DTO 转换为 `LoanPricingWorkflow` 实体: + +```java +public class LoanPricingConverter { + public static LoanPricingWorkflow toEntity(PersonalLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = new LoanPricingWorkflow(); + // 映射共同字段 + entity.setCustIsn(dto.getCustIsn()); + entity.setCustType("个人"); + entity.setCustName(dto.getCustName()); + entity.setIdType(dto.getIdType()); + entity.setIdNum(dto.getIdNum()); + entity.setGuarType(dto.getGuarType()); + entity.setApplyAmt(dto.getApplyAmt()); + entity.setCollType(dto.getCollType()); + entity.setCollThirdParty(dto.getCollThirdParty()); + // 映射个人特有字段 + entity.setBizProof(dto.getBizProof()); + entity.setLoanLoop(dto.getLoanLoop()); + return entity; + } + + public static LoanPricingWorkflow toEntity(CorporateLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = new LoanPricingWorkflow(); + // 映射共同字段 + entity.setCustIsn(dto.getCustIsn()); + entity.setCustType("企业"); + entity.setCustName(dto.getCustName()); + entity.setIdType(dto.getIdType()); + entity.setIdNum(dto.getIdNum()); + entity.setGuarType(dto.getGuarType()); + entity.setApplyAmt(dto.getApplyAmt()); + entity.setCollType(dto.getCollType()); + entity.setCollThirdParty(dto.getCollThirdParty()); + // 映射企业特有字段 + entity.setIsAgriGuar(dto.getIsAgriGuar()); + entity.setIsGreenLoan(dto.getIsGreenLoan()); + entity.setIsTechEnt(dto.getIsTechEnt()); + entity.setIsTradeConstruction(dto.getIsTradeConstruction()); + entity.setLoanTerm(dto.getLoanTerm()); + return entity; + } +} +``` + +### 5. 验证策略 + +#### 个人客户验证 + +- 必填字段:custIsn, custType, guarType, applyAmt +- 枚举验证:guarType 必须是"信用/保证/抵押/质押"之一 + +#### 企业客户验证 + +- 必填字段:custIsn, custType, guarType, applyAmt +- 枚举验证:guarType 必须是"信用/保证/抵押/质押"之一 + +### 6. 向后兼容性策略 + +1. 保留原有 `POST /loanPricing/workflow/create` 接口 +2. 新旧接口共存,前端可自由选择使用 +3. 不添加 @Deprecated 标记,保持接口的可用性 + +## 技术决策 + +### 为什么使用两个独立的 DTO 而不是一个带条件验证的 DTO? + +1. **类型安全**:编译期就能发现字段错误 +2. **API 文档更清晰**:Swagger 只显示相关字段 +3. **验证更简单**:不需要在 DTO 内部根据类型做条件验证 + +### 为什么保留原有接口? + +1. **多接口共存**:前端可以选择使用新接口或继续使用原有接口 +2. **降级方案**:如果新接口有问题,可以快速回退 +3. **兼容性**:可能有其他系统调用该接口 + +## 文件清单 + +### 数据库相关 + +- **新增**: `sql/add_missing_fields.sql` - 数据库迁移脚本 + +### 新增文件 + +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java` +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java` +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java` + +### 测试文件 + +- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTOTest.java` +- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTOTest.java` +- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/util/LoanPricingConverterTest.java` +- `test_api/test_personal_create.http` - 个人客户发起接口 HTTP 测试脚本 +- `test_api/test_corporate_create.http` - 企业客户发起接口 HTTP 测试脚本 +- `test_api/test_backward_compatibility.http` - 向后兼容性测试脚本 + +### 修改文件 + +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java` - 添加缺失字段的属性 +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java` +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java` +- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java` + +## 测试脚本示例 + +### HTTP 测试脚本格式 + +测试脚本使用 IntelliJ IDEA 的 .http 文件格式,示例如下: + +```http +### 获取测试 Token +POST http://localhost:8080/login/test +Content-Type: application/json + +{ + "username": "admin", + "password": "admin123" +} + +> {% + client.test("Request executed successfully", function() { + client.assert(response.status === 200, "Response status is 200"); + client.assert(response.body.code === 200, "Response code is 200"); + client.global.set("token", response.body.data.token); + }); +%} + +### 个人客户发起 - 成功场景 +POST http://localhost:8080/loanPricing/workflow/create/personal +Authorization: Bearer {{token}} +Content-Type: application/json + +{ + "custIsn": "TEST001", + "custName": "张三", + "idType": "身份证", + "idNum": "110101199001011234", + "guarType": "信用", + "applyAmt": "500000", + "bizProof": "true", + "loanLoop": "false" +} + +> {% + client.test("Personal loan creation successful", function() { + client.assert(response.status === 200, "Response status is 200"); + client.assert(response.body.code === 200, "Response code is 200"); + client.assert(response.body.data.custType === "个人", "Customer type is 个人"); + }); +%} + +### 企业客户发起 - 成功场景 +POST http://localhost:8080/loanPricing/workflow/create/corporate +Authorization: Bearer {{token}} +Content-Type: application/json + +{ + "custIsn": "CORP001", + "custName": "测试科技有限公司", + "idType": "统一社会信用代码", + "idNum": "91110000100000000X", + "guarType": "抵押", + "applyAmt": "1000000", + "isAgriGuar": "false", + "isGreenLoan": "true", + "isTechEnt": "true", + "loanTerm": "36" +} + +> {% + client.test("Corporate loan creation successful", function() { + client.assert(response.status === 200, "Response status is 200"); + client.assert(response.body.code === 200, "Response code is 200"); + client.assert(response.body.data.custType === "企业", "Customer type is 企业"); + }); +%} +``` diff --git a/openspec/changes/split-pricing-creation-interface/proposal.md b/openspec/changes/split-pricing-creation-interface/proposal.md new file mode 100644 index 0000000..c7647ea --- /dev/null +++ b/openspec/changes/split-pricing-creation-interface/proposal.md @@ -0,0 +1,83 @@ +# Proposal: 拆分个人和企业利率定价发起接口 + +## 概述 + +将现有的统一利率定价发起接口 (`POST /loanPricing/workflow/create`) 拆分为两个独立的接口: + +- 个人客户发起接口 (`POST /loanPricing/workflow/create/personal`) +- 企业客户发起接口 (`POST /loanPricing/workflow/create/corporate`) + +## 背景 + +当前系统中,`LoanPricingWorkflow` 实体包含了个人和企业客户的所有字段。当发起流程时,根据客户类型(custType)的不同,需要填写的字段存在差异: + +- **个人客户**:需要填写个人特有字段(如是否有经营佐证、循环功能等) +- **企业客户**:需要填写企业特有字段(如贸易和建筑业企业标识、省农担担保贷款、绿色贷款、科技型企业、贷款期限等) + +将接口拆分可以带来以下好处: + +1. **接口契约更清晰**:每个接口只包含对应客户类型的字段 +2. **验证更精确**:可以在 DTO 层面进行字段验证 +3. **文档更友好**:API 文档可以分别展示个人和企业的字段 +4. **维护性更好**:字段变更不会影响另一类型的客户 + +## 影响范围 + +### 后端变更 + +- 创建新的 DTO 类:`PersonalLoanPricingCreateDTO` 和 `CorporateLoanPricingCreateDTO` +- 在 `LoanPricingWorkflowController` 中添加两个新接口 +- 修改 `ILoanPricingWorkflowService` 接口,添加两个新的创建方法 +- 实现 `LoanPricingWorkflowServiceImpl` 中的新方法 +- 保留原有接口以保持向后兼容(可选,建议标记为 Deprecated) + +### 前端变更 + +> **注:本次变更仅涉及后端,前端暂不修改** + +### 数据库变更 + +需要向 `loan_pricing_workflow` 表添加以下字段: + +| 字段名 | 类型 | 说明 | 适用客户 | +|-----------------------|--------------|------------------------|-------| +| id_num | varchar(100) | 证件号码 | 个人、企业 | +| loan_loop | varchar(10) | 循环功能 | 个人 | +| is_trade_construction | varchar(10) | 贸易和建筑业企业标识(抵质押类上调20BP) | 企业 | +| is_green_loan | varchar(10) | 绿色贷款(最多下降5BP) | 企业 | +| is_tech_ent | varchar(10) | 科技型企业(最多下降5BP) | 企业 | +| loan_term | varchar(50) | 贷款期限 | 企业 | + +**迁移脚本位置**: `sql/add_missing_fields.sql` + +同时需要更新 `LoanPricingWorkflow` Entity 类,添加对应的属性和字段映射注解。 + +## 设计方案 + +详见 `design.md` + +## 风险和考虑 + +1. **向后兼容性**:原有接口 `POST /loanPricing/workflow/create` 继续保留 + - 原有接口不做标记为 Deprecated 的处理 + - 新旧接口共存,供前端自由选择使用 + +2. **数据迁移**:需要执行数据库迁移脚本添加新字段,但不涉及现有数据的迁移 + +3. **测试覆盖**:需要为新接口编写测试用例 + +## 依赖关系 + +- **数据库迁移必须最先执行**:所有后端开发依赖于新字段添加完成 +- 依赖现有的 `LoanPricingWorkflow` 实体 +- 依赖现有的 `ILoanPricingWorkflowService` 服务层 + +## 验收标准 + +1. **数据库变更**:所有新字段成功添加到数据库表,且可以正确存储和检索数据 +2. **Entity 类更新**:`LoanPricingWorkflow` 实体类包含所有新增字段的属性和映射 +3. **个人客户接口**:个人客户发起接口只接受个人相关的字段 +4. **企业客户接口**:企业客户发起接口只接受企业相关的字段 +5. **接口功能**:两个接口都能成功创建利率定价流程记录,包括新增字段的保存 +6. **字段验证**:字段验证正确生效 +7. **API 文档**:API 文档正确显示两个接口的差异 diff --git a/openspec/changes/split-pricing-creation-interface/specs/corporate-loan-pricing-creation/spec.md b/openspec/changes/split-pricing-creation-interface/specs/corporate-loan-pricing-creation/spec.md new file mode 100644 index 0000000..f9c65a4 --- /dev/null +++ b/openspec/changes/split-pricing-creation-interface/specs/corporate-loan-pricing-creation/spec.md @@ -0,0 +1,105 @@ +# 企业利率定价流程发起 Capability Spec + +## ADDED Requirements + +### Requirement: 企业客户利率定价流程发起 + +系统 SHALL 提供企业客户专用的利率定价流程发起接口 (`POST /loanPricing/workflow/create/corporate`),该接口只接受企业客户相关的字段。 + +#### Scenario: 成功发起企业客户利率定价流程 + +- **WHEN** 业务人员通过企业客户发起接口提交包含必填字段(custIsn、guarType、applyAmt)的完整申请 +- **THEN** 系统自动生成业务方流水号(serialNum)并保存记录,custType 固定为"企业",返回成功响应 + +#### Scenario: 字段验证-必填字段 + +- **WHEN** 提交的企业客户申请缺少必填字段(custIsn、guarType、applyAmt) +- **THEN** 系统返回参数验证失败的错误信息 + +#### Scenario: 字段验证-担保方式枚举值 + +- **WHEN** 提交的企业客户申请中 guarType 不是"信用"、"保证"、"抵押"、"质押"之一 +- **THEN** 系统返回参数验证失败的错误信息 + +#### Scenario: 记录企业特有字段 + +- **WHEN** 企业客户申请中包含 isAgriGuar(省农担担保贷款)、isGreenLoan(绿色贷款)、isTechEnt(科技型企业)或 loanTerm(贷款期限)字段 +- **THEN** 系统正确保存这些字段的值 + +#### Scenario: 自动设置客户类型 + +- **WHEN** 通过企业客户发起接口创建流程 +- **THEN** 系统自动将 custType 设置为"企业",无需客户端传入 + +#### Scenario: 自动生成业务方流水号 + +- **WHEN** 发起企业客户利率定价流程时 +- **THEN** 系统使用时间戳自动生成唯一的业务方流水号 + +#### Scenario: 记录创建和更新信息 + +- **WHEN** 企业客户利率定价流程创建成功 +- **THEN** 系统自动记录创建者、创建时间、更新者、更新时间 + +### Requirement: 企业客户发起接口字段定义 + +企业客户发起接口 SHALL 接受以下字段: + +#### Scenario: 基本信息字段 + +- **WHEN** 客户端提交企业客户发起请求 +- **THEN** 系统接受以下基本信息字段: + - `custIsn`(必填):客户内码 + - `custName`:客户名称 + - `idType`:证件类型 + - `idNum`:证件号码 + +#### Scenario: 贷款信息字段 + +- **WHEN** 客户端提交企业客户发起请求 +- **THEN** 系统接受以下贷款信息字段: + - `guarType`(必填):担保方式,可选值"信用"、"保证"、"抵押"、"质押" + - `applyAmt`(必填):申请金额,单位:元 + - `loanTerm`:贷款期限 + +#### Scenario: 企业特有字段-优惠条件 + +- **WHEN** 客户端提交企业客户发起请求 +- **THEN** 系统接受以下企业特有优惠条件字段: + - `isAgriGuar`:省农担担保贷款(省农担担保贷款下调40个BP) + - `isGreenLoan`:绿色贷款(绿色贷款或科技型企业最多下降5BP) + - `isTechEnt`:科技型企业(绿色贷款或科技型企业最多下降5BP) + +#### Scenario: 贸易和建筑业企业标识 + +- **WHEN** 企业客户申请中担保方式为抵(质)押类,且企业为贸易和建筑业企业 +- **THEN** 系统记录该标识,用于后续利率测算时上调20BP + +#### Scenario: 抵质押信息字段 + +- **WHEN** 客户端提交企业客户发起请求 +- **THEN** 系统接受以下抵质押信息字段: + - `collType`:抵质押类型 + - `collThirdParty`:抵质押物是否三方所有 + +## MODIFIED Requirements + +### Requirement: 利率定价流程发起接口弃用策略 + +原有的统一发起接口 (`POST /loanPricing/workflow/create`) SHALL 标记为 Deprecated,系统 SHALL +继续支持该接口以保证向后兼容,同时引导使用新的个人或企业专用接口。 + +#### Scenario: 原有接口向后兼容 + +- **WHEN** 客户端继续使用原有发起接口 +- **THEN** 系统继续处理请求并返回正确结果,但建议迁移到新接口 + +#### Scenario: 原有接口标记为已弃用 + +- **WHEN** 开发人员查看 API 文档 +- **THEN** 原有接口标记为 Deprecated,引导使用新的个人或企业专用接口 + +## Cross-References + +- 相关 Capability: `personal-loan-pricing-creation`(个人客户利率定价流程发起) +- 修改自 Capability: `loan-pricing-workflow` 中的"利率定价流程发起"需求 diff --git a/openspec/changes/split-pricing-creation-interface/specs/personal-loan-pricing-creation/spec.md b/openspec/changes/split-pricing-creation-interface/specs/personal-loan-pricing-creation/spec.md new file mode 100644 index 0000000..113748c --- /dev/null +++ b/openspec/changes/split-pricing-creation-interface/specs/personal-loan-pricing-creation/spec.md @@ -0,0 +1,98 @@ +# 个人利率定价流程发起 Capability Spec + +## ADDED Requirements + +### Requirement: 个人客户利率定价流程发起 + +系统 SHALL 提供个人客户专用的利率定价流程发起接口 (`POST /loanPricing/workflow/create/personal`),该接口只接受个人客户相关的字段。 + +#### Scenario: 成功发起个人客户利率定价流程 + +- **WHEN** 业务人员通过个人客户发起接口提交包含必填字段(custIsn、guarType、applyAmt)的完整申请 +- **THEN** 系统自动生成业务方流水号(serialNum)并保存记录,custType 固定为"个人",返回成功响应 + +#### Scenario: 字段验证-必填字段 + +- **WHEN** 提交的个人客户申请缺少必填字段(custIsn、guarType、applyAmt) +- **THEN** 系统返回参数验证失败的错误信息 + +#### Scenario: 字段验证-担保方式枚举值 + +- **WHEN** 提交的个人客户申请中 guarType 不是"信用"、"保证"、"抵押"、"质押"之一 +- **THEN** 系统返回参数验证失败的错误信息 + +#### Scenario: 记录个人特有字段 + +- **WHEN** 个人客户申请中包含 bizProof(是否有经营佐证)或 loanLoop(循环功能)字段 +- **THEN** 系统正确保存这些字段的值 + +#### Scenario: 自动设置客户类型 + +- **WHEN** 通过个人客户发起接口创建流程 +- **THEN** 系统自动将 custType 设置为"个人",无需客户端传入 + +#### Scenario: 自动生成业务方流水号 + +- **WHEN** 发起个人客户利率定价流程时 +- **THEN** 系统使用时间戳自动生成唯一的业务方流水号 + +#### Scenario: 记录创建和更新信息 + +- **WHEN** 个人客户利率定价流程创建成功 +- **THEN** 系统自动记录创建者、创建时间、更新者、更新时间 + +### Requirement: 个人客户发起接口字段定义 + +个人客户发起接口 SHALL 接受以下字段: + +#### Scenario: 基本信息字段 + +- **WHEN** 客户端提交个人客户发起请求 +- **THEN** 系统接受以下基本信息字段: + - `custIsn`(必填):客户内码 + - `custName`:客户名称 + - `idType`:证件类型 + - `idNum`:证件号码 + +#### Scenario: 贷款信息字段 + +- **WHEN** 客户端提交个人客户发起请求 +- **THEN** 系统接受以下贷款信息字段: + - `guarType`(必填):担保方式,可选值"信用"、"保证"、"抵押"、"质押" + - `applyAmt`(必填):申请金额,单位:元 + +#### Scenario: 个人特有字段 + +- **WHEN** 客户端提交个人客户发起请求 +- **THEN** 系统接受以下个人特有字段: + - `bizProof`:是否有经营佐证(个人经营性贷款提供的经营佐证包括:借款人或其配偶为法定代表人、实际经营者、股东的企业(个体工商户)营业执照或企查查、企信宝查档资料) + - `loanLoop`:贷款合同是否开通循环功能 + +#### Scenario: 抵质押信息字段 + +- **WHEN** 客户端提交个人客户发起请求 +- **THEN** 系统接受以下抵质押信息字段: + - `collType`:抵质押类型 + - `collThirdParty`:抵质押物是否三方所有 + +## MODIFIED Requirements + +### Requirement: 利率定价流程发起接口弃用策略 + +原有的统一发起接口 (`POST /loanPricing/workflow/create`) SHALL 标记为 Deprecated,系统 SHALL +继续支持该接口以保证向后兼容,同时引导使用新的个人或企业专用接口。 + +#### Scenario: 原有接口向后兼容 + +- **WHEN** 客户端继续使用原有发起接口 +- **THEN** 系统继续处理请求并返回正确结果,但建议迁移到新接口 + +#### Scenario: 原有接口标记为已弃用 + +- **WHEN** 开发人员查看 API 文档 +- **THEN** 原有接口标记为 Deprecated,引导使用新的个人或企业专用接口 + +## Cross-References + +- 相关 Capability: `corporate-loan-pricing-creation`(企业客户利率定价流程发起) +- 修改自 Capability: `loan-pricing-workflow` 中的"利率定价流程发起"需求 diff --git a/openspec/changes/split-pricing-creation-interface/tasks.md b/openspec/changes/split-pricing-creation-interface/tasks.md new file mode 100644 index 0000000..dea19e3 --- /dev/null +++ b/openspec/changes/split-pricing-creation-interface/tasks.md @@ -0,0 +1,149 @@ +# Tasks: 拆分个人和企业利率定价发起接口 + +## 数据库变更任务 + +### 0. 数据库表结构更新 + +- [x] 执行数据库迁移脚本,添加缺失字段: + - `id_num` varchar(100) - 证件号码(个人和企业都需要) + - `loan_loop` varchar(10) - 循环功能(个人客户专用) + - `is_trade_construction` varchar(10) - 贸易和建筑业企业标识(企业客户专用) + - `is_green_loan` varchar(10) - 绿色贷款(企业客户专用) + - `is_tech_ent` varchar(10) - 科技型企业(企业客户专用) + - `loan_term` varchar(50) - 贷款期限(企业客户专用) +- [x] 更新 `LoanPricingWorkflow` Entity 类,添加对应的属性和字段映射注解 +- [ ] 验证数据库变更是否成功执行(需手动执行 SQL 脚本) + +### 0.1 创建数据库迁移脚本 + +- [x] 在 `sql/` 目录下创建 `add_missing_fields.sql` 文件 +- [x] 包含所有 ALTER TABLE 语句 +- [x] 添加详细的注释说明每个字段的用途 + +## 后端实现任务 + +### 1. 创建 DTO 类 + +- [x] 创建 `PersonalLoanPricingCreateDTO.java` + - 添加共同字段:custIsn、custName、idType、idNum、guarType、applyAmt、collType、collThirdParty + - 添加个人客户特有字段:bizProof(是否有经营佐证)、loanLoop(循环功能) + - 添加共同字段验证注解:custIsn、guarType、applyAmt 为必填 + - 添加担保方式枚举验证 +- [x] 创建 `CorporateLoanPricingCreateDTO.java` + - 添加共同字段:custIsn、custName、idType、idNum、guarType、applyAmt、collType、collThirdParty + - 添加企业客户特有字段:isAgriGuar(省农担担保贷款)、isGreenLoan(绿色贷款)、isTechEnt(科技型企业)、isTradeConstruction(贸易和建筑业企业)、loanTerm(贷款期限) + - 添加共同字段验证注解:custIsn、guarType、applyAmt 为必填 + - 添加担保方式枚举验证 + +### 2. 更新 Entity 类 + +- [x] 在 `LoanPricingWorkflow.java` 中添加缺失的字段属性: + - `idNum` - 证件号码 + - `loanLoop` - 循环功能 + - `isTradeConstruction` - 贸易和建筑业企业标识 + - `isGreenLoan` - 绿色贷款 + - `isTechEnt` - 科技型企业 + - `loanTerm` - 贷款期限 +- [x] 为新字段添加 MyBatis Plus 字段映射注解(如果需要) +- [ ] 验证 Entity 类与数据库表字段映射正确(需执行 SQL 后验证) + +### 3. 创建转换器工具类 + +- [x] 创建 `LoanPricingConverter.java` + - 实现 `toEntity(PersonalLoanPricingCreateDTO)` 方法 + - 实现 `toEntity(CorporateLoanPricingCreateDTO)` 方法 + - 确保自动设置 custType 为"个人"或"企业" + - 正确映射所有字段,包括新增的 idNum、loanLoop、isTradeConstruction、isGreenLoan、isTechEnt、loanTerm + +### 4. 修改 Service 层 + +- [x] 在 `ILoanPricingWorkflowService` 接口中添加: + - `createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto)` 方法声明 + - `createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto)` 方法声明 +- [x] 在 `LoanPricingWorkflowServiceImpl` 中实现新方法: + - 实现 `createPersonalLoanPricing` 方法,调用转换器后复用现有逻辑 + - 实现 `createCorporateLoanPricing` 方法,调用转换器后复用现有逻辑 + +### 5. 修改 Controller 层 + +- [x] 在 `LoanPricingWorkflowController` 中添加: + - `POST /loanPricing/workflow/create/personal` 接口 + - `POST /loanPricing/workflow/create/corporate` 接口 +- [x] 添加 Swagger 注解,明确标注接口用途和字段说明 +- [x] 保持原有接口不变,不做 @Deprecated 标记 + +### 6. 单元测试 + +- [ ] 创建 `PersonalLoanPricingCreateDTOTest.java` 测试类 + - 测试必填字段验证(custIsn、guarType、applyAmt) + - 测试担保方式枚举验证(信用/保证/抵押/质押) + - 测试个人特有字段(bizProof、loanLoop) +- [ ] 创建 `CorporateLoanPricingCreateDTOTest.java` 测试类 + - 测试必填字段验证(custIsn、guarType、applyAmt) + - 测试担保方式枚举验证(信用/保证/抵押/质押) + - 测试企业特有字段(isAgriGuar、isGreenLoan、isTechEnt、isTradeConstruction、loanTerm) +- [ ] 创建 `LoanPricingConverterTest.java` 测试类 + - 测试个人 DTO 转 Entity 映射完整性 + - 测试企业 DTO 转 Entity 映射完整性 + - 验证 custType 自动设置正确 + +### 7. 集成测试与测试脚本 + +- [x] 生成 HTTP 测试脚本 `test_personal_create.http` + - 测试个人客户发起成功场景(完整必填字段) + - 测试缺少必填字段的失败场景 + - 测试担保方式枚举验证失败场景 + - 使用 `/login/test` 接口获取测试 token +- [x] 生成 HTTP 测试脚本 `test_corporate_create.http` + - 测试企业客户发起成功场景(完整必填字段) + - 测试缺少必填字段的失败场景 + - 测试担保方式枚举验证失败场景 + - 测试企业特有字段(isAgriGuar、isGreenLoan、isTechEnt、loanTerm) +- [x] 生成 HTTP 测试脚本 `test_backward_compatibility.http` + - 验证原有 `POST /loanPricing/workflow/create` 接口仍可正常工作 +- [x] 生成 Shell 测试脚本 `test_personal_create.sh` + - 将 HTTP 测试脚本转换为 Shell 脚本格式 + - 使用 curl 命令进行接口调用 + - 包含颜色输出和测试结果统计 +- [x] 生成 Shell 测试脚本 `test_corporate_create.sh` + - 将 HTTP 测试脚本转换为 Shell 脚本格式 + - 使用 curl 命令进行接口调用 + - 包含颜色输出和测试结果统计 +- [x] 生成 Shell 测试脚本 `test_backward_compatibility.sh` + - 将 HTTP 测试脚本转换为 Shell 脚本格式 + - 使用 curl 命令进行接口调用 + - 包含颜色输出和测试结果统计 +- [ ] 执行所有测试脚本并验证结果 +- [ ] 生成测试报告到 `doc/` 目录 + +## 文档和部署 + +### 8. API 文档 + +- [ ] 更新 Swagger 文档,添加两个新接口的完整说明 +- [ ] 生成并导出 API 文档到项目 doc 目录 + +### 9. 代码审查和合并 + +- [ ] 提交 Pull Request +- [ ] 通过代码审查 +- [ ] 合并到主分支 + +## 依赖关系 + +- **数据库变更(任务0)必须最先执行**:所有后端开发依赖于数据库字段完成 +- 任务 1-5 可以并行开发(依赖任务0完成) +- 任务 6-7 依赖任务 1-5 完成 +- 任务 8-9 依赖所有前序任务完成 + +> **注:本次变更仅涉及后端,前端暂不修改** + +## 验证检查点 + +1. **数据库字段完整性**:确保所有新增字段(idNum、loanLoop、isTradeConstruction、isGreenLoan、isTechEnt、loanTerm)已添加到数据库表 +2. **Entity 类映射正确性**:确保 Entity 类字段与数据库表字段一一对应 +3. **DTO 验证**:确保所有必填字段有 `@NotBlank` 注解,枚举字段有正确的验证 +4. **转换器正确性**:确保 DTO 到 Entity 的转换不丢失字段,包括新增字段 +5. **API 路由**:确保新接口路径正确且可访问 +6. **向后兼容**:确保原有接口继续工作 +7. **API 文档**:确保 Swagger 文档正确显示所有接口的参数说明 diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java index bc49a9e..c795fd2 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java @@ -9,6 +9,8 @@ import com.ruoyi.common.core.page.PageDomain; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableSupport; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.loanpricing.domain.dto.CorporateLoanPricingCreateDTO; +import com.ruoyi.loanpricing.domain.dto.PersonalLoanPricingCreateDTO; import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO; import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService; @@ -36,14 +38,25 @@ public class LoanPricingWorkflowController extends BaseController private ILoanPricingWorkflowService loanPricingWorkflowService; /** - * 发起利率定价流程 + * 发起个人客户利率定价流程 */ - @Operation(summary = "发起利率定价流程") - @Log(title = "利率定价流程", businessType = BusinessType.INSERT) - @PostMapping("/create") - public AjaxResult create(@Validated @RequestBody LoanPricingWorkflow loanPricingWorkflow) + @Operation(summary = "发起个人客户利率定价流程", description = "用于个人客户的利率定价流程发起") + @Log(title = "个人客户利率定价流程", businessType = BusinessType.INSERT) + @PostMapping("/create/personal") + public AjaxResult createPersonal(@Validated @RequestBody PersonalLoanPricingCreateDTO dto) { + LoanPricingWorkflow result = loanPricingWorkflowService.createPersonalLoanPricing(dto); + return success(result); + } + + /** + * 发起企业客户利率定价流程 + */ + @Operation(summary = "发起企业客户利率定价流程", description = "用于企业客户的利率定价流程发起") + @Log(title = "企业客户利率定价流程", businessType = BusinessType.INSERT) + @PostMapping("/create/corporate") + public AjaxResult createCorporate(@Validated @RequestBody CorporateLoanPricingCreateDTO dto) { - LoanPricingWorkflow result = loanPricingWorkflowService.createLoanPricing(loanPricingWorkflow); + LoanPricingWorkflow result = loanPricingWorkflowService.createCorporateLoanPricing(dto); return success(result); } diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java new file mode 100644 index 0000000..875b8e0 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java @@ -0,0 +1,64 @@ +package com.ruoyi.loanpricing.domain.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.Data; + +import java.io.Serializable; + +/** + * 企业客户利率定价发起DTO + * + * @author ruoyi + * @date 2025-01-19 + */ +@Data +@Schema(description = "企业客户利率定价发起请求") +public class CorporateLoanPricingCreateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "客户内码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CORP001") + @NotBlank(message = "客户内码不能为空") + private String custIsn; + + @Schema(description = "客户名称", example = "测试科技有限公司") + private String custName; + + @Schema(description = "证件类型", example = "统一社会信用代码") + private String idType; + + @Schema(description = "证件号码", example = "91110000100000000X") + private String idNum; + + @Schema(description = "担保方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "抵押", allowableValues = {"信用", "保证", "抵押", "质押"}) + @NotBlank(message = "担保方式不能为空") + @Pattern(regexp = "^(信用|保证|抵押|质押)$", message = "担保方式必须是:信用、保证、抵押、质押之一") + private String guarType; + + @Schema(description = "申请金额(元)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000") + @NotBlank(message = "申请金额不能为空") + private String applyAmt; + + @Schema(description = "贷款期限", example = "36") + private String loanTerm; + + @Schema(description = "省农担担保贷款", example = "false") + private String isAgriGuar; + + @Schema(description = "绿色贷款", example = "true") + private String isGreenLoan; + + @Schema(description = "科技型企业", example = "true") + private String isTechEnt; + + @Schema(description = "贸易和建筑业企业标识", example = "false") + private String isTradeConstruction; + + @Schema(description = "抵质押类型", example = "一类") + private String collType; + + @Schema(description = "抵质押物是否三方所有", example = "false") + private String collThirdParty; +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java new file mode 100644 index 0000000..fe7c1cc --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java @@ -0,0 +1,55 @@ +package com.ruoyi.loanpricing.domain.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.Data; + +import java.io.Serializable; + +/** + * 个人客户利率定价发起DTO + * + * @author ruoyi + * @date 2025-01-19 + */ +@Data +@Schema(description = "个人客户利率定价发起请求") +public class PersonalLoanPricingCreateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "客户内码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CUST001") + @NotBlank(message = "客户内码不能为空") + private String custIsn; + + @Schema(description = "客户名称", example = "张三") + private String custName; + + @Schema(description = "证件类型", example = "身份证") + private String idType; + + @Schema(description = "证件号码", example = "110101199001011234") + private String idNum; + + @Schema(description = "担保方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "信用", allowableValues = {"信用", "保证", "抵押", "质押"}) + @NotBlank(message = "担保方式不能为空") + @Pattern(regexp = "^(信用|保证|抵押|质押)$", message = "担保方式必须是:信用、保证、抵押、质押之一") + private String guarType; + + @Schema(description = "申请金额(元)", requiredMode = Schema.RequiredMode.REQUIRED, example = "500000") + @NotBlank(message = "申请金额不能为空") + private String applyAmt; + + @Schema(description = "是否有经营佐证", example = "true") + private String bizProof; + + @Schema(description = "循环功能", example = "false") + private String loanLoop; + + @Schema(description = "抵质押类型", example = "一类") + private String collType; + + @Schema(description = "抵质押物是否三方所有", example = "false") + private String collThirdParty; +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java index 2694532..8046e3c 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java @@ -64,6 +64,11 @@ public class LoanPricingWorkflow implements Serializable @NotBlank(message = "申请金额不能为空") private String applyAmt; + /** + * 贷款期限 + */ + private String loanTerm; + /** 净身企业: true/false */ private String isCleanEnt; @@ -76,6 +81,21 @@ public class LoanPricingWorkflow implements Serializable /** 省农担担保贷款: true/false */ private String isAgriGuar; + /** + * 贸易和建筑业企业标识: true/false + */ + private String isTradeConstruction; + + /** + * 绿色贷款: true/false + */ + private String isGreenLoan; + + /** + * 科技型企业: true/false + */ + private String isTechEnt; + /** 是否纳税信用等级A级: true/false */ private String isTaxA; @@ -88,6 +108,9 @@ public class LoanPricingWorkflow implements Serializable /** 是否有经营佐证: true/false */ private String bizProof; + /** 循环功能: true/false */ + private String loanLoop; + /** 抵质押类型: 一线/一类/二类 */ private String collType; @@ -95,7 +118,6 @@ public class LoanPricingWorkflow implements Serializable private String collThirdParty; /** 贷款利率 */ - @NotBlank(message = "贷款利率不能为空") private String loanRate; /** @@ -106,9 +128,14 @@ public class LoanPricingWorkflow implements Serializable /** 客户名称 */ private String custName; - /** 证件类型 */ + /** + * 证件类型 + */ private String idType; + /** 证件号码 */ + private String idNum; + /** 是否普惠小微借款人: true/false */ private String isInclusiveFinance; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java index d5114a5..693e3a0 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java @@ -2,6 +2,8 @@ package com.ruoyi.loanpricing.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.loanpricing.domain.dto.CorporateLoanPricingCreateDTO; +import com.ruoyi.loanpricing.domain.dto.PersonalLoanPricingCreateDTO; import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO; @@ -16,12 +18,20 @@ import java.util.List; public interface ILoanPricingWorkflowService { /** - * 发起利率定价流程 + * 发起个人客户利率定价流程 * - * @param loanPricingWorkflow 利率定价流程信息 + * @param dto 个人客户发起DTO * @return 结果 */ - public LoanPricingWorkflow createLoanPricing(LoanPricingWorkflow loanPricingWorkflow); + public LoanPricingWorkflow createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto); + + /** + * 发起企业客户利率定价流程 + * + * @param dto 企业客户发起DTO + * @return 结果 + */ + public LoanPricingWorkflow createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto); /** * 查询利率定价流程列表 diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java index 75f02ff..a2635db 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java @@ -3,6 +3,8 @@ package com.ruoyi.loanpricing.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.loanpricing.domain.dto.CorporateLoanPricingCreateDTO; +import com.ruoyi.loanpricing.domain.dto.PersonalLoanPricingCreateDTO; import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; import com.ruoyi.loanpricing.domain.entity.ModelCorpOutputFields; import com.ruoyi.loanpricing.domain.entity.ModelRetailOutputFields; @@ -12,6 +14,7 @@ import com.ruoyi.loanpricing.mapper.ModelCorpOutputFieldsMapper; import com.ruoyi.loanpricing.mapper.ModelRetailOutputFieldsMapper; import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService; import com.ruoyi.loanpricing.service.LoanPricingModelService; +import com.ruoyi.loanpricing.util.LoanPricingConverter; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,7 +53,6 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi * @param loanPricingWorkflow 利率定价流程信息 * @return 结果 */ - @Override @Transactional(rollbackFor = Exception.class) public LoanPricingWorkflow createLoanPricing(LoanPricingWorkflow loanPricingWorkflow) { @@ -75,6 +77,32 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi return loanPricingWorkflow; } + /** + * 发起个人客户利率定价流程 + * + * @param dto 个人客户发起DTO + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public LoanPricingWorkflow createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = LoanPricingConverter.toEntity(dto); + return createLoanPricing(entity); + } + + /** + * 发起企业客户利率定价流程 + * + * @param dto 企业客户发起DTO + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public LoanPricingWorkflow createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = LoanPricingConverter.toEntity(dto); + return createLoanPricing(entity); + } + /** * 查询利率定价流程列表 * diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java new file mode 100644 index 0000000..a59b06a --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java @@ -0,0 +1,65 @@ +package com.ruoyi.loanpricing.util; + +import com.ruoyi.loanpricing.domain.dto.CorporateLoanPricingCreateDTO; +import com.ruoyi.loanpricing.domain.dto.PersonalLoanPricingCreateDTO; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; + +/** + * 利率定价转换器 + * + * @author ruoyi + * @date 2025-01-19 + */ +public class LoanPricingConverter { + + /** + * 个人客户DTO转Entity + * + * @param dto 个人客户发起DTO + * @return 利率定价流程实体 + */ + public static LoanPricingWorkflow toEntity(PersonalLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = new LoanPricingWorkflow(); + // 映射共同字段 + entity.setCustIsn(dto.getCustIsn()); + entity.setCustType("个人"); + entity.setCustName(dto.getCustName()); + entity.setIdType(dto.getIdType()); + entity.setIdNum(dto.getIdNum()); + entity.setGuarType(dto.getGuarType()); + entity.setApplyAmt(dto.getApplyAmt()); + entity.setCollType(dto.getCollType()); + entity.setCollThirdParty(dto.getCollThirdParty()); + // 映射个人特有字段 + entity.setBizProof(dto.getBizProof()); + entity.setLoanLoop(dto.getLoanLoop()); + return entity; + } + + /** + * 企业客户DTO转Entity + * + * @param dto 企业客户发起DTO + * @return 利率定价流程实体 + */ + public static LoanPricingWorkflow toEntity(CorporateLoanPricingCreateDTO dto) { + LoanPricingWorkflow entity = new LoanPricingWorkflow(); + // 映射共同字段 + entity.setCustIsn(dto.getCustIsn()); + entity.setCustType("企业"); + entity.setCustName(dto.getCustName()); + entity.setIdType(dto.getIdType()); + entity.setIdNum(dto.getIdNum()); + entity.setGuarType(dto.getGuarType()); + entity.setApplyAmt(dto.getApplyAmt()); + entity.setCollType(dto.getCollType()); + entity.setCollThirdParty(dto.getCollThirdParty()); + // 映射企业特有字段 + entity.setIsAgriGuar(dto.getIsAgriGuar()); + entity.setIsGreenLoan(dto.getIsGreenLoan()); + entity.setIsTechEnt(dto.getIsTechEnt()); + entity.setIsTradeConstruction(dto.getIsTradeConstruction()); + entity.setLoanTerm(dto.getLoanTerm()); + return entity; + } +} diff --git a/ruoyi-ui/src/api/loanPricing/workflow.js b/ruoyi-ui/src/api/loanPricing/workflow.js index 1df46e4..b314a8d 100644 --- a/ruoyi-ui/src/api/loanPricing/workflow.js +++ b/ruoyi-ui/src/api/loanPricing/workflow.js @@ -17,10 +17,19 @@ export function getWorkflow(serialNum) { }) } -// 新增利率定价流程 -export function createWorkflow(data) { +// 创建个人客户利率定价流程 +export function createPersonalWorkflow(data) { return request({ - url: '/loanPricing/workflow/create', + url: '/loanPricing/workflow/create/personal', + method: 'post', + data: data + }) +} + +// 创建企业客户利率定价流程 +export function createCorporateWorkflow(data) { + return request({ + url: '/loanPricing/workflow/create/corporate', method: 'post', data: data }) diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue new file mode 100644 index 0000000..27f0224 --- /dev/null +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue @@ -0,0 +1,319 @@ + + + + + diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue new file mode 100644 index 0000000..2270879 --- /dev/null +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue @@ -0,0 +1,324 @@ + + + + + diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/CustomerTypeSelector.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/CustomerTypeSelector.vue new file mode 100644 index 0000000..98167ee --- /dev/null +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/CustomerTypeSelector.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue new file mode 100644 index 0000000..6351e7e --- /dev/null +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue @@ -0,0 +1,270 @@ + + + + + diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue new file mode 100644 index 0000000..6365313 --- /dev/null +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue @@ -0,0 +1,322 @@ + + + + + diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue deleted file mode 100644 index a5ae858..0000000 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue +++ /dev/null @@ -1,320 +0,0 @@ - - - - - diff --git a/ruoyi-ui/src/views/loanPricing/workflow/detail.vue b/ruoyi-ui/src/views/loanPricing/workflow/detail.vue index 82ddf7d..5d7bf02 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/detail.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/detail.vue @@ -6,143 +6,35 @@ 返回 - -
- -
- -
- 关键信息 -
- - {{ workflowDetail.serialNum }} - {{ workflowDetail.custName }} - {{ workflowDetail.custType }} - {{ workflowDetail.applyAmt }} 元 - - {{ getBaseLoanRate() }} % - - - {{ getTotalBp() }} - - - {{ getCalculateRate() }} % - - - -
- - - - - 确定 - -
-
-
-
-
+ + - -
- - -
- 流程详情 -
- - - - - {{ workflowDetail.orgCode }} - {{ workflowDetail.runType }} - {{ workflowDetail.custIsn }} - {{ workflowDetail.idType }} - - - - - - - {{ formatLoanPurpose(workflowDetail.loanPurpose) }} - {{ formatBoolean(workflowDetail.bizProof) }} - {{ workflowDetail.collType }} - {{ formatBoolean(workflowDetail.collThirdParty) }} - - - - - - - {{ formatBoolean(workflowDetail.midPerQuickPay) }} - {{ formatBoolean(workflowDetail.midPerEleDdc) }} - {{ formatBoolean(workflowDetail.midEntEleDdc) }} - {{ formatBoolean(workflowDetail.midEntWaterDdc) }} - - - - - - - {{ formatBoolean(workflowDetail.isCleanEnt) }} - {{ formatBoolean(workflowDetail.hasSettleAcct) }} - {{ formatBoolean(workflowDetail.isManufacturing) }} - {{ formatBoolean(workflowDetail.isAgriGuar) }} - {{ formatBoolean(workflowDetail.isTaxA) }} - {{ formatBoolean(workflowDetail.isAgriLeading) }} - {{ formatBoolean(workflowDetail.isInclusiveFinance) }} - - - - - - - {{ workflowDetail.createTime }} - {{ workflowDetail.createBy }} - {{ workflowDetail.updateTime }} - {{ workflowDetail.updateBy }} - - - -
- - - - - - -
-
+