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:
2026-03-01 22:49:49 +08:00
parent 0b29fe88b5
commit 2030ebe28f
50 changed files with 8687 additions and 1492 deletions

View File

@@ -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 }
}));