调整个人最终测算利率展示并重排详情卡片

This commit is contained in:
wkc
2026-04-11 15:33:40 +08:00
parent 235672304a
commit f1e4b26800
10 changed files with 129 additions and 21 deletions

View File

@@ -0,0 +1,19 @@
# 个人流程最终测算利率展示实施记录
## 修改时间
- 2026-04-11
## 修改内容
- 调整流程列表后端查询:个人客户列表“测算利率”改为读取 `model_retail_output_fields.final_calculate_rate`
- 调整个人流程详情左侧展示:标签改为“最终测算利率”,显示字段改为 `retailOutput.finalCalculateRate`
- 调整个人流程详情后端组装:`loanPricingWorkflow.loanRate` 改为取个人模型输出的 `finalCalculateRate`
## 影响范围
- 个人流程列表
- 个人流程详情左侧关键信息
- 企业流程列表与详情保持现状,不做改动
## 验证计划
- 后端单元测试验证个人详情取 `finalCalculateRate`
- 后端静态测试验证列表 SQL 的个人分支查询 `mr.final_calculate_rate`
- 前端静态测试验证个人详情展示 `finalCalculateRate`

View File

@@ -0,0 +1,17 @@
# 流程详情卡片顺序调整实施记录
## 修改时间
- 2026-04-11
## 修改内容
- 调整个人流程详情页右侧卡片顺序,将模型输出卡片移动到流程详情卡片上方
- 调整企业流程详情页右侧卡片顺序,将模型输出卡片移动到流程详情卡片上方
- 新增前端静态校验,约束个人与企业详情组件的卡片顺序
## 影响范围
- 个人流程详情页面布局
- 企业流程详情页面布局
## 验证计划
- 执行前端静态测试,确认卡片顺序断言通过
- 启动前端页面并在浏览器中检查个人、企业详情页卡片顺序

View File

@@ -172,7 +172,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
if (Objects.nonNull(modelRetailOutputFields))
{
maskModelRetailOutputBasicInfo(modelRetailOutputFields);
loanPricingWorkflow.setLoanRate(modelRetailOutputFields.getCalculateRate());
loanPricingWorkflow.setLoanRate(modelRetailOutputFields.getFinalCalculateRate());
}
loanPricingWorkflowVO.setModelRetailOutputFields(modelRetailOutputFields);
}

View File

@@ -12,7 +12,7 @@
lpw.guar_type AS guarType,
lpw.apply_amt AS applyAmt,
CASE
WHEN lpw.cust_type = '个人' THEN mr.calculate_rate
WHEN lpw.cust_type = '个人' THEN mr.final_calculate_rate
WHEN lpw.cust_type = '企业' THEN mc.calculate_rate
ELSE NULL
END AS calculateRate,

View File

@@ -0,0 +1,22 @@
package com.ruoyi.loanpricing.mapper;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StreamUtils;
class LoanPricingWorkflowMapperXmlTest
{
@Test
void shouldUseRetailFinalCalculateRateInWorkflowListQuery() throws IOException
{
ClassPathResource resource = new ClassPathResource("mapper/loanpricing/LoanPricingWorkflowMapper.xml");
String xml = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
assertTrue(xml.contains("WHEN lpw.cust_type = '个人' THEN mr.final_calculate_rate"));
assertTrue(xml.contains("WHEN lpw.cust_type = '企业' THEN mc.calculate_rate"));
}
}

View File

@@ -134,7 +134,7 @@ class LoanPricingWorkflowServiceImplTest
}
@Test
void shouldUseRetailModelOutputCalculateRateForWorkflowDetail()
void shouldUseRetailModelOutputFinalCalculateRateForWorkflowDetail()
{
LoanPricingWorkflow workflow = new LoanPricingWorkflow();
workflow.setSerialNum("P20260328001");
@@ -144,14 +144,16 @@ class LoanPricingWorkflowServiceImplTest
ModelRetailOutputFields retailOutputFields = new ModelRetailOutputFields();
retailOutputFields.setCalculateRate("6.15");
retailOutputFields.setFinalCalculateRate("6.05");
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
when(modelRetailOutputFieldsMapper.selectById(11L)).thenReturn(retailOutputFields);
LoanPricingWorkflowVO result = loanPricingWorkflowService.selectLoanPricingBySerialNum("P20260328001");
assertEquals("6.15", result.getLoanPricingWorkflow().getLoanRate());
assertEquals("6.05", result.getLoanPricingWorkflow().getLoanRate());
assertEquals("6.15", result.getModelRetailOutputFields().getCalculateRate());
assertEquals("6.05", result.getModelRetailOutputFields().getFinalCalculateRate());
}
@Test

