1
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<span class="font-bold text-gray-800">申请行为详情</span>
|
||||
</div>
|
||||
|
||||
<span class="text-sm text-gray-500 mb-2 mx-4">0-1之间指数越大用户逾期可能性越高</span>
|
||||
<div class="p-4">
|
||||
<!-- 核心指标 -->
|
||||
<div class="grid grid-cols-2 gap-4 mb-6">
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<!-- 申请命中情况 -->
|
||||
<LTitle title="申请命中情况" />
|
||||
<div class="grid grid-cols-2 gap-4 mb-6 mt-3">
|
||||
<div class="grid grid-cols-1 gap-4 mb-6 mt-3">
|
||||
<div class="bg-gray-50 rounded-lg p-3">
|
||||
<div class="text-sm text-gray-600 mb-1">申请命中机构数</div>
|
||||
<div class="text-lg font-bold text-gray-800">{{ getValue(data.A22160003, '0') }} 家</div>
|
||||
@@ -59,17 +59,17 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-3">
|
||||
<div class="bg-blue-50 rounded-lg p-3 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160008, '0') }}</div>
|
||||
<div class="text-xs text-gray-600">近1个月查询笔数</div>
|
||||
<div class="bg-blue-50 rounded-lg px-3 py-6 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-3xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160008, '0') }}</div>
|
||||
<div class="text-sm text-gray-600">近1个月查询笔数</div>
|
||||
</div>
|
||||
<div class="bg-blue-50 rounded-lg p-3 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160009, '0') }}</div>
|
||||
<div class="text-xs text-gray-600">近3个月查询笔数</div>
|
||||
<div class="bg-blue-50 rounded-lg px-3 py-6 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-3xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160009, '0') }}</div>
|
||||
<div class="text-sm text-gray-600">近3个月查询笔数</div>
|
||||
</div>
|
||||
<div class="bg-blue-50 rounded-lg p-3 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160010, '0') }}</div>
|
||||
<div class="text-xs text-gray-600">近6个月查询笔数</div>
|
||||
<div class="bg-blue-50 rounded-lg px-3 py-6 text-center border border-[#2B79EE8F]">
|
||||
<div class="text-3xl font-bold text-[#2B79EE] mb-1">{{ getValue(data.A22160010, '0') }}</div>
|
||||
<div class="text-sm text-gray-600">近6个月查询笔数</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -197,7 +197,7 @@ const applyScoreGaugeOption = computed(() => {
|
||||
axisLabel: {
|
||||
show: true,
|
||||
distance: -18,
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
formatter: function(value) {
|
||||
if (value === 0) return '0'
|
||||
@@ -318,7 +318,7 @@ const applyConfidenceGaugeOption = computed(() => {
|
||||
axisLabel: {
|
||||
show: true,
|
||||
distance: -15,
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
formatter: function(value) {
|
||||
// 将百分比映射回置信度值
|
||||
@@ -413,7 +413,7 @@ const queryTrendChartOption = computed(() => {
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
formatter: '{value} 次'
|
||||
},
|
||||
@@ -441,7 +441,7 @@ const queryTrendChartOption = computed(() => {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,17 +237,17 @@
|
||||
<div class="text-sm font-medium text-gray-700 mb-3">M0+逾期</div>
|
||||
<div class="space-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近6个月</span>
|
||||
<span class="text-sm text-gray-600">近6个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170025, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近12个月</span>
|
||||
<span class="text-sm text-gray-600">近12个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170026, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近24个月</span>
|
||||
<span class="text-sm text-gray-600">近24个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170027, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
@@ -259,17 +259,17 @@
|
||||
<div class="text-sm font-medium text-gray-700 mb-3">M1+逾期</div>
|
||||
<div class="space-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近6个月</span>
|
||||
<span class="text-sm text-gray-600">近6个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170028, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近12个月</span>
|
||||
<span class="text-sm text-gray-600">近12个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170029, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs text-gray-600">近24个月</span>
|
||||
<span class="text-sm text-gray-600">近24个月</span>
|
||||
<span class="text-sm font-bold text-[#EB3C3C]">{{ getValue(data.B22170030, '0') }}
|
||||
笔</span>
|
||||
</div>
|
||||
@@ -516,7 +516,7 @@ const behaviorScoreGaugeOption = computed(() => {
|
||||
axisLabel: {
|
||||
show: true,
|
||||
distance: -18,
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
formatter: function (value) {
|
||||
if (value === 0) return '0'
|
||||
@@ -637,7 +637,7 @@ const behaviorConfidenceGaugeOption = computed(() => {
|
||||
axisLabel: {
|
||||
show: true,
|
||||
distance: -15,
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
formatter: function (value) {
|
||||
// 将百分比映射回置信度值
|
||||
@@ -722,7 +722,7 @@ const loanTrendChartOption = computed(() => {
|
||||
type: 'category',
|
||||
data: periods,
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
rotate: 15
|
||||
},
|
||||
@@ -735,7 +735,7 @@ const loanTrendChartOption = computed(() => {
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
formatter: '{value} 笔'
|
||||
},
|
||||
@@ -763,7 +763,7 @@ const loanTrendChartOption = computed(() => {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
@@ -829,7 +829,7 @@ const overdueComparisonChartOption = computed(() => {
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
formatter: '{value} 笔'
|
||||
},
|
||||
@@ -857,7 +857,7 @@ const overdueComparisonChartOption = computed(() => {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#333'
|
||||
}
|
||||
},
|
||||
@@ -878,7 +878,7 @@ const overdueComparisonChartOption = computed(() => {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
@@ -921,7 +921,7 @@ const amountDistributionChartOption = computed(() => {
|
||||
type: 'category',
|
||||
data: categories,
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280'
|
||||
},
|
||||
axisLine: {
|
||||
@@ -933,7 +933,7 @@ const amountDistributionChartOption = computed(() => {
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
formatter: '{value} 笔'
|
||||
},
|
||||
@@ -961,7 +961,7 @@ const amountDistributionChartOption = computed(() => {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 11,
|
||||
fontSize: 12,
|
||||
color: '#333'
|
||||
}
|
||||
}
|
||||
|
||||
456
src/ui/JRZQ7F1A/components/BigDataReportSection.vue
Normal file
456
src/ui/JRZQ7F1A/components/BigDataReportSection.vue
Normal file
@@ -0,0 +1,456 @@
|
||||
<template>
|
||||
<div class="big-data-report-section bg-white rounded-lg border border-gray-200">
|
||||
<div class="flex items-center p-4">
|
||||
<div class="w-8 h-8 flex items-center justify-center mr-2">
|
||||
<img src="@/assets/images/report/gl.png" alt="大数据详情" class="w-8 h-8 object-contain" />
|
||||
</div>
|
||||
<span class="font-bold text-gray-800">大数据详情</span>
|
||||
</div>
|
||||
|
||||
<div class="p-4">
|
||||
<!-- 网络贷款类信用 -->
|
||||
<LTitle title="网络贷款类信用" />
|
||||
<div class="mt-3 mb-6">
|
||||
<div class="space-y-4 mb-4">
|
||||
<!-- 网贷授信额度 -->
|
||||
<div class="rounded-lg border border-[#2B79EE8F] bg-[#2B79EE1A] p-4 text-center">
|
||||
<div class="text-xl font-bold text-[#2B79EE] mb-1">
|
||||
{{ formatCreditAmount(data.C22180001) }}
|
||||
</div>
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">网贷授信额度</div>
|
||||
</div>
|
||||
|
||||
<!-- 网贷额度置信度 -->
|
||||
<div class="rounded-lg border border-[#2B79EE8F] bg-[#2B79EE1A] p-4">
|
||||
<div class="text-sm font-medium text-gray-700 mb-2 text-center">网贷额度置信度</div>
|
||||
<div class="h-40">
|
||||
<v-chart class="chart-container" :option="p2pConfidenceGaugeOption" autoresize />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 rounded-lg p-4 space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">网络贷款类机构数</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ getValue(data.C22180003, '0') }} 家</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">网络贷款类产品数</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ getValue(data.C22180004, '0') }} 个</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">网络贷款机构最大授信额度</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ formatCreditAmount(data.C22180005) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">网络贷款机构平均授信额度</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ formatCreditAmount(data.C22180006) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 授信额度对比图 -->
|
||||
<div class="mb-6">
|
||||
<LTitle title="授信额度对比" />
|
||||
<div class="h-64 mt-3">
|
||||
<v-chart class="chart-container" :option="creditAmountChartOption" autoresize />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 消金贷款类信用 -->
|
||||
<LTitle title="消金贷款类信用" />
|
||||
<div class="mt-3 mb-6">
|
||||
<div class="space-y-4 mb-4">
|
||||
<!-- 消金建议授信额度 -->
|
||||
<div class="rounded-lg border border-[#1FBE5D8F] bg-[#1FBE5D1A] p-4 text-center">
|
||||
<div class="text-xl font-bold text-[#1FBE5D] mb-1">
|
||||
{{ formatCreditAmount(data.C22180011) }}
|
||||
</div>
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">消金建议授信额度</div>
|
||||
</div>
|
||||
|
||||
<!-- 消金额度置信度 -->
|
||||
<div class="rounded-lg border border-[#1FBE5D8F] bg-[#1FBE5D1A] p-4">
|
||||
<div class="text-sm font-medium text-gray-700 mb-2 text-center">消金额度置信度</div>
|
||||
<div class="h-40">
|
||||
<v-chart class="chart-container" :option="consumerConfidenceGaugeOption" autoresize />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 rounded-lg p-4 space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">消金贷款类机构数</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ getValue(data.C22180007, '0') }} 家</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">消金贷款类产品数</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ getValue(data.C22180008, '0') }} 个</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">消金贷款类机构最大授信额度</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ formatCreditAmount(data.C22180009) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-gray-600">消金贷款类机构平均授信额度</span>
|
||||
<span class="text-lg font-bold text-gray-800">{{ formatCreditAmount(data.C22180010) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 温馨提示 -->
|
||||
<Remark
|
||||
content="大数据详情展示申请人在网络贷款和消金贷款领域的授信情况,包括授信额度、机构数、产品数等指标。授信额度反映了金融机构对申请人信用状况的评估,额度越高通常表示信用状况越好。建议关注授信额度置信度,置信度越高表示评估结果越可靠。同时需要结合申请人的实际借贷行为和还款记录进行综合评估。" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import LTitle from '@/components/LTitle.vue'
|
||||
import Remark from '@/components/Remark.vue'
|
||||
import VChart from 'vue-echarts'
|
||||
import { use } from 'echarts/core'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { BarChart, GaugeChart } from 'echarts/charts'
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
GridComponent
|
||||
} from 'echarts/components'
|
||||
import { formatCreditAmount, formatConfidence, getValue } from '../utils/formatUtils'
|
||||
|
||||
// 注册ECharts组件
|
||||
use([
|
||||
CanvasRenderer,
|
||||
BarChart,
|
||||
GaugeChart,
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
GridComponent
|
||||
])
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
// 网贷额度置信度仪表盘配置(50-100)
|
||||
const p2pConfidenceGaugeOption = computed(() => {
|
||||
const confidence = parseInt(getValue(props.data.C22180002, '0')) || 0
|
||||
const percentage = confidence >= 50 ? ((confidence - 50) / 50) * 100 : 0
|
||||
|
||||
// 根据置信度确定颜色
|
||||
let color = '#2B79EE' // 蓝色 - 高置信度
|
||||
if (confidence < 60) {
|
||||
color = '#faad14' // 黄色 - 中等置信度
|
||||
} else if (confidence < 70) {
|
||||
color = '#fa8c16' // 橙色 - 较低置信度
|
||||
}
|
||||
|
||||
return {
|
||||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 180,
|
||||
endAngle: 0,
|
||||
min: 0,
|
||||
max: 100,
|
||||
radius: '90%',
|
||||
center: ['50%', '75%'],
|
||||
itemStyle: {
|
||||
color: color,
|
||||
shadowBlur: 6,
|
||||
shadowColor: color,
|
||||
},
|
||||
progress: {
|
||||
show: true,
|
||||
width: 18,
|
||||
roundCap: true,
|
||||
},
|
||||
axisLine: {
|
||||
roundCap: true,
|
||||
lineStyle: {
|
||||
width: 18,
|
||||
color: [
|
||||
[percentage / 100, color],
|
||||
[1, '#e5e7eb']
|
||||
]
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
show: false
|
||||
},
|
||||
pointer: {
|
||||
show: false
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: color,
|
||||
offsetCenter: [0, '-5%'],
|
||||
formatter: '{value}%',
|
||||
rich: {
|
||||
value: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: color,
|
||||
lineHeight: 28
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: percentage
|
||||
}
|
||||
],
|
||||
title: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
offsetCenter: [0, '25%'],
|
||||
formatter: () => `${confidence}%`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
// 消金额度置信度仪表盘配置(50-100)
|
||||
const consumerConfidenceGaugeOption = computed(() => {
|
||||
const confidence = parseInt(getValue(props.data.C22180012, '0')) || 0
|
||||
const percentage = confidence >= 50 ? ((confidence - 50) / 50) * 100 : 0
|
||||
|
||||
// 根据置信度确定颜色
|
||||
let color = '#1FBE5D' // 绿色 - 高置信度
|
||||
if (confidence < 60) {
|
||||
color = '#faad14' // 黄色 - 中等置信度
|
||||
} else if (confidence < 70) {
|
||||
color = '#fa8c16' // 橙色 - 较低置信度
|
||||
}
|
||||
|
||||
return {
|
||||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 180,
|
||||
endAngle: 0,
|
||||
min: 0,
|
||||
max: 100,
|
||||
radius: '90%',
|
||||
center: ['50%', '75%'],
|
||||
itemStyle: {
|
||||
color: color,
|
||||
shadowBlur: 6,
|
||||
shadowColor: color,
|
||||
},
|
||||
progress: {
|
||||
show: true,
|
||||
width: 18,
|
||||
roundCap: true,
|
||||
},
|
||||
axisLine: {
|
||||
roundCap: true,
|
||||
lineStyle: {
|
||||
width: 18,
|
||||
color: [
|
||||
[percentage / 100, color],
|
||||
[1, '#e5e7eb']
|
||||
]
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
show: false
|
||||
},
|
||||
pointer: {
|
||||
show: false
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: color,
|
||||
offsetCenter: [0, '-5%'],
|
||||
formatter: '{value}%',
|
||||
rich: {
|
||||
value: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: color,
|
||||
lineHeight: 28
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: percentage
|
||||
}
|
||||
],
|
||||
title: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
offsetCenter: [0, '25%'],
|
||||
formatter: () => `${confidence}%`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
// 授信额度对比图配置
|
||||
const creditAmountChartOption = computed(() => {
|
||||
const categories = ['网贷', '消金']
|
||||
const maxData = [
|
||||
parseInt(getValue(props.data.C22180005, '0')) || 0,
|
||||
parseInt(getValue(props.data.C22180009, '0')) || 0
|
||||
]
|
||||
const avgData = [
|
||||
parseInt(getValue(props.data.C22180006, '0')) || 0,
|
||||
parseInt(getValue(props.data.C22180010, '0')) || 0
|
||||
]
|
||||
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
formatter: function (params) {
|
||||
let result = params[0].name + '<br/>'
|
||||
params.forEach(item => {
|
||||
const value = item.value >= 10000
|
||||
? `${(item.value / 10000).toFixed(2)}万元`
|
||||
: `${item.value}元`
|
||||
result += `${item.seriesName}: ${value}<br/>`
|
||||
})
|
||||
return result
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['最大授信额度', '平均授信额度'],
|
||||
top: '5%',
|
||||
textStyle: {
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
top: '20%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: categories,
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
color: '#6b7280'
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#e5e7eb'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
color: '#6b7280',
|
||||
formatter: function (value) {
|
||||
if (value >= 10000) {
|
||||
return `${(value / 10000).toFixed(1)}万`
|
||||
}
|
||||
return value
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#f3f4f6'
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '最大授信额度',
|
||||
type: 'bar',
|
||||
data: maxData,
|
||||
barWidth: '30%',
|
||||
itemStyle: {
|
||||
color: '#2B79EE',
|
||||
borderRadius: [4, 4, 0, 0]
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
color: '#1e5bb8'
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
formatter: function (params) {
|
||||
const value = params.value
|
||||
return value >= 10000
|
||||
? `${(value / 10000).toFixed(1)}万`
|
||||
: value
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '平均授信额度',
|
||||
type: 'bar',
|
||||
data: avgData,
|
||||
barWidth: '30%',
|
||||
itemStyle: {
|
||||
color: '#1FBE5D',
|
||||
borderRadius: [4, 4, 0, 0]
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
color: '#179e4d'
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
formatter: function (params) {
|
||||
const value = params.value
|
||||
return value >= 10000
|
||||
? `${(value / 10000).toFixed(1)}万`
|
||||
: value
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<!-- 放款还款详情 -->
|
||||
<BehaviorReportSection :data="behaviorData" />
|
||||
|
||||
<!-- 信用详情 -->
|
||||
<CurrentReportSection :data="currentData" />
|
||||
<!-- 大数据详情 -->
|
||||
<BigDataReportSection :data="bigDataData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -16,7 +16,7 @@ import { computed } from 'vue'
|
||||
import { useRiskNotifier } from '@/composables/useRiskNotifier'
|
||||
import ApplyReportSection from './components/ApplyReportSection.vue'
|
||||
import BehaviorReportSection from './components/BehaviorReportSection.vue'
|
||||
import CurrentReportSection from './components/CurrentReportSection.vue'
|
||||
import BigDataReportSection from './components/BigDataReportSection.vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
@@ -47,17 +47,17 @@ const applyData = computed(() => rawData.value.apply_report_detail || {})
|
||||
// 放款还款详情
|
||||
const behaviorData = computed(() => rawData.value.behavior_report_detail || {})
|
||||
|
||||
// 信用详情
|
||||
const currentData = computed(() => rawData.value.current_report_detail || {})
|
||||
// 大数据详情
|
||||
const bigDataData = computed(() => rawData.value.current_report_detail || {})
|
||||
|
||||
// 计算风险评分(0-100分,分数越高越安全)
|
||||
const riskScore = computed(() => {
|
||||
const apply = applyData.value
|
||||
const behavior = behaviorData.value
|
||||
const current = currentData.value
|
||||
const bigData = bigDataData.value
|
||||
|
||||
// 检查是否有数据
|
||||
if (!apply || !behavior || !current || Object.keys(apply).length === 0) {
|
||||
if (!apply || !behavior || !bigData || Object.keys(apply).length === 0) {
|
||||
return 100 // 无数据视为最安全
|
||||
}
|
||||
|
||||
|
||||
206
src/ui/JRZQ7F1A/utils/simpleSplitter.js
Normal file
206
src/ui/JRZQ7F1A/utils/simpleSplitter.js
Normal file
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* 全景雷达(JRZQ7F1A) 数据拆分工具
|
||||
* 将原始的全景雷达报告拆分为申请行为详情、放款还款详情和大数据详情三个独立模块
|
||||
* 以便在 BaseReport 中按 Tab 展示
|
||||
*/
|
||||
|
||||
/**
|
||||
* 判断数据对象是否有效(非空且包含至少一个键)
|
||||
* @param {object} data
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const EMPTY_STRING_MARKERS = new Set(['-', '--', '0', '0.0', '暂无数据', '无数据', 'null', 'NULL'])
|
||||
|
||||
function hasData(data, visited = new WeakSet()) {
|
||||
if (data === null || data === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeof data === 'number') {
|
||||
return data !== 0 && !Number.isNaN(data)
|
||||
}
|
||||
|
||||
if (typeof data === 'string') {
|
||||
const trimmed = data.trim()
|
||||
if (!trimmed) return false
|
||||
return !EMPTY_STRING_MARKERS.has(trimmed)
|
||||
}
|
||||
|
||||
if (typeof data === 'boolean') {
|
||||
return data
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
if (data.length === 0) return false
|
||||
return data.some(item => hasData(item, visited))
|
||||
}
|
||||
|
||||
if (typeof data === 'object') {
|
||||
if (visited.has(data)) return false
|
||||
visited.add(data)
|
||||
const values = Object.values(data)
|
||||
if (values.length === 0) return false
|
||||
return values.some(value => hasData(value, visited))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const createDefaultObject = (fields, defaultValue = '0') =>
|
||||
fields.reduce((acc, key) => {
|
||||
acc[key] = defaultValue
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
const APPLY_REPORT_FIELDS = [
|
||||
'A22160001',
|
||||
'A22160002',
|
||||
'A22160003',
|
||||
'A22160004',
|
||||
'A22160005',
|
||||
'A22160006',
|
||||
'A22160007',
|
||||
'A22160008',
|
||||
'A22160009',
|
||||
'A22160010'
|
||||
]
|
||||
|
||||
const APPLY_REPORT_DEFAULTS = createDefaultObject(APPLY_REPORT_FIELDS)
|
||||
|
||||
const BEHAVIOR_REPORT_FIELDS = [
|
||||
'B22170001',
|
||||
'B22170002',
|
||||
'B22170003',
|
||||
'B22170004',
|
||||
'B22170005',
|
||||
'B22170006',
|
||||
'B22170007',
|
||||
'B22170008',
|
||||
'B22170009',
|
||||
'B22170010',
|
||||
'B22170011',
|
||||
'B22170012',
|
||||
'B22170013',
|
||||
'B22170014',
|
||||
'B22170015',
|
||||
'B22170016',
|
||||
'B22170017',
|
||||
'B22170018',
|
||||
'B22170019',
|
||||
'B22170020',
|
||||
'B22170021',
|
||||
'B22170022',
|
||||
'B22170023',
|
||||
'B22170024',
|
||||
'B22170025',
|
||||
'B22170026',
|
||||
'B22170027',
|
||||
'B22170028',
|
||||
'B22170029',
|
||||
'B22170030',
|
||||
'B22170031',
|
||||
'B22170032',
|
||||
'B22170033',
|
||||
'B22170034',
|
||||
'B22170035',
|
||||
'B22170036',
|
||||
'B22170037',
|
||||
'B22170038',
|
||||
'B22170039',
|
||||
'B22170040',
|
||||
'B22170041',
|
||||
'B22170042',
|
||||
'B22170043',
|
||||
'B22170044',
|
||||
'B22170045',
|
||||
'B22170046',
|
||||
'B22170047',
|
||||
'B22170048',
|
||||
'B22170049',
|
||||
'B22170050',
|
||||
'B22170051',
|
||||
'B22170052',
|
||||
'B22170053',
|
||||
'B22170054'
|
||||
]
|
||||
|
||||
const BEHAVIOR_REPORT_DEFAULTS = createDefaultObject(BEHAVIOR_REPORT_FIELDS)
|
||||
|
||||
const BIG_DATA_REPORT_FIELDS = [
|
||||
'C22180001',
|
||||
'C22180002',
|
||||
'C22180003',
|
||||
'C22180004',
|
||||
'C22180005',
|
||||
'C22180006',
|
||||
'C22180007',
|
||||
'C22180008',
|
||||
'C22180009',
|
||||
'C22180010',
|
||||
'C22180011',
|
||||
'C22180012'
|
||||
]
|
||||
|
||||
const BIG_DATA_REPORT_DEFAULTS = createDefaultObject(BIG_DATA_REPORT_FIELDS)
|
||||
|
||||
const normalizeModuleData = (source, defaults) => {
|
||||
const normalized = { ...defaults }
|
||||
if (!source || typeof source !== 'object') {
|
||||
return normalized
|
||||
}
|
||||
|
||||
Object.entries(source).forEach(([key, value]) => {
|
||||
if (value === undefined || value === null) {
|
||||
return
|
||||
}
|
||||
normalized[key] = value
|
||||
})
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分 JRZQ7F1A 报告数据
|
||||
* @param {Array} reportData - 原始报告数据数组
|
||||
* @returns {Array} 拆分后的报告数据数组
|
||||
*/
|
||||
export function splitJRZQ7F1AForTabs(reportData) {
|
||||
const targetIndex = reportData.findIndex(item => item.data?.apiID === 'JRZQ7F1A');
|
||||
const target = targetIndex >= 0 ? reportData[targetIndex] : null;
|
||||
|
||||
if (!target || !target.data?.data) {
|
||||
return reportData;
|
||||
}
|
||||
|
||||
const originalData = target.data.data;
|
||||
const baseTimestamp = target.data.timestamp;
|
||||
const success = target.data.success ?? true;
|
||||
|
||||
const splitModules = [];
|
||||
|
||||
const pushModule = (suffix, payload, defaults) => {
|
||||
splitModules.push({
|
||||
data: {
|
||||
apiID: `JRZQ7F1A_${suffix}`,
|
||||
data: normalizeModuleData(payload, defaults),
|
||||
success,
|
||||
timestamp: baseTimestamp,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
pushModule('ApplyReport', originalData.apply_report_detail, APPLY_REPORT_DEFAULTS);
|
||||
pushModule('BehaviorReport', originalData.behavior_report_detail, BEHAVIOR_REPORT_DEFAULTS);
|
||||
pushModule('BigDataReport', originalData.current_report_detail, BIG_DATA_REPORT_DEFAULTS);
|
||||
|
||||
// 未能拆出子模块则直接返回原数据
|
||||
if (splitModules.length === 0) {
|
||||
return reportData;
|
||||
}
|
||||
|
||||
const result = [...reportData];
|
||||
result.splice(targetIndex, 1, ...splitModules);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user