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
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
-- V3.1 Batch C: 项目健康度评分 — qc_project_stats 加维度通过率 + 健康度评分
|
||||
-- 全部 ADD COLUMN,向后兼容,零停机
|
||||
|
||||
ALTER TABLE "iit_schema"."qc_project_stats"
|
||||
ADD COLUMN IF NOT EXISTS "d1_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d2_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d3_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d5_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d6_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d7_pass_rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "health_score" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "health_grade" TEXT,
|
||||
ADD COLUMN IF NOT EXISTS "dimension_detail" JSONB NOT NULL DEFAULT '{}';
|
||||
@@ -0,0 +1,60 @@
|
||||
-- V3.1 QC Engine Architecture Upgrade — Batch B: Event-level aggregation layer
|
||||
-- 本迁移全部为 ADD COLUMN / CREATE TABLE,向后兼容,零停机
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- 1. 新增表:qc_event_status(事件级质控状态,由 qc_field_status 聚合)
|
||||
----------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS "iit_schema"."qc_event_status" (
|
||||
"id" TEXT NOT NULL,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"record_id" TEXT NOT NULL,
|
||||
"event_id" TEXT NOT NULL,
|
||||
"event_label" TEXT,
|
||||
"status" TEXT NOT NULL,
|
||||
"fields_total" INTEGER NOT NULL DEFAULT 0,
|
||||
"fields_passed" INTEGER NOT NULL DEFAULT 0,
|
||||
"fields_failed" INTEGER NOT NULL DEFAULT 0,
|
||||
"fields_warning" INTEGER NOT NULL DEFAULT 0,
|
||||
"d1_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"d2_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"d3_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"d5_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"d6_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"d7_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
"forms_checked" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
"top_issues" JSONB NOT NULL DEFAULT '[]',
|
||||
"triggered_by" TEXT NOT NULL,
|
||||
"last_qc_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "qc_event_status_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uq_event_status"
|
||||
ON "iit_schema"."qc_event_status"("project_id", "record_id", "event_id");
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_es_record"
|
||||
ON "iit_schema"."qc_event_status"("project_id", "record_id");
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_es_status"
|
||||
ON "iit_schema"."qc_event_status"("project_id", "status");
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- 2. 改造表:record_summary 加聚合字段
|
||||
----------------------------------------------------------------------
|
||||
ALTER TABLE "iit_schema"."record_summary"
|
||||
ADD COLUMN IF NOT EXISTS "events_total" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "events_passed" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "events_failed" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "events_warning" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "fields_total" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "fields_passed" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "fields_failed" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d1_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d2_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d3_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d5_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d6_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "d7_issues" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "top_issues" JSONB NOT NULL DEFAULT '[]';
|
||||
@@ -0,0 +1,64 @@
|
||||
-- V3.1 QC Engine Architecture Upgrade: Five-level data structure (Batch A)
|
||||
-- Changes:
|
||||
-- 1. New table: qc_field_status (five-level coordinate QC status)
|
||||
-- 2. qc_logs: add instance_id column
|
||||
-- 3. equery: add instance_id column
|
||||
-- 4. field_mapping: add semantic_label, form_name, rule_category columns
|
||||
-- All new columns have defaults or are nullable — backward compatible, zero downtime
|
||||
|
||||
-- ============================================================
|
||||
-- 1. Create qc_field_status table (five-level coordinate)
|
||||
-- ============================================================
|
||||
CREATE TABLE "iit_schema"."qc_field_status" (
|
||||
"id" TEXT NOT NULL,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"record_id" TEXT NOT NULL,
|
||||
"event_id" TEXT NOT NULL,
|
||||
"form_name" TEXT NOT NULL,
|
||||
"instance_id" INTEGER NOT NULL DEFAULT 1,
|
||||
"field_name" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL,
|
||||
"rule_id" TEXT,
|
||||
"rule_name" TEXT,
|
||||
"rule_category" TEXT,
|
||||
"severity" TEXT,
|
||||
"message" TEXT,
|
||||
"actual_value" TEXT,
|
||||
"expected_value" TEXT,
|
||||
"source_qc_log_id" TEXT,
|
||||
"triggered_by" TEXT NOT NULL,
|
||||
"last_qc_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "qc_field_status_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Unique constraint: one status per five-level coordinate
|
||||
CREATE UNIQUE INDEX "uq_field_status" ON "iit_schema"."qc_field_status"("project_id", "record_id", "event_id", "form_name", "instance_id", "field_name");
|
||||
|
||||
-- Query indexes
|
||||
CREATE INDEX "idx_fs_record" ON "iit_schema"."qc_field_status"("project_id", "record_id");
|
||||
CREATE INDEX "idx_fs_event" ON "iit_schema"."qc_field_status"("project_id", "record_id", "event_id");
|
||||
CREATE INDEX "idx_fs_status" ON "iit_schema"."qc_field_status"("project_id", "status");
|
||||
CREATE INDEX "idx_fs_category" ON "iit_schema"."qc_field_status"("project_id", "rule_category");
|
||||
|
||||
-- ============================================================
|
||||
-- 2. qc_logs: add instance_id (default 1, backward compatible)
|
||||
-- ============================================================
|
||||
ALTER TABLE "iit_schema"."qc_logs"
|
||||
ADD COLUMN "instance_id" INTEGER NOT NULL DEFAULT 1;
|
||||
|
||||
-- ============================================================
|
||||
-- 3. equery: add instance_id (default 1, backward compatible)
|
||||
-- ============================================================
|
||||
ALTER TABLE "iit_schema"."equery"
|
||||
ADD COLUMN "instance_id" INTEGER NOT NULL DEFAULT 1;
|
||||
|
||||
-- ============================================================
|
||||
-- 4. field_mapping: add V3.1 columns (all nullable)
|
||||
-- ============================================================
|
||||
ALTER TABLE "iit_schema"."field_mapping"
|
||||
ADD COLUMN "semantic_label" TEXT,
|
||||
ADD COLUMN "form_name" TEXT,
|
||||
ADD COLUMN "rule_category" TEXT;
|
||||
@@ -1139,14 +1139,17 @@ model IitQcReport {
|
||||
|
||||
/// 字段名映射字典表 - 解决 LLM 生成的字段名与 REDCap 实际字段名不一致的问题
|
||||
model IitFieldMapping {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
aliasName String @map("alias_name") // LLM 可能传的名称(如 "gender", "性别")
|
||||
actualName String @map("actual_name") // REDCap 实际字段名(如 "sex")
|
||||
fieldType String? @map("field_type") // 字段类型:text, number, date, radio, checkbox
|
||||
fieldLabel String? @map("field_label") // 字段显示标签
|
||||
validation Json? @db.JsonB // 验证规则 { min, max, pattern, choices }
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
aliasName String @map("alias_name") // LLM 可能传的名称(如 "gender", "性别")
|
||||
actualName String @map("actual_name") // REDCap 实际字段名(如 "sex")
|
||||
fieldType String? @map("field_type") // 字段类型:text, number, date, radio, checkbox
|
||||
fieldLabel String? @map("field_label") // 字段显示标签
|
||||
validation Json? @db.JsonB // 验证规则 { min, max, pattern, choices }
|
||||
semanticLabel String? @map("semantic_label") // V3.1: 中文语义标签(LLM 输出方向),如"谷丙转氨酶(ALT)"
|
||||
formName String? @map("form_name") // V3.1: 所属表单名
|
||||
ruleCategory String? @map("rule_category") // V3.1: 所属维度 D1-D7
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@unique([projectId, aliasName], map: "unique_iit_field_mapping")
|
||||
@@index([projectId], map: "idx_iit_field_mapping_project")
|
||||
@@ -1331,6 +1334,7 @@ model IitQcLog {
|
||||
// 质控类型
|
||||
qcType String @map("qc_type") // 'form' | 'holistic'
|
||||
formName String? @map("form_name") // 单表质控时记录表单名
|
||||
instanceId Int @default(1) @map("instance_id") // V3.1: 重复表单实例编号
|
||||
|
||||
// 核心结果
|
||||
status String // 'PASS' | 'FAIL' | 'WARNING'
|
||||
@@ -1396,6 +1400,28 @@ model IitRecordSummary {
|
||||
|
||||
// 更新次数(用于趋势分析)
|
||||
updateCount Int @default(0) @map("update_count")
|
||||
|
||||
// V3.1: 事件级聚合
|
||||
eventsTotal Int @default(0) @map("events_total")
|
||||
eventsPassed Int @default(0) @map("events_passed")
|
||||
eventsFailed Int @default(0) @map("events_failed")
|
||||
eventsWarning Int @default(0) @map("events_warning")
|
||||
|
||||
// V3.1: 字段级聚合
|
||||
fieldsTotal Int @default(0) @map("fields_total")
|
||||
fieldsPassed Int @default(0) @map("fields_passed")
|
||||
fieldsFailed Int @default(0) @map("fields_failed")
|
||||
|
||||
// V3.1: 维度计数(D1-D7)
|
||||
d1Issues Int @default(0) @map("d1_issues")
|
||||
d2Issues Int @default(0) @map("d2_issues")
|
||||
d3Issues Int @default(0) @map("d3_issues")
|
||||
d5Issues Int @default(0) @map("d5_issues")
|
||||
d6Issues Int @default(0) @map("d6_issues")
|
||||
d7Issues Int @default(0) @map("d7_issues")
|
||||
|
||||
// V3.1: 关键问题摘要
|
||||
topIssues Json @default("[]") @db.JsonB @map("top_issues")
|
||||
|
||||
// 时间戳
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
@@ -1428,6 +1454,19 @@ model IitQcProjectStats {
|
||||
|
||||
// 录入进度统计
|
||||
avgCompletionRate Float @default(0) @map("avg_completion_rate")
|
||||
|
||||
// V3.1: D1-D7 维度统计
|
||||
d1PassRate Float @default(0) @map("d1_pass_rate")
|
||||
d2PassRate Float @default(0) @map("d2_pass_rate")
|
||||
d3PassRate Float @default(0) @map("d3_pass_rate")
|
||||
d5PassRate Float @default(0) @map("d5_pass_rate")
|
||||
d6PassRate Float @default(0) @map("d6_pass_rate")
|
||||
d7PassRate Float @default(0) @map("d7_pass_rate")
|
||||
|
||||
// V3.1: 综合健康度(0-100 加权评分)
|
||||
healthScore Float @default(0) @map("health_score")
|
||||
healthGrade String? @map("health_grade") // 'A' | 'B' | 'C' | 'D' | 'F'
|
||||
dimensionDetail Json @default("{}") @db.JsonB @map("dimension_detail")
|
||||
|
||||
// 更新时间
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
@@ -1436,6 +1475,80 @@ model IitQcProjectStats {
|
||||
@@schema("iit_schema")
|
||||
}
|
||||
|
||||
/// V3.1 字段级质控状态表 — 五级坐标(Record → Event → Form → Instance → Field)
|
||||
/// 设计原则:每个字段最新一次 QC 结果,UPSERT 语义
|
||||
model IitQcFieldStatus {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
recordId String @map("record_id")
|
||||
eventId String @map("event_id")
|
||||
formName String @map("form_name")
|
||||
instanceId Int @default(1) @map("instance_id")
|
||||
fieldName String @map("field_name")
|
||||
|
||||
status String // 'PASS' | 'FAIL' | 'WARNING'
|
||||
ruleId String? @map("rule_id")
|
||||
ruleName String? @map("rule_name")
|
||||
ruleCategory String? @map("rule_category") // 'D1' | 'D2' | 'D3' | 'D5' | 'D6' | 'D7'
|
||||
severity String? // 'critical' | 'warning' | 'info'
|
||||
message String? @db.Text
|
||||
actualValue String? @map("actual_value")
|
||||
expectedValue String? @map("expected_value")
|
||||
|
||||
sourceQcLogId String? @map("source_qc_log_id")
|
||||
triggeredBy String @map("triggered_by") // 'webhook' | 'cron' | 'manual'
|
||||
lastQcAt DateTime @default(now()) @map("last_qc_at")
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([projectId, recordId, eventId, formName, instanceId, fieldName], map: "uq_field_status")
|
||||
@@index([projectId, recordId], map: "idx_fs_record")
|
||||
@@index([projectId, recordId, eventId], map: "idx_fs_event")
|
||||
@@index([projectId, status], map: "idx_fs_status")
|
||||
@@index([projectId, ruleCategory], map: "idx_fs_category")
|
||||
@@map("qc_field_status")
|
||||
@@schema("iit_schema")
|
||||
}
|
||||
|
||||
/// V3.1 事件级质控状态表 — 由 qc_field_status 聚合而来
|
||||
/// 设计原则:每个 project × record × event 唯一一行,UPSERT 语义
|
||||
model IitQcEventStatus {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
recordId String @map("record_id")
|
||||
eventId String @map("event_id")
|
||||
eventLabel String? @map("event_label")
|
||||
|
||||
status String // 最严重的子级状态
|
||||
fieldsTotal Int @default(0) @map("fields_total")
|
||||
fieldsPassed Int @default(0) @map("fields_passed")
|
||||
fieldsFailed Int @default(0) @map("fields_failed")
|
||||
fieldsWarning Int @default(0) @map("fields_warning")
|
||||
|
||||
d1Issues Int @default(0) @map("d1_issues")
|
||||
d2Issues Int @default(0) @map("d2_issues")
|
||||
d3Issues Int @default(0) @map("d3_issues")
|
||||
d5Issues Int @default(0) @map("d5_issues")
|
||||
d6Issues Int @default(0) @map("d6_issues")
|
||||
d7Issues Int @default(0) @map("d7_issues")
|
||||
|
||||
formsChecked String[] @default([]) @map("forms_checked")
|
||||
topIssues Json @default("[]") @db.JsonB @map("top_issues")
|
||||
|
||||
triggeredBy String @map("triggered_by")
|
||||
lastQcAt DateTime @default(now()) @map("last_qc_at")
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([projectId, recordId, eventId], map: "uq_event_status")
|
||||
@@index([projectId, recordId], map: "idx_es_record")
|
||||
@@index([projectId, status], map: "idx_es_status")
|
||||
@@map("qc_event_status")
|
||||
@@schema("iit_schema")
|
||||
}
|
||||
|
||||
/// eQuery 表 - AI 自动生成的电子质疑,具有完整生命周期
|
||||
model IitEquery {
|
||||
// TODO: Tech Debt - DB 由 prisma db push 创建为 UUID 类型,未来大版本重构时统一为 String/TEXT
|
||||
@@ -1446,6 +1559,7 @@ model IitEquery {
|
||||
recordId String @map("record_id")
|
||||
eventId String? @map("event_id")
|
||||
formName String? @map("form_name")
|
||||
instanceId Int @default(1) @map("instance_id") // V3.1: 重复表单实例编号
|
||||
fieldName String? @map("field_name")
|
||||
qcLogId String? @map("qc_log_id")
|
||||
reportId String? @map("report_id")
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import type { DimensionCode } from '../src/modules/iit-manager/engines/HardRuleEngine.js';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
@@ -40,7 +41,7 @@ const INCLUSION_RULES = [
|
||||
},
|
||||
message: '年龄不在 16-35 岁范围内',
|
||||
severity: 'error',
|
||||
category: 'inclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -61,7 +62,7 @@ const INCLUSION_RULES = [
|
||||
},
|
||||
message: '出生日期不在 1989-01-01 至 2008-01-01 范围内',
|
||||
severity: 'error',
|
||||
category: 'inclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -82,7 +83,7 @@ const INCLUSION_RULES = [
|
||||
},
|
||||
message: '月经周期不在 21-35 天范围内(28±7天)',
|
||||
severity: 'error',
|
||||
category: 'inclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -98,7 +99,7 @@ const INCLUSION_RULES = [
|
||||
},
|
||||
message: 'VAS 疼痛评分 < 4 分,不符合入组条件',
|
||||
severity: 'error',
|
||||
category: 'inclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -114,7 +115,7 @@ const INCLUSION_RULES = [
|
||||
},
|
||||
message: '未签署知情同意书',
|
||||
severity: 'error',
|
||||
category: 'inclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
}
|
||||
];
|
||||
@@ -136,7 +137,7 @@ const EXCLUSION_RULES = [
|
||||
},
|
||||
message: '存在继发性痛经(盆腔炎、子宫内膜异位症、子宫腺肌病等)',
|
||||
severity: 'error',
|
||||
category: 'exclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -152,7 +153,7 @@ const EXCLUSION_RULES = [
|
||||
},
|
||||
message: '妊娠或哺乳期妇女,不符合入组条件',
|
||||
severity: 'error',
|
||||
category: 'exclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -168,7 +169,7 @@ const EXCLUSION_RULES = [
|
||||
},
|
||||
message: '合并有心脑血管、肝、肾、造血系统等严重疾病或精神病',
|
||||
severity: 'error',
|
||||
category: 'exclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
},
|
||||
{
|
||||
@@ -184,7 +185,7 @@ const EXCLUSION_RULES = [
|
||||
},
|
||||
message: '月经周期不规律或间歇性痛经发作',
|
||||
severity: 'error',
|
||||
category: 'exclusion',
|
||||
category: 'D1' as DimensionCode,
|
||||
applicableEvents: [] as string[],
|
||||
}
|
||||
];
|
||||
@@ -261,7 +262,7 @@ const LAB_RULES = LAB_VALUE_RULES.map(item => ({
|
||||
},
|
||||
message: `${item.name}超出正常范围(${item.min}-${item.max} ${item.unit})`,
|
||||
severity: 'warning',
|
||||
category: 'lab_values',
|
||||
category: 'D3' as DimensionCode,
|
||||
metadata: { min: item.min, max: item.max, unit: item.unit }
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user