Files
AIclinicalresearch/docs/03-业务模块/Redcap/00-模块概览/03-REDCap对接风险评估与技术挑战分析.md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
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%)
2026-01-14 19:15:01 +08:00

1224 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REDCap撖寞𦻖憌𡡞埯霂<E59FAF>摯銝擧<E98A9D><E693A7><EFBFBD><E88880>䀹楛摨血<E691A8><E8A180>?
> **<2A><><EFBFBD><EFB99D>𧋦嚗?* v1.0
> **<2A>𥕦遣<F0A595A6><EFBFBD>嚗?* 2025-12-30
> **<2A><><EFBFBD><EFBFBD>嚗?* <20><><EFBFBD><EFBFBD>萘輕<E89098><E8BC95><EFBFBD>REDCap撖寞𦻖<E5AF9E><F0A6BB96><EFBFBD><EFBFBD>舫𠗕<E888AB><EFBFBD><E5AB98><EFBFBD><EFBFBD>舀綉<E88880><EFBFBD><E588A0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E588B8>?
> **<2A><><EFBFBD>園𡢿嚗?* 20<32><30><EFBFBD>
> **<2A><EFBFBD><E6BBA9><EFBFBD>** 潃鐥<E6BD83>潃鐥<E6BD83>潃?**<2A><EFBFBD><E59786><EFBFBD><EFBFBD>粉**
---
## <20><> <20><>﹝霂湔<E99C82>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?*<2A><><EFBFBD><EFBFBD>萘輕<E89098><EFBFBD><E5B1B8><EFBFBD><E68B90>?*<2A><><EFBFBD><EFBFBD>鞉䲮瘜𤏪<E7989C><EFBFBD><E99C82>REDCap撖寞𦻖憿寧𤌍<E5AFA7><F0A48C8D><EFBFBD>
1. **<EFBFBD><EFBFBD><EFBFBD>舫𠗕<EFBFBD>?*嚗?憭扳瓲敹<E793B2>𠗕憸矋<E686B8>
2. **銝滚虾<E6BB9A><EFBFBD>蝝?*嚗?銝芷<E98A9D><E88AB7><EFBFBD><E398BE><EFBFBD>
3. **憭齿<E686AD>摨西<E691A8>隡?*嚗<><E59A97><EFBFBD><EFBFBD>EDC撖寞<E69296>嚗?
4. **憭梯揖獢<E68F96><E78DA2><EFBFBD><EFBFBD><EFBFBD>**嚗<><E59A97><EFBFBD>諹萱<E8ABB9>𤑳<EFBFBD>撉䕘<E69289>
5. **閫<><E996AB>蝑𣇉裦**嚗<><E59A97>雿閖<E99BBF>雿𡡞<E99BBF><F0A1A19E><EFBFBD>
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**嚗?
- <20>?REDCap<61><70>AV璅<E79285><E288AA>臬炏隡𡁏<E99AA1>銝箸<E98A9D><EFBFBD><E689AF><EFBFBD>嚗?
- <20>?External Module獢<65><EFBFBD><E6B2B2><EFBFBD><EFBFBD><EFBFBD>憭𡁜之嚗?
- <20>?<3F><>𧋦<EFBFBD><F0A78BA6>漣隡帋<E99AA1>隡𡁶聦<F0A181B6>𤩺<EFBFBD>隞祉<E99A9E><E7A589><EFBFBD><EFBFBD>嚗?
- <20>?<3F>唳旿銝<E697BF><E98A9D><EFBFBD><EFBFBD>雿蓥<E99BBF><EFBFBD><E99C82>
- <20>?<3F>臬炏<E887AC><EFBFBD><E6BE86><EFBFBD>嚗㇌OI<4F><49><EFBFBD>嚗㚁<E59A97>
---
## <20><20><EFBFBD>憌𡡞埯璁<E59FAF><E79281><EFBFBD><EFBFBD>航郎<E888AA>𠺪<EFBFBD>
### 憌𡡞埯蝑厩漣<E58EA9><E6BCA3>
| 憌𡡞埯蝐餃<E89D90> | 憌𡡞埯蝑厩漣 | 敶勗<E695B6><E58B97><EFBFBD>凒 | <20>舀綉<E88880>?| 撱箄悅 |
|---------|---------|---------|--------|------|
| **EAV璅<E79285><E288AA><EFBFBD>** | <20>𣞁 擃?| <20>唳旿<E594B3>?10銝<30><EFBFBD>?| <20>𩤃<EFBFBD> <20><EFBFBD><E585B8>舀綉 | 敹<>◆霈曇恣蝻枏<E89DBB><E69E8F><EFBFBD><E8ABB9><EFBFBD><EFBFBD><EFBFBD>?|
| **REDCap<61><70><EFBFBD>澆捆<E6BE86>?* | <20>𣞁 擃?| 瘥𤩺活REDCap<61><70>漣 | <20>?銝滚虾<E6BB9A>?| 銝交聢<E4BAA4><E881A2>𧋦<EFBFBD><F0A78BA6><EFBFBD>+<2B>𧼮<EFBFBD>瘚贝<E7989A> |
| **<EFBFBD>唳旿銝<EFBFBD><EFBFBD><EFBFBD>?* | <20>椬 銝?| <20><><EFBFBD><EFBFBD>峕郊<E5B395>箸艶 | <20>?<3F>舀綉 | 霈曇恣撟<E681A3><E6929F><EFBFBD>?<3F><EFBFBD><EFBFBD><E996AB><EFBFBD><EFBFBD> |
| **API<50><EFBFBD>** | <20>椬 銝?| <20><EFBFBD><E5AFA5><EFBFBD> | <20>?<3F>舀綉 | 摰䂿緵<E482BF><EFBFBD><E6AFBA>𣂼<EFBFBD><F0A382BC>峕鸌憭<E9B88C><E686AD> |
| **摰匧<E691B0><E58CA7><EFBFBD><EFBFBD>** | <20>𣞁 擃?| PHI<48>唳旿瘜<E697BF>蠧 | <20>?<3F>舀綉 | 銝交聢摰∟恣+<2B><EFBFBD>+HIPAA<41><41><EFBFBD> |
| **蝏湔擪<E6B994>鞉𧋦** | <20>椬 銝?| <20><EFBFBD>餈鞱𨯫 | <20>𩤃<EFBFBD> <20><EFBFBD><E585B8>舀綉 | 蝏<>遣銝㮖<E98A9D><E3AE96><EFBFBD> |
| **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>摨?* | <20>叚 雿?| <20><EFBFBD><E586BD>寡悌 | <20>?<3F>舀綉 | 皜鞱<E79A9C>撘𤩺綫撟?|
---
## <20>𣞁 <20><><EFBFBD><EFBFBD><E88880>?嚗鍃AV璅<E79285><E288AA><EFBFBD><EFBFBD><EFBFBD>瘛望<E7989B>
### <20><EFBFBD><E6A185>讛膩
REDCap雿輻鍂**Entity-Attribute-Value (EAV)** 璅<E79285>摮睃<E691AE><E79D83>唳旿嚗諹<E59A97><E8ABB9><EFBFBD>憭抒<E686AD><E68A92><EFBFBD><EFBFBD><EFBFBD><E88880><EFBFBD>?
#### REDCap<61><70><EFBFBD><EFBFBD><E6A180>冽䲮撘?
```sql
-- redcap_data銵函<E98AB5><E587BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵剁<E98AB5>
CREATE TABLE redcap_data (
project_id INT,
event_id INT,
record VARCHAR(100),
field_name VARCHAR(100),
value TEXT,
PRIMARY KEY (project_id, event_id, record, field_name)
);
-- 摮睃<E691AE>蝷箔<E89DB7>嚗帋<E59A97>銝芣<E98A9D><E88AA3><EFBFBD><EFBFBD>3銝芸<E98A9D>畾菟<E795BE>閬?銵?
| project_id | event_id | record | field_name | value |
|------------|----------|---------|------------|----------|
| 123 | 1 | PAT001 | age | 45 |
| 123 | 1 | PAT001 | gender | male |
| 123 | 1 | PAT001 | diagnosis | diabetes |
```
撖寞<EFBFBD>**隡删<E99AA1><E588A0>喟頂<E5969F>𧢲芋<F0A7A2B2>?*嚗?
```sql
-- 隡删<E99AA1>摰質”摮睃<E691AE><EFBFBD><E59A97>銵峕<E98AB5>摰𡄯<E691B0>
CREATE TABLE patients (
record_id VARCHAR(100) PRIMARY KEY,
age INT,
gender VARCHAR(10),
diagnosis VARCHAR(100)
);
| record_id | age | gender | diagnosis |
|-----------|-----|--------|-----------|
| PAT001 | 45 | male | diabetes |
```
### <20><EFBFBD><E689AF><EFBFBD><EFBFBD><E59A97>摰𧼮㦤<F0A7BCAE><EFBFBD>
#### <20>箸艶1嚗𡁏䰻霂<E99C82>銝芣<E98A9D><E88AA3><EFBFBD><EFBFBD>摰峕㟲<E5B395>唳旿
```sql
-- EAV璅<E79285>嚗𡁻<E59A97><EFBFBD><EFBFBD><EFBFBD>JOIN嚗<4E><E59A97>嚗?
SELECT
MAX(CASE WHEN field_name = 'age' THEN value END) AS age,
MAX(CASE WHEN field_name = 'gender' THEN value END) AS gender,
MAX(CASE WHEN field_name = 'diagnosis' THEN value END) AS diagnosis
FROM redcap_data
WHERE project_id = 123
AND record = 'PAT001'
GROUP BY record;
-- <20><EFBFBD><E689AF>園𡢿嚗?00銝芸<E98A9D>畾蛛<E795BE>嚗鰺50-200ms
-- 摰質”<E8B3AA><EFBFBD><E689AF>園𡢿嚗鰺1-5ms嚗<73>翰40-200<30><EFBFBD>
```
#### <20>箸艶2嚗𡁏鸌<F0A1818F>誩紡<E8AAA9>?000銝芣<E98A9D><E88AA3>?
```sql
-- EAV璅<E79285>嚗𡁶<E59A97><F0A181B6><EFBFBD><EFBFBD><E68A92><EFBFBD>
SELECT * FROM redcap_data
WHERE project_id = 123
AND record IN ('PAT001', 'PAT002', ..., 'PAT1000');
-- 蝏𤘪<E89D8F>嚗朞<E59A97><E69C9E>?00銝<30><E98A9D>嚗?000<30><30><EFBFBD>?<3F> 100摮埈挾 <20> 10鈭衤辣嚗?
-- <20><EFBFBD><E689AF>園𡢿嚗?0-60蝘?
-- <20><><EFBFBD><EFBFBD>删鍂嚗?00MB - 2GB
-- 蝵𤑳<E89DB5>隡㰘<E99AA1>嚗𡁜楊憭抒<E686AD>JSON payload
```
#### <20>箸艶3嚗𡁶<E59A97><E99C88><E288AA>鞉䰻霂?
```sql
-- <20>亥砭撟湧<E6929F>>50撗<30><E69297><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
SELECT COUNT(DISTINCT record)
FROM redcap_data
WHERE project_id = 123
AND field_name = 'age'
AND CAST(value AS UNSIGNED) > 50;
-- <20><EFBFBD>嚗𡁜<E59A97>銵冽醌<E586BD>𧶏<EFBFBD><F0A7B68F><EFBFBD><E4ADBE>拍鍂蝝<E89D9D>
-- <20><EFBFBD><E689AF>園𡢿嚗?0銝<30><E98A9D><EFBFBD><EFBFBD><EFBFBD>嚗?-30蝘?
```
### 撖農I撟喳蝱<E596B3><E89DB1><EFBFBD>?
1. **DC璅<E79285><EFBFBD><EFBFBD><EFBFBD>瘣梹<E798A3>**嚗?
- <20>?<3F><EFBFBD><E4ADBE>湔𦻖撖遂AV<41>唳旿<E594B3>𡁶<EFBFBD><E99C88><E288AA>?
- <20>?瘥𤩺活皜<E6B4BB><E79A9C><EFBFBD><EFBFBD><EFBFBD><E996AC>"<22>匧像"<22>唳旿嚗𠄌TL餈<4C><E9A488>嚗?
- <20><EFBFBD> 1000<30>∟扇敶閧<E695B6><EFBFBD><E79A9C><EFBFBD><EFBFBD><EFBFBD>閬?-10<31><30><EFBFBD><EFBFBD><E686B8><EFBFBD>?
2. **SSA璅<E79285><EFBFBD><E59A97><E99C88><E288AA><EFBFBD>**嚗?
- <20>?R/Python<6F>𡁏𧋦<F0A1818F><EFBFBD><E4ADBE>湔𦻖<E6B994><EFBFBD>EAV銵?
- <20>?敹<><EFBFBD><E29786><EFBFBD>蛹DataFrame<6D><EFBFBD>
- <20>𩤃<EFBFBD> <20><><EFBFBD><EFBFBD><E798A8>堒楊憭改<E686AD>10銝<30>扇敶𨰝<E695B6>2-5GB嚗?
3. **摰墧𧒄<E5A2A7>峕郊**嚗?
- <20>?瘥𤩺活靽嘥<E99DBD><E598A5>質圻<E8B3AA><EFBFBD><E7A983>渲扇敶閙䰻霂<E99C82><EFBD87><EFBFBD>
- <20>𩤃<EFBFBD> 擃㗛<E69383>敶訫<E695B6><E8A8AB>箸艶銝衤<E98A9D><E8A1A4>硋𡆇<E7A18B>唳旿摨?
### 閫<><E996AB><EFBFBD><EFBFBD><EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#### 蝑𣇉裦A嚗𡁶<E59A97><F0A181B6>𤥁<EFBFBD><F0A4A581>?+ 摰𡁏𧒄<F0A1818F>瑟鰵
```sql
-- <20>𥕦遣摰質”<E8B3AA><EFBFBD><EFBFBD>㦛嚗<E3A69B><E59A97>撠𤩺𧒄<F0A4A9BA>瑟鰵銝<E9B0B5>甈∴<E79488>
CREATE MATERIALIZED VIEW patient_data_flat AS
SELECT
record,
MAX(CASE WHEN field_name = 'age' THEN value END) AS age,
MAX(CASE WHEN field_name = 'gender' THEN value END) AS gender,
-- ... <20><EFBFBD>摮埈挾
FROM redcap_data
WHERE project_id = 123
GROUP BY record;
-- AI撟喳蝱<E596B3>亥砭摰質”嚗<E2809D>翰嚗?
SELECT * FROM patient_data_flat WHERE age > 50;
```
**<EFBFBD><EFBFBD>**嚗?
- <20>𩤃<EFBFBD> <20>唳旿撱嗉<E692B1><EFBFBD><E59A97>憭?撠𤩺𧒄嚗?
- <20>𩤃<EFBFBD> 摮睃<E691AE>蝛粹𡢿蝧餃<E89DA7>?
- <20>𩤃<EFBFBD> <20>瑟鰵餈<E9B0B5><E9A488>隡𡁻<E99AA1>銵?
#### 蝑𣇉裦B嚗鋫I撟喳蝱靘抒<E99D98>摮?
```typescript
// <20>杗I撟喳蝱PostgreSQL銝剔<E98A9D>摮?<3F>匧像"<22>𡒊<EFBFBD><F0A1928A>唳旿
model RedcapDataCache {
id String @id
projectId String
recordId String
flatData Json // 摮睃<E691AE>摰質”<E8B3AA><EFBFBD>
lastSyncAt DateTime
@@unique([projectId, recordId])
@@index([lastSyncAt])
}
// 憓鮋<E68693><E9AE8B>峕郊蝑𣇉裦
async function syncFromRedcap(projectId: string) {
const lastSyncTime = await getLastSyncTime(projectId);
// <20>芣䰻霂<E99C82><EFBCB7><EFBFBD><E8AAA9><EFBFBD><E6B99B><EFBFBD>redcap_log銵剁<E98AB5>
const changedRecords = await redcapApi.getChangedRecords({
projectId,
since: lastSyncTime
});
// <20><EFBFBD><E5AFA5>湔鰵蝻枏<E89DBB>
await batchUpdateCache(changedRecords);
}
```
**隡睃飵**嚗?
- <20>?<3F>亥砭<E4BAA5>笔漲敹恬<E695B9>PostgreSQL JSONB蝝<E89D9D>嚗?
- <20>?<3F><EFBFBD>REDCap<61>唳旿摨枏<E691A8><E69E8F>?
- <20>?<3F><EFBFBD><E88880><EFBFBD><E586BD>𦦵揣<F0A6A6B5><E68FA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>皛?
**<EFBFBD><EFBFBD>**嚗?
- <20>𩤃<EFBFBD> <20>唳旿<E594B3>𦯀<EFBFBD><EFBFBD><E59A97><EFBFBD>函蕃<E587BD><EFBFBD>
- <20>𩤃<EFBFBD> <20>峕郊撱嗉<E692B1>嚗?-30蝘𡜐<E89D98>
- <20>𩤃<EFBFBD> 蝏湔擪憭齿<E686AD>摨血<E691A8><E8A180>?
#### 蝑𣇉裦C嚗鑹EDCap API<50><EFBFBD><E5ADB5><EFBFBD><EFBFBD><EFBFBD>?
```php
// External Module銝哨<E98A9D><E593A8><EFBFBD><E5AFA5><EFBFBD><E79195>唳旿嚗<E697BF><E59A97>憿蛛<E686BF>
function getBatchRecords($projectId, $recordIds, $batchSize = 100) {
$batches = array_chunk($recordIds, $batchSize);
$allData = [];
foreach ($batches as $batch) {
// 雿輻鍂REDCap API嚗<49>歇隡睃<E99AA1>嚗?
$data = REDCap::getData([
'project_id' => $projectId,
'return_format' => 'json',
'records' => $batch,
'exportDataAccessGroups' => false,
'exportSurveyFields' => false
]);
$allData = array_merge($allData, $data);
// <20><EFBFBD><EFBFBD>𧒄
usleep(100000); // 100ms撱嗉<E692B1>
}
return $allData;
}
```
### 憌𡡞埯霂<E59FAF>
| <20><><EFBFBD> | 霂<>摯 | 霂湔<E99C82> |
|------|------|------|
| **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** | <20>𣞁 擃㗛<E69383><E3979B>?| <20>唳旿<E594B3>?5銝<35><EFBFBD><EFBFBD><E59786>?|
| **<EFBFBD>航圾<EFBFBD><EFBFBD>?* | <20><20><EFBFBD> | <20><><EFBFBD><E996AC><EFBFBD><EFBFBD><EFBFBD>蝻枏<E89DBB><E69E8F><EFBFBD> |
| **撘<><E69298><EFBFBD><E78390>?* | <20>𣞁 擃?| <20><><EFBFBD><EFBFBD>2-3<>刻挽霈∠<E99C88>摮睃<E691AE> |
| **餈鞟輕<E99E9F>鞉𧋦** | <20>椬 銝?| <20><><EFBFBD><E996AC><EFBFBD><EFBFBD>甇亙辣餈?|
---
## <20>𣞁 <20><><EFBFBD><EFBFBD><E88880>?嚗鑹EDCap<61><70>𧋦<EFBFBD><F0A78BA6><EFBFBD>?<3F><EFBFBD><E6B8B8>?
### <20><EFBFBD><E6A185>讛膩
REDCap<EFBFBD>?*敹恍<E695B9>蠘翮隞?*嚗<><E59A97>撟?-4銝芸之<E88AB8><E4B98B>𧋦嚗劐<E59A97>撣行䔉<E8A18C>澆捆<E6BE86>批埯璇艾<E79287>?
### <20><EFBFBD><EFBFBD><E78DA2><EFBFBD><E59A97>瘜芣<E7989C>霈哨<E99C88>
#### 獢<><E78DA2>1嚗䥅ook<6F>賣㺭蝑曉<E89D91><E69B89>䀹凒
```php
// REDCap 10.x<><78>𧋦
function redcap_save_record($project_id, $record, $instrument, $event_id) {
// 4銝芸<E98A9D><E88AB8>?
}
// REDCap 11.0<EFBFBD><EFBFBD>𧋦嚗?021撟湛<E6929F>
function redcap_save_record($project_id, $record, $instrument, $event_id,
$group_id, $survey_hash, $response_id, $repeat_instance) {
// 蝒<><E89D92><EFBFBD><EFBFBD>8銝芸<E98A9D><E88AB8><EFBFBD>
}
```
**敶勗<E695B6>**嚗?
- <20>?<3F><><EFBFBD><EFBFBD>韏𡝗迨Hook<6F><6B>xternal Module<6C><EFBFBD>撏拇<E6928F>
- <20><EFBFBD> <20><><EFBFBD><EFBFBD>乩耨憭滚僎瘚贝<E7989A>
- <20><><><E68692>瘝⊥<E7989D>銝交聢<E4BAA4><E881A2><EFBFBD><EFBFBD><EFBFBD>摰𡄯<E691B0><F0A184AF>煺漣<E785BA><EFBFBD><E887AC>湔𦻖<E6B994><F0A6BB96><EFBFBD>
#### 獢<><E78DA2>2嚗鋫PI<50><EFBFBD><E6BB9A><EFBFBD><E6BE86>䀹凒
```json
// REDCap 12.x API<50><EFBFBD>
{
"record_id": "PAT001",
"age": "45",
"gender": "1" // 摮㛖泵銝脩掩<E884A9>?
}
// REDCap 13.0 API<50><EFBFBD><EFBFBD><E59A97><EFBFBD>亦掩<E4BAA6>贝蓮<E8B49D><EFBFBD>
{
"record_id": "PAT001",
"age": 45, // <20><EFBFBD><E480B9>湔㺭蝐餃<E89D90>
"gender": "1" // 隞齿糓摮㛖泵銝?
}
```
**敶勗<E695B6>**嚗?
- <20>?蝐餃<E89D90><E9A483><EFBFBD>憭梯揖嚗㇍ypeScript銝交聢璅<E79285>嚗?
- <20>?<3F>唳旿撉諹<E69289><E8ABB9><EFBFBD>憭望<E686AD>
- <20><> <20>鞱𤪖<E99EB1><F0A4AA96>ug嚗?0" vs 0 撣<><E692A3><EFBFBD>斗鱏<E69697><EFBFBD>嚗?
#### 獢<><E78DA2>3嚗𡁏㺭<F0A1818F><EFBFBD>銵函<E98AB5><E587BD><EFBFBD><EFBFBD><EFBFBD>?
```sql
-- REDCap 14.x銋见<E98A8B>
SELECT * FROM redcap_projects WHERE project_id = 123;
-- REDCap 15.0<EFBFBD><EFBFBD>摮埈挾
ALTER TABLE redcap_projects
ADD COLUMN project_language VARCHAR(10) DEFAULT 'English';
-- 憒<><E68692>雿删<E99BBF>External Module<6C>湔𦻖<E6B994><EFBFBD><E6BBA2>唳旿摨橒<E691A8>
INSERT INTO redcap_projects (project_id, app_title)
VALUES (456, 'Test Project');
-- <20>?<3F>仿<EFBFBD>嚗䮝roject_language摮埈挾NOT NULL蝥行<E89DA5>憭梯揖
```
### 銝滚虾<E6BB9A><EFBFBD><EFBFBD><E689B9>?
| <20><>漣蝐餃<E89D90> | 憸𤑳<E686B8> | 敶勗<E695B6><E58B97><EFBFBD>凒 | <20><EFBFBD><E5A2A7>曉漲 | 憌𡡞埯蝑厩漣 |
|---------|------|---------|---------|---------|
| **憭抒<E686AD><E68A92><EFBFBD>蝥?* | 瘥誩僑3-4甈?| <20>𣞁 <20>券𢒰敶勗<E695B6> | <20>𣞁 <20>圈𠗕 | <20>𣞁<EFBFBD>𣞁<EFBFBD>𣞁<EFBFBD>𣞁<EFBFBD>𣞁 |
| **撠讐<E692A0><E8AE90>銝?* | 瘥𤩺<E798A5>1-2甈?| <20>椬 撅<><E69285>典蔣<E585B8>?| <20>椬 銝剔<E98A9D> | <20><EFBFBD><EFBFBD>椬 |
| **摰匧<E691B0>銵乩<E98AB5>** | 蝝扳<E89D9D><EFBFBD>撣?| <20>叚 頧餃凝敶勗<E695B6> | <20>叚 摰寞<E691B0> | <20><EFBFBD>叚 |
### 摨𥪜笆蝑𣇉裦嚗<E8A3A6><E59A97>雿𡡞<E99BBF><F0A1A19E><EFBFBD>
#### 蝑𣇉裦1嚗帋艇<E5B88B><EFBFBD><E6BD9B><EFBFBD>𧋦<EFBFBD><F0A78BA6><EFBFBD>
```json
// config.json銝剜<E98A9D>蝖桀ㄟ<E6A180>𤾸<EFBFBD>摰寧<E691B0><E5AFA7>?
{
"name": "AI Research Assistant",
"framework-version": 16,
"compatibility": {
"redcap-version-min": "15.8.0",
"redcap-version-max": "15.9.99",
"php-version-min": "7.4",
"php-version-max": "8.2"
}
}
```
```php
// <20>冽芋<E586BD><EFBFBD>憪见<E686AA><E8A781><EFBFBD><E59786><EFBFBD><E4BAA6>?
public function __construct() {
$redcapVersion = REDCAP_VERSION;
$minVersion = '15.8.0';
$maxVersion = '15.9.99';
if (version_compare($redcapVersion, $minVersion, '<') ||
version_compare($redcapVersion, $maxVersion, '>')) {
throw new Exception(
"甇斗芋<EFBFBD>𦯀<EFBFBD><EFBFBD><EFBFBD>REDCap {$minVersion} - {$maxVersion}嚗? .
"敶枏<EFBFBD><EFBFBD><EFBFBD>𧋦嚗㝯$redcapVersion}"
);
}
}
```
#### 蝑𣇉裦2嚗𡁏<E59A97>撠誩<E692A0><E8AAA9>湔𦻖靘肽<E99D98>
```php
// <20>?<3F>躰秤嚗𡁶凒<F0A181B6><EFBFBD>雿𨀣㺭<F0A880A3><EFBFBD>
$sql = "SELECT * FROM redcap_data WHERE project_id = $pid";
$result = db_query($sql);
// <20>?甇<>嚗帋蝙<E5B88B>沖EDCap撠<70><E692A0><EFBFBD><EFBFBD>PI
$data = REDCap::getData($pid, 'array');
```
**<EFBFBD><EFBFBD>**嚗?
- REDCap API隡𡁜<E99AA1><F0A1819C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>摰寞<E691B0>?
- <20>湔𦻖<E6B994><EFBFBD><E6BBA2>唳旿摨梶<E691A8><EFBFBD><E9A488>REDCap<61><70><EFBFBD><EFBFBD><EFBFBD>
#### 蝑𣇉裦3嚗𡁜<E59A97><F0A1819C><EFBFBD><EFBFBD><EFBFBD>𧼮<EFBFBD>瘚贝<E7989A>
```bash
# CI/CD Pipeline嚗<65><E59A97><E79488>蝥批<E89DA5>頝𡢅<E9A09D>
tests/
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> integration/
<EFBFBD>? <20><EFBFBD><E98EBF><EFBFBD> test_redcap_15.8.0.php # 敶枏<E695B6><E69E8F><EFBFBD>𧋦瘚贝<E7989A>
<EFBFBD>? <20><EFBFBD><E98EBF><EFBFBD> test_redcap_15.9.0.php # 憸<><E686B8>霂蓥<E99C82><EFBFBD><E98A9D><EFBFBD>𧋦
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD> test_redcap_16.0.0.php # 憸<><E686B8>霂閙𧊋<E99699><EFBFBD><E4BAA6>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> api/
<EFBFBD>? <20><EFBFBD><E98EBF><EFBFBD> test_export_records.php
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD> test_import_records.php
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> hooks/
<20><EFBFBD><E98EBF><EFBFBD> test_save_record.php
<20><EFBFBD><E5A999><EFBFBD> test_every_page_top.php
```
```php
// <20>芸𢆡<E88AB8>𡝗<EFBFBD>霂閧內靘?
class RedcapCompatibilityTest extends TestCase {
public function testSaveRecordHook() {
// 璅⊥<E79285>REDCap靚<70>鍂Hook
$result = $this->module->redcap_save_record(
123, 'PAT001', 'demographics', 1,
null, null, null, null
);
$this->assertNotNull($result);
$this->assertTrue($result['success']);
}
}
```
#### 蝑𣇉裦4嚗𡁜<E59A97>蝥折<E89DA5>蝳餌㴓憓?
```
<EFBFBD>煺漣<EFBFBD><EFBFBD>嚗㇌EDCap 15.8.0嚗?
<20>?
<EFBFBD><EFBFBD>鈭抒㴓憓<EFBFBD><EFBFBD>REDCap 15.9.0嚗争<EFBFBD> <20><><EFBFBD>蝥扳<E89DA5>霂?
<20>?
<EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD>REDCap 16.0.0嚗? <20>?<3F>𣂼<EFBFBD><F0A382BC><EFBFBD><EFBFBD>
```
**瘚<><E7989A>**嚗?
1. REDCap摰䀹䲮<E480B9><EFBFBD><E7A983><EFBFBD><E59581>?
2. <20><EFBFBD><E585B8>𤑳㴓憓<E3B493><E68693><EFBFBD>僎瘚贝<E7989A>嚗?<3F><EFBFBD>
3.<><E686B8>鈭抒㴓憓<E3B493><E68693><EFBFBD><E99C82>1<EFBFBD><EFBFBD>
4. <20>煺漣<E785BA><EFBFBD><E887AC><EFBFBD>漣嚗<E6BCA3><EFBFBD><EFBFBD><E98DA6><EFBFBD><E7AE87><EFBFBD><EFBFBD>
### 憌𡡞埯霂<E59FAF>
| <20><><EFBFBD> | 霂<>摯 | 霂湔<E99C82> |
|------|------|------|
| **銝滚虾<E6BB9A><EFBFBD>?* | <20>𣞁 <20><><EFBFBD> | REDCap<61><70><EFBFBD>園𡢿銝滨眏<E6BBA8>睲賑<E79DB2><EFBFBD> |
| **敶勗<E695B6><E58B97><EFBFBD>** | <20>𣞁 <20>券𢒰 | <20><EFBFBD><E888AA><EFBFBD><E6B8B8><EFBFBD><EFBFBD><EFBFBD><E58EB0>𣂼<EFBFBD><F0A382BC>?|
| **摨𥪜笆<F0A5AA9C>鞉𧋦** | <20>𣞁 擃?| 瘥𤩺活<F0A4A9BA><E6B4BB><EFBFBD><E6BCA3><EFBFBD><EFBFBD>1-2<><EFBFBD>霂?|
| **<EFBFBD><EFBFBD>蝏湔擪** | <20>𣞁 擃?| 蝏<>澈隡湧<E99AA1><E6B9A7><EFBFBD><EFBFBD><EFBFBD><E696B9>?|
---
## <20><20><><EFBFBD><EFBFBD><E88880>?嚗𡁏㺭<F0A1818F><EFBFBD><E6A190><EFBFBD><EFBFBD>"<22><><EFBFBD>?
### <20><EFBFBD><E6A185>讛膩
敶𣫮EDCap<EFBFBD>淾I撟喳蝱**<2A>峕𧒄**摮睃<E691AE><E79D83>唳旿<E594B3><EFBFBD>隡𡁻𢒰銝渡<E98A9D><E6B8A1><EFBFBD>**<2A><><EFBFBD>撘譍<E69298><E8AD8D><EFBFBD>折䔮憸?*<2A>?
### 銝<><E98A9D><EFBFBD>批㦤<E689B9><EFBFBD><E887AC>?
#### <20>箸艶1嚗𡁜<E59A97><F0A1819C><EFBFBD>甇亦<E79487><E4BAA6><EFBFBD>
```
<EFBFBD>園𡢿頧湛<EFBFBD>
T1: <20><EFBFBD>A<EFBFBD>沖EDCap靽格㺿<E6A0BC><E3BABF><EFBFBD><EFBFBD>AT001<30><31>僑樴<E58391>蛹45撗?
<20>?External Module<6C><EFBFBD><E588B8><EFBFBD>AI撟喳蝱
T2: <20><EFBFBD>B<EFBFBD>杗I撟喳蝱DC璅<E79285><EFBFBD><E79A9C><EFBFBD>唳旿嚗<E697BF><E59A97><EFBFBD>啣僑樴<E58391><E6A8B4>撣賂<E692A3>靽格㺿銝?6撗?
<20>?<3F>𧼮<EFBFBD><F0A7BCAE>訌EDCap嚗?
T3: REDCap銝剖僑樴<E58391><EFBFBD>冽糓嚗?5餈䀹糓46嚗?
<20>?憒<><E68692>瘝⊥<E7989D><E28AA5><EFBFBD><EFBFBD><E996AB><EFBFBD><EFBFBD>嚗峕㺭<E5B395><EFBFBD><EFBFBD><E98A9D><EFBFBD>
```
#### <20>箸艶2嚗𡁜<E59A97>甇亙辣餈笔紡<E7AC94><EFBFBD><E6B8A1>讛粉
```
T1: <20><EFBFBD><E586BD>沖EDCap敶訫<E695B6>摰峕㟲<E5B395><E39FB2><EFBFBD>嚗?0銝芾”<E88ABE>𤏪<EFBFBD>50銝芸<E98A9D>畾蛛<E795BE>
<20>?瘥譍葵摮埈挾靽嘥<E99DBD><E598A5><EFBFBD>閫血<E996AB>redcap_save_record
<20>?External Module<6C><EFBFBD>?0甈<E79488>AI撟喳蝱
T2: AI撟喳蝱<E596B3>交𤣰鈭<F0A4A3B0><E988AD>30銝芸<E98A9D>畾蛛<E795BE><E89B9B>?0銝芸<E98A9D>畾菔<E795BE><E88F94><EFBFBD>颲㮖葉
<20>?<3F><EFBFBD><E586BD>杗I撟喳蝱<E596B3><EFBFBD><E4BAA6><EFBFBD><EFBFBD>嚗𡁏遬蝷箔<E89DB7>摰峕㟲<E5B395>唳旿
<20>?<3F><EFBFBD>霂臭誑銝箸㺭<E7AEB8>桐腺憭梧<E686AD><E6A2A7>齿活敶訫<E695B6>
T3: <20>?0銝芸<E98A9D>畾萄<E795BE>颲橘<E9A2B2><EFBFBD><EFBFBD>瑕歇蝏誯<E89D8F>憭滚<E686AD><E6BB9A>?
<20>?<3F>唳旿<E594B3><EFBFBD>嚗?
```
#### <20>箸艶3嚗𡁶<E59A97>蝏𨀣<E89D8F><F0A880A3>𨅯紡<F0A885AF><EFBFBD><E6B8A1>唳旿銝
```
T1: <20><EFBFBD><E586BD>沖EDCap靽嘥<E99DBD><E598A5>唳旿
<20>?External Module<6C><EFBFBD><E588B8><EFBFBD>AI撟喳蝱
<20>?蝵𤑳<E89DB5><EFBFBD>𧒄嚗㇌EDCap<61>淾I撟喳蝱銋钅𡢿<E99285><F0A1A2BF><EFBFBD>蝏靝<E89D8F>蝔喳<E89D94>嚗?
T2: External Module<6C><EFBFBD><EFBFBD>𧒄<EFBFBD>躰秤
<20>?<3F>臬炏<E887AC><EFBFBD>嚗罸<E59A97>霂訫<E99C82>甈∴<E79488>
<20>?憒<><E68692><EFBFBD><EFBFBD>嚗䔶<E59A97>銝滢<E98A9D>撖潸稲<E6BDB8><EFBFBD><E6BB9A><EFBFBD>嚗?
T3: AI撟喳蝱<E596B3>唳旿蝻箏仃
<20>?<3F>𡒊賒<F0A1928A><E8B392><EFBFBD>蝏𤘪<E89D8F>銝滚<E98A9D>蝖?
```
### 銝<><E98A9D><EFBFBD><EFBFBD><EFBFBD><E99C82><EFBFBD>?
#### 蝑𣇉裦A嚗𡁜<E59A97>蝑㗇<E89D91>扯挽霈∴<E99C88>Idempotency嚗?
```typescript
// AI撟喳蝱Webhook<6F>交𤣰<E4BAA4><EFBFBD><EFBFBD><E6929F><EFBFBD><EFBFBD><EFBFBD><E99C82>
async function receiveRecordUpdate(req, res) {
const { project_id, record_id, data, timestamp } = req.body;
// <20><><EFBFBD><EFBFBD><E6929F><EFBFBD>免ey嚗<79>俈甇<E79487>憭滚<E686AD><E6BB9A><EFBFBD><EFBFBD>
const idempotencyKey = `${project_id}:${record_id}:${timestamp}`;
// 璉<><E79289>交糓<E4BAA4>血歇憭<E6AD87><E686AD>餈?
const existing = await prisma.redcapSyncRecord.findUnique({
where: { idempotencyKey }
});
if (existing) {
// 撌脣<E6928C><E884A3><EFBFBD><EFBFBD>嚗𣬚凒<F0A3AC9A><EFBFBD><E4BAA5><EFBFBD><E5A2A7>?
return res.send({
success: true,
message: '<27>唳旿撌脣<E6928C><E884A3><EFBFBD><EFBFBD><E6929F><EFBFBD><EFBFBD>'
});
}
// <20><EFBFBD><E7AC94><EFBFBD>雿頣<E99BBF><E9A0A3>𥕦遣<F0A595A6>峕郊霈啣<E99C88>+<2B>湔鰵<E6B994>唳旿
await prisma.$transaction(async (tx) => {
// 1. <20>𥕦遣<F0A595A6>峕郊霈啣<E99C88><EFBFBD><EFBFBD><EFBFBD>蝥行<E89DA5>嚗?
await tx.redcapSyncRecord.create({
data: {
idempotencyKey,
projectId: project_id,
recordId: record_id,
redcapData: data,
status: 'success',
syncedAt: new Date()
}
});
// 2. <20>湔鰵銝𡁜𦛚<F0A1819C>唳旿
await tx.patientData.upsert({
where: { recordId: record_id },
update: data,
create: data
});
});
return res.send({ success: true });
}
```
#### 蝑𣇉裦B嚗𡁶<E59A97><F0A181B6>砍噡<E7A08D><EFBFBD>嚗㇉ptimistic Locking嚗?
```typescript
// 瘥𤩺辺霈啣<E99C88><E595A3><EFBFBD><E8B3A3><EFBFBD>𧋦<EFBFBD>?
model PatientData {
recordId String @id
age Int
gender String
version Int @default(0) // <20><>𧋦<EFBFBD>?
updatedAt DateTime @updatedAt
@@index([version])
}
// <20>湔鰵<E6B994><EFBFBD><E59786><EFBFBD><E4BAA6>砍噡
async function updateRecord(recordId: string, newData: any, expectedVersion: number) {
const result = await prisma.patientData.updateMany({
where: {
recordId,
version: expectedVersion // <20><EFBFBD><E88AA3><EFBFBD>𧋦<EFBFBD>瑕龪<E79195>齿<EFBFBD><E9BDBF>湔鰵
},
data: {
...newData,
version: expectedVersion + 1 // <20><>𧋦<EFBFBD>?1
}
});
if (result.count === 0) {
// <20><>𧋦<EFBFBD><EFBFBD><E7919A><EFBFBD>嚗諹秩<E8ABB9><EFBFBD><E693A7><EFBFBD>
throw new ConflictError('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㺿<EFBFBD><EFBFBD>𡡞<EFBFBD>?);
}
}
```
#### 蝑𣇉裦C嚗𡁏<E59A97><EFBFBD><E89D8F><EFBFBD><EFBFBD>?+ <20><EFBFBD><E884A9><EFBFBD>
```typescript
// <20><EFBFBD><EFBFBD><E996AB>蝑𣇉裦嚗朞扇敶閙<E695B6><E99699><EFBFBD><EFBFBD><E89D92>鈭箏極鋆<E6A5B5><E98B86>
model DataConflict {
id String @id @default(cuid())
recordId String
fieldName String
redcapValue String // REDCap銝剔<E98A9D><E58994>?
aiPlatformValue String // AI撟喳蝱銝剔<E98A9D><E58994>?
redcapTimestamp DateTime // REDCap靽格㺿<E6A0BC>園𡢿
aiPlatformTimestamp DateTime // AI撟喳蝱靽格㺿<E6A0BC>園𡢿
status String // pending, resolved, ignored
resolution String? // 鈭箏極鋆<E6A5B5><E98B86>蝏𤘪<E89D8F>
resolvedBy String?
resolvedAt DateTime?
createdAt DateTime @default(now())
}
// 璉<>瘚见<E7989A>蝒?
async function detectConflict(recordId: string) {
const redcapData = await fetchFromRedcap(recordId);
const aiPlatformData = await fetchFromAIPlatform(recordId);
const conflicts = [];
for (const field of Object.keys(redcapData)) {
if (redcapData[field] !== aiPlatformData[field]) {
conflicts.push({
recordId,
fieldName: field,
redcapValue: redcapData[field],
aiPlatformValue: aiPlatformData[field],
redcapTimestamp: redcapData._timestamp,
aiPlatformTimestamp: aiPlatformData._timestamp
});
}
}
if (conflicts.length > 0) {
// 霈啣<E99C88><E595A3><EFBFBD>嚗𣬚<E59A97><EFBFBD>犖撌亙<E6928C><E4BA99>?
await prisma.dataConflict.createMany({ data: conflicts });
// <20><EFBFBD><E785BE><EFBFBD>霅阡<E99C85>𡁶䰻
await notifyAdmin('璉<>瘚见<E7989A><E8A781>唳旿<E594B3><EFBFBD>', { recordId, conflicts });
}
}
```
#### 蝑𣇉裦D嚗𡁜<E59A97><F0A1819C>睲蜓隞擧芋撘𧶏<E69298><F0A7B68F><EFBFBD>憭齿<E686AD>摨佗<E691A8>
```
<EFBFBD>㗇𥋘銝<EFBFBD>銝?銝餌頂蝏?嚗𠄎ource of Truth嚗㚁<E59A97>
<EFBFBD><EFBFBD>1嚗鑹EDCap銝箔蜓
- <20>唳旿敶訫<E695B6>嚗𡁜蘨<F0A1819C>沖EDCap銝剛<E98A9D>銵?
- AI撟喳蝱嚗𡁜蘨霂餅芋撘𧶏<E69298>銝滚<E98A9D>霈訾耨<E8A8BE><EFBFBD>憪𧢲㺭<F0A7A2B2>?
- AI憭<49><E686AD>蝏𤘪<E89D8F>嚗𡁜<E59A97><F0A1819C>典銁<E585B8>閧𡠺<E996A7><F0A1A0BA>”銝哨<E98A9D>銝滚<E98A9D><E6BB9A>筻EDCap
隡睃飵嚗?
<20>?銝<><E98A9D><EFBFBD>折䔮憸䀹<E686B8>憭?
<20>?<3F><EFBFBD><EFBFBD><E89D9E>?
<20>?<3F><EFBFBD>憟?
<20><>飵嚗?
<20>?AI撟喳蝱<E596B3><E89DB1><EFBFBD><EFBFBD>瘣㛖<E798A3><E39B96>𨀣<EFBFBD>瘜閗䌊<E99697><EFBFBD><E585B8>?
<20>?<3F><EFBFBD>雿㯄<E99BBF><E3AF84><EFBFBD><EFBFBD>舅銝芰頂蝏<E9A082><EFBFBD>𧼮<EFBFBD><F0A7BCAE><EFBFBD>
<EFBFBD><EFBFBD>2嚗鋫I撟喳蝱銝箔蜓
- <20>唳旿敶訫<E695B6>嚗𡁻<E59A97><EFBFBD>AI撟喳蝱<E596B3>屸𢒰嚗<F0A292B0><E59A97>撋朙EDCap iFrame<6D>䨝PI嚗?
- REDCap嚗帋<E59A97>銝箏<E98A9D><EFBFBD><E69285><EFBFBD><EFBFBD><E58981><EFBFBD>API<50><EFBFBD>
- 蝏煺<E89D8F><E785BA>杗I撟喳蝱憭<E89DB1><E686AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E58A90><EFBFBD><EFBFBD>
隡睃飵嚗?
<20>?<3F><EFBFBD>雿㯄<E99BBF>蝏煺<E89D8F>
<20>?<3F>臭誑<E887AD><E8AA91><EFBFBD><EFBFBD>拍鍂AI<41><EFBFBD>
<20><>飵嚗?
<20>?<3F><><EFBFBD><E996AC>撱摧EDCap<61><70><EFBFBD><EFBFBD>务I嚗<49>極雿𣈯<E99BBF>撌典之嚗?
<20>?憭勗縧REDCap<61><70><EFBFBD>閗挽霈膥蝑㗇瓲敹<E793B2><E695B9><EFBFBD>?
```
### 憌𡡞埯霂<E59FAF>
| <20><><EFBFBD> | 霂<>摯 | 霂湔<E99C82> |
|------|------|------|
| **憭齿<E686AD>摨?* | <20>𣞁 擃?| <20><><EFBFBD>撘譍<E69298><E8AD8D><EFBFBD>扳糓霈∠<E99C88><E288A0><EFBFBD>摮阡𠗕憸?|
| **<EFBFBD>舀綉<EFBFBD>?* | <20>椬 銝?| <20>臭誑霈曇恣蝑𣇉裦嚗䔶<E59A97><E494B6><EFBFBD>100%<25><EFBFBD> |
| **撘<><E69298><EFBFBD><E78390>?* | <20>椬 銝?| <20><>閬?-3<>刻挽霈?瘚贝<E7989A> |
| **<EFBFBD><EFBFBD>敶勗<EFBFBD>** | <20>椬 銝?| <20><EFBFBD><E888AA><EFBFBD><EFBFBD>犖撌乩<E6928C><E4B9A9>亥圾<E4BAA5><EFBFBD>蝒?|
**撱箄悅**嚗?
- <20>**隡睃<E99AA1><E79D83><EFBFBD><E588BB><EFBFBD>1嚗㇌EDCap銝箔蜓嚗<E89C93><E59A97><EFBFBD><EFBFBD>甇伐<E79487>**
- <20>𩤃<EFBFBD> <20><EFBFBD><E8B8B9><EFBFBD><EFBFBD>摰墧𧒄<E5A2A7>峕郊嚗<E9838A><E59A97><EFBFBD><EFBFBD><EFBFBD><E6BCB2><EFBFBD>嚗?
- <20><><><E68692><EFBFBD><EFBFBD><E29786><EFBFBD>嚗䔶蝙<E494B6>?*<2A><><EFBFBD><E89D8F><EFBFBD><EFBFBD>?鈭箏極摰⊥瓲**璅<E79285>
---
## <20><20><><EFBFBD><EFBFBD><E88880>?嚗鋫PI<50><EFBFBD>銝擧鸌<E693A7>𤩺<EFBFBD>雿𨀣<E99BBF><EFBFBD>
### <20><EFBFBD><E6A185>讛膩
REDCap API<50><EFBFBD><E58EB0><EFBFBD>**<2A><EFBFBD><E6AFBA>𣂼<EFBFBD>**嚗峕鸌<E5B395>𤩺<EFBFBD>雿𨀣𧒄摰寞<E691B0>閫血<E996AB><E8A180>?
### <20><EFBFBD><EFBFBD><E996AB><EFBFBD>𧊋<EFBFBD><EFBFBD><E7A08D><EFBFBD>﹝嚗?
```
<EFBFBD>寞旿蝷曉躹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>瘚页<EFBFBD>
- 瘥讐<E798A5>霂瑟<E99C82><E7919F><EFBFBD>QPS嚗㚁<E59A97>~10-50甈∴<E79488><E288B4><EFBFBD>鈭擧<E988AD><E693A7><E288AA>滨蔭嚗?
- <20>閙活撖澆枂霈啣<E99C88><E595A3><EFBFBD>撱箄悅<1000<30>?
- <20>閙活撖澆<E69296>霈啣<E99C88><E595A3><EFBFBD>撱箄悅<500<30>?
- 撟嗅<E6929F>餈墧𦻖<E5A2A7><EFBFBD>~5-10銝?
- 頞<>𧒄<EFBFBD>園𡢿嚗?0-60蝘?
<EFBFBD><EFBFBD>𣂼<EFBFBD>嚗?
- HTTP 429 (Too Many Requests)
- <20>𣇉凒<F0A38789><EFBFBD><E4BAA5><EFBFBD><E59786><EFBFBD>
```
### <20><EFBFBD><E7AC94>箸艶<E7AEB8><EFBFBD>
#### <20>箸艶1嚗𡁜<E59A97><F0A1819C><EFBFBD>甇?0銝<30>辺霈啣<E99C88>
```php
// <20>?<3F>躰秤<E8BAB0>𡁏<EFBFBD>嚗帋<E59A97>甈⊥<E79488>批紡<E689B9><EFBFBD><E7AE8F>?
$data = $redcapApi->exportRecords([
'format' => 'json',
'type' => 'flat'
]);
// 蝏𤘪<E89D8F>嚗朞<E59A97><E69C9E><EFBFBD><E5979A><EFBFBD>摮䀹滯<E480B9><EFBFBD><E7AE9D><EFBFBD><EFBFBD>膥撏拇<E6928F>
```
```php
// <20>?甇<><EFBFBD>𡁏<EFBFBD>嚗𡁜<E59A97>憿?<3F><EFBFBD>
function exportAllRecords($projectId, $batchSize = 500) {
$offset = 0;
$allData = [];
while (true) {
// <20><>鸌撖澆枂
$batch = $redcapApi->exportRecords([
'format' => 'json',
'records' => range($offset, $offset + $batchSize - 1)
]);
if (empty($batch)) break;
$allData = array_merge($allData, $batch);
$offset += $batchSize;
// <20><EFBFBD>嚗𡁏<E59A97><F0A1818F>寥𡢿<E5AFA5>?蝘?
sleep(2);
// 餈𥕦漲<F0A595A6><EFBFBD>
$progress = count($allData);
error_log("撌脣紡<EFBFBD>?{$progress} <20>∟扇敶?);
}
return $allData;
}
// 10銝<30>辺霈啣<E99C88> = 200<30>?<3F> 2蝘?= 6.7<EFBFBD><EFBFBD><EFBFBD>
```
#### <20>箸艶2嚗𡁜<E59A97><F0A1819C><EFBFBD>甇仿<E79487>憸穃<E686B8><E7A983>?
```
<EFBFBD>駁堺<EFBFBD>箸艶嚗?
- 20銝芰<E98A9D>蝛嗅𨭌<E59785><EFBFBD><E8A781><EFBFBD><E59785>交㺭<E4BAA4>?
- 瘥譍犖瘥誩<E798A5><E8AAA9><EFBFBD>摮?甈?
- <20>舔PS = 20 <20> 5 / 60 <20>?1.67甈?蝘?
<EFBFBD>贝絲<EFBFBD><EFBFBD>擃矋<EFBFBD><EFBFBD><EFBFBD>
- 瘥𤩺活靽嘥<E99DBD>閫血<E996AB>redcap_save_record Hook
- Hook靚<6B>鍂AI撟喳蝱API嚗<49><E59A97>埈𧒄500ms嚗?
- 憒<><E68692>Hook<6F><EFBFBD><E689AF>園𡢿>1蝘𡜐<E89D98>隡𡁻獈憛冚EDCap<61><EFBFBD>
- <20><EFBFBD><E586BD><EFBFBD>"<22>⊿▼"
```
**閫<><E996AB><EFBFBD><EFBFBD>嚗𡁜<E59A97>甇亙<E79487>**
```php
// <20>?<3F>躰秤嚗𡁜<E59A97>甇亥<E79487><E4BAA5><EFBFBD><E58981><EFBFBD>嚗?
function redcap_save_record($project_id, $record, ...) {
$data = REDCap::getData($project_id, 'array', $record);
// <20>峕郊HTTP霂瑟<E99C82><EFBFBD>獈憛?-5蝘𡜐<E89D98>
$this->apiClient->post('/webhook/records', $data);
}
// <20>?甇<>嚗𡁜<E59A97>甇仿<E79487><E4BBBF>?
function redcap_save_record($project_id, $record, ...) {
// 蝡见朖餈𥪜<E9A488>嚗䔶<E59A97><E494B6><EFBFBD>
$this->enqueueSync($project_id, $record);
}
function enqueueSync($project_id, $record) {
// <20><EFBFBD><E59D94>砍𧑐<E7A08D><EFBFBD>銵?
db_query("INSERT INTO em_sync_queue (project_id, record, status)
VALUES (?, ?, 'pending')", [$project_id, $record]);
}
// Cron隞餃𦛚瘥誩<E798A5><E8AAA9><EFBFBD><E7AC94><EFBFBD><EFBFBD><EFBFBD>?
function processSyncQueue() {
$queue = db_query("SELECT * FROM em_sync_queue
WHERE status = 'pending'
LIMIT 100");
foreach ($queue as $item) {
try {
$data = REDCap::getData($item['project_id'], 'array', $item['record']);
$this->apiClient->post('/webhook/records', $data);
// <20><><EFBFBD>𣂼<EFBFBD>
db_query("UPDATE em_sync_queue SET status = 'success'
WHERE id = ?", [$item['id']]);
} catch (Exception $e) {
// <20><>扇憭梯揖
db_query("UPDATE em_sync_queue SET status = 'failed', error = ?
WHERE id = ?", [$e->getMessage(), $item['id']]);
}
// <20><EFBFBD>
usleep(500000); // 500ms
}
}
```
### 憌𡡞埯霂<E59FAF>
| <20><><EFBFBD> | 霂<>摯 | 霂湔<E99C82> |
|------|------|------|
| **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** | <20>椬 銝?| 憭扳㺭<E689B3><EFBFBD><E6A185><EFBFBD><E59786>?|
| **<EFBFBD>舀綉<EFBFBD>?* | <20>?<3F>舀綉 | <20><EFBFBD><EFBFBD><E69C9E><EFBFBD>鸌+<2B><EFBFBD><EFBFBD><E996AB> |
| **撘<><E69298><EFBFBD><E78390>?* | <20>叚 雿?| 1-2憭拙<E686AD><E68B99>?|
| **<EFBFBD><EFBFBD>敶勗<EFBFBD>** | <20>叚 雿?| <20><EFBFBD><E586BD><EFBFBD><E4ADBE><EFBFBD><EFBFBD>郊憭<E9838A><E686AD>嚗?|
---
## <20>𣞁 <20><><EFBFBD><EFBFBD><E88880>?嚗鍃xternal Module獢<65><EFBFBD><E6B2B2><EFBFBD><EFBFBD>?
### <20><EFBFBD><E6A185>讛膩
External Module獢<65><EFBFBD><EFBFBD>撘箏之嚗䔶<E59A97><E494B6>?*銝滚虾<E6BB9A><EFBFBD><E69B87><EFBFBD><EFBFBD>?*<2A>?
### <20>𣂼<EFBFBD><EFBFBD><E79A9C>
#### <20>𣂼<EFBFBD>1嚗𡁏<E59A97>瘜蓥耨<E893A5>鄗EDCap<61><EFBFBD><E8A9A8>屸𢒰
```php
// <20>?<3F><EFBFBD><E4ADBE>𡁜<EFBFBD>嚗𡁜<E59A97><F0A1819C>冽𤜯<E586BD>㎞EDCap<61><70><EFBFBD><EFBFBD><E6A180><EFBFBD><E4BAA6>?
// <20><EFBFBD><E88ABE><EFBFBD>JavaScript瘜典<E7989C><E585B8>?憓𧼮撩"嚗峕<E59A97>瘜?<3F>踵揢"
function redcap_every_page_top($project_id) {
?>
<script>
// <20><EFBFBD>靽格㺿DOM嚗峕<E59A97>瘜閙𤜯<E99699>㟲銝芷△<E88AB7>?
$('#data_entry_form').append('<div>AI<41><EFBFBD></div>');
</script>
<?php
}
```
**敶勗<E695B6>**嚗?
- <20>?<3F><EFBFBD>摰䂿緵"摰<><E691B0>摰𡁜<E691B0><F0A1819C>?<3F><>I
- <20>𩤃<EFBFBD> <20><EFBFBD>鈭竃EDCap<61><EFBFBD><E6AFBA>屸𢒰<E5B1B8><F0A292B0><EFBFBD><EFBFBD><E69285>峕甅撘?
- <20>𩤃<EFBFBD> REDCap<61>屸𢒰<E5B1B8><F0A292B0><EFBFBD><EFBFBD><E888AA><EFBFBD><E6B8B8>睲賑<E79DB2><E8B391>OM<4F><EFBFBD>
#### <20>𣂼<EFBFBD>2嚗𡁏<E59A97>瘜閗挪<E99697><EFBFBD>鈭𥟇瓲敹<E793B2><EFBFBD>?
```php
// <20>?<3F>𣂷<EFBFBD>REDCap<61><70><EFBFBD><EFBFBD>賣㺭<E8B3A3><EFBFBD><E88890><EFBFBD>嚗袏xternal Module<6C><EFBFBD><EFBFBD>
// 靘见<E99D98>嚗鋽ataQuality蝐餌<E89D90><E9A48C>𣂷<EFBFBD><F0A382B7><EFBFBD>
// REDCap<61><EFBFBD><EFBFBD><E99A9E><EFBFBD><E59A97>瘜閗挪<E99697><EFBFBD>
namespace REDCap\Internal;
class DataQuality {
private function executeRule($ruleId) {
// External Module<6C><EFBFBD><EFBFBD>鍂甇斗䲮瘜?
}
}
```
#### <20>𣂼<EFBFBD>3嚗𡁏<E59A97><EFBFBD><EFBFBD><E69298><EFBFBD>
```php
// External Module<6C><65>ook隡𡁜<E99AA1><F0A1819C>𣳇<EFBFBD>憭硋<E686AD><E7A18B><EFBFBD>
function redcap_every_page_top($project_id) {
// 餈嗘葵<E59798>賣㺭<E8B3A3><EFBFBD>銝芷△<E88AB7><EFBFBD><EFBD81><EFBFBD>
// 憒<><E68692><EFBFBD><EFBFBD>憭齿<E686AD>嚗䔶<E59A97><E494B6>𡝗<EFBFBD>憿菟𢒰<E88F9F>㰘蝸
}
// 瘚贝<E7989A>蝏𤘪<E89D8F>嚗?
// - 蝛慵ook嚗?5-10ms
// - <20>㗇㺭<E39787><EFBFBD><E6A180>亥砭<E4BAA5><E7A0AD>ook嚗?50-200ms
// - <20>鵎TTP霂瑟<E99C82><E7919F><EFBFBD>ook嚗?500-2000ms
```
**蝏栞捏**嚗?
- <20>𩤃<EFBFBD> 銝滩<E98A9D><E6BBA9>沈ook銝剜<E98A9D>銵諹<E98AB5>埈𧒄<E59F88><EFBFBD>
- <20>?敹<>◆撘<E29786><EFBFBD>?
#### <20>𣂼<EFBFBD>4嚗𡁜<E59A97><F0A1819C><EFBFBD>蝞?
```php
// <20>?External Module餈鞱<E9A488><E99EB1><EFBFBD><E585B8>鞟㴓憓<E3B493>
// <20><EFBFBD>霈輸䔮嚗?
// - REDCap摰㕑<E691B0><E39591><EFBFBD>憭𣇉<E686AD><F0A38789><EFBFBD>
// - <20>𣂷<EFBFBD>蝟餌<E89D9F><E9A48C>賣㺭嚗Ềxec<65><63>hell_exec蝑㚁<E89D91>
// - <20>湔𦻖<E6B994><EFBFBD>PHP隡朞<E99AA1>
```
### 摨𥪜笆蝑𣇉裦
**蝑𣇉裦1嚗𡁏𥅾<F0A1818F><EFBFBD><E6A2A2><EFBFBD><E5A19A>刻器<E588BB><E599A8><EFBFBD><EFBFBD>𥟇鰵**
- <20><><EFBFBD><EFBFBD>拍鍂Hook<6F><EFBFBD>
- <20><EFBFBD>JavaScript憓𧼮撩UI嚗<49><E59A97><EFBFBD>舀𤜯<E88880><EFBFBD>
- 雿輻鍂API雿靝蛹"<22><><EFBFBD><EFBFBD>?
**蝑𣇉裦2嚗𡁏毽<F0A1818F><E6AFBD><EFBFBD>?*
```
REDCap (<28>唳旿敶訫<E695B6>) + AI撟喳蝱 (<28><><EFBFBD>撅閧內)
<20>?
<EFBFBD><EFBFBD><EFBFBD>沖EDCap敶訫<EFBFBD> <20>?<3F>唳旿<E594B3>峕郊 <20>?<3F>杗I撟喳蝱<E596B3><EFBFBD><E4BAA6><EFBFBD><EFBFBD>蝏𤘪<E89D8F>
```
餈蹱甅<EFBFBD>臭誑嚗?
- <20>?<3F>拍鍂REDCap<61><70><EFBFBD>閗挽霈膥嚗<E886A5>撩憭改<E686AD>
- <20>?<3F>拍鍂AI撟喳蝱<E596B3><E89DB1><EFBFBD><EFBFBD><EFBFBD><E99EB1>𨥈<EFBFBD><F0A8A588>菜暑嚗?
- <20>?閫<><E996AB>External Module<6C><65><EFBFBD><EFBFBD>?
---
## <20>𣞁 <20><><EFBFBD><EFBFBD><E88880>?嚗𡁜<E59A97><F0A1819C><EFBFBD><EFBFBD><E996AB><EFBFBD>HIPAA/GDPR嚗?
### <20><EFBFBD><E6A185>讛膩
REDCap<EFBFBD>𡁜虜摮睃<EFBFBD>**PHI嚗㇊rotected Health Information嚗匧<E59A97>靽脲擪<E884B2>亙熒靽⊥<E99DBD>**嚗<><EFBFBD>交𧒄<E4BAA4><F0A79284><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E79899>擃塩<E69383>?
### <20><><EFBFBD><EFBFBD><E996AC>
#### HIPAA閬<41><E996AC><EFBFBD><E59A97><EFBFBD><EFBFBD>
```
1. 霈輸䔮<E8BCB8><EFBFBD>嚗㇁ccess Control嚗?
- <20><EFBFBD>霈方<E99C88><EFBFBD>撩撖<E692A9><E69296>+2FA嚗?
- <20><>撠𤩺<E692A0><F0A4A9BA>𣂼<EFBFBD><F0A382BC>?
- 摰∟恣<E2889F><EFBFBD><EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5979A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E98A8B>
2. <20>唳旿<E594B3><EFBFBD>嚗𠄌ncryption嚗?
- 隡㰘<E99AA1><E3B098><EFBFBD>嚗関LS 1.2+
- <20><EFBFBD><E8B9B1><EFBFBD><EFBFBD><E69296>AES-256
- 撖<>𤨎蝞∠<E89D9E>嚗𡁜<E59A97><F0A1819C>蠘蔭<E8A098>?
3. <20>唳旿摰峕㟲<E5B395><EFBFBD>Integrity嚗?
- <20>脩砥<E884A9><EFBFBD><E5B08D><EFBFBD>蝑曉<E89D91>
- <20><>𧋦<EFBFBD><EFBFBD>嚗𡁏<E59A97><F0A1818F>劐耨<E58A90>孵虾餈賣滲
4. 摰∟恣<E2889F><EFBFBD>嚗㇁udit Logs嚗?
- 靽嘥<E99DBD><E598A5><EFBFBD>6撟?
- 銝滚虾<E6BB9A>𣳇膄
- 摰𡁏<E691B0>摰⊥䰻
```
### 瞏𨅯銁憌𡡞埯<F0A1A19E>?
#### 憌𡡞埯1嚗𡁏㺭<F0A1818F><EFBFBD><E6A0BC><EFBFBD>隡㰘<E99AA1><EFBFBD><E9A488>嚗?
```typescript
// <20>?<3F>躰秤嚗䥅TTP隡㰘<E99AA1><EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD>
const response = await fetch('http://ai-platform.com/api/webhook', {
method: 'POST',
body: JSON.stringify(patientData) // PHI<48><EFBFBD>隡㰘<E99AA1>嚗?
});
// <20>?甇<>嚗䥅TTPS + TLS 1.3
const response = await fetch('https://ai-platform.com/api/webhook', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': encryptedApiKey,
'X-Signature': hmacSignature
},
body: JSON.stringify(patientData)
});
// <20>?<3F><EFBFBD><EFBFBD>甇伐<E79487>蝡臬<E89DA1>蝡臬<E89DA1>撖?
const encryptedPayload = await encrypt(patientData, publicKey);
await fetch('https://ai-platform.com/api/webhook', {
method: 'POST',
body: encryptedPayload
});
```
#### 憌𡡞埯2嚗𡁏𠯫敹埈<E695B9><E59F88>?
```php
// <20>?<3F>躰秤嚗䥪HI霈啣<E99C88><E595A3>冽𠯫敹𦯀葉
$this->log("<EFBFBD><EFBFBD><EFBFBD>?撘牐<E69298> <20><>僑樴<E58391>蛹 45 撗?);
// 餈肽<E9A488><EFBFBD>𠯫敹𦯀葉銝滩<E98A9D><E6BBA9><EFBFBD>鉄PHI
// <20>?甇<>嚗朞<E59A97><E69C9E><EFBFBD>霈啣<E99C88>
$this->log("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>扇敶閙凒<EFBFBD>?, [
'record_id' => hash('sha256', $record), // <20><><EFBFBD><EFBFBD>?
'field_count' => count($data),
'timestamp' => time()
]);
```
#### 憌𡡞埯3嚗鋫PI Token瘜<6E>
```php
// <20>?<3F>躰秤嚗𡁏<E59A97><F0A1818F><EFBFBD><EFBFBD><EFBFBD>杗PI Token
$apiToken = 'ABC123DEF456...'; // 摮睃<E691AE><E79D83>其誨<E585B6><E8AAA8>
// <20>?<3F>躰秤嚗𡁏<E59A97><F0A1818F><EFBFBD><EFBFBD><EFBFBD>典銁<E585B8>唳旿摨?
INSERT INTO settings (key, value)
VALUES ('api_token', 'ABC123DEF456...');
// <20>?甇<>嚗𡁜<E59A97><EFBFBD><E69296><EFBFBD>?
$encrypted = openssl_encrypt(
$apiToken,
'AES-256-CBC',
$encryptionKey,
0,
$iv
);
INSERT INTO settings (key, value, iv)
VALUES ('api_token', $encrypted, $iv);
```
### <20><><EFBFBD><EFBFBD>鞉𧋦
| <20><><EFBFBD><EFBFBD><E996AC> | 摰墧鴌<E5A2A7>曉漲 | 撘<><E69298><EFBFBD><E78390>?| 摰∟恣<E2889F>鞉𧋦 | <20><EFBFBD><E9A485>?|
|---------|---------|---------|---------|--------|
| **霈輸䔮<E8BCB8><EFBFBD>** | <20>椬 銝?| 1-2<>?| 瘥誩僑1甈?| $$$ |
| **<EFBFBD>唳旿<EFBFBD><EFBFBD>** | <20>椬 銝?| 2-3<>?| 瘥誩僑1甈?| $$$ |
| **摰∟恣<E2889F><EFBFBD>** | <20>叚 雿?| 3-5憭?| 瘥誩僑2甈?| $$ |
| **摰匧<E691B0><EFBFBD>** | <20>𣞁 擃?| 4-6<>?| 瘥誩僑1甈?| $$$$ |
| **蝚砌<E89D9A><E7A08C>孵恣霈?* | <20>𣞁 擃?| N/A | 瘥誩僑1甈?| $$$$$ |
| **<EFBFBD>餉恣** | <20>𣞁 擃?| **2-3銝芣<E98A9D>** | **<EFBFBD><EFBFBD>賒** | **$10K-50K/撟?* |
---
## <20><> 憭齿<E686AD>摨血笆瘥䈑<E798A5>REDCap撖寞𦻖 vs <20><EFBFBD>EDC
### 摰𡁻<E691B0><F0A181BB><EFBFBD><EFBFBD>
| 蝏游漲 | REDCap撖寞𦻖 | <20><EFBFBD>EDC | 撖寞<E69296> |
|------|-----------|---------|------|
| **撘<><E69298>穃𪂹<E7A983>?* | 2-3銝芣<E98A9D> | 6-12銝芣<E98A9D> | <20>叚 REDCap敹?-5<>?|
| **撘<><E69298><EFBFBD><E78390>?* | $50K-100K | $300K-500K | <20>叚 REDCap<61>?200K+ |
| **蝏湔擪<E6B994>鞉𧋦/撟?* | $30K-50K | $50K-80K | <20>椬 REDCap<61><EFBFBD> |
| **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>箏𦛚** | <20>𣞁 擃矋<E69383>靘肽<E99D98>REDCap<61><70>漣嚗?| <20>叚 雿𠬍<E99BBF><EFBFBD><E691B0><EFBFBD>芯蜓嚗?| <20>𣞁 REDCap憌𡡞埯擃?|
| **<EFBFBD>菜暑<EFBFBD>?* | <20>椬 銝哨<E98A9D><E593A8>㜬M獢<4D><EFBFBD>𣂼<EFBFBD>嚗?| <20>叚 擃矋<E69383><EFBFBD><E691B0><EFBFBD>芰眏嚗?| <20>𣞁 REDCap<61><EFBFBD> |
| **<EFBFBD><EFBFBD>摰峕㟲<EFBFBD>?* | <20>叚 擃矋<E69383>REDCap<61><EFBFBD>嚗?| <20>椬 銝哨<E98A9D><E593A8><EFBFBD>隞𡡞妟撘<E5A69F><E69298>𡢅<EFBFBD> | <20>叚 REDCap隡睃飵 |
| **AI<41><49><EFBFBD>摨?* | <20>椬 銝哨<E98A9D><E593A8><EFBFBD>獢交𦻖嚗?| <20>叚 擃矋<E69383><E79F8B><EFBFBD><E6AFBA><EFBFBD><EFBFBD>嚗?| <20>𣞁 REDCap暻餌<E69ABB> |
| **<EFBFBD><EFBFBD>雿㯄<EFBFBD>** | <20>椬 銝哨<E98A9D>銝文<E98A9D>蝟餌<E89D9F>嚗?| <20>叚 擃矋<E69383>蝏煺<E89D8F>雿㯄<E99BBF>嚗?| <20>𣞁 REDCap<61><EFBFBD> |
### <20><EFBFBD><EFBFBD>
```
REDCap撖寞𦻖<EFBFBD><EFBFBD>OI<EFBFBD><EFBFBD><EFBFBD>嚗?
<EFBFBD>鞉𧋦嚗?
- 撘<><E69298>𡢅<EFBFBD>$80K
- 撟渡輕<E6B8A1><EFBFBD>$40K
- 5撟湔<E6929F><EFBFBD><E9A485>穿<EFBFBD>$280K
<EFBFBD><EFBFBD>嚗?
- <20><><EFBFBD><EFBFBD><E69298>烐𧒄<E78390><EFBFBD>9銝芣<E98A9D><EFBFBD>𣪧<EFBFBD>笔虾銝𤘪釣AI<41><EFBFBD>嚗?
- <20>拍鍂REDCap<61><EFBFBD><E99E9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵典<E98AB5>霈曇恣<E69B87><EFBFBD><E585B7><EFBFBD><EFBFBD>鞟恣<E99E9F><E681A3><EFBFBD><EFBFBD>恣霈⊥𠯫敹?
- 敹恍<E695B9><EFBFBD><EFBFBD><E692A3>2-3銝芣<E98A9D> vs 12銝芣<E98A9D>
憌𡡞埯嚗?
- <20><><EFBFBD><EFBFBD>箏𦛚嚗帋<E59A97>韏餸EDCap
- <20><EFBFBD>雿㯄<E99BBF>嚗𡁜<E59A97>蝟餌<E89D9F><E9A48C><EFBFBD>
- <20><EFBFBD><E689AF><EFBFBD>嚗鍃AV璅<E79285>
蝏栞捏嚗?
<EFBFBD>?憒<><E68692><EFBFBD><EFBFBD><E6A0BC>?敹恍<E695B9><EFBFBD><EFBFBD><E99C82><EFBFBD>?嚗朙EDCap撖寞𦻖<E5AF9E><EFBFBD><E88880><EFBFBD>㗇𥋘
<EFBFBD>?憒<><E68692><EFBFBD><EFBFBD><E6A0BC>?<3F><EFBFBD>鈭批<E988AD>蝡硺<E89DA1><E7A1BA>?嚗諹䌊<E8ABB9>漋DC<44>游末
<EFBFBD><20><EFBFBD>蝑𣇉裦嚗𡁜<E59A97><F0A1819C>沖EDCap撖寞𦻖敹恍<E695B9>𠵱VP嚗<50><E59A97><EFBFBD><EFBFBD><EFBFBD><E99C82><EFBFBD>滩䌊<E6BBA9>?
```
---
## <20><20><><EFBFBD>遣霈桐<E99C88><E6A190><EFBFBD><E5969F>?
### <20><EFBFBD><E5969F>?
```
Q1: <20>臬炏撌脫<E6928C>REDCap<61><EFBFBD><E586BD><EFBFBD>嚗?
<20><EFBFBD> <20>?<3F>?撘箇<E69298><E7AE87><EFBFBD>撖寞𦻖嚗<F0A6BB96><EFBFBD><EFBFBD>蝘餅<E89D98><E9A485><EFBFBD>嚗?
<20><EFBFBD> <20>?<3F>?蝏抒賒Q2
Q2: <20>臬炏<E887AC><E7828F><EFBFBD>銁6銝芣<E98A9D><E88AA3><EFBFBD><EFBFBD><EFBFBD><E692A3>
<20><EFBFBD> <20>?<3F>?<3F><EFBFBD>撖寞𦻖嚗<F0A6BB96><E59A97><EFBFBD><EFBFBD>笔漲敹恬<E695B9>
<20><EFBFBD> <20>?<3F>?蝏抒賒Q3
Q3: <20>臬炏<E887AC><E7828F><EFBFBD><E996AC><EFBFBD><EFBFBD><E6B8A1><EFBFBD>雿㯄<E99BBF><E3AF84>峕楛摨再I<E5868D><49><EFBFBD>嚗?
<20><EFBFBD> <20>?<3F>?<3F><EFBFBD><E588BB><EFBFBD><EFBFBD><E59A97>撉峕凒憟踝<E6869F>
<20><EFBFBD> <20>?<3F>?<3F><EFBFBD>撖寞𦻖
Q4: <20><><EFBFBD>臬𣪧<E887AC><F0A3AAA7><EFBFBD><EFBFBD>PHP + REDCap蝏誯<E89D8F>嚗?
<20><EFBFBD> <20>?<3F>?撖寞𦻖憌𡡞埯<F0A1A19E><EFBFBD>
<20><EFBFBD> <20>?<3F>?摮虫<E691AE><E899AB>鞉𧋦+2<>?
Q5: <20>臬炏<E887AC>賣𦻖<E8B3A3>妔EDCap<61><70>漣撣行䔉<E8A18C><E49489><EFBFBD>毺輕<E6AFBA><EFBFBD><E69697>穿<EFBFBD>
<20><EFBFBD> <20>?<3F>?<3F>臭誑撖寞𦻖
<20><EFBFBD> <20>?<3F>?銝齿綫<E9BDBF>𣂼笆<F0A382BC>?
```
### 銝厩<E98A9D>蝑𣇉裦
#### 蝑𣇉裦1嚗帋<E59A97><EFBFBD><E691B0><EFBFBD><EFBFBD><E4BC90><EFBFBD>嚗?
```
<EFBFBD>嗆挾1嚗?-3銝芣<E98A9D>嚗㚁<E59A97>REDCap撖寞𦻖MVP
- 摰䂿緵<E482BF><EFBFBD><E7AE87>唳旿<E594B3>峕郊
- <20><><EFBFBD>DC璅<E79285><EFBFBD><EFBFBD><EFBFBD>瘣梹<E798A3>
- <20><EFBFBD>嚗𡁻<E59A97><EFBFBD><E99C82><EFBFBD><EFBFBD>瘙?
<EFBFBD>嗆挾2嚗?-6銝芣<E98A9D>嚗㚁<E59A97>瘛勗漲<E58B97><E6BCB2><EFBFBD>
- <20><><EFBFBD>SSA璅<E79285><EFBFBD><E59A97><E99C88><E288AA><EFBFBD>
- 隡睃<E99AA1><E79D83><EFBFBD><E689AF>𣬚鍂<F0A3AC9A><EFBFBD>撉?
- <20><EFBFBD>嚗𡁶妖蝝舐鍂<E88890><EFBFBD><E79195>唳旿
<EFBFBD>嗆挾3嚗?-18銝芣<E98A9D>嚗㚁<E59A97><EFBFBD><EFBFBD><EFBFBD>
- <20>寞旿<E5AF9E><EFBFBD><E586BD><EFBFBD><E6BCA4><EFBFBD><E596B3>臬炏<E887AC><EFBFBD>EDC
- 憒<><E68692><EFBFBD>㦤撉諹<E69289><E8ABB9>𣂼<EFBFBD><EFBFBD><EFBFBD>刻䌊<E588BB>?
- <20><EFBFBD>嚗𡁻鵭<F0A181BB><EFBFBD>鈭匧<E988AD>
隡睃飵嚗?
<EFBFBD>?憌𡡞埯<F0A1A19E>舀綉嚗<E7B689><E59A97><EFBFBD>嗆挾<E59786><EFBFBD>嚗?
<EFBFBD>?韏<><E99F8F>擃䀹<E69383><EFBFBD><E59A97>瘚芾晶<E88ABE><EFBFBD>蝖桀<E89D96><E6A180><EFBFBD><EFBFBD><EFBFBD>嚗?
<EFBFBD>?敹恍<E695B9><EFBFBD><EFBFBD><E99C82>3銝芣<E98A9D><EFBFBD><E996AB><EFBFBD><EFBFBD>
```
#### 蝑𣇉裦2嚗𡁏<E59A97>餈𤤿<E9A488><F0A4A4BF><EFBFBD>銝齿綫<E9BDBF><EFBFBD>
```
<EFBFBD>湔𦻖<EFBFBD><EFBFBD><EFBFBD><EFBFBD>EDC嚗?-12銝芣<E98A9D>嚗?
憌𡡞埯嚗?
<EFBFBD>?撣<><EFBFBD><E3A6A4><EFBFBD>𧊋撉諹<E69289>
<EFBFBD>?蝡𧼮<E89DA1><F0A7BCAE><EFBFBD><E888AA><EFBFBD>
<EFBFBD>?韏<><E99F8F><EFBFBD><EFBFBD>憭?
```
#### 蝑𣇉裦3嚗𡁏毽<F0A1818F><E6AFBD><EFBFBD><EFBFBD><EFBFBD><E4BC90>䀝葉嚗?
```
<EFBFBD>峕𧒄餈𥡝<EFBFBD>嚗?
- 撠誩𣪧<E8AAA9><F0A3AAA7><EFBFBD>2鈭綽<E988AD>撖寞𦻖REDCap嚗<70><EFBFBD>𠵱VP嚗?
- 憭批𣪧<E689B9><F0A3AAA7><EFBFBD>5鈭綽<E988AD><E7B6BD><EFBFBD>EDC嚗<43><EFBFBD>煺漣<E785BA><E6BCA3><EFBFBD>
<EFBFBD><EFBFBD>嚗?
- REDCap皛∟雲<E2889F><EFBFBD><E691B0>
- <20><EFBFBD>EDC雿靝蛹<E99D9D><E89BB9>漣頝臬<E9A09D>
憌𡡞埯嚗?
<EFBFBD>𩤃<EFBFBD><><E99F8F><EFBFBD><EFBFBD>
<EFBFBD>𩤃<EFBFBD> 銝文<E98A9D>蝟餌<E89D9F>蝏湔擪<E6B994>鞉𧋦擃?
```
---
## <20><> 憌𡡞埯<F0A1A19E>拚猐<E68B9A><EFBFBD>
| 憌𡡞埯憿?| 敶勗<E695B6>蝔见漲 | <20>𤑳<EFBFBD><EFBFBD><E79281> | 隡睃<E99AA1>蝥?| 蝻栞圾<E6A09E>芣鴌 |
|-------|---------|---------|--------|---------|
| **EAV<41><EFBFBD><E689AF><EFBFBD>** | <20>𣞁 擃?| <20>𣞁 擃?| P0 | 霈曇恣蝻枏<E89DBB>撅?+ <20><EFBFBD><EFBFBD>㦛 |
| **<EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** | <20>𣞁 擃?| <20>椬 銝?| P0 | <20><>𧋦<EFBFBD><F0A78BA6><EFBFBD> + <20>𧼮<EFBFBD>瘚贝<E7989A> |
| **<EFBFBD>唳旿銝<EFBFBD><EFBFBD><EFBFBD>?* | <20>椬 銝?| <20>椬 銝?| P1 | <20><EFBFBD><E8A8AB>峕郊 + 撟<><E6929F><EFBFBD>扯挽霈?|
| **API<50><EFBFBD>** | <20>椬 銝?| <20>椬 銝?| P2 | <20><>鸌憭<E9B88C><E686AD> + <20><EFBFBD> |
| **EM獢<4D><EFBFBD>𣂼<EFBFBD>** | <20>椬 銝?| <20>叚 雿?| P3 | 瘛瑕<E7989B><E79195><EFBFBD>嚗㇌EDCap + AI撟喳蝱嚗?|
| **摰匧<E691B0><E58CA7><EFBFBD><EFBFBD>** | <20>𣞁 擃?| <20>叚 雿?| P0 | <20><EFBFBD> + 摰∟恣 + <20><><EFBFBD>霈方<E99C88> |
| **蝏湔擪<E6B994>鞉𧋦** | <20>椬 銝?| <20>𣞁 擃?| P1 | 蝏<>遣銝㮖<E98A9D><E3AE96><EFBFBD> |
---
## <20>𤁗 <20><><EFBFBD><E89D8F>霈?
### 蝑娍<E89D91><E5A88D><EFBFBD><E587BD><EFBFBD>
**Q: 銝竃EDCap撖寞𦻖<E5AF9E><EFBFBD><EFBFBD><E98A8B><EFBFBD><EFBFBD>**
A: **7憭扳<E686AD><E689B3><EFBFBD><E88880>?*嚗<><E59A97>銝?銝芣糓擃㗛<E69383><E3979B><EFBFBD>EAV<41><EFBFBD><E689AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝥扼<E89DA5><E689BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E996AB>
**Q: 銝滚虾<E6BB9A><EFBFBD><E68A92>唳䲮嚗?*
A: **REDCap<61><70>𧋦<EFBFBD><F0A78BA6>**<EFBFBD><EFBFBD>銝滚虾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>撟?-4甈∴<E79488><E288B4><EFBFBD><E888AA><EFBFBD><E6B8B8><EFBFBD><EFBFBD>嚗?
**Q: <20><><EFBFBD>舫𠗕<E888AB><EFBFBD>**
A: **EAV璅<E79285><E288AA><EFBFBD><EFBFBD><EFBFBD>隡睃<E99AA1>**<EFBFBD>?*<2A><><EFBFBD>撘𤩺㺭<F0A4A9BA><EFBFBD><E6A190><EFBFBD>?*<2A><EFBFBD>憭折𠗕<E68A98>?
**Q: 憭齿<E686AD><E9BDBF><EFBFBD><E68A98><EFBFBD>**
A: **銝剔<E98A9D><E58994><EFBFBD>憭齿<E686AD>摨?*嚗?/5嚗?
- 瘥磰䌊<E7A3B0>漋DC蝞<43><E89D9E>𤏪<EFBFBD>REDCap<61><EFBFBD>鈭?0%撌乩<E6928C>嚗?
- 瘥𥪜<E798A5>蝥涉PI<50><49><EFBFBD>憭齿<E686AD><EFBFBD><E59A97><EFBFBD><E686AD><EFBFBD><E98A9D><EFBFBD><EFBFBD><E689BC><EFBFBD><EFBFBD><E689AF><EFBFBD><EFBFBD>蝥抒<E89DA5><E68A92><EFBFBD>嚗?
### <20>𤑳<EFBFBD>撱箄悅
**<EFBFBD><20><EFBFBD><E588BB><EFBFBD>嚗𡁜<E59A97><F0A1819C>嗆挾蝑𣇉裦**
```
Phase 1 (0-2銝芣<E98A9D>): <20><EFBFBD><E888AA><EFBFBD>霂?
- <20>剖遣REDCap瘚贝<E7989A><E8B49D><EFBFBD>
- 撘<><E69298><EFBFBD>撠㛁xternal Module嚗<65><EFBFBD>𡁜<EFBFBD><F0A1819C><EFBFBD>甇伐<E79487>
- 瘚贝<E7989A>EAV<41><EFBFBD><E689AF><EFBFBD><EFBFBD>鍂10銝<30><EFBFBD><EFBFBD><E7AC94>唳旿嚗?
- 霂<>摯嚗𡁏糓<F0A1818F>衣誧蝏哨<E89D8F>
Phase 2 (2-3銝芣<E98A9D>): MVP撘<50><E69298>?
- <20>芸笆<E88AB8>主C璅<E79285><EFBFBD><E59A97><EFBFBD>劐遠<E58A90><EFBFBD>
- <20><EFBFBD><E8A8AB>峕郊嚗㇌EDCap <20>?AI嚗?
- 銝滩<E98A9D><E6BBA9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>摰墧𧒄
- <20><EFBFBD>嚗?-10銝芾<E98A9D><E88ABE>孵恥<E5ADB5>?
Phase 3 (3-6銝芣<E98A9D>): <20>寞旿<E5AF9E><EFBFBD><E6BCA4><EFBFBD>
- 憒<><E68692><E691B0><EFBCB8><EFBFBD>憟?<3F>?瘛勗漲<E58B97><E6BCB2><EFBFBD>
- 憒<><E68692><EFBFBD><EFBFBD><E689AF><EFBFBD><E59C92>擧遬 <20>?<3F><><EFBFBD><EFBFBD><EFBFBD>
- 憒<><E68692>蝏湔擪<E6B994>鞉𧋦憭芷<E686AD> <20>?頧砍<E9A0A7><E7A08D><EFBFBD>
```
**<EFBFBD><20>喲睸撱箄悅**嚗?
1. <20>?銝滩<E98A9D><EFBFBD><EFBFBD>憪见停餈賣<E9A488>"摰𣬚<E691B0>撖寞𦻖"
2. <20>?<3F><><EFBFBD><E98D82><EFBFBD><E89D9E>閙䲮獢<E4B2AE><E78DA2><EFBFBD><E99C82><EFBFBD><E79899><EFBFBD><EFBFBD><E8A8AB>峕郊頞喳<E9A09E>嚗?
3. <20>?<3F>𣂼<EFBFBD><EFBFBD><E996AB>"<22><><EFBFBD><EFBFBD><E7AE87>?嚗<><E59A97><EFBFBD>𨅯笆<F0A885AF>亙仃韐伐<E99F90><EFBFBD><E68692><EFBFBD><EFBFBD><EFBFBD>啗䌊<E59597><EFBFBD>
4. <20>𩤃<EFBFBD><><EFBFBD>侨HP + REDCap蝏誯<E89D8F><E8AAAF><EFBFBD>𣪧<EFBFBD><F0A3AAA7><EFBFBD><EFBFBD><EFBFBD>1鈭綽<E988AD>
5. <20>𩤃<EFBFBD><><E686B8>20-30%<25><>𧒄<EFBFBD><EFBFBD>撖?<3F><EFBFBD>"嚗<><E59A97><EFBFBD><EFBFBD>蝥扼<E89DA5><E689BC>ug嚗?
---
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𧋦**嚗鯝1.0
**<EFBFBD><EFBFBD><EFBFBD>擧凒<EFBFBD>?*嚗?025-12-30
**銝𧢲活霂<E6B4BB>恣**嚗䥪hase 1摰峕<E691B0><E5B395>𠬍<EFBFBD>2銝芣<E98A9D>嚗?
---
**<EFBFBD>辶 霈唬<E99C88>嚗𡁏<E59A97><F0A1818F><EFBFBD><EFBFBD>瘝⊥<E7989D>摰𣬚<E691B0><F0A3AC9A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E58EB0><EFBFBD>敶枏<E695B6><E69E8F>嗆挾<E59786><E68CBE>䲮獢<E4B2AE><E78DA2>?*