251 lines
6.5 KiB
Vue
251 lines
6.5 KiB
Vue
<template>
|
||
<div class="card">
|
||
<div class="header-box">
|
||
<h3 class="header-title">人车核验(详版)</h3>
|
||
<p class="header-desc">展示人员与车辆的详细匹配结果及相关说明</p>
|
||
</div>
|
||
|
||
<div class="result-section" :class="resultSectionClass">
|
||
<div class="result-icon-wrap">
|
||
<span class="result-icon" :class="iconClass">
|
||
{{ iconChar }}
|
||
</span>
|
||
</div>
|
||
<div class="result-label">认证结果</div>
|
||
<div class="result-value" :class="resultTextClass">{{ resultText }}</div>
|
||
<p v-if="resultDesc" class="result-desc">{{ resultDesc }}</p>
|
||
</div>
|
||
|
||
<div v-if="hasParams" class="info-rows">
|
||
<div class="info-row">
|
||
<span class="info-label">姓名</span>
|
||
<span class="info-value">{{ maskedName }}</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">车牌号</span>
|
||
<span class="info-value font-mono">{{ params?.plate_no || params?.car_license || '-' }}</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">号牌类型</span>
|
||
<span class="info-value">{{ params?.carplate_type || params?.car_type || '-' }}</span>
|
||
</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 maskedName = computed(() => {
|
||
const name = props.params?.name || '';
|
||
if (!name) return '-';
|
||
return name.length > 1 ? name[0] + '*'.repeat(name.length - 1) : '*';
|
||
});
|
||
|
||
// status: 0 一致, -1 不一致, -2 非法姓名, -4 无记录
|
||
const status = computed(() => {
|
||
const s = props.data?.status;
|
||
if (s === 0 || s === -1 || s === -2 || s === -4) return s;
|
||
return null;
|
||
});
|
||
|
||
const resultText = computed(() => {
|
||
const s = status.value;
|
||
if (s === 0) return '一致';
|
||
if (s === -1) return '不一致';
|
||
if (s === -2) return '非法姓名';
|
||
if (s === -4) return '无记录';
|
||
return '暂无结果';
|
||
});
|
||
|
||
const resultDesc = computed(() => {
|
||
const s = status.value;
|
||
if (s === -2) return '姓名长度或格式不正确,请核对后重试';
|
||
if (s === -4) return '未查询到相关核验记录';
|
||
return '';
|
||
});
|
||
|
||
const resultTextClass = computed(() => {
|
||
const s = status.value;
|
||
if (s === 0) return 'result-match';
|
||
if (s === -1) return 'result-mismatch';
|
||
if (s === -2) return 'result-invalid';
|
||
if (s === -4) return 'result-norecord';
|
||
return 'result-unknown';
|
||
});
|
||
|
||
const resultSectionClass = computed(() => {
|
||
const s = status.value;
|
||
if (s === 0) return 'result-section match';
|
||
if (s === -1) return 'result-section mismatch';
|
||
if (s === -2) return 'result-section invalid';
|
||
if (s === -4) return 'result-section norecord';
|
||
return 'result-section unknown';
|
||
});
|
||
|
||
const iconClass = computed(() => {
|
||
const s = status.value;
|
||
if (s === 0) return 'icon-match';
|
||
if (s === -1) return 'icon-mismatch';
|
||
if (s === -2) return 'icon-invalid';
|
||
if (s === -4) return 'icon-norecord';
|
||
return 'icon-unknown';
|
||
});
|
||
|
||
const iconChar = computed(() => {
|
||
const s = status.value;
|
||
if (s === 0) return '✓';
|
||
if (s === -1) return '✕';
|
||
if (s === -2) return '!';
|
||
if (s === -4) return '—';
|
||
return '?';
|
||
});
|
||
|
||
const hasParams = computed(() => {
|
||
const p = props.params || {};
|
||
return p.name || p.plate_no || p.car_license || p.carplate_type || p.car_type;
|
||
});
|
||
|
||
const riskScore = computed(() => 100);
|
||
useRiskNotifier(props, riskScore);
|
||
defineExpose({ riskScore });
|
||
</script>
|
||
|
||
<style scoped>
|
||
.card {
|
||
@apply bg-white rounded-lg p-4 shadow-sm border border-gray-100;
|
||
}
|
||
|
||
.header-box {
|
||
@apply rounded-lg mb-4 p-4;
|
||
background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);
|
||
color: #fff;
|
||
}
|
||
|
||
.header-title {
|
||
@apply text-lg font-semibold m-0;
|
||
}
|
||
|
||
.header-desc {
|
||
@apply text-sm mt-1 opacity-90 m-0;
|
||
}
|
||
|
||
.result-section {
|
||
@apply rounded-xl p-5 text-center mb-4;
|
||
}
|
||
|
||
.result-section.match {
|
||
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
|
||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||
}
|
||
|
||
.result-section.mismatch {
|
||
background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%);
|
||
border: 1px solid rgba(244, 67, 54, 0.3);
|
||
}
|
||
|
||
.result-section.invalid {
|
||
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
|
||
border: 1px solid rgba(255, 152, 0, 0.4);
|
||
}
|
||
|
||
.result-section.norecord {
|
||
background: linear-gradient(135deg, #eceff1 0%, #cfd8dc 100%);
|
||
border: 1px solid rgba(96, 125, 139, 0.3);
|
||
}
|
||
|
||
.result-section.unknown {
|
||
@apply bg-gray-50 border border-gray-200;
|
||
}
|
||
|
||
.result-icon-wrap {
|
||
@apply mb-2;
|
||
}
|
||
|
||
.result-icon {
|
||
@apply inline-flex items-center justify-center w-12 h-12 rounded-full text-2xl font-bold text-white;
|
||
}
|
||
|
||
.result-icon.icon-match {
|
||
background: linear-gradient(135deg, #43a047 0%, #2e7d32 100%);
|
||
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.4);
|
||
}
|
||
|
||
.result-icon.icon-mismatch {
|
||
background: linear-gradient(135deg, #e53935 0%, #c62828 100%);
|
||
box-shadow: 0 2px 8px rgba(244, 67, 54, 0.4);
|
||
}
|
||
|
||
.result-icon.icon-invalid {
|
||
background: linear-gradient(135deg, #fb8c00 0%, #ef6c00 100%);
|
||
box-shadow: 0 2px 8px rgba(255, 152, 0, 0.4);
|
||
}
|
||
|
||
.result-icon.icon-norecord {
|
||
background: linear-gradient(135deg, #78909c 0%, #546e7a 100%);
|
||
box-shadow: 0 2px 8px rgba(96, 125, 139, 0.3);
|
||
}
|
||
|
||
.result-icon.icon-unknown {
|
||
background: linear-gradient(135deg, #78909c 0%, #546e7a 100%);
|
||
box-shadow: 0 2px 8px rgba(96, 125, 139, 0.3);
|
||
}
|
||
|
||
.result-label {
|
||
@apply text-sm text-gray-500 mb-1;
|
||
}
|
||
|
||
.result-value {
|
||
@apply text-xl font-semibold;
|
||
}
|
||
|
||
.result-desc {
|
||
@apply text-sm mt-2 m-0 text-gray-600 max-w-xs mx-auto;
|
||
}
|
||
|
||
.result-match {
|
||
color: #2e7d32;
|
||
}
|
||
|
||
.result-mismatch {
|
||
color: #c62828;
|
||
}
|
||
|
||
.result-invalid {
|
||
color: #e65100;
|
||
}
|
||
|
||
.result-norecord {
|
||
color: #546e7a;
|
||
}
|
||
|
||
.result-unknown {
|
||
@apply text-gray-500;
|
||
}
|
||
|
||
.info-rows {
|
||
@apply space-y-3 pt-2 border-t border-gray-100;
|
||
}
|
||
|
||
.info-row {
|
||
@apply flex items-center text-sm;
|
||
}
|
||
|
||
.info-label {
|
||
@apply w-20 text-gray-500 shrink-0;
|
||
}
|
||
|
||
.info-value {
|
||
@apply font-medium text-gray-800;
|
||
}
|
||
</style>
|