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%)
32 KiB
REDCap撖寞𦻖憌𡡞埯霂<EFBFBD>摯銝擧<EFBFBD><EFBFBD>舀<EFBFBD><EFBFBD>䀹楛摨血<EFBFBD><EFBFBD>?
<EFBFBD><EFBFBD>﹝<EFBFBD><EFBFBD>𧋦嚗? v1.0
<EFBFBD>𥕦遣<EFBFBD>交<EFBFBD>嚗? 2025-12-30
<EFBFBD><EFBFBD>﹝<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>? <EFBFBD><EFBFBD>粉<EFBFBD>園𡢿嚗? 20<32><30><EFBFBD>
<EFBFBD>滩<EFBFBD><EFBFBD>改<EFBFBD> 潃鐥<E6BD83>潃鐥<E6BD83>潃?<EFBFBD>嗆<EFBFBD><EFBFBD>喟<EFBFBD>敹<EFBFBD>粉
<EFBFBD><EFBFBD> <20><>﹝霂湔<E99C82>
<EFBFBD>祆<EFBFBD>獢<EFBFBD><EFBFBD><EFBFBD>?<EFBFBD><EFBFBD><EFBFBD><EFBFBD>萘輕<EFBFBD>屸<EFBFBD><EFBFBD>拐<EFBFBD><EFBFBD>?<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞉䲮瘜𤏪<EFBFBD>霂<EFBFBD><EFBFBD>REDCap撖寞𦻖憿寧𤌍<EFBFBD><EFBFBD><EFBFBD>
- **<2A><><EFBFBD>舫𠗕<E888AB>?*嚗?憭扳瓲敹<E793B2>𠗕憸矋<E686B8>
- **銝滚虾<E6BB9A>批<EFBFBD>蝝?*嚗?銝芷<E98A9D><E88AB7>㘾<EFBFBD><E398BE>抬<EFBFBD>
- **憭齿<E686AD>摨西<E691A8>隡?*嚗<><E59A97><EFBFBD>芰<EFBFBD>EDC撖寞<E69296>嚗?
- **憭梯揖獢<E68F96><E78DA2><EFBFBD><EFBFBD><EFBFBD>**嚗<><E59A97><EFBFBD>諹萱<E8ABB9>𤑳<EFBFBD>撉䕘<E69289>
- 閫<EFBFBD><EFBFBD>蝑𣇉裦嚗<EFBFBD><EFBFBD>雿閖<EFBFBD>雿𡡞<EFBFBD><EFBFBD>抬<EFBFBD>
**<2A>詨<EFBFBD><E8A9A8>桅<EFBFBD>**嚗?
- <EFBFBD>?REDCap<61><70>AV璅∪<E79285><E288AA>臬炏隡𡁏<E99AA1>銝箸<E98A9D>扯<EFBFBD><E689AF>園<EFBFBD>嚗?
- <EFBFBD>?External Module獢<65>沲<EFBFBD><E6B2B2><EFBFBD><EFBFBD>嗆<EFBFBD>憭𡁜之嚗?
- <EFBFBD>?<3F><>𧋦<EFBFBD><F0A78BA6>漣隡帋<E99AA1>隡𡁶聦<F0A181B6>𤩺<EFBFBD>隞祉<E99A9E><E7A589><EFBFBD><EFBFBD>嚗?
- <EFBFBD>?<3F>唳旿銝<E697BF><E98A9D>湔<EFBFBD>批<EFBFBD>雿蓥<E99BBF>霂<EFBFBD><E99C82>
- <EFBFBD>?<3F>臬炏<E887AC>澆<EFBFBD><E6BE86>訫<EFBFBD>嚗㇌OI<4F><49><EFBFBD>嚗㚁<E59A97>
<EFBFBD>辶 <20>詨<EFBFBD>憌𡡞埯璁<E59FAF><E79281>嚗<EFBFBD>滯<EFBFBD>航郎<E888AA>𠺪<EFBFBD>
憌𡡞埯蝑厩漣<EFBFBD><EFBFBD>掩
| 憌𡡞埯蝐餃<EFBFBD> | 憌𡡞埯蝑厩漣 | 敶勗<EFBFBD><EFBFBD><EFBFBD>凒 | <EFBFBD>舀綉<EFBFBD>? | 撱箄悅 |
|---|---|---|---|---|
| EAV璅∪<EFBFBD><EFBFBD>扯<EFBFBD> | <EFBFBD>𣞁 擃? | <EFBFBD>唳旿<EFBFBD>?10銝<30>辺<EFBFBD>? | <EFBFBD>𩤃<EFBFBD> <20>典<EFBFBD><E585B8>舀綉 | 敹<EFBFBD>◆霈曇恣蝻枏<EFBFBD><EFBFBD>諹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? |
| *REDCap<EFBFBD><EFBFBD>漣<EFBFBD>澆捆<EFBFBD>? | <EFBFBD>𣞁 擃? | 瘥𤩺活REDCap<EFBFBD><EFBFBD>漣 | <EFBFBD>?銝滚虾<E6BB9A>? | 銝交聢<EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD><EFBFBD>+<2B>𧼮<EFBFBD>瘚贝<E7989A> |
| *<EFBFBD>唳旿銝<EFBFBD><EFBFBD>湔<EFBFBD>? | <EFBFBD>椬 銝? | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>峕郊<EFBFBD>箸艶 | <EFBFBD>?<3F>舀綉 | 霈曇恣撟<EFBFBD><EFBFBD><EFBFBD>?<3F>脩<EFBFBD>閫<EFBFBD><E996AB><EFBFBD>箏<EFBFBD> |
| API<EFBFBD>鞉<EFBFBD> | <EFBFBD>椬 銝? | <EFBFBD>寥<EFBFBD><EFBFBD>滢<EFBFBD> | <EFBFBD>?<3F>舀綉 | 摰䂿緵<EFBFBD>毺<EFBFBD><EFBFBD>𣂼<EFBFBD><EFBFBD>峕鸌憭<EFBFBD><EFBFBD> |
| 摰匧<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>𣞁 擃? | PHI<EFBFBD>唳旿瘜<EFBFBD>蠧 | <EFBFBD>?<3F>舀綉 | 銝交聢摰∟恣+<2B>惩<EFBFBD>+HIPAA<41><41><EFBFBD> |
| 蝏湔擪<EFBFBD>鞉𧋦 | <EFBFBD>椬 銝? | <EFBFBD>踵<EFBFBD>餈鞱𨯫 | <EFBFBD>𩤃<EFBFBD> <20>典<EFBFBD><E585B8>舀綉 | 蝏<EFBFBD>遣銝㮖<EFBFBD><EFBFBD>a<EFBFBD> |
| *<EFBFBD>冽<EFBFBD><EFBFBD>亙<EFBFBD>摨? | <EFBFBD>叚 雿? | <EFBFBD>冽<EFBFBD><EFBFBD>寡悌 | <EFBFBD>?<3F>舀綉 | 皜鞱<EFBFBD>撘𤩺綫撟? |
<EFBFBD>𣞁 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗鍃AV璅∪<E79285><E288AA><EFBFBD><EFBFBD>扯<EFBFBD>瘛望<E7989B>
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
REDCap雿輻鍂Entity-Attribute-Value (EAV) 璅∪<E79285>摮睃<E691AE><E79D83>唳旿嚗諹<E59A97><E8ABB9>舀<EFBFBD>憭抒<E686AD><E68A92><EFBFBD><EFBFBD>舀<EFBFBD><E88880>塩<EFBFBD>?
REDCap<EFBFBD><EFBFBD>㺭<EFBFBD>桀<EFBFBD><EFBFBD>冽䲮撘?
-- 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>?*嚗?
-- 隡删<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 |
<EFBFBD>扯<EFBFBD><EFBFBD>桅<EFBFBD>嚗<EFBFBD><EFBFBD>摰𧼮㦤<EFBFBD>荔<EFBFBD>
<EFBFBD>箸艶1嚗𡁏䰻霂W<EFBFBD>銝芣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>摰峕㟲<EFBFBD>唳旿
-- 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>
<EFBFBD>箸艶2嚗𡁏鸌<EFBFBD>誩紡<EFBFBD>?000銝芣<E98A9D><E88AA3>?
-- 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
<EFBFBD>箸艶3嚗𡁶<EFBFBD>霈∪<EFBFBD><EFBFBD>鞉䰻霂?
-- <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>拍鍂蝝W<E89D9D>
-- <20>扯<EFBFBD><E689AF>園𡢿嚗?0銝<30><E98A9D><EFBFBD><EFBFBD><EFBFBD>嚗?-30蝘?
撖農I撟喳蝱<EFBFBD><EFBFBD>蔣<EFBFBD>?
-
**DC璅∪<E79285>嚗<EFBFBD>㺭<EFBFBD>格<EFBFBD>瘣梹<E798A3>**嚗?
- <EFBFBD>?<3F>䭾<EFBFBD><E4ADBE>湔𦻖撖遂AV<41>唳旿<E594B3>𡁶<EFBFBD>霈∪<E99C88><E288AA>?
- <EFBFBD>?瘥𤩺活皜<E6B4BB><E79A9C><EFBFBD>賡<EFBFBD>閬<EFBFBD><E996AC>"<22>匧像"<22>唳旿嚗𠄌TL餈<4C><E9A488>嚗?
- <EFBFBD>梧<EFBFBD> 1000<30>∟扇敶閧<E695B6>皜<EFBFBD><E79A9C>嚗<EFBFBD>虾<EFBFBD>賡<EFBFBD>閬?-10<31><30><EFBFBD>憸<EFBFBD><E686B8><EFBFBD>?
-
**SSA璅∪<E79285>嚗<EFBFBD><E59A97>霈∪<E99C88><E288AA>琜<EFBFBD>**嚗?
- <EFBFBD>?R/Python<6F>𡁏𧋦<F0A1818F>䭾<EFBFBD><E4ADBE>湔𦻖<E6B994>滢<EFBFBD>EAV銵?
- <EFBFBD>?敹<>◆<EFBFBD><E29786>蓮<EFBFBD>V蛹DataFrame<6D>澆<EFBFBD>
- <EFBFBD>𩤃<EFBFBD> <20><><EFBFBD>瘨<EFBFBD><E798A8>堒楊憭改<E686AD>10銝<30>扇敶𨰝<E695B6>2-5GB嚗?
-
摰墧𧒄<EFBFBD>峕郊嚗?
- <EFBFBD>?瘥𤩺活靽嘥<E99DBD><E598A5>質圻<E8B3AA>穃<EFBFBD><E7A983>渲扇敶閙䰻霂g<E99C82><EFBD87>g<EFBFBD>
- <EFBFBD>𩤃<EFBFBD> 擃㗛<E69383>敶訫<E695B6><E8A8AB>箸艶銝衤<E98A9D><E8A1A4>硋𡆇<E7A18B>唳旿摨?
閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD>虾<EFBFBD>改<EFBFBD>
蝑𣇉裦A嚗𡁶<EFBFBD><EFBFBD>𤥁<EFBFBD><EFBFBD>?+ 摰𡁏𧒄<F0A1818F>瑟鰵
-- <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;
**<2A>桅<EFBFBD>**嚗?
- <EFBFBD>𩤃<EFBFBD> <20>唳旿撱嗉<E692B1>嚗<EFBFBD><E59A97>憭?撠𤩺𧒄嚗?
- <EFBFBD>𩤃<EFBFBD> 摮睃<E691AE>蝛粹𡢿蝧餃<E89DA7>?
- <EFBFBD>𩤃<EFBFBD> <20>瑟鰵餈<E9B0B5><E9A488>隡𡁻<E99AA1>銵?
蝑𣇉裦B嚗鋫I撟喳蝱靘抒<EFBFBD>摮?
// <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>芣䰻霂W<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);
}
隡睃飵嚗?
- <EFBFBD>?<3F>亥砭<E4BAA5>笔漲敹恬<E695B9>PostgreSQL JSONB蝝W<E89D9D>嚗?
- <EFBFBD>?<3F>誩<EFBFBD>REDCap<61>唳旿摨枏<E691A8><E69E8F>?
- <EFBFBD>?<3F>舀<EFBFBD><E88880>冽<EFBFBD><E586BD>𦦵揣<F0A6A6B5><E68FA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>皛?
**<2A>桅<EFBFBD>**嚗?
- <EFBFBD>𩤃<EFBFBD> <20>唳旿<E594B3>𦯀<EFBFBD>嚗<EFBFBD><E59A97><EFBFBD>函蕃<E587BD>㵪<EFBFBD>
- <EFBFBD>𩤃<EFBFBD> <20>峕郊撱嗉<E692B1>嚗?-30蝘𡜐<E89D98>
- <EFBFBD>𩤃<EFBFBD> 蝏湔擪憭齿<E686AD>摨血<E691A8><E8A180>?
蝑𣇉裦C嚗鑹EDCap API<50>孵<EFBFBD><E5ADB5><EFBFBD><EFBFBD><EFBFBD>?
// 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;
}
憌𡡞埯霂<EFBFBD>摯
| <EFBFBD><EFBFBD><EFBFBD> | 霂<EFBFBD>摯 | 霂湔<EFBFBD> |
|---|---|---|
| <EFBFBD>扯<EFBFBD><EFBFBD>園<EFBFBD> | <EFBFBD>𣞁 擃㗛<E69383><E3979B>? | <EFBFBD>唳旿<EFBFBD>?5銝<35>辺<EFBFBD>嗆<EFBFBD><E59786>? |
| *<EFBFBD>航圾<EFBFBD>單<EFBFBD>? | <EFBFBD>椬 <20>典<EFBFBD> | <EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝻枏<EFBFBD><EFBFBD>嗆<EFBFBD> |
| *撘<EFBFBD><EFBFBD>烐<EFBFBD><EFBFBD>? | <EFBFBD>𣞁 擃? | <EFBFBD><EFBFBD><EFBFBD>訫<EFBFBD>2-3<>刻挽霈∠<E99C88>摮睃<E691AE> |
| 餈鞟輕<EFBFBD>鞉𧋦 | <EFBFBD>椬 銝? | <EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>批<EFBFBD>甇亙辣餈? |
<EFBFBD>𣞁 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗鑹EDCap<61><70>𧋦<EFBFBD><F0A78BA6>漣<EFBFBD>?<3F>游<EFBFBD><E6B8B8>?
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
REDCap<EFBFBD>?*敹恍<E695B9>蠘翮隞?*嚗<><E59A97>撟?-4銝芸之<E88AB8><E4B98B>𧋦嚗劐<E59A97>撣行䔉<E8A18C>澆捆<E6BE86>批埯璇艾<E79287>?
<EFBFBD>笔<EFBFBD>獢<EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD>瘜芣<EFBFBD>霈哨<EFBFBD>
獢<EFBFBD><EFBFBD>1嚗䥅ook<EFBFBD>賣㺭蝑曉<EFBFBD><EFBFBD>䀹凒
// 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>**嚗?
- <EFBFBD>?<3F><><EFBFBD>劐<EFBFBD>韏𡝗迨Hook<6F><6B>xternal Module<6C>券<EFBFBD>撏拇<E6928F>
- <EFBFBD>梧<EFBFBD> <20><>閬<EFBFBD>揮<EFBFBD>乩耨憭滚僎瘚贝<E7989A>
- <EFBFBD><EFBFBD> 憒<><E68692>瘝⊥<E7989D>銝交聢<E4BAA4><E881A2><EFBFBD><EFBFBD>祇<EFBFBD>摰𡄯<E691B0><F0A184AF>煺漣<E785BA>臬<EFBFBD><E887AC>湔𦻖<E6B994><F0A6BB96><EFBFBD>
獢<EFBFBD><EFBFBD>2嚗鋫PI<EFBFBD>滚<EFBFBD><EFBFBD>澆<EFBFBD><EFBFBD>䀹凒
// 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>g<EFBFBD>
{
"record_id": "PAT001",
"age": 45, // <20>䀹<EFBFBD><E480B9>湔㺭蝐餃<E89D90>
"gender": "1" // 隞齿糓摮㛖泵銝?
}
**敶勗<E695B6>**嚗?
- <EFBFBD>?蝐餃<E89D90><E9A483>剛<EFBFBD>憭梯揖嚗㇍ypeScript銝交聢璅∪<E79285>嚗?
- <EFBFBD>?<3F>唳旿撉諹<E69289><E8ABB9>餉<EFBFBD>憭望<E686AD>
- <EFBFBD><EFBFBD> <20>鞱𤪖<E99EB1><F0A4AA96>ug嚗?0" vs 0 撣<><E692A3><EFBFBD>斗鱏<E69697>桅<EFBFBD>嚗?
獢<EFBFBD><EFBFBD>3嚗𡁏㺭<EFBFBD>桀<EFBFBD>銵函<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
-- 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>憭梯揖
銝滚虾<EFBFBD>扳<EFBFBD>批<EFBFBD><EFBFBD>?
| <EFBFBD><EFBFBD>漣蝐餃<EFBFBD> | 憸𤑳<EFBFBD> | 敶勗<EFBFBD><EFBFBD><EFBFBD>凒 | <EFBFBD>墧<EFBFBD><EFBFBD>曉漲 | 憌𡡞埯蝑厩漣 |
|---|---|---|---|---|
| *憭抒<EFBFBD><EFBFBD>砍<EFBFBD>蝥? | 瘥誩僑3-4甈? | <EFBFBD>𣞁 <20>券𢒰敶勗<E695B6> | <EFBFBD>𣞁 <20>圈𠗕 | <EFBFBD>𣞁<EFBFBD>𣞁<EFBFBD>𣞁<EFBFBD>𣞁<EFBFBD>𣞁 |
| *撠讐<EFBFBD><EFBFBD>祈‘銝? | 瘥𤩺<EFBFBD>1-2甈? | <EFBFBD>椬 撅<><E69285>典蔣<E585B8>? | <EFBFBD>椬 銝剔<E98A9D> | <EFBFBD>椬<EFBFBD>椬<EFBFBD>椬 |
| 摰匧<EFBFBD>銵乩<EFBFBD> | 蝝扳<EFBFBD>亙<EFBFBD>撣? | <EFBFBD>叚 頧餃凝敶勗<E695B6> | <EFBFBD>叚 摰寞<E691B0> | <EFBFBD>叚<EFBFBD>叚 |
摨𥪜笆蝑𣇉裦嚗<EFBFBD><EFBFBD>雿𡡞<EFBFBD><EFBFBD>抬<EFBFBD>
蝑𣇉裦1嚗帋艇<EFBFBD>潛<EFBFBD><EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD><EFBFBD>
// 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"
}
}
// <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(
"甇斗芋<E69697>𦯀<EFBFBD><F0A6AF80>舀<EFBFBD>REDCap {$minVersion} - {$maxVersion}嚗? .
"敶枏<EFBFBD><EFBFBD><EFBFBD>𧋦嚗㝯$redcapVersion}"
);
}
}
蝑𣇉裦2嚗𡁏<EFBFBD>撠誩<EFBFBD><EFBFBD>湔𦻖靘肽<EFBFBD>
// <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');
**<2A>笔<EFBFBD>**嚗?
- REDCap API隡𡁜<E99AA1><F0A1819C><EFBFBD><EFBFBD><EFBFBD>砍<EFBFBD>摰寞<E691B0>?
- <EFBFBD>湔𦻖<EFBFBD>滢<EFBFBD><EFBFBD>唳旿摨梶<EFBFBD>餈<EFBFBD><EFBFBD>REDCap<EFBFBD><EFBFBD><EFBFBD><EFBFBD>文<EFBFBD>
蝑𣇉裦3嚗𡁜<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𧼮<EFBFBD>瘚贝<EFBFBD>
# CI/CD Pipeline嚗<65><E59A97>甈∪<E79488>蝥批<E89DA5>頝𡢅<E9A09D>
tests/
<0A>鎿<EFBFBD><E98EBF><EFBFBD> integration/
<0A>? <20>鎿<EFBFBD><E98EBF><EFBFBD> test_redcap_15.8.0.php # 敶枏<E695B6><E69E8F><EFBFBD>𧋦瘚贝<E7989A>
<0A>? <20>鎿<EFBFBD><E98EBF><EFBFBD> test_redcap_15.9.0.php # 憸<><E686B8>霂蓥<E99C82>銝<EFBFBD><E98A9D><EFBFBD>𧋦
<0A>? <20>婙<EFBFBD><E5A999><EFBFBD> test_redcap_16.0.0.php # 憸<><E686B8>霂閙𧊋<E99699>亦<EFBFBD><E4BAA6>?
<0A>鎿<EFBFBD><E98EBF><EFBFBD> api/
<0A>? <20>鎿<EFBFBD><E98EBF><EFBFBD> test_export_records.php
<0A>? <20>婙<EFBFBD><E5A999><EFBFBD> test_import_records.php
<0A>婙<EFBFBD><E5A999><EFBFBD> hooks/
<20>鎿<EFBFBD><E98EBF><EFBFBD> test_save_record.php
<20>婙<EFBFBD><E5A999><EFBFBD> test_every_page_top.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嚗𡁜<EFBFBD>蝥折<EFBFBD>蝳餌㴓憓?
<EFBFBD>煺漣<EFBFBD>臬<EFBFBD>嚗㇌EDCap 15.8.0嚗?
<20>?
憸<><E686B8>鈭抒㴓憓<E3B493><E68693>REDCap 15.9.0嚗争<EFBFBD> <20><><EFBFBD>蝥扳<E89DA5>霂?
<20>?
撘<><E69298>𤑳㴓憓<E3B493><E68693>REDCap 16.0.0嚗? <20>?<3F>𣂼<EFBFBD><F0A382BC><EFBFBD><EFBFBD>
**瘚<><E7989A>**嚗?
- REDCap摰䀹䲮<EFBFBD>穃<EFBFBD><EFBFBD>啁<EFBFBD><EFBFBD>?
- <EFBFBD>典<EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD>鋆<EFBFBD>僎瘚贝<EFBFBD>嚗?<3F>剁<EFBFBD>
- 憸<EFBFBD><EFBFBD>鈭抒㴓憓<EFBFBD><EFBFBD>霂<EFBFBD><EFBFBD>1<EFBFBD>剁<EFBFBD>
- <EFBFBD>煺漣<EFBFBD>臬<EFBFBD><EFBFBD><EFBFBD>漣嚗<EFBFBD>恣<EFBFBD>鍦<EFBFBD><EFBFBD>箇<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
憌𡡞埯霂<EFBFBD>摯
| <EFBFBD><EFBFBD><EFBFBD> | 霂<EFBFBD>摯 | 霂湔<EFBFBD> |
|---|---|---|
| *銝滚虾<EFBFBD>扳<EFBFBD>? | <EFBFBD>𣞁 <20><><EFBFBD> | REDCap<EFBFBD><EFBFBD>漣<EFBFBD>園𡢿銝滨眏<EFBFBD>睲賑<EFBFBD>喳<EFBFBD> |
| 敶勗<EFBFBD><EFBFBD><EFBFBD>凒 | <EFBFBD>𣞁 <20>券𢒰 | <EFBFBD>航<EFBFBD><EFBFBD>游<EFBFBD><EFBFBD><EFBFBD><EFBFBD>厰<EFBFBD><EFBFBD>𣂼<EFBFBD><EFBFBD>? |
| 摨𥪜笆<EFBFBD>鞉𧋦 | <EFBFBD>𣞁 擃? | 瘥𤩺活<EFBFBD><EFBFBD>漣<EFBFBD><EFBFBD><EFBFBD>訫<EFBFBD>1-2<>冽<EFBFBD>霂? |
| <EFBFBD>踵<EFBFBD>蝏湔擪 | <EFBFBD>𣞁 擃? | 蝏<EFBFBD>澈隡湧<EFBFBD><EFBFBD><EFBFBD>輕<EFBFBD>方<EFBFBD><EFBFBD>? |
<EFBFBD>椬 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗𡁏㺭<F0A1818F>桐<EFBFBD><E6A190>湔<EFBFBD>抒<EFBFBD>"<22><>仍<EFBFBD>?
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
敶𣫮EDCap<EFBFBD>淾I撟喳蝱**<2A>峕𧒄摮睃<EFBFBD><EFBFBD>唳旿<EFBFBD>塚<EFBFBD>隡𡁻𢒰銝渡<EFBFBD><EFBFBD>貊<EFBFBD><EFBFBD><EFBFBD><EFBFBD>撘譍<EFBFBD><EFBFBD>湔<EFBFBD>折䔮憸?*<2A>?
銝<EFBFBD><EFBFBD>湔<EFBFBD>批㦤<EFBFBD>臬<EFBFBD><EFBFBD>?
<EFBFBD>箸艶1嚗𡁜<EFBFBD><EFBFBD>穃<EFBFBD>甇亦<EFBFBD><EFBFBD>脩<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>
<EFBFBD>箸艶2嚗𡁜<EFBFBD>甇亙辣餈笔紡<EFBFBD>渡<EFBFBD><EFBFBD>讛粉
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>嚗?
<EFBFBD>箸艶3嚗𡁶<EFBFBD>蝏𨀣<EFBFBD><EFBFBD>𨅯紡<EFBFBD>渡<EFBFBD><EFBFBD>唳旿銝W仃
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>蝖?
銝<EFBFBD><EFBFBD>湔<EFBFBD>找<EFBFBD>霂<EFBFBD><EFBFBD><EFBFBD>?
蝑𣇉裦A嚗𡁜<EFBFBD>蝑㗇<EFBFBD>扯挽霈∴<EFBFBD>Idempotency嚗?
// 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>俈甇a<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嚗𡁶<EFBFBD><EFBFBD>砍噡<EFBFBD>箏<EFBFBD>嚗㇉ptimistic Locking嚗?
// 瘥𤩺辺霈啣<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('<27>唳旿撌脰◤<E884B0>嗡<EFBFBD><E597A1>冽<EFBFBD>靽格㺿嚗諹窈<E8ABB9>瑟鰵<E7919F>𡡞<EFBFBD>霂?);
}
}
蝑𣇉裦C嚗𡁏<EFBFBD>蝏<EFBFBD><EFBFBD><EFBFBD>湔<EFBFBD>?+ <20>脩<EFBFBD><E884A9>亙<EFBFBD>
// <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嚗𡁜<EFBFBD><EFBFBD>睲蜓隞擧芋撘𧶏<EFBFBD><EFBFBD>滢<EFBFBD>憭齿<EFBFBD>摨佗<EFBFBD>
<EFBFBD>㗇𥋘銝<EFBFBD>銝?銝餌頂蝏?嚗𠄎ource of Truth嚗㚁<E59A97>
<0A>寞<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>g<EFBFBD>
<0A>寞<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>?
憌𡡞埯霂<EFBFBD>摯
| <EFBFBD><EFBFBD><EFBFBD> | 霂<EFBFBD>摯 | 霂湔<EFBFBD> |
|---|---|---|
| *憭齿<EFBFBD>摨? | <EFBFBD>𣞁 擃? | <EFBFBD><EFBFBD><EFBFBD>撘譍<EFBFBD><EFBFBD>湔<EFBFBD>扳糓霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮阡𠗕憸? |
| *<EFBFBD>舀綉<EFBFBD>? | <EFBFBD>椬 銝? | <EFBFBD>臭誑霈曇恣蝑𣇉裦嚗䔶<EFBFBD><EFBFBD>䭾<EFBFBD>100%<25>踹<EFBFBD> |
| *撘<EFBFBD><EFBFBD>烐<EFBFBD><EFBFBD>? | <EFBFBD>椬 銝? | <EFBFBD><EFBFBD>閬?-3<>刻挽霈?瘚贝<E7989A> |
| <EFBFBD>冽<EFBFBD>敶勗<EFBFBD> | <EFBFBD>椬 銝? | <EFBFBD>航<EFBFBD><EFBFBD><EFBFBD>閬<EFBFBD>犖撌乩<EFBFBD><EFBFBD>亥圾<EFBFBD>喳<EFBFBD>蝒? |
撱箄悅嚗?
- <EFBFBD>㴓 隡睃<EFBFBD><EFBFBD>刻<EFBFBD><EFBFBD>寞<EFBFBD>1嚗㇌EDCap銝箔蜓嚗<EFBFBD><EFBFBD><EFBFBD>穃<EFBFBD>甇伐<EFBFBD>
- <EFBFBD>𩤃<EFBFBD> <20>踹<EFBFBD><E8B8B9><EFBFBD><EFBFBD>摰墧𧒄<E5A2A7>峕郊嚗<E9838A><E59A97><EFBFBD><EFBFBD>漲<EFBFBD><E6BCB2><EFBFBD>嚗?
- <EFBFBD><EFBFBD> 憒<><E68692>敹<EFBFBD>◆<EFBFBD><E29786><EFBFBD>嚗䔶蝙<E494B6>?*<2A><>蝏<EFBFBD><E89D8F><EFBFBD>湔<EFBFBD>?鈭箏極摰⊥瓲**璅∪<E79285>
<EFBFBD>椬 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗鋫PI<50>鞉<EFBFBD>銝擧鸌<E693A7>𤩺<EFBFBD>雿𨀣<E99BBF>扯<EFBFBD>
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
REDCap API<50>厰<EFBFBD><E58EB0>怎<EFBFBD>**<2A>毺<EFBFBD><E6AFBA>𣂼<EFBFBD>**嚗峕鸌<E5B395>𤩺<EFBFBD>雿𨀣𧒄摰寞<E691B0>閫血<E996AB><E8A180>?
<EFBFBD>鞉<EFBFBD>閫<EFBFBD><EFBFBD>嚗<EFBFBD>𧊋<EFBFBD>砍<EFBFBD><EFBFBD><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>嚗?
- HTTP 429 (Too Many Requests)
- <20>𣇉凒<F0A38789>亥<EFBFBD><E4BAA5>嗆<EFBFBD><E59786>滚<EFBFBD>
<EFBFBD>笔<EFBFBD><EFBFBD>箸艶<EFBFBD>桅<EFBFBD>
<EFBFBD>箸艶1嚗𡁜<EFBFBD><EFBFBD>誩<EFBFBD>甇?0銝<30>辺霈啣<E99C88>
// <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>
// <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("撌脣紡<E884A3>?{$progress} <20>∟扇敶?);
}
return $allData;
}
// 10銝<30>辺霈啣<E99C88> = 200<30>?<3F> 2蝘?= 6.7<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>箸艶2嚗𡁜<EFBFBD><EFBFBD>嗅<EFBFBD>甇仿<EFBFBD>憸穃<EFBFBD><EFBFBD>?
<EFBFBD>駁堺<EFBFBD>箸艶嚗?
- 20銝芰<E98A9D>蝛嗅𨭌<E59785>见<EFBFBD><E8A781>嗅<EFBFBD><E59785>交㺭<E4BAA4>?
- 瘥譍犖瘥誩<E798A5><E8AAA9>煺<EFBFBD>摮?甈?
- <20>舔PS = 20 <20> 5 / 60 <20>?1.67甈?蝘?
<0A>贝絲<E8B49D>乩<EFBFBD>擃矋<E69383>雿<EFBFBD><E99BBF>
- 瘥𤩺活靽嘥<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>⊿▼"
閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>嚗𡁜<EFBFBD>甇亙<EFBFBD>
// <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
}
}
憌𡡞埯霂<EFBFBD>摯
| <EFBFBD><EFBFBD><EFBFBD> | 霂<EFBFBD>摯 | 霂湔<EFBFBD> |
|---|---|---|
| <EFBFBD>扯<EFBFBD><EFBFBD>園<EFBFBD> | <EFBFBD>椬 銝? | 憭扳㺭<EFBFBD>桅<EFBFBD><EFBFBD>嗆<EFBFBD><EFBFBD>? |
| *<EFBFBD>舀綉<EFBFBD>? | <EFBFBD>?<3F>舀綉 | <EFBFBD>舫<EFBFBD>朞<EFBFBD><EFBFBD><EFBFBD>鸌+<2B>鞉<EFBFBD>閫<EFBFBD><E996AB> |
| *撘<EFBFBD><EFBFBD>烐<EFBFBD><EFBFBD>? | <EFBFBD>叚 雿? | 1-2憭拙<E686AD><E68B99>? |
| <EFBFBD>冽<EFBFBD>敶勗<EFBFBD> | <EFBFBD>叚 雿? | <EFBFBD>冽<EFBFBD><EFBFBD>䭾<EFBFBD><EFBFBD>伐<EFBFBD>撘<EFBFBD>郊憭<EFBFBD><EFBFBD>嚗? |
<EFBFBD>𣞁 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗鍃xternal Module獢<65>沲<EFBFBD><E6B2B2><EFBFBD><EFBFBD>?
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
External Module獢<65>沲<EFBFBD>賜<EFBFBD>撘箏之嚗䔶<E59A97><E494B6>?銝滚虾<EFBFBD>曇<EFBFBD><EFBFBD><EFBFBD>器<EFBFBD>?<EFBFBD>?
<EFBFBD>𣂼<EFBFBD>皜<EFBFBD><EFBFBD>
<EFBFBD>𣂼<EFBFBD>1嚗𡁏<EFBFBD>瘜蓥耨<EFBFBD>鄗EDCap<EFBFBD>詨<EFBFBD><EFBFBD>屸𢒰
// <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>X㟲銝芷△<E88AB7>?
$('#data_entry_form').append('<div>AI<41>拇<EFBFBD></div>');
</script>
<?php
}
**敶勗<E695B6>**嚗?
- <EFBFBD>?<3F>䭾<EFBFBD>摰䂿緵"摰<><E691B0>摰𡁜<E691B0><F0A1819C>?<3F><>I
- <EFBFBD>𩤃<EFBFBD> <20>烾<EFBFBD>鈭竃EDCap<61>毺<EFBFBD><E6AFBA>屸𢒰<E5B1B8><F0A292B0><EFBFBD>撅<EFBFBD><E69285>峕甅撘?
- <EFBFBD>𩤃<EFBFBD> REDCap<61>屸𢒰<E5B1B8><F0A292B0>漣<EFBFBD>航<EFBFBD><E888AA>游<EFBFBD><E6B8B8>睲賑<E79DB2><E8B391>OM<4F>滢<EFBFBD>
<EFBFBD>𣂼<EFBFBD>2嚗𡁏<EFBFBD>瘜閗挪<EFBFBD>格<EFBFBD>鈭𥟇瓲敹<EFBFBD>遆<EFBFBD>?
// <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>鍂甇斗䲮瘜?
}
}
<EFBFBD>𣂼<EFBFBD>3嚗𡁏<EFBFBD>扯<EFBFBD>撘<EFBFBD><EFBFBD><EFBFBD>
// External Module<6C><65>ook隡𡁜<E99AA1><F0A1819C>𣳇<EFBFBD>憭硋<E686AD><E7A18B><EFBFBD>
function redcap_every_page_top($project_id) {
// 餈嗘葵<E59798>賣㺭<E8B3A3>冽<EFBFBD>銝芷△<E88AB7>a<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
蝏栞捏嚗?
- <EFBFBD>𩤃<EFBFBD> 銝滩<E98A9D><E6BBA9>沈ook銝剜<E98A9D>銵諹<E98AB5>埈𧒄<E59F88>滢<EFBFBD>
- <EFBFBD>?敹<>◆撘<E29786>郊<EFBFBD>?
<EFBFBD>𣂼<EFBFBD>4嚗𡁜<EFBFBD><EFBFBD>冽<EFBFBD>蝞?
// <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嚗𡁏𥅾<EFBFBD>梢<EFBFBD><EFBFBD>塚<EFBFBD><EFBFBD>刻器<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𥟇鰵
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>拍鍂Hook<EFBFBD>箏<EFBFBD>
- <EFBFBD>朞<EFBFBD>JavaScript憓𧼮撩UI嚗<EFBFBD><EFBFBD><EFBFBD>舀𤜯<EFBFBD>g<EFBFBD>
- 雿輻鍂API雿靝蛹"<22><><EFBFBD><EFBFBD>?
*蝑𣇉裦2嚗𡁏毽<EFBFBD><EFBFBD>沲<EFBFBD>?
REDCap (<28>唳旿敶訫<E695B6>) + AI撟喳蝱 (<28><><EFBFBD>撅閧內)
<20>?
<0A>冽<EFBFBD><E586BD>沖EDCap敶訫<E695B6> <20>?<3F>唳旿<E594B3>峕郊 <20>?<3F>杗I撟喳蝱<E596B3>亦<EFBFBD><E4BAA6><EFBFBD><EFBFBD>蝏𤘪<E89D8F>
餈蹱甅<EFBFBD>臭誑嚗?
- <EFBFBD>?<3F>拍鍂REDCap<61><70>”<EFBFBD>閗挽霈∪膥嚗<E886A5>撩憭改<E686AD>
- <EFBFBD>?<3F>拍鍂AI撟喳蝱<E596B3><E89DB1><EFBFBD><EFBFBD>鞱<EFBFBD><E99EB1>𨥈<EFBFBD><F0A8A588>菜暑嚗?
- <EFBFBD>?閫<><E996AB>External Module<6C><65><EFBFBD><EFBFBD>?
<EFBFBD>𣞁 <20><><EFBFBD>舀<EFBFBD><E88880>?嚗𡁜<E59A97><F0A1819C>典<EFBFBD>閫<EFBFBD><E996AB>改<EFBFBD>HIPAA/GDPR嚗?
<EFBFBD>桅<EFBFBD><EFBFBD>讛膩
REDCap<EFBFBD>𡁜虜摮睃<EFBFBD>**PHI嚗㇊rotected Health Information嚗匧<E59A97>靽脲擪<E884B2>亙熒靽⊥<E99DBD>**嚗<>笆<EFBFBD>交𧒄<E4BAA4><F0A79284><EFBFBD><EFBFBD>刻<EFBFBD>瘙<EFBFBD><E79899>擃塩<E69383>?
<EFBFBD><EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD>
HIPAA閬<EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD><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>摰⊥䰻
瞏𨅯銁憌𡡞埯<EFBFBD>?
憌𡡞埯1嚗𡁏㺭<EFBFBD>格<EFBFBD><EFBFBD>莎<EFBFBD>隡㰘<EFBFBD>餈<EFBFBD><EFBFBD>嚗?
// <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嚗𡁏𠯫敹埈<EFBFBD><EFBFBD>?
// <20>?<3F>躰秤嚗䥪HI霈啣<E99C88><E595A3>冽𠯫敹𦯀葉
$this->log("<22><><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>蠧
// <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);
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞉𧋦
| <EFBFBD><EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD> | 摰墧鴌<EFBFBD>曉漲 | 撘<EFBFBD><EFBFBD>烐<EFBFBD><EFBFBD>? | 摰∟恣<EFBFBD>鞉𧋦 | <EFBFBD>餅<EFBFBD><EFBFBD>? |
|---|---|---|---|---|
| 霈輸䔮<EFBFBD>批<EFBFBD> | <EFBFBD>椬 銝? | 1-2<>? | 瘥誩僑1甈? | $$$ |
| <EFBFBD>唳旿<EFBFBD>惩<EFBFBD> | <EFBFBD>椬 銝? | 2-3<>? | 瘥誩僑1甈? | $$$ |
| 摰∟恣<EFBFBD>亙<EFBFBD> | <EFBFBD>叚 雿? | 3-5憭? | 瘥誩僑2甈? | $$ |
| 摰匧<EFBFBD>霂<EFBFBD>摯 | <EFBFBD>𣞁 擃? | 4-6<>? | 瘥誩僑1甈? | |
| *蝚砌<EFBFBD><EFBFBD>孵恣霈? | <EFBFBD>𣞁 擃? | N/A | 瘥誩僑1甈? | $ |
| <EFBFBD>餉恣 | <EFBFBD>𣞁 擃? | 2-3銝芣<E98A9D> | <EFBFBD><EFBFBD>賒 | *$10K-50K/撟? |
<EFBFBD><EFBFBD> 憭齿<E686AD>摨血笆瘥䈑<E798A5>REDCap撖寞𦻖 vs <20>芰<EFBFBD>EDC
摰𡁻<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
| 蝏游漲 | REDCap撖寞𦻖 | <EFBFBD>芰<EFBFBD>EDC | 撖寞<EFBFBD> |
|---|---|---|---|
| *撘<EFBFBD><EFBFBD>穃𪂹<EFBFBD>? | 2-3銝芣<E98A9D> | 6-12銝芣<E98A9D> | <EFBFBD>叚 REDCap敹?-5<>? |
| *撘<EFBFBD><EFBFBD>烐<EFBFBD><EFBFBD>? | $50K-100K | $300K-500K | <EFBFBD>叚 REDCap<61>?200K+ |
| *蝏湔擪<EFBFBD>鞉𧋦/撟? | $30K-50K | $50K-80K | <EFBFBD>椬 REDCap<61>乩<EFBFBD> |
| <EFBFBD><EFBFBD><EFBFBD>臬<EFBFBD>箏𦛚 | <EFBFBD>𣞁 擃矋<E69383>靘肽<E99D98>REDCap<61><70>漣嚗? | <EFBFBD>叚 雿𠬍<E99BBF>摰<EFBFBD><E691B0><EFBFBD>芯蜓嚗? | <EFBFBD>𣞁 REDCap憌𡡞埯擃? |
| *<EFBFBD>菜暑<EFBFBD>? | <EFBFBD>椬 銝哨<E98A9D><E593A8>㜬M獢<4D>沲<EFBFBD>𣂼<EFBFBD>嚗? | <EFBFBD>叚 擃矋<E69383>摰<EFBFBD><E691B0><EFBFBD>芰眏嚗? | <EFBFBD>𣞁 REDCap<61>烾<EFBFBD> |
| *<EFBFBD>蠘<EFBFBD>摰峕㟲<EFBFBD>? | <EFBFBD>叚 擃矋<E69383>REDCap<61>鞟<EFBFBD>嚗? | <EFBFBD>椬 銝哨<E98A9D><E593A8><EFBFBD>隞𡡞妟撘<E5A69F><E69298>𡢅<EFBFBD> | <EFBFBD>叚 REDCap隡睃飵 |
| *AI<EFBFBD><EFBFBD><EFBFBD>摨? | <EFBFBD>椬 銝哨<E98A9D><E593A8><EFBFBD>獢交𦻖嚗? | <EFBFBD>叚 擃矋<E69383><E79F8B>毺<EFBFBD><E6AFBA><EFBFBD><EFBFBD>嚗? | <EFBFBD>𣞁 REDCap暻餌<E69ABB> |
| <EFBFBD>冽<EFBFBD>雿㯄<EFBFBD> | <EFBFBD>椬 銝哨<E98A9D>銝文<E98A9D>蝟餌<E89D9F>嚗? | <EFBFBD>叚 擃矋<E69383>蝏煺<E89D8F>雿㯄<E99BBF>嚗? | <EFBFBD>𣞁 REDCap<61>脰<EFBFBD> |
<EFBFBD>颱<EFBFBD>霂<EFBFBD>摯
REDCap撖寞𦻖<EFBFBD><EFBFBD>OI<EFBFBD><EFBFBD><EFBFBD>嚗?
<0A>鞉𧋦嚗?
- 撘<><E69298>𡢅<EFBFBD>$80K
- 撟渡輕<E6B8A1>歹<EFBFBD>$40K
- 5撟湔<E6929F>餅<EFBFBD><E9A485>穿<EFBFBD>$280K
<0A>嗥<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>
蝏栞捏嚗?
<0A>?憒<><E68692><EFBFBD>格<EFBFBD><E6A0BC>?敹恍<E695B9>罸<EFBFBD>霂<EFBFBD><E99C82><EFBFBD>?嚗朙EDCap撖寞𦻖<E5AF9E>舀<EFBFBD><E88880>粹<EFBFBD>㗇𥋘
<0A>?憒<><E68692><EFBFBD>格<EFBFBD><E6A0BC>?<3F>踵<EFBFBD>鈭批<E988AD>蝡硺<E89DA1><E7A1BA>?嚗諹䌊<E8ABB9>漋DC<44>游末
<0A>㴓 <20>刻<EFBFBD>蝑𣇉裦嚗𡁜<E59A97><F0A1819C>沖EDCap撖寞𦻖敹恍<E695B9>𠵱VP嚗<50><E59A97><EFBFBD>粹<EFBFBD>霂<EFBFBD><E99C82><EFBFBD>滩䌊<E6BBA9>?
<EFBFBD>㴓 <20><>蝏<EFBFBD>遣霈桐<E99C88><E6A190>喟<EFBFBD><E5969F>?
<EFBFBD>喟<EFBFBD><EFBFBD>?
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>?
銝厩<EFBFBD>蝑𣇉裦
蝑𣇉裦1嚗帋<EFBFBD>摰<EFBFBD><EFBFBD><EFBFBD>伐<EFBFBD><EFBFBD>刻<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>瘙?
<0A>嗆挾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>唳旿
<0A>嗆挾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>
隡睃飵嚗?
<0A>?憌𡡞埯<F0A1A19E>舀綉嚗<E7B689><E59A97><EFBFBD>嗆挾<E59786>訫<EFBFBD>嚗?
<0A>?韏<><E99F8F>擃䀹<E69383>嚗<EFBFBD><E59A97>瘚芾晶<E88ABE>其<EFBFBD>蝖桀<E89D96><E6A180><EFBFBD>★<EFBFBD>桐<EFBFBD>嚗?
<0A>?敹恍<E695B9>罸<EFBFBD>霂<EFBFBD><E99C82>3銝芣<E98A9D>閫<EFBFBD><E996AB><EFBFBD>頣<EFBFBD>
蝑𣇉裦2嚗𡁏<EFBFBD>餈𤤿<EFBFBD><EFBFBD>伐<EFBFBD>銝齿綫<EFBFBD>琜<EFBFBD>
<EFBFBD>湔𦻖<EFBFBD>訫<EFBFBD><EFBFBD>芰<EFBFBD>EDC嚗?-12銝芣<E98A9D>嚗?
憌𡡞埯嚗?
<0A>?撣<>㦤<EFBFBD><E3A6A4>瘙<EFBFBD>𧊋撉諹<E69289>
<0A>?蝡𧼮<E89DA1><F0A7BCAE>航<EFBFBD><E888AA>W<EFBFBD>
<0A>?韏<><E99F8F><EFBFBD>见<EFBFBD>憭?
蝑𣇉裦3嚗𡁏毽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>伐<EFBFBD><EFBFBD>䀝葉嚗?
<EFBFBD>峕𧒄餈𥡝<EFBFBD>嚗?
- 撠誩𣪧<E8AAA9><F0A3AAA7><EFBFBD>2鈭綽<E988AD>撖寞𦻖REDCap嚗<70>翰<EFBFBD>𠵱VP嚗?
- 憭批𣪧<E689B9><F0A3AAA7><EFBFBD>5鈭綽<E988AD><E7B6BD>芰<EFBFBD>EDC嚗<43>鵭<EFBFBD>煺漣<E785BA><E6BCA3><EFBFBD>
<0A>格<EFBFBD>嚗?
- REDCap皛∟雲<E2889F>拇<EFBFBD>摰X<E691B0>
- <20>芰<EFBFBD>EDC雿靝蛹<E99D9D><E89BB9>漣頝臬<E9A09D>
憌𡡞埯嚗?
<0A>𩤃<EFBFBD> 韏<><E99F8F><EFBFBD><EFBFBD>袇
<0A>𩤃<EFBFBD> 銝文<E98A9D>蝟餌<E89D9F>蝏湔擪<E6B994>鞉𧋦擃?
<EFBFBD><EFBFBD> 憌𡡞埯<F0A1A19E>拚猐<E68B9A>餌<EFBFBD>
| 憌𡡞埯憿? | 敶勗<EFBFBD>蝔见漲 | <EFBFBD>𤑳<EFBFBD>璁<EFBFBD><EFBFBD> | 隡睃<EFBFBD>蝥? | 蝻栞圾<EFBFBD>芣鴌 |
|---|---|---|---|---|
| EAV<EFBFBD>扯<EFBFBD><EFBFBD>園<EFBFBD> | <EFBFBD>𣞁 擃? | <EFBFBD>𣞁 擃? | P0 | 霈曇恣蝻枏<EFBFBD>撅?+ <20>拙<EFBFBD>閫<EFBFBD>㦛 |
| <EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD>漣<EFBFBD>游<EFBFBD> | <EFBFBD>𣞁 擃? | <EFBFBD>椬 銝? | P0 | <EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD><EFBFBD> + <20>𧼮<EFBFBD>瘚贝<E7989A> |
| *<EFBFBD>唳旿銝<EFBFBD><EFBFBD>湔<EFBFBD>? | <EFBFBD>椬 銝? | <EFBFBD>椬 銝? | P1 | <EFBFBD>訫<EFBFBD><EFBFBD>峕郊 + 撟<><E6929F><EFBFBD>扯挽霈? |
| API<EFBFBD>鞉<EFBFBD> | <EFBFBD>椬 銝? | <EFBFBD>椬 銝? | P2 | <EFBFBD><EFBFBD>鸌憭<EFBFBD><EFBFBD> + <20>鞉<EFBFBD> |
| EM獢<EFBFBD>沲<EFBFBD>𣂼<EFBFBD> | <EFBFBD>椬 銝? | <EFBFBD>叚 雿? | P3 | 瘛瑕<EFBFBD><EFBFBD>嗆<EFBFBD>嚗㇌EDCap + AI撟喳蝱嚗? |
| 摰匧<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>𣞁 擃? | <EFBFBD>叚 雿? | P0 | <EFBFBD>惩<EFBFBD> + 摰∟恣 + <20><><EFBFBD>霈方<E99C88> |
| 蝏湔擪<EFBFBD>鞉𧋦 | <EFBFBD>椬 銝? | <EFBFBD>𣞁 擃? | P1 | 蝏<EFBFBD>遣銝㮖<EFBFBD><EFBFBD>a<EFBFBD> |
<EFBFBD>𤁗 <20><>蝏<EFBFBD><E89D8F>霈?
蝑娍<EFBFBD><EFBFBD>函<EFBFBD><EFBFBD>桅<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<EFBFBD><EFBFBD>𧋦<EFBFBD><EFBFBD>漣<EFBFBD>舀<EFBFBD>銝滚虾<EFBFBD>抒<EFBFBD>嚗<EFBFBD><EFBFBD>撟?-4甈∴<E79488><E288B4>航<EFBFBD><E888AA>游<EFBFBD><E6B8B8><EFBFBD><EFBFBD>嚗?
Q: <20><><EFBFBD>舫𠗕<E888AB>對<EFBFBD> A: EAV璅∪<EFBFBD><EFBFBD><EFBFBD><EFBFBD>扯<EFBFBD>隡睃<EFBFBD><EFBFBD>?<EFBFBD><EFBFBD><EFBFBD>撘𤩺㺭<EFBFBD>桐<EFBFBD><EFBFBD>湔<EFBFBD>?<EFBFBD>舀<EFBFBD>憭折𠗕<EFBFBD>?
Q: 憭齿<E686AD><E9BDBF>折<EFBFBD><E68A98>梹<EFBFBD> A: **銝剔<E98A9D><E58994>誯<EFBFBD>憭齿<E686AD>摨?*嚗?/5嚗?
- 瘥磰䌊<EFBFBD>漋DC蝞<EFBFBD><EFBFBD>𤏪<EFBFBD>REDCap<EFBFBD>踵<EFBFBD>鈭?0%撌乩<E6928C>嚗?
- 瘥𥪜<EFBFBD>蝥涉PI<EFBFBD><EFBFBD><EFBFBD>憭齿<EFBFBD>嚗<EFBFBD><EFBFBD>憭<EFBFBD><EFBFBD>銝<EFBFBD><EFBFBD>湔<EFBFBD>扼<EFBFBD><EFBFBD><EFBFBD>扯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝥抒<EFBFBD><EFBFBD>桅<EFBFBD>嚗?
<EFBFBD>𤑳<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>摰X<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>喲睸撱箄悅嚗?
- <EFBFBD>?銝滩<E98A9D>銝<EFBFBD>撘<EFBFBD>憪见停餈賣<E9A488>"摰𣬚<E691B0>撖寞𦻖"
- <EFBFBD>?<3F><>鍂<EFBFBD><E98D82>蝞<EFBFBD><E89D9E>閙䲮獢<E4B2AE><E78DA2>霂<EFBFBD><E99C82>瘙<EFBFBD><E79899><EFBFBD>訫<EFBFBD><E8A8AB>峕郊頞喳<E9A09E>嚗?
- <EFBFBD>?<3F>𣂼<EFBFBD>閫<EFBFBD><E996AB>"<22><><EFBFBD>箇<EFBFBD><E7AE87>?嚗<><E59A97><EFBFBD>𨅯笆<F0A885AF>亙仃韐伐<E99F90>憒<EFBFBD><E68692><EFBFBD><EFBFBD>揢<EFBFBD>啗䌊<E59597>䈑<EFBFBD>
- <EFBFBD>𩤃<EFBFBD> 蝏<>遣<EFBFBD>侨HP + REDCap蝏誯<E89D8F><E8AAAF><EFBFBD>𣪧<EFBFBD><F0A3AAA7><EFBFBD><EFBFBD>喳<EFBFBD>1鈭綽<E988AD>
- <EFBFBD>𩤃<EFBFBD> 憸<><E686B8>20-30%<25><>𧒄<EFBFBD>游<EFBFBD>撖?<3F>誩<EFBFBD>"嚗<><E59A97><EFBFBD>砍<EFBFBD>蝥扼<E89DA5><E689BC>ug嚗?
<EFBFBD><EFBFBD>﹝<EFBFBD><EFBFBD>𧋦嚗鯝1.0
**<2A><><EFBFBD>擧凒<E693A7>?*嚗?025-12-30
銝𧢲活霂<EFBFBD>恣嚗䥪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>?