调整专项排查资产收入匹配口径
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ public class CcdiProjectFamilyIncomeDetailVO {
|
||||
/** 配偶年收入 */
|
||||
private BigDecimal spouseIncome;
|
||||
|
||||
/** 本人入职年限 */
|
||||
private Integer employmentYears;
|
||||
|
||||
/** 家庭总年收入 */
|
||||
private BigDecimal totalIncome;
|
||||
|
||||
/** 可解释收入 */
|
||||
private BigDecimal explainableIncome;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,14 @@
|
||||
<result property="staffName" column="staff_name"/>
|
||||
<result property="deptName" column="dept_name"/>
|
||||
<result property="totalIncome" column="total_income"/>
|
||||
<result property="selfIncome" column="self_income"/>
|
||||
<result property="spouseIncome" column="spouse_income"/>
|
||||
<result property="employmentYears" column="employment_years"/>
|
||||
<result property="totalAsset" column="total_asset"/>
|
||||
<result property="totalDebt" column="total_debt"/>
|
||||
<result property="comparisonAmount" column="comparison_amount"/>
|
||||
<result property="explainableIncome" column="explainable_income"/>
|
||||
<result property="assetIncomeRatio" column="asset_income_ratio"/>
|
||||
<result property="riskLevelCode" column="risk_level_code"/>
|
||||
<result property="riskLevelName" column="risk_level_name"/>
|
||||
</resultMap>
|
||||
@@ -95,7 +100,9 @@
|
||||
javaType="com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyIncomeDetailVO">
|
||||
<result property="selfIncome" column="income_self_income"/>
|
||||
<result property="spouseIncome" column="income_spouse_income"/>
|
||||
<result property="employmentYears" column="income_employment_years"/>
|
||||
<result property="totalIncome" column="income_total_income"/>
|
||||
<result property="explainableIncome" column="income_explainable_income"/>
|
||||
</association>
|
||||
<association property="assetDetail"
|
||||
javaType="com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetDetailVO">
|
||||
@@ -126,9 +133,14 @@
|
||||
<result property="staffName" column="summary_staff_name"/>
|
||||
<result property="deptName" column="summary_dept_name"/>
|
||||
<result property="totalIncome" column="summary_total_income"/>
|
||||
<result property="selfIncome" column="summary_self_income"/>
|
||||
<result property="spouseIncome" column="summary_spouse_income"/>
|
||||
<result property="employmentYears" column="summary_employment_years"/>
|
||||
<result property="totalAsset" column="summary_total_asset"/>
|
||||
<result property="totalDebt" column="summary_total_debt"/>
|
||||
<result property="comparisonAmount" column="summary_comparison_amount"/>
|
||||
<result property="explainableIncome" column="summary_explainable_income"/>
|
||||
<result property="assetIncomeRatio" column="summary_asset_income_ratio"/>
|
||||
<result property="riskLevelCode" column="summary_risk_level_code"/>
|
||||
<result property="riskLevelName" column="summary_risk_level_name"/>
|
||||
</association>
|
||||
@@ -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 (
|
||||
<include refid="projectEmployeeScopeSql"/>
|
||||
) 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 (
|
||||
<include refid="projectEmployeeScopeSql"/>
|
||||
) scope
|
||||
|
||||
@@ -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 时应为关注。
|
||||
@@ -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
|
||||
缺少资产,暂无法判断。
|
||||
```
|
||||
|
||||
缺少项会按实际情况展示为收入、资产或入职时间;多项同时缺失时展示“关键信息不完整,暂无法判断。”。
|
||||
|
||||
## 验证计划
|
||||
|
||||
- 执行前端构建或静态编译检查。
|
||||
- 页面验证专项排查列表家庭总年收入为万元。
|
||||
- 页面验证详查结果按多行展示,且长公式不溢出容器。
|
||||
@@ -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:员工有收入和入职时间但无资产,列表风险情况为 `缺少信息`,详查结果显示 `缺少资产,暂无法判断。`
|
||||
- 已在真实页面验证家庭资产负债表格展开箭头隐藏生效,序号列前不再显示异常符号;继续通过“查看详情”展开明细。
|
||||
@@ -4,16 +4,16 @@
|
||||
<section class="detail-block">
|
||||
<div class="block-header section-header">
|
||||
<div class="block-title">总收入</div>
|
||||
<div class="section-summary-value">{{ formatAmount(totalIncome) }}</div>
|
||||
<div class="section-summary-value">{{ formatWanAmount(totalIncome) }}</div>
|
||||
</div>
|
||||
<div class="detail-metric-list">
|
||||
<div class="detail-metric-item">
|
||||
<span class="metric-label">本人收入</span>
|
||||
<span class="metric-value">{{ formatAmount(incomeDetail.selfIncome) }}</span>
|
||||
<span class="metric-value">{{ formatWanAmount(incomeDetail.selfIncome) }}</span>
|
||||
</div>
|
||||
<div class="detail-metric-item">
|
||||
<span class="metric-label">配偶收入</span>
|
||||
<span class="metric-value">{{ formatAmount(incomeDetail.spouseIncome) }}</span>
|
||||
<span class="metric-value">{{ formatWanAmount(incomeDetail.spouseIncome) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -69,7 +69,7 @@
|
||||
<span class="metric-card-value">{{ assetDebtRatio }}</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span class="metric-card-label">资产/收入比</span>
|
||||
<span class="metric-card-label">资产收入倍数</span>
|
||||
<span class="metric-card-value">{{ assetIncomeRatio }}</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
@@ -86,7 +86,9 @@
|
||||
</div>
|
||||
<div class="result-card" :class="[`result-card--${riskResult.type}`]">
|
||||
<div class="result-card-label">结论</div>
|
||||
<div class="result-card-value">{{ riskResult.text }}</div>
|
||||
<div class="result-card-value">
|
||||
<div v-for="line in riskResult.lines" :key="line" class="result-card-line">{{ line }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -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;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<template slot="empty">
|
||||
<el-empty :image-size="80" description="暂无员工家庭资产负债核查数据" />
|
||||
</template>
|
||||
<el-table-column type="expand" width="1">
|
||||
<el-table-column type="expand" width="1" class-name="family-expand-column">
|
||||
<template slot-scope="scope">
|
||||
<div class="family-detail-wrapper">
|
||||
<div class="family-detail-toolbar">
|
||||
@@ -47,7 +47,7 @@
|
||||
<el-table-column prop="deptName" label="所属部门" min-width="140" />
|
||||
<el-table-column label="家庭总年收入" min-width="140">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatAmount(scope.row.totalIncome) }}</span>
|
||||
<span>{{ formatWanAmount(scope.row.totalIncome) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="家庭总负债" min-width="140">
|
||||
@@ -201,7 +201,7 @@ export default {
|
||||
}
|
||||
const detail = this.detailCache[row.staffIdCard] || {};
|
||||
const summary = detail.summary || {};
|
||||
const evidenceSummary = `${row.staffName}家庭资产负债核查:家庭总年收入${this.formatAmount(row.totalIncome)},家庭总负债${this.formatAmount(row.totalDebt)},家庭总资产${this.formatWanAmount(row.totalAsset)},风险情况${row.riskLevelName || "-" }。`;
|
||||
const evidenceSummary = `${row.staffName}家庭资产负债核查:家庭总年收入${this.formatWanAmount(row.totalIncome)},家庭总负债${this.formatAmount(row.totalDebt)},家庭总资产${this.formatWanAmount(row.totalAsset)},风险情况${row.riskLevelName || "-" }。`;
|
||||
this.$emit("evidence-confirm", {
|
||||
evidenceType: "ASSET",
|
||||
relatedPersonName: row.staffName || "关联人员",
|
||||
@@ -291,4 +291,9 @@ export default {
|
||||
background: #f8fafc;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
::v-deep .family-expand-column .cell,
|
||||
::v-deep .family-expand-column .el-table__expand-icon {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user