# 结果总览项目分析弹窗真实详情设计

**日期**: 2026-03-25  
**模块**: 初核项目详情 - 结果总览  
**作者**: Codex  
**状态**: 已确认

## 1. 概述

现有 `结果总览` 页的“项目分析”弹窗已完成前端壳子，但弹窗内容仍依赖本地静态拼装：

- 弹窗宽度偏窄，流水类信息阅读空间不足
- `异常明细` 仍使用本地 mock 数据
- 左侧 `人员基础信息` 未读取员工信息表真实数据
- `命中模型摘要` 当前由弹窗内部拼装，和入口上下文绑定不清晰

本次设计只解决上述真实详情接入问题，目标是在保留现有弹窗结构的前提下，把“查看详情”改造成可查询真实人员详情和真实异常明细的工作台弹窗。

## 2. 设计目标

### 2.1 包含内容

- 调整 `项目分析` 弹窗宽度
- 新增结果总览详情专用后端接口
- `人员基础信息` 改为读取员工信息表真实数据
- `异常明细` 改为调用真实接口返回
- `命中模型摘要` 改为由外部列表透传进入弹窗
- `异常明细` 中：
  - 流水维度异常按表格展示
  - `object` 类型异常标签按摘要卡展示

### 2.2 不包含内容

- 不改造项目详情页路由和导航
- 不扩展弹窗内 `资产分析 / 征信摘要 / 关系图谱 / 资金流向` 的真实接口
- 不把弹窗拆成新页面
- 不向现有列表接口塞入详情字段
- 不增加兼容分支、降级分支或补丁式旁路方案

## 3. 当前上下文

当前相关前端文件：

- `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisSidebar.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisAbnormalTab.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js`

当前相关后端文件：

- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementController.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java`
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiBaseStaff.java`

当前问题：

1. 弹窗宽度固定为 `1280px`，流水类表格列空间不足
2. 异常明细页仍是“当前行数据 + 静态模板”拼装
3. 左侧基础信息没有使用员工主数据
4. 结果总览后端尚无详情接口，只有列表类接口

## 4. 方案比较

### 4.1 方案 A：新增结果总览详情专用接口

做法：

- 在结果总览控制器下新增详情接口
- 一次返回人员基础信息和异常明细
- 前端弹窗只负责展示和状态管理

优点：

- 接口职责清晰，列表与详情边界明确
- 前端不需要并发拼多个真实接口
- 后续继续扩展其他页签时可以沿用同一详情链路

缺点：

- 需要补一条新的后端查询链路

### 4.2 方案 B：前端并发查询员工信息和异常明细

做法：

- 员工信息单独查员工模块
- 异常明细单独查结果总览模块
- 前端弹窗自行合并两份结果

优点：

- 单个接口改动较小

缺点：

- 前端状态更散
- 打开弹窗时更容易出现半成功半失败
- 员工信息与详情上下文容易失去统一入口

### 4.3 方案 C：把详情字段塞回现有列表接口

做法：

- 在风险人员总览和模型人员列表接口中直接追加详情字段
- 弹窗尽量少请求或不请求

优点：

- 表面改动快

缺点：

- 列表接口职责被拉坏
- 数据量被放大
- 不符合“查看详情单独获取真实信息”的语义

### 4.4 结论

采用 **方案 A**。

原因：

1. 最符合“详情数据独立获取”的业务语义
2. 不破坏现有结果总览列表接口职责
3. 前后端边界最稳定，后续扩展成本最低

## 5. 总体设计

### 5.1 打开入口

以下两个入口继续共用同一个 `项目分析` 弹窗：

1. `风险人员总览`
2. `命中模型涉及人员列表`

### 5.2 打开流程

1. 用户点击列表中的 `查看详情`
2. 前端立即打开弹窗，默认进入 `异常明细`
3. 前端将入口行中的 `命中模型摘要` 直接透传给弹窗
4. 前端发起结果总览详情接口请求
5. 接口返回后刷新左侧真实人员基础信息和右侧真实异常明细

### 5.3 数据来源边界

- `人员基础信息`：后端详情接口内部查询员工信息表 `ccdi_base_staff`
- `命中模型摘要`：由外部列表透传，不由详情接口负责
- `异常明细`：由详情接口统一返回真实信息

## 6. 后端设计

### 6.1 接口设计

建议在结果总览控制器下新增接口：

- `GET /ccdi/project/overview/person-analysis/detail`

入参：

- `projectId`
- `staffIdCard`

只保留这两个字段，避免把外层上下文和真实详情查询混在一起。

### 6.2 返回结构

返回对象建议收口为：

```json
{
  "basicInfo": {
    "name": "张三",
    "idNo": "3301********1234",
    "staffCode": "A1023",
    "department": "信息二部",
    "phone": "138****0000",
    "riskLevel": "高风险",
    "projectName": "项目A"
  },
  "abnormalDetail": {
    "groups": [
      {
        "groupCode": "BANK_STATEMENT",
        "groupName": "流水异常明细",
        "groupType": "BANK_STATEMENT",
        "records": []
      },
      {
        "groupCode": "RELATED_OBJECT",
        "groupName": "异常对象摘要",
        "groupType": "OBJECT",
        "records": []
      }
    ]
  }
}
```

### 6.3 人员基础信息查询

人员基础信息统一从员工信息表读取：

- 主表：`ccdi_base_staff`
- 关联补充：
  - 部门名称
  - 当前项目名称
  - 结果总览员工结果表中的风险等级

