Files
loan-pricing/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue

335 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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">
<!-- 模型输出卡片 -->
<ModelOutputDisplay
:cust-type="detailData.custType"
:retail-output="retailOutput"
:corp-output="null"
/>
<!-- 流程详情卡片 -->
<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="贷款用途">{{ formatLoanPurpose(detailData.loanPurpose) }}</el-descriptions-item>
<el-descriptions-item label="业务种类">{{ detailData.businessType || '-' }}</el-descriptions-item>
<el-descriptions-item label="历史贷款利率">{{ formatRate(detailData.loanRateHistory) }}</el-descriptions-item>
<el-descriptions-item label="借款期限">{{ detailData.loanTerm || '-' }}</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>
<!-- 议价池卡片 -->
<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"
import {formatRate} from "@/utils/rate"
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 = formatRate(newVal, '')
},
immediate: true
}
},
methods: {
formatRate,
/** 格式化布尔值为中文 */
formatBoolean(value) {
if (value === 'true' || value === true || value === '1' || value === 1) return '是'
if (value === 'false' || value === false || value === '0' || value === 0) return '否'
return value || '-'
},
/** 格式化贷款用途 */
formatLoanPurpose(value) {
if (value === 'consumer') return '消费'
if (value === 'business') return '经营'
return value || '-'
},
/** 获取基准利率 */
getBaseLoanRate() {
return this.formatRate(this.retailOutput?.baseLoanRate)
},
/** 获取浮动BP */
getTotalBp() {
return this.retailOutput?.totalBp || '-'
},
/** 获取最终测算利率 */
getCalculateRate() {
return this.formatRate(this.retailOutput?.finalCalculateRate)
},
/** 设定执行利率 */
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>