View File

@@ -46,6 +46,13 @@
<!-- 右侧面板 -->
<div class="right-panel">
<!-- 模型输出卡片 -->
<ModelOutputDisplay
:cust-type="detailData.custType"
:retail-output="null"
:corp-output="corpOutput"
/>
<!-- 流程详情卡片 -->
<el-card class="detail-card">
<div slot="header" class="card-header">
@@ -88,13 +95,6 @@
</div>
</el-card>
<!-- 模型输出卡片 -->
<ModelOutputDisplay
:cust-type="detailData.custType"
:retail-output="null"
:corp-output="corpOutput"
/>
<!-- 议价池卡片 -->
<BargainingPoolDisplay
v-if="bargainingPool"

View File

@@ -19,7 +19,7 @@
<el-descriptions-item label="浮动BP">
<span class="total-bp-value">{{ getTotalBp() }}</span>
</el-descriptions-item>
<el-descriptions-item label="测算利率">
<el-descriptions-item label="最终测算利率">
<span class="calculate-rate">{{ getCalculateRate() }}</span> %
</el-descriptions-item>
<el-descriptions-item label="执行利率">
@@ -46,6 +46,13 @@
<!-- 右侧面板 -->
<div class="right-panel">
<!-- 模型输出卡片 -->
<ModelOutputDisplay
:cust-type="detailData.custType"
:retail-output="retailOutput"
:corp-output="null"
/>
<!-- 流程详情卡片 -->
<el-card class="detail-card">
<div slot="header" class="card-header">
@@ -88,13 +95,6 @@
</div>
</el-card>
<!-- 模型输出卡片 -->
<ModelOutputDisplay
:cust-type="detailData.custType"
:retail-output="retailOutput"
:corp-output="null"
/>
<!-- 议价池卡片 -->
<BargainingPoolDisplay
v-if="bargainingPool"
@@ -168,9 +168,9 @@ export default {
getTotalBp() {
return this.retailOutput?.totalBp || '-'
},
/** 获取测算利率 */
/** 获取最终测算利率 */
getCalculateRate() {
return this.retailOutput?.calculateRate || '-'
return this.retailOutput?.finalCalculateRate || '-'
},
/** 设定执行利率 */
handleSetExecuteRate() {

View File

@@ -0,0 +1,21 @@
const fs = require('fs')
const path = require('path')
const assert = require('assert')
function read(relativePath) {
return fs.readFileSync(path.join(__dirname, '..', relativePath), 'utf8')
}
const personalDetail = read('src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue')
assert(
/label="最终测算利率"/.test(personalDetail),
'个人流程详情左侧缺少“最终测算利率”标签'
)
assert(
/return this\.retailOutput\?\.finalCalculateRate \|\| '-'/.test(personalDetail),
'个人流程详情没有使用 finalCalculateRate 展示最终测算利率'
)
console.log('personal final calculate rate display assertions passed')

View File

@@ -0,0 +1,27 @@
const fs = require('fs')
const path = require('path')
const assert = require('assert')
function read(relativePath) {
return fs.readFileSync(path.join(__dirname, '..', relativePath), 'utf8')
}
function assertModelOutputBeforeDetailCard(source, label) {
const modelOutputIndex = source.indexOf('<ModelOutputDisplay')
const detailCardIndex = source.indexOf('<el-card class="detail-card">')
assert(modelOutputIndex !== -1, `${label} 缺少模型输出卡片`)
assert(detailCardIndex !== -1, `${label} 缺少流程详情卡片`)
assert(
modelOutputIndex < detailCardIndex,
`${label} 的模型输出卡片应位于流程详情卡片上方`
)
}
const personalDetail = read('src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue')
const corporateDetail = read('src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue')
assertModelOutputBeforeDetailCard(personalDetail, '个人流程详情')
assertModelOutputBeforeDetailCard(corporateDetail, '企业流程详情')
console.log('workflow detail card order assertions passed')