# 专项核查拓展查询卡片设计文档

**模块**: 项目详情 - 专项核查
**日期**: 2026-03-24
**状态**: 已确认

## 一、背景

当前项目详情页的专项核查页签已包含两块内容：

1. 员工家庭资产负债专项核查
2. 图谱外链展示占位卡片

其中图谱外链卡片当前仅作为后续接入外链图谱页面的预留入口，尚未承载真实业务查询能力。

本轮需求是在图谱外链卡片下方新增一张“拓展查询”卡片，用于查询项目范围内员工的采购、招聘、调动记录，并支持按主题 Tab 切换、按主题对应姓名字段和时间范围检索，以及按记录查看完整详情。

## 二、目标

本次设计目标如下：

1. 在专项核查页签中新增“拓展查询”卡片，位置固定在图谱外链卡片下方。
2. 通过 Tab 切换展示 3 类拓展查询主题：
   - 采购记录
   - 招聘记录
   - 调动记录
3. 列表数据只查询当前专项核查同范围员工，不扩展到项目全部目标员工。
4. 查询栏按主题独立配置，不共享无关筛选项。
5. 列表展示必要字段，操作列提供“查看详情”按钮。
6. 点击“查看详情”后，通过弹窗展示该条记录全部字段。

## 三、范围

### 3.1 本次范围

- 新增专项核查页的拓展查询卡片
- 新增采购、招聘、调动 3 个主题的 Tab 切换
- 新增项目范围拓展查询列表接口
- 新增项目范围拓展查询详情接口
- 新增对应前端查询、分页、详情弹窗交互
- 补充前后端测试与验证记录

### 3.2 不在本次范围

- 不接入真实图谱外链地址
- 不改动现有员工家庭资产负债专项核查逻辑
- 不新开独立路由页面
- 不扩展到项目全部目标员工
- 不为招聘记录新增时间筛选字段
- 不新增导出、编辑、删除等操作
- 不引入缓存、异步预计算或额外结果表

## 四、已确认业务口径

本次设计确认以下口径，后续实施必须严格遵守：

1. “项目范围内员工”定义为当前专项核查同范围员工，即现有专项核查链路中已归并出来的员工集合。
2. 不按项目全部目标员工查询。
3. 查询卡片位置固定在“图谱外链展示”卡片下方。
4. 采用横向 Tab 切换主题，不使用竖向主题导航。
5. 每个主题使用独立查询栏，不共享查询表单。
6. 采购记录按“申请人姓名 + 申请日期范围”筛选。
7. 招聘记录按“面试官姓名”筛选，本次不增加时间筛选。
8. 调动记录按“员工姓名 + 调动日期范围”筛选。
9. 列表只展示必要字段，详情弹窗展示该条记录全部字段。

## 五、方案对比

### 5.1 方案 A：图谱卡片下方新增独立拓展查询卡片

做法：

- 保留现有图谱卡片不变
- 在图谱卡片下方新增一张“拓展查询”卡片
- 卡片内部顶部使用横向 Tab 切换主题

优点：

- 完全符合“在图谱外链卡片下面添加拓展查询功能卡片”的原始需求
- 不影响现有图谱占位卡片结构
- 页面层级清晰，用户认知成本低
- 前端改造路径最短

缺点：

- 页面纵向高度会增加

### 5.2 方案 B：图谱卡片与拓展查询合并为一个大卡片

做法：

- 图谱占位与拓展查询共用同一张卡片

问题：

- 与“在图谱外链卡片下面添加卡片”的需求不一致
- 图谱占位与实际查询职责混在一起，层次不清

### 5.3 方案 C：独立拓展查询卡片，但使用左侧竖向主题导航

做法：

- 与方案 A 一样新增独立卡片
- 但主题切换改为左侧竖向导航

问题：

- 用户已明确要求通过 Tab 页切换主题
- 与当前页面已有横向区块风格不一致

### 5.4 推荐方案

采用方案 A：在图谱外链卡片下方新增独立拓展查询卡片，卡片内部使用横向 Tab 切换采购、招聘、调动 3 个主题。

## 六、页面结构设计

专项核查页整体结构调整后如下：

1. 员工家庭资产负债专项核查卡片
2. 图谱外链展示卡片
3. 拓展查询卡片

其中前两张卡片不修改现有交互，仅在其下方追加第三张卡片。

拓展查询卡片的渲染条件独立于家庭资产负债列表数据：

- 只要当前 `projectId` 有效，就应展示拓展查询卡片
- 即使家庭资产负债列表为空，拓展查询卡片仍需可见并可使用

