Major Changes: - Add StreamingService with OpenAI Compatible format - Upgrade Chat component V2 with Ant Design X integration - Implement AIA module with 12 intelligent agents - Update API routes to unified /api/v1 prefix - Update system documentation Backend (~1300 lines): - common/streaming: OpenAI Compatible adapter - modules/aia: 12 agents, conversation service, streaming integration - Update route versions (RVW, PKB to v1) Frontend (~3500 lines): - modules/aia: AgentHub + ChatWorkspace (100% prototype restoration) - shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook - Update API endpoints to v1 Documentation: - AIA module status guide - Universal capabilities catalog - System overview updates - All module documentation sync Tested: Stream response verified, authentication working Status: AIA V2.0 core completed (85%)
39 KiB
REDCap荳拶Iclinicalresearch蟷ウ蜿ー蟇ケ謗・諤サ菴捺婿譯<EFBFBD>
*譁<EFBFBD>。」迚域悽<EFBFBD>? v1.0
*蛻帛サコ譌・譛滂シ? 2025-12-30
譛蜷取峩譁ー<EFBFBD><EFBFBD> 2025-12-30
譁<EFBFBD>。」迥カ諤<EFBFBD>シ<EFBFBD> 隗<><E99A97>荳? 菴懆<EFBFBD>シ<EFBFBD> 謚譛ッ譫カ譫<EFBDB6>ク<EFBFBD>
<EFBFBD>搭 譁<>。」隸エ譏<EFBDB4>
譛ャ譁<EFBFBD>。」螳壻ケ嘘EDCap<EFBFBD>?5.8.0<EFBFBD>我ク主」ケ隸∝セェAI遘醍<EFBFBD>泌ケウ蜿ー逧?*螳梧紛蟇ケ謗・譁ケ譯<EFBDB9>**<2A>悟桁諡ャ<E8ABA1><EFBDAC>
- 蟇ケ謗・譫カ譫<EFBFBD>ョセ隶。
- External Module蠑蜿第婿譯?
- API髮<EFBFBD><EFBFBD>譁ケ譯<EFBFBD>
- 謨ー謐ョ豬∬ョセ隶?
- 蠑蜿題ョ。蛻剃ク主ョ樊命豁・鬪、
*蜑咲スョ譚。莉カ<EFBFBD>?
- 笨?蟾イ闔キ蠕由EDCap螳俶婿謗域揀
- 笨?諡・譛嘘EDCap 15.8.0貅蝉サ」遐?
- 笨?諡・譛右xternal Module Framework譁<6B>。」
*逶ク蜈ウ譁<EFBFBD>。」<EFBFBD>?
<EFBFBD>識 蟇ケ謗・逶ョ譬<EFBDAE>ク惹サキ蛟?
譬ク蠢<EFBFBD>岼譬<EFBFBD>
*蟆<EFBFBD>EDCap逧<EFBFBD>シコ螟ァEDC閭ス蜉帑ク拶I遘醍<EFBFBD>泌ケウ蜿ー逧БI蠅槫シ蜉溯<EFBFBD>豺ア蠎ヲ陞榊<EFBFBD>?
REDCap (謨ー謐ョ驥<EFBDAE>寔) + AIclinicalresearch (AI閭ス蜉<EFBDBD>)
竊? 竊?
荳エ蠎頑焚謐ョ蠖募<E8A096> AI譎コ閭ス螟<EFBDBD>炊縲∝<E7B8B2>譫舌∵エ槫ッ?
竊? 竊?
螳梧紛逧БI鬩ア蜉ィ荳エ蠎顔<E8A08E>皮ゥカ髣ュ邇ッ
荳壼苅莉キ蛟?
| 蜉溯<EFBFBD>讓。蝮<EFBFBD> | REDCap蝓コ遑閭ス蜉<EFBFBD> | AI蟷ウ蜿ー蠅槫シ閭ス蜉? | 蜊丞酔莉キ蛟? |
|---|---|---|---|
| 謨ー謐ョ驥<EFBFBD>寔 | 笨?陦ィ蜊戊ョセ隶。縲∵焚謐ョ蠖募<E8A096>縲<EFBFBD>ェ瑚ッ? | <EFBFBD>氏 AI霎<49>勧蠖募<E8A096>縲∵匱閭ス雍ィ謗? | 謠仙合蠖募<EFBFBD>謨育紫50% |
| 謨ー謐ョ貂<EFBFBD>エ<EFBFBD> | 笞<EFBFBD><EFBFBD><EFBFBD> 謇句勘譟・隸「縲∝ッシ蜃コExcel | <EFBFBD>氏 DC讓。蝮苓<E89DAE>蜉ィ貂<EFBDA8>エ励¨ER謠仙叙 | 蜃丞ー第焚謐ョ螟<EFBFBD>炊譌カ髣エ80% |
| 扈溯ョ。蛻<EFBFBD>梵 | 笞<EFBFBD><EFBFBD><EFBFBD> 髴蟇シ蜃コ蛻ーR/SPSS | <EFBFBD>氏 SSA讓。蝮嶺ク髞ョ蛻<EFBDAE>梵縲∝庄隗<E5BA84>喧 | 髯堺ス守サ溯ョ。髣ィ讒幢シ悟<EFBFBD>譫宣溷コヲ謠仙合10蛟? |
| 譁<EFBFBD>鍵謾ッ謖<EFBFBD> | 笶?譌? | <EFBFBD>氏 ASL讓。蝮玲匱閭ス譁<EFBDBD>鍵遲幃? | 邉サ扈溯ッ<EFBFBD>サキ謨育紫謠仙合5蛟? |
| AI髣ョ遲<EFBFBD> | 笶?譌? | <EFBFBD>氏 AIA讓。蝮<EFBDA1>10+譎コ閭ス菴楢セ<E6A5A2><EFBDBE>? | 蜈ィ豬∫ィ帰I霎<EFBFBD>勧 |
| *遏・隸<EFBFBD>コ? | 笶?譌? | <EFBFBD>氏 PKB讓。蝮由AG髣ョ遲<EFBDAE> | 鬘ケ逶ョ遏・隸<EFBFBD>イ画キ |
<EFBFBD>女<EFBFBD>?蟇ケ謗・譫カ譫<EFBDB6>ョセ隶。
謨エ菴捺楔譫<EFBFBD>
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 逕ィ謌キ螻ゑシ育<EFBDBC>皮ゥカ莠コ蜻<EFBDBA>/蛹サ逕滂シ? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 蜑咲ォッ螻慕、コ螻? 笏?
笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏? 笏? REDCap Web UI 笏? 笏?AIclinicalresearch 笏? 笏?
笏? 笏? (蜴溽函逡碁擇) 笏や淀笏笏笏笏笏笏笏笏笏笏笏笏笆コ笏<EFBDBA> Frontend (React) 笏? 笏?
笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 髮<><E9ABAE>螻ゑシ域<EFBDBC>ク蠢<EFBDB8>シ? 笏?
笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏? 笏? REDCap External Module: "AI Research Assistant" 笏? 笏?
笏? 笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏? 笏?
笏? 笏? 笏懌楳笏 謨ー謐ョ蜷梧ュ・譛榊苅 (Data Sync Service) 笏? 笏?
笏? 笏? 笏懌楳笏 AI蜉溯<E89C89>闖懷黒 (AI Menu Links) 笏? 笏?
笏? 笏? 笏懌楳笏 Hooks螟<73>炊蝎?(Hook Handlers) 笏? 笏?
笏? 笏? 笏披楳笏 API莉」逅<EFBDA3>ア?(API Proxy) 笏? 笏?
笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏? 竊? 笏?
笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏? 笏? AIclinicalresearch Backend RESTful API 笏? 笏?
笏? 笏? /api/v1/redcap/* 笏? 笏?
笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 荳壼苅螟<E88B85>炊螻ゑシ<E38291>I閭ス蜉幢シ? 笏?
笏? 笏娯楳笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏? 笏?
笏? 笏?DC 笏? 笏?SSA 笏? 笏?ASL 笏? 笏?AIA 笏? 笏?PKB 笏? ... 笏?
笏? 笏よ焚謐? 笏? 笏らサ溯ョ? 笏? 笏よ枚迪? 笏? 笏る琉遲? 笏? 笏ら衍隸<E8A18D>コ凪<EFBDBA>? 笏?
笏? 笏よク<E38288>エ? 笏? 笏ょ<E7AC8F>譫? 笏? 笏らュ幃? 笏? 笏? 笏? 笏? 笏? 笏?
笏? 笏披楳笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 謨ー謐ョ蟄伜お螻? 笏?
笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏? 笏? REDCap MySQL 笏? 笏? AI Platform 笏? 笏?
笏? 笏? (荳エ蠎頑焚謐ョ) 笏や淀笏笏笏笏笏笏笏笆コ笏<EFBDBA> PostgreSQL 笏? 笏?
笏? 笏? - 謔」閠<EFBDA3>焚謐? 笏? 蜷梧ュ・ 笏? (蛻<>梵扈捺棡) 笏? 笏?
笏? 笏? - 陦ィ蜊募<E89C8A>謨ー謐? 笏? 笏? - 貂<>エ怜錘謨ー謐? 笏? 笏?
笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
譬ク蠢<EFBFBD>ッケ謗・讓。蠑<EFBFBD>
謌台サャ驥<EFBFBD>畑**蜿悟髄蟇ケ謗・**遲也払<E4B99F>?
讓。蠑就<EFBFBD>啌EDCap 竊?AI蟷ウ蜿ー<E89CBF>域焚謐ョ謗ィ騾<EFBDA8>シ<EFBFBD>
逕ィ謌キ蝨ィREDCap蠖募<EFBFBD>謨ー謐ョ
竊?
redcap_save_record Hook隗ヲ蜿<EFBDA6>
竊?
External Module謗ィ騾∵焚謐ョ蛻ーAI蟷ウ蜿ーAPI
竊?
AI蟷ウ蜿ー螟<EFBDB0>炊<EFBFBD>域ク<E59F9F>エ?蛻<>梵/AI螟<49>炊<EFBFBD>?
竊?
扈捺棡霑泌屓REDCap蟄伜お
讓。蠑州<EFBFBD>哂I蟷ウ蜿ー 竊?REDCap<61>域焚謐ョ諡牙叙<E78999><E58F99>
逕ィ謌キ蝨ィAI蟷ウ蜿ー蜿題オキ蛻<EFBFBD>梵
竊?
AI蟷ウ蜿ー隹<EFBDB0>畑REDCap API闔キ蜿匁焚謐ョ
竊?
AI蟷ウ蜿ー謇ァ陦悟<E999A6>譫撰シ<E692B0>C/SSA/AIA遲会シ<E4BC9A>
竊?
扈捺棡螻慕、コ蝨ィAI蟷ウ蜿ー蜑咲ォッ
竊?
<0A>亥庄騾会シ臥サ捺棡蝗槫<E89D97>REDCap
<EFBFBD>肌 謚譛ッ譁ケ譯郁ッヲ隗?
譁ケ譯<EFBFBD>1<EFBFBD>啌EDCap External Module蠑蜿?
讓。蝮怜多蜷堺ク守サ捺<EFBFBD>?
讓。蝮怜錐遘ー: ai_research_assistant
迚域悽: v1.0.0
螳梧紛逶ョ蠖<EFBDAE>: <redcap-root>/modules/ai_research_assistant_v1.0.0/
逶ョ蠖慕サ捺桷:
ai_research_assistant_v1.0.0/
笏懌楳笏 config.json # 讓。蝮鈴<E89DAE>鄂ョ
笏懌楳笏 AiResearchAssistantModule.php # 荳サ騾サ霎醍ア?
笏懌楳笏 README.md # 隸エ譏取枚譯」
笏懌楳笏 LICENSE # MIT隶ク蜿ッ
笏懌楳笏 pages/ # 閾ェ螳壻ケ蛾。オ髱?
笏? 笏懌楳笏 dashboard.php # AI蜉溯<E89C89>莉ェ陦ィ逶?
笏? 笏懌楳笏 data_sync.php # 謨ー謐ョ蜷梧ュ・邂。逅<EFBDA1>
笏? 笏懌楳笏 analysis_center.php # 蛻<>梵荳ュ蠢<EFBDAD>
笏? 笏披楳笏 settings.php # 讓。蝮苓ョセ鄂ョ
笏懌楳笏 js/ # JavaScript譁<74>サカ
笏? 笏懌楳笏 dashboard.js
笏? 笏披楳笏 data_sync.js
笏懌楳笏 css/ # 譬キ蠑乗枚莉カ
笏? 笏披楳笏 style.css
笏披楳笏 services/ # 譛榊苅邀?
笏懌楳笏 ApiClient.php # AI蟷ウ蜿ーAPI螳「謌キ遶?
笏懌楳笏 DataMapper.php # 謨ー謐ョ譏<EFBDAE>蟆<EFBFBD>スャ謐「
笏披楳笏 SyncService.php # 蜷梧ュ・譛榊苅
config.json譬ク蠢<EFBDB8><E8A0A2>鄂ョ
{
"name": "AI Research Assistant",
"description": "螢ケ隸∝セェAI遘醍<E98198>泌ケウ蜿ー髮<EFBDB0><E9ABAE>讓。蝮<EFBDA1> - 謠蝉セ帶焚謐ョ譎コ閭ス貂<EFBDBD>エ励∫サ溯ョ。蛻<EFBDA1>梵縲∵枚迪ョ謾ッ謖∫ュ陰I蠅槫シ蜉溯<E89C89>?,
"authors": [
{
"name": "螢ケ隸∝セェ遘第橿",
"email": "support@yizx.ai",
"institution": "螢ケ隸∝セェ遘第橿"
}
],
"framework-version": 16,
"permissions": [],
"links": {
"project": [
{
"name": "<EFBFBD>、<EFBFBD> AI蜉溯<EFBFBD>荳ュ蠢<EFBFBD>",
"icon": "fas fa-brain",
"url": "pages/dashboard.php",
"show-header-and-footer": true
},
{
"name": "<EFBFBD>売 謨ー謐ョ蜷梧ュ・",
"icon": "fas fa-sync-alt",
"url": "pages/data_sync.php",
"show-header-and-footer": true
},
{
"name": "<EFBFBD>投 AI蛻<EFBFBD>梵荳ュ蠢<EFBFBD>",
"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蟇<49>徴",
"type": "password",
"required": true
},
{
"key": "enable_auto_sync",
"name": "蜷ッ逕ィ閾ェ蜉ィ蜷梧ュ・",
"type": "checkbox",
"default": true
}
],
"project-settings": [
{
"key": "sync_mode",
"name": "蜷梧ュ・讓。蠑<EFBDA1>",
"type": "dropdown",
"choices": [
{"value": "manual", "name": "謇句勘蜷梧ュ・"},
{"value": "realtime", "name": "螳樊慮蜷梧ュ・"},
{"value": "scheduled", "name": "螳壽慮蜷梧ュ・"}
],
"default": "realtime"
},
{
"key": "enable_dc_module",
"name": "蜷ッ逕ィ謨ー謐ョ貂<EFBDAE>エ玲ィ。蝮<EFBDA1>",
"type": "checkbox",
"default": true
},
{
"key": "enable_ssa_module",
"name": "蜷ッ逕ィ扈溯ョ。蛻<EFBDA1>梵讓。蝮<EFBDA1>",
"type": "checkbox",
"default": true
},
{
"key": "enable_asl_module",
"name": "蜷ッ逕ィ譎コ閭ス譁<EFBDBD>鍵讓。蝮<EFBDA1>",
"type": "checkbox",
"default": false
}
],
"crons": [
{
"cron_name": "data_sync_cron",
"cron_description": "螳壽慮蜷梧ュ・謨ー謐ョ蛻ーAI蟷ウ蜿ー",
"method": "syncDataToAIPlatform",
"cron_frequency": "3600",
"cron_max_run_time": "600"
}
]
}
荳サ騾サ霎醍アサ<EFBFBD><EFBFBD>iResearchAssistantModule.php<68>?
<?php
namespace YiZhengXun\AiResearchAssistant;
use ExternalModules\AbstractExternalModule;
use REDCap;
class AiResearchAssistantModule extends AbstractExternalModule {
// API螳「謌キ遶ッ螳樔セ?
private $apiClient;
/**
* 譫<><EFBFBD>蜃ス謨?- 蛻晏ァ句喧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: 謨ー謐ョ菫晏ュ俶慮隗ヲ蜿?
* 譬ク蠢<EFBDB8>粥閭ス<E996AD>壼ョ樊慮謗ィ騾∵焚謐ョ蛻ー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;
}
// 髦イ豁「譌<EFBDA2>髯仙セェ邇ッ
static $is_syncing = false;
if ($is_syncing) return;
$is_syncing = true;
try {
// 闔キ蜿冶ョー蠖墓焚謐ョ
$data = REDCap::getData($project_id, 'array', $record);
// 霓ャ謐「謨ー謐ョ譬シ蠑<EFBDBC>
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);
// 隶ー蠖墓律蠢<E5BE8B>
$this->log("謨ー謐ョ蜷梧ュ・謌仙粥", [
'project_id' => $project_id,
'record' => $record,
'instrument' => $instrument,
'ai_platform_response' => $result
]);
// 螯よ棡蜷ッ逕ィ莠<EFBDA8>I謨ー謐ョ貂<EFBDAE>エ暦シ瑚ァヲ蜿第ク<E7ACAC>エ嶺ササ蜉?
if ($this->getProjectSetting('enable_dc_module')) {
$this->triggerDataCleaning($project_id, $record);
}
} catch (\Exception $e) {
// 髞呵ッッ螟<EFBDAF>炊
$this->log("謨ー謐ョ蜷梧ュ・螟ア雍・", [
'project_id' => $project_id,
'record' => $record,
'error' => $e->getMessage()
]);
}
$is_syncing = false;
}
/**
* Hook: 豈丈クェ鬘オ髱「鬘カ驛ィ
* 蜉溯<E89C89><E6BAAF>壽ウィ蜈・AI霎<49>勧蠖募<E8A096>逧ЙavaScript
*/
public function redcap_every_page_top($project_id) {
// 莉<>惠謨ー謐ョ蠖募<E8A096>鬘オ髱「逕滓譜
if (strpos(PAGE, 'DataEntry/index.php') !== false) {
$this->injectAIAssistant();
}
}
/**
* Hook: 謨ー謐ョ蟇シ蜃コ蜑?
* 蜉溯<E89C89><E6BAAF>壼庄莉・豺サ蜉<EFBDBB>AI蛻<49>梵扈捺棡蟄玲ョオ蛻ー蟇シ蜃?
*/
public function redcap_custom_verify_username($username) {
// 鬪瑚ッ<E7919A>サ霎<EFBDBB>
}
/**
* 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("螳壽慮蜷梧ュ・螳梧<E89EB3>", [
'project_id' => $project_id,
'records_count' => count($data)
]);
} catch (\Exception $e) {
$this->log("螳壽慮蜷梧ュ・螟ア雍・", [
'project_id' => $project_id,
'error' => $e->getMessage()
]);
}
}
return "蜷梧ュ・螳梧<E89EB3>";
}
/**
* 隗ヲ蜿羨I謨ー謐ョ貂<EFBDAE>エ<EFBFBD>
*/
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霎<49>勧蠖募<E8A096>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;
}
}
譁ケ譯<EFBFBD>2<EFBFBD>哂I蟷ウ蜿ーBackend API蠑蜿?
譁ー蠅朿EDCap荳鍋畑讓。蝮<EFBFBD>
// 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 // 鬘ケ逶ョ譏<EFBDAE>蟆<EFBFBD>恪蜉。
笏懌楳笏 models/
笏? 笏披楳笏 redcap.prisma // Prisma Schema
笏懌楳笏 routes/
笏? 笏披楳笏 redcap.routes.ts // 霍ッ逕ア螳壻ケ<E5A3BB>
笏披楳笏 types/
笏披楳笏 redcap.types.ts // TypeScript邀サ蝙句ョ壻ケ<E5A3BB>
Prisma Schema隶セ隶。
// backend/prisma/schema.prisma
// REDCap Schema
datasource redcap_schema {
provider = "postgresql"
url = env("DATABASE_URL")
schemas = ["redcap_schema"]
}
// REDCap鬘ケ逶ョ譏<EFBDAE>蟆<EFBFBD>。?
model RedcapProject {
id String @id @default(cuid())
redcapProjectId Int @unique // REDCap鬘ケ逶ョID
redcapUrl String // REDCap譛榊苅蝎ィ蝨ー蝮
redcapApiToken String @db.VarChar(64) // API Token (蜉<>蟇<EFBFBD>ュ伜お)
// 譏<>蟆<EFBFBD><E89F86>邉サ
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
// 蜈ウ閨泌<E996A8>邉サ
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隶ー蠖肘D
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蟷ウ蜿ー螟<EFBDB0>炊蜷取焚謐?
// 髞呵ッッ菫。諱ッ
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蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>。?
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蟷ウ蜿ー蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>
aiPlatformField String? // 譏<>蟆<EFBFBD>芦AI蟷ウ蜿ー逧<EFBDB0>ュ玲ョオ蜷<EFBDB5>
transformRule Json? // 霓ャ謐「隗<EFBDA2><E99A97><EFBFBD><EFBFBD>SON<4F>?
// 譏<>蟆<EFBFBD><E89F86>鄂ョ
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霍ッ逕ア螳壻ケ<E5A3BB>
// 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();
// ========== 鬘ケ逶ョ邂。逅<EFBDA1> ==========
// 蛻帛サコREDCap鬘ケ逶ョ譏<EFBDAE>蟆<EFBFBD>
fastify.post('/api/v1/redcap/projects',
redcapController.createProject
);
// 闔キ蜿夜。ケ逶ョ蛻苓。ィ
fastify.get('/api/v1/redcap/projects',
redcapController.listProjects
);
// 闔キ蜿夜。ケ逶ョ隸ヲ諠<EFBDA6>
fastify.get('/api/v1/redcap/projects/:id',
redcapController.getProject
);
// 譖エ譁ー鬘ケ逶ョ驟咲スョ
fastify.put('/api/v1/redcap/projects/:id',
redcapController.updateProject
);
// 蛻<>髯、鬘ケ逶ョ譏<EFBDAE>蟆<EFBFBD>
fastify.delete('/api/v1/redcap/projects/:id',
redcapController.deleteProject
);
// ========== 謨ー謐ョ蜷梧ュ・ ==========
// 謇句勘隗ヲ蜿大酔豁・<E8B181><EFBDA5>EDCap 竊?AI蟷ウ蜿ー<E89CBF>?
fastify.post('/api/v1/redcap/sync/import/:projectId',
syncController.importFromRedcap
);
// 謗ィ騾∵焚謐ョ蛻ーREDCap<61><70>I蟷ウ蜿ー 竊?REDCap<61>?
fastify.post('/api/v1/redcap/sync/export/:projectId',
syncController.exportToRedcap
);
// 譟・隸「蜷梧ュ・迥カ諤?
fastify.get('/api/v1/redcap/sync/status/:projectId',
syncController.getSyncStatus
);
// 譟・隸「蜷梧ュ・蜴<EFBDA5>彰
fastify.get('/api/v1/redcap/sync/history/:projectId',
syncController.getSyncHistory
);
// ========== Webhook謗・謾カ ==========
// REDCap External Module謗ィ騾∵焚謐ョ<E8AC90>亥ョ樊慮蜷梧ュ・<EFBDAD>?
fastify.post('/api/v1/redcap/webhook/records',
webhookController.receiveRecordUpdate
);
// 謇ケ驥丞酔豁・<E8B181>亥ョ壽慮莉サ蜉。<E89C89><EFBDA1>
fastify.post('/api/v1/redcap/webhook/batch-sync',
webhookController.receiveBatchSync
);
// ========== 蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>ョ。逅<EFBDA1> ==========
// 闔キ蜿乏EDCap鬘ケ逶ョ蜈<EFBDAE>焚謐ョ<E8AC90>亥ュ玲ョオ蛻苓。ィ<EFBDA1>?
fastify.get('/api/v1/redcap/projects/:id/metadata',
redcapController.getProjectMetadata
);
// 蛻帛サコ/譖エ譁ー蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>
fastify.post('/api/v1/redcap/projects/:id/field-mappings',
redcapController.upsertFieldMappings
);
// 闔キ蜿門ュ玲ョオ譏<EFBDB5>蟆<EFBFBD>
fastify.get('/api/v1/redcap/projects/:id/field-mappings',
redcapController.getFieldMappings
);
// ========== AI蜉溯<E89C89>髮<EFBFBD><E9ABAE> ==========
// 隗ヲ蜿第焚謐ョ貂<EFBDAE>エ暦シ<E69AA6>C讓。蝮暦シ?
fastify.post('/api/v1/redcap/dc/clean',
redcapController.triggerDataCleaning
);
// 隗ヲ蜿醍サ溯ョ。蛻<EFBDA1>梵<EFBFBD><E6A2B5>SA讓。蝮暦シ?
fastify.post('/api/v1/redcap/ssa/analyze',
redcapController.triggerStatisticalAnalysis
);
// 闔キ蜿泡I蛻<49>梵扈捺棡
fastify.get('/api/v1/redcap/analysis/:recordId',
redcapController.getAnalysisResults
);
}
譬ク蠢イontroller螳樒鴫
// 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 {
/**
* 莉山EDCap蟇シ蜈・謨ー謐ョ蛻ー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: '鬘ケ逶ョ荳榊ュ伜<EFBDAD>?
});
}
// 2. 隹<>畑REDCap API闔キ蜿匁焚謐ョ
const redcapClient = new RedcapApiClient(
project.redcapUrl,
project.redcapApiToken
);
const redcapData = await redcapClient.exportRecords({
format: 'json',
type: 'flat'
});
logger.info('莉山EDCap闔キ蜿匁焚謐ョ謌仙粥', {
projectId,
recordCount: redcapData.length
});
// 3. 謨ー謐ョ霓ャ謐「
const transformer = new DataTransformService();
const transformedData = await transformer.redcapToAIPlatform(
redcapData,
project.fieldMappings
);
// 4. 蟄伜お蛻ーAI蟷ウ蜿ー謨ー謐ョ蠎?
// 譬ケ謐ョ鬘ケ逶ョ驟咲スョ<EFBDBD>梧耳騾∝芦DC/SSA/ASL遲画ィ。蝮?
if (project.dcProjectId) {
await this.importToDCModule(project.dcProjectId, transformedData);
}
if (project.ssaProjectId) {
await this.importToSSAModule(project.ssaProjectId, transformedData);
}
// 5. 隶ー蠖募酔豁・蜴<EFBDA5>彰
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讓。蝮<EFBDA1>
*/
private async importToDCModule(dcProjectId: string, data: any[]) {
// 隹<>畑DC讓。蝮礼噪蟇シ蜈・API
// TODO: 螳樒鴫DC讓。蝮鈴寔謌宣サ霎<EFBDBB>
}
/**
* 蟇シ蜈・蛻ーSSA讓。蝮<EFBDA1>
*/
private async importToSSAModule(ssaProjectId: string, data: any[]) {
// 隹<>畑SSA讓。蝮礼噪蟇シ蜈・API
// TODO: 螳樒鴫SSA讓。蝮鈴寔謌宣サ霎<EFBDBB>
}
}
<EFBFBD>投 謨ー謐ョ豬∬ョセ隶?
謨ー謐ョ豬?<3F>啌EDCap 竊?AI蟷ウ蜿ー<E89CBF>亥ョ樊慮蜷梧ュ・<EFBDAD><EFBDA5>
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? Step 1: 逕ィ謌キ蝨ィREDCap蠖募<E8A096>謨ー謐ョ 笏?
笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏?
笏? 遐皮ゥカ莠コ蜻伜惠REDCap陦ィ蜊穂クュ蠖募<E8A096>謔」閠<EFBDA3>焚謐? 笏?
笏? 萓句ヲゑシ壽ぅ閠<E38185>D縲∝ケエ鮴<EFBDB4>∵ァ蛻ォ縲∬ッ頑妙縲∵」鬪檎サ捺棡遲<E6A3A1> 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? Step 2: REDCap隗ヲ蜿喪edcap_save_record Hook 笏?
笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏?
笏? External Module謐戊執菫晏ュ倅コ倶サカ 笏?
笏? 闔キ蜿厄シ嗔roject_id, record, instrument, event_id 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? Step 3: 謨ー謐ョ闔キ蜿紋ク取丐蟆? 笏?
笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏?
笏? 1. 隹<>畑REDCap::getData()闔キ蜿門ョ梧紛隶ー蠖<EFBDB0> 笏?
笏? 2. DataMapper霓ャ謐「REDCap EAV譬シ蠑鞘<E8A091>AI蟷ウ蜿ー譬<EFBDB0>㊥譬シ蠑<EFBDBC> 笏?
笏? 3. 蠎皮畑蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>ァ<EFBFBD><EFBDA7><EFBFBD><EFBFBD>edcap_field_mappings陦ィ<E999A6><EFBDA8> 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? 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蟷ウ蜿ー謗・謾カ蟷カ螟<EFBDB6><E89E9F>? 笏?
笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏?
笏? 1. WebhookController鬪瑚ッ∬ッキ豎らュセ蜷<EFBDBE> 笏?
笏? 2. 蟄伜お蜴溷ァ区焚謐ョ蛻ーredcap_sync_records陦? 笏?
笏? 3. 蠑よュ・隗ヲ蜿羨I螟<49>炊莉サ蜉。<E89C89><EFBDA1>C/SSA讓。蝮暦シ? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
竊?
笏娯楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
笏? Step 6: AI螟<49>炊荳守サ捺棡霑泌<E99C91>? 笏?
笏? 笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏 笏?
笏? 1. DC讓。蝮暦シ壽焚謐ョ貂<EFBDAE>エ励¨ER謠仙叙縲∫シコ螟ア蛟シ螟<EFBDBC><E89E9F>? 笏?
笏? 2. SSA讓。蝮暦シ夊<EFBDBC>蜉ィ扈溯ョ。蛻<EFBDA1>梵縲∫函謌仙庄隗<E5BA84>喧蝗セ陦ィ 笏?
笏? 3. 扈捺棡蟄伜お蛻ーAI蟷ウ蜿ー謨ー謐ョ蠎? 笏?
笏? 4. <20>亥庄騾会シ牙屓蜀咏サ捺棡蛻ーREDCap<61>磯夊ソ②PI<50>? 笏?
笏披楳笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏笏?
謨ー謐ョ豬?<3F>哂I蟷ウ蜿ー 竊?REDCap<61>亥<EFBFBD>譫千サ捺棡蝗槫<E89D97><E6A7AB><EFBFBD>
AI蟷ウ蜿ー螳梧<EFBFBD>蛻<EFBFBD>梵
竊?
逕滓<E98095>蛻<EFBFBD>梵扈捺棡<E68DBA><E6A3A1>SON<4F>?
竊?
隹<>畑REDCap API: importRecords
竊?
REDCap蟄伜お扈捺棡蛻ー迚ケ螳壼ュ玲ョ?
竊?
遐皮ゥカ莠コ蜻伜惠REDCap荳ュ譟・逵帰I蛻<49>梵扈捺棡
<EFBFBD>噫 蠑蜿題ョ。蛻剃ク主ョ樊命豁・鬪、
Phase 1: 蝓コ遑蟇ケ謗・<E8AC97><EFBDA5>eek 1-2<>俄怛 莨伜<E88EA8>郤ァP0
逶ョ譬<EFBFBD><EFBFBD>壼サコ遶騎EDCap荳拶I蟷ウ蜿ー逧<EFBFBD>渕譛ャ霑樊<EFBFBD>?
Week 1: External Module鬪ィ譫カ
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 蛻帛サコExternal Module逶ョ蠖慕サ捺桷
- 郛門<EFBFBD>config.json驟咲スョ譁<EFBDAE>サカ
- 螳樒鴫AiResearchAssistantModule.php蝓コ遑邀?
- 螳樒鴫redcap_save_record Hook<6F>亥渕遑迚茨シ<E88CA8>
- 蠑蜿羨piClient.php<68><70>TTP螳「謌キ遶ッ<E981B6><EFBDAF>
- 豬玖ッ包シ啌EDCap菫晏ュ俶焚謐ョ竊呈遠蜊ー譌・蠢?
**莠、莉倡<E88E89>?*<2A>?
ai_research_assistant_v1.0.0/螳梧紛逶ョ蠖<EFBDAE>- 蜿ッ蝨ィREDCap荳ュ蜷ッ逕ィ逧Еxternal Module
- 蝓コ遑譌・蠢苓ョー蠖募粥閭ス
Week 2: AI蟷ウ蜿ーAPI遶ッ轤ケ
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 蛻帛サコredcap_schema謨ー謐ョ蠎鉄chema
- 螳樒鴫Prisma讓。蝙具シ<EFBFBD>edcapProject遲?荳ェ陦ィ<E999A6>?
- 蠑蜿糎ebhookController謗・謾カ謨ー謐ョ
- 螳樒鴫謨ー謐ョ霓ャ謐「譛榊苅DataTransformService
- 蠑蜿鷹。ケ逶ョ邂。逅<EFBFBD>PI<EFBFBD><EFBFBD>RUD<EFBFBD>?
- 豬玖ッ包シ啌EDCap謗ィ騾≫<EFBFBD>AI蟷ウ蜿ー謗・謾カ竊貞ュ伜<EFBFBD>?
**莠、莉倡<E88E89>?*<2A>?
/api/v1/redcap/*API遶ッ轤ケ- PostgreSQL redcap_schema蛻帛サコ
- Postman豬玖ッ暮寔蜷<EFBFBD>
Phase 2: 謨ー謐ョ蜷梧ュ・荳取丐蟆<E4B890>シ<EFBFBD>eek 3-4<>俄ュ<E4BF84> 莨伜<E88EA8>郤ァP1
逶ョ譬<EFBFBD><EFBFBD>壼ョ樒鴫蜿悟髄謨ー謐ョ蜷梧ュ・蜥悟ュ玲ョオ譎コ閭ス譏<EFBFBD>蟆<EFBFBD>
Week 3: 蟄玲ョオ譏<EFBDB5>蟆<EFBFBD>ウサ扈<EFBDBB>
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 蠑蜿大ュ玲ョオ譏<EFBFBD>蟆<EFBFBD>ョ。逅<EFBFBD>I<EFBFBD>亥燕遶ッReact<EFBFBD>?
- 螳樒鴫REDCap蜈<EFBFBD>焚謐ョ闔キ蜿泡PI
- 蠑蜿大ュ玲ョオ譏<EFBFBD>蟆<EFBFBD><EFBFBD>鄂ョ逡碁<EFBFBD>?
- 螳樒鴫譏<EFBFBD>蟆<EFBFBD>ァ<EFBFBD><EFBFBD>蠑墓梼<EFBFBD><EFBFBD>ataMapper<EFBFBD>?
- 謾ッ謖∝、肴揩霓ャ謐「<EFBFBD>亥ヲゑシ壼黒菴崎スャ謐「縲∫シ也<EFBFBD>∵丐蟆<EFBFBD>シ<EFBFBD>
- 豬玖ッ包シ壽丐蟆<EFBFBD><EFBFBD>鄂ョ竊呈焚謐ョ霓ャ謐「鬪瑚ッ<EFBFBD>
**莠、莉倡<E88E89>?*<2A>?
- 蟄玲ョオ譏<EFBFBD>蟆ФI鬘オ髱「
- 譏<EFBFBD>蟆<EFBFBD>ァ<EFBFBD><EFBFBD>蠑墓梼
- 驟咲スョ譁<EFBFBD>。」
Week 4: 蜿悟髄蜷梧ュ・
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 螳樒鴫謇ケ驥乗焚謐ョ蟇シ蜈・<EFBFBD><EFBFBD>EDCap 竊?AI<41>?
- 螳樒鴫蛻<EFBFBD>梵扈捺棡蝗槫<EFBFBD><EFBFBD><EFBFBD>I 竊?REDCap<61>?
- 蠑蜿舛ron螳壽慮蜷梧ュ・莉サ蜉。
- 螳樒鴫蜷梧ュ・迥カ諤∫尅謗ァ逡碁<EFBFBD>?
- 髞呵ッッ螟<EFBFBD>炊荳朱㍾隸墓惻蛻?
- 豬玖ッ包シ壼ョ梧紛蜷梧ュ・豬∫ィ?
**莠、莉倡<E88E89>?*<2A>?
- 蜿悟髄蜷梧ュ・蜉溯<EFBFBD>
- 蜷梧ュ・逶第而Dashboard
- 髞呵ッッ螟<EFBFBD>炊譛コ蛻カ
Phase 3: AI蜉溯<E89C89>髮<EFBFBD><E9ABAE><EFBFBD><EFBFBD>eek 5-6<>解沁?莨伜<E88EA8>郤ァP1
逶ョ譬<EFBFBD><EFBFBD>夐寔謌織C縲ヾSA縲、IA遲陰I讓。蝮<EFBFBD>
Week 5: DC讓。蝮鈴寔謌<E5AF94>
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- REDCap謨ー謐ョ竊奪C讓。蝮苓<EFBFBD>蜉ィ貂<EFBFBD>エ<EFBFBD>
- 貂<EFBFBD>エ礼サ捺棡竊坦EDCap蝗槫<EFBFBD>
- 蝨ィREDCap荳ュ螻慕、コ貂<EFBFBD>エ玲冠蜻?
- 謾ッ謖∵焔蜉ィ隗ヲ蜿第ク<EFBFBD>エ<EFBFBD>
- 豬玖ッ包シ壼ス募<EFBFBD>竊呈ク<EFBFBD>エ冷<EFBFBD>譟・逵狗サ捺<EFBFBD>?
**莠、莉倡<E88E89>?*<2A>?
- DC髮<EFBFBD><EFBFBD>API
- REDCap貂<EFBFBD>エ玲冠蜻企。オ髱「
Week 6: SSA讓。蝮鈴寔謌<E5AF94>
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- REDCap謨ー謐ョ竊担SA讓。蝮苓<EFBFBD>蜉ィ蛻<EFBFBD>梵
- 謾ッ謖∽ク牙、ァ蛻<EFBFBD>梵霍ッ蠕<EFBFBD>シ磯弌蛻?鬚<>オ<EFBFBD>/RCT<43>?
- 蝨ィREDCap荳ュ蠏悟<EFBFBD>扈溯ョ。謚・蜻?
- 蜿ッ隗<EFBFBD>喧蝗セ陦ィ螻慕、?
- 豬玖ッ包シ壽焚謐ョ蠖募<EFBFBD>竊定<EFBFBD>蜉ィ蛻<EFBFBD>梵竊呈冠蜻顔函謌?
**莠、莉倡<E88E89>?*<2A>?
- SSA髮<EFBFBD><EFBFBD>API
- 扈溯ョ。謚・蜻雁オ悟<EFBFBD>鬘オ髱「
Phase 4: 鬮倡コァ蜉溯<E89C89><E6BAAF><EFBFBD>eek 7-8<>解沍?莨伜<E88EA8>郤ァP2
逶ョ譬<EFBFBD><EFBFBD>哂I霎<EFBFBD>勧蠖募<EFBFBD>縲∵匱閭ス雍ィ謗ァ遲牙「槫シ蜉溯<EFBFBD>?
Week 7: AI霎<49>勧蠖募<E8A096>
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 蠑蜿第匱閭ス閾ェ蜉ィ螳梧<EFBFBD><EFBFBD>亥渕莠主紙蜿イ謨ー謐ョ<EFBFBD>?
- 蠑ょクク蛟シ鬚<EFBFBD>ュヲ<EFBFBD>亥ョ樊慮AI蛻、譁ュ<EFBFBD>?
- 蟄玲ョオ蜈ウ閨疲耳闕撰シ<EFBFBD>I鬚<EFBFBD>オ具シ?
- 蠖募<EFBFBD>謨育紫謠仙合扈溯ョ。
- 豬玖ッ包シ壼ス募<EFBFBD>菴馴ェ御シ伜喧鬪瑚ッ?
**莠、莉倡<E88E89>?*<2A>?
- AI霎<EFBFBD>勧蠖募<EFBFBD>JS謠剃サカ
- 譎コ閭ス雍ィ謗ァ隗<EFBFBD><EFBFBD>蠑墓梼
Week 8: 扈シ蜷域オ玖ッ穂ク惹シ伜<EFBDBC>?
莉サ蜉。貂<EFBFBD>黒<EFBFBD>?
- 諤ァ閭ス豬玖ッ包シ?00荳<30>擅隶ー蠖募酔豁・<E8B181>?
- 螳牙<EFBFBD>豬玖ッ包シ<EFBFBD>PI隶、隸√∵焚謐ョ蜉<EFBFBD>蟇<EFBFBD>シ<EFBFBD>
- 逕ィ謌キ鬪梧噺豬玖ッ包シ<EFBFBD>AT<EFBFBD>?
- 譁<EFBFBD>。」郛門<EFBFBD><EFBFBD>育畑謌キ謇句<EFBFBD>?蠑蜿第枚譯」<E8ADAF><EFBDA3>
- 驛ィ鄂イ蛻ー逕滉コァ邇ッ蠅?
**莠、莉倡<E88E89>?*<2A>?
- 諤ァ閭ス豬玖ッ墓冠蜻<EFBFBD>
- 螳梧紛譁<EFBFBD>。」
- 逕滉コァ邇ッ蠅<EFBFBD>Κ鄂イ
<EFBFBD>白 螳牙<E89EB3>諤ァ隶セ隶?
API隶、隸∵惻蛻カ
// 菴ソ逕ィHMAC-SHA256遲セ蜷埼ェ瑚ッ<E7919A>
// 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蟷ウ蜿ー鬪瑚ッ<E7919A>
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;
}
謨ー謐ョ蜉<EFBFBD>蟇<EFBFBD>
- REDCap API Token<65>壻スソ逕ィAES-256蜉<36>蟇<EFBFBD>ュ伜お
- 莨<EFBFBD>霎灘刈蟇<EFBFBD>シ壼シコ蛻カHTTPS
- 謨乗─蟄玲ョオ<EFBFBD>壽髪謖∝ュ玲ョオ郤ァ蜉<EFBFBD>蟇<EFBFBD>シ<EFBFBD>HI謨ー謐ョ<EFBFBD>?
譚<EFBFBD>剞謗ァ蛻カ
// REDCap逕ィ謌キ譚<EFBDB7>剞蜷梧ュ・蛻ー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;
};
}
<EFBFBD>答 謚譛ッ譬域サ扈<EFBDBB>
| 螻らコァ | REDCap萓? | AI蟷ウ蜿ー萓? |
|---|---|---|
| 郛也ィ玖ッュ險 | PHP 7.4+ | TypeScript/Node.js 22 |
| 譯<EFBFBD>楔 | REDCap EM Framework v16 | Fastify v4 |
| *謨ー謐ョ蠎? | MySQL 5.7+ | PostgreSQL 15 |
| 謨ー謐ョ讓。蝙<EFBFBD> | EAV讓。蝙<EFBFBD> | 蜈ウ邉サ蝙?JSONB |
| 蜑咲ォッ | jQuery + Bootstrap 5 | React 19 + Ant Design 6 |
| API | REDCap RESTful API | Fastify RESTful API |
| 隶、隸<EFBFBD> | API Token | HMAC-SHA256遲セ蜷<EFBDBE> |
| 譌・蠢<EFBFBD> | REDCap譌・蠢苓。? | Winston + SLS |
| 莉サ蜉。髦溷<EFBFBD> | REDCap Cron | pg-boss (Postgres-Only) |
<EFBFBD>統 荳倶ク豁・陦悟<E999A6>?
遶句叉陦悟勘<EFBFBD>域悽蜻ィ<EFBFBD><EFBFBD>
-
**遑ョ隶、髴豎?*<2A>?
- 遑ョ隶、莨伜<EFBFBD>郤ァ<EFBFBD><EFBFBD>C莨伜<EFBFBD><EFBFBD>溯ソ俶弍SSA莨伜<EFBFBD><EFBFBD>滂シ<EFBFBD>
- 遑ョ隶、驛ィ鄂イ蠖「諤<EFBFBD>シ井コ醍ォッSaaS<EFBFBD>溯ソ俶弍遘∵怏蛹夜Κ鄂イ<EFBFBD>滂シ<EFBFBD>
- 遑ョ隶、REDCap譛榊苅蝎ィ菫。諱ッ<EFBFBD><EFBFBD>RL縲∫沿譛ャ縲∬ョソ髣ョ譚<EFBFBD>剞<EFBFBD><EFBFBD>
-
邇ッ蠅<EFBFBD>㊥螟<EFBFBD><EFBFBD>?
- 謳ュ蟒コREDCap豬玖ッ慕識蠅<EFBFBD>シ井スソ逕ィDocker<EFBFBD>?
- 蛻帛サコ豬玖ッ暮。ケ逶ョ蜥梧オ玖ッ墓焚謐?
- 驟咲スョAI蟷ウ蜿ー豬玖ッ柊PI
-
**蜷ッ蜉ィ蠑蜿?*<2A>?
- 蛻帛サコExternal Module逶ョ蠖<EFBDAE>
- 蛻晏ァ句喧Git莉灘コ<EFBFBD>
- 郛門<EFBFBD>config.json
謚譛ッ鬚<EFBFBD><EFBFBD>?
- REDCap API豺ア蜈・豬玖ッ<E78E96>
- External Module Hook譛コ蛻カ鬪瑚ッ<E7919A>
- 螟ァ謨ー謐ョ驥丞酔豁・諤ァ閭ス豬玖ッ<EFBFBD>
- *遘サ蜉ィ遶ッ<EFBFBD><EFBFBD>EDCap Mobile App<70>蛾寔謌仙庄陦梧?
<EFBFBD>識 謌仙粥譬<E7B2A5>㊥
**MVP迚域悽<E59F9F><E682BD>hase 1-2螳梧<E89EB3><E6A2A7>?*<2A>?
- 笨?REDCap謨ー謐ョ閭ス謗ィ騾∝芦AI蟷ウ蜿ー
- 笨?AI蟷ウ蜿ー閭ス謗・謾カ蟷カ蟄伜お謨ー謐ョ
- 笨?蟄玲ョオ譏<EFBDB5>蟆<EFBFBD><E89F86>鄂ョ蜉溯<E89C89>蜿ッ逕ィ
- 笨?蝓コ遑蜷梧ュ・逶第而蜿ッ逕ィ
**譬<>㊥迚域悽<E59F9F><E682BD>hase 3螳梧<E89EB3><E6A2A7>?*<2A>?
- 笨?DC讓。蝮鈴寔謌仙ョ梧<EFBDAE><E6A2A7>郁<EFBFBD>蜉ィ貂<EFBDA8>エ暦シ<E69AA6>
- 笨?SSA讓。蝮鈴寔謌仙ョ梧<EFBDAE><E6A2A7>郁<EFBFBD>蜉ィ蛻<EFBDA8>梵<EFBFBD><E6A2B5>
- 笨?蛻<>梵扈捺棡蜿ッ蝨ィREDCap荳ュ譟・逵?
- 笨?逕ィ謌キ菴馴ェ梧オ∫腐
**莨∽ク夂沿譛ャ<E8AD9B><EFBDAC>hase 4螳梧<E89EB3><E6A2A7>?*<2A>?
- 笨?AI霎<49>勧蠖募<E8A096>謠仙合謨育紫50%+
- 笨?譎コ閭ス雍ィ謗ァ蜃丞ー鷹漠隸ッ邇?0%+
- 笨?謾ッ謖<EFBDAF>100荳?隶ー蠖募酔豁・
- 笨?螳牙<E89EB3>蜷郁ァ<E98381>シ育ャヲ蜷<EFBDA6>DA 21 CFR Part 11<31>?
譁<EFBFBD>。」迚域悽<EFBFBD>嘛1.0
**譛蜷取峩譁?*<2A>?025-12-30
荳区ャ。譖エ譁ー<EFBFBD>啀hase 1蜷ッ蜉ィ蜷取峩譁ー蠑蜿題ソ帛コ?
<EFBFBD>噫 蜃<>、<EFBFBD>・ス蠑蟋倶コ<E580B6>雛<EFBFBD>溯ョゥ謌台サャ蠑蜷ッREDCap荳拶I逧<49>檮蜷井ケ区羅<E58CBA><E7BE85>