/** * 调试脚本:诊断字段获取问题 * * 问题: * 1. Record 1 有 age=21,但质控显示空 * 2. Record 3 应该有年龄但 API 返回无 */ import { PrismaClient } from '@prisma/client'; import { RedcapAdapter } from './src/modules/iit-manager/adapters/RedcapAdapter.js'; import jsonLogic from 'json-logic-js'; const prisma = new PrismaClient(); async function main() { console.log('='.repeat(60)); console.log('🔍 字段获取问题诊断'); console.log('='.repeat(60)); // 1. 获取项目配置 const project = await prisma.iitProject.findFirst({ where: { name: { contains: 'test0207' } }, }); if (!project) { console.log('❌ 未找到项目'); await prisma.$disconnect(); return; } // 2. 获取质控规则配置 const skill = await prisma.iitSkill.findFirst({ where: { projectId: project.id, isActive: true }, }); if (!skill) { console.log('❌ 未找到激活的 Skill'); await prisma.$disconnect(); return; } const config = skill.config as any; const rules = config?.rules || []; console.log('\n📋 质控规则中的字段配置:'); for (const rule of rules) { console.log(` ${rule.name}:`); console.log(` field: "${rule.field}"`); console.log(` logic: ${JSON.stringify(rule.logic)}`); } // 3. 从 REDCap 获取原始数据(检查 Record 1 和 Record 3) const adapter = new RedcapAdapter(project.redcapUrl, project.redcapApiToken); console.log('\n' + '='.repeat(60)); console.log('📊 检查 Record 1 的原始 REDCap 数据'); console.log('='.repeat(60)); // 获取 Record 1 的原始记录(不合并) const rawRecords1 = await adapter.exportRecords({ records: ['1'] }); console.log(`\nRecord 1 原始记录数: ${rawRecords1.length} (多事件)`); for (const r of rawRecords1) { console.log(` 事件: ${r.redcap_event_name || '(无)'}`); console.log(` age: ${r.age !== undefined ? r.age : '(字段不存在)'}`); console.log(` date_of_birth: ${r.date_of_birth || '(空)'}`); } // 获取 Record 1 合并后的数据 const merged1 = await adapter.getRecordById('1'); console.log(`\nRecord 1 合并后数据:`); console.log(` age: ${merged1?.age}`); console.log(` date_of_birth: ${merged1?.date_of_birth}`); console.log('\n' + '='.repeat(60)); console.log('📊 检查 Record 3 的原始 REDCap 数据'); console.log('='.repeat(60)); const rawRecords3 = await adapter.exportRecords({ records: ['3'] }); console.log(`\nRecord 3 原始记录数: ${rawRecords3.length} (多事件)`); for (const r of rawRecords3) { console.log(` 事件: ${r.redcap_event_name || '(无)'}`); console.log(` age: ${r.age !== undefined ? r.age : '(字段不存在)'}`); console.log(` date_of_birth: ${r.date_of_birth || '(空)'}`); } const merged3 = await adapter.getRecordById('3'); console.log(`\nRecord 3 合并后数据:`); console.log(` age: ${merged3?.age}`); console.log(` date_of_birth: ${merged3?.date_of_birth}`); // 4. 模拟质控规则执行,看看哪里出问题 console.log('\n' + '='.repeat(60)); console.log('📊 模拟质控规则执行 (Record 1)'); console.log('='.repeat(60)); // 找到年龄规则 const ageRule = rules.find((r: any) => r.name.includes('年龄')); if (ageRule && merged1) { console.log(`\n规则: ${ageRule.name}`); console.log(` field: "${ageRule.field}"`); console.log(` logic: ${JSON.stringify(ageRule.logic)}`); // 检查字段值 const fieldValue = merged1[ageRule.field]; console.log(`\n 从数据中获取 "${ageRule.field}" 的值: ${fieldValue} (类型: ${typeof fieldValue})`); // 尝试执行 JSON Logic try { const result = jsonLogic.apply(ageRule.logic, merged1); console.log(` JSON Logic 执行结果: ${result}`); } catch (error: any) { console.log(` JSON Logic 执行失败: ${error.message}`); } // 列出数据中所有可能的年龄相关字段 console.log(`\n 数据中的年龄相关字段:`); for (const [key, value] of Object.entries(merged1)) { if (key.toLowerCase().includes('age') || key === ageRule.field) { console.log(` ${key}: ${value}`); } } } // 5. 检查 SkillRunner 如何获取记录 console.log('\n' + '='.repeat(60)); console.log('📊 检查 SkillRunner 获取记录的方式'); console.log('='.repeat(60)); // 查看 getRecordsToProcess 的实现逻辑 // 它可能使用不同的方法获取数据 const allRecordsMerged = await adapter.getAllRecordsMerged(); console.log(`\ngetAllRecordsMerged 返回 ${allRecordsMerged.length} 条记录`); const r1FromAll = allRecordsMerged.find(r => r.record_id === '1'); const r3FromAll = allRecordsMerged.find(r => r.record_id === '3'); console.log(`\nRecord 1 from getAllRecordsMerged:`); console.log(` age: ${r1FromAll?.age}`); console.log(` date_of_birth: ${r1FromAll?.date_of_birth}`); console.log(`\nRecord 3 from getAllRecordsMerged:`); console.log(` age: ${r3FromAll?.age}`); console.log(` date_of_birth: ${r3FromAll?.date_of_birth}`); console.log('\n' + '='.repeat(60)); console.log('✅ 诊断完成'); console.log('='.repeat(60)); await prisma.$disconnect(); } main().catch(async (error) => { console.error('❌ 脚本出错:', error); await prisma.$disconnect(); process.exit(1); });