Files
report_viewer/src/ui/CJRZQ0B6Y.vue
2026-05-13 11:01:42 +08:00

236 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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">
<h3 class="header-title">银行卡黑名单(实时)</h3>
<p class="header-desc">查询银行卡是否命中各类黑名单/风险名单</p>
</div>
<div v-if="hasData" class="result-section">
<div class="risk-summary" :class="summaryClass">
<span class="risk-label">综合结果</span>
<span class="risk-value">
{{ summaryText }}
</span>
</div>
<div class="risk-tags">
<div v-for="item in riskItems" :key="item.key" class="risk-item" :class="item.hit ? 'hit' : 'normal'">
<div class="risk-item-title">{{ item.label }}</div>
<div class="risk-item-value">
{{ item.hit ? '命中' : '未命中' }}
</div>
</div>
</div>
</div>
<div v-if="hasParams" class="info-block">
<div class="block-title">被核验信息</div>
<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">{{ maskedIdCard }}</span>
</div>
<div class="info-row">
<span class="info-label">银行卡号</span>
<span class="info-value font-mono">{{ maskedBankCard }}</span>
</div>
</div>
<div v-if="!hasData" class="empty-tip">暂无核验结果</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
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 hasData = computed(() => props.data && Object.keys(props.data).length > 0);
const riskItems = computed(() => {
const d = props.data || {};
const toBool = (v) => v === '1' || v === 1;
return [
{ key: 'badCardHolder', label: '不良持卡人', hit: toBool(d.badCardHolder) },
{ key: 'caseRelated', label: '涉案卡片', hit: toBool(d.caseRelated) },
{ key: 'fraudTrans', label: '交易欺诈卡片', hit: toBool(d.fraudTrans) },
{ key: 'offlineBlack', label: '线下卡号黑名单', hit: toBool(d.offlineBlack) },
{ key: 'onlineBlack', label: '线上卡号黑名单', hit: toBool(d.onlineBlack) },
{ key: 'otherBlack', label: '其他卡号黑名单', hit: toBool(d.otherBlack) },
];
});
const anyHit = computed(() => riskItems.value.some((i) => i.hit));
const summaryText = computed(() => {
if (!hasData.value) return '暂无结果';
if (!anyHit.value) return '未命中任何银行卡黑名单';
return '存在银行卡黑名单或风险记录';
});
const summaryClass = computed(() => {
if (!hasData.value) return 'summary unknown';
if (anyHit.value) return 'summary bad';
return 'summary ok';
});
const maskedName = computed(() => {
const name = props.params?.name || '';
if (!name) return '-';
return name.length > 1 ? name[0] + '*'.repeat(name.length - 1) : '*';
});
const maskedIdCard = computed(() => {
const id = props.params?.id_card || '';
if (!id || id.length < 8) return id || '-';
return id.slice(0, 4) + '********' + id.slice(-4);
});
const maskedBankCard = computed(() => {
const card = props.params?.bank_card || '';
if (!card || card.length < 8) return card || '-';
return card.slice(0, 4) + '********' + card.slice(-4);
});
const hasParams = computed(() => {
const p = props.params || {};
return p.name || p.id_card || p.bank_card;
});
</script>
<style scoped>
.card {
padding: 1rem;
}
.header-box {
margin-bottom: 1rem;
}
.header-title {
font-size: 1.125rem;
font-weight: 600;
}
.header-desc {
font-size: 0.875rem;
color: #6b7280;
margin-top: 0.25rem;
}
.result-section {
padding: 0.75rem 0.875rem;
border-radius: 0.75rem;
margin-bottom: 1rem;
border: 1px solid #e5e7eb;
background: #f9fafb;
}
.risk-summary {
font-size: 0.95rem;
margin-bottom: 0.5rem;
}
.summary.ok {
background: #ecfdf3;
border-color: #22c55e33;
}
.summary.bad {
background: #fef2f2;
border-color: #ef444433;
}
.summary.unknown {
background: #f9fafb;
}
.risk-label {
color: #6b7280;
}
.risk-value {
font-weight: 600;
color: #111827;
}
.risk-tags {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5rem;
}
.risk-item {
border-radius: 0.5rem;
padding: 0.5rem 0.6rem;
font-size: 0.8rem;
}
.risk-item.hit {
background: #fef2f2;
border: 1px solid #ef4444;
color: #b91c1c;
}
.risk-item.normal {
background: #ecfdf3;
border: 1px solid #22c55e33;
color: #166534;
}
.risk-item-title {
margin-bottom: 0.15rem;
}
.risk-item-value {
font-weight: 600;
}
.info-block {
margin-top: 1rem;
padding: 0.75rem 0.875rem;
border-radius: 0.75rem;
background: #f9fafb;
}
.block-title {
font-size: 0.875rem;
font-weight: 600;
color: #374151;
margin-bottom: 0.5rem;
}
.info-row {
display: flex;
justify-content: space-between;
font-size: 0.875rem;
padding: 0.15rem 0;
}
.info-label {
color: #6b7280;
}
.info-value {
color: #111827;
margin-left: 1rem;
text-align: right;
}
.empty-tip {
color: #9ca3af;
font-size: 0.875rem;
padding: 1rem 0;
text-align: center;
}
</style>