Files
tyc-webview/src/views/Report.vue
2026-01-17 18:38:45 +08:00

1180 lines
54 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.

<script setup>
const featureMap = {
G09SC02: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CMarriage.vue")),
},
IDV044: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G09XM02: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "本人需求推测",
component: defineAsyncComponent(() =>
import("@/ui/CBankLoanApplication.vue")
),
},
G28BJ05: {
name: "借贷行为记录",
component: defineAsyncComponent(() =>
import("@/ui/CBankLoanBehavior.vue")
),
},
G26BJ05: {
name: "借贷违约失信",
component: defineAsyncComponent(() => import("@/ui/CSpecialList.vue")),
},
G34BJ03: {
name: "不良记录",
component: defineAsyncComponent(() => import("@/ui/CBad.vue")),
},
G35SC01: {
name: "司法涉诉",
component: defineAsyncComponent(() => import("@/ui/CLawsuit.vue")),
},
G22SC01: {
name: "司法涉诉",
component: defineAsyncComponent(() => import("@/ui/CLawsuitPP.vue")),
},
G05HZ01: {
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CRelatedEnterprises.vue")
),
},
Q23SC01: {
name: "企业涉诉",
component: defineAsyncComponent(() => import("@/ui/CLawsuit.vue")),
},
Q03SC01: {
name: "企业涉诉",
component: defineAsyncComponent(() => import("@/ui/CLawsuitPP.vue")),
},
G37SC01: {
name: "个人失信",
component: defineAsyncComponent(() =>
import("@/ui/CPersonalDiscredit.vue")
),
},
G36SC01: {
name: "个人限高",
component: defineAsyncComponent(() =>
import("@/ui/CPersonalConsumptionRestriction.vue")
),
},
G15BJ02: {
name: "手机三要素",
component: defineAsyncComponent(() =>
import("@/ui/CPhoneThreeElements.vue")
),
},
KZEYS: {
name: "身份证二要素",
component: defineAsyncComponent(() =>
import("@/ui/CIDCardTwoElements.vue")
),
},
G17BJ02: {
name: "手机号二要素",
component: defineAsyncComponent(() =>
import("@/ui/CPhoneTwoElements.vue")
),
},
G10XM02: {
name: "双人婚姻核验",
component: defineAsyncComponent(() => import("@/ui/CDualMarriage.vue")),
},
P_C_B332: {
name: "人车核验",
component: defineAsyncComponent(() => import("@/ui/CP_C_B332.vue")),
},
FIN019: {
name: "银行卡黑名单",
component: defineAsyncComponent(() => import("@/ui/CFIN019.vue")),
},
G20GZ01: {
name: "银行卡四要素核验",
component: defineAsyncComponent(() => import("@/ui/CG20GZ01.vue")),
},
G03HZ01: {
name: "手机号码风险",
component: defineAsyncComponent(() => import("@/ui/CG03HZ01.vue")),
},
G19BJ02: {
name: "手机二次卡",
component: defineAsyncComponent(() => import("@/ui/CG19BJ02.vue")),
},
G02BJ02: {
name: "手机在网时长",
component: defineAsyncComponent(() => import("@/ui/CG02BJ02.vue")),
},
CAR061: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CCAR061.vue")),
},
QCXG9P1C: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CQCXG9P1C.vue")),
},
COM187: {
name: "限制出境查询",
component: defineAsyncComponent(() => import("@/ui/CCOM187.vue")),
},
MOB035: {
name: "手机月消费档次",
component: defineAsyncComponent(() => import("@/ui/CMOB035.vue")),
},
RIS031: {
name: "反诈反赌风险核验",
component: defineAsyncComponent(() => import("@/ui/CRIS031.vue")),
},
PCB601: {
name: "手机号空号检测",
component: defineAsyncComponent(() => import("@/ui/CPCB601.vue")),
},
PCB148: {
name: "银行卡归属地查询",
component: defineAsyncComponent(() => import("@/ui/CPCB148.vue")),
},
FIN011: {
name: "银行卡姓名二要素验证",
component: defineAsyncComponent(() => import("@/ui/CFIN011.vue")),
},
FIN020: {
name: "银行卡身份证号二要素验证",
component: defineAsyncComponent(() => import("@/ui/CFIN020.vue")),
},
FIN018: {
name: "银行卡三要素综合验证",
component: defineAsyncComponent(() => import("@/ui/CFIN018.vue")),
},
MOB032: {
name: "高风险特殊手机号核验",
component: defineAsyncComponent(() => import("@/ui/CMOB032.vue")),
},
mobilelocal: {
name: "手机归属地查询",
component: defineAsyncComponent(() => import("@/ui/CMobileLocal.vue")),
},
sfz: {
name: "身份证归属地查询",
component: defineAsyncComponent(() => import("@/ui/CSFZ.vue")),
},
PCB915: {
name: "学历核验",
component: defineAsyncComponent(() =>
import("@/ui/CEducationVerification.vue")
),
},
CAR066: {
name: "车辆过户次数",
component: defineAsyncComponent(() => import("@/ui/CCAR066.vue")),
},
BehaviorRiskScan: {
name: "风险行为扫描",
component: defineAsyncComponent(() =>
import("@/ui/CBehaviorRiskScan.vue")
),
},
PersonEnterprisePro: {
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CPersonEnterprisePro/index.vue")
),
},
G29BJ05: {
name: "还款压力",
component: defineAsyncComponent(() => import("@/ui/CG29BJ05.vue")),
},
G11BJ06: {
name: "学历信息查询",
component: defineAsyncComponent(() => import("@/ui/CG11BJ06.vue")),
remark: "暂无学历信息记录可能是因为学历信息不公开、暂无高等教育学历(大专及以上学历)或学历较早未被数字化收录。",
},
FLXGDEA9: {
name: "本人不良",
component: defineAsyncComponent(() => import("@/ui/CFLXGDEA9.vue")),
},
IVYZ6G7H: {
name: "婚姻状态(补证版)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ6G7H.vue")),
},
IVYZ3A7F: {
name: "学历信息查询(含学校名称)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ3A7F.vue")),
},
YYSY7D3E: {
name: "携号转网查询",
component: defineAsyncComponent(() => import("@/ui/CYYSY7D3E.vue")),
},
IVYZ3P9M: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
},
QCGX1H7Y: {
name: "车辆过户详版",
component: defineAsyncComponent(() => import("@/ui/QCGX1H7Y.vue")),
},
};
import LEmpty from "@/components/LEmpty.vue";
import LPendding from "@/components/LPendding.vue";
import LTitle from "@/components/LTitle.vue";
const route = useRoute();
const productId = ref(null);
const isDone = ref(false);
const active = ref(null);
const reportData = ref([]);
const reportParams = ref({});
const reportName = ref("");
const reportDateTime = ref(null);
const orderId = ref(null);
const orderNo = ref("");
const isEmpty = ref(false);
const isPending = ref(false);
const reportScore = ref(0);
const queryState = ref("");
const pollingInterval = ref(null);
onMounted(() => {
const query = new URLSearchParams(window.location.search);
orderNo.value = query.get("out_trade_no");
orderId.value = query.get("order_id");
if (!orderNo.value && !orderId.value) {
orderId.value = route.query.orderId;
orderNo.value = route.query.orderNo;
}
if (!orderId.value && !orderNo.value) return;
getReport();
});
onBeforeUnmount(() => {
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
}
});
const getReport = async () => {
let queryUrl = "";
if (orderNo.value) {
queryUrl = `/query/orderNo/${orderNo.value}`;
} else if (orderId.value) {
queryUrl = `/query/orderId/${orderId.value}`;
} else {
return;
}
const { data, error } = await useApiFetch(queryUrl).get().json();
if (data.value && !error.value) {
if (data.value.code === 200) {
queryState.value = data.value.data.query_state;
if (queryState.value === "paid" || queryState.value === "success") {
reportData.value = data.value.data.query_data.sort((a, b) => {
return a.feature.sort - b.feature.sort;
});
productId.value = data.value.data.product_id;
reportParams.value = data.value.data.query_params;
reportName.value = data.value.data.product_name;
reportDateTime.value = data.value.data.create_time;
reportScore.value = calculateScore(reportData.value);
isDone.value = true;
console.log("reportData", reportData.value);
// 如果成功,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
} else if (queryState.value === "pending") {
// 如果是pending状态且没有轮询启动轮询
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport();
}, 1000); // 每1秒轮询一次
}
} else if (queryState.value === "failed") {
isEmpty.value = true;
isDone.value = true;
// 如果失败,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
} else if (queryState.value === "refunded") {
isEmpty.value = true;
isDone.value = true;
// 如果已退款,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
}
} else if (data.value.code === 200003) {
isEmpty.value = true;
isDone.value = true;
} else if (data.value.code === 200002) {
isPending.value = true;
isDone.value = true;
}
}
};
// 对请求参数进行脱敏处理
const maskValue = computed(() => {
return (type, value) => {
if (!value) return value;
if (type === "name") {
// 姓名脱敏(保留首位)
if (value.length === 1) {
return "*"; // 只保留一个字,返回 "*"
} else if (value.length === 2) {
return value[0] + "*"; // 两个字,保留姓氏,第二个字用 "*" 替代
} else {
return (
value[0] +
"*".repeat(value.length - 2) +
value[value.length - 1]
); // 两个字以上,保留第一个和最后一个字,其余的用 "*" 替代
}
} else if (type === "certificate_number") {
// 证书编号脱敏保留前4位和后4位中间用*替代)
if (value.length <= 8) {
return value.slice(0, 4) + "*".repeat(value.length - 4);
} else {
return (
value.slice(0, 4) +
"*".repeat(value.length - 8) +
value.slice(-4)
);
}
} else if (type === "id_card") {
// 身份证号脱敏保留前6位和最后4位
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
} else if (type === "mobile") {
if (value.length === 11) {
return value.substring(0, 3) + "****" + value.substring(7);
}
return value; // 如果手机号不合法或长度不为 11 位,直接返回原手机号
} else if (type === "bank_card") {
// 银行卡号脱敏保留前6位和后4位
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
} else if (type === "ent_name") {
// 企业名称脱敏保留前3个字符和后3个字符中间部分用 "*" 替代)
if (value.length <= 6) {
return value[0] + "*".repeat(value.length - 1); // 少于6个字符时只保留第一个字符其他用 * 替代
} else {
return (
value.slice(0, 3) +
"*".repeat(value.length - 6) +
value.slice(-3)
); // 多于6个字符时保留前3和后3
}
} else if (type === "ent_code") {
// 企业代码脱敏保留前4个字符和后4个字符中间部分用 "*" 替代)
if (value.length <= 8) {
return value.slice(0, 4) + "*".repeat(value.length - 4); // 长度不超过8时保留前4个字符其他用 * 替代
} else {
return (
value.slice(0, 4) +
"*".repeat(value.length - 8) +
value.slice(-4)
); // 长度超过8时保留前4个字符和后4个字符
}
} else if (type === "car_license") {
// 车牌号脱敏保留前2个字符后2个字符其他部分用 "*" 替代)
if (value.length <= 4) {
return value[0] + "*".repeat(value.length - 1); // 如果车牌号长度小于等于4只保留首字符
} else {
// 如果车牌号较长保留前2个字符后2个字符其余部分用 "*" 替代
return (
value.slice(0, 2) +
"*".repeat(value.length - 4) +
value.slice(-2)
);
}
} else if (type === "vin_code") {
// 车架号脱敏保留前6位和后4位中间用*替代)
if (value.length <= 10) {
return value.slice(0, 6) + "*".repeat(value.length - 6);
} else {
return (
value.slice(0, 6) +
"*".repeat(value.length - 10) +
value.slice(-4)
);
}
}
return value;
};
});
// 计算综合评分的函数
const calculateScore = (reportData) => {
// 从0分开始0分表示无风险
let score = 0;
// 最高分为90分90分表示最高风险
const maxScore = 90;
// 定义各接口的相对风险权重比例
const relativeWeights = {
// 关键风险指标(高优先级)
G34BJ03: 250, // 不良记录
G26BJ05: 100, // 违约异常
G22SC01: 400, // 司法涉诉
G35SC01: 20, // 司法涉诉(次要)
Q23SC01: 50, // 企业涉诉
FIN019: 100, // 银行卡黑名单
// 高风险指标(中优先级)
G27BJ05: 40, // 本人需求推测
G28BJ05: 40, // 借贷行为记录
G03HZ01: 70, // 手机号码风险
// 中风险指标(低优先级)
G19BJ02: 50, // 手机二次卡
G02BJ02: 50, // 手机在网时长
G05HZ01: 50, // 名下企业关联
// 验证指标(最低优先级)
G15BJ02: 25, // 手机三要素
G17BJ02: 25, // 手机号二要素
KZEYS: 25, // 身份证二要素
G20GZ01: 25, // 银行卡四要素核验
};
// 找出当前报告中包含的接口
const availableAPIs = reportData
.map((item) => item.data.apiID)
.filter((id) => relativeWeights[id]);
// 如果没有可评分的接口,返回默认分数
if (availableAPIs.length === 0) return 30; // 默认30分中等风险
// 计算当前报告中所有接口的相对权重总和
let totalWeight = 0;
availableAPIs.forEach((apiID) => {
totalWeight += relativeWeights[apiID];
});
// 计算每个权重点对应的分数
const pointValue = maxScore / totalWeight;
// 基于当前报告中的接口计算实际权重
const actualWeights = {};
availableAPIs.forEach((apiID) => {
// 将相对权重转换为实际分数权重
actualWeights[apiID] = relativeWeights[apiID] * pointValue;
});
// 遍历报告数据进行评分 - 风险越高分数越高
reportData.forEach((item) => {
const apiID = item.data.apiID;
const data = item.data.data;
// 如果没有定义权重,跳过
if (!actualWeights[apiID]) return;
// 根据不同的API ID计算分数有风险时加分
switch (apiID) {
case "G09SC02": // 婚姻状态
// 不计入风险
break;
case "G27BJ05": // 本人需求推测
if (data) {
// 检查是否有申请记录(有则表示风险)
let hasRisk = false;
for (const key in data) {
if (
data[key] !== 0 &&
data[key] !== "0" &&
key.indexOf("allnum") > -1 &&
!isNaN(parseInt(data[key])) &&
parseInt(data[key]) > 0
) {
hasRisk = true;
break;
}
}
if (hasRisk) {
score += actualWeights[apiID];
}
}
break;
case "G28BJ05": // 借贷行为记录
if (data) {
// 检查是否有借贷记录(有则表示风险)
let hasRisk = false;
for (const key in data) {
if (
data[key] !== 0 &&
data[key] !== "0" &&
(key.indexOf("lendamt") > -1 ||
key.indexOf("num") > -1) &&
!isNaN(parseInt(data[key])) &&
parseInt(data[key]) > 0
) {
hasRisk = true;
break;
}
}
if (hasRisk) {
score += actualWeights[apiID];
}
}
break;
case "G26BJ05": // 违约异常
if (data) {
// 检查除特定字段外的其他字段是否有异常值(有异常则表示风险)
const excludeFields = [
"swift_number",
"code",
"flag_specialList_c",
];
let hasRisk = false;
for (const key in data) {
if (
!excludeFields.includes(key) &&
data[key] !== 0 &&
data[key] !== "0"
) {
hasRisk = true;
break;
}
}
if (hasRisk) {
score += actualWeights[apiID];
}
}
break;
case "G34BJ03": // 不良记录
if (data && data.risk_level) {
// 根据风险等级加分
switch (data.risk_level) {
case "A": // 无风险
// 不加分
break;
case "F": // 低风险
score += actualWeights[apiID] * 0.3;
break;
case "C": // 中风险
case "D": // 中风险
score += actualWeights[apiID] * 0.7;
break;
case "B": // 高风险
case "E": // 高风险
score += actualWeights[apiID];
break;
}
}
break;
case "G35SC01": // 司法涉诉
case "G22SC01": // 司法涉诉
case "Q23SC01": // 企业涉诉
if (data) {
let hasRisk = false;
// 检查各种涉诉信息 - 处理嵌套数据结构
// entout是一个单元素数组数组中第一个元素是JSON对象对象中有entout属性
if (
data.entout &&
Array.isArray(data.entout) &&
data.entout.length > 0 &&
data.entout[0] &&
data.entout[0].entout &&
((Array.isArray(data.entout[0].entout) &&
data.entout[0].entout.length > 0) ||
(typeof data.entout[0].entout === "object" &&
Object.keys(data.entout[0].entout).length > 0))
) {
hasRisk = true;
}
// 处理sxbzxr(失信被执行人)嵌套结构
if (
data.sxbzxr &&
Array.isArray(data.sxbzxr) &&
data.sxbzxr.length > 0 &&
data.sxbzxr[0] &&
data.sxbzxr[0].sxbzxr &&
((Array.isArray(data.sxbzxr[0].sxbzxr) &&
data.sxbzxr[0].sxbzxr.length > 0) ||
(typeof data.sxbzxr[0].sxbzxr === "object" &&
Object.keys(data.sxbzxr[0].sxbzxr).length > 0))
) {
hasRisk = true;
}
// 处理xgbzxr(限制高消费被执行人)嵌套结构
if (
data.xgbzxr &&
Array.isArray(data.xgbzxr) &&
data.xgbzxr.length > 0 &&
data.xgbzxr[0] &&
data.xgbzxr[0].xgbzxr &&
((Array.isArray(data.xgbzxr[0].xgbzxr) &&
data.xgbzxr[0].xgbzxr.length > 0) ||
(typeof data.xgbzxr[0].xgbzxr === "object" &&
Object.keys(data.xgbzxr[0].xgbzxr).length > 0))
) {
hasRisk = true;
}
if (hasRisk) {
score += actualWeights[apiID];
}
}
break;
case "G03HZ01": // 手机号码风险
if (data && data.filterType) {
// 根据filterType判断风险等级
switch (data.filterType) {
case "0": // 安全
// 不加分
break;
case "3": // 低危
score += actualWeights[apiID] * 0.3;
break;
case "2": // 中危
score += actualWeights[apiID] * 0.7;
break;
case "1": // 高危
score += actualWeights[apiID];
break;
}
}
break;
case "G19BJ02": // 手机二次卡
if (data && data.is_second_card === true) {
score += actualWeights[apiID];
}
break;
case "G02BJ02": // 手机在网时长
if (data && data.online_months < 6) {
score += actualWeights[apiID];
}
break;
case "G15BJ02": // 手机三要素
case "G17BJ02": // 手机号二要素
case "KZEYS": // 身份证二要素
case "G20GZ01": // 银行卡四要素核验
if (data && data.is_consistent === false) {
score += actualWeights[apiID];
}
break;
case "FIN019": // 银行卡黑名单
if (data && data.is_blacklisted === true) {
score += actualWeights[apiID];
}
break;
default:
// 未知接口类型不影响评分
break;
}
});
// 确保分数在0-90范围内并四舍五入
return Math.max(0, Math.min(maxScore, Math.round(score)));
};
</script>
<template>
<div v-if="queryState === 'pending'" class="loading-container">
<div class="loading-spinner"></div>
<p>报告生成中请稍候...</p>
</div>
<div v-else-if="queryState === 'failed' || queryState === 'refunded'" class="p-4">
<LEmpty />
</div>
<div v-else-if="queryState === 'paid' || queryState === 'success'"
class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<template v-if="isDone">
<!-- 当reportData.length > 1时使用van-tabs -->
<van-tabs v-if="reportData.length > 1" v-model:active="active" scrollspy sticky :offset-top="46">
<div class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<LPendding v-if="isPending" />
<template v-if="!isEmpty && !isPending">
<van-tab title="分析指数">
<div id="overdiv" class="title mb-4">分析指数</div>
<div class="card mb-4">
<div class="my-4">
<GaugeChart :score="reportScore" />
</div>
</div>
</van-tab>
<van-tab title="基本信息">
<div id="overdiv" class="title mb-4">基本信息</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<LTitle title="报告信息" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div class="flex justify-between border-b pb-2 pl-2">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">{{
reportDateTime
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="!isEmpty">
<span class="text-gray-700 font-bold">报告项目</span>
<span class="text-gray-600">
{{ reportName }}</span>
</div>
</div>
<template v-if="
Object.keys(reportParams).length !=
0
">
<LTitle title="报告对象" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.name">
<span class="text-gray-700 font-bold">姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.name
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.id_card">
<span class="text-gray-700 font-bold">身份证号</span>
<span class="text-gray-600">
{{
maskValue(
"id_card",
reportParams?.id_card
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.nameMan">
<span class="text-gray-700 font-bold">男方姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.nameMan
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.idCardMan">
<span class="text-gray-700 font-bold">男方身份证号</span>
<span class="text-gray-600">{{
maskValue(
"id_card",
reportParams?.idCardMan
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.nameWoman">
<span class="text-gray-700 font-bold">女方姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.nameWoman
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.idCardWoman">
<span class="text-gray-700 font-bold">女方身份证号</span>
<span class="text-gray-600">{{
maskValue(
"id_card",
reportParams?.idCardWoman
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.bank_card">
<span class="text-gray-700 font-bold">银行卡号</span>
<span class="text-gray-600">{{
maskValue(
"bank_card",
reportParams?.bank_card
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.mobile">
<span class="text-gray-700 font-bold">手机号</span>
<span class="text-gray-600">{{
maskValue(
"mobile",
reportParams?.mobile
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="
reportParams?.verification_code
">
<span class="text-gray-700 font-bold">验证码</span>
<span class="text-gray-600">{{
maskValue(
"code",
reportParams?.verification_code
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.car_license">
<span class="text-gray-700 font-bold">车牌号</span>
<span class="text-gray-600">{{
maskValue(
"car_license",
reportParams?.car_license
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.ent_name">
<span class="text-gray-700 font-bold">企业名称</span>
<span class="text-gray-600">{{
maskValue(
"ent_name",
reportParams?.ent_name
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.ent_code">
<span class="text-gray-700 font-bold">企业代码</span>
<span class="text-gray-600">{{
maskValue(
"ent_code",
reportParams?.ent_code
)
}}</span>
</div>
<div class="flex flex-col gap-4">
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
</van-tab>
<van-tab v-for="(item, index) in reportData" :key="index"
:title="featureMap[item.data.apiID]?.name">
<div id="lawsuit" class="title mb-4">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
">
</component>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</van-tab>
</template>
</div>
</van-tabs>
<!-- 当reportData.length <= 1时不使用tabs直接展示内容 -->
<div v-else class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<LPendding v-if="isPending" />
<template v-if="!isEmpty && !isPending">
<div id="overdiv" class="title">报告概述</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<LTitle title="报告信息" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div class="flex justify-between border-b pb-2 pl-2">
<span class="text-gray-700 font-bold">报告时间:</span>
<span class="text-gray-600">{{
reportDateTime
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="!isEmpty">
<span class="text-gray-700 font-bold">报告项目:</span>
<span class="text-gray-600">
{{ reportName }}</span>
</div>
</div>
<template v-if="Object.keys(reportParams).length != 0">
<LTitle title="报告对象" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.name">
<span class="text-gray-700 font-bold">姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.name
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.id_card">
<span class="text-gray-700 font-bold">身份证号</span>
<span class="text-gray-600">
{{
maskValue(
"id_card",
reportParams?.id_card
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.nameMan">
<span class="text-gray-700 font-bold">男方姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.nameMan
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.idCardMan">
<span class="text-gray-700 font-bold">男方身份证号</span>
<span class="text-gray-600">{{
maskValue(
"id_card",
reportParams?.idCardMan
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.nameWoman">
<span class="text-gray-700 font-bold">女方姓名</span>
<span class="text-gray-600">{{
maskValue(
"name",
reportParams?.nameWoman
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.idCardWoman">
<span class="text-gray-700 font-bold">女方身份证号</span>
<span class="text-gray-600">{{
maskValue(
"id_card",
reportParams?.idCardWoman
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.bank_card">
<span class="text-gray-700 font-bold">银行卡号</span>
<span class="text-gray-600">{{
maskValue(
"bank_card",
reportParams?.bank_card
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.mobile">
<span class="text-gray-700 font-bold">手机号</span>
<span class="text-gray-600">{{
maskValue(
"mobile",
reportParams?.mobile
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.verification_code">
<span class="text-gray-700 font-bold">验证码</span>
<span class="text-gray-600">{{
maskValue(
"code",
reportParams?.verification_code
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.car_license">
<span class="text-gray-700 font-bold">车牌号</span>
<span class="text-gray-600">{{
maskValue(
"car_license",
reportParams?.car_license
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_name">
<span class="text-gray-700 font-bold">企业名称</span>
<span class="text-gray-600">{{
maskValue(
"ent_name",
reportParams?.ent_name
)
}}</span>
</div>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_code">
<span class="text-gray-700 font-bold">企业代码</span>
<span class="text-gray-600">{{
maskValue(
"ent_code",
reportParams?.ent_code
)
}}</span>
</div>
<div class="flex flex-col gap-4">
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
<!-- 显示报告数据 -->
<template v-for="(item, index) in reportData" :key="index">
<div id="lawsuit" class="title">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
">
</component>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</template>
</template>
</div>
<!-- 报告说明部分,无论哪种展示模式都需要 -->
<div class="p-4 -mt-4">
<div class="card">
<div>
<div class="text-bold text-blue-500 mb-2">报告说明</div>
<div>
&nbsp;
&nbsp;本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
</div>
<p>
&nbsp; &nbsp; 报告有效期<strong class="text-red-500">15天</strong>,过期自动删除。
</p>
<p>
&nbsp; &nbsp;
若您的数据不全面,可能是数据具有延迟性或者合作信息机构未获取到您的数据。若数据有错误请联系客服
</p>
<p>
&nbsp;
&nbsp;本产品所有数据均来自第三方。可能部分数据未公开、数据更新延迟或信息受到限制,贵司不对数据的准确性、真实性、完整性做任何承诺。用户需根据实际情况,结合报告内容自行判断与决策。
</p>
</div>
</div>
</div>
</template>
</div>
<div class="disclaimer">
<div class="flex flex-col items-center">
<div class="flex items-center">
<img class="w-4 h-4 mr-2" src="@/assets/images/public_security_record_icon.png" alt="公安备案" />
<text>桂公网安备45010002451084号</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
桂ICP备2024038462号
</a>
</div>
</div>
<div>广西福铭网络科技有限公司版权所有</div>
</div>
</template>
<style lang="scss" scoped>
.title {
@apply mx-auto mt-2 w-64 border rounded-3xl bg-gradient-to-r from-blue-400 via-green-500 to-teal-500 py-2 text-center text-white font-bold;
}
.a {
color: #e03131;
}
.disclaimer {
/* margin-top: 24px; */
padding: 10px;
font-size: 12px;
color: #999;
text-align: center;
border-top: 1px solid #e0e0e0;
padding-bottom: 60px;
background: #ffffff;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
p {
color: #666;
font-size: 16px;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>