From 4a7cfde4af419498fb24bbc75a85a8d1e9fd4acf Mon Sep 17 00:00:00 2001 From: wjj <2069666735@qq.com> Date: Thu, 16 Jul 2026 14:47:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=93=E9=A1=B9=E6=8E=92?= =?UTF-8?q?=E6=9F=A5=E8=B5=84=E4=BA=A7=E6=94=B6=E5=85=A5=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E5=8F=A3=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ProjectFamilyAssetLiabilityListItemVO.java | 15 ++ .../vo/CcdiProjectFamilyIncomeDetailVO.java | 6 + .../CcdiProjectSpecialCheckServiceImpl.java | 1 + .../project/CcdiProjectSpecialCheckMapper.xml | 153 ++++++++++++------ ...t-income-caliber-backend-implementation.md | 39 +++++ ...-income-caliber-frontend-implementation.md | 42 +++++ ...7-16-special-check-asset-income-caliber.md | 32 ++++ .../detail/FamilyAssetLiabilityDetail.vue | 88 ++++++++-- .../detail/FamilyAssetLiabilitySection.vue | 11 +- 9 files changed, 315 insertions(+), 72 deletions(-) create mode 100644 docs/plans/backend/2026-07-16-special-check-asset-income-caliber-backend-implementation.md create mode 100644 docs/plans/frontend/2026-07-16-special-check-asset-income-caliber-frontend-implementation.md create mode 100644 docs/reports/implementation/2026-07-16-special-check-asset-income-caliber.md diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java index 23b90ed2..9786c464 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java @@ -24,6 +24,15 @@ public class CcdiProjectFamilyAssetLiabilityListItemVO { /** 家庭总年收入 */ private BigDecimal totalIncome; + /** 本人年收入 */ + private BigDecimal selfIncome; + + /** 配偶年收入 */ + private BigDecimal spouseIncome; + + /** 本人入职年限 */ + private Integer employmentYears; + /** 家庭总资产 */ private BigDecimal totalAsset; @@ -33,6 +42,12 @@ public class CcdiProjectFamilyAssetLiabilityListItemVO { /** 收入负债对比金额 */ private BigDecimal comparisonAmount; + /** 可解释收入 */ + private BigDecimal explainableIncome; + + /** 资产收入倍数 */ + private BigDecimal assetIncomeRatio; + /** 风险等级编码 */ private String riskLevelCode; diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java index ee2ddb43..5d0b23d0 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java @@ -15,6 +15,12 @@ public class CcdiProjectFamilyIncomeDetailVO { /** 配偶年收入 */ private BigDecimal spouseIncome; + /** 本人入职年限 */ + private Integer employmentYears; + /** 家庭总年收入 */ private BigDecimal totalIncome; + + /** 可解释收入 */ + private BigDecimal explainableIncome; } diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java index 5cb4f093..74aa690a 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java @@ -227,6 +227,7 @@ public class CcdiProjectSpecialCheckServiceImpl implements ICcdiProjectSpecialCh incomeDetail.setSelfIncome(BigDecimal.ZERO); incomeDetail.setSpouseIncome(BigDecimal.ZERO); incomeDetail.setTotalIncome(BigDecimal.ZERO); + incomeDetail.setExplainableIncome(BigDecimal.ZERO); detail.setIncomeDetail(incomeDetail); } diff --git a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml index d913cc05..9e585bf4 100644 --- a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml +++ b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml @@ -9,9 +9,14 @@ + + + + + @@ -95,7 +100,9 @@ javaType="com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyIncomeDetailVO"> + + @@ -126,9 +133,14 @@ + + + + + @@ -194,44 +206,58 @@ aggregated.staff_name, aggregated.dept_name, aggregated.total_income, + aggregated.self_income, + aggregated.spouse_income, + aggregated.employment_years, aggregated.total_asset, aggregated.total_debt, aggregated.comparison_amount, + aggregated.explainable_income, + aggregated.asset_income_ratio, case - when aggregated.missing_asset_info = 1 or aggregated.missing_debt_info = 1 then 'MISSING_INFO' - when comparison_amount <= total_asset * 1.5 then 'NORMAL' - when comparison_amount > total_asset * 1.5 and comparison_amount <= total_asset * 3 then 'RISK' - when comparison_amount > total_asset * 3 then 'HIGH' + when aggregated.missing_info = 1 then 'MISSING_INFO' + when aggregated.asset_income_ratio <= 1.5 then 'NORMAL' + when aggregated.asset_income_ratio > 1.5 and aggregated.asset_income_ratio <= 3 then 'RISK' + when aggregated.asset_income_ratio > 3 then 'HIGH' else 'HIGH' end as risk_level_code, case - when aggregated.missing_asset_info = 1 or aggregated.missing_debt_info = 1 then '缺少信息' - when comparison_amount <= total_asset * 1.5 then '正常' - when comparison_amount > total_asset * 1.5 and comparison_amount <= total_asset * 3 then '存在风险' - when comparison_amount > total_asset * 3 then '高风险' - else '高风险' + when aggregated.missing_info = 1 then '缺少信息' + when aggregated.asset_income_ratio <= 1.5 then '正常' + when aggregated.asset_income_ratio > 1.5 and aggregated.asset_income_ratio <= 3 then '关注' + when aggregated.asset_income_ratio > 3 then '高关注' + else '高关注' end as risk_level_name from ( select source.*, case - when source.self_asset_record_count = 0 - or source.spouse_staff_asset_record_count = 0 then 1 + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 then 1 else 0 - end as missing_asset_info, + end as missing_info, + source.self_income * source.employment_years + + source.spouse_income + + source.total_debt as explainable_income, + source.self_income * source.employment_years + + source.spouse_income + + source.total_debt as comparison_amount, case - when source.self_debt_record_count = 0 - or source.spouse_staff_debt_record_count = 0 then 1 - else 0 - end as missing_debt_info, + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 + or (source.self_income * source.employment_years + source.spouse_income + source.total_debt) <= 0 then null + else source.total_asset / (source.self_income * source.employment_years + source.spouse_income + source.total_debt) + end as asset_income_ratio, case - when source.self_asset_record_count = 0 - or source.spouse_staff_asset_record_count = 0 - or source.self_debt_record_count = 0 - or source.spouse_staff_debt_record_count = 0 then 4 - when source.comparison_amount <= source.total_asset * 1.5 then 1 - when source.comparison_amount <= source.total_asset * 3 then 2 - when source.comparison_amount > source.total_asset * 3 then 3 + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 + or (source.self_income * source.employment_years + source.spouse_income + source.total_debt) <= 0 then 0 + when source.total_asset / (source.self_income * source.employment_years + source.spouse_income + source.total_debt) <= 1.5 then 1 + when source.total_asset / (source.self_income * source.employment_years + source.spouse_income + source.total_debt) <= 3 then 2 + when source.total_asset / (source.self_income * source.employment_years + source.spouse_income + source.total_debt) > 3 then 3 else 3 end as risk_level_sort from ( @@ -240,6 +266,12 @@ scope.staff_code, scope.staff_name, scope.dept_name, + coalesce(base_staff.annual_income, 0) as self_income, + coalesce(spouse.spouse_income, 0) as spouse_income, + case + when base_staff.hire_date is null then null + else greatest(1, ceiling(datediff(curdate(), base_staff.hire_date) / 365)) + end as employment_years, coalesce(base_staff.annual_income, 0) + coalesce(spouse.spouse_income, 0) as total_income, coalesce(( select count(1) @@ -294,15 +326,7 @@ from ccdi_debts_info debt where debt.person_id = scope.staff_id_card or (spouse.spouse_id_card is not null and debt.person_id = spouse.spouse_id_card) - ), 0) as total_debt, - coalesce(base_staff.annual_income, 0) - + coalesce(spouse.spouse_income, 0) - + coalesce(( - select sum(coalesce(debt.principal_balance, 0)) - from ccdi_debts_info debt - where debt.person_id = scope.staff_id_card - or (spouse.spouse_id_card is not null and debt.person_id = spouse.spouse_id_card) - ), 0) as comparison_amount + ), 0) as total_debt from ( ) scope @@ -328,7 +352,9 @@ aggregated.dept_name, aggregated.self_income as income_self_income, aggregated.spouse_income as income_spouse_income, + aggregated.employment_years as income_employment_years, aggregated.total_income as income_total_income, + aggregated.explainable_income as income_explainable_income, aggregated.missing_self_asset_info as asset_missing_self_asset_info, aggregated.self_total_asset as asset_self_total_asset, aggregated.spouse_total_asset as asset_spouse_total_asset, @@ -342,36 +368,61 @@ aggregated.staff_name as summary_staff_name, aggregated.dept_name as summary_dept_name, aggregated.total_income as summary_total_income, + aggregated.self_income as summary_self_income, + aggregated.spouse_income as summary_spouse_income, + aggregated.employment_years as summary_employment_years, aggregated.total_asset as summary_total_asset, aggregated.total_debt as summary_total_debt, aggregated.comparison_amount as summary_comparison_amount, + aggregated.explainable_income as summary_explainable_income, + aggregated.asset_income_ratio as summary_asset_income_ratio, case - when aggregated.missing_self_asset_info = 1 or aggregated.missing_self_debt_info = 1 then 'MISSING_INFO' - when comparison_amount <= total_asset * 1.5 then 'NORMAL' - when comparison_amount > total_asset * 1.5 and comparison_amount <= total_asset * 3 then 'RISK' - when comparison_amount > total_asset * 3 then 'HIGH' + when aggregated.missing_info = 1 then 'MISSING_INFO' + when aggregated.asset_income_ratio <= 1.5 then 'NORMAL' + when aggregated.asset_income_ratio > 1.5 and aggregated.asset_income_ratio <= 3 then 'RISK' + when aggregated.asset_income_ratio > 3 then 'HIGH' else 'HIGH' end as summary_risk_level_code, case - when aggregated.missing_self_asset_info = 1 or aggregated.missing_self_debt_info = 1 then '缺少信息' - when comparison_amount <= total_asset * 1.5 then '正常' - when comparison_amount > total_asset * 1.5 and comparison_amount <= total_asset * 3 then '存在风险' - when comparison_amount > total_asset * 3 then '高风险' - else '高风险' + when aggregated.missing_info = 1 then '缺少信息' + when aggregated.asset_income_ratio <= 1.5 then '正常' + when aggregated.asset_income_ratio > 1.5 and aggregated.asset_income_ratio <= 3 then '关注' + when aggregated.asset_income_ratio > 3 then '高关注' + else '高关注' end as summary_risk_level_name from ( select source.*, case - when source.self_asset_record_count = 0 - or source.spouse_staff_asset_record_count = 0 then 1 + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 then 1 else 0 end as missing_self_asset_info, case when source.self_debt_record_count = 0 or source.spouse_staff_debt_record_count = 0 then 1 else 0 - end as missing_self_debt_info + end as missing_self_debt_info, + case + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 then 1 + else 0 + end as missing_info, + source.self_income * source.employment_years + + source.spouse_income + + source.total_debt as explainable_income, + source.self_income * source.employment_years + + source.spouse_income + + source.total_debt as comparison_amount, + case + when source.self_income <= 0 + or source.employment_years is null + or source.total_asset <= 0 + or (source.self_income * source.employment_years + source.spouse_income + source.total_debt) <= 0 then null + else source.total_asset / (source.self_income * source.employment_years + source.spouse_income + source.total_debt) + end as asset_income_ratio from ( select #{projectId} as project_id, @@ -383,6 +434,10 @@ spouse.spouse_is_staff, coalesce(base_staff.annual_income, 0) as self_income, coalesce(spouse.spouse_income, 0) as spouse_income, + case + when base_staff.hire_date is null then null + else greatest(1, ceiling(datediff(curdate(), base_staff.hire_date) / 365)) + end as employment_years, coalesce(base_staff.annual_income, 0) + coalesce(spouse.spouse_income, 0) as total_income, coalesce(( select count(1) @@ -471,15 +526,7 @@ from ccdi_debts_info debt where debt.person_id = scope.staff_id_card or (spouse.spouse_id_card is not null and debt.person_id = spouse.spouse_id_card) - ), 0) as total_debt, - coalesce(base_staff.annual_income, 0) - + coalesce(spouse.spouse_income, 0) - + coalesce(( - select sum(coalesce(debt.principal_balance, 0)) - from ccdi_debts_info debt - where debt.person_id = scope.staff_id_card - or (spouse.spouse_id_card is not null and debt.person_id = spouse.spouse_id_card) - ), 0) as comparison_amount + ), 0) as total_debt from ( ) scope diff --git a/docs/plans/backend/2026-07-16-special-check-asset-income-caliber-backend-implementation.md b/docs/plans/backend/2026-07-16-special-check-asset-income-caliber-backend-implementation.md new file mode 100644 index 00000000..4a6d4043 --- /dev/null +++ b/docs/plans/backend/2026-07-16-special-check-asset-income-caliber-backend-implementation.md @@ -0,0 +1,39 @@ +# 专项排查资产收入匹配口径后端实施计划 + +## 保存路径确认 + +本文档保存于 `docs/plans/backend/`,用于记录专项排查后端口径调整计划。 + +## 背景 + +专项排查家庭资产负债原逻辑将无负债记录判为缺少信息,且使用收入、负债、资产之间的旧比较方式,无法满足“无负债仍需输出资产收入匹配判断”的业务口径。 + +## 实施范围 + +- 调整 `CcdiProjectSpecialCheckMapper.xml` 中家庭资产负债列表与详情查询。 +- 保留家庭总年收入、家庭总资产、家庭总负债等原字段。 +- 新增本人年收入、配偶年收入、本人入职年限、可解释收入、资产收入倍数等返回字段。 +- 风险等级统一为 `高关注`、`关注`、`正常`、`缺少信息`。 + +## 计算口径 + +- 本人年收入取 `ccdi_base_staff.annual_income`。 +- 本人入职年限由 `ccdi_base_staff.hire_date` 按当前日期折算,不足 1 年按 1 年。 +- 配偶年收入取配偶员工年收入或亲属关系年收入。 +- 家庭总资产取本人及配偶 `ccdi_asset_info.current_value` 合计。 +- 家庭总负债取本人及配偶 `ccdi_debts_info.principal_balance` 合计,无记录按 0。 +- 可解释收入 = 本人年收入 × 本人入职年限 + 配偶年收入 + 家庭总负债。 +- 资产收入倍数 = 家庭总资产 / 可解释收入。 + +## 风险规则 + +- 缺少信息:本人年收入为空或小于等于 0、入职时间为空、家庭总资产为空或小于等于 0。 +- 正常:资产收入倍数小于等于 1.5。 +- 关注:资产收入倍数大于 1.5 且小于等于 3。 +- 高关注:资产收入倍数大于 3。 + +## 验证计划 + +- 执行后端编译或针对 `ccdi-project` 模块的编译检查。 +- 检查 MyBatis XML 中新增字段映射与 SQL 别名一致。 +- 对典型数据进行公式复核:年收入 20 万、入职 10 年、资产 586 万、负债 0 时应为关注。 diff --git a/docs/plans/frontend/2026-07-16-special-check-asset-income-caliber-frontend-implementation.md b/docs/plans/frontend/2026-07-16-special-check-asset-income-caliber-frontend-implementation.md new file mode 100644 index 00000000..1a57c3ac --- /dev/null +++ b/docs/plans/frontend/2026-07-16-special-check-asset-income-caliber-frontend-implementation.md @@ -0,0 +1,42 @@ +# 专项排查资产收入匹配口径前端实施计划 + +## 保存路径确认 + +本文档保存于 `docs/plans/frontend/`,用于记录专项排查前端展示调整计划。 + +## 背景 + +专项排查家庭资产负债详情需要展示新的资产收入匹配结论,并将家庭总年收入改为万元展示,便于业务人员阅读。 + +## 实施范围 + +- 调整 `FamilyAssetLiabilitySection.vue` 列表中的家庭总年收入展示为万元。 +- 调整 `FamilyAssetLiabilityDetail.vue` 总收入、本人收入、配偶收入展示为万元。 +- 将详查结果结论改为分行展示。 +- 结论显示风险等级、家庭总资产、可解释收入公式和资产收入倍数。 + +## 展示口径 + +详查结果结论示例: + +```text +关注 + +家庭总资产:586.00 万元 +可解释收入:本人年收入 20.00 万元 × 入职年限 10 年 + 配偶年收入 0.00 万元 + 家庭总负债 0.00 万元 = 200.00 万元 +资产收入倍数:2.93 +``` + +缺少信息时仅显示: + +```text +缺少资产,暂无法判断。 +``` + +缺少项会按实际情况展示为收入、资产或入职时间;多项同时缺失时展示“关键信息不完整,暂无法判断。”。 + +## 验证计划 + +- 执行前端构建或静态编译检查。 +- 页面验证专项排查列表家庭总年收入为万元。 +- 页面验证详查结果按多行展示,且长公式不溢出容器。 diff --git a/docs/reports/implementation/2026-07-16-special-check-asset-income-caliber.md b/docs/reports/implementation/2026-07-16-special-check-asset-income-caliber.md new file mode 100644 index 00000000..da2c186d --- /dev/null +++ b/docs/reports/implementation/2026-07-16-special-check-asset-income-caliber.md @@ -0,0 +1,32 @@ +# 专项排查资产收入匹配口径实施记录 + +## 保存路径确认 + +本文档保存于 `docs/reports/implementation/`,用于记录本次专项排查口径调整的实施内容、影响范围与验证情况。 + +## 修改内容 + +- 后端专项排查家庭资产负债查询新增本人年收入、配偶年收入、入职年限、可解释收入、资产收入倍数。 +- 后端风险结论改为 `高关注`、`关注`、`正常`、`缺少信息`。 +- 无负债记录不再阻断结论判断,负债金额按 0 纳入可解释收入。 +- 前端专项排查列表中家庭总年收入改为万元展示。 +- 前端详查结果改为分行展示家庭总资产、可解释收入公式与资产收入倍数。 +- 缺少信息结论按实际缺项展示收入、资产或入职时间,多项缺失时展示关键信息不完整。 +- 隐藏家庭资产负债表格内置展开箭头,保留“查看详情”按钮作为展开入口,避免展开箭头挤在序号列前导致显示异常。 + +## 影响范围 + +- `ccdi-project` 专项排查家庭资产负债接口。 +- `ruoyi-ui` 项目详情专项排查家庭资产负债列表与展开详情。 +- 不涉及员工信息维护、资产导入、征信负债导入和数据库结构变更。 + +## 验证情况 + +- 已执行 `mvn -pl ccdi-project -am compile -DskipTests`,编译通过。执行过程中 Maven 提示 `ccdi-info-collection` 中存在既有重复依赖声明警告,本次未调整该无关问题。 +- 已执行前端 Node 环境确认。`.nvmrc` 指向 `14.21.3`,但本机 PowerShell 环境下 `nvm use` 未能直接切换该版本;按仓库约定改用已验证可用的 `Node v22.22.3`、`npm 10.9.8`。 +- 已执行 `npm run build:prod`,生产构建通过。构建输出存在既有资源体积警告,本次未调整该无关问题。 +- 已重新完整打包并启动真实后端 `ruoyi-admin.jar`,确认 62318 端口由本仓库 Java 进程监听,日志出现 `Started RuoYiApplication`。 +- 已在真实页面验证项目 42:员工“模型二测试员工”有收入、有入职时间、有资产、无负债,列表家庭总年收入展示为 `12.35 万元`,风险情况为 `正常`;详查结果展示 `本人年收入 12.35 万元 × 入职年限 7 年 + 配偶年收入 0.00 万元 + 家庭总负债 0.00 万元 = 86.42 万元`。 +- 已在真实页面验证项目 44:同一项目内两名员工均可按新口径展示,列表家庭总年收入分别展示为 `24.35 万元`、`12.35 万元`,风险情况为 `正常`。 +- 已在真实页面验证项目 90629002:员工有收入和入职时间但无资产,列表风险情况为 `缺少信息`,详查结果显示 `缺少资产,暂无法判断。` +- 已在真实页面验证家庭资产负债表格展开箭头隐藏生效,序号列前不再显示异常符号;继续通过“查看详情”展开明细。 diff --git a/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilityDetail.vue b/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilityDetail.vue index e7a0ce6d..1ba129ad 100644 --- a/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilityDetail.vue +++ b/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilityDetail.vue @@ -4,16 +4,16 @@
总收入
-
{{ formatAmount(totalIncome) }}
+
{{ formatWanAmount(totalIncome) }}
本人收入 - {{ formatAmount(incomeDetail.selfIncome) }} + {{ formatWanAmount(incomeDetail.selfIncome) }}
配偶收入 - {{ formatAmount(incomeDetail.spouseIncome) }} + {{ formatWanAmount(incomeDetail.spouseIncome) }}
@@ -69,7 +69,7 @@ {{ assetDebtRatio }}
- 资产/收入比 + 资产收入倍数 {{ assetIncomeRatio }}
@@ -86,7 +86,9 @@
结论
-
{{ riskResult.text }}
+
+
{{ line }}
+
@@ -115,7 +117,9 @@ export default { : { selfIncome: 0, spouseIncome: 0, + employmentYears: null, totalIncome: 0, + explainableIncome: 0, }; }, summary() { @@ -160,6 +164,15 @@ export default { totalDebt() { return this.resolveAmount(this.summary.totalDebt, this.debtDetail.totalDebt); }, + employmentYears() { + const target = this.summary.employmentYears !== undefined && this.summary.employmentYears !== null + ? this.summary.employmentYears + : this.incomeDetail.employmentYears; + return target === undefined || target === null || target === "" ? null : Number(target); + }, + explainableIncome() { + return this.resolveAmount(this.summary.explainableIncome, this.incomeDetail.explainableIncome); + }, assetItems() { return Array.isArray(this.assetDetail.items) ? this.assetDetail.items : []; }, @@ -184,12 +197,10 @@ export default { isPercent: true, }); }, - // 资产/收入比 = totalAsset / totalIncome + // 资产收入倍数 = totalAsset / explainableIncome assetIncomeRatio() { - return this.formatMetricValue(this.totalAsset / this.totalIncome, { - denominator: this.totalIncome, - suffix: "倍", - }); + const ratio = this.resolveRatio(this.summary.assetIncomeRatio, this.totalAsset, this.explainableIncome); + return this.formatRatio(ratio); }, // 负债/收入比 = totalDebt / totalIncome debtIncomeRatio() { @@ -202,22 +213,22 @@ export default { const riskResultMap = { NORMAL: { name: this.summary.riskLevelName || "正常", - text: "结构基本合理", + lines: this.buildResultLines(), type: "success", }, RISK: { - name: this.summary.riskLevelName || "存在风险", - text: "负债与收入压力偏高", + name: this.summary.riskLevelName || "关注", + lines: this.buildResultLines(), type: "warning", }, HIGH: { - name: this.summary.riskLevelName || "高风险", - text: "资产负债结构明显异常", + name: this.summary.riskLevelName || "高关注", + lines: this.buildResultLines(), type: "danger", }, MISSING_INFO: { name: this.summary.riskLevelName || "缺少信息", - text: "当前信息不完整", + lines: [this.buildMissingInfoLine()], type: "info", }, }; @@ -246,6 +257,46 @@ export default { maximumFractionDigits: 2, })} 万元`; }, + buildResultLines() { + return [ + `家庭总资产:${this.formatWanAmount(this.totalAsset)}`, + `可解释收入:本人年收入 ${this.formatWanAmount(this.incomeDetail.selfIncome)} × 入职年限 ${this.employmentYears || "-"} 年 + 配偶年收入 ${this.formatWanAmount(this.incomeDetail.spouseIncome)} + 家庭总负债 ${this.formatWanAmount(this.totalDebt)} = ${this.formatWanAmount(this.explainableIncome)}`, + `资产收入倍数:${this.formatRatio(this.resolveRatio(this.summary.assetIncomeRatio, this.totalAsset, this.explainableIncome))}`, + ]; + }, + buildMissingInfoLine() { + const missing = []; + if (this.resolveAmount(this.incomeDetail.selfIncome) <= 0) { + missing.push("收入"); + } + if (this.resolveAmount(this.totalAsset) <= 0) { + missing.push("资产"); + } + if (!this.employmentYears) { + missing.push("入职时间"); + } + return missing.length === 1 + ? `缺少${missing[0]},暂无法判断。` + : "关键信息不完整,暂无法判断。"; + }, + resolveRatio(preferred, numerator, denominator) { + if (preferred !== undefined && preferred !== null && preferred !== "") { + const ratio = Number(preferred); + return Number.isFinite(ratio) ? ratio : null; + } + const divisor = Number(denominator || 0); + if (!divisor) { + return null; + } + const ratio = Number(numerator || 0) / divisor; + return Number.isFinite(ratio) ? ratio : null; + }, + formatRatio(value) { + if (value === null || value === undefined || !Number.isFinite(Number(value))) { + return "-"; + } + return Number(value).toFixed(2); + }, buildAmountGroups(items, amountField, resolveLabel, totalAmount) { const groupMap = items.reduce((result, item, index) => { const label = resolveLabel(item); @@ -467,6 +518,11 @@ export default { color: #111827; } +.result-card-line { + line-height: 1.7; + word-break: break-word; +} + .empty-hint { font-size: 13px; color: #94a3b8; diff --git a/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilitySection.vue b/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilitySection.vue index 6409ebe6..b84c78cc 100644 --- a/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilitySection.vue +++ b/ruoyi-ui/src/views/ccdiProject/components/detail/FamilyAssetLiabilitySection.vue @@ -19,7 +19,7 @@ - +