Files
qncV4uni-app/src/report-ui/vehicles/CQCXG6B4E.vue
2026-05-16 15:47:07 +08:00

494 lines
16 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="card">
<div class="header-box">
<div class="header-left">
<h3 class="header-title">车辆出险记录核验</h3>
<p class="header-desc">综合车辆出险脱保重大事故等信息评估风险</p>
</div>
</div>
<template v-if="hasData">
<div class="risk-band" :class="riskLevelClass">
<div class="risk-band-label">风险等级</div>
<div class="risk-band-text">{{ riskLevelText }}</div>
</div>
<!-- 顶部车辆与价格概览 -->
<div class="summary-card">
<div class="summary-main">
<div class="summary-left">
<div class="plate" v-if="data.LicensePlate">{{ data.LicensePlate }}</div>
<div class="car-type">{{ data.CarType || '未知车型' }}</div>
</div>
<div class="summary-right">
<div class="summary-label">二手车价格参考</div>
<div class="summary-price">{{ usedCarPriceText }}</div>
<div class="summary-sub">新车购置价{{ newCarPriceText }}</div>
</div>
</div>
<div class="summary-meta">
<div class="meta-line">
<span>燃料</span><span class="strong">{{ data.FuelType || '未知' }}</span>
<span class="dot"></span>
<span>发动机号</span><span class="strong code">{{ data.EngineNumber || '-' }}</span>
</div>
<div class="meta-line">
<span>初登日期</span><span class="strong">{{ data.DebutDate || '-' }}</span>
<span class="dot"></span>
<span>车龄</span><span class="strong">{{ carAgeText }}</span>
</div>
</div>
</div>
<!-- 核心风险指标 -->
<div class="detail-card">
<h4 class="section-title">核心风险指标</h4>
<div class="field-grid">
<div class="field">
<div class="field-label">是否高风险车辆</div>
<div class="field-value" :class="flagClass(data.IfHighriskVehicle === '1')">
{{ yesNoText(data.IfHighriskVehicle, '高风险车辆') }}
</div>
</div>
<div class="field">
<div class="field-label">是否营运车辆</div>
<div class="field-value" :class="flagClass(data.IsOperation === '1')">
{{ yesNoText(data.IsOperation, '营运车辆') }}
</div>
</div>
<div class="field">
<div class="field-label">是否投保车损险</div>
<div class="field-value" :class="flagClass(data.IfCarDamage === '1')">
{{ yesNoText(data.IfCarDamage, '已投保车损险', '未投保车损险') }}
</div>
</div>
<div class="field">
<div class="field-label">是否连续投保</div>
<div class="field-value" :class="flagClass(data.IsConInsure === '1')">
{{ yesNoText(data.IsConInsure, '连续投保', '非连续投保') }}
</div>
</div>
<div class="field">
<div class="field-label">历史是否脱保</div>
<div class="field-value" :class="flagClass(data.IfTuoBao === '1')">
{{ yesNoText(data.IfTuoBao, '有脱保记录', '无脱保记录') }}
</div>
</div>
<div class="field">
<div class="field-label">历史最大脱保时间</div>
<div class="field-value">{{ data.TuoBaoTime || '-' }}</div>
</div>
<div class="field">
<div class="field-label">最高车损险损失比例</div>
<div class="field-value">{{ data.CompensationRatioo || '-' }}</div>
</div>
<div class="field">
<div class="field-label">车损险综合评分</div>
<div class="field-value strong">{{ data.Total || '-' }}</div>
</div>
</div>
</div>
<!-- 出险与事故情况 -->
<div class="detail-card">
<h4 class="section-title">出险与事故情况</h4>
<div class="field-grid">
<div class="field">
<div class="field-label">商业险出险</div>
<div class="field-value">{{ formatDangerCount(data.CommercialPolicyDangerCount, '商业险') }}</div>
</div>
<div class="field">
<div class="field-label">交强险出险</div>
<div class="field-value">{{ formatDangerCount(data.CompulsoryPolicyDangerCount, '交强险') }}</div>
</div>
<div class="field">
<div class="field-label">三者险出险次数</div>
<div class="field-value">{{ formatDangerCount(data.ThreeRisksDangerCount, '三者险') }}</div>
</div>
<div class="field">
<div class="field-label">全损情况</div>
<div class="field-value">{{ totalLossText }}</div>
</div>
<div class="field field-span">
<div class="field-label">重大事故标志</div>
<div class="field-value">{{ formatMajorAccident(data.MajorAccident) }}</div>
</div>
<div class="field">
<div class="field-label">事故次数</div>
<div class="field-value">{{ data.IsMajorAccidentData || '-' }}</div>
</div>
<div class="field">
<div class="field-label">事故等级</div>
<div class="field-value">{{ data.IsMajorAccidentLevel || '-' }}</div>
</div>
<div class="field field-span">
<div class="field-label">损失部位</div>
<div class="field-value">{{ formatLossPart(data.LossPart) }}</div>
</div>
</div>
</div>
<!-- 保单与责任险可保情况 -->
<div class="detail-card">
<h4 class="section-title">保单与责任险承保情况</h4>
<div class="field-grid">
<div class="field">
<div class="field-label">商业险保单倒计时</div>
<div class="field-value">{{ formatPolicyTime(data.CommercialPolicyTime, '商业险') }}</div>
</div>
<div class="field">
<div class="field-label">交强险保单倒计时</div>
<div class="field-value">{{ formatPolicyTime(data.CompulsoryPolicyTime, '交强险') }}</div>
</div>
<div class="field">
<div class="field-label">商业险过户次数</div>
<div class="field-value">{{ formatTransferCount(data.CommercialPolicyTransferCount) }}</div>
</div>
<div class="field">
<div class="field-label">交强险过户次数</div>
<div class="field-value">{{ formatTransferCount(data.CompulsoryPolicyTransferCount) }}</div>
</div>
<div class="field">
<div class="field-label">是否可投保责任险</div>
<div class="field-value" :class="flagClass(data.IsLiabilityAvailable === 'Y')">
{{ ynText(data.IsLiabilityAvailable, '可投保', '不可投保') }}
</div>
</div>
<div class="field">
<div class="field-label">是否可承保延保</div>
<div class="field-value" :class="flagClass(data.IsExtendAvailable === 'Y')">
{{ ynText(data.IsExtendAvailable, '可承保', '不可承保') }}
</div>
</div>
</div>
</div>
</template>
<div v-else class="empty">
<div class="icon"></div>
<div class="title">暂无出险记录</div>
<div class="sub">未查询到车辆出险记录或返回数据为空</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useRiskNotifier } from '@/composables/useRiskNotifier';
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 data = computed(() => props.data || {});
const hasData = computed(() => !!data.value && Object.keys(data.value).length > 0);
const usedCarPriceText = computed(() => {
const v = data.value.UsedCarPrice;
if (!v) return '-';
return `${v}`;
});
const newCarPriceText = computed(() => {
const v = data.value.PurchasePrice;
if (!v) return '-';
return `${v}`;
});
const carAgeText = computed(() => {
const m = data.value.CarAge;
if (!m) return '-';
return `${m} 个月`;
});
const totalLossText = computed(() => {
const v = data.value.TotalLoss;
if (v === '1') return '存在全损记录';
if (v === '0') return '无全损记录';
return '-';
});
// 简单按高风险车辆/重大事故等情况给出一个文字风险等级
const riskLevelText = computed(() => {
if (data.value.IfHighriskVehicle === '1') return '高风险';
if (data.value.IsMajorAccidentLevel && data.value.IsMajorAccidentLevel !== '一般') return '较高风险';
if (data.value.IsMajorAccidentData && data.value.IsMajorAccidentData !== '0') return '有事故记录';
return '风险可控';
});
const riskLevelClass = computed(() => {
const t = riskLevelText.value;
if (t === '高风险') return 'risk-high';
if (t === '较高风险' || t === '有事故记录') return 'risk-mid';
return 'risk-low';
});
const flagClass = (flag) => {
return flag ? 'flag-yes' : 'flag-no';
};
const yesNoText = (val, yesText, noText = '否') => {
if (val === '1') return yesText;
if (val === '0') return noText;
return '-';
};
const ynText = (val, yesText, noText) => {
if (val === 'Y') return yesText;
if (val === 'N') return noText;
return '-';
};
const formatPolicyTime = (val, label) => {
if (!val || val === 'NULL') {
return `当期无${label}保单`;
}
const parts = String(val).split(':');
if (parts.length < 2) return val;
const daysRaw = parts[1];
if (!daysRaw || daysRaw.toLowerCase() === 'null') {
return `${label}保单已过期`;
}
const days = Number(daysRaw);
if (Number.isNaN(days)) return val;
if (days < 0) return `${label}保单已过期`;
return `${label}保单剩余 ${days}`;
};
const formatDangerCount = (val, label) => {
if (!val) return '-';
const parts = String(val).split(':');
const countRaw = parts[1] ?? '';
if (!countRaw || countRaw.toLowerCase() === 'null') {
return `${label}暂无出险记录`;
}
const count = Number(countRaw);
if (Number.isNaN(count)) return val;
if (count === 0) return `${label}暂无出险记录`;
return `${label}出险 ${count}`;
};
const formatTransferCount = (val) => {
if (!val) return '-';
const parts = String(val).split(':');
const countRaw = parts[1] ?? '';
if (!countRaw || countRaw.toLowerCase() === 'null') return '-';
const count = Number(countRaw);
if (Number.isNaN(count)) return val;
return `${count}`;
};
const formatMajorAccident = (val) => {
if (!val) return '-';
const map = {
A: '碰撞',
B: '火自燃',
C: '水淹',
D: '盗抢',
};
const list = [];
String(val)
.split(',')
.forEach((pair) => {
const [k, v] = pair.split(':');
if (v === '1' && map[k]) {
list.push(map[k]);
}
});
if (!list.length) return '无重大事故记录';
return `重大事故类型:${list.join('、')}`;
};
const formatLossPart = (val) => {
if (!val) return '-';
const partMap = {
1: '正前方',
2: '正后方',
3: '顶部',
4: '底部',
5: '前方左侧',
6: '后方左侧',
7: '中间左侧',
8: '前方右侧',
9: '后方右侧',
10: '中间右侧',
11: '内部',
12: '其它',
13: '不详',
};
const items = [];
String(val)
.split(',')
.forEach((pair) => {
const [kRaw, vRaw] = pair.split(':');
const key = Number(kRaw);
const count = Number(vRaw);
if (!Number.isNaN(key) && !Number.isNaN(count) && count > 0) {
const label = partMap[key] || `部位${key}`;
items.push(`${label}${count}`);
}
});
if (!items.length) return '暂无损失部位信息';
return items.join('、');
};
const riskScore = computed(() => 100);
useRiskNotifier(props, riskScore);
defineExpose({ riskScore });
</script>
<style scoped>
.card {
@apply bg-white rounded-2xl p-6 shadow-sm border border-gray-100;
}
.header-box {
@apply flex items-center mb-3 px-5 py-4 rounded-2xl bg-gradient-to-r from-rose-50 via-orange-50 to-amber-50;
}
.header-left {
@apply flex flex-col;
}
.header-title {
@apply text-2xl font-semibold m-0 text-rose-900;
}
.header-desc {
@apply text-base mt-3 m-0 text-rose-800 opacity-90;
}
.risk-band {
@apply mb-4 px-4 py-3 rounded-2xl flex items-center justify-between;
}
.risk-band.risk-high {
@apply bg-red-50 border border-red-100;
}
.risk-band.risk-mid {
@apply bg-amber-50 border border-amber-100;
}
.risk-band.risk-low {
@apply bg-emerald-50 border border-emerald-100;
}
.risk-band-label {
@apply text-sm text-gray-600;
}
.risk-band-text {
@apply text-xl font-bold;
}
.summary-card {
@apply rounded-2xl border border-amber-100 bg-amber-50/60 px-5 py-4 mb-4;
}
.summary-main {
@apply flex items-start justify-between mb-3 gap-4;
}
.summary-left {
@apply flex flex-col gap-2;
}
.plate {
@apply inline-flex items-center px-4 py-2 rounded-full bg-slate-900 text-white text-xl font-semibold tracking-widest;
}
.car-type {
@apply text-lg font-medium text-gray-800;
}
.summary-right {
@apply text-right;
}
.summary-label {
@apply text-sm text-gray-500;
}
.summary-price {
@apply text-2xl font-bold text-amber-800 mt-1;
}
.summary-sub {
@apply text-sm text-amber-700 opacity-90;
}
.summary-meta {
@apply space-y-1 text-base text-gray-800;
}
.meta-line {
@apply flex flex-wrap items-center gap-2;
}
.meta-line .dot {
@apply w-1 h-1 rounded-full bg-gray-400;
}
.strong {
@apply font-semibold;
}
.code {
@apply font-mono tracking-wide;
}
.detail-card {
@apply rounded-2xl border border-gray-100 bg-gray-50/60 px-5 py-4 mb-4;
}
.section-title {
@apply text-base font-semibold text-gray-800 mb-3;
}
.field-grid {
@apply grid gap-y-3 gap-x-6;
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.field-label {
@apply text-sm text-gray-500 mb-1;
}
.field-value {
@apply text-base text-gray-900;
}
.field-span {
grid-column: 1 / -1;
}
.flag-yes {
@apply text-red-700;
}
.flag-no {
@apply text-emerald-700;
}
.empty {
@apply text-center py-10 text-gray-500;
}
.empty .icon {
@apply text-3xl mb-2;
}
.empty .title {
@apply text-lg font-medium mb-1;
}
.empty .sub {
@apply text-sm;
}
</style>