简介这套EDC电子数据采集系统完整源代码面向临床研究领域的系统开发者、临床试验数据管理员及医学信息研究者用于解决临床试验数据采集、校验、管理与分析中的效率与准确性问题覆盖项目管理、试验设计、CRF表单设计、疑问管理、数据录入、逻辑自动校验、CRF/DCF导出PDF及统计报表等关键功能。压缩包共6个文件以4个Java源文件为主体另含2个scc辅助文件整体大小仅17KBJava文件对应系统核心业务逻辑scc文件为源码管理辅助标记便于追溯版本。资源内包含input数据录入与handquery手动查询两个功能模块分别对应受试者数据录入和手动查询两条链路代码结构简洁适合学习或二次开发。该资源已有1722人学习/下载对于希望快速上手临床试验数据采集流程、理解EDC系统模块设计或需要轻量级参考实现的开发者是一份可直接研读的源头代码。 EDC系统全称是Electronic Data Capture System临床研究里的数据采集管理平台。干这行的都知道一期临床试验几百个病例每个病例几十个访视每个访视几百个数据点再加上方案偏离记录、不良事件、合并用药靠Excel根本管不过来更别提满足监管方对数据完整性、可追溯性的硬性要求。所以EDC系统不是“要不要上”的问题而是“怎么上、怎么选、怎么落地”的问题。这次我整理了一份临床研究数据采集管理EDC系统的完整源代码从受试者入组、访视安排、电子CRF表单构建到数据校验、质疑管理、电子签名、稽查轨迹再到最后的数据库锁定与导出把一整套闭环逻辑全部落在代码里了。本文就基于这套代码把我的设计思路、模块拆解、关键实现和踩过的坑全部梳理一遍。对正在自研EDC、想评估EDC源码质量、或者刚接手相关项目的同行都有直接的参考价值。1. 内容整体设计与思路拆解1.1 为什么需要一套“完整”的源码而不是零散的功能代码很多人找EDC源代码上来就问有没有现成的“病历报告表设计器”或者“数据校验规则”脚本。但真正用过临床数据管理系统的人都知道EDC是一个强流程、强状态机、强审计要求的系统碎片化代码根本撑不起真实的项目运营受试者从筛选Screening到随机Randomization、治疗Treatment、随访Follow-up、结束Completion、提前退出Early Termination每一步都有严格的状态流转每次数据修改都要留痕稽查轨迹Audit Trail必须记录谁、何时、改了哪个字段的哪个值改前值、改后值、原因说明数据锁定后任何字段都不允许再改动否则整个统计分析的盲态就被破坏了不同角色CRC、CRA、DM、PI、申办方看到的数据范围、可操作按钮、审核流程完全不一样。所以这套源码在设计之初就是按“可运行、可上线、可验收”的标准来组织的。不是给你一个能跑的Demo而是把项目配置、数据采集、数据清洗、过程管控、报表输出一条链路全部打通。1.2 模块选型与整体架构既要合规也要实用整套系统采用前后端分离架构。后端用Spring Boot 2.7 MyBatis-Plus MySQL 8.0前端用Vue 3 Element Plus认证授权用Spring Security JWT。选这套组合的原因很简单招人容易、社区活跃、部署简单绝大多数做临床数据管理的团队都能快速接手。在部署上做了Docker化处理数据库、后端服务、前端静态资源、MinIO文件存储各一个容器一条命令就能把整套环境拉起来。这对做演示、做POC、做培训验证特别重要——不用花三天时间配环境拿到源码当天就能看到完整界面在跑。这也回应了一个很常见的问题“EDC需要部署在验证过的服务器上自己用Docker搭一套行不行”答案是Docker更适合开发、测试、演示环境用在生产环境前必须完成计算机化系统验证CSV包括安装确认IQ、运行确认OQ、性能确认PQ。这套源码的定位是让你以最低成本跑通全部业务逻辑再在合规框架下去做环境迁移。2. 核心模块设计与数据库表关系解析2.1 受试者全生命周期管理从筛选到锁库的闭环受试者模块是EDC的“地基”。如果没有一套清晰的状态机很容易出现“受试者已经提前退出了还在填后续访视的表单”这种逻辑漏洞。我设计了一张subject表和一张subject_status_log表。subject表记录受试者编号Subject ID、筛选日期、随机号、入组日期、状态等静态信息。状态字段用枚举管理SCREENING、RANDOMIZED、ON_TREATMENT、COMPLETED、WITHDRAWN、SCREEN_FAILED。subject_status_log表记录每一次状态变更的时间、操作人、变更原因配合后端的状态机校验防止非法跳转。状态机校验的核心逻辑是任何状态变更请求都先经过SubjectStateMachine校验比如状态为 COMPLETED试验完成的受试者不允许直接变成 WITHDRAWN提前退出必须先走方案偏离或不良事件流程。这个设计在稽查时会非常加分因为监管方本来就要求“系统应有机制防止不合理的状态流转”。2.2 电子CRF表单引擎不写代码的动态建表方案CRFCase Report Form病例报告表是EDC的灵魂。方案不同CRF结构完全不同有的项目表单是固定的有的项目需要在试验过程中新增访视或新版CRF。所以这套源码选择了“元数据驱动”的动态表单引擎而不是为每个表单硬编码一张数据库表。核心表有三张form_template表单模板存访视编码、表单名称、表单版本、是否启用form_field字段定义存字段名Field Name、字段标签Label、字段类型Text/Number/Date/Radio/Checkbox/Dropdown、是否必填、是否受控术语form_field_option下拉选项或单选选项的候选值绑定医学编码字典如MedDRA、WHO Drug。前端表单渲染引擎会根据form_field的配置动态生成页面新增一个字段只需在后台配置不用重新发版。很多团队觉得“动态表单会影响录入效率”但实测下来配合字段级权限和条件显示即逻辑跳转效率反而比传统表单高因为患者当前症状不同显示的字段也会自动变化录入员看到的就是最精简的界面。3. 实操过程与核心环节实现3.1 项目创建与CRF构建完整流程拆解一个典型的EDC实施项目从建库到上线录制需要经过以下环节。我在代码中把这套流程做成了可视化向导任何有DM背景的人都能快速上手。项目配置阶段在“项目管理”菜单创建试验项目设置试验编号、试验名称、适应症、方案版本号。保存后系统会自动创建该项目的独立数据库Schema或逻辑隔离空间。这样多个试验项目跑在同一套EDC上数据不会相互污染。访视与表单构建一个完整的试验方案通常包含筛选期、治疗期、随访期和试验结束。以肿瘤项目为例筛选期有“入选排除标准”“基线肿瘤评估”“实验室检查”治疗期有“用药记录”“不良事件”“合并用药”随访期有“疗效评估”“生存随访”。我梳理了这套源码中的实际CRF构建模板核心逻辑就这么几步在“访视管理”模块创建访视比如 Visit 1Screening、Visit 2Baseline、Visit 3Week 6 随访在访视下挂表单比如“生命体征”“实验室检查”“不良事件”在表单中添加字段除了常规的文本、数字、日期、下拉还支持“计算字段”可以自定义公式如BMI自动根据身高体重计算和“逻辑控制”当某个字段填了“是”才显示下一组字段设置字段级的编辑权限比如“实验室检查结果”只有CRC能录入CRA只能查看表单版本化如果试验中途方案修订可以直接复制旧版表单修改后发布新版本旧数据不受影响新数据按新版录入。这一步的关键代码在FormFieldController和DynamicFormParser。前者负责字段的后台管理后者负责把数据库中的元数据JSON解析成前端页面的表格和控件。3.2 数据校验与质疑管理核心逻辑与代码实现EDC系统最核心的价值是数据质量的实时控制。录入员保存表单时系统必须立即检查数据是否满足方案要求不满足的自动生成质疑Query数据管理员审核后发给录入员修改。这套系统的校验引擎有两种触发方式即时校验Frontend Validation前端在失焦blur时校验比如“收缩压”字段只能输入 50~300 之间的整数用字典项“男/女/未知”控制受控术语后端规则校验Backend Rule Engine以Groovy脚本的形式支持复杂逻辑比如“如果受试者性别为男性则‘是否怀孕’字段不可填写且不应显示”。这个规则引擎用Groovy而不是硬编码Java因为不同项目的校验规则千差万别Groovy脚本可以做到不改代码热更新。质疑管理的数据表设计如下表名核心字段用途说明queryquery_id, subject_id, form_instance_id, field_name, query_type, status, assigned_to质疑主表记录每个问题发生在哪个受试者、哪个表单、哪个字段query_replyreply_id, query_id, reply_content, replied_by, replied_at质疑回复记录query_loglog_id, query_id, operation, operator, operate_at质疑流转轨迹新增、回复、关闭、重开、取消全部留痕质疑的状态机设计为OPEN待处理→ REPLIED已回复→ CLOSED已关闭如果数据管理员对回复不满意可以把质疑重新打开REOPEN并追加说明理由。这个“质疑闭环”逻辑在稽查时是检查重点必须做到每次状态变化都有记录所以我在每一次状态流转时除了更新状态字段还会强制写入query_log。3.3 电子签名与稽查轨迹满足GCP要求的不可否认性设计电子签名不只是“输入账号密码”而是要满足21 CFR Part 11的电子记录/电子签名要求。这套源码的签名流程是在表单提交或稽查关键节点用户需要重新输入账号和密码系统校验合格后生成一个带时间戳的签名记录绑定用户姓名、角色、操作内容和签名的唯一ID。签名记录表esignature_record包含签名者ID、姓名、角色签名对应的数据记录ID记录是哪个患者、哪个表单、哪个版本签名类型INITIAL、CORRECT、FINAL签名时的完整数据快照JSON格式记录了“签名那一刻表单是什么样子”SHA-256哈希值用于防篡改验证。“数据快照”这个设计特别重要。如果只记录“谁在什么时候签了名”而不记录签名那一刻表单的具体内容稽查时无法证明数据在签名后没被改过。所以每次签名时源码会自动生成当前表单所有字段值 字段Label 字段版本的JSON快照计算哈希后存入签名表。下次核对时用同样的算法重新计算现有数据的哈希与存储值对比就能检测出是否被非法篡改。稽查轨迹的实现则依托于MyBatis-Plus的元数据填充MetaObjectHandler和AOP切面。对所有数据表的增、删、改操作系统自动记录操作前值和操作后值落到audit_trail表操作时间、操作人、操作类型INSERT/UPDATE/DELETE表名、主键ID、字段名修改前值JSON、修改后值JSON修改原因说明填写“数据录入错误更正”“方案定义更新”等。这条链路覆盖了90%以上的监管追溯需求。唯一要注意的是AOP记录操作日志会增加一定的IO开销。在真实项目中我建议用异步线程池去写审计日志同时保证事务提交后日志必须先落库再返回前端操作成功的提示确保“操作看似成功了日志也一定存在”。3.4 随机化与药物管理与EDC边界划分的常见误区很多团队做EDC时想把随机化、药物调配都塞进EDC里。我的建议是EDC系统只负责记录数据随机化和发药功能交互的场景必须理清逻辑边界。随机化通常由独立的IWRS交互式网络应答系统系统管理EDC通过接口同步随机化编号和药物编号即可。这套源码中的做法是提供RandomizationService接口通过API对接外部IWRS系统。每次调用时前端填写受试者编号后端将编号发送至IWRS获取返回的随机分组结果和药物编号自动填充到EDC的“随机化记录”表单。整个过程不提供人工直接编辑随机结果的功能——这是底线也是稽查的常见关注点。如果项目预算有限用不到独立IWRS系统源码也内置了一个简易随机化模块支持区组随机和分层随机根据中心、年龄分层算法在SimpleRandomizer类中。但正式项目中我一般不建议用内嵌随机化因为独立系统更容易做盲态保护且随机化种子和算法应该对EDC系统的普通操作员不可见。3.5 数据库锁定与SDV源数据核验试验结束前的最后一道闸数据库锁定Database Lock是EDC项目最关键的操作。测试数据、脏数据、未清理的质疑哪怕有一项没处理完都不应该允许锁库。这套源码在锁定前会自动做“锁定检查”受试者状态完整性是否存在状态为“ONGOING”的受试者若有必须确认是否应该提前终止表单完整性是否存在未填写的必填字段form_field.is_required true且字段值为空质疑状态是否还有 OPEN 状态的质疑必须全部CLOSED签名状态关键表单是否已完成电子签名系统会生成一份“锁库检查报告”列出所有不满足条件的项目数据管理员逐条处理完后才能点击“提交锁库”。锁库完成后所有表单进入只读状态任何修改操作都会被系统拒绝并记录尝试行为——这个“拒绝并记录”的功能也在一定程度上保护了数据完整性。SDVSource Data Verification源数据核验则是将EDC数据与住院病历、检验报告单等原始数据核对的流程。源码中提供了sdv_task表和sdv_verify_record表CRA在系统里创建核验任务逐条填写“已与源数据核对是否一致”的结果并做电子签名。虽然SDV操作本身偏流程化但表设计得好不好直接决定了锁库前的核查效率。4. 源码落地过程中最常见的坑与对应解决方案4.1 电子表单字段调整后历史数据“错位”这是动态CRF最常见的坑。比如某数字字段本来填的是“收缩压mmHg”因为方案修订这个字段的定义改成了“舒张压mmHg”如果不做字段版本控制历史数据就会被新的字段定义污染统计时会产生不可信的数据。解决办法这套源码里引入了“字段版本号”。每次编辑字段定义系统会生成一条新版本同时保留该字段的历史版本。查询历史数据时按当时录入时绑定的版本号去解释字段含义。这个小设计在应对临床项目长期运营时非常实用。4.2 MySQL的JSON字段在复杂查询时的性能问题由于动态表单的数据存储在JSON字段中当项目数据量到了几万条记录按字段值做筛选会明显变慢。实测中一条带JSON字段过滤条件的列表查询数据量10万条时耗时可能从毫秒级涨到秒级。我的优化经验是核心查询字段如受试者编号、访视编码、表单编码在表中建独立冗余列并加复合索引JSON字段只存“页面展示用”的完整数据。这么做既保留了动态表单的灵活性又避免了全部依赖MySQL JSON函数带来的性能瓶颈。另外MySQL的JSON字段还有一个大坑写入时不做结构性校验。解决办法是在后端DynamicFormParser中定义完整的校验器用JSON Schema校验前端传入的表单数据不符合Schema直接400拒绝避免脏数据落库。4.3 稽查轨迹丢了怎么办“丢日志”是数据完整性的大忌。排查后发现常见原因是AOP切面在事务提交前就同步写日志如果业务失败回滚日志也被一起回滚了。正确的做法是把消息发送到MQ队列单独事务去落库或者写日志时使用独立数据源和不参与业务回滚的事务。这套源码的默认实现是“同步写日志 独立事务REQUIRES_NEW”简单项目够用如果数据量特别大我会建议扩展成Logback/MQ异步处理但注意确保消息不丢失比如落盘前先写入本地队列。4.4 权限粒度太粗导致的数据越权很多团队做权限管理时只分“管理员、录入员、查看者”三类角色这在EDC场景下完全不够。实际项目中常有“CRA只许看自己所在中心的受试者”“DM只能看到未锁定的数据”“CRC只能编辑自己负责的受试者”这类需求。这套源码实现了“角色-数据范围”双维度控制。角色控制“能做什么操作”查看、编辑、审核、导出、锁库数据范围控制“能看哪些数据”全部项目、仅本中心、仅本人负责的受试者。数据范围校验不是在前端隐藏按钮而是在后端做全局拦截器即使有人绕过前端直接调接口也无法跨越数据权限。5. 部署验证与源代码交付后的下一步建议5.1 本地环境快速运行指南源码拿到手后建议按以下顺序启动安装Docker DesktopWindows/Mac均可确保有4GB以上可用内存在根目录执行docker-compose up -d拉起MySQL、MinIO、Redis、后端服务和前端Nginx容器访问http://localhost:8080默认用户名admin初始密码在README中登录后先进入“系统初始化”页面创建试验项目、编辑CRF模板创建两个测试账号一个CRC、一个DM按“录入数据 → 自动校验 → 生成质疑 → 回复质疑 → 关闭质疑 → 电子签名 → 锁库”的流程完整走一遍确认全链路正常。我特别建议第一步就模拟“录错数据”来验证质疑流程。比如在“收缩压”字段里填一个600前端会立即报错但你要测的是后端层——通过API直接推送600这个值看系统是否拒绝、是否产生质疑、质疑回复后能否正确关闭。这才是真正的“系统抗造”验证。5.2 源码交付后的合规路径规划拿到源码不等于系统可以直接上线围绕合规还需要做三件事完成计算机化系统验证CSV准备验证计划VP、需求规格说明书URS、功能规范FS、设计规范DS、Traceability Matrix追溯矩阵按机构SOP完成IQ/OQ/PQ建立系统管理员SOP包括用户账号管理、角色权限分配、CRF变更流程、数据备份与恢复流程、业务连续性计划缺陷管理流程在系统运维期发现Bug后需要有标准化的“分析缺陷-修复-回归测试-发布-记录”机制并且修复中对历史数据的影响要评估。做过真实项目的人都知道临床数据系统的合规投入很多时候比开发投入还要大。这也是为什么我坚持把这套代码做得尽量贴近真实生产系统的原因——如果不按生产标准来写验证阶段会不断踩坑改造成本比从零开发还高。5.3 基于这套源码还能扩展的三个方向如果这套EDC源码在你的团队里跑顺了后续可以按优先级考虑以下扩展将表单引擎升级为支持“多中心协作”增加中心级数据隔离和中心级质控看板增加“EDC与LIS实验室信息系统对接”实验室结果自动回传减少手工转录错误引入“SAS导出接口”统计分析阶段直接把EDC数据导出成SAS XPORT格式避免中间转换环节出错。我个人在实际操作中的体会是EDC系统的价值不在于界面多漂亮而在于数据流转的严谨程度。从数据录入到锁库每一环都要有控制、有记录、有审计。这套源码的核心思路就是把“严谨”两个字用代码落实下来希望给正在做临床数据管理的团队一个可以直接上手、少走弯路的基础工程。哪怕你不打算完全用这套代码把它当做一个业务逻辑参考手册也能帮你在实际项目中规避很多隐蔽的坑。本文还有配套的精品资源点击获取