Files
tyc-webview-v2/src/components/BaseReport.vue
2026-03-21 11:04:05 +08:00

956 lines
40 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>
import ShareReportButton from "./ShareReportButton.vue";
import TitleBanner from "./TitleBanner.vue";
import VerificationCard from "./VerificationCard.vue";
import StyledTabs from "./StyledTabs.vue";
import { splitDWBG8B4DForTabs } from '@/ui/CDWBG8B4D/utils/simpleSplitter.js';
import { splitDWBG6A2CForTabs } from '@/ui/DWBG6A2C/utils/simpleSplitter.js';
import { splitCJRZQ5E9FForTabs } from '@/ui/CJRZQ5E9F/utils/simpleSplitter.js';
import { splitCQYGL3F8EForTabs } from '@/ui/CQYGL3F8E/utils/simpleSplitter.js';
// 动态导入产品背景图片的函数
const loadProductBackground = async (productType) => {
try {
switch (productType) {
case 'companyinfo':
return (await import("@/assets/images/report/xwqy_report_bg.jpg")).default;
case 'preloanbackgroundcheck':
return (await import("@/assets/images/report/dqfx_report_bg.jpg")).default;
case 'personalData':
return (await import("@/assets/images/report/grdsj_report_bg.jpg")).default;
case 'marriage':
return (await import("@/assets/images/report/marriage_report_bg.jpg")).default;
case 'homeservice':
return (await import("@/assets/images/report/homeservice_report_bg.jpg")).default;
case 'backgroundcheck':
return (await import("@/assets/images/report/backgroundcheck_report_bg.png")).default;
default:
return null;
}
} catch (error) {
console.warn(`Failed to load background image for ${productType}:`, error);
return null;
}
};
const props = defineProps({
isShare: {
type: Boolean,
default: false,
},
orderId: {
type: String,
required: false,
default: "",
},
orderNo: {
type: String,
default: "",
},
feature: {
type: String,
required: true,
},
reportData: {
type: Array,
required: true,
},
reportParams: {
type: Object,
required: true,
},
reportName: {
type: String,
required: true,
},
reportDateTime: {
type: [String, null],
required: false,
default: null,
},
isEmpty: {
type: Boolean,
required: true,
},
isDone: {
type: Boolean,
required: true,
},
isExample: {
type: Boolean,
default: false,
},
});
// 使用toRefs将props转换为组件内的ref
const {
feature,
reportData,
reportParams,
reportName,
reportDateTime,
isEmpty,
isDone,
isExample,
} = toRefs(props);
const active = ref(null);
const backgroundContainerRef = ref(null); // 背景容器的引用
const reportScore = ref(0); // 默认分数
const productBackground = ref('');
const backgroundHeight = ref(0);
const imageAspectRatio = ref(0); // 缓存图片宽高比
const MAX_BACKGROUND_HEIGHT = 211; // 最大背景高度,防止图片过高变形
const trapezoidBgImage = ref(''); // 牌匾背景图片
// 计算背景高度
const calculateBackgroundHeight = () => {
if (imageAspectRatio.value > 0) {
// 获取容器的实际宽度,而不是整个窗口宽度
const containerWidth = backgroundContainerRef.value
? backgroundContainerRef.value.offsetWidth
: window.innerWidth;
const calculatedHeight = containerWidth * imageAspectRatio.value;
// 限制最大高度,防止图片过高
backgroundHeight.value = Math.min(calculatedHeight, MAX_BACKGROUND_HEIGHT);
}
};
// 加载背景图片并计算高度
const loadBackgroundImage = async () => {
const background = await loadProductBackground(feature.value);
productBackground.value = background || '';
// 加载图片后计算高度
if (background) {
const img = new Image();
img.onload = () => {
// 缓存图片宽高比
imageAspectRatio.value = img.height / img.width;
// 图片加载完成后,等待下一帧再计算高度,确保容器已渲染
nextTick(() => {
calculateBackgroundHeight();
});
};
img.src = background;
}
};
// 防抖定时器
let resizeTimer = null;
// 在组件挂载时加载背景图
onMounted(async () => {
console.log("isExample", isExample.value);
await loadBackgroundImage();
await loadTrapezoidBackground();
// 监听窗口大小变化,重新计算高度
window.addEventListener('resize', handleResize);
});
// 处理窗口大小变化(带防抖)
const handleResize = () => {
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(() => {
calculateBackgroundHeight();
}, 100); // 100ms 防抖延迟
};
// 组件卸载时移除监听器
onUnmounted(() => {
if (resizeTimer) {
clearTimeout(resizeTimer);
}
window.removeEventListener('resize', handleResize);
});
// 处理数据拆分支持DWBG8B4D、DWBG6A2C、CJRZQ5E9F和CQYGL3F8E
const processedReportData = computed(() => {
let data = reportData.value;
// 拆分DWBG8B4D数据
data = splitDWBG8B4DForTabs(data);
// 拆分DWBG6A2C数据
data = splitDWBG6A2CForTabs(data);
// // 拆分CJRZQ5E9F数据
// data = splitCJRZQ5E9FForTabs(data);
// 拆分CQYGL3F8E数据
data = splitCQYGL3F8EForTabs(data);
// 过滤掉在featureMap中没有对应的项
return data.filter(item => featureMap[item.data.apiID]);
});
// 获取产品背景图片
const getProductBackground = computed(() => productBackground.value);
// 背景图片容器样式
const backgroundContainerStyle = computed(() => {
if (backgroundHeight.value > 0) {
return {
height: `${backgroundHeight.value}px`,
};
}
return {
height: '180px', // 默认高度
};
});
// 判断是否有背景图
const hasBackgroundImage = computed(() => {
return !!getProductBackground.value;
});
// 背景图片样式
const backgroundImageStyle = computed(() => {
if (getProductBackground.value) {
return {
backgroundImage: `url(${getProductBackground.value})`,
backgroundSize: '100% auto', // 宽度100%,高度自动保持比例
backgroundPosition: 'center top',
backgroundRepeat: 'no-repeat',
overflow: 'hidden', // 超出部分裁剪
};
}
return {};
});
// 动态加载牌匾背景图片
const loadTrapezoidBackground = async () => {
try {
const bgModule = await import("@/assets/images/report/title_inquire_bg.png");
trapezoidBgImage.value = bgModule.default;
} catch (error) {
console.warn(`Failed to load trapezoid background image:`, error);
}
};
// 牌匾背景图片样式
const trapezoidBgStyle = computed(() => {
if (trapezoidBgImage.value) {
return {
backgroundImage: `url(${trapezoidBgImage.value})`,
};
}
return {};
});
const featureMap = {
IVYZ5733: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIVYZ5733.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
IVYZ81NC: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIVYZ81NC.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
JRZQ0A03: {
name: "借贷申请记录",
component: defineAsyncComponent(() =>
import("@/ui/CJRZQ0A03.vue")
),
},
JRZQ8203: {
name: "借贷行为记录",
component: defineAsyncComponent(() =>
import("@/ui/CJRZQ8203.vue")
),
},
FLXG3D56: {
name: "违约失信",
component: defineAsyncComponent(() => import("@/ui/CFLXG3D56.vue")),
},
FLXG3A9B: {
name: "限高被执行人",
component: defineAsyncComponent(() => import("@/ui/CFLX3A9B.vue")),
remark: '限高被执行人模块展示法院公布的限制高消费记录,并同时提示历史失信记录,帮助识别严重履约风险。'
},
FLXG7E8F: {
name: "司法涉诉",
component: defineAsyncComponent(() =>
import("@/ui/FLXG7E8F/index.vue")
),
remark: '司法涉诉风险展示申请人相关的诉讼情况,包括民事诉讼、刑事诉讼、行政诉讼、执行案件、失信被执行人、限制消费等。数据来源于各级法院的公开判决书和法官网等权威渠道。'
},
FLXG0V4B: {
name: "司法涉诉",
component: defineAsyncComponent(() =>
import("@/ui/CFLXG0V4B/index.vue")
),
},
QYGL3F8E: {
name: "人企关系加强版",
component: defineAsyncComponent(() =>
import("@/ui/CQYGL3F8E/index.vue")
),
remark: '人企关系加强版提供全面的企业关联分析,包括投资企业记录、高管任职记录和涉诉风险等多维度信息。'
},
QYGL66SL: {
name: "企业司法涉诉",
component: defineAsyncComponent(() => import("@/ui/CQYGL66SL.vue")),
remark: '企业司法涉诉模块展示被查询企业在全国法院公开信息中的民事案件情况,包括案件数量、结案情况、涉案地域与案由分布等,用于评估企业的司法风险。'
},
QYGL2S0W: {
name: "失信被执行人",
component: defineAsyncComponent(() => import("@/ui/CQYGL2S0W.vue")),
remark: '失信被执行人模块展示最高法院公布的失信记录,包括履行情况、执行法院、执行依据等信息,是评估严重违约风险的重要参考。'
},
// IVYZ0S0D:{
// name: "劳动仲裁信息查询(个人版)",
// component: defineAsyncComponent(() => import("@/ui/CIVYZ0S0D.vue")),
// remark: '劳动仲裁信息查询(个人版)用于查询个人在劳动仲裁方面的信息,包括劳动仲裁案件数量、劳动仲裁案件类型、劳动仲裁案件结果等。',
// },
// 人企关系加强版拆分模块
CQYGL3F8E_Investment: {
name: "投资企业记录",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Investment.vue")),
},
CQYGL3F8E_SeniorExecutive: {
name: "高管任职记录",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/SeniorExecutive.vue")),
},
CQYGL3F8E_Lawsuit: {
name: "涉诉风险",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Lawsuit.vue")),
},
CQYGL3F8E_InvestHistory: {
name: "对外投资历史",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/InvestHistory.vue")),
},
CQYGL3F8E_FinancingHistory: {
name: "融资历史",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/FinancingHistory.vue")),
},
CQYGL3F8E_Punishment: {
name: "行政处罚",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Punishment.vue")),
},
CQYGL3F8E_Abnormal: {
name: "经营异常",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Abnormal.vue")),
},
CQYGL3F8E_TaxRisk: {
name: "税务风险",
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/TaxRisk/index.vue")),
},
QCXG7A2B: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CQCXG7A2B.vue")),
},
QCXG9P1C: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CQCXG9P1C.vue")),
},
QCXGGB2Q: {
name: "人车核验简版",
component: defineAsyncComponent(() => import("@/ui/CQCXGGB2Q.vue")),
},
QCXGYTS2: {
name: "人车核验详版",
component: defineAsyncComponent(() => import("@/ui/CQCXGYTS2.vue")),
},
QCXG5F3A: {
name: "名下车辆(车牌)",
component: defineAsyncComponent(() => import("@/ui/QCXG5F3A.vue")),
},
QCXG4D2E: { name: "名下车辆(数量)", component: defineAsyncComponent(() => import("@/ui/CQCXG4D2E.vue")) },
QCXG5U0Z: { name: "车辆静态信息查询", component: defineAsyncComponent(() => import("@/ui/CQCXG5U0Z.vue")) },
QCXG1U4U: { name: "车辆里程记录(混合查询)", component: defineAsyncComponent(() => import("@/ui/CQCXG1U4U.vue")) },
QCXGY7F2: { name: "二手车VIN估值", component: defineAsyncComponent(() => import("@/ui/CQCXGY7F2.vue")) },
QCXG1H7Y: { name: "车辆过户简版查询", component: defineAsyncComponent(() => import("@/ui/CQCXG1H7Y.vue")) },
QCXG4I1Z: { name: "车辆过户详版查询", component: defineAsyncComponent(() => import("@/ui/CQCXG4I1Z.vue")) },
QCXG3Y6B: { name: "车辆维保简版查询", component: defineAsyncComponent(() => import("@/ui/CQCXG3Y6B.vue")) },
QCXG3Z3L: { name: "车辆维保详细版查询", component: defineAsyncComponent(() => import("@/ui/CQCXG3Z3L.vue")) },
QCXGP00W: { name: "车辆出险详版查询", component: defineAsyncComponent(() => import("@/ui/CQCXGP00W.vue")) },
QCXG6B4E: { name: "车辆出险记录核验", component: defineAsyncComponent(() => import("@/ui/CQCXG6B4E.vue")) },
IVYZ9K7F: { name: "公安二要素认证", component: defineAsyncComponent(() => import("@/ui/CIVYZ9K7F.vue")) },
IVYZA1B3: { name: "公安三要素", component: defineAsyncComponent(() => import("@/ui/CIVYZA1B3.vue")) },
IVYZ6M8P: { name: "职业资格证书查询", component: defineAsyncComponent(() => import("@/ui/CIVYZ6M8P.vue")) },
JRZQ8B3C: { name: "个人消费能力等级", component: defineAsyncComponent(() => import("@/ui/JRZQ8B3C/index.vue")) },
YYSY3M8S: { name: "运营商二要素", component: defineAsyncComponent(() => import("@/ui/CYYSY3M8S.vue")) },
YYSYK9R4: { name: "全网手机三要素验证周更", component: defineAsyncComponent(() => import("@/ui/CYYSYK9R4.vue")) },
YYSYF2T7: { name: "号码二次放号", component: defineAsyncComponent(() => import("@/ui/CYYSYF2T7.vue")) },
YYSYK8R3: { name: "手机空号检测", component: defineAsyncComponent(() => import("@/ui/CYYSYK8R3.vue")) },
YYSYS9W1: { name: "手机携号转网", component: defineAsyncComponent(() => import("@/ui/CYYSYS9W1.vue")) },
YYSYE7V5: { name: "手机在网状态", component: defineAsyncComponent(() => import("@/ui/CYYSYE7V5.vue")) },
YYSYP0T4: { name: "手机号码在网时长", component: defineAsyncComponent(() => import("@/ui/CYYSYP0T4.vue")) },
YYSY6F2B: { name: "手机消费区间验证", component: defineAsyncComponent(() => import("@/ui/CYYSY6F2B.vue")) },
YYSY9E4A: { name: "手机号码归属地核验", component: defineAsyncComponent(() => import("@/ui/CYYSY9E4A.vue")) },
QYGL5F6A: { name: "名下企业关联", component: defineAsyncComponent(() => import("@/ui/CQYGL5F6A.vue")) },
JRZQACAB: { name: "银行卡四要素验证(详版)", component: defineAsyncComponent(() => import("@/ui/CJRZQACAB.vue")) },
JRZQ0B6Y: { name: "银行卡黑名单", component: defineAsyncComponent(() => import("@/ui/CJRZQ0B6Y.vue")) },
BehaviorRiskScan: {
name: "风险行为扫描",
component: defineAsyncComponent(() =>
import("@/ui/CBehaviorRiskScan.vue")
),
},
JRZQ4AA8: {
name: "还款压力",
component: defineAsyncComponent(() => import("@/ui/CJRZQ4AA8.vue")),
},
IVYZ9A2B: {
name: "学历信息查询",
component: defineAsyncComponent(() => import("@/ui/CIVYZ9A2B.vue")),
},
IVYZ7F3A: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/CIVYZ7F3A.vue")),
},
IVYZ3P9M: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
},
DWBG8B4D: {
name: "谛听多维报告",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/index.vue")),
},
// 谛听多维报告拆分模块
DWBG8B4D_Overview: {
name: "报告概览",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/ReportOverview.vue")),
},
DWBG8B4D_ElementVerification: {
name: "要素核查",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/ElementVerification.vue")),
},
DWBG8B4D_Identity: {
name: "运营商核验",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/Identity.vue")),
},
DWBG8B4D_RiskWarning: {
name: "公安重点人员检验",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskWarning.vue")),
},
DWBG8B4D_OverdueRisk: {
name: "逾期风险综述",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/OverdueRiskSection.vue")),
},
DWBG8B4D_CourtInfo: {
name: "法院曝光台信息",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/MultCourtInfoSection.vue")),
},
DWBG8B4D_LoanEvaluation: {
name: "借贷评估",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/LoanEvaluationSection.vue")),
},
DWBG8B4D_LeasingRisk: {
name: "租赁风险评估",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/LeasingRiskSection.vue")),
},
DWBG8B4D_RiskSupervision: {
name: "关联风险监督",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskSupervisionSection.vue")),
},
DWBG8B4D_RiskWarningTab: {
name: "规则风险提示",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskWarningTab.vue")),
},
JRZQ4B6C: {
name: "信贷表现",
component: defineAsyncComponent(() => import("@/ui/JRZQ4B6C/index.vue")),
remark: '信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人信用过滤。数据来源于多个征信机构,可能存在数据延迟或不完整的情况。'
},
JRZQ09J8: {
name: "收入评估",
component: defineAsyncComponent(() => import("@/ui/JRZQ09J8/index.vue")),
remark: '基于全国社会保险信息系统的缴费基数数据进行收入水平评估。评级反映相对收入水平,实际收入可能因地区差异而有所不同,建议结合其他收入证明材料进行综合评估。'
},
JRZQ8B3C: {
name: "个人消费能力",
component: defineAsyncComponent(() => import("@/ui/JRZQ8B3C/index.vue")),
remark: '根据个人的消费能力,评估其消费水平,从而评估其信用风险。'
},
// 司南报告
DWBG6A2C: {
name: "司南报告",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/index.vue")),
remark: '司南报告提供全面的个人信用风险评估,包括身份核验、风险名单、借贷行为、履约情况等多维度分析。'
},
// 司南报告拆分模块
// DWBG6A2C_BaseInfo: {
// name: "基本信息",
// component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/BaseInfoSection.vue")),
// },
DWBG6A2C_StandLiveInfo: {
name: "身份信息核验",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/StandLiveInfoSection.vue")),
},
DWBG6A2C_RiskPoint: {
name: "命中风险标注",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskPointSection.vue")),
},
DWBG6A2C_SecurityInfo: {
name: "公安重点人员核验",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/SecurityInfoSection.vue")),
},
DWBG6A2C_AntiFraudInfo: {
name: "涉赌涉诈人员核验",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/AntiFraudInfoSection.vue")),
},
DWBG6A2C_RiskList: {
name: "风险名单",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskListSection.vue")),
},
DWBG6A2C_ApplicationStatistics: {
name: "历史借贷行为",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/ApplicationStatisticsSection.vue")),
},
DWBG6A2C_LendingStatistics: {
name: "近24个月放款情况",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/LendingStatisticsSection.vue")),
},
DWBG6A2C_PerformanceStatistics: {
name: "履约情况",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/PerformanceStatisticsSection.vue")),
},
DWBG6A2C_OverdueRecord: {
name: "历史逾期记录",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/OverdueRecordSection.vue")),
},
DWBG6A2C_CreditDetail: {
name: "授信详情",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/CreditDetailSection.vue")),
},
DWBG6A2C_RentalBehavior: {
name: "租赁行为",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RentalBehaviorSection.vue")),
},
DWBG6A2C_RiskSupervision: {
name: "关联风险监督",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskSupervisionSection.vue")),
},
DWBG6A2C_CourtRiskInfo: {
name: "法院风险信息",
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/CourtRiskInfoSection.vue")),
},
// 贷款风险报告
JRZQ5E9F: {
name: "贷款风险评估",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/index.vue")),
remark: '贷款风险评估提供全面的个人贷款风险分析,包括风险概览、信用评分、贷款行为分析、机构分析等多维度评估。'
},
// 贷款风险报告拆分模块
CJRZQ5E9F_RiskOverview: {
name: "风险概览",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskOverview.vue")),
},
CJRZQ5E9F_CreditScores: {
name: "信用评分",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/CreditScores.vue")),
},
CJRZQ5E9F_LoanBehaviorAnalysis: {
name: "贷款行为分析",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/LoanBehaviorAnalysis.vue")),
},
CJRZQ5E9F_InstitutionAnalysis: {
name: "机构分析",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/InstitutionAnalysis.vue")),
},
CJRZQ5E9F_TimeTrendAnalysis: {
name: "时间趋势分析",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/TimeTrendAnalysis.vue")),
},
CJRZQ5E9F_RiskIndicators: {
name: "风险指标详情",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskIndicators.vue")),
},
CJRZQ5E9F_RiskAdvice: {
name: "专业建议",
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskAdvice.vue")),
}
};
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 === "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)
);
}
}
return value;
};
});
// ==================== 新评分系统 ====================
// Feature 风险等级配置(权重越高表示风险越大,最终分数越高越安全)
const featureRiskLevels = {
// 🔴 高风险类 - 权重 10
'FLXG0V4B': 20, // 司法涉诉
'FLXG7E8F': 20, // 司法涉诉
'FLXG3D56': 10, // 违约失信
'JRZQ4AA8': 10, // 还款压力
// 🟠 中高风险类 - 权重 7
'JRZQ0A03': 7, // 借贷申请记录
'JRZQ8203': 7, // 借贷行为记录
'JRZQ4B6C': 7, // 信贷表现
'BehaviorRiskScan': 7, // 风险行为扫描
// 🟡 中风险类 - 权重 5
'QYGL3F8E': 5, // 人企关系加强版
'QCXG7A2B': 5, // 名下车辆
'QCXGGB2Q': 5, // 人车核验简版
'QCXGYTS2': 5, // 人车核验详版
'QCXG5F3A': 5, // 名下车辆(车牌)
'QCXG4D2E': 5, 'QCXG5U0Z': 5, 'QCXG1U4U': 5, 'QCXGY7F2': 5, 'QCXG1H7Y': 5,
'QCXG4I1Z': 5, 'QCXG3Y6B': 5, 'QCXG3Z3L': 5, 'QCXGP00W': 5, 'QCXG6B4E': 5,
'JRZQ09J8': 5, // 收入评估
'IVYZ9K7F': 5, 'IVYZA1B3': 5, 'IVYZ6M8P': 5, 'JRZQ8B3C': 3,
'YYSY3M8S': 5, 'YYSYK9R4': 5, 'YYSYF2T7': 5, 'YYSYK8R3': 5,
'YYSYS9W1': 5, 'YYSYE7V5': 5, 'YYSYP0T4': 5, 'YYSY6F2B': 5,
'YYSY9E4A': 3, 'QYGL5F6A': 5, 'JRZQACAB': 5, 'JRZQ0B6Y': 5,
'QYGL66SL': 10, 'QYGL2S0W': 10, 'FLXG3A9B': 10,
// 🔵 低风险类 - 权重 3
'IVYZ5733': 3, // 婚姻状态
'IVYZ9A2B': 3, // 学历信息
'IVYZ3P9M': 3, // 学历信息查询(实时版)
// 📊 复合报告类 - 按子模块动态计算
'DWBG8B4D': 0, // 谛听多维报告(由子模块计算)
'DWBG6A2C': 0, // 司南报告(由子模块计算)
'JRZQ5E9F': 0, // 贷款风险评估(由子模块计算)
// 谛听多维报告子模块
'DWBG8B4D_Overview': 10,
'DWBG8B4D_ElementVerification': 4,
'DWBG8B4D_Identity': 4,
'DWBG8B4D_RiskWarning': 10,
'DWBG8B4D_OverdueRisk': 9,
'DWBG8B4D_LoanEvaluation': 7,
'DWBG8B4D_LeasingRisk': 6,
'DWBG8B4D_RiskSupervision': 8,
'DWBG8B4D_RiskWarningTab': 9,
'DWBG8B4D_CourtInfo':9,
// 司南报告子模块
'DWBG6A2C_StandLiveInfo': 4,
'DWBG6A2C_RiskPoint': 9,
'DWBG6A2C_SecurityInfo': 15,
'DWBG6A2C_AntiFraudInfo': 15,
'DWBG6A2C_RiskList': 12,
'DWBG6A2C_ApplicationStatistics': 7,
'DWBG6A2C_LendingStatistics': 6,
'DWBG6A2C_PerformanceStatistics': 7,
'DWBG6A2C_OverdueRecord': 9,
'DWBG6A2C_CreditDetail': 5,
'DWBG6A2C_RentalBehavior': 5,
'DWBG6A2C_RiskSupervision': 8,
'DWBG6A2C_CourtRiskInfo':13,
// 贷款风险评估子模块
'CJRZQ5E9F_RiskOverview': 8,
'CJRZQ5E9F_CreditScores': 7,
'CJRZQ5E9F_LoanBehaviorAnalysis': 7,
'CJRZQ5E9F_InstitutionAnalysis': 5,
'CJRZQ5E9F_TimeTrendAnalysis': 6,
'CJRZQ5E9F_RiskIndicators': 8,
'CJRZQ5E9F_RiskAdvice': 2,
// 人企关系加强版子模块
'CQYGL3F8E_Investment': 4,
'CQYGL3F8E_SeniorExecutive': 4,
'CQYGL3F8E_Lawsuit': 8,
'CQYGL3F8E_InvestHistory': 3,
'CQYGL3F8E_FinancingHistory': 3,
'CQYGL3F8E_Punishment': 7,
'CQYGL3F8E_Abnormal': 6,
'CQYGL3F8E_TaxRisk': 7,
};
// 存储每个组件的 ref 引用
const componentRefs = ref({});
// 存储每个组件的风险评分(由组件主动通知)
const componentRiskScores = ref({});
// 提供方法让子组件通知自己的风险评分0-100分分数越高越安全
const notifyRiskStatus = (apiID, index, riskScore) => {
const key = `${apiID}_${index}`;
componentRiskScores.value[key] = riskScore;
};
// 暴露给子组件
defineExpose({
notifyRiskStatus
});
// 计算综合评分的函数(分数越高越安全)
const calculateScore = () => {
// 收集实际存在的 features 及其风险权重
const presentFeatures = [];
processedReportData.value.forEach((item, index) => {
const apiID = item.data?.apiID;
if (!apiID) return;
// 获取风险权重(如果不在配置中,默认为 3
const weight = featureRiskLevels[apiID] ?? 3;
// 跳过权重为 0 的复合报告主模块(它们由子模块计算)
if (weight === 0) return;
presentFeatures.push({
apiID,
index,
weight
});
});
if (presentFeatures.length === 0) return 100; // 无有效特征时返回满分(最安全)
// 累计总风险分数
let totalRiskScore = 0;
const riskDetails = []; // 用于调试
presentFeatures.forEach(({ apiID, index, weight }) => {
// 从组件风险评分中获取评分0-100分分数越高越安全
const key = `${apiID}_${index}`;
const componentScore = componentRiskScores.value[key] ?? 100; // 默认100分最安全
// 将组件评分转换为风险分数0-100 -> 100-0
const componentRisk = 100 - componentScore;
// 计算该模块的风险贡献(固定分值,不按占比)
// 使用权重系数放大高风险模块的影响
// 高风险模块权重10如果风险分数是0扣20分权重10 × 系数2
// 中风险模块权重7如果风险分数是0扣14分权重7 × 系数2
// 低风险模块权重3如果风险分数是0扣6分权重3 × 系数2
const weightMultiplier = 1.5; // 权重系数,可以调整这个值来控制影响程度
const riskContribution = (componentRisk / 100) * weight * weightMultiplier;
riskDetails.push({
apiID,
index,
weight,
componentScore,
componentRisk,
riskContribution,
hasStatus: key in componentRiskScores.value
});
// 累加风险分数
totalRiskScore += riskContribution;
});
// 将总风险分数限制在 0-90 范围内确保最低分为10分
const finalRiskScore = Math.max(0, Math.min(90, Math.round(totalRiskScore)));
// 转换为安全分数分数越高越安全100 - 风险分数)
// 最终分数范围10-100分
const safetyScore = 100 - finalRiskScore;
return safetyScore;
};
// 监听 reportData 和 componentRiskScores 变化并计算评分
watch([reportData, componentRiskScores], () => {
reportScore.value = calculateScore();
// 将评分系统数据整理到一个对象中
const scoreData = {
timestamp: new Date().toISOString(),
finalScore: reportScore.value,
reportModules: processedReportData.value.map((item, index) => ({
apiID: item.data.apiID,
name: featureMap[item.data.apiID]?.name || '未知',
index: index,
riskScore: componentRiskScores.value[`${item.data.apiID}_${index}`] ?? '未上报',
weight: featureRiskLevels[item.data.apiID] ?? 0
})),
componentScores: componentRiskScores.value,
riskLevels: featureRiskLevels
};
}, { immediate: true, deep: true });
</script>
<template>
<div class="min-h-full bg-[#f6f8fe]">
<template v-if="isDone">
<!-- 背景图容器 -->
<div v-if="hasBackgroundImage" ref="backgroundContainerRef" class="w-full"
:style="[backgroundContainerStyle, backgroundImageStyle]">
</div>
<!-- Tabs 区域 -->
<StyledTabs v-model:active="active" scrollspy sticky :offset-top="46">
<div class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<van-tab title="分析指数" v-if="processedReportData.length > 1">
<div class="relative mb-4">
<!-- 产品卡片牌匾效果 - 使用背景图片 -->
<div class="absolute -top-[12px] left-1/2 transform -translate-x-1/2 w-[140px]">
<div class="trapezoid-bg-image flex items-center justify-center"
:style="trapezoidBgStyle">
<div class="text-xl whitespace-nowrap">分析指数</div>
</div>
</div>
<div class="card mb-4 mt-6 !pt-10">
<div class="my-4">
<GaugeChart :score="reportScore" />
</div>
</div>
</div>
</van-tab>
<van-tab title="基本信息">
<TitleBanner id="basic" class="mb-4">基本信息</TitleBanner>
<VerificationCard :report-params="reportParams" :report-date-time="reportDateTime"
:report-name="reportName" :is-empty="isEmpty" :is-share="isShare" :order-id="orderId"
:order-no="orderNo" />
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
</van-tab>
<van-tab v-for="(item, index) in processedReportData" :key="`${item.data.apiID}_${index}`"
:title="featureMap[item.data.apiID]?.name">
<TitleBanner :id="item.data.apiID" class="mb-4">
{{ featureMap[item.data.apiID]?.name }}
</TitleBanner>
<component :is="featureMap[item.data.apiID]?.component" :ref="el => {
if (el) {
const refKey = `${item.data.apiID}_${index}`;
componentRefs[refKey] = el;
}
}" :data="item.data.data" :params="reportParams" :api-id="item.data.apiID" :index="index"
:notify-risk-status="notifyRiskStatus">
</component>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</van-tab>
<ShareReportButton v-if="!isShare" class="h-12 text-3xl mt-8" :order-id="orderId"
:order-no="orderNo" :is-example="isExample" />
<span class="mb-4 text-center text-sm text-gray-500">分享当前{{ isExample ? '示例' : '报告' }}链接</span>
<div class="card">
<div>
<div class="text-bold text-center text-[#333333] mb-2">
免责声明
</div>
<p class="text-[#999999]">
&nbsp; &nbsp;
1本份报告是在取得您个人授权后我们才向合法存有您以上个人信息的机构去调取相关内容我们不会以任何形式对您的报告进行存储除您和您授权的人外不会提供给任何人和机构进行查看
</p>
<p class="text-[#999999]">
&nbsp; &nbsp; 2本报告自生成之日起有效期 15
过期自动删除如果您对本份报告存有异议可能是合作机构数据有延迟或未能获取到您的相关数据出于合作平台数据隐私的保护本平台将不做任何解释
</p>
<p class="text-[#999999]">
&nbsp; &nbsp; 3若以上数据有错误请联系平台客服
</p>
</div>
</div>
</div>
</StyledTabs>
</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>
.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;
}
:deep(.card) {
@apply p-3;
box-shadow: 0px 0px 24px 0px #3F3F3F0F;
}
/* 梯形背景图片样式 */
.trapezoid-bg-image {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
height: 44px;
}
</style>