This commit is contained in:
2026-03-02 16:50:34 +08:00
parent a48770eaa6
commit 56ccf8a28d
25 changed files with 686 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -361,6 +361,11 @@ const featureMap = {
name: "名下车辆(车牌)",
component: defineAsyncComponent(() => import("@/ui/QCXG5F3A.vue")),
},
FLXGDEA9: {
name: "本人不良",
component: defineAsyncComponent(() => import("@/ui/CFLXGDEA9.vue")),
remark: '本人不良记录查询结果来源于公安部门等权威机构,包括各类违法犯罪前科记录。查询结果仅供参考,具体信息以相关部门官方记录为准。'
},
QCXG4D2E: { name: "名下车辆(数量)", component: defineAsyncComponent(() => import("@/ui/CQCXG4D2E.vue")) },
QCXG5U0Z: { name: "车辆静态信息查询", component: defineAsyncComponent(() => import("@/ui/CQCXG5U0Z.vue")) },
QCXG1U4U: { name: "车辆里程记录(混合查询)", component: defineAsyncComponent(() => import("@/ui/CQCXG1U4U.vue")) },
@@ -644,6 +649,7 @@ const featureRiskLevels = {
'FLXG7E8F': 20, // 司法涉诉
'FLXG3D56': 10, // 违约失信
'JRZQ4AA8': 10, // 还款压力
'FLXGDEA9': 20, // 本人不良
// 🟠 中高风险类 - 权重 7
'JRZQ0A03': 7, // 借贷申请记录
@@ -685,7 +691,7 @@ const featureRiskLevels = {
'DWBG8B4D_LeasingRisk': 6,
'DWBG8B4D_RiskSupervision': 8,
'DWBG8B4D_RiskWarningTab': 9,
'DWBG8B4D_CourtInfo':9,
'DWBG8B4D_CourtInfo': 9,
// 司南报告子模块
'DWBG6A2C_StandLiveInfo': 4,
@@ -700,7 +706,7 @@ const featureRiskLevels = {
'DWBG6A2C_CreditDetail': 5,
'DWBG6A2C_RentalBehavior': 5,
'DWBG6A2C_RiskSupervision': 8,
'DWBG6A2C_CourtRiskInfo':13,
'DWBG6A2C_CourtRiskInfo': 13,
// 贷款风险评估子模块
'CJRZQ5E9F_RiskOverview': 8,

View File

@@ -654,6 +654,7 @@ const getFeatureIcon = (apiId) => {
JRZQ8203: "/inquire_icons/jiedaixingwei.svg", // 借贷行为记录
JRZQ09J8: "/inquire_icons/beijianguanrenyuan.svg", // 收入评估
JRZQ4B6C: "/inquire_icons/fengxianxingwei.svg", // 探针C风险评估
FLXGDEA9: "/inquire_icons/benrenbuliang.png", // 本人不良
};
return iconMap[apiId] || "/inquire_icons/default.svg";
};

View File

@@ -60,6 +60,8 @@ export function useInquireForm(featureRef) {
// 司法涉诉
toc_PersonalLawsuit: ["name", "idCard", "mobile", "verificationCode"],
// 本人不良:姓名 + 身份证(授权由后端默认传 1
toc_PersonalBadRecord: ["name", "idCard"],
// 人企关系加强版:仅身份证号
toc_PersonEnterprisePro: ["idCard"],
// 新企业司法涉诉QYGL66SL仅企业名称其他字段后端自动补齐

View File

@@ -44,6 +44,13 @@ export const inquireCategoryConfig = {
icon: "sjsys_icon.svg",
iconFrom: "category",
},
{
name: "本人不良",
feature: "toc_PersonalBadRecord",
desc: "本人不良记录风险评估",
icon: "sifasheyu.svg",
iconFrom: "category",
},
],
},
/** 婚恋风险 */

668
src/ui/CFLXGDEA9.vue Normal file
View File

@@ -0,0 +1,668 @@
<template>
<div class="personal-bad-record card">
<!-- 空数据提示 -->
<div v-if="!hasData" class="py-8 text-center text-gray-500">
<div class="flex flex-col items-center">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-3">
<span class="text-2xl text-gray-400">📋</span>
</div>
<p>暂无本人不良数据</p>
</div>
</div>
<div v-else class="space-y-4">
<!-- 风险总览 -->
<div class="">
<div class="flex items-center mb-3">
<div class="w-12 h-12">
<img src="/inquire_icons/benrenbuliang.png" alt="本人不良记录" class="w-8 h-8 object-contain" />
</div>
<div>
<h2 class="text-lg font-bold text-gray-800">风险总览</h2>
<p class="text-sm text-[#999999]">本人不良记录风险评估</p>
</div>
</div>
<!-- 风险统计 -->
<div class="bg-[#FFF0F0] border border-red-200 rounded-lg p-4" v-if="!isNormalPerson">
<div class="grid grid-cols-3 gap-4">
<div class="text-center">
<div class="text-sm text-[#666666] mb-1">总风险点</div>
<div class="text-lg font-bold text-[#E53935]">{{ hitRiskTypes.length }}</div>
</div>
<div class="text-center">
<div class="text-sm text-[#666666] mb-1">高风险</div>
<div class="text-lg font-bold text-[#E53935]">{{ getHighRiskCount() }}</div>
</div>
<div class="text-center">
<div class="text-sm text-[#666666] mb-1">中风险</div>
<div class="text-lg font-bold text-[#FFC107]">{{ getMiddleRiskCount() }}</div>
</div>
</div>
</div>
<!-- 正常人员显示 -->
<div class="bg-[#F0FFF0] border border-green-200 rounded-lg p-4" v-else>
<div class="flex items-center justify-center">
<div class="w-10 h-10 mr-4">
<img src="@/assets/images/report/zq.png" alt="暂无风险" class="w-10 h-10 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-[#333333] text-center">正常人员</div>
<div class="text-sm text-[#999999] text-center">无不良记录属于正常人员</div>
</div>
</div>
</div>
</div>
<!-- 所有风险类型列表 -->
<div class="space-y-3">
<!-- 人员状态 -->
<div class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass('0')">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass('0')]">
{{ getNormalPersonBadgeText() }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon('0')" :alt="isNormalPerson ? '正常人员' : '存在风险'"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor('0')">
{{ isNormalPerson ? '正常人员' : '人员状态' }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ isNormalPerson ? '无不良记录,属于正常人员' : '存在不良记录风险'
}}</div>
</div>
</div>
</div>
<!-- A类侵犯公民人身权利民主权利 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">A类侵犯公民人身权利民主权利</div>
<div class="space-y-2">
<div v-for="code in ['A', 'A1', 'A2', 'A3', 'A4', 'A5']" :key="code"
class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass(code)">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass(code)]">
{{ isHit(code) ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon(code)" :alt="getRiskTypeInfo(code).text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor(code)">
{{ getRiskTypeInfo(code).text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo(code).description }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- B类经济类前科 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">B类经济类前科</div>
<div class="space-y-2">
<div v-for="code in ['B', 'B1', 'B2', 'B3', 'B4', 'B5']" :key="code"
class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass(code)">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass(code)]">
{{ isHit(code) ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon(code)" :alt="getRiskTypeInfo(code).text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor(code)">
{{ getRiskTypeInfo(code).text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo(code).description }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- C类妨害社会管理秩序 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">C类妨害社会管理秩序</div>
<div class="space-y-2">
<div v-for="code in ['C', 'C1', 'C2', 'C3', 'C4', 'C5']" :key="code"
class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass(code)">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass(code)]">
{{ isHit(code) ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon(code)" :alt="getRiskTypeInfo(code).text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor(code)">
{{ getRiskTypeInfo(code).text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo(code).description }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- D类重点 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">D类重点</div>
<div class="space-y-2">
<div v-for="code in ['D', 'D1', 'D2', 'D3', 'D4', 'D5']" :key="code"
class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass(code)">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass(code)]">
{{ isHit(code) ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon(code)" :alt="getRiskTypeInfo(code).text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor(code)">
{{ getRiskTypeInfo(code).text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo(code).description }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- E类涉交通案件 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">E类涉交通案件</div>
<div class="space-y-2">
<div class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass('E')">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass('E')]">
{{ isHit('E') ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon('E')" :alt="getRiskTypeInfo('E').text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor('E')">
{{ getRiskTypeInfo('E').text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo('E').description }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- F类法院文书 -->
<div class="risk-group">
<div class="text-sm font-semibold text-gray-700 mb-2 px-2">F类法院文书</div>
<div class="space-y-2">
<div class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass('F')">
<div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass('F')]">
{{ isHit('F') ? '异常' : '正常' }}
</div>
<div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon('F')" :alt="getRiskTypeInfo('F').text"
class="w-8 h-8 object-contain" />
</div>
<div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor('F')">
{{ getRiskTypeInfo('F').text }}
</div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo('F').description }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from "vue";
import LRemark from '@/components/LRemark.vue'
import { useRiskNotifier } from '@/composables/useRiskNotifier'
// 导入风险类型图标
import iconZfx from '@/assets/images/report/zfx.png'
import iconGfx from '@/assets/images/report/gfx.png'
import iconSafe from '@/assets/images/report/zq.png'
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
params: {
type: Object,
default: () => ({}),
},
apiId: {
type: String,
default: '',
},
index: {
type: Number,
default: 0,
},
notifyRiskStatus: {
type: Function,
default: () => { },
},
})
// 风险类型代码映射
const riskTypeMap = {
'0': {
text: '正常人员',
description: '无不良记录,属于正常人员',
level: 'normal',
riskLevel: '正常'
},
'A': {
text: '前科:侵犯公民人身权利,民主权利',
description: '存在侵犯公民人身权利、民主权利的前科记录(在逃,盗窃、诈骗、抢劫、故意伤害、强奸等在刑或前科等)',
level: 'high',
riskLevel: '高风险'
},
'A1': {
text: '盗窃',
description: '存在盗窃前科记录',
level: 'high',
riskLevel: '高风险'
},
'A2': {
text: '诈骗',
description: '存在诈骗前科记录',
level: 'high',
riskLevel: '高风险'
},
'A3': {
text: '抢劫/夺',
description: '存在抢劫、抢夺前科记录',
level: 'high',
riskLevel: '高风险'
},
'A4': {
text: '故意伤害/杀人',
description: '存在故意伤害、杀人前科记录',
level: 'high',
riskLevel: '高风险'
},
'A5': {
text: '强奸/性侵/猥亵',
description: '存在强奸、性侵、猥亵前科记录',
level: 'high',
riskLevel: '高风险'
},
'B': {
text: '经济类前科',
description: '存在破坏金融秩序、非法吸存、违发贷款、金融诈骗、集资诈骗、保险诈骗、假币等在刑或前科等',
level: 'medium',
riskLevel: '中风险'
},
'B1': {
text: '走私',
description: '存在走私前科记录',
level: 'medium',
riskLevel: '中风险'
},
'B2': {
text: '破坏金融管理秩序',
description: '存在破坏金融管理秩序前科记录',
level: 'medium',
riskLevel: '中风险'
},
'B3': {
text: '金融诈骗',
description: '存在金融诈骗前科记录',
level: 'medium',
riskLevel: '中风险'
},
'B4': {
text: '洗钱',
description: '存在洗钱前科记录',
level: 'medium',
riskLevel: '中风险'
},
'B5': {
text: '偷漏税',
description: '存在偷漏税前科记录',
level: 'medium',
riskLevel: '中风险'
},
'C': {
text: '妨害社会管理秩序',
description: '存在扰乱公共秩序、妨害司法、妨害国境管理、妨害文物管理、涉毒、涉黄等在刑或前科等',
level: 'medium',
riskLevel: '中风险'
},
'C1': {
text: '扰乱公共秩序',
description: '存在扰乱公共秩序前科记录',
level: 'medium',
riskLevel: '中风险'
},
'C2': {
text: '妨害司法',
description: '存在妨害司法前科记录',
level: 'medium',
riskLevel: '中风险'
},
'C3': {
text: '涉毒',
description: '存在涉毒前科记录',
level: 'medium',
riskLevel: '中风险'
},
'C4': {
text: '涉黄刑案',
description: '存在涉黄刑案前科记录',
level: 'medium',
riskLevel: '中风险'
},
'C5': {
text: '帮信/掩隐/侵公',
description: '存在帮助信息网络犯罪活动、掩饰隐瞒犯罪所得、侵犯公民个人信息前科记录',
level: 'medium',
riskLevel: '中风险'
},
'D': {
text: '重点',
description: '存在危害国家、公共安全,涉恐、疆藏,涉稳、涉黑、涉及境外等',
level: 'critical',
riskLevel: '高风险'
},
'D1': {
text: '危害国家、公共安全',
description: '存在危害国家、公共安全前科记录',
level: 'critical',
riskLevel: '高风险'
},
'D2': {
text: '涉稳',
description: '存在涉稳前科记录',
level: 'critical',
riskLevel: '高风险'
},
'D3': {
text: '涉及境外',
description: '存在涉及境外前科记录',
level: 'critical',
riskLevel: '高风险'
},
'D4': {
text: '涉恐、疆藏',
description: '存在涉恐、疆藏前科记录',
level: 'critical',
riskLevel: '高风险'
},
'D5': {
text: '涉黑',
description: '存在涉黑前科记录',
level: 'critical',
riskLevel: '高风险'
},
'E': {
text: '涉交通案件',
description: '存在危险驾驶、交通肇事等交通案件前科记录',
level: 'low',
riskLevel: '低风险'
},
'F': {
text: '法院文书',
description: '存在法院文书记录',
level: 'low',
riskLevel: '低风险'
}
}
// 获取风险类型信息
const getRiskTypeInfo = (type) => {
return riskTypeMap[type] || riskTypeMap['F']
}
// 解析命中的风险代码
const hitRiskCodes = computed(() => {
const levelData = props.data?.data?.level || props.data?.level
if (!levelData) return []
const levelStr = levelData.toString()
return levelStr.split(',').map(code => code.trim()).filter(code => code)
})
// 判断是否命中某个风险代码
const isHit = (code) => {
if (code === '0') {
// 如果level是'0',则正常人员命中
return hitRiskCodes.value.includes('0')
}
// 如果直接包含该代码,则命中
if (hitRiskCodes.value.includes(code)) {
return true
}
// 对于父级类型A、B、C、D如果子类型命中父类型也算命中
if (code === 'A') {
// 如果 A1、A2、A3、A4、A5 任何一个命中A 也算命中
return ['A1', 'A2', 'A3', 'A4', 'A5'].some(subCode => hitRiskCodes.value.includes(subCode))
}
if (code === 'B') {
// 如果 B1、B2、B3、B4、B5 任何一个命中B 也算命中
return ['B1', 'B2', 'B3', 'B4', 'B5'].some(subCode => hitRiskCodes.value.includes(subCode))
}
if (code === 'C') {
// 如果 C1、C2、C3、C4、C5 任何一个命中C 也算命中
return ['C1', 'C2', 'C3', 'C4', 'C5'].some(subCode => hitRiskCodes.value.includes(subCode))
}
if (code === 'D') {
// 如果 D1、D2、D3、D4、D5 任何一个命中D 也算命中
return ['D1', 'D2', 'D3', 'D4', 'D5'].some(subCode => hitRiskCodes.value.includes(subCode))
}
return false
}
// 获取命中的风险类型列表
const hitRiskTypes = computed(() => {
return hitRiskCodes.value.filter(code => code !== '0').map(code => ({
code,
...getRiskTypeInfo(code)
}))
})
// 判断是否有数据
const hasData = computed(() => {
const levelData = props.data?.data?.level || props.data?.level
return levelData && Object.keys(props.data || {}).length > 0
})
// 判断是否为正常人员
const isNormalPerson = computed(() => {
return hitRiskCodes.value.includes('0') && hitRiskCodes.value.length === 1
})
// 获取高风险数量
const getHighRiskCount = () => {
return hitRiskTypes.value.filter(risk =>
risk.level === 'high' || risk.level === 'critical'
).length
}
// 获取中风险数量
const getMiddleRiskCount = () => {
return hitRiskTypes.value.filter(risk => risk.level === 'medium').length
}
// 获取风险项样式类
const getRiskItemClass = (code) => {
const hit = isHit(code)
const riskInfo = getRiskTypeInfo(code)
if (code === '0') {
// 正常人员:如果是正常人员显示绿色,否则显示红色(存在异常)
return isNormalPerson.value ? 'bg-green-50 border-green-200' : 'bg-red-50 border-red-200'
}
if (hit) {
if (riskInfo.level === 'critical' || riskInfo.level === 'high') {
return 'bg-red-50 border-red-200'
} else if (riskInfo.level === 'medium') {
return 'bg-orange-50 border-orange-200'
} else {
return 'bg-yellow-50 border-yellow-200'
}
}
return 'bg-gray-50 border-gray-200'
}
// 获取风险项文本颜色
const getRiskItemTextColor = (code) => {
const hit = isHit(code)
const riskInfo = getRiskTypeInfo(code)
if (code === '0') {
// 正常人员:如果是正常人员显示绿色,否则显示红色(存在异常)
return isNormalPerson.value ? 'text-green-600' : 'text-red-600'
}
if (hit) {
if (riskInfo.level === 'critical' || riskInfo.level === 'high') {
return 'text-red-600'
} else if (riskInfo.level === 'medium') {
return 'text-orange-600'
} else {
return 'text-yellow-600'
}
}
return 'text-gray-600'
}
// 获取风险项图标
const getRiskItemIcon = (code) => {
const hit = isHit(code)
const riskInfo = getRiskTypeInfo(code)
if (code === '0') {
// 正常人员:如果是正常人员显示安全图标,否则显示风险图标(存在异常)
return isNormalPerson.value ? iconSafe : iconGfx
}
if (hit) {
if (riskInfo.level === 'critical' || riskInfo.level === 'high') {
return iconGfx
} else {
return iconZfx
}
}
return iconSafe
}
// 获取正常人员标签文本
const getNormalPersonBadgeText = () => {
// 只有当 level 只有 '0' 时才显示"正常人员"
if (isNormalPerson.value) {
return '正常'
}
// 否则显示"存在异常"
return '存在异常'
}
// 获取风险标签样式类
const getRiskBadgeClass = (code) => {
const hit = isHit(code)
const riskInfo = getRiskTypeInfo(code)
if (code === '0') {
// 正常人员:如果是正常人员显示绿色,否则显示红色(存在异常)
return isNormalPerson.value ? 'bg-green-500' : 'bg-[#E53935]'
}
if (hit) {
if (riskInfo.level === 'critical' || riskInfo.level === 'high') {
return 'bg-[#E53935]'
} else if (riskInfo.level === 'medium') {
return 'bg-[#D6943E]'
} else {
return 'bg-yellow-500'
}
}
// 未命中显示绿色(正常)
return 'bg-green-500'
}
// 计算风险评分0-100分分数越高越安全
const riskScore = computed(() => {
if (isNormalPerson.value) {
return 100 // 正常人员,最安全
}
if (hitRiskTypes.value.length === 0) {
return 100 // 无风险数据,最安全
}
// 获取高风险和中风险数量
const highRiskCount = getHighRiskCount()
const middleRiskCount = getMiddleRiskCount()
// 高风险数量越多,分数越低
let score = 100
// 高风险扣分每个高风险扣15分
score -= highRiskCount * 15
// 中风险扣分每个中风险扣8分
score -= middleRiskCount * 8
// 确保分数在合理范围内最低20分
return Math.max(20, Math.min(100, score))
})
// 使用 composable 通知父组件风险评分
useRiskNotifier(props, riskScore)
// 暴露给父组件
defineExpose({
riskScore
})
</script>
<style lang="scss" scoped>
.personal-bad-record {
@apply space-y-4;
}
.risk-group {
@apply mb-4;
}
</style>