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:
@@ -243,6 +243,43 @@ export async function iitQcCockpitRoutes(fastify: FastifyInstance) {
|
||||
},
|
||||
}, iitQcCockpitController.refreshReport.bind(iitQcCockpitController));
|
||||
|
||||
// V3.1: D1-D7 维度统计
|
||||
fastify.get('/:projectId/qc-cockpit/dimensions', {
|
||||
schema: {
|
||||
description: 'D1-D7 各维度详细统计',
|
||||
tags: ['IIT Admin - 质控驾驶舱'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getDimensions.bind(iitQcCockpitController));
|
||||
|
||||
// V3.1: 按受试者缺失率
|
||||
fastify.get('/:projectId/qc-cockpit/completeness', {
|
||||
schema: {
|
||||
description: '按受试者返回缺失率',
|
||||
tags: ['IIT Admin - 质控驾驶舱'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getCompleteness.bind(iitQcCockpitController));
|
||||
|
||||
// V3.1: 字段级质控结果(分页)
|
||||
fastify.get('/:projectId/qc-cockpit/field-status', {
|
||||
schema: {
|
||||
description: '字段级质控结果(分页,支持 recordId/eventId/status 筛选)',
|
||||
tags: ['IIT Admin - 质控驾驶舱'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
recordId: { type: 'string' },
|
||||
eventId: { type: 'string' },
|
||||
status: { type: 'string', enum: ['PASS', 'FAIL', 'WARNING'] },
|
||||
page: { type: 'string', default: '1' },
|
||||
pageSize: { type: 'string', default: '50' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}, iitQcCockpitController.getFieldStatus.bind(iitQcCockpitController));
|
||||
|
||||
// AI 工作时间线
|
||||
fastify.get('/:projectId/qc-cockpit/timeline', iitQcCockpitController.getTimeline.bind(iitQcCockpitController));
|
||||
|
||||
@@ -251,4 +288,59 @@ export async function iitQcCockpitRoutes(fastify: FastifyInstance) {
|
||||
|
||||
// 质控趋势(近N天通过率折线)
|
||||
fastify.get('/:projectId/qc-cockpit/trend', iitQcCockpitController.getTrend.bind(iitQcCockpitController));
|
||||
|
||||
// V3.1: D6 方案偏离列表
|
||||
fastify.get('/:projectId/qc-cockpit/deviations', iitQcCockpitController.getDeviations.bind(iitQcCockpitController));
|
||||
|
||||
// ============================================================
|
||||
// GCP 业务报表路由
|
||||
// ============================================================
|
||||
|
||||
fastify.get('/:projectId/qc-cockpit/report/eligibility', {
|
||||
schema: {
|
||||
description: 'D1 筛选入选表 — 入排合规性评估',
|
||||
tags: ['IIT Admin - GCP 报表'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getEligibilityReport.bind(iitQcCockpitController));
|
||||
|
||||
fastify.get('/:projectId/qc-cockpit/report/completeness', {
|
||||
schema: {
|
||||
description: 'D2 数据完整性总览 — L1 项目 + L2 受试者 + L3 事件级统计',
|
||||
tags: ['IIT Admin - GCP 报表'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getCompletenessReport.bind(iitQcCockpitController));
|
||||
|
||||
fastify.get('/:projectId/qc-cockpit/report/completeness/fields', {
|
||||
schema: {
|
||||
description: 'D2 字段级懒加载 — 按 recordId + eventId 返回缺失字段清单',
|
||||
tags: ['IIT Admin - GCP 报表'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
recordId: { type: 'string' },
|
||||
eventId: { type: 'string' },
|
||||
},
|
||||
required: ['recordId', 'eventId'],
|
||||
},
|
||||
},
|
||||
}, iitQcCockpitController.getCompletenessFields.bind(iitQcCockpitController));
|
||||
|
||||
fastify.get('/:projectId/qc-cockpit/report/equery-log', {
|
||||
schema: {
|
||||
description: 'D3/D4 eQuery 全生命周期跟踪 — 统计 + 分组 + 全量明细',
|
||||
tags: ['IIT Admin - GCP 报表'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getEqueryLogReport.bind(iitQcCockpitController));
|
||||
|
||||
fastify.get('/:projectId/qc-cockpit/report/deviations', {
|
||||
schema: {
|
||||
description: 'D6 方案偏离报表 — 结构化超窗数据 + 汇总统计',
|
||||
tags: ['IIT Admin - GCP 报表'],
|
||||
params: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] },
|
||||
},
|
||||
}, iitQcCockpitController.getDeviationReport.bind(iitQcCockpitController));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user