Files
report_viewer/src/ui/CJRZQ5E9F/components/RiskOverview.vue

376 lines
12 KiB
Vue
Raw Normal View History

2025-12-18 15:39:43 +08:00
<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>