拓展查询卡片结构如下：

### 6.1 卡片头部

- 标题：拓展查询
- 副标题：查询专项核查同范围员工的采购、招聘、调动记录

### 6.2 Tab 区

- Tab 1：采购记录
- Tab 2：招聘记录
- Tab 3：调动记录

### 6.3 主题查询区

每个 Tab 使用独立查询栏：

- 采购记录：
  - 申请人姓名
  - 申请日期范围
  - 搜索
  - 重置
- 招聘记录：
  - 面试官姓名
  - 搜索
  - 重置
- 调动记录：
  - 员工姓名
  - 调动日期范围
  - 搜索
  - 重置

### 6.4 列表区

Tab 下方展示当前主题列表与分页。

切换 Tab 时：

- 不共用查询表单
- 不互相覆盖列表数据
- 各主题保留自己的查询条件与分页状态
- 首次进入某个 Tab 时再触发该 Tab 的首查

### 6.5 详情弹窗

操作列统一提供“查看详情”按钮。

点击后：

- 采购记录弹出采购详情弹窗
- 招聘记录弹出招聘详情弹窗
- 调动记录弹出调动详情弹窗

详情弹窗展示该条记录全部字段，不裁剪字段内容。

## 七、列表字段设计

### 7.1 采购记录列表字段

- 采购事项 ID
- 项目名称
- 标的物名称
- 申请人姓名
- 申请日期
- 操作

### 7.2 招聘记录列表字段

- 招聘项目编号
- 招聘项目名称
- 职位名称
- 面试官姓名摘要
- 录用情况
- 操作

其中面试官姓名摘要定义为：

- 优先展示 `面试官1姓名 / 面试官2姓名`
- 如某一个为空，则只展示存在的姓名

### 7.3 调动记录列表字段

- 员工姓名
- 调动类型
- 调动前部门
- 调动后部门
- 调动日期
- 操作

## 八、后端设计

### 8.1 接口归属

本次不直接复用信息采集模块现有 `/list` 接口，而是在专项核查域新增项目范围拓展查询接口，统一挂在：

- `CcdiProjectSpecialCheckController`

原因：

1. 现有信息采集模块接口仅面向各自主表查询，不包含“专项核查同范围员工”的限制。
2. 如果前端调用现有接口后自行过滤，会导致项目范围口径不稳定。
3. 在专项核查域统一收口，后续维护更清晰。

### 8.2 接口设计

建议新增 6 个接口：

- `GET /ccdi/project/special-check/extended-query/purchase/list`
- `GET /ccdi/project/special-check/extended-query/purchase/detail`
- `GET /ccdi/project/special-check/extended-query/recruitment/list`
- `GET /ccdi/project/special-check/extended-query/recruitment/detail`
- `GET /ccdi/project/special-check/extended-query/transfer/list`
- `GET /ccdi/project/special-check/extended-query/transfer/detail`

### 8.3 项目范围员工口径复用

项目范围员工统一复用当前专项核查 mapper 中的员工范围定义，即：

- `CcdiProjectSpecialCheckMapper.xml` 中的 `projectEmployeeScopeSql`

该范围已经与当前专项核查页保持一致，本轮不重新定义口径，不新增第二套项目员工范围逻辑。

### 8.4 列表查询设计

#### 采购记录

数据来源：

- `ccdi_purchase_transaction`

范围限制：

- 记录必须命中专项核查同范围员工

筛选条件：

- `projectId`
- `applicantName`
- `applyDateStart`
- `applyDateEnd`

员工姓名口径：

- 按采购记录的 `applicant_name` 检索

时间口径：

- 按采购记录的 `apply_date` 检索

#### 招聘记录

数据来源：

- `ccdi_staff_recruitment`

范围限制：

- 记录必须命中专项核查同范围员工

筛选条件：

- `projectId`
- `interviewerName`

员工姓名口径：

- 按招聘记录的 `interviewer_name_1` 或 `interviewer_name_2` 检索
- 同一条招聘记录若同时命中 `interviewer_name_1` 与 `interviewer_name_2`，列表结果必须按招聘记录主键去重

时间口径：

- 本次不提供招聘时间筛选

#### 调动记录

数据来源：

- `ccdi_staff_transfer`
- `ccdi_base_staff`

范围限制：

- 记录必须命中专项核查同范围员工

筛选条件：

- `projectId`
- `staffName`
- `transferDateStart`
- `transferDateEnd`

员工姓名口径：

- 按调动记录对应员工的 `staff_name` 检索

