核心成果: 创建REDCap模块文档体系(4个分类目录) 完成《REDCap Docker部署操作手册》- 最核心文档 梳理从0到1的完整部署流程 明确Docker文件的可复用性 文档体系: - 00-模块概览/ 系统介绍、方案设计、决策报告 - 01-部署与配置/ 部署手册、问题排查(核心) - 02-系统配置与运维/ 日常管理(规划中) - 03-API对接与开发/ API开发、二次开发 - 04-参考资料/ 旧版文档存档 核心文档: 10-REDCap_Docker部署操作手册.md(最重要) - 完整的从0到1部署流程 - Docker文件复用说明和可复用性分析 - 3种环境差异配置(本地/ECS/医院) - 5大常见问题与解决方案 - 部署检查清单 - 日常维护命令 13-部署问题排查手册.md - 基于实际踩坑经验 - ERR_CONTENT_DECODING_FAILED - CRLF污染问题 - Base URL配置错误 - MySQL连接问题 Docker文件可复用性: 100%可复用(无需修改): - Dockerfile.redcap - docker-entrypoint.sh - config/php/php.ini - .gitattributes 需根据环境调整: - docker-compose.yml(端口、卷路径) - config/apache/redcap.conf(域名) - config/database.php(数据库连接) 文档重组: - 移动文档到对应分类目录 - 重命名为标准格式(数字前缀) - 旧版文档归档到参考资料 - 创建README快速入口 下一步: - Day 2: 开发REDCap API Adapter - 创建API使用指南 - 创建对接设计文档
1201 lines
40 KiB
Markdown
1201 lines
40 KiB
Markdown
# REDCap与AIclinicalresearch平台对接总体方案
|
||
|
||
> **文档版本:** v1.0
|
||
> **创建日期:** 2025-12-30
|
||
> **最后更新:** 2025-12-30
|
||
> **文档状态:** 规划中
|
||
> **作者:** 技术架构师
|
||
|
||
---
|
||
|
||
## 📋 文档说明
|
||
|
||
本文档定义REDCap(15.8.0)与壹证循AI科研平台的**完整对接方案**,包括:
|
||
1. 对接架构设计
|
||
2. External Module开发方案
|
||
3. API集成方案
|
||
4. 数据流设计
|
||
5. 开发计划与实施步骤
|
||
|
||
**前置条件:**
|
||
- ✅ 已获得REDCap官方授权
|
||
- ✅ 拥有REDCap 15.8.0源代码
|
||
- ✅ 拥有External Module Framework文档
|
||
|
||
**相关文档:**
|
||
- [REDCap 二次开发深度指南](./REDCap%20二次开发深度指南.md)
|
||
- [系统架构分层设计](../../00-系统总体设计/01-系统架构分层设计.md)
|
||
|
||
---
|
||
|
||
## 🎯 对接目标与价值
|
||
|
||
### 核心目标
|
||
|
||
**将REDCap的强大EDC能力与AI科研平台的AI增值功能深度融合**
|
||
|
||
```
|
||
REDCap (数据采集) + AIclinicalresearch (AI能力)
|
||
↓ ↓
|
||
临床数据录入 AI智能处理、分析、洞察
|
||
↓ ↓
|
||
完整的AI驱动临床研究闭环
|
||
```
|
||
|
||
### 业务价值
|
||
|
||
| 功能模块 | REDCap基础能力 | AI平台增值能力 | 协同价值 |
|
||
|---------|--------------|--------------|---------|
|
||
| **数据采集** | ✅ 表单设计、数据录入、验证 | 🎁 AI辅助录入、智能质控 | 提升录入效率50% |
|
||
| **数据清洗** | ⚠️ 手动查询、导出Excel | 🎁 DC模块自动清洗、NER提取 | 减少数据处理时间80% |
|
||
| **统计分析** | ⚠️ 需导出到R/SPSS | 🎁 SSA模块一键分析、可视化 | 降低统计门槛,分析速度提升10倍 |
|
||
| **文献支持** | ❌ 无 | 🎁 ASL模块智能文献筛选 | 系统评价效率提升5倍 |
|
||
| **AI问答** | ❌ 无 | 🎁 AIA模块10+智能体辅助 | 全流程AI辅助 |
|
||
| **知识库** | ❌ 无 | 🎁 PKB模块RAG问答 | 项目知识沉淀 |
|
||
|
||
---
|
||
|
||
## 🏗️ 对接架构设计
|
||
|
||
### 整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 用户层(研究人员/医生) │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 前端展示层 │
|
||
│ ┌────────────────┐ ┌─────────────────────────┐ │
|
||
│ │ REDCap Web UI │ │ AIclinicalresearch │ │
|
||
│ │ (原生界面) │◄────────────►│ Frontend (React) │ │
|
||
│ └────────────────┘ └─────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 集成层(核心) │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ REDCap External Module: "AI Research Assistant" │ │
|
||
│ │ ───────────────────────────────────────────────────── │ │
|
||
│ │ ├── 数据同步服务 (Data Sync Service) │ │
|
||
│ │ ├── AI功能菜单 (AI Menu Links) │ │
|
||
│ │ ├── Hooks处理器 (Hook Handlers) │ │
|
||
│ │ └── API代理层 (API Proxy) │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ ↕ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ AIclinicalresearch Backend RESTful API │ │
|
||
│ │ /api/v1/redcap/* │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 业务处理层(AI能力) │
|
||
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
|
||
│ │ DC │ │ SSA │ │ ASL │ │ AIA │ │ PKB │ ... │
|
||
│ │数据 │ │统计 │ │文献 │ │问答 │ │知识库│ │
|
||
│ │清洗 │ │分析 │ │筛选 │ │ │ │ │ │
|
||
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 数据存储层 │
|
||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||
│ │ REDCap MySQL │ │ AI Platform │ │
|
||
│ │ (临床数据) │◄───────►│ PostgreSQL │ │
|
||
│ │ - 患者数据 │ 同步 │ (分析结果) │ │
|
||
│ │ - 表单元数据 │ │ - 清洗后数据 │ │
|
||
│ └──────────────────┘ └──────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 核心对接模式
|
||
|
||
我们采用**双向对接**策略:
|
||
|
||
#### 模式A:REDCap → AI平台(数据推送)
|
||
|
||
```
|
||
用户在REDCap录入数据
|
||
↓
|
||
redcap_save_record Hook触发
|
||
↓
|
||
External Module推送数据到AI平台API
|
||
↓
|
||
AI平台处理(清洗/分析/AI处理)
|
||
↓
|
||
结果返回REDCap存储
|
||
```
|
||
|
||
#### 模式B:AI平台 → REDCap(数据拉取)
|
||
|
||
```
|
||
用户在AI平台发起分析
|
||
↓
|
||
AI平台调用REDCap API获取数据
|
||
↓
|
||
AI平台执行分析(DC/SSA/AIA等)
|
||
↓
|
||
结果展示在AI平台前端
|
||
↓
|
||
(可选)结果回写REDCap
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 技术方案详解
|
||
|
||
### 方案1:REDCap External Module开发
|
||
|
||
#### 模块命名与结构
|
||
|
||
```
|
||
模块名称: ai_research_assistant
|
||
版本: v1.0.0
|
||
完整目录: <redcap-root>/modules/ai_research_assistant_v1.0.0/
|
||
|
||
目录结构:
|
||
ai_research_assistant_v1.0.0/
|
||
├── config.json # 模块配置
|
||
├── AiResearchAssistantModule.php # 主逻辑类
|
||
├── README.md # 说明文档
|
||
├── LICENSE # MIT许可
|
||
├── pages/ # 自定义页面
|
||
│ ├── dashboard.php # AI功能仪表盘
|
||
│ ├── data_sync.php # 数据同步管理
|
||
│ ├── analysis_center.php # 分析中心
|
||
│ └── settings.php # 模块设置
|
||
├── js/ # JavaScript文件
|
||
│ ├── dashboard.js
|
||
│ └── data_sync.js
|
||
├── css/ # 样式文件
|
||
│ └── style.css
|
||
└── services/ # 服务类
|
||
├── ApiClient.php # AI平台API客户端
|
||
├── DataMapper.php # 数据映射转换
|
||
└── SyncService.php # 同步服务
|
||
```
|
||
|
||
#### config.json核心配置
|
||
|
||
```json
|
||
{
|
||
"name": "AI Research Assistant",
|
||
"description": "壹证循AI科研平台集成模块 - 提供数据智能清洗、统计分析、文献支持等AI增值功能",
|
||
"authors": [
|
||
{
|
||
"name": "壹证循科技",
|
||
"email": "support@yizx.ai",
|
||
"institution": "壹证循科技"
|
||
}
|
||
],
|
||
"framework-version": 16,
|
||
"permissions": [],
|
||
"links": {
|
||
"project": [
|
||
{
|
||
"name": "🤖 AI功能中心",
|
||
"icon": "fas fa-brain",
|
||
"url": "pages/dashboard.php",
|
||
"show-header-and-footer": true
|
||
},
|
||
{
|
||
"name": "🔄 数据同步",
|
||
"icon": "fas fa-sync-alt",
|
||
"url": "pages/data_sync.php",
|
||
"show-header-and-footer": true
|
||
},
|
||
{
|
||
"name": "📊 AI分析中心",
|
||
"icon": "fas fa-chart-line",
|
||
"url": "pages/analysis_center.php",
|
||
"show-header-and-footer": true
|
||
}
|
||
],
|
||
"control-center": [
|
||
{
|
||
"name": "AI平台配置",
|
||
"icon": "fas fa-cog",
|
||
"url": "pages/settings.php"
|
||
}
|
||
]
|
||
},
|
||
"system-settings": [
|
||
{
|
||
"key": "ai_platform_url",
|
||
"name": "AI平台地址",
|
||
"type": "text",
|
||
"required": true,
|
||
"default": "https://ai.yizx.com"
|
||
},
|
||
{
|
||
"key": "ai_platform_api_key",
|
||
"name": "API密钥",
|
||
"type": "password",
|
||
"required": true
|
||
},
|
||
{
|
||
"key": "enable_auto_sync",
|
||
"name": "启用自动同步",
|
||
"type": "checkbox",
|
||
"default": true
|
||
}
|
||
],
|
||
"project-settings": [
|
||
{
|
||
"key": "sync_mode",
|
||
"name": "同步模式",
|
||
"type": "dropdown",
|
||
"choices": [
|
||
{"value": "manual", "name": "手动同步"},
|
||
{"value": "realtime", "name": "实时同步"},
|
||
{"value": "scheduled", "name": "定时同步"}
|
||
],
|
||
"default": "realtime"
|
||
},
|
||
{
|
||
"key": "enable_dc_module",
|
||
"name": "启用数据清洗模块",
|
||
"type": "checkbox",
|
||
"default": true
|
||
},
|
||
{
|
||
"key": "enable_ssa_module",
|
||
"name": "启用统计分析模块",
|
||
"type": "checkbox",
|
||
"default": true
|
||
},
|
||
{
|
||
"key": "enable_asl_module",
|
||
"name": "启用智能文献模块",
|
||
"type": "checkbox",
|
||
"default": false
|
||
}
|
||
],
|
||
"crons": [
|
||
{
|
||
"cron_name": "data_sync_cron",
|
||
"cron_description": "定时同步数据到AI平台",
|
||
"method": "syncDataToAIPlatform",
|
||
"cron_frequency": "3600",
|
||
"cron_max_run_time": "600"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 主逻辑类(AiResearchAssistantModule.php)
|
||
|
||
```php
|
||
<?php
|
||
namespace YiZhengXun\AiResearchAssistant;
|
||
|
||
use ExternalModules\AbstractExternalModule;
|
||
use REDCap;
|
||
|
||
class AiResearchAssistantModule extends AbstractExternalModule {
|
||
|
||
// API客户端实例
|
||
private $apiClient;
|
||
|
||
/**
|
||
* 构造函数 - 初始化API客户端
|
||
*/
|
||
public function __construct() {
|
||
parent::__construct();
|
||
require_once __DIR__ . '/services/ApiClient.php';
|
||
$this->apiClient = new ApiClient(
|
||
$this->getSystemSetting('ai_platform_url'),
|
||
$this->getSystemSetting('ai_platform_api_key')
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Hook: 数据保存时触发
|
||
* 核心功能:实时推送数据到AI平台
|
||
*/
|
||
public function redcap_save_record(
|
||
$project_id,
|
||
$record,
|
||
$instrument,
|
||
$event_id,
|
||
$group_id,
|
||
$survey_hash,
|
||
$response_id,
|
||
$repeat_instance
|
||
) {
|
||
// 检查是否启用实时同步
|
||
$syncMode = $this->getProjectSetting('sync_mode');
|
||
if ($syncMode !== 'realtime') {
|
||
return;
|
||
}
|
||
|
||
// 防止无限循环
|
||
static $is_syncing = false;
|
||
if ($is_syncing) return;
|
||
$is_syncing = true;
|
||
|
||
try {
|
||
// 获取记录数据
|
||
$data = REDCap::getData($project_id, 'array', $record);
|
||
|
||
// 转换数据格式
|
||
require_once __DIR__ . '/services/DataMapper.php';
|
||
$mapper = new DataMapper();
|
||
$mappedData = $mapper->redcapToAIPlatform($data, $project_id, $record);
|
||
|
||
// 推送到AI平台
|
||
$result = $this->apiClient->post('/api/v1/redcap/records', $mappedData);
|
||
|
||
// 记录日志
|
||
$this->log("数据同步成功", [
|
||
'project_id' => $project_id,
|
||
'record' => $record,
|
||
'instrument' => $instrument,
|
||
'ai_platform_response' => $result
|
||
]);
|
||
|
||
// 如果启用了AI数据清洗,触发清洗任务
|
||
if ($this->getProjectSetting('enable_dc_module')) {
|
||
$this->triggerDataCleaning($project_id, $record);
|
||
}
|
||
|
||
} catch (\Exception $e) {
|
||
// 错误处理
|
||
$this->log("数据同步失败", [
|
||
'project_id' => $project_id,
|
||
'record' => $record,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
|
||
$is_syncing = false;
|
||
}
|
||
|
||
/**
|
||
* Hook: 每个页面顶部
|
||
* 功能:注入AI辅助录入的JavaScript
|
||
*/
|
||
public function redcap_every_page_top($project_id) {
|
||
// 仅在数据录入页面生效
|
||
if (strpos(PAGE, 'DataEntry/index.php') !== false) {
|
||
$this->injectAIAssistant();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Hook: 数据导出前
|
||
* 功能:可以添加AI分析结果字段到导出
|
||
*/
|
||
public function redcap_custom_verify_username($username) {
|
||
// 验证逻辑
|
||
}
|
||
|
||
/**
|
||
* Cron任务: 定时同步数据
|
||
*/
|
||
public function syncDataToAIPlatform($cron_info) {
|
||
$projects = $this->getEnabledProjects();
|
||
|
||
foreach ($projects as $project_id) {
|
||
try {
|
||
// 获取项目所有数据
|
||
$data = REDCap::getData($project_id, 'array');
|
||
|
||
// 批量推送
|
||
$result = $this->apiClient->post('/api/v1/redcap/batch-sync', [
|
||
'project_id' => $project_id,
|
||
'data' => $data,
|
||
'timestamp' => time()
|
||
]);
|
||
|
||
$this->log("定时同步完成", [
|
||
'project_id' => $project_id,
|
||
'records_count' => count($data)
|
||
]);
|
||
|
||
} catch (\Exception $e) {
|
||
$this->log("定时同步失败", [
|
||
'project_id' => $project_id,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
}
|
||
|
||
return "同步完成";
|
||
}
|
||
|
||
/**
|
||
* 触发AI数据清洗
|
||
*/
|
||
private function triggerDataCleaning($project_id, $record) {
|
||
$result = $this->apiClient->post('/api/v1/redcap/dc/clean', [
|
||
'project_id' => $project_id,
|
||
'record' => $record,
|
||
'auto_mode' => true
|
||
]);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 注入AI辅助录入JavaScript
|
||
*/
|
||
private function injectAIAssistant() {
|
||
?>
|
||
<script src="<?= $this->getUrl('js/ai_assistant.js') ?>"></script>
|
||
<script>
|
||
const aiConfig = {
|
||
apiUrl: '<?= $this->getSystemSetting('ai_platform_url') ?>',
|
||
projectId: <?= PROJECT_ID ?>,
|
||
enableAutoComplete: true,
|
||
enableSmartValidation: true
|
||
};
|
||
AiAssistant.init(aiConfig);
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* 获取启用模块的项目列表
|
||
*/
|
||
private function getEnabledProjects() {
|
||
$sql = "SELECT project_id FROM redcap_external_modules
|
||
WHERE external_module_id = ?
|
||
AND directory_prefix = ?";
|
||
$result = $this->query($sql, [
|
||
$this->getModuleId(),
|
||
$this->PREFIX
|
||
]);
|
||
|
||
$projects = [];
|
||
while ($row = $result->fetch_assoc()) {
|
||
$projects[] = $row['project_id'];
|
||
}
|
||
|
||
return $projects;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 方案2:AI平台Backend API开发
|
||
|
||
#### 新增REDCap专用模块
|
||
|
||
```typescript
|
||
// backend/src/modules/redcap/ 目录结构
|
||
backend/src/modules/redcap/
|
||
├── controllers/
|
||
│ ├── RedcapController.ts // 主控制器
|
||
│ ├── SyncController.ts // 数据同步控制器
|
||
│ └── WebhookController.ts // Webhook控制器
|
||
├── services/
|
||
│ ├── RedcapApiClient.ts // REDCap API客户端
|
||
│ ├── DataTransformService.ts // 数据转换服务
|
||
│ ├── SyncService.ts // 同步服务
|
||
│ └── ProjectMappingService.ts // 项目映射服务
|
||
├── models/
|
||
│ └── redcap.prisma // Prisma Schema
|
||
├── routes/
|
||
│ └── redcap.routes.ts // 路由定义
|
||
└── types/
|
||
└── redcap.types.ts // TypeScript类型定义
|
||
```
|
||
|
||
#### Prisma Schema设计
|
||
|
||
```prisma
|
||
// backend/prisma/schema.prisma
|
||
|
||
// REDCap Schema
|
||
datasource redcap_schema {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
schemas = ["redcap_schema"]
|
||
}
|
||
|
||
// REDCap项目映射表
|
||
model RedcapProject {
|
||
id String @id @default(cuid())
|
||
redcapProjectId Int @unique // REDCap项目ID
|
||
redcapUrl String // REDCap服务器地址
|
||
redcapApiToken String @db.VarChar(64) // API Token (加密存储)
|
||
|
||
// 映射关系
|
||
dcProjectId String? // 关联的DC项目ID
|
||
ssaProjectId String? // 关联的SSA项目ID
|
||
aslProjectId String? // 关联的ASL项目ID
|
||
|
||
// 同步配置
|
||
syncEnabled Boolean @default(true)
|
||
syncMode String @default("realtime") // realtime, scheduled, manual
|
||
lastSyncAt DateTime?
|
||
|
||
// 元数据
|
||
projectName String
|
||
projectDescription String? @db.Text
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
// 关联关系
|
||
syncRecords RedcapSyncRecord[]
|
||
fieldMappings RedcapFieldMapping[]
|
||
|
||
@@map("redcap_projects")
|
||
@@schema("redcap_schema")
|
||
}
|
||
|
||
// REDCap同步记录表
|
||
model RedcapSyncRecord {
|
||
id String @id @default(cuid())
|
||
projectId String
|
||
project RedcapProject @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||
|
||
recordId String // REDCap记录ID
|
||
eventId String? // REDCap事件ID
|
||
instrument String? // 表单名称
|
||
|
||
// 同步状态
|
||
status String // pending, syncing, success, failed
|
||
direction String // redcap_to_ai, ai_to_redcap
|
||
|
||
// 数据快照
|
||
redcapData Json // REDCap原始数据
|
||
aiPlatformData Json? // AI平台处理后数据
|
||
|
||
// 错误信息
|
||
errorMessage String? @db.Text
|
||
retryCount Int @default(0)
|
||
|
||
syncedAt DateTime @default(now())
|
||
|
||
@@map("redcap_sync_records")
|
||
@@schema("redcap_schema")
|
||
@@index([projectId, recordId])
|
||
@@index([status])
|
||
}
|
||
|
||
// REDCap字段映射表
|
||
model RedcapFieldMapping {
|
||
id String @id @default(cuid())
|
||
projectId String
|
||
project RedcapProject @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||
|
||
// REDCap字段信息
|
||
redcapFieldName String
|
||
redcapFieldLabel String?
|
||
redcapFieldType String // text, radio, checkbox, dropdown, etc.
|
||
|
||
// AI平台字段映射
|
||
aiPlatformField String? // 映射到AI平台的字段名
|
||
transformRule Json? // 转换规则(JSON)
|
||
|
||
// 映射配置
|
||
isRequired Boolean @default(false)
|
||
isIdentifier Boolean @default(false) // 是否为主键字段
|
||
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@map("redcap_field_mappings")
|
||
@@schema("redcap_schema")
|
||
@@unique([projectId, redcapFieldName])
|
||
}
|
||
```
|
||
|
||
#### REDCap API路由定义
|
||
|
||
```typescript
|
||
// backend/src/modules/redcap/routes/redcap.routes.ts
|
||
|
||
import { FastifyInstance } from 'fastify';
|
||
import { RedcapController } from '../controllers/RedcapController';
|
||
import { SyncController } from '../controllers/SyncController';
|
||
import { WebhookController } from '../controllers/WebhookController';
|
||
|
||
export async function redcapRoutes(fastify: FastifyInstance) {
|
||
const redcapController = new RedcapController();
|
||
const syncController = new SyncController();
|
||
const webhookController = new WebhookController();
|
||
|
||
// ========== 项目管理 ==========
|
||
|
||
// 创建REDCap项目映射
|
||
fastify.post('/api/v1/redcap/projects',
|
||
redcapController.createProject
|
||
);
|
||
|
||
// 获取项目列表
|
||
fastify.get('/api/v1/redcap/projects',
|
||
redcapController.listProjects
|
||
);
|
||
|
||
// 获取项目详情
|
||
fastify.get('/api/v1/redcap/projects/:id',
|
||
redcapController.getProject
|
||
);
|
||
|
||
// 更新项目配置
|
||
fastify.put('/api/v1/redcap/projects/:id',
|
||
redcapController.updateProject
|
||
);
|
||
|
||
// 删除项目映射
|
||
fastify.delete('/api/v1/redcap/projects/:id',
|
||
redcapController.deleteProject
|
||
);
|
||
|
||
// ========== 数据同步 ==========
|
||
|
||
// 手动触发同步(REDCap → AI平台)
|
||
fastify.post('/api/v1/redcap/sync/import/:projectId',
|
||
syncController.importFromRedcap
|
||
);
|
||
|
||
// 推送数据到REDCap(AI平台 → REDCap)
|
||
fastify.post('/api/v1/redcap/sync/export/:projectId',
|
||
syncController.exportToRedcap
|
||
);
|
||
|
||
// 查询同步状态
|
||
fastify.get('/api/v1/redcap/sync/status/:projectId',
|
||
syncController.getSyncStatus
|
||
);
|
||
|
||
// 查询同步历史
|
||
fastify.get('/api/v1/redcap/sync/history/:projectId',
|
||
syncController.getSyncHistory
|
||
);
|
||
|
||
// ========== Webhook接收 ==========
|
||
|
||
// REDCap External Module推送数据(实时同步)
|
||
fastify.post('/api/v1/redcap/webhook/records',
|
||
webhookController.receiveRecordUpdate
|
||
);
|
||
|
||
// 批量同步(定时任务)
|
||
fastify.post('/api/v1/redcap/webhook/batch-sync',
|
||
webhookController.receiveBatchSync
|
||
);
|
||
|
||
// ========== 字段映射管理 ==========
|
||
|
||
// 获取REDCap项目元数据(字段列表)
|
||
fastify.get('/api/v1/redcap/projects/:id/metadata',
|
||
redcapController.getProjectMetadata
|
||
);
|
||
|
||
// 创建/更新字段映射
|
||
fastify.post('/api/v1/redcap/projects/:id/field-mappings',
|
||
redcapController.upsertFieldMappings
|
||
);
|
||
|
||
// 获取字段映射
|
||
fastify.get('/api/v1/redcap/projects/:id/field-mappings',
|
||
redcapController.getFieldMappings
|
||
);
|
||
|
||
// ========== AI功能集成 ==========
|
||
|
||
// 触发数据清洗(DC模块)
|
||
fastify.post('/api/v1/redcap/dc/clean',
|
||
redcapController.triggerDataCleaning
|
||
);
|
||
|
||
// 触发统计分析(SSA模块)
|
||
fastify.post('/api/v1/redcap/ssa/analyze',
|
||
redcapController.triggerStatisticalAnalysis
|
||
);
|
||
|
||
// 获取AI分析结果
|
||
fastify.get('/api/v1/redcap/analysis/:recordId',
|
||
redcapController.getAnalysisResults
|
||
);
|
||
}
|
||
```
|
||
|
||
#### 核心Controller实现
|
||
|
||
```typescript
|
||
// backend/src/modules/redcap/controllers/SyncController.ts
|
||
|
||
import { FastifyRequest, FastifyReply } from 'fastify';
|
||
import { prisma } from '@/config/database';
|
||
import { logger } from '@/common/logging';
|
||
import { RedcapApiClient } from '../services/RedcapApiClient';
|
||
import { DataTransformService } from '../services/DataTransformService';
|
||
|
||
export class SyncController {
|
||
|
||
/**
|
||
* 从REDCap导入数据到AI平台
|
||
*/
|
||
async importFromRedcap(
|
||
req: FastifyRequest<{ Params: { projectId: string } }>,
|
||
res: FastifyReply
|
||
) {
|
||
const { projectId } = req.params;
|
||
|
||
try {
|
||
// 1. 获取项目配置
|
||
const project = await prisma.redcapProject.findUnique({
|
||
where: { id: projectId },
|
||
include: { fieldMappings: true }
|
||
});
|
||
|
||
if (!project) {
|
||
return res.status(404).send({
|
||
success: false,
|
||
error: '项目不存在'
|
||
});
|
||
}
|
||
|
||
// 2. 调用REDCap API获取数据
|
||
const redcapClient = new RedcapApiClient(
|
||
project.redcapUrl,
|
||
project.redcapApiToken
|
||
);
|
||
|
||
const redcapData = await redcapClient.exportRecords({
|
||
format: 'json',
|
||
type: 'flat'
|
||
});
|
||
|
||
logger.info('从REDCap获取数据成功', {
|
||
projectId,
|
||
recordCount: redcapData.length
|
||
});
|
||
|
||
// 3. 数据转换
|
||
const transformer = new DataTransformService();
|
||
const transformedData = await transformer.redcapToAIPlatform(
|
||
redcapData,
|
||
project.fieldMappings
|
||
);
|
||
|
||
// 4. 存储到AI平台数据库
|
||
// 根据项目配置,推送到DC/SSA/ASL等模块
|
||
if (project.dcProjectId) {
|
||
await this.importToDCModule(project.dcProjectId, transformedData);
|
||
}
|
||
|
||
if (project.ssaProjectId) {
|
||
await this.importToSSAModule(project.ssaProjectId, transformedData);
|
||
}
|
||
|
||
// 5. 记录同步历史
|
||
await prisma.redcapSyncRecord.create({
|
||
data: {
|
||
projectId,
|
||
recordId: 'batch_import',
|
||
status: 'success',
|
||
direction: 'redcap_to_ai',
|
||
redcapData: redcapData as any,
|
||
aiPlatformData: transformedData as any
|
||
}
|
||
});
|
||
|
||
// 6. 更新同步时间
|
||
await prisma.redcapProject.update({
|
||
where: { id: projectId },
|
||
data: { lastSyncAt: new Date() }
|
||
});
|
||
|
||
return res.send({
|
||
success: true,
|
||
message: '数据导入成功',
|
||
data: {
|
||
recordCount: redcapData.length,
|
||
transformedCount: transformedData.length
|
||
}
|
||
});
|
||
|
||
} catch (error) {
|
||
logger.error('REDCap数据导入失败', {
|
||
projectId,
|
||
error: error.message
|
||
});
|
||
|
||
return res.status(500).send({
|
||
success: false,
|
||
error: '数据导入失败',
|
||
details: error.message
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 导入到DC模块
|
||
*/
|
||
private async importToDCModule(dcProjectId: string, data: any[]) {
|
||
// 调用DC模块的导入API
|
||
// TODO: 实现DC模块集成逻辑
|
||
}
|
||
|
||
/**
|
||
* 导入到SSA模块
|
||
*/
|
||
private async importToSSAModule(ssaProjectId: string, data: any[]) {
|
||
// 调用SSA模块的导入API
|
||
// TODO: 实现SSA模块集成逻辑
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 数据流设计
|
||
|
||
### 数据流1:REDCap → AI平台(实时同步)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 1: 用户在REDCap录入数据 │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ 研究人员在REDCap表单中录入患者数据 │
|
||
│ 例如:患者ID、年龄、性别、诊断、检验结果等 │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 2: REDCap触发redcap_save_record Hook │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ External Module捕获保存事件 │
|
||
│ 获取:project_id, record, instrument, event_id │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 3: 数据获取与映射 │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ 1. 调用REDCap::getData()获取完整记录 │
|
||
│ 2. DataMapper转换REDCap EAV格式→AI平台标准格式 │
|
||
│ 3. 应用字段映射规则(redcap_field_mappings表) │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 4: HTTP POST推送到AI平台API │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ URL: https://ai.yizx.com/api/v1/redcap/webhook/records │
|
||
│ Payload: { │
|
||
│ project_id: 123, │
|
||
│ record_id: "PAT001", │
|
||
│ data: {...}, │
|
||
│ timestamp: 1735542000 │
|
||
│ } │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 5: AI平台接收并处理 │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ 1. WebhookController验证请求签名 │
|
||
│ 2. 存储原始数据到redcap_sync_records表 │
|
||
│ 3. 异步触发AI处理任务(DC/SSA模块) │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Step 6: AI处理与结果返回 │
|
||
│ ───────────────────────────────────────────────────── │
|
||
│ 1. DC模块:数据清洗、NER提取、缺失值处理 │
|
||
│ 2. SSA模块:自动统计分析、生成可视化图表 │
|
||
│ 3. 结果存储到AI平台数据库 │
|
||
│ 4. (可选)回写结果到REDCap(通过API) │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 数据流2:AI平台 → REDCap(分析结果回写)
|
||
|
||
```
|
||
AI平台完成分析
|
||
↓
|
||
生成分析结果(JSON)
|
||
↓
|
||
调用REDCap API: importRecords
|
||
↓
|
||
REDCap存储结果到特定字段
|
||
↓
|
||
研究人员在REDCap中查看AI分析结果
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 开发计划与实施步骤
|
||
|
||
### Phase 1: 基础对接(Week 1-2)✅ 优先级P0
|
||
|
||
**目标**:建立REDCap与AI平台的基本连接
|
||
|
||
#### Week 1: External Module骨架
|
||
|
||
**任务清单**:
|
||
- [ ] 创建External Module目录结构
|
||
- [ ] 编写config.json配置文件
|
||
- [ ] 实现AiResearchAssistantModule.php基础类
|
||
- [ ] 实现redcap_save_record Hook(基础版)
|
||
- [ ] 开发ApiClient.php(HTTP客户端)
|
||
- [ ] 测试:REDCap保存数据→打印日志
|
||
|
||
**交付物**:
|
||
- `ai_research_assistant_v1.0.0/` 完整目录
|
||
- 可在REDCap中启用的External Module
|
||
- 基础日志记录功能
|
||
|
||
#### Week 2: AI平台API端点
|
||
|
||
**任务清单**:
|
||
- [ ] 创建redcap_schema数据库Schema
|
||
- [ ] 实现Prisma模型(RedcapProject等3个表)
|
||
- [ ] 开发WebhookController接收数据
|
||
- [ ] 实现数据转换服务DataTransformService
|
||
- [ ] 开发项目管理API(CRUD)
|
||
- [ ] 测试:REDCap推送→AI平台接收→存储
|
||
|
||
**交付物**:
|
||
- `/api/v1/redcap/*` API端点
|
||
- PostgreSQL redcap_schema创建
|
||
- Postman测试集合
|
||
|
||
---
|
||
|
||
### Phase 2: 数据同步与映射(Week 3-4)⭐ 优先级P1
|
||
|
||
**目标**:实现双向数据同步和字段智能映射
|
||
|
||
#### Week 3: 字段映射系统
|
||
|
||
**任务清单**:
|
||
- [ ] 开发字段映射管理UI(前端React)
|
||
- [ ] 实现REDCap元数据获取API
|
||
- [ ] 开发字段映射配置界面
|
||
- [ ] 实现映射规则引擎(DataMapper)
|
||
- [ ] 支持复杂转换(如:单位转换、编码映射)
|
||
- [ ] 测试:映射配置→数据转换验证
|
||
|
||
**交付物**:
|
||
- 字段映射UI页面
|
||
- 映射规则引擎
|
||
- 配置文档
|
||
|
||
#### Week 4: 双向同步
|
||
|
||
**任务清单**:
|
||
- [ ] 实现批量数据导入(REDCap → AI)
|
||
- [ ] 实现分析结果回写(AI → REDCap)
|
||
- [ ] 开发Cron定时同步任务
|
||
- [ ] 实现同步状态监控界面
|
||
- [ ] 错误处理与重试机制
|
||
- [ ] 测试:完整同步流程
|
||
|
||
**交付物**:
|
||
- 双向同步功能
|
||
- 同步监控Dashboard
|
||
- 错误处理机制
|
||
|
||
---
|
||
|
||
### Phase 3: AI功能集成(Week 5-6)🎁 优先级P1
|
||
|
||
**目标**:集成DC、SSA、AIA等AI模块
|
||
|
||
#### Week 5: DC模块集成
|
||
|
||
**任务清单**:
|
||
- [ ] REDCap数据→DC模块自动清洗
|
||
- [ ] 清洗结果→REDCap回写
|
||
- [ ] 在REDCap中展示清洗报告
|
||
- [ ] 支持手动触发清洗
|
||
- [ ] 测试:录入→清洗→查看结果
|
||
|
||
**交付物**:
|
||
- DC集成API
|
||
- REDCap清洗报告页面
|
||
|
||
#### Week 6: SSA模块集成
|
||
|
||
**任务清单**:
|
||
- [ ] REDCap数据→SSA模块自动分析
|
||
- [ ] 支持三大分析路径(队列/预测/RCT)
|
||
- [ ] 在REDCap中嵌入统计报告
|
||
- [ ] 可视化图表展示
|
||
- [ ] 测试:数据录入→自动分析→报告生成
|
||
|
||
**交付物**:
|
||
- SSA集成API
|
||
- 统计报告嵌入页面
|
||
|
||
---
|
||
|
||
### Phase 4: 高级功能(Week 7-8)🌟 优先级P2
|
||
|
||
**目标**:AI辅助录入、智能质控等增值功能
|
||
|
||
#### Week 7: AI辅助录入
|
||
|
||
**任务清单**:
|
||
- [ ] 开发智能自动完成(基于历史数据)
|
||
- [ ] 异常值预警(实时AI判断)
|
||
- [ ] 字段关联推荐(AI预测)
|
||
- [ ] 录入效率提升统计
|
||
- [ ] 测试:录入体验优化验证
|
||
|
||
**交付物**:
|
||
- AI辅助录入JS插件
|
||
- 智能质控规则引擎
|
||
|
||
#### Week 8: 综合测试与优化
|
||
|
||
**任务清单**:
|
||
- [ ] 性能测试(100万条记录同步)
|
||
- [ ] 安全测试(API认证、数据加密)
|
||
- [ ] 用户验收测试(UAT)
|
||
- [ ] 文档编写(用户手册+开发文档)
|
||
- [ ] 部署到生产环境
|
||
|
||
**交付物**:
|
||
- 性能测试报告
|
||
- 完整文档
|
||
- 生产环境部署
|
||
|
||
---
|
||
|
||
## 🔒 安全性设计
|
||
|
||
### API认证机制
|
||
|
||
```typescript
|
||
// 使用HMAC-SHA256签名验证
|
||
|
||
// REDCap External Module发送请求时
|
||
const timestamp = Date.now();
|
||
const signature = crypto
|
||
.createHmac('sha256', apiSecret)
|
||
.update(`${timestamp}${JSON.stringify(payload)}`)
|
||
.digest('hex');
|
||
|
||
// Headers:
|
||
{
|
||
'X-API-Key': apiKey,
|
||
'X-Timestamp': timestamp,
|
||
'X-Signature': signature
|
||
}
|
||
|
||
// AI平台验证
|
||
function verifySignature(req) {
|
||
const { timestamp, signature } = req.headers;
|
||
const expectedSignature = crypto
|
||
.createHmac('sha256', apiSecret)
|
||
.update(`${timestamp}${JSON.stringify(req.body)}`)
|
||
.digest('hex');
|
||
|
||
return signature === expectedSignature;
|
||
}
|
||
```
|
||
|
||
### 数据加密
|
||
|
||
- REDCap API Token:使用AES-256加密存储
|
||
- 传输加密:强制HTTPS
|
||
- 敏感字段:支持字段级加密(PHI数据)
|
||
|
||
### 权限控制
|
||
|
||
```typescript
|
||
// REDCap用户权限同步到AI平台
|
||
interface UserPermission {
|
||
userId: string;
|
||
redcapRights: {
|
||
data_entry: boolean;
|
||
data_export: boolean;
|
||
data_analysis: boolean;
|
||
};
|
||
aiPlatformRights: {
|
||
dc_access: boolean;
|
||
ssa_access: boolean;
|
||
asl_access: boolean;
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📚 技术栈总结
|
||
|
||
| 层级 | REDCap侧 | AI平台侧 |
|
||
|------|---------|---------|
|
||
| **编程语言** | PHP 7.4+ | TypeScript/Node.js 22 |
|
||
| **框架** | REDCap EM Framework v16 | Fastify v4 |
|
||
| **数据库** | MySQL 5.7+ | PostgreSQL 15 |
|
||
| **数据模型** | EAV模型 | 关系型+JSONB |
|
||
| **前端** | jQuery + Bootstrap 5 | React 19 + Ant Design 6 |
|
||
| **API** | REDCap RESTful API | Fastify RESTful API |
|
||
| **认证** | API Token | HMAC-SHA256签名 |
|
||
| **日志** | REDCap日志表 | Winston + SLS |
|
||
| **任务队列** | REDCap Cron | pg-boss (Postgres-Only) |
|
||
|
||
---
|
||
|
||
## 📝 下一步行动
|
||
|
||
### 立即行动(本周)
|
||
|
||
1. **确认需求**:
|
||
- [ ] 确认优先级(DC优先?还是SSA优先?)
|
||
- [ ] 确认部署形态(云端SaaS?还是私有化部署?)
|
||
- [ ] 确认REDCap服务器信息(URL、版本、访问权限)
|
||
|
||
2. **环境准备**:
|
||
- [ ] 搭建REDCap测试环境(使用Docker)
|
||
- [ ] 创建测试项目和测试数据
|
||
- [ ] 配置AI平台测试API
|
||
|
||
3. **启动开发**:
|
||
- [ ] 创建External Module目录
|
||
- [ ] 初始化Git仓库
|
||
- [ ] 编写config.json
|
||
|
||
### 技术预研
|
||
|
||
1. **REDCap API深入测试**
|
||
2. **External Module Hook机制验证**
|
||
3. **大数据量同步性能测试**
|
||
4. **移动端(REDCap Mobile App)集成可行性**
|
||
|
||
---
|
||
|
||
## 🎯 成功标准
|
||
|
||
**MVP版本(Phase 1-2完成)**:
|
||
- ✅ REDCap数据能推送到AI平台
|
||
- ✅ AI平台能接收并存储数据
|
||
- ✅ 字段映射配置功能可用
|
||
- ✅ 基础同步监控可用
|
||
|
||
**标准版本(Phase 3完成)**:
|
||
- ✅ DC模块集成完成(自动清洗)
|
||
- ✅ SSA模块集成完成(自动分析)
|
||
- ✅ 分析结果可在REDCap中查看
|
||
- ✅ 用户体验流畅
|
||
|
||
**企业版本(Phase 4完成)**:
|
||
- ✅ AI辅助录入提升效率50%+
|
||
- ✅ 智能质控减少错误率80%+
|
||
- ✅ 支持100万+记录同步
|
||
- ✅ 安全合规(符合FDA 21 CFR Part 11)
|
||
|
||
---
|
||
|
||
**文档版本**:v1.0
|
||
**最后更新**:2025-12-30
|
||
**下次更新**:Phase 1启动后更新开发进度
|
||
|
||
---
|
||
|
||
**🚀 准备好开始了吗?让我们开启REDCap与AI的融合之旅!**
|
||
|
||
|
||
|
||
|
||
|