查询口径：

1. `staffIdCard` 作为员工识别主键
2. 员工表查不到时，仍允许返回异常明细，但 `basicInfo` 中对应字段为空
3. 不新增前端二次查员工接口

### 6.4 异常明细查询

异常明细统一组织为 `groups` 列表，每组包含：

- `groupCode`
- `groupName`
- `groupType`
- `records`

本轮只支持两种 `groupType`：

- `BANK_STATEMENT`
- `OBJECT`

### 6.5 流水维度异常

`BANK_STATEMENT` 类型的 `records` 直接按流水明细展示口径返回，字段尽量贴近现有流水查询 VO：

- `bankStatementId`
- `trxDate`
- `leAccountNo`
- `leAccountName`
- `customerAccountName`
- `customerAccountNo`
- `userMemo`
- `cashType`
- `displayAmount`
- `hitTags`

要求：

1. 展示口径与现有“流水明细查询”页面保持一致
2. 命中标签继续沿用当前流水标签结果表查询方式
3. 不再为弹窗单独造一套与流水查询不一致的字段命名

### 6.6 `OBJECT` 类型异常

`OBJECT` 类型记录用于卡片展示，返回摘要结构，不返回整对象平铺结构。

每条记录建议包含：

- `title`
- `subtitle`
- `riskTags`
- `summary`
- `extraFields`

其中：

- `title`：对象主识别名称
- `subtitle`：对象类型、关系或补充说明
- `riskTags`：异常标签数组
- `summary`：一句话摘要
- `extraFields`：最多 2 到 4 个补充字段

这样可满足“卡片展示核心信息”的要求，避免对象型数据在弹窗内变成字段堆叠。

### 6.7 查询范围

无论从哪个入口进入，详情接口都返回“该人员在当前项目下的全部异常明细”。

即使入口来自 `命中模型涉及人员列表`，也：

- 顶部继续显示当前命中模型上下文
- 但异常明细不按当前模型过滤

## 7. 前端设计

### 7.1 弹窗尺寸

`ProjectAnalysisDialog.vue` 中弹窗宽度从 `1280px` 调整为 `1440px`。

布局建议：

- 左侧侧栏宽度从 `320px` 微调到 `340px`
- 右侧主工作区尽量为流水表格腾出空间

### 7.2 侧栏展示

左侧侧栏拆成两类来源：

1. 真实详情接口返回：
   - 姓名
   - 身份证号
   - 工号
   - 部门
   - 联系方式
   - 风险等级
   - 所属项目
2. 外层透传：
   - 命中模型数
   - 当前命中模型
   - 核心异常标签

`排查记录摘要` 本轮没有真实口径，继续保留占位文案，不新增接口。

### 7.3 异常明细渲染

`ProjectAnalysisAbnormalTab.vue` 改为分组渲染：

1. `BANK_STATEMENT`
   - 渲染表格
   - 表头风格参考 `DetailQuery.vue`
2. `OBJECT`
   - 渲染摘要卡列表
   - 每张卡只展示核心字段

空数据处理：

- 空分组不展示
- 全部为空时展示统一空态

### 7.4 Mock 替换策略

`preliminaryCheck.mock.js` 中的弹窗数据构造逻辑不再承担真实详情拼装职责。

保留内容：

- 占位页签文案
- 少量默认结构常量

移出内容：

- `basicInfo`
- `abnormalDetail`

这两部分改为完全由真实接口驱动。

## 8. 状态与交互设计

### 8.1 打开时机

点击后立即打开弹窗，不等待接口先返回。

### 8.2 加载态

- 左侧真实基础信息未返回前显示骨架或 `-`
- 右侧 `异常明细` 区域显示 `v-loading` 或骨架态
- 外层透传的命中模型摘要可先展示

### 8.3 错误态

如果详情接口失败：

- 弹窗保持打开
- 右侧异常明细区域展示错误提示和重试入口
- 左侧命中模型摘要继续保留
- 未获取到的基础信息字段显示为空

### 8.4 页签行为

- 默认页签始终为 `异常明细`
- 关闭弹窗后再次打开，仍回到 `异常明细`
- 其余 4 个页签继续展示占位内容，不在本次扩展真实数据

## 9. 测试与验收要点

### 9.1 后端验收

1. 详情接口可根据 `projectId + staffIdCard` 返回真实详情
2. 人员基础信息来源于员工信息表
3. 流水型异常可返回真实流水记录和命中标签
4. `OBJECT` 类型异常可返回摘要卡结构
5. 从模型人员列表进入时，异常明细仍返回该人的全部异常

### 9.2 前端验收

1. 弹窗宽度明显加宽，流水表格可读性提升
2. 点击 `查看详情` 后弹窗立即打开
3. 左侧命中模型摘要由外层透传
4. 左侧人员基础信息展示真实数据
5. 流水型异常按表格展示
6. `OBJECT` 类型异常按摘要卡展示
7. 详情请求失败时弹窗不关闭，可重试

## 10. 结论

本方案采用“**结果总览新增专用详情接口 + 前端弹窗按类型渲染真实数据**”的最短路径实现：

1. 不污染现有列表接口
2. 不让前端并发拼多条真实接口
3. 人员基础信息、异常明细、入口模型摘要三类职责边界清晰
4. 既满足本轮真实详情接入，也为后续逐步接通更多页签留出稳定扩展位
