Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/09-技术评审报告/GCP 质控报表开发计划专家审查报告.md
HaHafeng 2030ebe28f feat(iit): Complete V3.1 QC engine + GCP business reports + AI timeline + bug fixes
V3.1 QC Engine:
- QcExecutor unified entry + D1-D7 dimension engines + three-level aggregation
- HealthScoreEngine + CompletenessEngine + ProtocolDeviationEngine + QcAggregator
- B4 flexible cron scheduling (project-level cronExpression + pg-boss dispatcher)
- Prisma migrations for qc_field_status, event_status, project_stats

GCP Business Reports (Phase A - 4 reports):
- D1 Eligibility: record_summary full list + qc_field_status D1 overlay
- D2 Completeness: data entry rate and missing rate aggregation
- D3/D4 Query Tracking: severity distribution from qc_field_status
- D6 Protocol Deviation: D6 dimension filtering
- 4 frontend table components + ReportsPage 5-tab restructure

AI Timeline Enhancement:
- SkillRunner outputs totalRules (33 actual rules vs 1 skill)
- iitQcCockpitController severity mapping fix (critical->red, warning->yellow)
- AiStreamPage expandable issue detail table with Chinese labels
- Event label localization (eventLabel from backend)

Business-side One-click Batch QC:
- DashboardPage batch QC button with SyncOutlined icon
- Auto-refresh QcReport cache after batch execution

Bug Fixes:
- dimension_code -> rule_category in 4 SQL queries
- D1 eligibility data source: record_summary full + qc_field_status overlay
- Timezone UTC -> Asia/Shanghai (QcReportService toBeijingTime helper)
- Pass rate calculation: passed/totalEvents instead of passed/totalRecords

Docs:
- Update IIT module status with GCP reports and bug fix milestones
- Update system status doc v6.6 with IIT progress

Tested: Backend compiles, frontend linter clean, batch QC verified
Made-with: Cursor
2026-03-01 22:49:49 +08:00

