diff --git a/.env b/.env index abdd69f..55182d9 100644 --- a/.env +++ b/.env @@ -12,6 +12,6 @@ VITE_CHAT_AES_KEY=qw5w6SFE2D1jmxyd VITE_CHAT_AES_IV=345GDFED433223DF VITE_SHARE_TITLE=一查查|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用 -VITE_SHARE_DESC=提供个人信用评估、入职背调、信贷风控、企业风险监测等服务 +VITE_SHARE_DESC=提供个人风险评估、入职背调、信贷风控、企业风险监测等服务 VITE_SHARE_IMG=https://www.onecha.cn/logo.png VITE_TOKEN_VERSION=1.5 \ No newline at end of file diff --git a/index.html b/index.html index 194fd18..43615a0 100644 --- a/index.html +++ b/index.html @@ -3,22 +3,36 @@ - - - - + + + + - + 一查查|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用 - + - - + + - + - - - + + + @@ -50,31 +76,31 @@ - + - + @@ -82,13 +108,13 @@ window.jWeixin = window.wx; delete window.wx; - + - - - - - + + + + + - diff --git a/src/components/ShareReportButton.vue b/src/components/ShareReportButton.vue index 7668716..fd644f8 100644 --- a/src/components/ShareReportButton.vue +++ b/src/components/ShareReportButton.vue @@ -1,6 +1,5 @@ + + diff --git a/src/ui/JRZQ3C9R/components/InsufficientRatioSection.vue b/src/ui/JRZQ3C9R/components/InsufficientRatioSection.vue new file mode 100644 index 0000000..52ea192 --- /dev/null +++ b/src/ui/JRZQ3C9R/components/InsufficientRatioSection.vue @@ -0,0 +1,114 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/components/LoanAndOverdueSection.vue b/src/ui/JRZQ3C9R/components/LoanAndOverdueSection.vue new file mode 100644 index 0000000..15c8b7d --- /dev/null +++ b/src/ui/JRZQ3C9R/components/LoanAndOverdueSection.vue @@ -0,0 +1,329 @@ + + + + + diff --git a/src/ui/JRZQ3C9R/components/QueryOverviewSection.vue b/src/ui/JRZQ3C9R/components/QueryOverviewSection.vue new file mode 100644 index 0000000..066797e --- /dev/null +++ b/src/ui/JRZQ3C9R/components/QueryOverviewSection.vue @@ -0,0 +1,259 @@ + + + + + diff --git a/src/ui/JRZQ3C9R/components/QueryTrendSection.vue b/src/ui/JRZQ3C9R/components/QueryTrendSection.vue new file mode 100644 index 0000000..33b5677 --- /dev/null +++ b/src/ui/JRZQ3C9R/components/QueryTrendSection.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/ui/JRZQ3C9R/components/RepayFailTrendSection.vue b/src/ui/JRZQ3C9R/components/RepayFailTrendSection.vue new file mode 100644 index 0000000..afde8bb --- /dev/null +++ b/src/ui/JRZQ3C9R/components/RepayFailTrendSection.vue @@ -0,0 +1,111 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/components/RepayOrgAndLevelSection.vue b/src/ui/JRZQ3C9R/components/RepayOrgAndLevelSection.vue new file mode 100644 index 0000000..5e5774c --- /dev/null +++ b/src/ui/JRZQ3C9R/components/RepayOrgAndLevelSection.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/src/ui/JRZQ3C9R/components/RepaySuccessTrendSection.vue b/src/ui/JRZQ3C9R/components/RepaySuccessTrendSection.vue new file mode 100644 index 0000000..bb2e355 --- /dev/null +++ b/src/ui/JRZQ3C9R/components/RepaySuccessTrendSection.vue @@ -0,0 +1,111 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/components/RepayTrendSection.vue b/src/ui/JRZQ3C9R/components/RepayTrendSection.vue new file mode 100644 index 0000000..2cfc29d --- /dev/null +++ b/src/ui/JRZQ3C9R/components/RepayTrendSection.vue @@ -0,0 +1,124 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/components/ScoreSection.vue b/src/ui/JRZQ3C9R/components/ScoreSection.vue new file mode 100644 index 0000000..c15c7cd --- /dev/null +++ b/src/ui/JRZQ3C9R/components/ScoreSection.vue @@ -0,0 +1,78 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/index.vue b/src/ui/JRZQ3C9R/index.vue new file mode 100644 index 0000000..5ed41c7 --- /dev/null +++ b/src/ui/JRZQ3C9R/index.vue @@ -0,0 +1,105 @@ + + + + + + + diff --git a/src/ui/JRZQ3C9R/utils/dataParser.js b/src/ui/JRZQ3C9R/utils/dataParser.js new file mode 100644 index 0000000..aed3223 --- /dev/null +++ b/src/ui/JRZQ3C9R/utils/dataParser.js @@ -0,0 +1,430 @@ +/** + * 支付行为指数(JRZQ3C9R)数据解析工具 + */ + +/** + * 将 -1 / 空 / null 统一视为 0,其他数值转为 Number + */ +export function normalizeValue(value) { + if (value === undefined || value === null || value === "" || value === -1) { + return 0; + } + const num = Number(value); + return Number.isNaN(num) ? 0 : num; +} + +/** + * 从原始 data 中提取真正的指标对象 + * 兼容多种包裹结构: + * - { code, data: {...} } + * - { data: { code, data: {...} } } + */ +export function extractPpcmData(raw) { + if (!raw) return {}; + + // example.json 结构:data.data.data + if (raw.data && raw.data.data) { + return raw.data.data || {}; + } + + // 已经是 { code, data } 这一层 + if (raw.data && !raw.code) { + return raw.data || {}; + } + + return raw || {}; +} + +/** + * 获取支付行为评分(原始 300-900 分) + */ +export function getBehavScore(ppcm) { + const score = normalizeValue(ppcm.ppcm_behav_score); + return score; +} + +/** + * 将 300-900 分映射到 0-100 分(用于统一风险评分体系) + */ +export function mapScoreTo100(score) { + if (!score || score <= 0) { + return 100; + } + // 限制在 [300,900] + const clamped = Math.min(900, Math.max(300, score)); + // 300 -> 0, 900 -> 100 + const mapped = ((clamped - 300) / 600) * 100; + return Math.round(mapped); +} + +/** + * 支付行为评分等级标签 + */ +export function getBehavLevel(score) { + if (!score || score <= 0) return "暂无评分"; + if (score >= 800) return "优秀"; + if (score >= 750) return "良好"; + if (score >= 700) return "中等"; + if (score >= 650) return "一般"; + return "偏低"; +} + +/** + * 通用时间段 + */ +export const PERIODS = [ + { key: "d7", label: "近7天" }, + { key: "m1", label: "近1个月" }, + { key: "m3", label: "近3个月" }, + { key: "m6", label: "近6个月" }, + { key: "m12", label: "近1年" }, + { key: "m24", label: "近2年" }, +]; + +/** + * 获取查验次数统计(按时间段) + * ppcm_{period}_bank_qynum / _nbank_fin_qynum / _nbank_other_qynum / _qynum + */ +export function getQueryCountsByPeriod(ppcm) { + const result = {}; + + PERIODS.forEach((p) => { + const prefix = `ppcm_${p.key}`; + result[p.key] = { + bank: normalizeValue(ppcm[`${prefix}_bank_qynum`]), + nbankFin: normalizeValue(ppcm[`${prefix}_nbank_fin_qynum`]), + nbankOther: normalizeValue(ppcm[`${prefix}_nbank_other_qynum`]), + total: normalizeValue(ppcm[`${prefix}_qynum`]), + }; + }); + + return result; +} + +/** + * 获取还款成功 / 失败次数统计(按时间段) + * success:ppcm_{period}_succ_repnum + * fail:ppcm_{period}_fail_repnum + */ +export function getRepayCountsByPeriod(ppcm) { + const result = {}; + + PERIODS.forEach((p) => { + const prefix = `ppcm_${p.key}`; + result[p.key] = { + success: normalizeValue(ppcm[`${prefix}_succ_repnum`]), + fail: normalizeValue(ppcm[`${prefix}_fail_repnum`]), + }; + }); + + return result; +} + +/** + * 获取余额不足失败占比(按时间段) + * ppcm_{period}_fail_neh_repnum_ratio + */ +export function getInsufficientRatioByPeriod(ppcm) { + const result = {}; + + PERIODS.forEach((p) => { + const prefix = `ppcm_${p.key}`; + result[p.key] = normalizeValue(ppcm[`${prefix}_fail_neh_repnum_ratio`]); + }); + + return result; +} + +/** + * 解析最近一次查验距今天数区间编码 + * ppcm_latest_qytoday: 1-10 档位 + */ +export function getLatestQueryBucket(ppcm) { + const code = normalizeValue(ppcm.ppcm_latest_qytoday); + if (!code) return "暂无查验记录"; + + const mapping = { + 1: "0-7天", + 2: "7-15天", + 3: "15-30天", + 4: "30-60天", + 5: "60-90天", + 6: "90-120天", + 7: "120-150天", + 8: "150-180天", + 9: "180-360天", + 10: "360天以上", + }; + + return mapping[code] || "未知区间"; +} + +/** + * 生成各 card 的解读文本 + */ + +/** + * 支付行为评分解读(数据解读 + 意思解读) + */ +export function getScoreRemark(score, level) { + if (!score || score <= 0) { + return "暂无支付行为评分数据。\n\n【数据解读】评分基于近两年查验及还款行为综合评估,分数越高代表支付行为越稳定、违约风险越低。\n\n【意思解读】支付行为评分是机构评估您还款能力和信用状况的重要指标。评分越高,说明您的还款履约记录越好,机构对您的信任度越高,未来申请贷款或信用卡时更容易获得批准和更优惠的利率。"; + } + + let dataRemark = `【数据解读】您的支付行为评分为 ${score} 分,等级为"${level}"。`; + let meaningRemark = ""; + + if (score >= 800) { + dataRemark += "您的支付行为表现优秀,还款履约能力强,违约风险极低。"; + meaningRemark = "【意思解读】优秀评分表明您有非常稳定的还款记录和良好的资金管理能力。这意味着机构认为您是低风险客户,在申请贷款、信用卡等金融产品时更容易获得批准,且可能享受更优惠的利率和更高的额度。继续保持这种良好的支付习惯,有助于维护和提升您的信用价值。"; + } else if (score >= 750) { + dataRemark += "您的支付行为表现良好,还款履约能力较强,违约风险较低。"; + meaningRemark = "【意思解读】良好评分说明您的还款记录稳定,机构对您的信任度较高。这有助于您在申请金融产品时获得较好的审批结果。建议继续保持良好的支付习惯,避免逾期,可以进一步提升评分等级。"; + } else if (score >= 700) { + dataRemark += "您的支付行为表现中等,还款履约能力一般,违约风险适中。"; + meaningRemark = "【意思解读】中等评分表示您的还款记录存在一定波动,机构可能会对您的申请进行更严格的审核。建议注意按时还款,减少还款失败的情况,提高支付稳定性,这将有助于提升您的评分和信用价值。"; + } else if (score >= 650) { + dataRemark += "您的支付行为表现一般,还款履约能力有待提升,违约风险偏高。"; + meaningRemark = "【意思解读】一般评分表明您的还款记录不够稳定,可能存在逾期或还款失败的情况。这会导致机构对您的信任度降低,在申请金融产品时可能面临更严格的审核或被拒绝。建议加强还款管理,提前准备还款资金,避免逾期,逐步改善支付行为。"; + } else { + dataRemark += "您的支付行为表现偏低,还款履约能力较弱,违约风险较高。"; + meaningRemark = "【意思解读】偏低评分表明您的还款记录存在较多问题,如频繁逾期、还款失败等。这会导致机构认为您的违约风险较高,在申请贷款、信用卡等金融产品时很可能被拒绝,即使获批也可能面临更高的利率和更低的额度。建议重点关注还款情况,及时处理逾期问题,制定还款计划,逐步改善支付行为,提升信用评分。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 查验次数时间分布解读(数据解读 + 意思解读) + */ +export function getQueryTrendRemark(ppcm) { + const counts = getQueryCountsByPeriod(ppcm); + const m12Total = counts.m12?.total || 0; + const m3Total = counts.m3?.total || 0; + const bankTotal = counts.m12?.bank || 0; + const finTotal = counts.m12?.nbankFin || 0; + const otherTotal = counts.m12?.nbankOther || 0; + + let dataRemark = `【数据解读】近一年查验总次数:${m12Total}次,其中银行查验${bankTotal}次,消费金融查验${finTotal}次,其他机构查验${otherTotal}次。近3个月查验次数:${m3Total}次。`; + let meaningRemark = ""; + + if (m12Total === 0) { + dataRemark += "暂无查验记录。"; + meaningRemark = "【意思解读】无查验记录可能表示近期无相关机构查询您的支付行为数据,或者您近期没有申请相关金融产品。这通常意味着您的信用活动较少,但也可能表示您的信用记录不够活跃。"; + } else if (m12Total <= 5) { + dataRemark += "查验次数较少。"; + meaningRemark = "【意思解读】查验次数较少说明机构对您的支付行为关注度较低,整体风险可控。这可能是因为您的还款记录良好,机构认为风险较低,或者您的信用活动较少。较低的查验频率通常对信用评分影响较小。"; + } else if (m12Total <= 15) { + dataRemark += "查验次数适中。"; + meaningRemark = "【意思解读】查验次数适中说明机构对您的支付行为保持正常关注。这通常发生在您有正常的金融活动时,如申请贷款、信用卡等。适度的查验是正常的信用评估过程,不会对您的信用产生负面影响。"; + } else { + dataRemark += "查验次数较多。"; + meaningRemark = "【意思解读】查验次数较多可能表示机构对您的支付行为关注度较高,这可能是因为您近期有较多的金融申请活动,或者机构需要更频繁地评估您的信用状况。频繁的查验虽然不会直接降低您的信用评分,但可能反映出机构对您的风险关注。建议关注自身还款情况,保持良好的支付记录,减少不必要的金融申请。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 查验行为概览解读(数据解读 + 意思解读) + */ +export function getQueryOverviewRemark(ppcm) { + const m12Count = normalizeValue(ppcm.ppcm_m12_qynum); + const m12Org = normalizeValue(ppcm.ppcm_m12_qyorg); + const m12Day = normalizeValue(ppcm.ppcm_m12_qyday); + + let dataRemark = `【数据解读】近一年查验行为概览:查验次数${m12Count}次,涉及机构${m12Org}家,查验天数${m12Day}天。`; + let meaningRemark = ""; + + if (m12Count === 0) { + dataRemark += "暂无查验记录。"; + meaningRemark = "【意思解读】无查验记录表示近期没有机构查询您的支付行为数据。这可能意味着您的信用活动较少,或者没有申请相关金融产品。虽然不会对信用产生负面影响,但信用记录的活跃度也是评估因素之一。"; + } else { + const avgPerDay = m12Day > 0 ? (m12Count / m12Day).toFixed(2) : 0; + dataRemark += `平均每天查验${avgPerDay}次。`; + + if (m12Org > 0 && m12Count / m12Org > 3) { + dataRemark += "单机构查验频率较高。"; + meaningRemark = "【意思解读】单机构查验频率较高可能表示该机构对您的信用状况需要更频繁的评估,这可能是因为您与该机构有业务往来,或者该机构在评估您的申请。较高的查验频率通常不会直接影响信用评分,但可能反映出机构对您的关注度。建议关注相关机构的关注原因,保持良好的还款记录。"; + } else { + meaningRemark = "【意思解读】查验次数、机构数和天数的组合反映了机构对您信用状况的关注程度。适度的查验是正常的信用评估过程,说明您有正常的金融活动。保持稳定的还款记录,有助于维持良好的信用形象。"; + } + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 还款成功次数趋势解读(数据解读 + 意思解读) + */ +export function getRepaySuccessRemark(ppcm) { + const counts = getRepayCountsByPeriod(ppcm); + const m12Success = counts.m12?.success || 0; + const m3Success = counts.m3?.success || 0; + + let dataRemark = `【数据解读】近一年还款成功次数:${m12Success}次,近3个月还款成功次数:${m3Success}次。`; + let meaningRemark = ""; + + if (m12Success === 0) { + dataRemark += "暂无还款成功记录。"; + meaningRemark = "【意思解读】无还款成功记录可能表示您近期没有需要还款的金融产品,或者还款数据尚未更新。如果确实有还款义务,建议确认还款是否成功,避免因还款失败影响信用记录。"; + } else if (m12Success >= 20) { + dataRemark += "还款成功次数较多。"; + meaningRemark = "【意思解读】还款成功次数较多说明您的还款履约能力较强,支付行为稳定。这表明您有良好的资金管理能力和还款习惯,机构会认为您是可靠的客户。这种稳定的还款记录有助于提升您的信用评分,在申请新的金融产品时更容易获得批准和更优惠的条件。"; + } else if (m12Success >= 10) { + dataRemark += "还款成功次数适中。"; + meaningRemark = "【意思解读】还款成功次数适中说明您的还款履约能力良好。这表明您能够按时完成还款义务,机构对您的信任度较高。继续保持这种良好的还款习惯,有助于维持和提升您的信用价值。"; + } else { + dataRemark += "还款成功次数较少。"; + meaningRemark = "【意思解读】还款成功次数较少可能表示您的还款活动不够频繁,或者存在还款失败的情况。如果确实有还款义务,建议关注还款情况,确保按时还款。稳定的还款记录是建立良好信用的基础,频繁的还款成功有助于提升您的信用评分。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 还款失败次数趋势解读(数据解读 + 意思解读) + */ +export function getRepayFailRemark(ppcm) { + const counts = getRepayCountsByPeriod(ppcm); + const m12Fail = counts.m12?.fail || 0; + const m3Fail = counts.m3?.fail || 0; + + let dataRemark = `【数据解读】近一年还款失败次数:${m12Fail}次,近3个月还款失败次数:${m3Fail}次。`; + let meaningRemark = ""; + + if (m12Fail === 0) { + dataRemark += "无还款失败记录。"; + meaningRemark = "【意思解读】无还款失败记录说明您的还款履约能力优秀,支付行为稳定。这表明您有良好的资金管理能力和还款习惯,所有还款都能按时成功完成。这种完美的还款记录会显著提升您的信用评分,机构会认为您是低风险客户,在申请金融产品时更容易获得批准和更优惠的条件。"; + } else if (m12Fail <= 2) { + dataRemark += "还款失败次数较少。"; + meaningRemark = "【意思解读】还款失败次数较少说明整体还款履约能力良好。偶尔的还款失败可能是由于临时资金紧张或技术原因,但如果频繁发生,可能会影响机构对您的信任度。建议继续保持良好的还款习惯,提前准备还款资金,避免因余额不足等原因导致还款失败。"; + } else if (m12Fail <= 5) { + dataRemark += "还款失败次数适中。"; + meaningRemark = "【意思解读】还款失败次数适中可能表示您的资金管理存在一定问题,或者还款计划不够合理。频繁的还款失败会导致机构对您的还款能力产生怀疑,可能影响您的信用评分和未来申请金融产品的审批结果。建议关注还款情况,制定合理的还款计划,确保账户有足够资金,避免频繁失败。"; + } else { + dataRemark += "还款失败次数较多。"; + meaningRemark = "【意思解读】还款失败次数较多表明您的还款履约能力存在问题,可能是资金管理不当、还款计划不合理或账户余额不足等原因。这会导致机构认为您的违约风险较高,严重影响您的信用评分。在申请新的金融产品时很可能被拒绝,即使获批也可能面临更高的利率和更严格的限制。建议重点关注还款管理,及时处理还款问题,制定还款计划,确保账户有足够资金,逐步改善还款行为,避免影响信用记录。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 余额不足导致还款失败占比解读(数据解读 + 意思解读) + */ +export function getInsufficientRatioRemark(ppcm) { + const ratios = getInsufficientRatioByPeriod(ppcm); + const m12Ratio = ratios.m12 || 0; + const m3Ratio = ratios.m3 || 0; + + const m12Percent = (m12Ratio * 100).toFixed(2); + const m3Percent = (m3Ratio * 100).toFixed(2); + + let dataRemark = `【数据解读】近一年余额不足导致还款失败占比:${m12Percent}%,近3个月占比:${m3Percent}%。`; + let meaningRemark = ""; + + if (m12Ratio === 0) { + dataRemark += "无余额不足导致的还款失败。"; + meaningRemark = "【意思解读】无余额不足导致的还款失败说明您的账户资金管理良好,能够确保还款时有足够的资金。这表明您有良好的资金规划能力,能够提前准备还款资金。这种良好的资金管理习惯有助于维持稳定的还款记录,提升机构对您的信任度。"; + } else if (m12Ratio <= 0.1) { + dataRemark += "余额不足占比很低。"; + meaningRemark = "【意思解读】余额不足占比很低说明整体资金管理良好,偶尔的余额不足可能是由于临时资金周转问题。虽然占比很低,但仍需注意,因为即使是偶尔的余额不足也可能导致还款失败,影响信用记录。建议继续保持良好的资金管理习惯,提前准备还款资金。"; + } else if (m12Ratio <= 0.3) { + dataRemark += "余额不足占比适中。"; + meaningRemark = "【意思解读】余额不足占比适中表明您的资金管理存在一定问题,可能没有提前准备足够的还款资金。这会导致部分还款因余额不足而失败,影响您的还款履约记录。机构可能会认为您的资金管理能力不足,影响信用评分。建议关注账户余额,制定资金规划,确保还款时有足够资金,避免因余额不足导致还款失败。"; + } else { + dataRemark += "余额不足占比较高。"; + meaningRemark = "【意思解读】余额不足占比较高表明您的资金管理存在严重问题,经常没有足够的资金用于还款。这会导致频繁的还款失败,严重影响您的还款履约记录和信用评分。机构会认为您的资金管理能力不足,违约风险较高,在申请新的金融产品时很可能被拒绝。建议加强资金管理,制定详细的资金规划,提前准备还款资金,建立还款提醒机制,避免因余额不足导致还款失败,逐步改善资金管理习惯。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 还款机构数与等级解读(数据解读 + 意思解读) + */ +export function getRepayOrgAndLevelRemark(ppcm) { + const m12SuccOrg = normalizeValue(ppcm.ppcm_m12_succ_reporg); + const m12FailOrg = normalizeValue(ppcm.ppcm_m12_fail_reporg); + const m12SuccLevel = normalizeValue(ppcm.ppcm_m12_succ_repamt); + const m12FailLevel = normalizeValue(ppcm.ppcm_m12_fail_repamt); + + let dataRemark = `【数据解读】近一年还款成功机构数:${m12SuccOrg}家,还款失败机构数:${m12FailOrg}家。还款成功等级:${m12SuccLevel},还款失败等级:${m12FailLevel}。`; + let meaningRemark = ""; + + if (m12SuccOrg > 0 && m12FailOrg === 0) { + dataRemark += "所有机构还款均成功。"; + meaningRemark = "【意思解读】所有机构还款均成功说明您的还款履约能力优秀,能够与多家机构保持良好的还款关系。这表明您有稳定的资金流和良好的还款习惯,机构对您的信任度很高。这种完美的还款记录会显著提升您的信用评分,在申请新的金融产品时更容易获得批准和更优惠的条件。"; + } else if (m12SuccOrg > m12FailOrg) { + dataRemark += "还款成功机构数多于失败机构数。"; + meaningRemark = "【意思解读】还款成功机构数多于失败机构数说明整体还款履约能力良好,虽然存在部分机构的还款失败,但大部分机构都能成功还款。这表明您有基本的还款能力,但资金管理可能存在一定问题。建议关注失败原因,及时处理还款问题,确保所有机构都能成功还款,进一步提升信用价值。"; + } else if (m12FailOrg > 0) { + dataRemark += "存在还款失败机构。"; + meaningRemark = "【意思解读】存在还款失败机构表明您的还款履约能力存在问题,可能无法与所有机构保持良好的还款关系。这会导致相关机构对您的信任度降低,可能影响您与该机构的业务往来,甚至影响您的整体信用评分。建议关注失败原因,及时处理还款问题,制定还款计划,确保所有机构都能成功还款,维护良好的信用关系。"; + } else { + meaningRemark = "【意思解读】还款机构数和等级反映了您与不同机构的还款关系。成功机构数越多、失败机构数越少,说明您的还款履约能力越强,机构对您的信任度越高。保持良好的还款记录有助于维护和提升您的信用价值。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 借款与逾期概览解读(数据解读 + 意思解读) + */ +export function getLoanAndOverdueRemark(ppcm) { + const m12Loan = normalizeValue(ppcm.ppcm_m12_loannum); + const m12LoanOrg = normalizeValue(ppcm.ppcm_m12_loanorg); + const m12LoanAmt = normalizeValue(ppcm.ppcm_m12_loanamt); + const m12OverNum = normalizeValue(ppcm.ppcm_m12_overnum); + const m12OverOrg = normalizeValue(ppcm.ppcm_m12_overorg); + const m12OverAmt = normalizeValue(ppcm.ppcm_m12_overamt); + + let dataRemark = `【数据解读】近一年借款情况:借款次数${m12Loan}次,涉及机构${m12LoanOrg}家,借款等级${m12LoanAmt}。逾期情况:逾期次数${m12OverNum}次,逾期机构数${m12OverOrg}家,逾期等级${m12OverAmt}。`; + let meaningRemark = ""; + + if (m12OverNum === 0) { + dataRemark += "无逾期记录。"; + meaningRemark = "【意思解读】无逾期记录说明您的还款履约能力优秀,能够按时完成所有还款义务。这表明您有良好的资金管理能力和还款习惯,机构会认为您是低风险客户。这种完美的还款记录会显著提升您的信用评分,在申请新的金融产品时更容易获得批准和更优惠的条件。借款等级反映了您的借款规模,适度的借款有助于建立信用记录,但过度借款可能增加还款压力。"; + } else if (m12OverNum <= 2) { + dataRemark += "逾期次数较少。"; + meaningRemark = "【意思解读】逾期次数较少说明整体还款履约能力良好,虽然存在偶尔的逾期,但大部分还款都能按时完成。偶尔的逾期可能是由于临时资金紧张或忘记还款,但如果频繁发生,可能会影响机构对您的信任度。建议继续保持良好的还款习惯,建立还款提醒机制,避免逾期,进一步提升信用价值。"; + } else { + dataRemark += "逾期次数较多。"; + meaningRemark = "【意思解读】逾期次数较多表明您的还款履约能力存在问题,可能无法按时完成还款义务。这会导致机构认为您的违约风险较高,严重影响您的信用评分。在申请新的金融产品时很可能被拒绝,即使获批也可能面临更高的利率和更严格的限制。逾期记录会在信用报告中保留较长时间,影响您的长期信用价值。建议重点关注还款管理,制定还款计划,提前准备还款资金,及时处理逾期问题,避免影响信用记录。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} + +/** + * 基础信息与查贷比解读(数据解读 + 意思解读) + */ +export function getBasicInfoRemark(ppcm) { + const flag = normalizeValue(ppcm.flag); + const flagDb = normalizeValue(ppcm.flagdb); + const m12Ratio = normalizeValue(ppcm.ppcm_m12_qy_rep_ratio); + + const flagText = flag === 1 ? "查得" : "查无"; + const flagDbText = flagDb === 1 ? "库有" : "库无"; + const ratioText = m12Ratio > 0 ? m12Ratio.toFixed(2) : "0"; + + let dataRemark = `【数据解读】基础信息:查得标识为"${flagText}",库有标识为"${flagDbText}"。近一年查贷比(查验次数/借款次数):${ratioText}。`; + let meaningRemark = ""; + + if (m12Ratio === 0) { + dataRemark += "查贷比为0。"; + meaningRemark = "【意思解读】查贷比为0表示无查验或借款记录,可能表示您近期没有相关的金融活动。查得标识和库有标识反映了您的信用记录在系统中的存在情况。如果标识为\"查无\"或\"库无\",可能表示您的信用记录不够完整或活跃,建议适当使用金融产品以建立信用记录。"; + } else if (m12Ratio <= 1) { + dataRemark += "查贷比较低。"; + meaningRemark = "【意思解读】查贷比较低说明查验次数少于或等于借款次数,这表明机构对您的关注度相对较低,整体风险可控。较低的查贷比通常意味着您的借款活动正常,机构不需要频繁查验就能评估您的信用状况。这通常是一个积极的信号,表明您的信用记录稳定,机构对您的信任度较高。"; + } else if (m12Ratio <= 3) { + dataRemark += "查贷比适中。"; + meaningRemark = "【意思解读】查贷比适中说明查验与借款比例正常,这是正常的信用评估过程。适度的查验是机构评估您信用状况的正常手段,通常发生在您申请金融产品时。这种比例表明您的信用活动正常,机构对您的关注度在合理范围内。"; + } else { + dataRemark += "查贷比较高。"; + meaningRemark = "【意思解读】查贷比较高说明查验次数明显多于借款次数,可能表示机构对您的关注度较高。这可能是因为您近期有较多的金融申请活动,或者机构需要更频繁地评估您的信用状况。虽然频繁的查验不会直接降低您的信用评分,但可能反映出机构对您的风险关注。建议关注自身信用状况,保持良好的还款记录,减少不必要的金融申请,避免过度查询影响信用形象。"; + } + + return `${dataRemark}\n\n${meaningRemark}`; +} diff --git a/src/ui/JRZQ4B6C/README.md b/src/ui/JRZQ4B6C/README.md index 383e825..d4f36b3 100644 --- a/src/ui/JRZQ4B6C/README.md +++ b/src/ui/JRZQ4B6C/README.md @@ -2,7 +2,7 @@ ## 组件概述 -信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人信用过滤。 +信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人风险过滤。 ## 组件结构 @@ -52,28 +52,28 @@ const probeData = { ## 数据字段说明 -| 字段名 | 类型 | 必填 | 描述 | 示例值 | -|-------|------|------|------|--------| -| result_code | String | 否 | 探查结果编码 | "1" | -| max_overdue_amt | String | 否 | 最大逾期金额 | "1000-2000" | -| max_overdue_days | String | 否 | 最长逾期天数 | "1-15" | -| latest_overdue_time | String | 否 | 最近逾期时间 | "2018-10" | -| max_performance_amt | String | 否 | 最大履约金额 | "1000-2000" | -| latest_performance_time | String | 否 | 最近履约时间 | "2018-10" | -| count_performance | String | 否 | 履约笔数 | "1" | -| currently_overdue | String | 否 | 当前逾期机构数 | "1" | -| currently_performance | String | 否 | 当前履约机构数 | "29" | -| acc_exc | String | 否 | 异常还款机构数 | "0" | -| acc_sleep | String | 否 | 睡眠机构数 | "39" | +| 字段名 | 类型 | 必填 | 描述 | 示例值 | +| ----------------------- | ------ | ---- | -------------- | ----------- | +| result_code | String | 否 | 探查结果编码 | "1" | +| max_overdue_amt | String | 否 | 最大逾期金额 | "1000-2000" | +| max_overdue_days | String | 否 | 最长逾期天数 | "1-15" | +| latest_overdue_time | String | 否 | 最近逾期时间 | "2018-10" | +| max_performance_amt | String | 否 | 最大履约金额 | "1000-2000" | +| latest_performance_time | String | 否 | 最近履约时间 | "2018-10" | +| count_performance | String | 否 | 履约笔数 | "1" | +| currently_overdue | String | 否 | 当前逾期机构数 | "1" | +| currently_performance | String | 否 | 当前履约机构数 | "29" | +| acc_exc | String | 否 | 异常还款机构数 | "0" | +| acc_sleep | String | 否 | 睡眠机构数 | "39" | ## 结果编码说明 -| 编码 | 显示内容 | 探查明细说明 | 风险等级 | -|------|----------|-------------|----------| -| 1 | 用户最近一笔订单未结清 | 用户最近一笔订单未结清 | 高风险 | -| 2 | 用户订单结清情况良好 | 多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清 | 低风险 | -| 3 | 用户最近订单已结清,历史存在未结清订单 | 用户最近一笔订单已结清,但历史存在未结清订单 | 中等风险 | -| 4 | 用户数据不充分 | 数据不充分 | 未知风险 | +| 编码 | 显示内容 | 探查明细说明 | 风险等级 | +| ---- | -------------------------------------- | --------------------------------------------------------------------------------------------------------- | -------- | +| 1 | 用户最近一笔订单未结清 | 用户最近一笔订单未结清 | 高风险 | +| 2 | 用户订单结清情况良好 | 多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清 | 低风险 | +| 3 | 用户最近订单已结清,历史存在未结清订单 | 用户最近一笔订单已结清,但历史存在未结清订单 | 中等风险 | +| 4 | 用户数据不充分 | 数据不充分 | 未知风险 | ### 详细说明 diff --git a/src/ui/JRZQ4B6C/components/ProbeOverview.vue b/src/ui/JRZQ4B6C/components/ProbeOverview.vue index 8f5602f..ae68f74 100644 --- a/src/ui/JRZQ4B6C/components/ProbeOverview.vue +++ b/src/ui/JRZQ4B6C/components/ProbeOverview.vue @@ -90,7 +90,7 @@ const getResultDescription = (code) => { '3': '通过模型计算展现该用户行为画像,用户最近一笔订单已结清,但历史存在未结清订单,建议关注其历史还款记录。', '4': '用户数据不充分无法展现该用户行为画像。建议通过其他征信渠道补充信息进行综合评估。' } - return descriptionMap[code] || '信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人信用过滤。' + return descriptionMap[code] || '信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人风险过滤。' } // 探查明细描述 diff --git a/src/ui/JRZQ4B6C/utils/probeUtils.js b/src/ui/JRZQ4B6C/utils/probeUtils.js index 56d02af..383bfb0 100644 --- a/src/ui/JRZQ4B6C/utils/probeUtils.js +++ b/src/ui/JRZQ4B6C/utils/probeUtils.js @@ -6,72 +6,76 @@ * 结果编码映射 */ export const RESULT_CODE_MAP = { - '1': { - text: '用户最近一笔订单未结清', - description: '通过模型计算展现该用户行为画像,用户最近一笔订单未结清,建议谨慎评估其信用状况和还款能力。', - detail: '用户最近一笔订单未结清', - color: 'text-red-500', - level: 'high' - }, - '2': { - text: '用户订单结清情况良好', - description: '通过模型计算展现该用户行为画像,多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清,信贷表现良好。', - detail: '多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清', - color: 'text-green-500', - level: 'low' - }, - '3': { - text: '用户最近订单已结清,历史存在未结清订单', - description: '通过模型计算展现该用户行为画像,用户最近一笔订单已结清,但历史存在未结清订单,建议关注其历史还款记录。', - detail: '用户最近一笔订单已结清,但历史存在未结清订单', - color: 'text-yellow-500', - level: 'medium' - }, - '4': { - text: '用户数据不充分', - description: '用户数据不充分无法展现该用户行为画像。建议通过其他征信渠道补充信息进行综合评估。', - detail: '数据不充分', - color: 'text-gray-500', - level: 'unknown' - } -} + 1: { + text: "用户最近一笔订单未结清", + description: + "通过模型计算展现该用户行为画像,用户最近一笔订单未结清,建议谨慎评估其信用状况和还款能力。", + detail: "用户最近一笔订单未结清", + color: "text-red-500", + level: "high", + }, + 2: { + text: "用户订单结清情况良好", + description: + "通过模型计算展现该用户行为画像,多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清,信贷表现良好。", + detail: "多笔订单用户最近一笔订单已结清且历史所有订单均已结清,或单笔订单用户该订单发生时间在3个月之内且该订单结清", + color: "text-green-500", + level: "low", + }, + 3: { + text: "用户最近订单已结清,历史存在未结清订单", + description: + "通过模型计算展现该用户行为画像,用户最近一笔订单已结清,但历史存在未结清订单,建议关注其历史还款记录。", + detail: "用户最近一笔订单已结清,但历史存在未结清订单", + color: "text-yellow-500", + level: "medium", + }, + 4: { + text: "用户数据不充分", + description: + "用户数据不充分无法展现该用户行为画像。建议通过其他征信渠道补充信息进行综合评估。", + detail: "数据不充分", + color: "text-gray-500", + level: "unknown", + }, +}; /** * 金额区间映射(根据文档提供的区间) */ export const AMOUNT_RANGES = [ - '(1~1000]', - '(1000~2000]', - '(2000~3000]', - '(3000~4000]', - '(4000~6000]', - '(6000~8000]', - '(8000~10000]', - '(10000~20000]', - '(20000~40000]', - '(40000~60000]', - '(60000~80000]', - '(80000~100000]', - '(100000~150000]', - '(150000~200000]', - '(200000~250000]', - '(250000~300000]', - '(300000~350000]', - '(350000~400000]', - '(400000~450000]', - '(450000~500000]', - '(500000~550000]', - '(550000~600000]', - '(600000~650000]', - '(650000~700000]', - '(700000~750000]', - '(750000~800000]', - '(800000~850000]', - '(850000~900000]', - '(900000~950000]', - '(950000~1000000]', - '>1000000' -] + "(1~1000]", + "(1000~2000]", + "(2000~3000]", + "(3000~4000]", + "(4000~6000]", + "(6000~8000]", + "(8000~10000]", + "(10000~20000]", + "(20000~40000]", + "(40000~60000]", + "(60000~80000]", + "(80000~100000]", + "(100000~150000]", + "(150000~200000]", + "(200000~250000]", + "(250000~300000]", + "(300000~350000]", + "(350000~400000]", + "(400000~450000]", + "(450000~500000]", + "(500000~550000]", + "(550000~600000]", + "(600000~650000]", + "(650000~700000]", + "(700000~750000]", + "(750000~800000]", + "(800000~850000]", + "(850000~900000]", + "(900000~950000]", + "(950000~1000000]", + ">1000000", +]; /** * 获取结果编码信息 @@ -79,13 +83,16 @@ export const AMOUNT_RANGES = [ * @returns {object} 结果编码信息 */ export const getResultCodeInfo = (code) => { - return RESULT_CODE_MAP[code] || { - text: '未知状态', - description: '信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人信用过滤。', - color: 'text-gray-500', - level: 'unknown' - } -} + return ( + RESULT_CODE_MAP[code] || { + text: "未知状态", + description: + "信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人风险过滤。", + color: "text-gray-500", + level: "unknown", + } + ); +}; /** * 格式化金额区间 @@ -93,32 +100,32 @@ export const getResultCodeInfo = (code) => { * @returns {string} 格式化后的金额区间 */ export const formatAmountRange = (amount) => { - if (!amount || amount === '0') { - return '无记录' - } - - // 处理标准区间格式,如 "1000-2000" - if (amount.includes('-')) { - const [min, max] = amount.split('-') - return `${formatNumber(min)}元 - ${formatNumber(max)}元` - } - - // 处理带括号的区间格式,如 "(1000~2000]" - if (amount.includes('~')) { - const cleanAmount = amount.replace(/[()[\]]/g, '') - const [min, max] = cleanAmount.split('~') - return `${formatNumber(min)}元 - ${formatNumber(max)}元` - } - - // 处理大于某个值的格式,如 ">1000000" - if (amount.startsWith('>')) { - const value = amount.substring(1) - return `大于 ${formatNumber(value)}元` - } - - // 其他格式直接返回 - return amount -} + if (!amount || amount === "0") { + return "无记录"; + } + + // 处理标准区间格式,如 "1000-2000" + if (amount.includes("-")) { + const [min, max] = amount.split("-"); + return `${formatNumber(min)}元 - ${formatNumber(max)}元`; + } + + // 处理带括号的区间格式,如 "(1000~2000]" + if (amount.includes("~")) { + const cleanAmount = amount.replace(/[()[\]]/g, ""); + const [min, max] = cleanAmount.split("~"); + return `${formatNumber(min)}元 - ${formatNumber(max)}元`; + } + + // 处理大于某个值的格式,如 ">1000000" + if (amount.startsWith(">")) { + const value = amount.substring(1); + return `大于 ${formatNumber(value)}元`; + } + + // 其他格式直接返回 + return amount; +}; /** * 格式化天数区间 @@ -126,25 +133,25 @@ export const formatAmountRange = (amount) => { * @returns {string} 格式化后的天数区间 */ export const formatDaysRange = (days) => { - if (!days || days === '0') { - return '无记录' - } - - // 处理区间格式,如 "1-15" - if (days.includes('-')) { - const [min, max] = days.split('-') - return `${min}天 - ${max}天` - } - - // 处理带括号的区间格式,如 "[1~15]" - if (days.includes('~')) { - const cleanDays = days.replace(/[()[\]]/g, '') - const [min, max] = cleanDays.split('~') - return `${min}天 - ${max}天` - } - - return days + '天' -} + if (!days || days === "0") { + return "无记录"; + } + + // 处理区间格式,如 "1-15" + if (days.includes("-")) { + const [min, max] = days.split("-"); + return `${min}天 - ${max}天`; + } + + // 处理带括号的区间格式,如 "[1~15]" + if (days.includes("~")) { + const cleanDays = days.replace(/[()[\]]/g, ""); + const [min, max] = cleanDays.split("~"); + return `${min}天 - ${max}天`; + } + + return days + "天"; +}; /** * 格式化时间 @@ -152,23 +159,23 @@ export const formatDaysRange = (days) => { * @returns {string} 格式化后的时间 */ export const formatTime = (time) => { - if (!time) { - return '无记录' - } - - // 处理 YYYY-MM 格式 - if (time.match(/^\d{4}-\d{2}$/)) { - return time.replace('-', '年') + '月' - } - - // 处理 YYYY-MM-DD 格式 - if (time.match(/^\d{4}-\d{2}-\d{2}$/)) { - const [year, month, day] = time.split('-') - return `${year}年${month}月${day}日` - } - - return time -} + if (!time) { + return "无记录"; + } + + // 处理 YYYY-MM 格式 + if (time.match(/^\d{4}-\d{2}$/)) { + return time.replace("-", "年") + "月"; + } + + // 处理 YYYY-MM-DD 格式 + if (time.match(/^\d{4}-\d{2}-\d{2}$/)) { + const [year, month, day] = time.split("-"); + return `${year}年${month}月${day}日`; + } + + return time; +}; /** * 格式化数字,添加千分位分隔符 @@ -176,14 +183,14 @@ export const formatTime = (time) => { * @returns {string} 格式化后的数字 */ export const formatNumber = (num) => { - if (!num) return '0' - - const number = typeof num === 'string' ? parseFloat(num) : num - - if (isNaN(number)) return num - - return number.toLocaleString('zh-CN') -} + if (!num) return "0"; + + const number = typeof num === "string" ? parseFloat(num) : num; + + if (isNaN(number)) return num; + + return number.toLocaleString("zh-CN"); +}; /** * 获取风险等级颜色类名 @@ -191,15 +198,15 @@ export const formatNumber = (num) => { * @returns {string} CSS类名 */ export const getRiskLevelClass = (level) => { - const levelMap = { - 'high': 'text-red-500', - 'medium': 'text-yellow-500', - 'low': 'text-green-500', - 'unknown': 'text-gray-500' - } - - return levelMap[level] || 'text-gray-500' -} + const levelMap = { + high: "text-red-500", + medium: "text-yellow-500", + low: "text-green-500", + unknown: "text-gray-500", + }; + + return levelMap[level] || "text-gray-500"; +}; /** * 获取风险等级背景色类名 @@ -207,15 +214,15 @@ export const getRiskLevelClass = (level) => { * @returns {string} CSS类名 */ export const getRiskLevelBgClass = (level) => { - const levelMap = { - 'high': 'bg-red-50 border-red-200', - 'medium': 'bg-yellow-50 border-yellow-200', - 'low': 'bg-green-50 border-green-200', - 'unknown': 'bg-gray-50 border-gray-200' - } - - return levelMap[level] || 'bg-gray-50 border-gray-200' -} + const levelMap = { + high: "bg-red-50 border-red-200", + medium: "bg-yellow-50 border-yellow-200", + low: "bg-green-50 border-green-200", + unknown: "bg-gray-50 border-gray-200", + }; + + return levelMap[level] || "bg-gray-50 border-gray-200"; +}; /** * 生成信贷表现总结 @@ -223,66 +230,66 @@ export const getRiskLevelBgClass = (level) => { * @returns {object} 风险评估总结 */ export const generateRiskSummary = (data) => { - if (!data) { - return { - level: 'unknown', - text: '无法获取数据进行风险评估', - recommendations: ['建议通过其他渠道获取更多信息'] + if (!data) { + return { + level: "unknown", + text: "无法获取数据进行风险评估", + recommendations: ["建议通过其他渠道获取更多信息"], + }; } - } - - const resultCode = data.result_code - const codeInfo = getResultCodeInfo(resultCode) - - const currentlyOverdue = parseInt(data.currently_overdue) || 0 - const accExc = parseInt(data.acc_exc) || 0 - const accSleep = parseInt(data.acc_sleep) || 0 - - let riskLevel = codeInfo.level - let recommendations = [] - - // 基于结果编码的建议 - switch (resultCode) { - case '1': // 用户最近一笔订单未结清 - recommendations.push('用户最近一笔订单未结清,存在风险') - recommendations.push('建议进一步核实原因和当前还款能力') - recommendations.push('考虑要求提供担保或抵押措施') - break - case '2': // 用户订单结清情况良好 - recommendations.push('用户订单结清情况良好,信贷表现正常') - recommendations.push('可以正常开展业务合作') - recommendations.push('建议定期跟踪信用状况变化') - break - case '3': // 用户最近订单已结清,历史存在未结清订单 - recommendations.push('用户最近订单已结清,但历史存在未结清订单') - recommendations.push('建议关注历史还款记录和还款意愿') - recommendations.push('可考虑适当降低授信额度或增加风控措施') - break - case '4': // 用户数据不充分 - recommendations.push('用户数据不充分,无法完整评估行为画像') - recommendations.push('建议通过其他征信渠道补充信息') - recommendations.push('谨慎开展高风险业务,建议人工审核') - break - } - - // 基于其他指标的额外风险评估 - if (currentlyOverdue > 0) { - riskLevel = 'high' - recommendations.push(`当前有${currentlyOverdue}个机构逾期,风险较高`) - } - - if (accExc > 2) { - if (riskLevel !== 'high') riskLevel = 'medium' - recommendations.push(`存在${accExc}个异常还款机构,需要关注`) - } - - if (accSleep > 10) { - recommendations.push(`有${accSleep}个睡眠机构,信贷活跃度偏低`) - } - - return { - level: riskLevel, - text: codeInfo.description, - recommendations: recommendations - } -} + + const resultCode = data.result_code; + const codeInfo = getResultCodeInfo(resultCode); + + const currentlyOverdue = parseInt(data.currently_overdue) || 0; + const accExc = parseInt(data.acc_exc) || 0; + const accSleep = parseInt(data.acc_sleep) || 0; + + let riskLevel = codeInfo.level; + let recommendations = []; + + // 基于结果编码的建议 + switch (resultCode) { + case "1": // 用户最近一笔订单未结清 + recommendations.push("用户最近一笔订单未结清,存在风险"); + recommendations.push("建议进一步核实原因和当前还款能力"); + recommendations.push("考虑要求提供担保或抵押措施"); + break; + case "2": // 用户订单结清情况良好 + recommendations.push("用户订单结清情况良好,信贷表现正常"); + recommendations.push("可以正常开展业务合作"); + recommendations.push("建议定期跟踪信用状况变化"); + break; + case "3": // 用户最近订单已结清,历史存在未结清订单 + recommendations.push("用户最近订单已结清,但历史存在未结清订单"); + recommendations.push("建议关注历史还款记录和还款意愿"); + recommendations.push("可考虑适当降低授信额度或增加风控措施"); + break; + case "4": // 用户数据不充分 + recommendations.push("用户数据不充分,无法完整评估行为画像"); + recommendations.push("建议通过其他征信渠道补充信息"); + recommendations.push("谨慎开展高风险业务,建议人工审核"); + break; + } + + // 基于其他指标的额外风险评估 + if (currentlyOverdue > 0) { + riskLevel = "high"; + recommendations.push(`当前有${currentlyOverdue}个机构逾期,风险较高`); + } + + if (accExc > 2) { + if (riskLevel !== "high") riskLevel = "medium"; + recommendations.push(`存在${accExc}个异常还款机构,需要关注`); + } + + if (accSleep > 10) { + recommendations.push(`有${accSleep}个睡眠机构,信贷活跃度偏低`); + } + + return { + level: riskLevel, + text: codeInfo.description, + recommendations: recommendations, + }; +}; diff --git a/src/ui/JRZQ6F2A/components/ApplicationCountSection.vue b/src/ui/JRZQ6F2A/components/ApplicationCountSection.vue index 1bb0829..ba22bd1 100644 --- a/src/ui/JRZQ6F2A/components/ApplicationCountSection.vue +++ b/src/ui/JRZQ6F2A/components/ApplicationCountSection.vue @@ -52,6 +52,11 @@ const props = defineProps({ type: Object, required: true, default: () => ({}) + }, + // 维度:id(身份证) / cell(手机号) + dimension: { + type: String, + default: 'id' } }) @@ -61,7 +66,7 @@ const labels = periodKeys.map(key => PERIOD_MAP[key].label) // 总申请次数图表配置 const chartOption = computed(() => { const data = periodKeys.map(key => { - const counts = getApplicationCounts(props.data, key) + const counts = getApplicationCounts(props.data, key, props.dimension) return counts.total }) @@ -90,7 +95,7 @@ const chartOption = computed(() => { type: 'category', data: labels, axisLabel: { - fontSize: 10, + fontSize: 16, color: '#6b7280', rotate: 45 }, @@ -103,7 +108,7 @@ const chartOption = computed(() => { yAxis: { type: 'value', axisLabel: { - fontSize: 11, + fontSize: 16, color: '#6b7280', formatter: '{value} 次' }, @@ -137,11 +142,11 @@ const chartOption = computed(() => { // 特殊时段(周末 / 夜间)图表配置 const specialChartOption = computed(() => { const weekendData = periodKeys.map(key => { - const s = getSpecialPeriodCounts(props.data, key) + const s = getSpecialPeriodCounts(props.data, key, props.dimension) return s.weekend || 0 }) const nightData = periodKeys.map(key => { - const s = getSpecialPeriodCounts(props.data, key) + const s = getSpecialPeriodCounts(props.data, key, props.dimension) return s.night || 0 }) @@ -163,7 +168,7 @@ const specialChartOption = computed(() => { data: ['周末申请次数', '夜间申请次数'], top: '5%', textStyle: { - fontSize: 12 + fontSize: 14 } }, grid: { @@ -177,7 +182,7 @@ const specialChartOption = computed(() => { type: 'category', data: labels, axisLabel: { - fontSize: 10, + fontSize: 16, color: '#6b7280', rotate: 45 }, @@ -190,7 +195,7 @@ const specialChartOption = computed(() => { yAxis: { type: 'value', axisLabel: { - fontSize: 11, + fontSize: 16, color: '#6b7280', formatter: '{value} 次' }, diff --git a/src/ui/JRZQ6F2A/components/ApplicationTotalSection.vue b/src/ui/JRZQ6F2A/components/ApplicationTotalSection.vue index e1411ed..608cf0d 100644 --- a/src/ui/JRZQ6F2A/components/ApplicationTotalSection.vue +++ b/src/ui/JRZQ6F2A/components/ApplicationTotalSection.vue @@ -1,22 +1,18 @@ + + diff --git a/src/ui/JRZQ6F2A/components/BankInstitutionSection.vue b/src/ui/JRZQ6F2A/components/BankInstitutionSection.vue index aeaf1b5..1a1355d 100644 --- a/src/ui/JRZQ6F2A/components/BankInstitutionSection.vue +++ b/src/ui/JRZQ6F2A/components/BankInstitutionSection.vue @@ -1,5 +1,5 @@ diff --git a/src/ui/JRZQ6F2A/components/NBankOrgSection.vue b/src/ui/JRZQ6F2A/components/NBankOrgSection.vue index 2edfd28..7ac594d 100644 --- a/src/ui/JRZQ6F2A/components/NBankOrgSection.vue +++ b/src/ui/JRZQ6F2A/components/NBankOrgSection.vue @@ -1,28 +1,41 @@ diff --git a/src/ui/JRZQ6F2A/components/ProductTypeDistributionSection.vue b/src/ui/JRZQ6F2A/components/ProductTypeDistributionSection.vue index 1165d04..65c62a7 100644 --- a/src/ui/JRZQ6F2A/components/ProductTypeDistributionSection.vue +++ b/src/ui/JRZQ6F2A/components/ProductTypeDistributionSection.vue @@ -8,8 +8,9 @@ -
-
+
+
{{ item.label }} @@ -52,6 +53,11 @@ const props = defineProps({ type: Object, required: true, default: () => ({}) + }, + // 维度:id(身份证) / cell(手机号) + dimension: { + type: String, + default: 'id' } }) @@ -79,7 +85,8 @@ const detailList = computed(() => { const labels = FIELD_LABELS.bank || {} return TYPE_KEYS.map((key, index) => { - const field = `${PREFIX}_id_${key}_allnum` + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + const field = `${PREFIX}_${dimKey}_${key}_allnum` const value = getValue(v[field]) || 0 return { @@ -121,7 +128,7 @@ const chartOption = computed(() => { type: 'category', data: categories, axisLabel: { - fontSize: 10, + fontSize: 13, color: '#6b7280', rotate: 30 }, @@ -134,7 +141,7 @@ const chartOption = computed(() => { yAxis: { type: 'value', axisLabel: { - fontSize: 11, + fontSize: 16, color: '#6b7280', formatter: '{value} 次' }, @@ -170,15 +177,4 @@ const chartOption = computed(() => { width: 100%; height: 100%; } - - -{ -"cells": [], -"metadata": { -"language_info": { -"name": "python" -} -}, -"nbformat": 4, -"nbformat_minor": 2 -} \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/JRZQ6F2A/components/RecentIntensiveApplicationSection.vue b/src/ui/JRZQ6F2A/components/RecentIntensiveApplicationSection.vue index 8226fb0..e117d15 100644 --- a/src/ui/JRZQ6F2A/components/RecentIntensiveApplicationSection.vue +++ b/src/ui/JRZQ6F2A/components/RecentIntensiveApplicationSection.vue @@ -3,34 +3,15 @@
-
-
- 最近在银行连续申请次数 - {{ bankCons }} 次 -
-
- 最近在银行连续申请天数 - {{ bankDays }} 天 -
-
- 最近在非银连续申请次数 - {{ nbankCons }} 次 -
-
- 最近在非银连续申请天数 - {{ nbankDays }} 天 -
-
- 距最近一次在银行机构申请 - {{ bankGap }} 天 -
-
- 距最近一次在非银机构申请 - {{ nbankGap }} 天 +
+
+ {{ item.label }} + {{ item.value }}
-
+
暂未查询到明显的近期集中申请行为。
@@ -48,15 +29,38 @@ const props = defineProps({ required: true, default: () => ({}), }, + // 维度:id(身份证) / cell(手机号) + dimension: { + type: String, + default: 'id', + }, }) -const bankCons = computed(() => getValue(props.data?.als_lst_id_bank_consnum)) -const bankDays = computed(() => getValue(props.data?.als_lst_id_bank_csinteday)) -const nbankCons = computed(() => getValue(props.data?.als_lst_id_nbank_consnum)) -const nbankDays = computed(() => getValue(props.data?.als_lst_id_nbank_csinteday)) +const bankCons = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_bank_consnum`]) +}) +const bankDays = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_bank_csinteday`]) +}) +const nbankCons = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_nbank_consnum`]) +}) +const nbankDays = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_nbank_csinteday`]) +}) -const bankGap = computed(() => getValue(props.data?.als_lst_id_bank_inteday)) -const nbankGap = computed(() => getValue(props.data?.als_lst_id_nbank_inteday)) +const bankGap = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_bank_inteday`]) +}) +const nbankGap = computed(() => { + const dimKey = props.dimension === 'cell' ? 'cell' : 'id' + return getValue(props.data?.[`als_lst_${dimKey}_nbank_inteday`]) +}) const hasAnyData = computed(() => { return ( @@ -68,6 +72,18 @@ const hasAnyData = computed(() => { (nbankGap.value || 0) > 0 ) }) + +// 数据项列表 +const dataItems = computed(() => { + return [ + { label: '最近在银行连续申请次数', value: `${bankCons.value} 次` }, + { label: '最近在银行连续申请天数', value: `${bankDays.value} 天` }, + { label: '最近在非银连续申请次数', value: `${nbankCons.value} 次` }, + { label: '最近在非银连续申请天数', value: `${nbankDays.value} 天` }, + { label: '距最近一次在银行机构申请', value: `${bankGap.value} 天` }, + { label: '距最近一次在非银机构申请', value: `${nbankGap.value} 天` } + ] +}) - - diff --git a/src/ui/JRZQ6F2A/components/RiskSummarySection.vue b/src/ui/JRZQ6F2A/components/RiskSummarySection.vue new file mode 100644 index 0000000..ff0f4dd --- /dev/null +++ b/src/ui/JRZQ6F2A/components/RiskSummarySection.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/ui/JRZQ6F2A/components/SummaryApplyStats.vue b/src/ui/JRZQ6F2A/components/SummaryApplyStats.vue index f20eb7e..a212618 100644 --- a/src/ui/JRZQ6F2A/components/SummaryApplyStats.vue +++ b/src/ui/JRZQ6F2A/components/SummaryApplyStats.vue @@ -1,21 +1,35 @@ + + diff --git a/src/views/PromotionInquire.vue b/src/views/PromotionInquire.vue index bc60c63..2b72a03 100644 --- a/src/views/PromotionInquire.vue +++ b/src/views/PromotionInquire.vue @@ -4,6 +4,7 @@ import { useRoute } from "vue-router"; import { storeToRefs } from 'pinia'; import { useUserStore } from '@/stores/userStore'; import InquireForm from "@/components/InquireForm.vue"; +import WechatOverlay from "@/components/WechatOverlay.vue"; const route = useRoute(); const router = useRouter(); @@ -63,4 +64,5 @@ async function getProduct() { \ No newline at end of file diff --git a/src/views/Report.vue b/src/views/Report.vue index 3f85288..0b5daec 100644 --- a/src/views/Report.vue +++ b/src/views/Report.vue @@ -1,7 +1,7 @@