diff --git a/package.json b/package.json index 900dcd9..16b5466 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "@vant/area-data": "^2.0.0", "@vueuse/core": "^11.3.0", "axios": "^1.7.7", "crypto-js": "^4.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f9d93a7..61d0d0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@vant/area-data': + specifier: ^2.0.0 + version: 2.0.0 '@vueuse/core': specifier: ^11.3.0 version: 11.3.0(vue@3.5.13) @@ -521,6 +524,9 @@ packages: '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@vant/area-data@2.0.0': + resolution: {integrity: sha512-zgP4AA8z09S9QTNgVCCHo9cHjcybrv22RJDYPjuCkecn4SB98T5EoPQh2TwqbQXmUhbaOGgiZGy3OUaUxnY7qg==} + '@vant/auto-import-resolver@1.2.1': resolution: {integrity: sha512-czGWW4UolNITkF3qQSQlpHDHAsI3/GHVKbRMmEEpry7NWdnU4p5a5jBi0VApbaLa5g80Hy10XVs3IB+UozoSUw==} @@ -2042,6 +2048,8 @@ snapshots: '@types/web-bluetooth@0.0.20': {} + '@vant/area-data@2.0.0': {} + '@vant/auto-import-resolver@1.2.1': {} '@vant/popperjs@1.3.0': {} diff --git a/src/assets/images/banner.png b/src/assets/images/banner.png index e1246d4..54c024d 100644 Binary files a/src/assets/images/banner.png and b/src/assets/images/banner.png differ diff --git a/src/assets/images/head_shot.webp b/src/assets/images/head_shot.webp new file mode 100644 index 0000000..50a540e Binary files /dev/null and b/src/assets/images/head_shot.webp differ diff --git a/src/assets/images/icon_bg.svg b/src/assets/images/icon_bg.svg new file mode 100644 index 0000000..fcd561c --- /dev/null +++ b/src/assets/images/icon_bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/icon_bz.svg b/src/assets/images/icon_bz.svg new file mode 100644 index 0000000..5fe642c --- /dev/null +++ b/src/assets/images/icon_bz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/invitation.png b/src/assets/images/invitation.png new file mode 100644 index 0000000..183a516 Binary files /dev/null and b/src/assets/images/invitation.png differ diff --git a/src/assets/images/invitation_agent_apply.png b/src/assets/images/invitation_agent_apply.png new file mode 100644 index 0000000..d9b54b4 Binary files /dev/null and b/src/assets/images/invitation_agent_apply.png differ diff --git a/src/assets/images/logo.jpg b/src/assets/images/logo.jpg new file mode 100644 index 0000000..517584e Binary files /dev/null and b/src/assets/images/logo.jpg differ diff --git a/src/assets/images/promote_bg.png b/src/assets/images/promote_bg.png new file mode 100644 index 0000000..9087024 Binary files /dev/null and b/src/assets/images/promote_bg.png differ diff --git a/src/assets/images/tg_qrcode_1.png b/src/assets/images/tg_qrcode_1.png new file mode 100644 index 0000000..1157bb4 Binary files /dev/null and b/src/assets/images/tg_qrcode_1.png differ diff --git a/src/assets/images/vip_banner.png b/src/assets/images/vip_banner.png new file mode 100644 index 0000000..5de629d Binary files /dev/null and b/src/assets/images/vip_banner.png differ diff --git a/src/assets/images/vip_bg.png b/src/assets/images/vip_bg.png new file mode 100644 index 0000000..0a30280 Binary files /dev/null and b/src/assets/images/vip_bg.png differ diff --git a/src/assets/images/yq_qrcode_1.png b/src/assets/images/yq_qrcode_1.png new file mode 100644 index 0000000..d8d4fcc Binary files /dev/null and b/src/assets/images/yq_qrcode_1.png differ diff --git a/src/components/AgentApplicationForm.vue b/src/components/AgentApplicationForm.vue new file mode 100644 index 0000000..85e1306 --- /dev/null +++ b/src/components/AgentApplicationForm.vue @@ -0,0 +1,187 @@ + + + diff --git a/src/components/GaugeChart.vue b/src/components/GaugeChart.vue new file mode 100644 index 0000000..8a5a3ed --- /dev/null +++ b/src/components/GaugeChart.vue @@ -0,0 +1,255 @@ + + + + + \ No newline at end of file diff --git a/src/components/WechatOverlay.vue b/src/components/WechatOverlay.vue index 5a6c6c5..29412fc 100644 --- a/src/components/WechatOverlay.vue +++ b/src/components/WechatOverlay.vue @@ -1,5 +1,5 @@ + + + + diff --git a/src/ui/CSpecialList.vue b/src/ui/CSpecialList.vue index 3f97730..4a086d6 100644 --- a/src/ui/CSpecialList.vue +++ b/src/ui/CSpecialList.vue @@ -1,14 +1,17 @@ + + \ No newline at end of file diff --git a/src/views/AgentServiceAgreement.vue b/src/views/AgentServiceAgreement.vue new file mode 100644 index 0000000..05dbeca --- /dev/null +++ b/src/views/AgentServiceAgreement.vue @@ -0,0 +1,277 @@ + + + + + \ No newline at end of file diff --git a/src/views/AppExample.vue b/src/views/AppExample.vue new file mode 100644 index 0000000..644fc4a --- /dev/null +++ b/src/views/AppExample.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/src/views/AppInquire.vue b/src/views/AppInquire.vue new file mode 100644 index 0000000..536458a --- /dev/null +++ b/src/views/AppInquire.vue @@ -0,0 +1,591 @@ + + + + + diff --git a/src/views/AppUserAgreement.vue b/src/views/AppUserAgreement.vue new file mode 100644 index 0000000..554d4d2 --- /dev/null +++ b/src/views/AppUserAgreement.vue @@ -0,0 +1,268 @@ + + + diff --git a/src/views/Example.vue b/src/views/Example.vue index 031ce2d..ababa15 100644 --- a/src/views/Example.vue +++ b/src/views/Example.vue @@ -31,6 +31,10 @@ const featureMap = { name: '司法涉诉', component: defineAsyncComponent(() => import('@/ui/CLawsuit.vue')), }, + G22SC01: { + name: '司法涉诉', + component: defineAsyncComponent(() => import('@/ui/CLawsuitPP.vue')), + }, G05HZ01: { name: '股东人企关系', component: defineAsyncComponent(() => import('@/ui/CRelatedEnterprises.vue')), @@ -100,6 +104,8 @@ const reportName = ref("") const reportDateTime = ref(null) const feature = ref("") const isEmpty = ref(false) +const reportScore = ref(75); // 默认分数 + onMounted(() => { const query = new URLSearchParams(window.location.search); feature.value = query.get("feature"); @@ -124,6 +130,10 @@ const getReport = async () => { 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); } else if (data.value.code === 200003) { isEmpty.value = true } @@ -178,6 +188,274 @@ const maskValue = computed(() => { return value; } }); + +// 计算综合评分的函数 +const calculateScore = (reportData) => { + // 从0分开始 + let score = 0; + // 最高分为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 60; // 默认60分 + + // 计算当前报告中所有接口的相对权重总和 + 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) { + // 检查所有字段是否都为0(没有风险) + let noRisk = true; + for (const key in data) { + if (data[key] !== 0 && data[key] !== '0') { + noRisk = false; + break; + } + } + if (noRisk || !Object.keys(data).length) { + score += actualWeights[apiID]; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G28BJ05': // 借贷行为记录 + if (data) { + // 检查所有字段是否都为0(没有风险) + let noRisk = true; + for (const key in data) { + if (data[key] !== 0 && data[key] !== '0') { + noRisk = false; + break; + } + } + if (noRisk || !Object.keys(data).length) { + score += actualWeights[apiID]; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G26BJ05': // 违约异常 + if (data) { + // 检查除特定字段外的其他字段是否都为0(没有风险) + const excludeFields = ['swift_number', 'code', 'flag_specialList_c']; + let noRisk = true; + + for (const key in data) { + if (!excludeFields.includes(key) && data[key] !== 0 && data[key] !== '0') { + noRisk = false; + break; + } + } + + if (noRisk || !Object.keys(data).length) { + score += actualWeights[apiID]; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G34BJ03': // 不良记录 + if (data && data.risk_level) { + // 根据风险等级加分 + switch (data.risk_level) { + case 'A': // 无风险 + score += actualWeights[apiID]; + break; + case 'F': // 低风险 + score += actualWeights[apiID] * 0.7; + break; + case 'C': // 中风险 + case 'D': // 中风险 + score += actualWeights[apiID] * 0.3; + break; + case 'B': // 高风险 + case 'E': // 高风险 + // 不加分 + break; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + 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]; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G03HZ01': // 手机号码风险 + if (data && data.filterType) { + // 根据filterType判断风险等级 + switch (data.filterType) { + case '0': // 安全 + score += actualWeights[apiID]; + break; + case '3': // 低危 + score += actualWeights[apiID] * 0.7; + break; + case '2': // 中危 + score += actualWeights[apiID] * 0.3; + break; + case '1': // 高危 + // 不加分 + break; + } + } else { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G19BJ02': // 手机二次卡 + if (data && data.is_second_card === false) { + score += actualWeights[apiID]; + } else if (!data) { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G02BJ02': // 手机在网时长 + if (data && data.online_months >= 6) { + score += actualWeights[apiID]; + } else if (!data) { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'G15BJ02': // 手机三要素 + case 'G17BJ02': // 手机号二要素 + case 'KZEYS': // 身份证二要素 + case 'G20GZ01': // 银行卡四要素核验 + if (data && data.is_consistent) { + score += actualWeights[apiID]; + } else if (!data) { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + case 'FIN019': // 银行卡黑名单 + if (data && data.is_blacklisted === false) { + score += actualWeights[apiID]; + } else if (!data) { + // 无数据视为无风险 + score += actualWeights[apiID]; + } + break; + + default: + // 未知接口类型不影响评分 + break; + } + }); + + // 确保分数在0-90范围内并四舍五入 + return Math.max(0, Math.min(maxScore, Math.round(score))); +}; +