103 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **业务端 GCP 质控报表开发计划专家审查报告**
**审查对象**《GCP Business Reports 开发计划》 (5aeb159b.plan)
**审查定位**:针对 D1、D2、D3/D4、D6 报表开发的逻辑闭环、性能瓶颈及 LLM 协同性进行深度排雷。
**审查结论**:总体架构极佳,完美贯彻了“硬计算归系统,软推理归 LLM”的原则。但在 D2 缺失数据写入、D6 字段解析及前端加载性能上存在 4 个隐藏坑点,需在编码前修正。
## **一、 值得高度肯定的亮点What's Good**
1. **极其敏锐的 P0 漏洞捕捉**
发现 SkillRunner 未将 category 传播给 QcExecutor导致 D1 变 D3。这个 Bug 如果在测试期才发现,会导致所有报表数据串位。修复方案非常精准。
2. **对 LLM 极其友好的底层设计**
你没有选择“把几十万条数据直接扔给 LLM 让它画表格”,而是**老老实实写了 4 个结构化的 API**。这是最顶级的 LLM 友好型架构!
*未来 LLM 只需要调用这 4 个 API 获取 JSON极低 Token就能在 Tab 0执行摘要里写出极其精准且绝对不会幻觉的全局分析报告。*
3. **前端 UI 的“渐进式展开Progressive Disclosure”设计**
D2 报表的 受试者 → 事件 → 字段清单 三级展开设计,完全对标了 Medidata J-Review 的体验,非常符合 CRA “从宏观到微观”的查错习惯。
## **二、 架构排雷与修正建议What needs fix**
### **💣 坑点 1D2 (数据完整性) 的“幽灵记录”取数陷阱**
**🔍 计划漏洞**
计划中 D2 的 API 打算用这段 SQL 统计缺失率SELECT count(\*) FROM qc\_field\_status WHERE rule\_category \= 'D2' AND status \= 'FAIL'。
**临床逻辑断层**:如果是“缺失数据”,意味着 CRC **根本没有填这个字段**。如果没填Webhook 就不会推送这个字段HardRuleEngine 如果只是遍历传来的数据,就**永远不会为这个缺失字段在 qc\_field\_status 中插入一行 FAIL 记录**。没有记录,你的 SQL 就什么都 count 不到!
**🛠️ 修正建议 (后端)**
必须明确界定 CompletenessEngine (D2 引擎) 的特殊职责:**它必须是主动轮询Proactive Polling**。
D2 引擎在运行时,必须拿患者当前的 Event 去对比 REDCap 的 Data Dictionary。对于字典里有但数据库里没有的必填项引擎必须**主动强行向 qc\_field\_status 插入一条具有五层坐标的“幽灵记录”**(实际值为空,状态为 FAIL类别为 D2
*只有这样,你计划里的 SQL 才能真正生效。请将此要求补充进 D2 的开发任务中。*
### **💣 坑点 2D6 (方案偏离) 脆断的文本解析**
**🔍 计划漏洞**
计划中写道:对于 D6 API从 actual\_value / expected\_value 解析超窗天数和方向。
**过度耦合**:如果在规则引擎里 actual\_value 存的是字符串 "延误 10 天"API 层再去用正则解析提取数字 10 和方向 late这是极其脆弱的设计只要底层提示语改一个字报表就崩了。
**🛠️ 修正建议 (后端数据结构)**
不要在 API 层解析字符串。在底层执行超窗规则D6规则引擎应该把结构化的偏离数据写入到一个元数据字段。
如果 qc\_field\_status 没有 JSONB 的 meta 字段,建议巧妙利用现有的字段,或者要求 D6 引擎输出标准的 JSON string 到 actual\_value例如
// actual\_value 存储规范
{"days": 10, "direction": "late", "text": "延误10天"}
API 直接 JSON.parse(actual\_value) 即可安全获取 deviationDays。
### **💣 坑点 3D1 (筛选入选表) Inclusion/Exclusion 的身份识别**
**🔍 计划漏洞**
D1 API 的返回结构要求明确区分 type: 'inclusion' | 'exclusion',以便分别统计。但在我们现有的 qc\_field\_status 五层表中,并没有字段标识一条规则到底是纳入还是排除。
**🛠️ 修正建议 (后端映射)**
在执行 P0 Bugfix 时,连同将规则的子分类也传递下去。或者在项目的 IitSkill 配置中,规定 D1 规则的命名必须带有前缀例如INC-年龄校验EXC-妊娠状态。D1 的 API 通过解析 ruleName 的前缀来区分 inclusion 和 exclusion从而正确归类到前端表格中。
### **💣 坑点 4D2 前端表格的三级展开 (L5) 性能雪崩**
**🔍 计划漏洞**
D2 前端组件如果一次性请求包含了整个项目所有患者、所有访视、所有缺失字段清单的“全量树状 JSON”对于一个入组 200 人、缺失 5000 个字段的 IIT 项目,这个 API payload 可能会超过 5MB导致前端渲染卡死。
**🛠️ 修正建议 (前端与 API)**
采用**过度设计审查**L5具体字段清单不能随总览 API 一起返回。
* **API 拆分**
* GET /report/completeness/summary (返回 L1, L2, L3 宏观统计和访视级统计)
* GET /report/completeness/fields?recordId=P001\&eventId=V2 (懒加载/Lazy Load API)
* **前端交互**:当 CRA 在 CompletenessTable 中点击展开某次访视的详细表单时,前端再按需调用第二个 API 获取具体的缺失字段清单。
## **三、 对 LLM 友好的延伸设计 (架构红利)**
当前的计划主要聚焦在“传统业务报表(表格)”的渲染。既然您已经做好了这 4 个高质量的结构化 API千万不要浪费了它对大模型的巨大价值
**💡 建议补充任务:增强 Tab 0 (执行摘要) 的 LLM 总结能力**
在前端加载 ReportsPage.tsx 的 Tab 0 时:
1. 前端并行请求 D1, D2, D3, D6 的 4 个 API 的 **summary 部分**(不包含 entries 明细)。
2. 将这 4 个 JSON summary 拼成一个 Context 对象:
const llmContext \= { D1: d1.summary, D2: d2.summary, D3: d3.summary, D6: d6.summary };
3. 把这个极简的 Context 喂给系统的 LLM 接口:
*Prompt: "你是一个资深项目经理,请根据以下当前项目的多维 GCP 质控摘要,写一段 200 字以内的项目质量执行总结,并指出当前最需要介入的风险点。"*
4. 将 LLM 生成的这段话展示在 Tab 0 的最顶端。
**这就是真正的 AI 原生 SaaS**:不仅能提供冷冰冰的报表,还能直接基于结构化报表进行像人一样的洞察和汇报。
## **四、 审查最终结论**
这个开发计划的**粒度非常合适**,属于“刚刚好能落地且能商用”的级别。它没有去强求一次性做完所有的 AI 关联,而是优先把 GCP 需要的“表单底子”搭了出来。
只要在开发任务Jira/Todos中**补充上述 4 个避坑建议(特别是 D2 幽灵记录的生成机制)**,这份计划就可以直接发给开发团队启动 Sprint 了!