376 lines
12 KiB
Vue
376 lines
12 KiB
Vue
<template>
|
|
<div class="">
|
|
<div class="rounded-lg border border-[#99999933] pb-2 mb-4">
|
|
|
|
<!-- 标题栏 -->
|
|
<div class="flex items-center mb-4 p-4">
|
|
<div class="w-8 h-8 flex items-center justify-center mr-2">
|
|
<img src="@/assets/images/report/fxgl.png" alt="风险概览" class="w-8 h-8 object-contain" />
|
|
</div>
|
|
<span class="font-bold text-gray-800">风险概览</span>
|
|
</div>
|
|
|
|
<div class="px-4 pb-4">
|
|
<!-- 综合风险等级 -->
|
|
<div class="mb-6">
|
|
<div class="p-4 rounded-lg" :class="getRiskCardClass()">
|
|
<div class="flex items-start">
|
|
<div class="mr-3 mt-1">
|
|
<img :src="getRiskIconPath()" alt="综合风险等级" class="w-10 h-10 object-contain" />
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="font-semibold text-gray-800">综合风险等级</h4>
|
|
<div class="risk-level-badge" :class="getRiskLevelClass()">
|
|
{{ riskLevel }}
|
|
</div>
|
|
</div>
|
|
<p class="text-gray-400 text-sm mb-2">
|
|
基于多维度数据分析的风险评估
|
|
</p>
|
|
<p class=" text-sm" :class="riskLevelTextClass">
|
|
{{ riskDescription }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 当前状态 -->
|
|
<div class="mb-6">
|
|
<LTitle title="当前状态" class="mb-4" />
|
|
<div class="space-y-4">
|
|
<!-- 逾期状态 -->
|
|
<div class="p-4 rounded-lg" :class="getOverdueCardClass()">
|
|
<div class="flex items-start">
|
|
<div class="mr-3 mt-1">
|
|
<img :src="getOverdueIconPath()" alt="逾期状态" class="w-10 h-10 object-contain" />
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="font-semibold text-gray-800">逾期状态</h4>
|
|
<div class="risk-level-badge" :class="getOverdueStatusClass()">
|
|
{{ overdueStatus }}
|
|
</div>
|
|
</div>
|
|
<p class="text-gray-400 text-sm">
|
|
当前逾期情况
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 当前逾期机构 -->
|
|
<div class="p-4 rounded-lg" :class="getOverdueInstitutionCardClass()">
|
|
<div class="flex items-start">
|
|
<div class="mr-3 mt-1">
|
|
<img :src="getOverdueInstitutionIconPath()" alt="当前逾期机构" class="w-10 h-10 object-contain" />
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="font-semibold text-gray-800">当前逾期机构</h4>
|
|
<div class="risk-level-badge" :class="getOverdueInstitutionClass()">
|
|
{{ currentOverdueInstitutions }}家
|
|
</div>
|
|
</div>
|
|
<p class="text-gray-400 text-sm">
|
|
逾期机构数量
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 关键指标 -->
|
|
<div class="">
|
|
<LTitle title="关键指标" />
|
|
<div class="space-y-2 p-4">
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-[#999999]">贷款总机构数</span>
|
|
<span class="text-[#333333] font-bold">{{ formatMetricValue(totalInstitutions) }}家</span>
|
|
</div>
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-[#999999]">已结清机构数</span>
|
|
<span class="text-[#333333] font-bold">{{ formatMetricValue(settledInstitutions) }}家</span>
|
|
</div>
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-[#999999]">信用贷款时长</span>
|
|
<span class="text-[#333333] font-bold">{{ formatDays(creditLoanDuration) }}</span>
|
|
</div>
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-[#999999]">最近一次交易距今</span>
|
|
<span class="text-[#333333] font-bold">{{ formatDays(lastTransactionDays) }}</span>
|
|
</div>
|
|
<div class="flex justify-between items-center text-sm">
|
|
<span class="text-[#999999]">最近一次还款距今</span>
|
|
<span class="text-[#333333] font-bold">{{ formatDays(lastRepaymentDays) }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 温馨提示 -->
|
|
<LRemark
|
|
content="风险概览提供申请人的整体风险状况总结,包括综合风险等级、当前状态和关键指标。风险等级基于多维度数据分析计算得出,包括但不限于逾期情况、借贷历史、还款表现等。当前状态展示申请人的实时风险指标,包括逾期状态、最近交易情况等。建议结合具体业务场景和风险政策进行综合判断。" />
|
|
</template>
|
|
|
|
<script>
|
|
import LTitle from '@/components/LTitle.vue'
|
|
import LRemark from '@/components/LRemark.vue'
|
|
|
|
export default {
|
|
name: 'RiskOverview',
|
|
components: {
|
|
LTitle,
|
|
LRemark
|
|
},
|
|
props: {
|
|
data: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
},
|
|
computed: {
|
|
// 解析区间化数据的辅助方法
|
|
totalInstitutions() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0001)
|
|
},
|
|
settledInstitutions() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0002)
|
|
},
|
|
currentOverdueStatus() {
|
|
return this.data.xyp_cpl0044 === '1'
|
|
},
|
|
currentOverdueInstitutions() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0071)
|
|
},
|
|
creditLoanDuration() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0045)
|
|
},
|
|
recent1DayInstitutions() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0070)
|
|
},
|
|
recent7DayInstitutions() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0009)
|
|
},
|
|
lastTransactionDays() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0046)
|
|
},
|
|
lastRepaymentDays() {
|
|
return this.parseIntervalValue(this.data.xyp_cpl0068)
|
|
},
|
|
|
|
// 综合风险等级计算
|
|
riskLevel() {
|
|
const creditScore = parseFloat(this.data.xyp_cpl0081) || 0
|
|
const overdueIndex = parseFloat(this.data.xyp_cpl0082) || 0
|
|
|
|
if (creditScore > 0.7 || overdueIndex > 0.7 || this.currentOverdueStatus) {
|
|
return '高风险'
|
|
} else if (creditScore > 0.4 || overdueIndex > 0.4) {
|
|
return '中风险'
|
|
} else {
|
|
return '低风险'
|
|
}
|
|
},
|
|
|
|
riskLevelClass() {
|
|
switch (this.riskLevel) {
|
|
case '高风险': return 'risk-high'
|
|
case '中风险': return 'risk-medium'
|
|
default: return 'risk-low'
|
|
}
|
|
},
|
|
|
|
riskLevelIconClass() {
|
|
switch (this.riskLevel) {
|
|
case '高风险': return 'bg-red-500'
|
|
case '中风险': return 'bg-yellow-500'
|
|
default: return 'bg-green-500'
|
|
}
|
|
},
|
|
|
|
riskLevelTextClass() {
|
|
switch (this.riskLevel) {
|
|
case '高风险': return 'text-red-600'
|
|
case '中风险': return 'text-yellow-600'
|
|
default: return 'text-green-600'
|
|
}
|
|
},
|
|
|
|
overdueStatusIconClass() {
|
|
return this.hasOverdue ? 'bg-red-500' : 'bg-green-500'
|
|
},
|
|
|
|
overdueStatusTextClass() {
|
|
return this.hasOverdue ? 'text-red-600' : 'text-green-600'
|
|
},
|
|
|
|
riskDescription() {
|
|
switch (this.riskLevel) {
|
|
case '高风险': return '存在较高信用风险,建议谨慎放贷'
|
|
case '中风险': return '信用风险适中,需要进一步评估'
|
|
default: return '信用风险较低,具备良好还款能力'
|
|
}
|
|
},
|
|
|
|
overdueStatus() {
|
|
return this.currentOverdueStatus ? '存在逾期' : '无逾期'
|
|
},
|
|
|
|
overdueStatusClass() {
|
|
return this.currentOverdueStatus ? 'status-danger' : 'status-success'
|
|
},
|
|
|
|
hasRecentActivity() {
|
|
return this.recent1DayInstitutions > 0 || this.recent7DayInstitutions > 0
|
|
},
|
|
|
|
hasOverdue() {
|
|
return this.currentOverdueStatus
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
// 获取综合风险等级卡片样式
|
|
getRiskCardClass() {
|
|
switch (this.riskLevel) {
|
|
case '高风险':
|
|
return 'bg-red-50 border border-red-200'
|
|
case '中风险':
|
|
return 'bg-yellow-50 border border-yellow-200'
|
|
default:
|
|
return 'bg-green-50 border border-green-200'
|
|
}
|
|
},
|
|
|
|
// 获取综合风险等级图标路径
|
|
getRiskIconPath() {
|
|
switch (this.riskLevel) {
|
|
case '高风险':
|
|
return new URL('@/assets/images/report/gfx.png', import.meta.url).href
|
|
case '中风险':
|
|
return new URL('@/assets/images/report/zfx.png', import.meta.url).href
|
|
default:
|
|
return new URL('@/assets/images/report/zq.png', import.meta.url).href
|
|
}
|
|
},
|
|
|
|
// 获取综合风险等级标签样式
|
|
getRiskLevelClass() {
|
|
switch (this.riskLevel) {
|
|
case '高风险':
|
|
return 'bg-red-600 text-white'
|
|
case '中风险':
|
|
return 'bg-yellow-600 text-white'
|
|
default:
|
|
return 'bg-green-600 text-white'
|
|
}
|
|
},
|
|
|
|
// 获取逾期状态卡片样式
|
|
getOverdueCardClass() {
|
|
return this.hasOverdue
|
|
? 'bg-red-50 border border-red-200'
|
|
: 'bg-green-50 border border-green-200'
|
|
},
|
|
|
|
// 获取逾期状态图标路径
|
|
getOverdueIconPath() {
|
|
return this.hasOverdue
|
|
? new URL('@/assets/images/report/gfx.png', import.meta.url).href
|
|
: new URL('@/assets/images/report/zq.png', import.meta.url).href
|
|
},
|
|
|
|
// 获取逾期状态标签样式
|
|
getOverdueStatusClass() {
|
|
return this.hasOverdue
|
|
? 'bg-red-600 text-white'
|
|
: 'bg-green-600 text-white'
|
|
},
|
|
|
|
// 获取当前逾期机构卡片样式
|
|
getOverdueInstitutionCardClass() {
|
|
return this.currentOverdueInstitutions > 0
|
|
? 'bg-red-50 border border-red-200'
|
|
: 'bg-green-50 border border-green-200'
|
|
},
|
|
|
|
// 获取当前逾期机构图标路径
|
|
getOverdueInstitutionIconPath() {
|
|
return this.currentOverdueInstitutions > 0
|
|
? new URL('@/assets/images/report/gfx.png', import.meta.url).href
|
|
: new URL('@/assets/images/report/zq.png', import.meta.url).href
|
|
},
|
|
|
|
// 获取当前逾期机构标签样式
|
|
getOverdueInstitutionClass() {
|
|
return this.currentOverdueInstitutions > 0
|
|
? 'bg-red-600 text-white'
|
|
: 'bg-green-600 text-white'
|
|
},
|
|
// 解析区间化数值
|
|
parseIntervalValue(value) {
|
|
if (!value || value === '' || value === '-1') return 0
|
|
const num = parseInt(value)
|
|
if (isNaN(num)) return 0
|
|
|
|
// 根据区间映射返回大致范围的中值
|
|
switch (num) {
|
|
case 1: return 1
|
|
case 2: return 3
|
|
case 3: return 7
|
|
case 4: return 15
|
|
case 5: return 25
|
|
default: return num
|
|
}
|
|
},
|
|
|
|
formatMetricValue(value) {
|
|
if (value === 0) return '0'
|
|
if (value < 5) return `${value}`
|
|
if (value < 10) return `${value}`
|
|
return `${value}+`
|
|
},
|
|
|
|
formatDays(value) {
|
|
if (value === 0) return '无记录'
|
|
if (value < 30) return `${value}天`
|
|
if (value < 365) return `${Math.floor(value / 30)}个月`
|
|
return `${Math.floor(value / 365)}年`
|
|
},
|
|
|
|
getMetricClass(value) {
|
|
if (value > 10) return 'text-red-600'
|
|
if (value > 5) return 'text-orange-600'
|
|
return 'text-green-600'
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 风险等级标签 */
|
|
.risk-level-badge {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
padding: 2px 6px;
|
|
border-radius: 0 8px 0 8px;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* 卡片需要相对定位 */
|
|
.p-4.rounded-lg {
|
|
position: relative;
|
|
}
|
|
</style>
|