feat(iit): Implement event-level QC architecture V3.1 with dynamic rule filtering, report deduplication and AI intent enhancement

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-08 21:22:11 +08:00
parent 45c7b32dbb
commit 7a299e8562
51 changed files with 10638 additions and 184 deletions

View File

@@ -0,0 +1,217 @@
# 2026-02-08 事件级质控与报告优化开发记录
> **开发日期:** 2026-02-08
> **开发人员:** AI Assistant
> **版本:** V3.1
> **状态:** ✅ 基本测试成功
---
## 📋 开发概述
本次开发主要完成了 IIT Manager Agent 质控系统的重大架构升级,从"记录级合并质控"改为"事件级独立质控",同时优化了质控报告生成逻辑和 AI 对话能力。
---
## 🎯 核心改动
### 1. 事件级质控架构V3.1
**问题背景:**
- REDCap 纵向研究中,一个 record_id 可能有多个事件如筛选期、随访1、随访2等
- 之前的质控将所有事件的数据合并到一条记录,导致数据覆盖问题
- 不同事件的表单应该独立质控
**解决方案:**
| 改动文件 | 改动内容 |
|---------|---------|
| `RedcapAdapter.ts` | 新增 `getAllRecordsByEvent()` 方法,按 record+event 返回独立数据单元 |
| `RedcapAdapter.ts` | 新增 `getFormEventMapping()``getEvents()` 获取事件配置 |
| `RedcapAdapter.ts` | 新增 `getFormCompletionStatusByEvent()` 按事件获取表单完成状态 |
| `HardRuleEngine.ts` | `QCRule` 接口新增 `applicableEvents``applicableForms` 字段 |
| `SoftRuleEngine.ts` | `SoftRuleCheck` 接口同样新增事件/表单适用性字段 |
| `SkillRunner.ts` | 重构 `runByTrigger()` 按 record+event 独立执行质控 |
| `SkillRunner.ts` | 新增 `filterApplicableRules()` 方法,按事件/表单动态过滤规则 |
| `SkillRunner.ts` | `SkillRunResult` 新增 `eventName``eventLabel``forms` 字段 |
| `SkillRunner.ts` | `saveQcLog()` 现在保存 `eventId` 到数据库 |
**架构变化:**
```
之前(记录级合并):
Record 1 = Event A 数据 + Event B 数据 + ... (合并可能覆盖)
之后(事件级独立):
Record 1 + Event A = 独立质控单元 1
Record 1 + Event B = 独立质控单元 2
...
```
### 2. 质控报告优化
**问题背景:**
- 报告从多个事件收集问题,导致同一规则重复出现
- 报告使用缓存,不是最新数据
- 显示限制导致部分问题被隐藏
**解决方案:**
| 改动文件 | 改动内容 |
|---------|---------|
| `QcReportService.ts` | SQL 查询改用 `DISTINCT ON (record_id, event_id)` |
| `QcReportService.ts` | 新增 `deduplicateIssues()` 按 recordId+ruleId 去重 |
| `QcReportService.ts` | 统计计数也按 recordId+ruleId 去重(使用 Set |
| `QcReportService.ts` | 移除所有 slice 显示限制,显示所有问题 |
| `QcReportService.ts` | 兼容新旧两种 issues 格式(数组 vs { items: [...] }|
### 3. 批量操作 API 更新
| 改动文件 | 改动内容 |
|---------|---------|
| `iitBatchController.ts` | `batchQualityCheck` 改用 `SkillRunner.runByTrigger()` |
| `ToolsService.ts` | `batch_quality_check` 工具同样改用事件级质控 |
### 4. 前端优化
| 改动文件 | 改动内容 |
|---------|---------|
| `QcReportDrawer.tsx` | 导出 XML 前自动刷新报告(确保获取最新数据)|
| `QcReportDrawer.tsx` | 文件名添加时分HHMM格式便于区分 |
| `IitQcCockpitPage.tsx` | 删除重复的"全量质控"按钮(保留配置页的)|
### 5. AI 对话增强
| 改动文件 | 改动内容 |
|---------|---------|
| `ChatService.ts` | 增强意图识别,支持更多质控查询表达方式 |
| `PromptBuilder.ts` | 修复 `this` 上下文丢失导致的 500 错误 |
---
## 🐛 修复的 Bug
### Bug 1: `formatPatientData` undefined 错误
**现象:** 点击记录详情时返回 500 错误
**原因:** `buildClinicalSlice` 函数导出时丢失了 `this` 上下文
**修复:**`this.formatPatientData` 改为 `PromptBuilder.formatPatientData`
### Bug 2: 质控报告重复问题
**现象:** Record 1 显示 14 条违规,实际应该是 5 条
**原因:** 同一规则在多个事件中执行,结果都被收集到报告中
**修复:**`recordId + ruleId` 去重,只保留最新结果
### Bug 3: 报告记录数不正确
**现象:** 显示 13 条记录,实际有 14 条
**原因:**`iitRecordSummary` 获取记录数,该表可能缺少记录
**修复:** 从质控日志获取独立 `record_id` 数量
### Bug 4: AI 无法回答质控问题
**现象:** 问"严重违规有几项"AI 说"没有相关信息"
**原因:** 意图识别规则不够全面
**修复:** 增加更多匹配模式质控问题、严重违规、record问题等
---
## 📁 涉及文件清单
### 后端核心文件
```
backend/src/modules/iit-manager/
├── adapters/
│ └── RedcapAdapter.ts ✅ 新增 3 个方法
├── engines/
│ ├── HardRuleEngine.ts ✅ QCRule 接口扩展
│ ├── SoftRuleEngine.ts ✅ SoftRuleCheck 接口扩展
│ └── SkillRunner.ts ✅ 事件级质控核心重构
├── services/
│ ├── QcReportService.ts ✅ 去重 + 移除限制
│ ├── ChatService.ts ✅ 意图识别增强
│ ├── PromptBuilder.ts ✅ 修复 this 上下文
│ └── ToolsService.ts ✅ batch_quality_check 更新
backend/src/modules/admin/iit-projects/
└── iitBatchController.ts ✅ 使用 SkillRunner
```
### 前端文件
```
frontend-v2/src/modules/admin/
├── components/qc-cockpit/
│ └── QcReportDrawer.tsx ✅ 自动刷新 + 文件名优化
└── pages/
└── IitQcCockpitPage.tsx ✅ 删除重复按钮
```
---
## 🧪 测试验证
### 测试结果
| 测试项 | 结果 | 备注 |
|--------|------|------|
| 事件级质控执行 | ✅ | 14 条记录 × 5 个事件 = 70 个质控单元 |
| 规则动态过滤 | ✅ | 配置 applicableForms 后规则只在相关事件执行 |
| 报告去重 | ✅ | 168 条问题去重后变为 69 条 |
| XML 导出 | ✅ | 自动刷新 + 显示所有问题 |
| AI 质控查询 | ✅ | 能正确回答"严重违规有几项" |
| 详情页 500 错误 | ✅ | formatPatientData 修复后正常 |
---
## 📝 配置说明
### 规则适用性配置示例
```typescript
// 在 Skill 配置中设置规则的适用表单
{
"id": "inc_001",
"name": "年龄范围检查",
"applicableForms": ["basic_demography_form"], // 只在人口学表单执行
"applicableEvents": [] // 空数组 = 适用所有事件
}
```
### 执行配置更新脚本
```bash
cd backend
npx tsx update-skill-applicable-forms.ts
```
---
## 🔄 后续优化建议
1. **规则配置 UI**:在管理端添加规则 → 表单映射的可视化配置界面
2. **事件标签显示**:在报告中显示事件的中文标签(如"筛选期")而非唯一标识
3. **增量质控**:只对有变化的事件执行质控,避免全量重算
4. **质控历史**:保留历史质控结果,支持趋势分析
---
## 📚 相关文档
- [模块状态文档](../00-模块当前状态与开发指南.md)
- [实时质控系统开发记录](./2026-02-07-实时质控系统开发记录.md)
- [质控系统 UI 与 LLM 格式优化计划](../04-开发计划/07-质控系统UI与LLM格式优化计划.md)
---
> **总结:** 本次开发完成了 IIT 质控系统从"记录级"到"事件级"的架构升级解决了数据合并覆盖、报告重复、AI 无法回答等多个问题,为 REDCap 纵向研究提供了更精确的质控能力。