时间口径：

- 按 `transfer_date` 检索

### 8.5 详情查询设计

详情接口按各自主键查询，并返回该条记录全部字段：

- 采购详情：按 `purchaseId`
- 招聘详情：按 `recruitId`
- 调动详情：按 `id`

详情查询仍需校验该记录属于当前专项核查同范围员工；不属于时返回业务错误，避免越权或口径漂移。

### 8.6 DTO / VO 设计

建议在 `ccdi-project` 模块下新增独立 DTO：

- 采购拓展查询 DTO
- 招聘拓展查询 DTO
- 调动拓展查询 DTO

其中招聘主题查询字段命名统一使用 `interviewerName`，不再使用泛化的 `staffName`。
采购主题查询字段命名统一使用 `applicantName`，不再使用泛化的 `staffName`。

列表返回对象按主题独立定义轻量 VO，仅保留列表必要字段。

详情返回可优先复用现有 VO 字段结构：

- `CcdiPurchaseTransactionVO`
- `CcdiStaffRecruitmentVO`
- `CcdiStaffTransferVO`

如直接复用存在耦合问题，再在 `ccdi-project` 下补充专项核查详情 VO，但本轮优先选择最短路径实现。

## 九、前端设计

### 9.1 页面挂载位置

继续以：

- `ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue`

作为专项核查页签容器，不新增路由。

### 9.2 组件拆分

建议新增一张独立的拓展查询区块组件，例如：

- `ExtendedQuerySection.vue`

职责如下：

- 管理当前激活 Tab
- 管理各 Tab 的查询参数
- 驱动列表加载与分页
- 打开并关闭详情弹窗

详情展示建议按主题拆分为小组件或局部模板：

- 采购详情复用现有采购页的分组展示方式
- 招聘详情复用现有招聘页的分组展示方式
- 调动详情补齐与前两者一致的详情展示结构

### 9.3 状态管理

每个 Tab 独立维护以下状态：

- `query`
- `list`
- `loading`
- `pageNum`
- `pageSize`
- `total`
- `detailOpen`
- `detailLoading`
- `detailData`

原则如下：

1. 不共享查询表单
2. 不共享列表数据
3. 切换 Tab 时保留各自上次查询状态
4. 首次进入 Tab 时再请求列表

### 9.4 空态与异常

- 列表无数据时展示当前主题无数据空态
- 列表查询失败时提示错误信息，并清空当前主题列表
- 详情查询失败时只提示错误，不污染列表状态
- `projectId` 为空时沿用当前专项核查页已有空态逻辑

## 十、测试与验证设计

### 10.1 前端验证

补充以下验证：

1. 专项核查页新增拓展查询卡片结构断言
2. 卡片位于图谱外链卡片下方的结构断言
3. 3 个主题 Tab 的存在性断言
4. 不同 Tab 显示不同查询栏字段的断言
5. 操作列“查看详情”按钮存在性断言
6. 调动主题详情弹窗存在性断言
7. 前端构建验证

### 10.2 后端验证

补充以下验证：

1. 项目范围员工口径是否与 `projectEmployeeScopeSql` 一致
2. 采购列表按申请人姓名和申请日期范围过滤是否正确
3. 招聘列表按面试官姓名过滤是否正确
4. 调动列表按员工姓名和调动日期范围过滤是否正确
5. 详情接口是否能校验记录属于当前项目范围员工
6. 记录不属于当前项目范围员工时是否返回预期错误

### 10.3 联调验证

联调时重点验证：

1. Tab 切换后各自查询条件不会互相污染
2. 招聘主题不展示时间范围
3. 采购与调动主题展示时间范围
4. 详情弹窗字段完整性与原业务页一致

## 十一、实施约束

本轮实施需遵守以下要求：

1. 不新增兼容性分支或降级方案。
2. 不在需求外扩展更多主题。
3. 不新增导出、编辑、删除、批量操作。
4. 不改变现有图谱占位卡片行为。
5. 根据本设计文档产出两份实施计划：
   - 后端实施计划放 `docs/plans/backend/`
   - 前端实施计划放 `docs/plans/frontend/`

## 十二、结论

本次采用“图谱外链卡片下方新增独立拓展查询卡片”的方案，在专项核查页签内新增采购、招聘、调动 3 个主题查询能力。所有查询严格限制为当前专项核查同范围员工，采购与调动支持时间范围筛选，招聘仅支持面试官姓名筛选。前端不新增路由，后端在专项核查域新增统一接口，保持实现路径最短、页面职责清晰、业务口径稳定。
