客户类型字段更新
This commit is contained in:
854
doc/plans/2025-02-02-customer-type-based-detail-view.md
Normal file
854
doc/plans/2025-02-02-customer-type-based-detail-view.md
Normal file
@@ -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
|
||||
<template>
|
||||
<div class="personal-workflow-detail" v-loading="loading">
|
||||
<!-- 两栏布局:左侧关键信息 + 右侧(流程详情+模型输出) -->
|
||||
<div v-if="!loading && detailData" class="detail-layout">
|
||||
<!-- 左侧关键信息卡片 -->
|
||||
<div class="left-panel">
|
||||
<el-card class="summary-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title">关键信息</span>
|
||||
</div>
|
||||
<el-descriptions :column="1" direction="vertical" border>
|
||||
<el-descriptions-item label="业务方流水号">{{ detailData.serialNum }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户名称">{{ detailData.custName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户类型">{{ detailData.custType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请金额">{{ detailData.applyAmt }} 元</el-descriptions-item>
|
||||
<el-descriptions-item label="基准利率">
|
||||
<span class="rate-value">{{ getBaseLoanRate() }}</span> %
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="浮动BP">
|
||||
<span class="total-bp-value">{{ getTotalBp() }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="测算利率">
|
||||
<span class="calculate-rate">{{ getCalculateRate() }}</span> %
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="执行利率">
|
||||
<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-card>
|
||||
</div>
|
||||
|
||||
<!-- 右侧面板 -->
|
||||
<div class="right-panel">
|
||||
<!-- 流程详情卡片 -->
|
||||
<el-card class="detail-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title">流程详情</span>
|
||||
</div>
|
||||
|
||||
<!-- 基本信息组 -->
|
||||
<div class="info-section">
|
||||
<h4 class="section-title">基本信息</h4>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="机构编码">{{ detailData.orgCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="运行模式">{{ detailData.runType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户内码">{{ detailData.custIsn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="证件类型">{{ detailData.idType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="证件号码">{{ detailData.idNum }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detailData.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建者">{{ detailData.createBy }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 业务信息组 -->
|
||||
<div class="info-section">
|
||||
<h4 class="section-title">业务信息</h4>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="担保方式">{{ detailData.guarType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请金额">{{ detailData.applyAmt }} 元</el-descriptions-item>
|
||||
<el-descriptions-item label="是否有经营佐证">{{ formatBoolean(detailData.bizProof) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="循环功能">{{ formatBoolean(detailData.loanLoop) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="抵质押类型">{{ detailData.collType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="抵质押物是否三方所有">{{ formatBoolean(detailData.collThirdParty) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 模型输出卡片 -->
|
||||
<ModelOutputDisplay
|
||||
:cust-type="detailData.custType"
|
||||
:retail-output="retailOutput"
|
||||
:corp-output="null"
|
||||
/>
|
||||
|
||||
<!-- 议价池卡片 -->
|
||||
<BargainingPoolDisplay
|
||||
v-if="bargainingPool"
|
||||
:branch-pool="bargainingPool.branchPool"
|
||||
:sub-branch-pool="bargainingPool.subBranchPool"
|
||||
:private-domain-pool="bargainingPool.privateDomainPool"
|
||||
:excess-profit-share="bargainingPool.excessProfitShare"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setExecuteRate } from "@/api/loanPricing/workflow"
|
||||
import ModelOutputDisplay from "./ModelOutputDisplay.vue"
|
||||
import BargainingPoolDisplay from "./BargainingPoolDisplay.vue"
|
||||
|
||||
export default {
|
||||
name: "PersonalWorkflowDetail",
|
||||
components: {
|
||||
ModelOutputDisplay,
|
||||
BargainingPoolDisplay
|
||||
},
|
||||
props: {
|
||||
detailData: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
retailOutput: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
bargainingPool: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
executeRateInput: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'detailData.executeRate': {
|
||||
handler(newVal) {
|
||||
this.executeRateInput = newVal || ''
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 格式化布尔值为中文 */
|
||||
formatBoolean(value) {
|
||||
if (value === 'true' || value === true) return '是'
|
||||
if (value === 'false' || value === false) return '否'
|
||||
return value || '-'
|
||||
},
|
||||
/** 获取基准利率 */
|
||||
getBaseLoanRate() {
|
||||
return this.retailOutput?.baseLoanRate || '-'
|
||||
},
|
||||
/** 获取浮动BP */
|
||||
getTotalBp() {
|
||||
return this.retailOutput?.totalBp || '-'
|
||||
},
|
||||
/** 获取测算利率 */
|
||||
getCalculateRate() {
|
||||
return this.retailOutput?.calculateRate || '-'
|
||||
},
|
||||
/** 设定执行利率 */
|
||||
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
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
setExecuteRate(this.detailData.serialNum, value.toString()).then(() => {
|
||||
this.$modal.msgSuccess("执行利率设定成功")
|
||||
this.$emit('refresh')
|
||||
this.loading = false
|
||||
}).catch(error => {
|
||||
this.$modal.msgError("设定失败:" + (error.msg || error.message || "未知错误"))
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.personal-workflow-detail {
|
||||
.detail-layout {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: flex-start;
|
||||
|
||||
.left-panel {
|
||||
flex: 0 0 280px;
|
||||
max-width: 280px;
|
||||
|
||||
.summary-card {
|
||||
::v-deep .el-card__header {
|
||||
padding: 16px 20px;
|
||||
background-color: #fafafa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-card__body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.execute-rate-input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
|
||||
.execute-rate-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rate-value {
|
||||
color: #67c23a;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.total-bp-value {
|
||||
color: #e6a23c;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.calculate-rate {
|
||||
color: #f56c6c;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
.detail-card {
|
||||
::v-deep .el-card__header {
|
||||
padding: 16px 20px;
|
||||
background-color: #fafafa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-card__body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 992px) {
|
||||
.personal-workflow-detail {
|
||||
.detail-layout {
|
||||
flex-direction: column;
|
||||
|
||||
.left-panel,
|
||||
.right-panel {
|
||||
flex: 1 1 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
**Step 2: 验证组件语法正确**
|
||||
|
||||
检查: 在浏览器开发工具中确认无语法错误
|
||||
|
||||
---
|
||||
|
||||
## Task 2: 创建企业客户详情组件 CorporateWorkflowDetail.vue
|
||||
|
||||
**文件:**
|
||||
|
||||
- 创建: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue`
|
||||
|
||||
**Step 1: 创建组件基础结构**
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="corporate-workflow-detail" v-loading="loading">
|
||||
<!-- 两栏布局:左侧关键信息 + 右侧(流程详情+模型输出) -->
|
||||
<div v-if="!loading && detailData" class="detail-layout">
|
||||
<!-- 左侧关键信息卡片 -->
|
||||
<div class="left-panel">
|
||||
<el-card class="summary-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title">关键信息</span>
|
||||
</div>
|
||||
<el-descriptions :column="1" direction="vertical" border>
|
||||
<el-descriptions-item label="业务方流水号">{{ detailData.serialNum }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户名称">{{ detailData.custName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户类型">{{ detailData.custType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请金额">{{ detailData.applyAmt }} 元</el-descriptions-item>
|
||||
<el-descriptions-item label="基准利率">
|
||||
<span class="rate-value">{{ getBaseLoanRate() }}</span> %
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="浮动BP">
|
||||
<span class="total-bp-value">{{ getTotalBp() }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="测算利率">
|
||||
<span class="calculate-rate">{{ getCalculateRate() }}</span> %
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="执行利率">
|
||||
<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-card>
|
||||
</div>
|
||||
|
||||
<!-- 右侧面板 -->
|
||||
<div class="right-panel">
|
||||
<!-- 流程详情卡片 -->
|
||||
<el-card class="detail-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title">流程详情</span>
|
||||
</div>
|
||||
|
||||
<!-- 基本信息组 -->
|
||||
<div class="info-section">
|
||||
<h4 class="section-title">基本信息</h4>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="机构编码">{{ detailData.orgCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="运行模式">{{ detailData.runType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户内码">{{ detailData.custIsn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="证件类型">{{ detailData.idType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="证件号码">{{ detailData.idNum }}</el-descriptions-item>
|
||||
<el-descriptions-item label="贷款期限">{{ detailData.loanTerm || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detailData.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建者">{{ detailData.createBy }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 业务信息组 -->
|
||||
<div class="info-section">
|
||||
<h4 class="section-title">业务信息</h4>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="担保方式">{{ detailData.guarType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请金额">{{ detailData.applyAmt }} 元</el-descriptions-item>
|
||||
<el-descriptions-item label="省农担担保贷款">{{ formatBoolean(detailData.isAgriGuar) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="绿色贷款">{{ formatBoolean(detailData.isGreenLoan) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="科技型企业">{{ formatBoolean(detailData.isTechEnt) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="抵质押类型">{{ detailData.collType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="抵质押物是否三方所有">{{ formatBoolean(detailData.collThirdParty) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 模型输出卡片 -->
|
||||
<ModelOutputDisplay
|
||||
:cust-type="detailData.custType"
|
||||
:retail-output="null"
|
||||
:corp-output="corpOutput"
|
||||
/>
|
||||
|
||||
<!-- 议价池卡片 -->
|
||||
<BargainingPoolDisplay
|
||||
v-if="bargainingPool"
|
||||
:branch-pool="bargainingPool.branchPool"
|
||||
:sub-branch-pool="bargainingPool.subBranchPool"
|
||||
:private-domain-pool="bargainingPool.privateDomainPool"
|
||||
:excess-profit-share="bargainingPool.excessProfitShare"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setExecuteRate } from "@/api/loanPricing/workflow"
|
||||
import ModelOutputDisplay from "./ModelOutputDisplay.vue"
|
||||
import BargainingPoolDisplay from "./BargainingPoolDisplay.vue"
|
||||
|
||||
export default {
|
||||
name: "CorporateWorkflowDetail",
|
||||
components: {
|
||||
ModelOutputDisplay,
|
||||
BargainingPoolDisplay
|
||||
},
|
||||
props: {
|
||||
detailData: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
corpOutput: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
bargainingPool: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
executeRateInput: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'detailData.executeRate': {
|
||||
handler(newVal) {
|
||||
this.executeRateInput = newVal || ''
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 格式化布尔值为中文 */
|
||||
formatBoolean(value) {
|
||||
if (value === 'true' || value === true) return '是'
|
||||
if (value === 'false' || value === false) return '否'
|
||||
return value || '-'
|
||||
},
|
||||
/** 获取基准利率 */
|
||||
getBaseLoanRate() {
|
||||
return this.corpOutput?.baseLoanRate || '-'
|
||||
},
|
||||
/** 获取浮动BP */
|
||||
getTotalBp() {
|
||||
return this.corpOutput?.totalBp || '-'
|
||||
},
|
||||
/** 获取测算利率 */
|
||||
getCalculateRate() {
|
||||
return this.corpOutput?.calculateRate || '-'
|
||||
},
|
||||
/** 设定执行利率 */
|
||||
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
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
setExecuteRate(this.detailData.serialNum, value.toString()).then(() => {
|
||||
this.$modal.msgSuccess("执行利率设定成功")
|
||||
this.$emit('refresh')
|
||||
this.loading = false
|
||||
}).catch(error => {
|
||||
this.$modal.msgError("设定失败:" + (error.msg || error.message || "未知错误"))
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.corporate-workflow-detail {
|
||||
.detail-layout {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: flex-start;
|
||||
|
||||
.left-panel {
|
||||
flex: 0 0 280px;
|
||||
max-width: 280px;
|
||||
|
||||
.summary-card {
|
||||
::v-deep .el-card__header {
|
||||
padding: 16px 20px;
|
||||
background-color: #fafafa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-card__body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.execute-rate-input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
|
||||
.execute-rate-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rate-value {
|
||||
color: #67c23a;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.total-bp-value {
|
||||
color: #e6a23c;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.calculate-rate {
|
||||
color: #f56c6c;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
.detail-card {
|
||||
::v-deep .el-card__header {
|
||||
padding: 16px 20px;
|
||||
background-color: #fafafa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-card__body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 992px) {
|
||||
.corporate-workflow-detail {
|
||||
.detail-layout {
|
||||
flex-direction: column;
|
||||
|
||||
.left-panel,
|
||||
.right-panel {
|
||||
flex: 1 1 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
**Step 2: 验证组件语法正确**
|
||||
|
||||
检查: 在浏览器开发工具中确认无语法错误
|
||||
|
||||
---
|
||||
|
||||
## Task 3: 修改 detail.vue 为容器组件
|
||||
|
||||
**文件:**
|
||||
|
||||
- 修改: `ruoyi-ui/src/views/loanPricing/workflow/detail.vue`
|
||||
|
||||
**Step 1: 替换为容器组件结构**
|
||||
|
||||
将整个文件内容替换为:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="app-container workflow-detail-container" v-loading="loading">
|
||||
<!-- 页面头部:标题和返回按钮 -->
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">流程详情</h2>
|
||||
<el-button icon="el-icon-back" size="small" @click="goBack">返回</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 根据客户类型渲染对应的详情组件 -->
|
||||
<personal-workflow-detail
|
||||
v-if="!loading && workflowDetail && workflowDetail.custType === '个人'"
|
||||
:detail-data="workflowDetail"
|
||||
:retail-output="retailOutput"
|
||||
:bargaining-pool="bargainingPool"
|
||||
@refresh="getDetail"
|
||||
/>
|
||||
|
||||
<corporate-workflow-detail
|
||||
v-if="!loading && workflowDetail && workflowDetail.custType === '企业'"
|
||||
:detail-data="workflowDetail"
|
||||
:corp-output="corpOutput"
|
||||
:bargaining-pool="bargainingPool"
|
||||
@refresh="getDetail"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getWorkflow } from "@/api/loanPricing/workflow"
|
||||
import PersonalWorkflowDetail from "./components/PersonalWorkflowDetail.vue"
|
||||
import CorporateWorkflowDetail from "./components/CorporateWorkflowDetail.vue"
|
||||
|
||||
export default {
|
||||
name: "LoanPricingWorkflowDetail",
|
||||
components: {
|
||||
PersonalWorkflowDetail,
|
||||
CorporateWorkflowDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
workflowDetail: null,
|
||||
retailOutput: null,
|
||||
corpOutput: null,
|
||||
bargainingPool: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getDetail()
|
||||
},
|
||||
methods: {
|
||||
/** 获取流程详情 */
|
||||
getDetail() {
|
||||
const serialNum = this.$route.params.serialNum
|
||||
if (!serialNum) {
|
||||
this.$modal.msgError("缺少业务方流水号参数")
|
||||
this.goBack()
|
||||
return
|
||||
}
|
||||
|
||||
getWorkflow(serialNum).then(response => {
|
||||
this.workflowDetail = response.data.loanPricingWorkflow
|
||||
this.retailOutput = response.data.modelRetailOutputFields
|
||||
this.corpOutput = response.data.modelCorpOutputFields
|
||||
this.bargainingPool = response.data.bargainingPool
|
||||
this.loading = false
|
||||
}).catch(error => {
|
||||
this.$modal.msgError("获取流程详情失败:" + (error.message || "未知错误"))
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 返回上一页 */
|
||||
goBack() {
|
||||
this.$router.go(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.workflow-detail-container {
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 4px;
|
||||
|
||||
.page-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
**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` (修改前)
|
||||
Reference in New Issue
Block a user