docs(iit): Add QC system UI and LLM format optimization plan
- Add development plan: 07-QC system UI and LLM format optimization - Phase 1: PromptBuilder + XML clinical slice format (~5.5h) - Phase 2: QC cockpit + stat cards + risk heatmap (~9.5h) - Phase 3: Variable tagging system (~5h) - Add CRA Agent design document and prototype - Update module status: design 100%, code 45% - Update system status: real-time QC complete + plan ready Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
# AIclinicalresearch 系统当前状态与开发指南
|
||||
|
||||
> **文档版本:** v4.7
|
||||
> **文档版本:** v4.8
|
||||
> **创建日期:** 2025-11-28
|
||||
> **维护者:** 开发团队
|
||||
> **最后更新:** 2026-02-05
|
||||
> **最后更新:** 2026-02-08
|
||||
> **🎉 重大里程碑:**
|
||||
> - **2026-02-08:IIT 质控系统优化计划制定!** XML 临床切片格式 + 质控驾驶舱 + 方案 A 确认
|
||||
> - **2026-02-07:IIT 实时质控系统开发完成!** pg-boss 防抖 + 质控日志 + 录入汇总 + 管理端批量操作
|
||||
> - **2026-02-05:IIT Manager Agent V2.9.1 架构设计完成!** 双脑架构 + 三层记忆 + 主动性增强 + 隐私合规
|
||||
> - **2026-02-02:REDCap 生产环境部署完成!** ECS + RDS + HTTPS + 域名全部配置完成
|
||||
> - **2026-01-28:Prompt 知识库集成完成!** Prompt 可动态引用系统知识库内容
|
||||
@@ -14,12 +16,13 @@
|
||||
> - **2026-01-22:OSS 存储集成完成!** 阿里云 OSS 正式接入平台基础层
|
||||
> - **2026-01-21:成功替换 Dify!** PKB 模块完全使用自研 pgvector RAG 引擎
|
||||
>
|
||||
> **最新进展(IIT Manager Agent V2.9.1 架构 2026-02-05):**
|
||||
> **最新进展(IIT Manager Agent 2026-02-08):**
|
||||
> - ✅ **实时质控系统**:pg-boss 防抖 + 质控日志(审计轨迹) + 录入汇总(upsert)
|
||||
> - ✅ **管理端批量操作**:一键全量质控 + 一键全量汇总(前后端完整)
|
||||
> - ✅ **质控优化计划**:XML 临床切片格式 + 质控驾驶舱 + 变量标签系统
|
||||
> - ✅ **双脑架构**:SOP 状态机(结构化任务) + ReAct 引擎(模糊查询)
|
||||
> - ✅ **三层记忆**:流水账(全量日志) + 热记忆(高频注入) + 历史书(按需检索)
|
||||
> - ✅ **主动性增强**:Cron Skill 定时任务 + 用户画像 + 反馈循环
|
||||
> - ✅ **隐私合规**:PII 脱敏中间件 + 审计日志 + 可恢复脱敏
|
||||
> - ✅ **自动化工具**:AutoMapper REDCap Schema 自动对齐
|
||||
>
|
||||
> **部署状态:** ✅ 生产环境运行中 | 公网地址:http://8.140.53.236/
|
||||
> **REDCap 状态:** ✅ 生产环境运行中 | 地址:https://redcap.xunzhengyixue.com/
|
||||
@@ -59,7 +62,7 @@
|
||||
| **PKB** | 个人知识库 | RAG问答、私人文献库 | ⭐⭐⭐ | 🎉 **Dify已替换!自研RAG上线(95%)** | P1 |
|
||||
| **ASL** | AI智能文献 | 文献筛选、Meta分析、证据图谱 | ⭐⭐⭐⭐⭐ | 🎉 **智能检索MVP完成(60%)** - DeepSearch集成 | **P0** |
|
||||
| **DC** | 数据清洗整理 | ETL + 医学NER(百万行级数据) | ⭐⭐⭐⭐⭐ | ✅ **Tool B完成 + Tool C 99%(异步架构+性能优化-99%+多指标转换+7大功能)** | **P0** |
|
||||
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 双脑架构+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **V2.9.1 架构完成 - 准备实施(设计100%,代码25%)** | **P0** |
|
||||
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 双脑架构+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **实时质控完成 + UI优化计划制定(设计100%,代码45%)** | **P0** |
|
||||
| **SSA** | 智能统计分析 | 队列/预测模型/RCT分析 | ⭐⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程、Word导出 | ⭐⭐⭐⭐ | ✅ **开发完成(95%)** | P3 |
|
||||
@@ -143,11 +146,24 @@
|
||||
|
||||
---
|
||||
|
||||
## 🚀 当前开发状态(2026-02-05)
|
||||
## 🚀 当前开发状态(2026-02-08)
|
||||
|
||||
### 🎉 最新进展:IIT Manager Agent V2.9.1 架构设计完成(2026-02-05)
|
||||
### 🎉 最新进展:IIT 实时质控系统完成 + UI 优化计划制定(2026-02-08)
|
||||
|
||||
#### ✅ 双脑架构 + 三层记忆 + 主动性增强 + 隐私合规
|
||||
#### ✅ 实时质控系统 + 管理端批量操作 + 质控驾驶舱设计
|
||||
|
||||
**2026-02-07 开发完成:**
|
||||
- ✅ 4 个新数据库表:`iit_qc_logs`、`iit_record_summary`、`iit_qc_project_stats`、`iit_field_metadata`
|
||||
- ✅ pg-boss 防抖机制:`singletonKey` 5 分钟去重
|
||||
- ✅ Worker 双产出:质控日志(仅新增)+ 录入汇总(upsert)
|
||||
- ✅ 管理端批量操作:一键全量质控 + 一键全量汇总
|
||||
|
||||
**2026-02-08 计划制定:**
|
||||
- 📋 XML 临床切片格式:对 LLM 更友好,减少幻觉
|
||||
- 📋 质控驾驶舱页面:风险热力图 + 统计卡片
|
||||
- 📋 变量标签系统:按语义标签切片数据
|
||||
|
||||
#### ✅ 双脑架构 + 三层记忆 + 主动性增强 + 隐私合规(V2.9.1)
|
||||
|
||||
**重大里程碑**:
|
||||
- 🎉 **完整架构设计**:V2.9.1 开发计划发布,6份模块化文档
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# IIT Manager Agent模块 - 当前状态与开发指南
|
||||
|
||||
> **文档版本:** v2.1
|
||||
> **文档版本:** v2.2
|
||||
> **创建日期:** 2026-01-01
|
||||
> **维护者:** IIT Manager开发团队
|
||||
> **最后更新:** 2026-02-07 🎉 **实时质控系统核心功能开发完成!**
|
||||
> **最后更新:** 2026-02-08 🎉 **质控系统 UI 与 LLM 格式优化计划制定完成!**
|
||||
> **重大里程碑:**
|
||||
> - ✅ 2026-02-08:**质控系统优化计划制定**(XML 临床切片格式 + 质控驾驶舱设计 + 方案 A 确认)
|
||||
> - ✅ 2026-02-07:**实时质控系统开发完成**(pg-boss防抖 + 质控日志 + 录入汇总 + 管理端批量操作)
|
||||
> - ✅ 2026-02-05:**V2.9.1 完整开发计划发布**(双脑架构 + 三层记忆 + 主动性增强 + 隐私合规)
|
||||
> - ✅ 2026-02-02:**REDCap 生产环境部署完成**(ECS + RDS + HTTPS)
|
||||
@@ -82,11 +83,18 @@ IIT Manager Agent(研究者发起试验管理助手)是一个基于企业微
|
||||
| **Phase 1** | 基础工具层(ToolsService + HardRuleEngine + AutoMapper) | P0 | ✅ 部分完成(HardRuleEngine 已实现) |
|
||||
| **Phase 1.5** | 隐私安全(AnonymizerService + PII 脱敏) | **P0 合规必需** | 待开始 |
|
||||
| **Phase 2** | 实时质控系统(QC Worker + QcService + 批量操作) | P0 | ✅ **已完成** |
|
||||
| **Phase 2.5** | 质控 UI 与 LLM 格式优化(驾驶舱 + XML 临床切片) | P0 | 📋 **计划已制定** |
|
||||
| **Phase 3** | ReAct 引擎 + 流水账(ReActEngine + 反馈循环) | P0 | 待开始 |
|
||||
| **Phase 4** | 调度系统(SchedulerService + Cron Skill + ProfilerService) | P1 | 待开始 |
|
||||
| **Phase 5** | 智能路由(IntentService + 多意图处理) | P1 | 待开始 |
|
||||
| **Phase 6** | 视觉能力(VisionService) | 延后 | 待开始 |
|
||||
|
||||
#### 📋 新增开发计划(2026-02-08)
|
||||
- **[质控系统 UI 与 LLM 格式优化计划](./04-开发计划/07-质控系统UI与LLM格式优化计划.md)**
|
||||
- 阶段 1:LLM 格式优化(PromptBuilder + XML 临床切片)~5.5h
|
||||
- 阶段 2:管理端 UI 增强(质控驾驶舱 + 统计卡片 + 热力图)~9.5h
|
||||
- 阶段 3:变量标签系统(按语义标签切片数据)~5h
|
||||
|
||||
- **部署状态**:✅ REDCap 生产环境运行中(https://redcap.xunzhengyixue.com/)
|
||||
- **已知问题**:无
|
||||
- **开发计划文档**:[V2.9.1 综合开发计划](./04-开发计划/IIT%20Manager%20Agent%20V2.6%20综合开发计划.md)
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
# **CRA Agent (临床监查) 深度设计与展现方案**
|
||||
|
||||
**文档版本:** v2.0
|
||||
|
||||
**文档目的:** 针对多变量(300+)、高复杂度(入排/PD/AE/伦理)的临床研究场景,设计 CRA Agent 的数据处理逻辑与交互界面。
|
||||
|
||||
**适用版本:** IIT Manager Agent V2.9.1
|
||||
|
||||
**创建日期:** 2026-02-07
|
||||
|
||||
## **🏗️ 一、 架构设计:如何处理 300+ 变量?**
|
||||
|
||||
面对 10 个表单、300 个变量,我们不能试图一次性把所有数据塞进 Prompt。我们需要建立一个 **"变量知识图谱" (Variable Metadata Graph)**。
|
||||
|
||||
### **1.1 变量分组策略 (Grouping)**
|
||||
|
||||
在 Admin 端配置 REDCap 映射时,不仅要映射字段名,还要给变量打 **"语义标签"**:
|
||||
|
||||
| REDCap 变量名 | 语义标签 (Tag) | 归属域 (Domain) | 关键度 |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| dob | \#demographics | 基线 | High |
|
||||
| icf\_date | \#consent, \#ethics | 伦理 | Critical |
|
||||
| visit\_date | \#timeline | 访视 | High |
|
||||
| alt, ast | \#lab, \#safety | 实验室 | Medium |
|
||||
| tumor\_size | \#efficacy | 疗效 | High |
|
||||
|
||||
**设计价值**:
|
||||
|
||||
当 CRA Agent 需要核查 "是否符合入排标准" 时,它不需要读取 300 个变量,只需要请求 \#demographics \+ \#lab \+ \#efficacy 标签下的 20 个变量。
|
||||
|
||||
### **1.2 双层质控引擎 (Hybrid QC Engine)**
|
||||
|
||||
我们将质控分为两层,只有复杂逻辑才交给 LLM,既省钱又准确。
|
||||
|
||||
* **Layer 1: 基础清洗 (HardRuleEngine)**
|
||||
* **执行者**:Node.js 代码
|
||||
* **检查内容**:空值、数据类型、数值范围 (如 BMI \> 50)、逻辑跳转。
|
||||
* **输出**:直接生成错误日志,不消耗 Token。
|
||||
* **Layer 2: 医学逻辑 (AI Logic Engine)**
|
||||
* **执行者**:LLM (DeepSeek/Qwen) \+ RAG (Protocol)
|
||||
* **检查内容**:入排标准符合性、AE 判定、方案偏离 (PD)、合并用药禁忌。
|
||||
* **输入**:Layer 1 清洗后的数据 \+ 方案规则。
|
||||
|
||||
## **🤖 二、 对 LLM 友好的数据格式设计 (Context Protocol)**
|
||||
|
||||
为了让 LLM 精准判断医学逻辑,我们放弃 JSON 堆砌,采用 **"临床切片 (Clinical Slice)"** 模式。
|
||||
|
||||
### **2.1 场景一:入排标准核查 (Inclusion/Exclusion)**
|
||||
|
||||
**LLM Prompt 结构建议:**
|
||||
|
||||
\<task\>核查该患者是否符合研究入排标准\</task\>
|
||||
|
||||
\<protocol\_criteria\>
|
||||
\<\!-- 从 RAG 检索出的标准 \--\>
|
||||
1\. 年龄 18-75 岁。
|
||||
2\. 病理确诊为非小细胞肺癌。
|
||||
3\. 肝肾功能正常 (ALT/AST \< 2.5 ULN)。
|
||||
\</protocol\_criteria\>
|
||||
|
||||
\<patient\_slice tag="screening\_data"\>
|
||||
\<\!-- 仅注入相关变量,已转化为自然语言描述 \--\>
|
||||
\- 出生日期:1950-05-12 (当前年龄 75 岁)
|
||||
\- 诊断:右肺腺癌 (2025-12-01 确诊)
|
||||
\- 实验室检查:ALT 150 U/L (参考值 0-40), AST 45 U/L。
|
||||
\</patient\_slice\>
|
||||
|
||||
\<instruction\>
|
||||
请一步步推理,对比患者数据与标准。重点关注肝功能指标。
|
||||
\</instruction\>
|
||||
|
||||
### **2.2 场景二:方案偏离 (Protocol Deviation) \- 时间窗检查**
|
||||
|
||||
**LLM Prompt 结构建议:**
|
||||
|
||||
\<task\>检查 V2 访视是否超窗\</task\>
|
||||
|
||||
\<rule\_context\>
|
||||
规则:V2 访视应在 V1 后 28 天 ± 3 天进行。
|
||||
前提:V1 访视日期为基准。
|
||||
\</rule\_context\>
|
||||
|
||||
\<timeline\_slice\>
|
||||
\- V1 访视日期:2026-01-01
|
||||
\- V2 实际访视日期:2026-02-05
|
||||
\</timeline\_slice\>
|
||||
|
||||
### **2.3 场景三:AE 事件侦测 (Safety Monitoring)**
|
||||
|
||||
这是最复杂的,需要对比前后两次数据。
|
||||
|
||||
\<task\>基于实验室数据变化,判断是否发生潜在 AE\</task\>
|
||||
|
||||
\<lab\_comparison\>
|
||||
\<baseline\>
|
||||
WBC: 5.5 (正常)
|
||||
PLT: 200 (正常)
|
||||
\</baseline\>
|
||||
\<current\_visit\>
|
||||
WBC: 2.1 (低于下限 4.0) ⚠️
|
||||
PLT: 180 (正常)
|
||||
\</current\_visit\>
|
||||
\</lab\_comparison\>
|
||||
|
||||
\<question\>
|
||||
白细胞计数 (WBC) 出现显著下降且低于正常值,根据 CTCAE 标准,这属于几级不良事件?是否在 AE 表中记录?
|
||||
\</question\>
|
||||
|
||||
## **🖥️ 三、 后台展现形式设计 (Human UI)**
|
||||
|
||||
Admin 端需要一个高密度的 **"CRA 驾驶舱"**,让 CRA 一眼看穿 300 个变量背后的风险。
|
||||
|
||||
### **3.1 宏观视图:风险热力图 (Risk Heatmap)**
|
||||
|
||||
不要只列出 List,要用矩阵。
|
||||
|
||||
* **行**:受试者 (Subject 001, 002...)
|
||||
* **列**:访视/表单 (Screening, Baseline, V1, V2, AE, CM)
|
||||
* **单元格**:颜色代表风险等级。
|
||||
* 🟢 **Green**: Clean (无问题)
|
||||
* 🟡 **Yellow**: Query (有疑问/空值)
|
||||
* 🔴 **Red**: Critical (违背入排/严重 PD/SAE)
|
||||
* ⚪ **Gray**: Not Started
|
||||
|
||||
**交互**:点击红色单元格,右侧滑出 "智能诊断报告"。
|
||||
|
||||
### **3.2 微观视图:智能诊断报告 (The "Why" Panel)**
|
||||
|
||||
当点击某个具体的报警(例如 Subject 001 的入排标准红色警告)时,展示如下内容:
|
||||
|
||||
#### **📋 诊断卡片:入排标准违规**
|
||||
|
||||
**\[结论\]**:❌ **建议剔除**
|
||||
|
||||
**\[置信度\]**:High (基于硬指标)
|
||||
|
||||
**\[AI 推理链\]**:
|
||||
|
||||
1. **标准要求**:ALT \< 2.5倍 ULN (即 \< 100 U/L)。
|
||||
2. **患者数据**:当前 ALT 为 150 U/L。
|
||||
3. **判定**:150 \> 100,不符合入组标准第 3 条。
|
||||
|
||||
**\[原始证据\]**:
|
||||
|
||||
* lab\_alt: 150 (来源于 form: lab\_results, field: alt)
|
||||
* lab\_date: 2026-01-15
|
||||
|
||||
**\[CRA 操作区\]**:
|
||||
|
||||
* \[ \] 忽略 (医学判断无碍)
|
||||
* \[ \] 发送 Query (询问 CRC)
|
||||
* \[ \] 确认违规 (标记为 PD)
|
||||
|
||||
### **3.3 调试视图:LLM 视角 (Trace Viewer)**
|
||||
|
||||
在每条质控记录的详情中,提供一个 **"AI 思考过程"** Tab,实现黑盒透明化。
|
||||
|
||||
* **Input (Prompt Context)**: 展示发送给 LLM 的 XML+Markdown 格式原始提示词(即“临床切片”)。
|
||||
* **Process (Thinking)**: 展示 LLM 的思维链(Chain of Thought)。
|
||||
* **Output (JSON)**: 展示最终生成的结构化结论。
|
||||
|
||||
## **⚙️ 四、 配置层设计 (Rule Studio)**
|
||||
|
||||
### **4.1 规则配置中心**
|
||||
|
||||
采用 **“分层配置,自动托底”** 策略:
|
||||
|
||||
1. **Layer 1 字段自动映射 (Auto Mapping)**:
|
||||
* 系统读取 REDCap Metadata,自动生成 Hard Rules(空值、范围)。
|
||||
* 用户仅需为变量打标签(Tagging),如 \#safety, \#efficacy。
|
||||
2. **Layer 2 逻辑构建器 (Logic Builder)**:
|
||||
* 低代码配置跨表逻辑:IF \[V2.Date\] \- \[V1.Date\] \> 31 THEN \[PD Alert\]。
|
||||
3. **Layer 3 AI 监查员配置 (AI Setup)**:
|
||||
* **上传 Protocol PDF** \-\> AI 自动提取入排标准 \-\> 人工确认 \-\> 自动生成 Layer 2 检查 Prompt。
|
||||
|
||||
## **🛡️ 五、 特殊医学逻辑设计**
|
||||
|
||||
针对你提到的 4 个核心需求,设计如下专项 Check:
|
||||
|
||||
### **5.1 入排标准 (I/E Criteria)**
|
||||
|
||||
* **设计**:将 Protocol PDF 中的入排标准 OCR 化,转为结构化规则库。
|
||||
* **展现**:在 "受试者列表" 增加一列 "I/E Status"。
|
||||
* Pass: ✅
|
||||
* Fail: ❌ (Hover 显示具体哪一条没过,如 "I3: Age")
|
||||
|
||||
### **5.2 方案偏离 (PD)**
|
||||
|
||||
* **核心**:时间窗 (Time Window) 和 漏做检查 (Missing Procedure)。
|
||||
* **展现**:**时间轴视图 (Gantt-like)**。
|
||||
* 展示 "计划访视日" vs "实际访视日"。
|
||||
* 如果超窗,用红色区间标出。
|
||||
|
||||
### **5.3 伦理合规 (Ethics)**
|
||||
|
||||
* **核心逻辑**:Date(ICF\_Sign) \<= Date(Any\_Study\_Procedure)。
|
||||
* **逻辑**:如果任何检查日期早于知情同意书签署日期,触发 **最高级别警报 (Critical)**。
|
||||
* **展现**:置顶 Banner 警告,因为这是合规红线。
|
||||
|
||||
### **5.4 AE 事件侦测 (Safety)**
|
||||
|
||||
* **逻辑**:
|
||||
1. **Change Check**: 实验室指标从 Normal 变为 Abnormal。
|
||||
2. **Cross Check**: 检查 AE Log 表单中是否有对应日期的记录。
|
||||
3. 如果 Lab 异常但 AE 表为空 \-\> **提示 "潜在漏报 AE"**。
|
||||
* **展现**:
|
||||
* "Lab vs AE 一致性检查" 面板。
|
||||
* 左侧显示异常 Lab 指标,右侧显示 AE 记录,中间用连线表示匹配关系。
|
||||
|
||||
## **📝 总结建议**
|
||||
|
||||
1. **不要全量喂数据**:建立 VariableMetadata,按 Tag 切片。
|
||||
2. **LLM 看"病历"**:将 JSON 转换为 **XML 标签包裹的 Markdown** 格式的“临床叙事”,不仅省 Token,还能极大提升 AI 对医学逻辑的理解力。
|
||||
3. **UI 矩阵化**:CRA 需要上帝视角,热力图是最佳选择。
|
||||
4. **推理透明化**:AI 报出错误时,必须展示 "标准 vs 现状" 的对比证据,方便 CRA 快速复核。
|
||||
598
docs/03-业务模块/IIT Manager Agent/01-需求分析/质控管理原型图.html
Normal file
598
docs/03-业务模块/IIT Manager Agent/01-需求分析/质控管理原型图.html
Normal file
@@ -0,0 +1,598 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>IIT Manager - CRA 智能监查驾驶舱</title>
|
||||
<!-- 引入 Tailwind CSS 进行快速样式构建 -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- 引入 FontAwesome 图标 -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<!-- 引入 Google Fonts (Inter) -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body { font-family: 'Inter', sans-serif; }
|
||||
/* 自定义滚动条 */
|
||||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||||
::-webkit-scrollbar-track { background: #f1f1f1; }
|
||||
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
|
||||
|
||||
/* 模拟代码高亮 */
|
||||
.xml-tag { color: #2563eb; }
|
||||
.xml-attr { color: #9333ea; }
|
||||
.xml-val { color: #16a34a; }
|
||||
.xml-content { color: #374151; }
|
||||
|
||||
/* 动画 */
|
||||
.slide-in-right {
|
||||
animation: slideIn 0.3s ease-out forwards;
|
||||
}
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(100%); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 text-gray-800 h-screen flex overflow-hidden">
|
||||
|
||||
<!-- 左侧导航栏 -->
|
||||
<aside class="w-64 bg-slate-900 text-white flex-shrink-0 flex flex-col transition-all duration-300">
|
||||
<div class="h-16 flex items-center px-6 border-b border-slate-800">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center">
|
||||
<i class="fas fa-robot text-white text-sm"></i>
|
||||
</div>
|
||||
<span class="font-bold text-lg tracking-tight">IIT Manager</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="flex-1 py-6 px-3 space-y-1">
|
||||
<a href="#" onclick="switchTab('overview')" class="nav-item flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
|
||||
<i class="fas fa-chart-pie w-5 text-center"></i>
|
||||
<span>项目概览</span>
|
||||
</a>
|
||||
|
||||
<!-- 激活状态 -->
|
||||
<a href="#" onclick="switchTab('cockpit')" class="nav-item active flex items-center gap-3 px-3 py-2.5 rounded-lg bg-blue-600 text-white shadow-lg shadow-blue-900/20 transition-colors">
|
||||
<i class="fas fa-table-cells w-5 text-center"></i>
|
||||
<span>智能监查驾驶舱</span>
|
||||
</a>
|
||||
|
||||
<a href="#" onclick="switchTab('rules')" class="nav-item flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
|
||||
<i class="fas fa-sliders w-5 text-center"></i>
|
||||
<span>规则配置中心</span>
|
||||
</a>
|
||||
|
||||
<div class="pt-4 mt-4 border-t border-slate-800">
|
||||
<p class="px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider mb-2">数据管理</p>
|
||||
<a href="#" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
|
||||
<i class="fas fa-users w-5 text-center"></i>
|
||||
<span>受试者管理</span>
|
||||
</a>
|
||||
<a href="#" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
|
||||
<i class="fas fa-database w-5 text-center"></i>
|
||||
<span>REDCap 同步</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="p-4 border-t border-slate-800">
|
||||
<div class="flex items-center gap-3">
|
||||
<img src="https://ui-avatars.com/api/?name=Admin&background=random" class="w-8 h-8 rounded-full">
|
||||
<div>
|
||||
<p class="text-sm font-medium">Dr. Admin</p>
|
||||
<p class="text-xs text-slate-500">项目管理员</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<main class="flex-1 flex flex-col min-w-0 overflow-hidden relative">
|
||||
<!-- 顶部栏 -->
|
||||
<header class="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-8 flex-shrink-0 z-10">
|
||||
<div>
|
||||
<h1 class="text-xl font-bold text-gray-800" id="page-title">CRA 智能监查驾驶舱</h1>
|
||||
<p class="text-xs text-gray-500 mt-0.5">项目: 肺癌靶向治疗研究 (PID: 16) | 最后同步: 10分钟前</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<button class="px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg text-sm font-medium hover:bg-gray-50 flex items-center gap-2">
|
||||
<i class="fas fa-sync-alt"></i> 全量质控
|
||||
</button>
|
||||
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 shadow-sm flex items-center gap-2">
|
||||
<i class="fas fa-file-export"></i> 导出监查报告
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 视图容器 -->
|
||||
<div id="content-area" class="flex-1 overflow-auto p-8 bg-gray-50 relative">
|
||||
|
||||
<!-- VIEW 1: 智能监查驾驶舱 (Risk Heatmap) -->
|
||||
<div id="view-cockpit" class="view-section space-y-6">
|
||||
<!-- 统计卡片 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">总体数据质量分</p>
|
||||
<h3 class="text-3xl font-bold text-gray-800 mt-2">92 <span class="text-sm font-normal text-gray-400">/100</span></h3>
|
||||
</div>
|
||||
<span class="p-2 bg-green-100 text-green-600 rounded-lg"><i class="fas fa-heartbeat"></i></span>
|
||||
</div>
|
||||
<div class="mt-4 w-full bg-gray-100 rounded-full h-1.5">
|
||||
<div class="bg-green-500 h-1.5 rounded-full" style="width: 92%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm border-l-4 border-l-red-500">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">严重违规 (Critical)</p>
|
||||
<h3 class="text-3xl font-bold text-red-600 mt-2">3 <span class="text-sm font-normal text-gray-500">条</span></h3>
|
||||
</div>
|
||||
<span class="p-2 bg-red-100 text-red-600 rounded-lg"><i class="fas fa-exclamation-triangle"></i></span>
|
||||
</div>
|
||||
<p class="text-xs text-red-500 mt-3 font-medium">需立即处理:入排标准违背 (2)</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm border-l-4 border-l-yellow-400">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">待确认 Query (Major)</p>
|
||||
<h3 class="text-3xl font-bold text-yellow-600 mt-2">12 <span class="text-sm font-normal text-gray-500">条</span></h3>
|
||||
</div>
|
||||
<span class="p-2 bg-yellow-100 text-yellow-600 rounded-lg"><i class="fas fa-question-circle"></i></span>
|
||||
</div>
|
||||
<p class="text-xs text-yellow-600 mt-3">主要是实验室数据异常</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 font-medium">方案偏离 (PD)</p>
|
||||
<h3 class="text-3xl font-bold text-gray-800 mt-2">5 <span class="text-sm font-normal text-gray-500">条</span></h3>
|
||||
</div>
|
||||
<span class="p-2 bg-purple-100 text-purple-600 rounded-lg"><i class="fas fa-clock"></i></span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-3">大多为访视超窗</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 风险热力图 (The Matrix) -->
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center bg-gray-50">
|
||||
<h3 class="font-bold text-gray-800">受试者风险全景图 (Risk Heatmap)</h3>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-500">
|
||||
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-green-500"></span> 无异常</span>
|
||||
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-yellow-400"></span> 疑问 (Query)</span>
|
||||
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-red-500"></span> 严重违规</span>
|
||||
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-gray-200"></span> 未开始</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm text-left">
|
||||
<thead class="text-xs text-gray-500 uppercase bg-gray-50 border-b border-gray-200">
|
||||
<tr>
|
||||
<th class="px-6 py-3 font-medium">受试者 ID</th>
|
||||
<th class="px-6 py-3 font-medium">入组状态</th>
|
||||
<th class="px-4 py-3 text-center">Screening<br>(筛查期)</th>
|
||||
<th class="px-4 py-3 text-center">Baseline<br>(基线期)</th>
|
||||
<th class="px-4 py-3 text-center">Visit 1<br>(第1周)</th>
|
||||
<th class="px-4 py-3 text-center">Visit 2<br>(第4周)</th>
|
||||
<th class="px-4 py-3 text-center">AE Log<br>(不良事件)</th>
|
||||
<th class="px-4 py-3 text-center">CM Log<br>(合并用药)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<!-- 行 1: 有严重问题 -->
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 font-medium text-gray-900">SUB-001</td>
|
||||
<td class="px-6 py-4"><span class="px-2 py-1 bg-green-100 text-green-700 text-xs rounded-full">已入组</span></td>
|
||||
<!-- 红色单元格:可点击 -->
|
||||
<td class="px-4 py-4 text-center cursor-pointer hover:bg-red-50" onclick="openDrawer('SUB-001', 'Screening')">
|
||||
<div class="w-8 h-8 rounded-lg bg-red-500 text-white flex items-center justify-center mx-auto shadow-sm shadow-red-200 transition-transform hover:scale-110">
|
||||
<i class="fas fa-times"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
</tr>
|
||||
<!-- 行 2: 有警告 -->
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 font-medium text-gray-900">SUB-002</td>
|
||||
<td class="px-6 py-4"><span class="px-2 py-1 bg-green-100 text-green-700 text-xs rounded-full">已入组</span></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center cursor-pointer hover:bg-yellow-50">
|
||||
<div class="w-8 h-8 rounded-lg bg-yellow-400 text-white flex items-center justify-center mx-auto shadow-sm shadow-yellow-200 transition-transform hover:scale-110">
|
||||
<i class="fas fa-exclamation"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
</tr>
|
||||
<!-- 更多行... -->
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 font-medium text-gray-900">SUB-003</td>
|
||||
<td class="px-6 py-4"><span class="px-2 py-1 bg-blue-100 text-blue-700 text-xs rounded-full">筛查中</span></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VIEW 2: 规则配置中心 (Rule Studio) -->
|
||||
<div id="view-rules" class="view-section hidden space-y-6">
|
||||
<!-- Layer 3: AI 配置 -->
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-6">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-bold text-gray-800 flex items-center gap-2">
|
||||
<span class="bg-purple-100 text-purple-600 px-2 py-1 rounded text-xs">Layer 3</span>
|
||||
AI 监查员配置 (AI Setup)
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500 mt-1">负责复杂医学逻辑(如入排标准、AE判定)的智能化配置</p>
|
||||
</div>
|
||||
<button class="px-4 py-2 bg-purple-600 text-white rounded-lg text-sm hover:bg-purple-700">
|
||||
<i class="fas fa-file-pdf mr-2"></i>重新解析 Protocol
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
<!-- 左侧:Protocol 提取 -->
|
||||
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
|
||||
<h4 class="text-sm font-bold text-gray-700 mb-3">AI 提取的入排标准 (Top 3)</h4>
|
||||
<div class="space-y-3">
|
||||
<div class="p-3 bg-white border border-gray-200 rounded shadow-sm">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs font-bold text-gray-500">I-03 (入选)</span>
|
||||
<span class="text-xs text-green-600 bg-green-50 px-1 rounded">已确认</span>
|
||||
</div>
|
||||
<p class="text-sm mt-1">肝肾功能正常,定义为 ALT/AST < 2.5倍 ULN。</p>
|
||||
<div class="mt-2 flex gap-2">
|
||||
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #lab</span>
|
||||
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #safety</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 bg-white border border-gray-200 rounded shadow-sm">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-xs font-bold text-gray-500">E-02 (排除)</span>
|
||||
<span class="text-xs text-green-600 bg-green-50 px-1 rounded">已确认</span>
|
||||
</div>
|
||||
<p class="text-sm mt-1">既往 5 年内有其他恶性肿瘤病史。</p>
|
||||
<div class="mt-2 flex gap-2">
|
||||
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #history</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:Prompt 预览 -->
|
||||
<div class="bg-slate-900 text-slate-300 p-4 rounded-lg font-mono text-xs overflow-auto h-64">
|
||||
<div class="text-slate-500 mb-2">// 系统自动生成的 Layer 2 检查 Prompt</div>
|
||||
<p class="text-purple-400"><task></p>
|
||||
<p class="pl-4">基于上传的 Protocol,核查患者是否符合 I-03 标准。</p>
|
||||
<p class="text-purple-400"></task></p>
|
||||
<br>
|
||||
<p class="text-purple-400"><criteria></p>
|
||||
<p class="pl-4">标准值:ALT < 2.5 * ULN (100 U/L)</p>
|
||||
<p class="text-purple-400"></criteria></p>
|
||||
<br>
|
||||
<p class="text-purple-400"><data_requirement></p>
|
||||
<p class="pl-4 text-green-400">Tag: #lab, #safety</p>
|
||||
<p class="text-purple-400"></data_requirement></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Layer 1: 字段映射 -->
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-6">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-4 flex items-center gap-2">
|
||||
<span class="bg-blue-100 text-blue-600 px-2 py-1 rounded text-xs">Layer 1</span>
|
||||
字段自动映射 (Auto Mapping)
|
||||
</h3>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm text-left">
|
||||
<thead class="bg-gray-50 text-gray-500">
|
||||
<tr>
|
||||
<th class="px-4 py-2">REDCap 字段</th>
|
||||
<th class="px-4 py-2">所属表单</th>
|
||||
<th class="px-4 py-2">自动规则 (Hard Rules)</th>
|
||||
<th class="px-4 py-2">语义标签 (Tags)</th>
|
||||
<th class="px-4 py-2">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<tr>
|
||||
<td class="px-4 py-3 font-mono">dob</td>
|
||||
<td class="px-4 py-3">Demographics</td>
|
||||
<td class="px-4 py-3"><span class="bg-gray-100 px-2 py-1 rounded text-xs">Required</span> <span class="bg-gray-100 px-2 py-1 rounded text-xs">Date</span></td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="bg-blue-50 text-blue-600 border border-blue-200 px-2 py-0.5 rounded text-xs">#demographics</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-blue-600 cursor-pointer">编辑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 font-mono">lab_alt</td>
|
||||
<td class="px-4 py-3">Lab Test</td>
|
||||
<td class="px-4 py-3"><span class="bg-gray-100 px-2 py-1 rounded text-xs">Min: 0</span> <span class="bg-gray-100 px-2 py-1 rounded text-xs">Max: 1000</span></td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="bg-blue-50 text-blue-600 border border-blue-200 px-2 py-0.5 rounded text-xs">#lab</span>
|
||||
<span class="bg-red-50 text-red-600 border border-red-200 px-2 py-0.5 rounded text-xs">#safety</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-blue-600 cursor-pointer">编辑</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 侧滑抽屉:智能诊断详情 (Subject 360) -->
|
||||
<div id="drawer-overlay" class="fixed inset-0 bg-black/50 z-40 hidden transition-opacity opacity-0" onclick="closeDrawer()"></div>
|
||||
<div id="drawer-panel" class="fixed inset-y-0 right-0 w-[1000px] bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col">
|
||||
|
||||
<!-- 抽屉头部 -->
|
||||
<div class="h-16 px-6 border-b border-gray-200 flex items-center justify-between bg-gray-50">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-10 h-10 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center font-bold">
|
||||
01
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-lg font-bold text-gray-800">受试者 SUB-001</h2>
|
||||
<p class="text-xs text-gray-500">访视阶段: Screening | 录入时间: 2026-02-07 14:30</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="px-3 py-1.5 bg-white border border-gray-300 text-gray-600 rounded text-sm hover:bg-gray-50">
|
||||
<i class="fas fa-external-link-alt mr-1"></i> REDCap
|
||||
</button>
|
||||
<button onclick="closeDrawer()" class="p-2 text-gray-400 hover:text-gray-600 rounded-full hover:bg-gray-100">
|
||||
<i class="fas fa-times text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 抽屉内容:左右分栏 -->
|
||||
<div class="flex-1 flex overflow-hidden">
|
||||
<!-- 左栏:真实数据 (Source of Truth) -->
|
||||
<div class="w-1/2 border-r border-gray-200 flex flex-col bg-white">
|
||||
<div class="p-4 bg-gray-50 border-b border-gray-200 flex justify-between items-center">
|
||||
<h3 class="font-bold text-gray-700"><i class="fas fa-database mr-2"></i>真实数据 (Screening Form)</h3>
|
||||
<span class="text-xs bg-gray-200 text-gray-600 px-2 py-0.5 rounded">Read Only</span>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-6 space-y-6">
|
||||
<!-- 表单字段 -->
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-500 uppercase">Screening Date</label>
|
||||
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">2026-01-15</div>
|
||||
</div>
|
||||
|
||||
<!-- 异常字段高亮 -->
|
||||
<div class="relative group">
|
||||
<div class="absolute -left-4 top-2 text-red-500"><i class="fas fa-arrow-right"></i></div>
|
||||
<label class="block text-xs font-medium text-gray-500 uppercase">Lab Test: ALT (U/L)</label>
|
||||
<div class="mt-1 p-2 bg-red-50 border border-red-300 rounded text-red-700 font-bold flex justify-between items-center">
|
||||
<span>150</span>
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
</div>
|
||||
<p class="text-xs text-red-500 mt-1">Ref Range: 0-40</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-500 uppercase">Lab Test: AST (U/L)</label>
|
||||
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">45</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-500 uppercase">Inclusion Criteria Checklist</label>
|
||||
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">Complete</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右栏:AI 监查报告 + LLM Trace -->
|
||||
<div class="w-1/2 flex flex-col bg-slate-50">
|
||||
<div class="border-b border-gray-200 bg-white">
|
||||
<nav class="flex -mb-px">
|
||||
<button onclick="switchDrawerTab('report')" id="tab-report" class="w-1/2 py-4 px-1 text-center border-b-2 border-blue-500 font-medium text-sm text-blue-600">
|
||||
<i class="fas fa-robot mr-2"></i>智能诊断报告
|
||||
</button>
|
||||
<button onclick="switchDrawerTab('trace')" id="tab-trace" class="w-1/2 py-4 px-1 text-center border-b-2 border-transparent font-medium text-sm text-gray-500 hover:text-gray-700 hover:border-gray-300">
|
||||
<i class="fas fa-code mr-2"></i>LLM Trace (透视)
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Tab 1: 报告 -->
|
||||
<div id="drawer-content-report" class="flex-1 overflow-y-auto p-6 space-y-4">
|
||||
<!-- 严重报警卡片 -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-red-200 overflow-hidden">
|
||||
<div class="bg-red-50 px-4 py-3 border-b border-red-100 flex justify-between items-center">
|
||||
<h4 class="text-red-700 font-bold flex items-center gap-2">
|
||||
<i class="fas fa-times-circle"></i> 违反入排标准 (Critical)
|
||||
</h4>
|
||||
<span class="text-xs bg-white text-red-600 px-2 py-1 rounded border border-red-200">置信度: High</span>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="mb-4">
|
||||
<p class="text-xs font-bold text-gray-500 uppercase mb-1">AI 观点</p>
|
||||
<p class="text-sm text-gray-800">
|
||||
根据 Protocol 标准 I-03,受试者肝功能需正常(ALT < 2.5倍 ULN,即 < 100)。
|
||||
<br>检测到该患者当前 <strong>ALT 为 150</strong>,显著超出允许范围,建议剔除。
|
||||
</p>
|
||||
</div>
|
||||
<div class="mb-4 bg-gray-50 p-3 rounded border border-gray-200 text-xs text-gray-600">
|
||||
<p class="font-bold mb-1">原始证据链 (Evidence Chain):</p>
|
||||
<ul class="list-disc pl-4 space-y-1">
|
||||
<li>Variable: <code>lab_alt</code> = 150</li>
|
||||
<li>Standard: <code>limit_max</code> = 100</li>
|
||||
<li>Form: Screening Form</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="flex gap-2 pt-2 border-t border-gray-100">
|
||||
<button class="flex-1 bg-red-600 text-white text-sm py-2 rounded hover:bg-red-700">确认违规 (PD)</button>
|
||||
<button class="flex-1 bg-white border border-gray-300 text-gray-700 text-sm py-2 rounded hover:bg-gray-50">发送 Query</button>
|
||||
<button class="px-3 bg-white border border-gray-300 text-gray-400 rounded hover:text-gray-600" title="忽略"><i class="fas fa-trash-alt"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 警告卡片 -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-yellow-200 overflow-hidden opacity-75">
|
||||
<div class="bg-yellow-50 px-4 py-3 border-b border-yellow-100 flex justify-between items-center">
|
||||
<h4 class="text-yellow-700 font-bold flex items-center gap-2">
|
||||
<i class="fas fa-exclamation-triangle"></i> 数据完整性警告
|
||||
</h4>
|
||||
<span class="text-xs bg-white text-yellow-600 px-2 py-1 rounded border border-yellow-200">置信度: Medium</span>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<p class="text-sm text-gray-800">AST 字段有值 (45),但未填写单位。虽然数值在正常范围内,建议确认单位是否为 U/L。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab 2: LLM Trace (XML View) -->
|
||||
<div id="drawer-content-trace" class="hidden flex-1 overflow-y-auto p-0 bg-[#1e1e1e] text-gray-300 font-mono text-xs">
|
||||
<div class="p-4 border-b border-gray-700 bg-[#252526] text-gray-400 flex justify-between">
|
||||
<span>Prompt Context (Sent to DeepSeek-V3)</span>
|
||||
<span class="text-blue-400">XML Protocol</span>
|
||||
</div>
|
||||
<div class="p-6 space-y-1">
|
||||
<div><span class="xml-tag"><task></span>核查该患者是否符合研究入排标准<span class="xml-tag"></task></span></div>
|
||||
<br>
|
||||
<div><span class="xml-tag"><protocol_criteria></span></div>
|
||||
<div class="pl-4 text-[#ce9178]">1. 年龄 18-75 岁。</div>
|
||||
<div class="pl-4 text-[#ce9178]">2. 病理确诊为非小细胞肺癌。</div>
|
||||
<div class="pl-4 text-[#ce9178]">3. 肝肾功能正常 (ALT/AST < 2.5 ULN)。</div>
|
||||
<div><span class="xml-tag"></protocol_criteria></span></div>
|
||||
<br>
|
||||
<div><span class="xml-tag"><patient_slice</span> <span class="xml-attr">tag</span>=<span class="xml-val">"#lab"</span><span class="xml-tag">></span></div>
|
||||
<div class="pl-4 text-gray-400"><!-- Layer 1 Filtered Data --></div>
|
||||
<div class="pl-4 text-[#9cdcfe]">- 实验室检查日期: 2026-01-15</div>
|
||||
<div class="pl-4 text-[#9cdcfe]">- ALT: <span class="bg-red-900 text-white px-1">150</span> U/L</div>
|
||||
<div class="pl-4 text-[#9cdcfe]">- AST: 45 U/L</div>
|
||||
<div><span class="xml-tag"></patient_slice></span></div>
|
||||
<br>
|
||||
<div><span class="xml-tag"><instruction></span></div>
|
||||
<div class="pl-4 text-[#ce9178]">请一步步推理,对比患者数据与标准。重点关注肝功能指标。</div>
|
||||
<div><span class="xml-tag"></instruction></span></div>
|
||||
|
||||
<div class="mt-8 pt-4 border-t border-gray-700">
|
||||
<div class="text-green-400 mb-2">// LLM Output (Chain of Thought)</div>
|
||||
<div class="text-gray-400 italic">
|
||||
> Thinking: 标准要求 ALT 小于 100 (2.5 * 40)。<br>
|
||||
> 检查 patient_slice 数据...<br>
|
||||
> 发现 ALT = 150。<br>
|
||||
> 150 > 100,判定违规。<br>
|
||||
> 生成 Critical 级别报警。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// 简单的 Tab 切换逻辑
|
||||
function switchTab(tabId) {
|
||||
// 隐藏所有视图
|
||||
document.querySelectorAll('.view-section').forEach(el => el.classList.add('hidden'));
|
||||
document.querySelectorAll('.nav-item').forEach(el => {
|
||||
el.classList.remove('bg-blue-600', 'text-white', 'shadow-lg');
|
||||
el.classList.add('text-slate-400', 'hover:bg-slate-800');
|
||||
});
|
||||
|
||||
// 显示选中视图
|
||||
document.getElementById('view-' + tabId).classList.remove('hidden');
|
||||
|
||||
// 这里的 active 样式逻辑简化处理,实际开发可用 Vue/React 控制 class
|
||||
const activeLink = document.querySelector(`a[onclick="switchTab('${tabId}')"]`);
|
||||
activeLink.classList.remove('text-slate-400', 'hover:bg-slate-800');
|
||||
activeLink.classList.add('bg-blue-600', 'text-white', 'shadow-lg');
|
||||
|
||||
// 更新标题
|
||||
const titles = {
|
||||
'overview': '项目概览 Dashboard',
|
||||
'cockpit': 'CRA 智能监查驾驶舱',
|
||||
'rules': '规则配置中心 (Rule Studio)'
|
||||
};
|
||||
document.getElementById('page-title').innerText = titles[tabId];
|
||||
}
|
||||
|
||||
// 抽屉控制
|
||||
function openDrawer(subjectId, visit) {
|
||||
const drawerPanel = document.getElementById('drawer-panel');
|
||||
const drawerOverlay = document.getElementById('drawer-overlay');
|
||||
|
||||
drawerOverlay.classList.remove('hidden');
|
||||
// 强制重绘以触发 transition
|
||||
setTimeout(() => {
|
||||
drawerOverlay.classList.remove('opacity-0');
|
||||
drawerPanel.classList.remove('translate-x-full');
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
const drawerPanel = document.getElementById('drawer-panel');
|
||||
const drawerOverlay = document.getElementById('drawer-overlay');
|
||||
|
||||
drawerPanel.classList.add('translate-x-full');
|
||||
drawerOverlay.classList.add('opacity-0');
|
||||
|
||||
setTimeout(() => {
|
||||
drawerOverlay.classList.add('hidden');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// 抽屉内 Tab 切换
|
||||
function switchDrawerTab(tabName) {
|
||||
const reportContent = document.getElementById('drawer-content-report');
|
||||
const traceContent = document.getElementById('drawer-content-trace');
|
||||
const tabReport = document.getElementById('tab-report');
|
||||
const tabTrace = document.getElementById('tab-trace');
|
||||
|
||||
if (tabName === 'report') {
|
||||
reportContent.classList.remove('hidden');
|
||||
traceContent.classList.add('hidden');
|
||||
|
||||
tabReport.classList.add('border-blue-500', 'text-blue-600');
|
||||
tabReport.classList.remove('border-transparent', 'text-gray-500');
|
||||
|
||||
tabTrace.classList.remove('border-blue-500', 'text-blue-600');
|
||||
tabTrace.classList.add('border-transparent', 'text-gray-500');
|
||||
} else {
|
||||
reportContent.classList.add('hidden');
|
||||
traceContent.classList.remove('hidden');
|
||||
|
||||
tabTrace.classList.add('border-blue-500', 'text-blue-600');
|
||||
tabTrace.classList.remove('border-transparent', 'text-gray-500');
|
||||
|
||||
tabReport.classList.remove('border-blue-500', 'text-blue-600');
|
||||
tabReport.classList.add('border-transparent', 'text-gray-500');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
384
docs/03-业务模块/IIT Manager Agent/04-开发计划/07-质控系统UI与LLM格式优化计划.md
Normal file
384
docs/03-业务模块/IIT Manager Agent/04-开发计划/07-质控系统UI与LLM格式优化计划.md
Normal file
@@ -0,0 +1,384 @@
|
||||
# 质控系统 UI 与 LLM 格式优化开发计划
|
||||
|
||||
> **版本:** v1.0
|
||||
> **创建日期:** 2026-02-08
|
||||
> **基于讨论:** 团队技术方案评审 + 产品原型对比分析
|
||||
> **决策确认:** 方案 A(渐进式改进)
|
||||
|
||||
---
|
||||
|
||||
## 一、背景与目标
|
||||
|
||||
### 1.1 现状问题
|
||||
|
||||
1. **LLM 格式问题**:当前使用简单 JSON 格式返回数据,LLM 理解力有限,容易产生幻觉
|
||||
2. **UI 展示缺失**:管理端只有批量操作按钮,无法直观查看质控结果和录入进度
|
||||
3. **入口层级深**:IIT 管理嵌套在运营管理端中,质控监控功能不够突出
|
||||
|
||||
### 1.2 参考文档
|
||||
|
||||
| 文档 | 路径 | 核心内容 |
|
||||
|------|------|----------|
|
||||
| CRA Agent 深度设计方案 | `docs/03-业务模块/IIT Manager Agent/01-需求分析/CRA Agent (临床监查) 深度设计与展现方案.md` | 变量分组、双层质控、临床切片格式 |
|
||||
| 质控管理原型图 | `docs/03-业务模块/IIT Manager Agent/01-需求分析/质控管理原型图.html` | 风险热力图、统计卡片、智能诊断抽屉 |
|
||||
|
||||
### 1.3 目标
|
||||
|
||||
1. **提升 AI 回答准确性**:采用 XML 临床切片格式,减少 LLM 幻觉
|
||||
2. **提升运营效率**:提供可视化质控驾驶舱,一眼看穿数据问题
|
||||
3. **渐进式改进**:不破坏现有架构,逐步增强功能
|
||||
|
||||
---
|
||||
|
||||
## 二、详细评估表
|
||||
|
||||
### 2.1 团队方案 vs 当前代码对比
|
||||
|
||||
| 功能点 | 团队方案描述 | 当前状态 | 建议 |
|
||||
|--------|-------------|---------|------|
|
||||
| **1. 变量语义标签 (Tagging)** | 为变量打 `#demographics`, `#lab`, `#safety` 等标签,按需加载 | ❌ 未实现 | 🔴 **采纳** - 在 `iit_field_metadata` 表增加 `tags` 字段 |
|
||||
| **2. 双层质控引擎** | Layer 1: HardRuleEngine, Layer 2: AI Logic Engine | ✅ Layer 1 已完成 | 🟡 Layer 2 可延后 |
|
||||
| **3. 临床切片格式** | XML + Markdown 结构化提示词,对 LLM 更友好 | ❌ 使用简单 JSON | 🔴 **采纳** - 新增 `PromptBuilder.buildClinicalSlice()` |
|
||||
| **4. 风险热力图** | 矩阵式受试者 × 访视/表单视图,颜色表示风险等级 | ❌ 未实现 | 🔴 **采纳** - 管理端新增驾驶舱页面 |
|
||||
| **5. 统计卡片** | 数据质量分、严重违规数、Query 数、方案偏离数 | ❌ 未实现 | 🔴 **采纳** - 驾驶舱页面顶部 |
|
||||
| **6. 智能诊断抽屉** | 左侧真实数据 + 右侧 AI 诊断,可操作(Query/确认/忽略) | ❌ 未实现 | 🟡 **简化采纳** - 先实现详情弹窗 |
|
||||
| **7. LLM Trace 视图** | 展示发送给 LLM 的 Prompt 和思考过程 | ❌ 未实现 | 🟢 延后 - 调试阶段使用 |
|
||||
| **8. 规则配置中心** | Layer 1/2/3 分层配置界面 | ✅ 已有质控规则页面 | ✅ 保持现有 |
|
||||
| **9. AI 自动提取规则** | 上传 Protocol PDF 自动生成规则 | ❌ 未实现 | 🟢 延后 - 高级功能 |
|
||||
| **10. qc_logs 审计轨迹** | 质控日志仅新增,保留历史记录 | ✅ 已实现 | ✅ 保持现有 |
|
||||
| **11. record_summary 汇总** | 录入汇总表 upsert 模式 | ✅ 已实现 | ✅ 保持现有 |
|
||||
| **12. pg-boss 防抖** | Webhook 去重机制 | ✅ 已实现 | ✅ 保持现有 |
|
||||
|
||||
### 2.2 LLM 格式对比
|
||||
|
||||
| 维度 | 当前 JSON 格式 | XML 临床切片格式 |
|
||||
|------|---------------|-----------------|
|
||||
| **Token 消耗** | 较多(括号、引号、嵌套) | 较少(语义化标签) |
|
||||
| **LLM 理解力** | 一般(需要解析 JSON 结构) | 极强(医学叙事文本) |
|
||||
| **上下文切割** | 困难(全量或无) | 简单(按 tag 切片) |
|
||||
| **推理准确性** | 中等 | 高(有明确任务指令) |
|
||||
| **调试友好度** | 一般 | 好(XML 结构清晰) |
|
||||
|
||||
**当前 JSON 格式示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"projectName": "test0207",
|
||||
"stats": {
|
||||
"totalRecords": 13,
|
||||
"passedRecords": 0,
|
||||
"failedRecords": 13
|
||||
},
|
||||
"problemRecords": [
|
||||
{
|
||||
"recordId": "1",
|
||||
"status": "FAIL",
|
||||
"issues": [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**XML 临床切片格式示例:**
|
||||
|
||||
```xml
|
||||
<task>核查该患者是否符合研究入排标准</task>
|
||||
|
||||
<protocol_criteria>
|
||||
1. 年龄 16-35 岁。
|
||||
2. 月经周期规律(28±7天)。
|
||||
3. VAS 评分 ≥ 4 分。
|
||||
4. 签署知情同意书。
|
||||
</protocol_criteria>
|
||||
|
||||
<patient_slice tag="#demographics, #screening">
|
||||
- 出生日期:2003-01-07(当前年龄 22 岁)✅
|
||||
- 月经周期:45 天 ⚠️ 超出范围
|
||||
- VAS 评分:未填写 ⚠️
|
||||
- 知情同意:未签署 ❌
|
||||
</patient_slice>
|
||||
|
||||
<instruction>
|
||||
请一步步推理,对比患者数据与标准。如发现异常,说明具体哪条标准被违反。
|
||||
</instruction>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、架构方案确认
|
||||
|
||||
### 3.1 方案 A(确认采用)
|
||||
|
||||
**核心思路:渐进式改进,增加"质控全览图"按钮**
|
||||
|
||||
```
|
||||
运营管理端 → IIT 项目管理 → 项目详情页
|
||||
│
|
||||
├── REDCap 配置 (Tab)
|
||||
├── 质控规则 (Tab)
|
||||
├── 通知设置 (Tab)
|
||||
├── 知识库 (Tab)
|
||||
│
|
||||
└── [⚡一键全量质控] [📊一键全量汇总] [🔍质控全览图]
|
||||
│
|
||||
▼
|
||||
全新页面(全屏驾驶舱)
|
||||
/admin/iit-projects/:id/cockpit
|
||||
```
|
||||
|
||||
**优势:**
|
||||
1. 不破坏现有系统架构
|
||||
2. 配置与监控职责分离
|
||||
3. 全屏展示更多内容
|
||||
4. 开发成本可控
|
||||
|
||||
### 3.2 驾驶舱页面布局
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ← 返回项目配置 test0207 - CRA 智能监查驾驶舱 ⚡全量质控 📄导出报告 │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐│
|
||||
│ │ 总体数据质量分 │ │ 严重违规 │ │ 待确认 Query │ │ 录入完成率 ││
|
||||
│ │ │ │ (Critical) │ │ (Major) │ │ ││
|
||||
│ │ 0 /100 │ │ 13 条 │ │ 0 条 │ │ 14% ││
|
||||
│ │ ████░░░░░░░░ │ │ 需立即处理 │ │ │ │ 7个表单/1个完成││
|
||||
│ └────────────────┘ └────────────────┘ └────────────────┘ └────────────────┘│
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ 受试者风险全景图 (Risk Heatmap) │
|
||||
│ ────────────────────────────────────────────────────────────────────────── │
|
||||
│ 🟢 无异常 🟡 疑问(Query) 🔴 严重违规 ⚪ 未开始 │
|
||||
│ ────────────────────────────────────────────────────────────────────────── │
|
||||
│ 记录ID │ 入组状态 │ 人口学信息 │ 病史诊断 │ 知情同意 │ 入排标准 │ CMSS │ ...│
|
||||
│ ───────┼─────────┼───────────┼─────────┼─────────┼─────────┼──────┼─────│
|
||||
│ 1 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
|
||||
│ 2 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
|
||||
│ 3 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
|
||||
│ ... │ ... │ ... │ ... │ ... │ ... │ ... │ ... │
|
||||
│ 13 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ 点击红色单元格
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ 侧滑抽屉:记录 1 - 入排标准详情 │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ 【质控问题】 │
|
||||
│ ❌ 年龄不在 25-35 岁范围内(当前:22岁) │
|
||||
│ ❌ 月经周期不在 21-35 天范围内(当前:45天) │
|
||||
│ ❌ VAS 评分 < 4 分(当前:空值) │
|
||||
│ ❌ 未签署知情同意书 │
|
||||
│ │
|
||||
│ 【原始数据】 │
|
||||
│ age: 22 | menstrual_cycle: 45 | vas_score: null | informed_consent: 0 │
|
||||
│ │
|
||||
│ [发送 Query] [确认违规] [忽略] │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、分阶段开发计划
|
||||
|
||||
### 阶段 1:LLM 格式优化(P0 - 优先级最高)
|
||||
|
||||
**目标:提升 AI 回答准确性,减少幻觉**
|
||||
|
||||
| 任务 | 描述 | 工作量 | 优先级 |
|
||||
|------|------|--------|--------|
|
||||
| 1.1 创建 PromptBuilder 类 | 实现 `buildClinicalSlice()` 方法,生成 XML 格式 | 2h | P0 |
|
||||
| 1.2 修改 ChatService | 在质控查询时使用 PromptBuilder 格式化数据 | 1.5h | P0 |
|
||||
| 1.3 添加自然语言摘要 | 返回结果增加 `summary` 字段,便于 LLM 直接引用 | 1h | P0 |
|
||||
| 1.4 测试验证 | 企业微信端测试 AI 回答准确性 | 1h | P0 |
|
||||
|
||||
**技术实现:**
|
||||
|
||||
```typescript
|
||||
// backend/src/modules/iit-manager/services/PromptBuilder.ts
|
||||
|
||||
export class PromptBuilder {
|
||||
/**
|
||||
* 构建 XML 临床切片格式
|
||||
*/
|
||||
static buildClinicalSlice(params: {
|
||||
task: string;
|
||||
criteria: string[];
|
||||
patientData: Record<string, any>;
|
||||
tags?: string[];
|
||||
instruction?: string;
|
||||
}): string {
|
||||
const { task, criteria, patientData, tags = [], instruction } = params;
|
||||
|
||||
return `
|
||||
<task>${task}</task>
|
||||
|
||||
<protocol_criteria>
|
||||
${criteria.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}
|
||||
</protocol_criteria>
|
||||
|
||||
<patient_slice${tags.length > 0 ? ` tag="${tags.join(', ')}"` : ''}>
|
||||
${Object.entries(patientData)
|
||||
.map(([k, v]) => ` - ${k}: ${v ?? '未填写'}`)
|
||||
.join('\n')}
|
||||
</patient_slice>
|
||||
|
||||
${instruction ? `<instruction>\n${instruction}\n</instruction>` : ''}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建质控结果摘要(自然语言)
|
||||
*/
|
||||
static buildQcSummary(stats: {
|
||||
projectName: string;
|
||||
totalRecords: number;
|
||||
passRate: number;
|
||||
topIssues: Array<{ issue: string; count: number }>;
|
||||
}): string {
|
||||
const { projectName, totalRecords, passRate, topIssues } = stats;
|
||||
|
||||
const issueText = topIssues
|
||||
.slice(0, 3)
|
||||
.map(i => `${i.issue}(${i.count}条)`)
|
||||
.join('、');
|
||||
|
||||
return `项目 ${projectName} 共有 ${totalRecords} 条记录,` +
|
||||
`质控通过率 ${passRate.toFixed(1)}%。` +
|
||||
(topIssues.length > 0 ? `主要问题包括:${issueText}。` : '暂无质控问题。');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 阶段 2:管理端 UI 增强(P0)
|
||||
|
||||
**目标:提供可视化质控驾驶舱**
|
||||
|
||||
| 任务 | 描述 | 工作量 | 优先级 |
|
||||
|------|------|--------|--------|
|
||||
| 2.1 添加"质控全览图"按钮 | 在 IitProjectDetailPage 增加按钮 | 0.5h | P0 |
|
||||
| 2.2 创建驾驶舱页面骨架 | IitQcCockpitPage.tsx + 路由配置 | 1h | P0 |
|
||||
| 2.3 实现统计卡片组件 | 4 个卡片:质量分、违规数、Query 数、完成率 | 1.5h | P0 |
|
||||
| 2.4 实现风险热力图组件 | 矩阵式表格,颜色表示风险等级 | 3h | P0 |
|
||||
| 2.5 实现详情抽屉组件 | 点击单元格展示问题详情 | 2h | P1 |
|
||||
| 2.6 后端 API:热力图数据 | 按记录×表单聚合质控状态 | 1.5h | P0 |
|
||||
|
||||
**新增文件清单:**
|
||||
|
||||
```
|
||||
frontend-v2/src/modules/admin/
|
||||
├── pages/
|
||||
│ └── IitQcCockpitPage.tsx # 驾驶舱主页面
|
||||
├── components/
|
||||
│ ├── QcStatCards.tsx # 统计卡片组件
|
||||
│ ├── RiskHeatmap.tsx # 风险热力图组件
|
||||
│ └── QcDetailDrawer.tsx # 详情抽屉组件
|
||||
|
||||
backend/src/modules/admin/iit-projects/
|
||||
├── iitQcCockpitController.ts # 驾驶舱数据 API
|
||||
└── iitQcCockpitRoutes.ts # 路由定义
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 阶段 3:变量标签系统(P1)
|
||||
|
||||
**目标:支持按语义标签切片数据**
|
||||
|
||||
| 任务 | 描述 | 工作量 | 优先级 |
|
||||
|------|------|--------|--------|
|
||||
| 3.1 扩展数据库表 | `iit_field_metadata` 增加 `tags` 字段 | 0.5h | P1 |
|
||||
| 3.2 管理端标签编辑 | 质控规则页面支持为字段打标签 | 2h | P1 |
|
||||
| 3.3 REDCap 同步时自动打标签 | 根据表单名推断默认标签 | 1.5h | P2 |
|
||||
| 3.4 PromptBuilder 按标签切片 | 只加载指定标签的字段 | 1h | P1 |
|
||||
|
||||
**数据库变更:**
|
||||
|
||||
```sql
|
||||
-- 扩展 iit_field_metadata 表
|
||||
ALTER TABLE iit_schema.field_metadata
|
||||
ADD COLUMN tags TEXT[] DEFAULT '{}';
|
||||
|
||||
-- 示例数据
|
||||
UPDATE iit_schema.field_metadata
|
||||
SET tags = ARRAY['#demographics', '#screening']
|
||||
WHERE field_name IN ('age', 'date_of_birth', 'sex');
|
||||
|
||||
UPDATE iit_schema.field_metadata
|
||||
SET tags = ARRAY['#consent', '#ethics']
|
||||
WHERE field_name = 'informed_consent';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 阶段 4:高级功能(P2 - 延后)
|
||||
|
||||
| 任务 | 描述 | 工作量 | 优先级 |
|
||||
|------|------|--------|--------|
|
||||
| 4.1 LLM Trace 视图 | 展示发送给 LLM 的 Prompt | 3h | P2 |
|
||||
| 4.2 AI 自动提取规则 | 上传 Protocol PDF 自动生成规则 | 8h | P3 |
|
||||
| 4.3 Layer 2 AI 逻辑引擎 | 复杂医学逻辑判断 | 10h | P3 |
|
||||
| 4.4 导出监查报告 | 生成 PDF/Word 格式报告 | 4h | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 五、开发优先级总结
|
||||
|
||||
| 优先级 | 阶段 | 核心任务 | 预计工时 |
|
||||
|--------|------|----------|----------|
|
||||
| **P0** | 阶段 1 | LLM 格式优化(PromptBuilder + ChatService) | 5.5h |
|
||||
| **P0** | 阶段 2 | 管理端 UI(驾驶舱 + 统计卡片 + 热力图) | 9.5h |
|
||||
| **P1** | 阶段 3 | 变量标签系统 | 5h |
|
||||
| **P2** | 阶段 4 | 高级功能(延后) | 25h+ |
|
||||
|
||||
**MVP 阶段(阶段 1 + 2)总工时:~15 小时**
|
||||
|
||||
---
|
||||
|
||||
## 六、验收标准
|
||||
|
||||
### 6.1 阶段 1 验收
|
||||
|
||||
- [ ] 企业微信问"质控情况",AI 回答格式清晰、无幻觉
|
||||
- [ ] AI 回答包含具体问题和记录数
|
||||
- [ ] 日志中可看到 XML 格式的 Prompt
|
||||
|
||||
### 6.2 阶段 2 验收
|
||||
|
||||
- [ ] 点击"质控全览图"按钮可进入驾驶舱页面
|
||||
- [ ] 统计卡片正确显示质量分、违规数、完成率
|
||||
- [ ] 热力图正确显示记录×表单的质控状态
|
||||
- [ ] 点击红色单元格可查看问题详情
|
||||
|
||||
### 6.3 阶段 3 验收
|
||||
|
||||
- [ ] 字段可配置语义标签
|
||||
- [ ] PromptBuilder 支持按标签过滤数据
|
||||
- [ ] AI 查询时只加载相关字段
|
||||
|
||||
---
|
||||
|
||||
## 七、风险与依赖
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
|------|------|----------|
|
||||
| 热力图数据量大 | 页面卡顿 | 分页加载、虚拟滚动 |
|
||||
| XML 格式 Token 计算 | 超出 LLM 上下文限制 | 按标签切片、限制字段数 |
|
||||
| REDCap 表单结构多变 | 热力图列不固定 | 动态渲染、表单配置 |
|
||||
|
||||
---
|
||||
|
||||
## 八、相关文档
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [06-实时质控系统开发计划.md](./06-实时质控系统开发计划.md) | 质控后端架构 |
|
||||
| [CRA Agent 深度设计方案](../01-需求分析/CRA%20Agent%20(临床监查)%20深度设计与展现方案.md) | 技术方案参考 |
|
||||
| [质控管理原型图](../01-需求分析/质控管理原型图.html) | UI 原型参考 |
|
||||
|
||||
---
|
||||
|
||||
**文档维护人:** AI Assistant
|
||||
**创建时间:** 2026-02-08
|
||||
**下次评审:** 阶段 1 完成后
|
||||
@@ -989,9 +989,7 @@
|
||||
font-size: 1.2em;
|
||||
}.message-bubble .markdown-content h3 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.message-bubble .markdown-content ul,
|
||||
}.message-bubble .markdown-content ul,
|
||||
.message-bubble .markdown-content ol {
|
||||
margin: 8px 0 12px 0;
|
||||
padding-left: 24px;
|
||||
@@ -1028,4 +1026,4 @@
|
||||
border-radius: 4px;
|
||||
font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user