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%)
41 KiB
璅∪<EFBFBD><EFBFBD>祉<EFBFBD><EFBFBD>函蔡銝𤾸<EFBFBD><EFBFBD>箇<EFBFBD><EFBFBD>寞<EFBFBD>
*<EFBFBD><EFBFBD>﹝<EFBFBD><EFBFBD>𧋦嚗? v1.0
*<EFBFBD>𥕦遣<EFBFBD>交<EFBFBD>嚗? 2025-11-06
<EFBFBD><EFBFBD><EFBFBD>擧凒<EFBFBD>堆<EFBFBD> 2025-11-06
<EFBFBD><EFBFBD>﹝<EFBFBD>嗆<EFBFBD><EFBFBD><EFBFBD> <20>嗆<EFBFBD>霈曇恣
雿𡏭<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>舀沲<E88880><E6B2B2><EFBFBD>
<EFBFBD><EFBFBD> <20>詨<EFBFBD><E8A9A8>桅<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>祉<EFBFBD>鈭批<EFBFBD><EFBFBD><EFBFBD><EFBFBD>殷<EFBFBD>
- 憒<EFBFBD><EFBFBD>摰䂿緵<EFBFBD>砍𧑐<EFBFBD>㚚<EFBFBD>蝵莎<EFBFBD>
-
*憒<EFBFBD><EFBFBD>撘<EFBFBD><EFBFBD>穃<EFBFBD><EFBFBD>箇<EFBFBD>嚗?
- 憒<EFBFBD><EFBFBD><EFBFBD>拍鍂Electron獢<EFBFBD>沲嚗?
- 憒<EFBFBD><EFBFBD>憭滨鍂<EFBFBD>唳<EFBFBD>隞<EFBFBD><EFBFBD>嚗?
- <EFBFBD>嗆<EFBFBD>憒<EFBFBD><EFBFBD>霈曇恣嚗?
<EFBFBD>㴓 Part 1嚗𡁏芋<F0A1818F>㛖𡠺蝡钅<E89DA1>蝵脫䲮獢?
<EFBFBD>詨<EFBFBD><EFBFBD><EFBFBD>艙嚗𡁶𡠺蝡钅<EFBFBD>蝵?<3F>?摰<><E691B0>摮斤<E691AE>
*<EFBFBD>喲睸瘣𧼮<EFBFBD>嚗?
<EFBFBD>祉<EFBFBD><EFBFBD>函蔡<EFBFBD><EFBFBD><EFBFBD>甇<EFBFBD>鉄銋㚁<EFBFBD>
<0A>?<3F>臭誑<E887AD>閧𡠺<E996A7>枏<EFBFBD>
<0A>?<3F>臭誑<E887AD>閧𡠺餈鞱<E9A488>
<0A>?<3F>臭誑<E887AD>閧𡠺<E996A7><F0A1A0BA><EFBFBD>?
<0A>?<3F>臭誑<E887AD>閧𡠺<E996A7><F0A1A0BA>漣
雿<><E99BBF><EFBFBD>荔<EFBFBD>
<0A>?摰<><E691B0>銝滢<E98A9D>韏硋<E99F8F>隞碶誨<E7A2B6>?
<0A>?摰<><E691B0>銝滚<E98A9D>鈭怠抅蝖<E68A85>霈暹鴌
*蝐餅<EFBFBD>嚗?
撠勗<EFBFBD>銝<EFBFBD>銝芰𡠺蝡讠<EFBFBD><EFBFBD>𧢲㦤App嚗?
- 摰<><E691B0>韏𡝗<E99F8F>雿𦦵頂蝏<E9A082><E89D8F>Android/iOS嚗?
- 摰<><E691B0>韏𣇉頂蝏鬹PI嚗<49><E59A97><EFBFBD>誩仍<E8AAA9><E4BB8D><EFBFBD>雿滨<E99BBF>嚗?
- 雿<><E99BBF><EFBFBD>臭誑<E887AD>祉<EFBFBD>銝贝蝸<E8B49D><E89DB8><EFBFBD>鋆<EFBFBD><E98B86><EFBFBD><EFBFBD>銵䎚<E98AB5><E48E9A>桊頧?
璅∪<E79285><E288AA>祉<EFBFBD><E7A589>函蔡銋<E894A1>糓銝<E7B393><E98A9D>瘀<EFBFBD>
- 摰<><E691B0>韏硋像<E7A18B>啣<EFBFBD>嚗<EFBFBD>鍂<EFBFBD>瑁恕霂<E68195><E99C82><EFBFBD><EFBFBD><EFBFBD>函<EFBFBD>嚗?
- 摰<><E691B0>韏㚚<E99F8F>𡁶鍂<F0A181B6>賢<EFBFBD>撅<EFBFBD><E69285>LLM蝵穃<E89DB5><E7A983><EFBFBD><EFBFBD>獢<EFBFBD><E78DA2><EFBFBD><EFBFBD><EFBFBD>嚗?
- 雿<><E99BBF><EFBFBD>臭誑<E887AD>祉<EFBFBD><E7A589>枏<EFBFBD><E69E8F><EFBFBD><EFBFBD>蝵脯<E89DB5><E884AF><EFBFBD><EFBFBD>?
<EFBFBD>𣑐 <20>寞<EFBFBD>銝<EFBFBD>嚗𡁜<E59A97><F0A1819C>湔<EFBFBD><E6B994><EFBFBD><EFBFBD><EFBFBD>刻<EFBFBD><E588BB>其<EFBFBD><E585B6>祉<EFBFBD>鈭批<E988AD>嚗?
<EFBFBD><EFBFBD>鍂<EFBFBD>箸艶
- <EFBFBD>?璅∪<E79285>雿靝蛹<E99D9D>祉<EFBFBD>鈭批<E988AD><E689B9><EFBFBD><EFBFBD>殷<EFBFBD>憒<EFBFBD>恣蝔輻頂蝏<E9A082><E89D8F>
- <EFBFBD>?摰X<E691B0>閬<EFBFBD><E996AC>摰<EFBFBD><E691B0><EFBFBD>砍𧑐<E7A08D>㚚<EFBFBD>蝵?
- <EFBFBD>?銝滢<E98A9D>韏硋<E99F8F>隞𡝗芋<F0A19D97>埈<EFBFBD>撟喳蝱
<EFBFBD>詨<EFBFBD><EFBFBD>肽楝
*撠<EFBFBD><EFBFBD>韏𣇉<EFBFBD>撟喳蝱撅<EFBFBD><EFBFBD><EFBFBD>𡁶鍂<EFBFBD>賢<EFBFBD>撅<EFBFBD><EFBFBD>韏瑟<EFBFBD><EFBFBD>?
摰∠阮蝟餌<EFBFBD><EFBFBD>祉<EFBFBD>鈭批<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<0A>𢞖<EFBFBD><F0A29E96><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>? RVW摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD>鈭批<E988AD> <20>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>? 銝𡁜𦛚璅∪<E79285>撅? <20>?<3F>?
<0A>? <20>? RVW嚗<57>阮隞嗅恣<E59785>伐<EFBFBD> <20>?<3F>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>? <20>𡁶鍂<F0A181B6>賢<EFBFBD>撅<EFBFBD><E69285>敹<EFBFBD><E695B9><EFBFBD>典<EFBFBD>嚗? <20>?<3F>?
<0A>? <20>? - LLM蝵穃<E89DB5> <20>?<3F>?
<0A>? <20>? - <20><>﹝憭<EFB99D><E686AD>撘閙<E69298> <20>?<3F>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>? 撟喳蝱<E596B3>箇<EFBFBD>撅<EFBFBD><E69285>敹<EFBFBD><E695B9><EFBFBD>典<EFBFBD>嚗? <20>?<3F>?
<0A>? <20>? - <20>冽<EFBFBD>霈方<E99C88>嚗<EFBFBD><E59A97><EFBFBD>𣇉<EFBFBD>嚗? <20>?<3F>?
<0A>? <20>? - 摮睃<E691AE><E79D83>滚𦛚 <20>?<3F>?
<0A>? <20>? - <20>烐綉<E78390>亙<EFBFBD> <20>?<3F>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>? <20>? <20>祉<EFBFBD><E7A589>唳旿摨? <20>?<3F>?
<0A>? <20>? PostgreSQL嚗㇄ocker嚗? <20>?<3F>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
<0A>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD><EFBFBD><EFBFBD>臬<EFBFBD><EFBFBD>?
Step 1: 隞<><E99A9E>蝏<EFBFBD><E89D8F>嚗㇈onorepo嚗?
AIclinicalresearch/
<20>鎿<EFBFBD><E98EBF><EFBFBD> packages/ # Monorepo<70><6F>恣<EFBFBD>?
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> platform-core/ # 撟喳蝱<E596B3>詨<EFBFBD>嚗<EFBFBD>虾憭滨鍂嚗?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> auth/ # <20>冽<EFBFBD>霈方<E99C88>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> storage/ # 摮睃<E691AE><E79D83>滚𦛚
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> monitoring/ # <20>烐綉<E78390>亙<EFBFBD>
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> index.ts
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> capabilities-core/ # <20>𡁶鍂<F0A181B6>賢<EFBFBD><E8B3A2>詨<EFBFBD>嚗<EFBFBD>虾憭滨鍂嚗?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> llm-gateway/ # LLM蝵穃<E89DB5>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> document-processor/ # <20><>﹝憭<EFB99D><E686AD>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> rag-engine/ # RAG撘閙<E69298>
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> index.ts
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> module-aia/ # AI<41>桃<EFBFBD>璅∪<E79285>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> backend/
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> frontend/
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> module-asl/ # AI<41><49>讃璅∪<E79285>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> backend/
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> frontend/
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> module-review/ # 摰∠阮蝟餌<E89D9F>璅∪<E79285>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> backend/
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> frontend/
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json
<20>? <20>?
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> ...
<20>?
<20>鎿<EFBFBD><E98EBF><EFBFBD> products/ # <20>祉<EFBFBD>鈭批<E988AD><E689B9>枏<EFBFBD>
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> review-system/ # 摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD>鈭批<E988AD> 潃?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> docker-compose.yml
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> deploy.sh
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> README.md
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json # 靘肽<E99D98><E882BD>喟頂
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> literature-system/ # AI<41><49>讃<EFBFBD>祉<EFBFBD>鈭批<E988AD> 潃?
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> ...
<20>? <20>?
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> full-platform/ # 摰峕㟲撟喳蝱
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> ...
<20>?
<20>婙<EFBFBD><E5A999><EFBFBD> ...
Step 2: 靘肽<E99D98>蝞∠<E89D9E>嚗īackage.json嚗?
摰∠阮蝟餌<EFBFBD><EFBFBD>祉<EFBFBD>鈭批<EFBFBD><EFBFBD><EFBFBD><EFBFBD>韏吔<EFBFBD>
// products/review-system/package.json
{
"name": "@yizhengxun/review-system",
"version": "1.0.0",
"private": true,
"dependencies": {
// 撟喳蝱<E596B3>詨<EFBFBD>嚗<EFBFBD><E59A97><EFBFBD><EFBFBD>嚗?
"@yizhengxun/platform-core": "workspace:*",
// <20>𡁶鍂<F0A181B6>賢<EFBFBD>嚗<EFBFBD><E59A97><EFBFBD><EFBFBD>嚗?
"@yizhengxun/capabilities-core": "workspace:*",
// 銝𡁜𦛚璅∪<E79285>
"@yizhengxun/module-review": "workspace:*"
},
"scripts": {
"build": "node build.js",
"deploy": "sh deploy.sh"
}
}
撟喳蝱<EFBFBD>詨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㗇𥋘<EFBFBD>批紡<EFBFBD>綽<EFBFBD>
// packages/platform-core/index.ts
// 摰峕㟲撖澆枂嚗<E69E82>鍂鈭𤾸<E988AD><F0A4BEB8>游像<E6B8B8>堆<EFBFBD>
export * from './auth';
export * from './storage';
export * from './monitoring';
export * from './notification';
// 蝎曄<E89D8E>撖澆枂嚗<E69E82>鍂鈭𡒊𡠺蝡衤漣<E8A1A4><E6BCA3><EFBFBD>
export {
// <20>芸紡<E88AB8>箏<EFBFBD><E7AE8F><EFBFBD><EFBFBD><EFBFBD>恕霂<E68195><E99C82><EFBFBD>?
authMiddleware,
jwtService
} from './auth';
export {
// <20>芸紡<E88AB8>箏<EFBFBD><E7AE8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>典<EFBFBD><E585B8>?
uploadFile,
downloadFile
} from './storage';
export {
// <20>芸紡<E88AB8>箏<EFBFBD><E7AE8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>批<EFBFBD><E689B9>?
logError,
logAudit
} from './monitoring';
Step 3: <20>枏<EFBFBD><E69E8F>𡁏𧋦
*摰∠阮蝟餌<EFBFBD><EFBFBD>祉<EFBFBD><EFBFBD>枏<EFBFBD>嚗?
// products/review-system/build.js
const { build } = require('esbuild');
const { dependencies } = require('./package.json');
async function buildReviewSystem() {
console.log('<27><>遣摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD>鈭批<E988AD>...');
// 1. <20><>遣<EFBFBD>𡒊垢
await build({
entryPoints: ['../../packages/module-review/backend/src/index.ts'],
bundle: true,
platform: 'node',
target: 'node18',
outfile: 'dist/backend/index.js',
external: ['pg', 'fastify', 'prisma'], // 銝齿<E98A9D><E9BDBF><EFBFBD><EFBFBD>鈭𥕦之摨?
// <20>芸𢆡<E88AB8><F0A286A1>鉄靘肽<E99D98>
plugins: [
// <20>芸𢆡閫<F0A286A1><E996AB>workspace靘肽<E99D98>
resolveWorkspaceDependencies()
]
});
// 2. <20><>遣<EFBFBD>滨垢
await build({
entryPoints: ['../../packages/module-review/frontend/src/main.tsx'],
bundle: true,
platform: 'browser',
outfile: 'dist/frontend/index.js',
loader: { '.tsx': 'tsx' }
});
// 3. 憭滚<E686AD>敹<EFBFBD><E695B9><EFBFBD><EFBFBD>辣
copyFiles([
'docker-compose.yml',
'README.md',
'deploy.sh'
]);
console.log('<27><>遣摰峕<EFBFBD>嚗?);
}
buildReviewSystem();
Step 4: Docker<65>函蔡<E587BD>滨蔭
*摰∠阮蝟餌<EFBFBD><EFBFBD>祉<EFBFBD><EFBFBD>函蔡嚗?
# products/review-system/docker-compose.yml
version: '3.8'
services:
# PostgreSQL<51>唳旿摨橒<E691A8><E6A992>祉<EFBFBD>嚗?
postgres:
image: postgres:15-alpine
container_name: review-system-postgres
environment:
POSTGRES_DB: review_system
POSTGRES_USER: review
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- review-network
# <20>𡒊垢<F0A1928A>滚𦛚嚗<F0A69B9A><E59A97><EFBFBD>怠像<E680A0>啣<EFBFBD><E595A3>屸<EFBFBD>𡁶鍂<F0A181B6>賢<EFBFBD>撅<EFBFBD><E69285>
backend:
build:
context: ./dist/backend
container_name: review-system-backend
environment:
DATABASE_URL: postgresql://review:${DB_PASSWORD}@postgres:5432/review_system
LLM_API_KEY: ${LLM_API_KEY}
depends_on:
- postgres
networks:
- review-network
# <20>滨垢<E6BBA8>滚𦛚
frontend:
build:
context: ./dist/frontend
container_name: review-system-frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- review-network
volumes:
postgres_data:
networks:
review-network:
driver: bridge
Step 5: 銝<><E98A9D>桅<EFBFBD>蝵脰<E89DB5><E884B0>?
#!/bin/bash
# products/review-system/deploy.sh
echo "======================================"
echo " 摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD><E7A589>函蔡<E587BD>𡁏𧋦"
echo "======================================"
# 1. 璉<><E79289>主ocker
if ! command -v docker &> /dev/null; then
echo "<22>躰秤嚗𡁏𧊋摰㕑<E691B0>Docker"
exit 1
fi
# 2. 霈曄蔭<E69B84>臬<EFBFBD><E887AC>㗛<EFBFBD>
read -p "霂瑁<E99C82><E79181>交㺭<E4BAA4>桀<EFBFBD>撖<EFBFBD><E69296>: " DB_PASSWORD
read -p "霂瑁<E99C82><E79181>他LM API撖<49>𤨎: " LLM_API_KEY
export DB_PASSWORD
export LLM_API_KEY
# 3. <20>臬𢆡<E887AC>滚𦛚
docker-compose up -d
# 4. 蝑匧<E89D91><E58CA7>滚𦛚<E6BB9A>臬𢆡
echo "蝑匧<E89D91><E58CA7>滚𦛚<E6BB9A>臬𢆡..."
sleep 10
# 5. <20>嘥<EFBFBD><E598A5>𡝗㺭<F0A19D97>桀<EFBFBD>
docker exec review-system-backend npx prisma migrate deploy
# 6. <20>𥕦遣暺䁅恕蝞∠<E89D9E><E288A0>?
docker exec review-system-backend node scripts/create-admin.js
echo "======================================"
echo " <20>函蔡摰峕<E691B0>嚗?
echo " 霈輸䔮<E8BCB8>啣<EFBFBD>嚗冴ttp://localhost"
echo " 蝞∠<E89D9E><E288A0>䁅揭<E48185>瘀<EFBFBD>admin@review.com"
echo " 撖<><E69296>嚗惨dmin123嚗<33>窈<EFBFBD>𦠜𧒄靽格㺿嚗?
echo "======================================"
<EFBFBD>喲睸<EFBFBD><EFBFBD><EFBFBD>舐<EFBFBD>
1. 撟喳蝱撅<E89DB1><E69285>蝎曄<E89D8E><E69B84>屸<EFBFBD><E5B1B8><EFBFBD>
摰峕㟲撟喳蝱<EFBFBD><EFBFBD>鍂<EFBFBD>瑁恕霂<EFBFBD><EFBFBD>憭齿<EFBFBD>嚗㚁<EFBFBD>
// 摰峕㟲撟喳蝱
- 憭𡁶<EFBFBD><EFBFBD>瑟𣈲<EFBFBD>?
- RBAC<EFBFBD><EFBFBD><EFBFBD><EFBFBD>批<EFBFBD>
- SSO<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>吔<EFBFBD>嚗?
// 摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD>鈭批<E988AD>
- 蝞<EFBFBD><EFBFBD>𣇉<EFBFBD><EFBFBD>冽<EFBFBD>霈方<EFBFBD>嚗<EFBFBD><EFBFBD>蝞?撖<EFBFBD><EFBFBD>嚗?
- 蝞<EFBFBD><EFBFBD>閧<EFBFBD>閫坿𠧧嚗<EFBFBD>恣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>颲㻫<EFBFBD><EFBFBD>恣蝔蹂犖嚗?
- <EFBFBD>箔<EFBFBD>JWT<EFBFBD><EFBFBD>oken霈方<EFBFBD>
- <EFBFBD>䒷SO<EFBFBD><EFBFBD><EFBFBD>憭𡁶<EFBFBD><EFBFBD>?
*摰䂿緵<EFBFBD>孵<EFBFBD>嚗?
// packages/platform-core/auth/simple-auth.ts
// 銝箇𡠺蝡衤漣<E8A1A4><E6BCA3><EFBFBD>靘𤤿<E99D98><F0A4A4BF>𣇉<EFBFBD>霈方<E99C88>
export class SimpleAuthService {
// <20>芯<EFBFBD><E88AAF>蹱瓲敹<E793B2><E695B9><EFBFBD>?
async login(email: string, password: string) { }
async register(email: string, password: string) { }
async verifyToken(token: string) { }
async logout(userId: string) { }
// 蝘駁膄憭齿<E686AD><E9BDBF>蠘<EFBFBD>
// <20>?async loginWithWeChat()
// <20>?async setupSSO()
// <20>?async multiTenantCheck()
}
2. <20>𡁶鍂<F0A181B6>賢<EFBFBD>撅<EFBFBD><E69285>蝎曄<E89D8E><E69B84>屸<EFBFBD><E5B1B8><EFBFBD>
*摰峕㟲撟喳蝱<EFBFBD><EFBFBD>LM蝵穃<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?
// 摰峕㟲撟喳蝱
- <EFBFBD>舀<EFBFBD>10+蝘齿芋<EFBFBD>?
- Feature Flag<EFBFBD>批<EFBFBD>
- <EFBFBD>漤<EFBFBD>蝞∠<EFBFBD>
- <EFBFBD>鞉𧋦<EFBFBD><EFBFBD><EFBFBD>
- A/B瘚贝<EFBFBD>
*摰∠阮蝟餌<EFBFBD><EFBFBD><EFBFBD>LM蝵穃<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>吔<EFBFBD>嚗?
// 摰∠阮蝟餌<E89D9F><E9A48C>祉<EFBFBD>鈭批<E988AD>
- <EFBFBD>芣𣈲<EFBFBD>?-2蝘齿芋<EFBFBD>页<EFBFBD>DeepSeek + Claude嚗?
- 蝞<EFBFBD><EFBFBD>閧<EFBFBD><EFBFBD>漤<EFBFBD>璉<EFBFBD><EFBFBD>?
- <EFBFBD>硓eature Flag
- <EFBFBD>䭾<EFBFBD><EFBFBD>砍<EFBFBD><EFBFBD>?
*摰䂿緵<EFBFBD>孵<EFBFBD>嚗?
// packages/capabilities-core/llm-gateway/simple-llm.ts
export class SimpleLLMGateway {
// <20>芯<EFBFBD><E88AAF>蹱瓲敹<E793B2><E695B9><EFBFBD>?
async chat(params: ChatParams) { }
async checkQuota(userId: string) { }
// 蝘駁膄憭齿<E686AD><E9BDBF>蠘<EFBFBD>
// <20>?async getCostStats()
// <20>?async selectModelByVersion()
// <20>?async runABTest()
}
3. <20>唳旿摨梶<E691A8><E6A2B6>𠉛氖
*摰峕㟲撟喳蝱<EFBFBD><EFBFBD>㺭<EFBFBD>桀<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?
-- 撟喳蝱撅<E89DB1>chema
platform_schema.users
platform_schema.tenants
platform_schema.feature_flags
-- ...
-- <20><><EFBFBD>㗇芋<E39787>𣶷chema
aia_schema.*
asl_schema.*
review_schema.*
-- ...
*摰∠阮蝟餌<EFBFBD><EFBFBD>祉<EFBFBD>鈭批<EFBFBD><EFBFBD><EFBFBD>㺭<EFBFBD>桀<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>吔<EFBFBD>嚗?
-- <20>芸<EFBFBD><E88AB8>怠<EFBFBD><E680A0><EFBFBD><EFBFBD><EFBFBD>”
CREATE DATABASE review_system;
-- 蝞<><E89D9E>𣇉<EFBFBD><F0A38789>冽<EFBFBD>銵?
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL, -- admin/editor/reviewer
created_at TIMESTAMP DEFAULT NOW()
);
-- 摰∠阮蝟餌<E89D9F><E9A48C><EFBFBD><EFBFBD><EFBFBD>∟”
CREATE TABLE review_tasks (...);
CREATE TABLE review_journals (...);
CREATE TABLE review_reviewers (...);
-- ...
<EFBFBD>祉<EFBFBD>鈭批<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
| 隡睃飵 | 霂湔<EFBFBD> |
|---|---|
| *<EFBFBD>祉<EFBFBD><EFBFBD><EFBFBD><EFBFBD>? | <EFBFBD>臭誑<EFBFBD>閧𡠺摰帋遠<EFBFBD><EFBFBD><EFBFBD><EFBFBD>祇<EFBFBD><EFBFBD>? |
| <EFBFBD>祉<EFBFBD><EFBFBD>函蔡 | 摰X<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><EFBFBD>蠘<EFBFBD>嚗<EFBFBD><EFBFBD>雿梶妖撠? |
| *摰𡁜<EFBFBD><EFBFBD>? | <EFBFBD>臭誑<EFBFBD><EFBFBD>笆<EFBFBD>孵<EFBFBD>摰X<EFBFBD>摰𡁜<EFBFBD> |
<EFBFBD>𣑐 <20>寞<EFBFBD>鈭䕘<E988AD><E49598>曹澈<E69BB9>滚𦛚嚗<F0A69B9A>綫<EFBFBD>鞟鍂鈭𤾸像<F0A4BEB8>啣<EFBFBD>璅∪<E79285>嚗?
<EFBFBD><EFBFBD>鍂<EFBFBD>箸艶
- <EFBFBD>?<3F>䔶<EFBFBD>摰X<E691B0>韐凋僭憭帋葵璅∪<E79285>
- <EFBFBD>?鈭𤑳垢SaaS<61>函蔡
- <EFBFBD>?璅∪<E79285>銋钅𡢿<E99285><F0A1A2BF>閬<EFBFBD><E996AC>鈭怎鍂<E6808E>瑕<EFBFBD><E79195>唳旿
<EFBFBD>詨<EFBFBD><EFBFBD>肽楝
*撟喳蝱撅<EFBFBD><EFBFBD><EFBFBD>𡁶鍂<EFBFBD>賢<EFBFBD>撅<EFBFBD><EFBFBD>銝箏<EFBFBD>鈭急<EFBFBD><EFBFBD>?
摰峕㟲撟喳蝱<EFBFBD>嗆<EFBFBD>嚗<EFBFBD>凝<EFBFBD>滚𦛚<EFBFBD><EFBFBD><EFBFBD>嚗?
<0A>𢞖<EFBFBD><F0A29E96><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>? API蝵穃<E89DB5>嚗𠃋ong/Traefik嚗? <20>?
<0A>? 頝舐眏嚗?aia/* /asl/* /review/* <20>?
<0A>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<20>? <20>? <20>?
<20>? <20>? <20>?
<0A>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>?AIA璅∪<E79285><E288AA>滚𦛚 <20>?<3F>?ASL璅∪<E79285><E288AA>滚𦛚 <20>?<3F>?RVW璅∪<E79285><E288AA>滚𦛚 <20>?
<0A>?(<28>祉<EFBFBD><E7A589>函蔡) <20>?<3F>?(<28>祉<EFBFBD><E7A589>函蔡) <20>?<3F>?(<28>祉<EFBFBD><E7A589>函蔡) <20>?
<0A>婙<EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>婙<EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>婙<EFBFBD><E5A999><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>? <20>? <20>?
<20>婙<EFBFBD><E5A999><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><EFBFBD>氯<EFBFBD><E6B0AF><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><EFBFBD>?
<20>?
<20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD>?
<20>? <20>曹澈<E69BB9>滚𦛚嚗<F0A69B9A>像<EFBFBD>啣<EFBFBD>嚗? <20>?
<20>? - <20>冽<EFBFBD>霈方<E99C88><E696B9>滚𦛚 <20>?
<20>? - 摮睃<E691AE><E79D83>滚𦛚 <20>?
<20>? - <20>烐綉<E78390>滚𦛚 <20>?
<20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD>?
<20>?
<20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD>?
<20>? <20>曹澈<E69BB9>滚𦛚嚗<F0A69B9A><E59A97>𡁶鍂<F0A181B6>賢<EFBFBD>撅<EFBFBD><E69285> <20>?
<20>? - LLM蝵穃<E89DB5><E7A983>滚𦛚 <20>?
<20>? - <20><>﹝憭<EFB99D><E686AD><EFBFBD>滚𦛚 <20>?
<20>? - RAG撘閙<E69298><E99699>滚𦛚 <20>?
<20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD>?
<20>?
<20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD>?
<20>? <20>曹澈<E69BB9>唳旿摨? <20>?
<20>? - PostgreSQL (憭锭chema) <20>?
<20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD>?
<EFBFBD><EFBFBD><EFBFBD>臬<EFBFBD><EFBFBD>?
Step 1: <20>滚𦛚<E6BB9A><F0A69B9A><EFBFBD>
*撟喳蝱<EFBFBD>箇<EFBFBD><EFBFBD>滚𦛚嚗<EFBFBD>𡠺蝡钅<EFBFBD>蝵莎<EFBFBD>嚗?
# services/platform/docker-compose.yml
services:
# <20>冽<EFBFBD>霈方<E99C88><E696B9>滚𦛚
auth-service:
image: yizhengxun/auth-service:latest
ports:
- "3001:3000"
environment:
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET: ${JWT_SECRET}
# 摮睃<E691AE><E79D83>滚𦛚
storage-service:
image: yizhengxun/storage-service:latest
ports:
- "3002:3000"
environment:
OSS_ENDPOINT: ${OSS_ENDPOINT}
# <20>烐綉<E78390>滚𦛚
monitoring-service:
image: yizhengxun/monitoring-service:latest
ports:
- "3003:3000"
*<EFBFBD>𡁶鍂<EFBFBD>賢<EFBFBD><EFBFBD>滚𦛚嚗<EFBFBD>𡠺蝡钅<EFBFBD>蝵莎<EFBFBD>嚗?
# services/capabilities/docker-compose.yml
services:
# LLM蝵穃<E89DB5><E7A983>滚𦛚
llm-gateway:
image: yizhengxun/llm-gateway:latest
ports:
- "3010:3000"
environment:
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY}
QWEN_API_KEY: ${QWEN_API_KEY}
# <20><>﹝憭<EFB99D><E686AD><EFBFBD>滚𦛚
document-processor:
image: yizhengxun/document-processor:latest
ports:
- "3011:3000"
# RAG撘閙<E69298><E99699>滚𦛚
rag-engine:
image: yizhengxun/rag-engine:latest
ports:
- "3012:3000"
*銝𡁜𦛚璅∪<EFBFBD><EFBFBD>滚𦛚嚗<EFBFBD>𡠺蝡钅<EFBFBD>蝵莎<EFBFBD>嚗?
# services/modules/review-system/docker-compose.yml
services:
review-system:
image: yizhengxun/review-system:latest
ports:
- "4001:3000"
environment:
# 靘肽<E99D98><E882BD>曹澈<E69BB9>滚𦛚
AUTH_SERVICE_URL: http://auth-service:3000
STORAGE_SERVICE_URL: http://storage-service:3000
LLM_GATEWAY_URL: http://llm-gateway:3000
DOCUMENT_PROCESSOR_URL: http://document-processor:3000
# <20>芸楛<E88AB8><E6A59B>㺭<EFBFBD>桀<EFBFBD>Schema
DATABASE_URL: postgresql://user:pass@postgres:5432/platform?schema=review_schema
Step 2: API蝵穃<E89DB5><E7A983>滨蔭
*Kong API蝵穃<E89DB5><E7A983>滨蔭嚗?
# api-gateway/kong.yml
_format_version: "3.0"
services:
# <20>冽<EFBFBD>霈方<E99C88><E696B9>滚𦛚
- name: auth-service
url: http://auth-service:3000
routes:
- name: auth-routes
paths:
- /api/auth
# 摰∠阮蝟餌<E89D9F>璅∪<E79285>
- name: review-system
url: http://review-system:3000
routes:
- name: review-routes
paths:
- /api/review
plugins:
- name: jwt
config:
secret_is_base64: false
key_claim_name: kid
# AI<41><49>讃璅∪<E79285>
- name: literature-system
url: http://literature-system:3000
routes:
- name: literature-routes
paths:
- /api/literature
plugins:
- name: jwt
Step 3: <20>滚𦛚<E6BB9A>湧<EFBFBD>帋縑
*銝𡁜𦛚璅∪<EFBFBD>靚<EFBFBD>鍂<EFBFBD>曹澈<EFBFBD>滚𦛚嚗?
// packages/module-review/backend/src/services/review.service.ts
import { AuthClient } from '@yizhengxun/platform-core/clients';
import { LLMClient } from '@yizhengxun/capabilities-core/clients';
export class ReviewService {
private authClient: AuthClient;
private llmClient: LLMClient;
constructor() {
// 餈墧𦻖<E5A2A7>啣<EFBFBD>鈭急<E988AD><E680A5>?
this.authClient = new AuthClient({
baseURL: process.env.AUTH_SERVICE_URL
});
this.llmClient = new LLMClient({
baseURL: process.env.LLM_GATEWAY_URL
});
}
async createReviewTask(userId: string, file: File) {
// 1. 撉諹<E69289><E8ABB9>冽<EFBFBD>嚗<EFBFBD><E59A97><EFBFBD>典<EFBFBD>鈭怨恕霂<E68195><E99C82><EFBFBD>∴<EFBFBD>
const user = await this.authClient.verifyUser(userId);
// 2. 銝𠹺<E98A9D><F0A0B9BA><EFBFBD>辣嚗<E8BEA3><E59A97><EFBFBD>典<EFBFBD>鈭怠<E988AD><E680A0>冽<EFBFBD><E586BD>∴<EFBFBD>
const fileUrl = await this.storageClient.upload(file);
// 3. AI<41><49><EFBFBD>嚗<EFBFBD><E59A97><EFBFBD>典<EFBFBD>鈭俠LM蝵穃<E89DB5>嚗?
const analysis = await this.llmClient.chat({
messages: [{ role: 'user', content: `<60><><EFBFBD>餈嗵<E9A488>蝔蹂辣: ${fileUrl}` }]
});
// 4. 靽嘥<E99DBD><E598A5>啗䌊撌梁<E6928C><E6A281>唳旿摨?
const task = await prisma.reviewTask.create({
data: {
userId,
fileUrl,
analysis: analysis.content
}
});
return task;
}
}
璅∪<EFBFBD><EFBFBD>祉<EFBFBD><EFBFBD>函蔡<EFBFBD><EFBFBD>郊撉?
*1. <20>函蔡<E587BD>曹澈<E69BB9>滚𦛚嚗<F0A69B9A><E59A97>甈⊥<E79488>改<EFBFBD>嚗?
# <20>函蔡撟喳蝱<E596B3>箇<EFBFBD><E7AE87>滚𦛚
cd services/platform
docker-compose up -d
# <20>函蔡<E587BD>𡁶鍂<F0A181B6>賢<EFBFBD><E8B3A2>滚𦛚
cd services/capabilities
docker-compose up -d
# <20>函蔡API蝵穃<E89DB5>
cd services/api-gateway
docker-compose up -d
2. <20>函蔡銝𡁜𦛚璅∪<E79285>嚗<EFBFBD><E59A97><EFBFBD><EFBFBD>嚗㚁<E59A97>
# <20>芷<EFBFBD>蝵脣恣蝔輻頂蝏<E9A082>芋<EFBFBD>?
cd services/modules/review-system
docker-compose up -d
# 摰X<E691B0>A韐凋僭鈭<E583AD>恣蝔輻頂蝏<E9A082><E89D8F><EFBFBD>芷<EFBFBD><E88AB7>函蔡餈嗘<E9A488>銝芣芋<E88AA3>?
# <20>嗡<EFBFBD>璅∪<E79285>銝漤<E98A9D>閬<EFBFBD><E996AC>蝵?
3. <20>啣恥<E595A3>瑁揚銋啣<E98A8B>隞𡝗芋<F0A19D97>梹<EFBFBD>
# 摰X<E691B0>B韐凋僭鈭<E583AD>I<EFBFBD><49>讃璅∪<E79285>嚗<EFBFBD><E59A97><EFBFBD>函蔡餈嗘葵璅∪<E79285>
cd services/modules/literature-system
docker-compose up -d
# <20>曹澈<E69BB9>滚𦛚撌脩<E6928C><E884A9>函蔡嚗䔶<E59A97><E494B6><EFBFBD>閬<EFBFBD><E996AC>憭漤<E686AD>蝵?
# <20>芷<EFBFBD>憓𧼮<E68693><F0A7BCAE>啁<EFBFBD>銝𡁜𦛚璅∪<E79285>
<EFBFBD>棅儭?Part 2嚗鍃lectron<6F>閙㦤<E99699><E3A6A4>䲮獢?
銝箔<EFBFBD>銋<EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>箇<EFBFBD>嚗?
<EFBFBD>詨<EFBFBD><EFBFBD><EFBFBD>瘙<EFBFBD><EFBFBD>
- **<2A>唳旿<E594B3>鞟<EFBFBD>**嚗𡁜龫<F0A1819C>煺葵鈭箸㺭<E7AEB8>桐<EFBFBD><E6A190>賭<EFBFBD>隡牐<E99AA1>蝡?
- 蝳餌瑪雿輻鍂嚗𡁏<EFBFBD><EFBFBD><EFBFBD>蝵𤑳<EFBFBD>餈墧𦻖
- **靘踵𡉼<E8B8B5>?*嚗𡁜虾隞亙銁隞颱<E99A9E><E9A2B1>菔<EFBFBD>銝𠰴<E98A9D>鋆<EFBFBD>蝙<EFBFBD>?
- **<2A>祉<EFBFBD>餈鞱<E9A488>**嚗帋<E59A97>靘肽<E99D98>憭㚚<E686AD><E39A9A>滚𦛚<E6BB9A>?
*<EFBFBD>格<EFBFBD><EFBFBD>冽<EFBFBD>嚗?
- 銝芯犖<EFBFBD>餌<EFBFBD>
- <EFBFBD>唳旿<EFBFBD>𤩺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝛嗉<EFBFBD>?
- <EFBFBD>删<EFBFBD>蝏𦦵㴓憓<EFBFBD><EFBFBD><EFBFBD>箸艶
Electron<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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>? 瘚讛<E7989A><E8AE9B>?(Chrome) <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? <20>滨垢 (React + Vite) <20>? <20>?
<0A>? <20>? http://localhost:5173 <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<20>?HTTP霂瑟<E99C82>
<0A>𢞖<EFBFBD><F0A29E96><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>? <20>𡒊垢 (Node.js + Fastify) <20>?
<0A>? http://localhost:3001 <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? API頝舐眏<E88890><E79C8F><EFBFBD><EFBFBD>⊿<EFBFBD>餉<EFBFBD><E9A489><EFBFBD>risma ORM <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<20>?
<0A>𢞖<EFBFBD><F0A29E96><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<0A>? PostgreSQL (Docker) <20>?
<0A>? localhost:5432 <20>?
<0A>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
Electron<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><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><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><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><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>?
<0A>? Electron 摨𠉛鍂 <20>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? 皜脫<E79A9C>餈𤤿<E9A488> (Chromium) <20>? <20>?
<0A>? <20>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>? <20>?
<0A>? <20>? <20>? <20>滨垢 (React) 潃?憭滨鍂<E6BBA8>唳<EFBFBD>隞<EFBFBD><E99A9E> <20>? <20>? <20>?
<0A>? <20>? <20>? file://app/index.html <20>? <20>? <20>?
<0A>? <20>? <20>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>?IPC<50>帋縑 <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? 銝餉<E98A9D>蝔?(Node.js) <20>? <20>?
<0A>? <20>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>? <20>?
<0A>? <20>? <20>? API<50>餉<EFBFBD><E9A489><EFBFBD><EFBFBD><EFBFBD>⊿<EFBFBD>餉<EFBFBD> 潃?憭滨鍂<E6BBA8>唳<EFBFBD>隞<EFBFBD><E99A9E> <20>? <20>? <20>?
<0A>? <20>? <20>? Prisma ORM<52><4D>𧋦<EFBFBD>唳<EFBFBD>隞嗥頂蝏? <20>? <20>? <20>?
<0A>? <20>? <20>婙<EFBFBD><E5A999><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? SQLite (撋<><E6928B>撘𤩺㺭<F0A4A9BA>桀<EFBFBD>) <20>? <20>?
<0A>? <20>? ~/Documents/YizhengxunData/app.db <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>?
<0A>? <20>𢞖<EFBFBD><F0A29E96><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>? <20>? 摮鞱<E691AE>蝔?(Python/R) <20>? <20>?
<0A>? <20>? <20><>﹝<EFBFBD>𣂼<EFBFBD><F0A382BC><EFBFBD>㺭<EFBFBD>桀<EFBFBD><E6A180>? <20>? <20>?
<0A>? <20>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<0A>婙<EFBFBD><E5A999><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><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><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><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>詨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>舀䲮獢?
1. <20>滨垢隞<E59EA2><E99A9E>憭滨鍂嚗?0%+ 憭滨鍂嚗?
*<EFBFBD>唳<EFBFBD><EFBFBD>滨垢隞<EFBFBD><EFBFBD>嚗Áeb<EFBFBD><EFBFBD><EFBFBD>嚗?
// frontend/src/api/client.ts
const API_BASE_URL = 'http://localhost:3001';
export const apiClient = {
async get(url: string) {
return fetch(`${API_BASE_URL}${url}`);
},
async post(url: string, data: any) {
return fetch(`${API_BASE_URL}${url}`, {
method: 'POST',
body: JSON.stringify(data)
});
}
};
Electron<EFBFBD><EFBFBD><EFBFBD>蝡荔<EFBFBD>靽格㺿API靚<EFBFBD>鍂<EFBFBD>孵<EFBFBD>嚗㚁<EFBFBD>
// electron-frontend/src/api/client.ts
// 雿輻鍂Electron<6F><6E>PC<50>帋縑嚗諹<E59A97>䔶<EFBFBD><E494B6>浹TTP
const { ipcRenderer } = window.require('electron');
export const apiClient = {
async get(url: string) {
// <20>朞<EFBFBD>IPC<50>煾<EFBFBD><E785BE><EFBFBD>銝餉<E98A9D>蝔?
return ipcRenderer.invoke('api-request', {
method: 'GET',
url
});
},
async post(url: string, data: any) {
return ipcRenderer.invoke('api-request', {
method: 'POST',
url,
data
});
}
};
*React蝏<EFBFBD>辣摰<EFBFBD><EFBFBD>銝漤<EFBFBD>閬<EFBFBD>㺿嚗?
// 銝𡁜𦛚蝏<F0A69B9A>辣摰<E8BEA3><E691B0>銝滚<E98A9D> <20>?
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
// API靚<49>鍂<EFBFBD>孵<EFBFBD>銝滚<E98A9D>嚗<EFBFBD><E59A97>撅<EFBFBD>䌊<EFBFBD>券<EFBFBD><E588B8><EFBFBD>
apiClient.get('/api/users').then(setUsers);
}, []);
return <div>{/* ... */}</div>;
}
*憭滨鍂<EFBFBD><EFBFBD><EFBFBD>90%+ <20>?
- <EFBFBD>?<3F><><EFBFBD>兴eact蝏<74>辣
- <EFBFBD>?<3F><><EFBFBD>务I摨橒<E691A8>Ant Design嚗?
- <EFBFBD>?<3F><><EFBFBD>厩𠶖<E58EA9><F0A0B696>恣<EFBFBD><E681A3><EFBFBD>Zustand嚗?
- <EFBFBD>?<3F><><EFBFBD>㕑楝<E39591>梧<EFBFBD>React Router嚗?
- <EFBFBD>𩤃<EFBFBD> <20>芷<EFBFBD>靽格㺿API靚<49>鍂撅<E98D82><E69285>1銝芣<E98A9D>隞塚<E99A9E>
2. <20>𡒊垢隞<E59EA2><E99A9E>憭滨鍂嚗?0%+ 憭滨鍂嚗?
*<EFBFBD>唳<EFBFBD><EFBFBD>𡒊垢隞<EFBFBD><EFBFBD>嚗Áeb<EFBFBD><EFBFBD><EFBFBD>嚗?
// backend/src/routes/users.ts
import { FastifyInstance } from 'fastify';
export async function userRoutes(fastify: FastifyInstance) {
// GET /api/users
fastify.get('/api/users', async (request, reply) => {
const users = await prisma.user.findMany();
return users;
});
// POST /api/users
fastify.post('/api/users', async (request, reply) => {
const user = await prisma.user.create({
data: request.body
});
return user;
});
}
*Electron<EFBFBD><EFBFBD><EFBFBD>蝡荔<EFBFBD>銝餉<EFBFBD>蝔页<EFBFBD>嚗?
// electron-backend/src/ipc-handlers.ts
import { ipcMain } from 'electron';
import { prisma } from './prisma-client';
// 憭滨鍂銝𡁜𦛚<F0A1819C>餉<EFBFBD> 潃?
import { UserService } from '../../../backend/src/services/user.service';
export function setupIpcHandlers() {
const userService = new UserService(prisma);
// 撠<>TTP頝舐眏頧祆揢銝截PC Handler
ipcMain.handle('api-request', async (event, { method, url, data }) => {
// 頝舐眏<E88890><E79C8F><EFBFBD>嚗<EFBFBD><E59A97><EFBFBD>𣇉<EFBFBD><F0A38789><EFBFBD>astify嚗?
if (url === '/api/users' && method === 'GET') {
return userService.findAll();
}
if (url === '/api/users' && method === 'POST') {
return userService.create(data);
}
// ... <20>嗡<EFBFBD>頝舐眏
});
}
*<EFBFBD>詨<EFBFBD>銝𡁜𦛚<EFBFBD>餉<EFBFBD>摰<EFBFBD><EFBFBD>憭滨鍂嚗?
// backend/src/services/user.service.ts
// 餈嗘葵<E59798><E891B5>辣<EFBFBD>汾eb<65><62><EFBFBD>Electron<6F><6E><EFBFBD><EFBFBD>典<EFBFBD>鈭?<3F>?
export class UserService {
constructor(private prisma: PrismaClient) {}
async findAll() {
return this.prisma.user.findMany();
}
async create(data: CreateUserDto) {
// 銝𡁜𦛚<F0A1819C>餉<EFBFBD>
const hashedPassword = await bcrypt.hash(data.password, 10);
return this.prisma.user.create({
data: {
...data,
password: hashedPassword
}
});
}
}
*憭滨鍂<EFBFBD><EFBFBD><EFBFBD>80%+ <20>?
- <EFBFBD>?<3F><><EFBFBD>农ervice撅<65><E69285>銝𡁜𦛚<F0A1819C>餉<EFBFBD>嚗?
- <EFBFBD>?<3F><><EFBFBD>侨risma Model<65>峕䰻霂?
- <EFBFBD>?<3F><><EFBFBD>匧極<E58CA7>瑕遆<E79195>?
- <EFBFBD>𩤃<EFBFBD> <20><>閬<EFBFBD><E996AC><EFBFBD><EFBFBD>嚗䥅TTP頝舐眏 <20>?IPC Handler
- <EFBFBD>𩤃<EFBFBD> <20><>閬<EFBFBD>𤜯<EFBFBD>g<EFBFBD>PostgreSQL <20>?SQLite
3. <20>唳旿摨㯄<E691A8><E3AF84><EFBFBD>嚗㇊ostgreSQL <20>?SQLite嚗?
*Prisma Schema靽格㺿嚗<E3BABF><E59A97>撠𤩺㺿<F0A4A9BA>剁<EFBFBD>嚗?
// electron-backend/prisma/schema.prisma
datasource db {
// Web<65><62><EFBFBD>PostgreSQL
// provider = "postgresql"
// url = env("DATABASE_URL")
// Electron<6F><6E><EFBFBD>SQLite 潃?
provider = "sqlite"
url = "file:./app.db"
}
// Model摰帋<E691B0>摰<EFBFBD><E691B0>銝滚<E98A9D> <20>?
model User {
id String @id @default(uuid())
email String @unique
password String
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users")
}
*瘜冽<EFBFBD>鈭钅★嚗?
// SQLite銝齿𣈲<E9BDBF><F0A388B2><EFBFBD>鈭𢏺ostgreSQL<51>寞<EFBFBD>?
// <20>?PostgreSQL<51>舀<EFBFBD>嚗玺QLite銝齿𣈲<E9BDBF><F0A388B2><EFBFBD>
- JSON<EFBFBD>㛖掩<EFBFBD>页<EFBFBD><EFBFBD><EFBFBD>閬<EFBFBD>鍂TEXT摮睃<EFBFBD>嚗?
- 憭齿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝝?
- <EFBFBD>𣂷<EFBFBD><EFBFBD>𡁜<EFBFBD><EFBFBD>賣㺭
// <20>?閫<><E996AB><EFBFBD>寞<EFBFBD>嚗?
// 1. <20>汽EXT摮睃<E691AE>JSON嚗<4E><E59A97><EFBFBD>典<EFBFBD><E585B8>堒<EFBFBD>嚗?
model Config {
id String @id
data String // JSON.stringify(data)
}
// 2. 蝞<><E89D9E>𡝗䰻霂g<E99C82><EFBD87>踹<EFBFBD>憭齿<E686AD>SQL嚗?
// 3. <20>典<EFBFBD><E585B8>典<EFBFBD>摰䂿緵<E482BF>𣂷<EFBFBD><F0A382B7>蠘<EFBFBD>
摰峕㟲憿寧𤌍蝏𤘪<EFBFBD>
AIclinicalresearch/
<20>鎿<EFBFBD><E98EBF><EFBFBD> packages/ # <20>曹澈隞<E6BE88><E99A9E>嚗㇈onorepo嚗?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> frontend-core/ # <20>滨垢<E6BBA8>詨<EFBFBD>嚗Áeb + Electron憭滨鍂嚗?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> backend-core/ # <20>𡒊垢<F0A1928A>詨<EFBFBD>嚗Áeb + Electron憭滨鍂嚗?
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> shared-types/ # <20>曹澈蝐餃<E89D90>摰帋<E691B0>
<20>?
<20>鎿<EFBFBD><E98EBF><EFBFBD> apps/
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> web/ # Web<65><62><EFBFBD>敶枏<E695B6>嚗?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> frontend/
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> backend/
<20>? <20>?
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> electron/ # Electron<6F>?潃?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> main/ # 銝餉<E98A9D>蝔页<E89D94>Node.js<6A>𡒊垢嚗?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> src/
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> main.ts # Electron<6F>亙藁
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> ipc-handlers.ts # IPC憭<43><E686AD><EFBFBD>?
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> services/ # 憭滨鍂backend-core
<20>? <20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> prisma/
<20>? <20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> schema.prisma # SQLite<74><65>𧋦
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> renderer/ # 皜脫<E79A9C>餈𤤿<E9A488>嚗㇌eact<63>滨垢嚗?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> src/
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> main.tsx
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> api/ # IPC摰X<E691B0>蝡?
<20>? <20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> pages/ # 憭滨鍂frontend-core
<20>? <20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> components/ # 憭滨鍂frontend-core
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> package.json
<20>? <20>?
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> resources/ # <20>枏<EFBFBD>韏<EFBFBD><E99F8F>
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> python/ # Python餈鞱<E9A488><E99EB1>?
<20>? <20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> r/ # R餈鞱<E9A488><E99EB1>塚<EFBFBD>憒<EFBFBD><E68692>閬<EFBFBD><E996AC>
<20>? <20>? <20>婙<EFBFBD><E5A999><EFBFBD> assets/
<20>? <20>?
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> electron-builder.yml # <20>枏<EFBFBD><E69E8F>滨蔭
<20>?
<20>婙<EFBFBD><E5A999><EFBFBD> ...
<EFBFBD>喲睸摰䂿緵蝏<EFBFBD><EFBFBD>
1. Electron銝餉<E98A9D>蝔页<E89D94>main.ts嚗?
// apps/electron/main/src/main.ts
import { app, BrowserWindow, ipcMain } from 'electron';
import path from 'path';
import { setupIpcHandlers } from './ipc-handlers';
import { initDatabase } from './database';
import { startPythonService } from './python-service';
let mainWindow: BrowserWindow | null = null;
async function createWindow() {
// 1. <20>𥕦遣瘚讛<E7989A><E8AE9B>函<EFBFBD><E587BD>?
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js') // 摰匧<E691B0><E58CA7><EFBFBD>PC獢交𦻖
}
});
// 2. <20>㰘蝸<E3B098>滨垢嚗<E59EA2><E59A97>鈭抒㴓憓<E3B493><E68693>
if (app.isPackaged) {
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
} else {
// 撘<><E69298>𤑳㴓憓<E3B493><E68693>餈墧𦻖<E5A2A7>訓ite撘<65><E69298>烐<EFBFBD><E78390>∪膥
mainWindow.loadURL('http://localhost:5173');
}
// 3. <20>嘥<EFBFBD><E598A5>𡝗㺭<F0A19D97>桀<EFBFBD>
await initDatabase();
// 4. <20>臬𢆡Python<6F><6E>﹝憭<EFB99D><E686AD><EFBFBD>滚𦛚
await startPythonService();
// 5. 霈曄蔭IPC憭<43><E686AD><EFBFBD>?
setupIpcHandlers();
}
// Electron<6F>笔𦶢<E7AC94>冽<EFBFBD>
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
2. IPC憭<43><E686AD><EFBFBD>剁<EFBFBD>ipc-handlers.ts嚗?
// apps/electron/main/src/ipc-handlers.ts
import { ipcMain } from 'electron';
import { prisma } from './prisma-client';
// 憭滨鍂銝𡁜𦛚<F0A1819C>餉<EFBFBD> 潃?
import { UserService } from '@yizhengxun/backend-core/services';
import { ProjectService } from '@yizhengxun/backend-core/services';
import { ConversationService } from '@yizhengxun/backend-core/services';
export function setupIpcHandlers() {
// <20>嘥<EFBFBD><E598A5>𡝗<EFBFBD><F0A19D97>?
const userService = new UserService(prisma);
const projectService = new ProjectService(prisma);
const conversationService = new ConversationService(prisma);
// <20>冽<EFBFBD><E586BD>詨<EFBFBD>API
ipcMain.handle('api:users:list', async () => {
return userService.findAll();
});
ipcMain.handle('api:users:create', async (event, data) => {
return userService.create(data);
});
// 憿寧𤌍<E5AFA7>詨<EFBFBD>API
ipcMain.handle('api:projects:list', async (event, userId) => {
return projectService.findByUser(userId);
});
ipcMain.handle('api:projects:create', async (event, data) => {
return projectService.create(data);
});
// 撖寡<E69296><E5AFA1>詨<EFBFBD>API
ipcMain.handle('api:conversations:create', async (event, data) => {
return conversationService.create(data);
});
ipcMain.handle('api:conversations:chat', async (event, data) => {
// 靚<>鍂LLM嚗<4D>𧋦<EFBFBD>唳<EFBFBD>鈭𤑳垢API嚗?
return conversationService.chat(data);
});
// <20><>辣<EFBFBD>滢<EFBFBD>
ipcMain.handle('api:files:upload', async (event, file) => {
// 靽嘥<E99DBD><E598A5>唳𧋦<E594B3>唳<EFBFBD>隞嗥頂蝏?
const filePath = await saveFile(file);
return { url: filePath };
});
}
3. <20>滨垢IPC摰X<E691B0>蝡荔<E89DA1>api-client.ts嚗?
// apps/electron/renderer/src/api/client.ts
const { ipcRenderer } = window.require('electron');
export const apiClient = {
// <20>冽<EFBFBD>API
users: {
async list() {
return ipcRenderer.invoke('api:users:list');
},
async create(data: any) {
return ipcRenderer.invoke('api:users:create', data);
}
},
// 憿寧𤌍API
projects: {
async list(userId: string) {
return ipcRenderer.invoke('api:projects:list', userId);
},
async create(data: any) {
return ipcRenderer.invoke('api:projects:create', data);
}
},
// 撖寡<E69296>API
conversations: {
async create(data: any) {
return ipcRenderer.invoke('api:conversations:create', data);
},
async chat(data: any) {
return ipcRenderer.invoke('api:conversations:chat', data);
}
},
// <20><>辣銝𠹺<E98A9D>
files: {
async upload(file: File) {
// 撠<>ile頧祆揢銝慷uffer
const buffer = await file.arrayBuffer();
return ipcRenderer.invoke('api:files:upload', {
name: file.name,
data: Buffer.from(buffer)
});
}
}
};
4. Python摮鞱<E691AE>蝔讠恣<E8AEA0>?
// apps/electron/main/src/python-service.ts
import { spawn, ChildProcess } from 'child_process';
import path from 'path';
import { app } from 'electron';
let pythonProcess: ChildProcess | null = null;
export async function startPythonService(): Promise<void> {
return new Promise((resolve, reject) => {
// Python餈鞱<E9A488><E99EB1>嗉楝敺<E6A59D><E695BA><EFBFBD>枏<EFBFBD><E69E8F>嗅<EFBFBD><E59785>恬<EFBFBD>
const pythonPath = app.isPackaged
? path.join(process.resourcesPath, 'python', 'python.exe')
: 'python'; // 撘<><E69298>𤑳㴓憓<E3B493>蝙<EFBFBD>函頂蝏𡼏ython
// Python<6F>𡁏𧋦頝臬<E9A09D>
const scriptPath = app.isPackaged
? path.join(process.resourcesPath, 'python', 'extraction_service', 'main.py')
: path.join(__dirname, '../../../../extraction_service/main.py');
// <20>臬𢆡Python餈𤤿<E9A488>
pythonProcess = spawn(pythonPath, [
'-m', 'uvicorn',
'main:app',
'--host', '127.0.0.1',
'--port', '8000'
], {
cwd: path.dirname(scriptPath),
stdio: 'pipe'
});
// <20>穃𨯬颲枏枂
pythonProcess.stdout?.on('data', (data) => {
console.log(`Python: ${data}`);
if (data.toString().includes('Application startup complete')) {
resolve();
}
});
pythonProcess.stderr?.on('data', (data) => {
console.error(`Python Error: ${data}`);
});
pythonProcess.on('error', reject);
});
}
export function stopPythonService(): void {
if (pythonProcess) {
pythonProcess.kill();
pythonProcess = null;
}
}
// 摨𠉛鍂<F0A0899B><E98D82><EFBFBD>箸𧒄<E7AEB8>喲𡡒Python<6F>滚𦛚
app.on('will-quit', stopPythonService);
5. <20>枏<EFBFBD><E69E8F>滨蔭嚗Ềlectron-builder.yml嚗?
# apps/electron/electron-builder.yml
appId: com.yizhengxun.aiclinical
productName: 憯寡<EFBFBD>敺服I蝘𤑳<EFBFBD><EFBFBD>拇<EFBFBD>
# <20>枏<EFBFBD><E69E8F>桀<EFBFBD>
directories:
output: dist
buildResources: resources
# Windows<77>滨蔭
win:
target:
- nsis
- portable
icon: resources/icon.ico
# NSIS摰㕑<E691B0>蝔见<E89D94><E8A781>滨蔭
nsis:
oneClick: false
allowToChangeInstallationDirectory: true
createDesktopShortcut: always
createStartMenuShortcut: true
# Mac<61>滨蔭
mac:
target:
- dmg
- zip
icon: resources/icon.icns
category: public.app-category.productivity
# <20>枏<EFBFBD><E69E8F><EFBFBD>鉄<EFBFBD><E98984><EFBFBD>隞?
files:
- "main/**/*"
- "renderer/**/*"
- "!**/*.ts"
- "!**/*.map"
# 憸嘥<E686B8>韏<EFBFBD><E99F8F>嚗㇊ython餈鞱<E9A488><E99EB1>嗥<EFBFBD>嚗?
extraResources:
- from: resources/python
to: python
- from: ../../../../extraction_service
to: python/extraction_service
# <20>枏<EFBFBD><E69E8F>𤾸之撠?
asar: true
asarUnpack:
- "**/*.node"
- "resources/**/*"
<EFBFBD>閙㦤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>喲睸<EFBFBD><EFBFBD><EFBFBD>舀<EFBFBD><EFBFBD>?
<EFBFBD>烐<EFBFBD>1嚗𡁏<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝘荔<EFBFBD>500MB+嚗?
*<EFBFBD><EFBFBD>鉄<EFBFBD><EFBFBD>捆嚗?
摰㕑<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>琜<EFBFBD>
- Electron獢<6E>沲嚗鰺100MB
- Node.js餈鞱<E9A488><E99EB1>塚<EFBFBD><E5A19A><EFBFBD>鉄<EFBFBD>汞lectron銝?
- <20>滨垢隞<E59EA2><E99A9E>嚗<EFBFBD><E59A97>霂穃<E99C82>嚗㚁<E59A97>~10MB
- <20>𡒊垢隞<E59EA2><E99A9E>嚗<EFBFBD><E59A97>霂穃<E99C82>嚗㚁<E59A97>~5MB
- SQLite<74>唳旿摨橒<E691A8>~5MB嚗<42>征摨橒<E691A8>
- Python餈鞱<E9A488><E99EB1>塚<EFBFBD>~150MB
- Python靘肽<E99D98>嚗鰺100MB
- R餈鞱<E9A488><E99EB1>塚<EFBFBD><E5A19A>舫<EFBFBD>㚁<EFBFBD>嚗鰺200MB
- R靘肽<E99D98>嚗<EFBFBD>虾<EFBFBD>㚁<EFBFBD>嚗鰺100MB
<0A>餉恣嚗?00-700MB
*隡睃<EFBFBD><EFBFBD>寞<EFBFBD>嚗?
- <EFBFBD>?雿輻鍂ASAR<41>讠憬嚗𠄌lectron暺䁅恕嚗?
- <EFBFBD>?銝滚<E98A9D><E6BB9A>俘餈鞱<E9A488><E99EB1>塚<EFBFBD>隞<EFBFBD><E99A9E>蝡舐<E89DA1><E88890><EFBFBD>閬<EFBFBD><E996AC>
- <EFBFBD>?Python靘肽<E99D98>蝎曄<E89D8E>嚗<EFBFBD>蘨<EFBFBD><E898A8>鉄敹<E98984><E695B9><EFBFBD><EFBFBD><EFBFBD>嚗?
- <EFBFBD>?憓鮋<E68693><E9AE8B>湔鰵嚗<E9B0B5>蘨銝贝蝸<E8B49D>睃<EFBFBD><E79D83><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>烐<EFBFBD>2嚗朞楊撟喳蝱<EFBFBD>澆捆<EFBFBD>?
<EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>急<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- Windows x64
- Windows ARM64嚗𠄎urface蝑㕑挽憭<E68CBD><E686AD>
- macOS x64
- macOS ARM64嚗㇁pple Silicon嚗?
- Linux x64
瘚贝<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>烐<EFBFBD>3嚗朞䌊<EFBFBD>冽凒<EFBFBD>?
*electron-updater<65>滨蔭嚗?
// apps/electron/main/src/updater.ts
import { autoUpdater } from 'electron-updater';
import { dialog } from 'electron';
export function setupAutoUpdater() {
// <20>滨蔭<E6BBA8>湔鰵<E6B994>滚𦛚<E6BB9A>?
autoUpdater.setFeedURL({
provider: 'generic',
url: 'https://releases.yizhengxun.com'
});
// 璉<><E79289>交凒<E4BAA4>?
autoUpdater.checkForUpdatesAndNotify();
// <20>𤑳緵<F0A491B3>啁<EFBFBD><E59581>?
autoUpdater.on('update-available', () => {
dialog.showMessageBox({
type: 'info',
title: '<27>𤑳緵<F0A491B3>啁<EFBFBD><E59581>?,
message: '璉<EFBFBD>瘚见<EFBFBD><EFBFBD>啁<EFBFBD><EFBFBD>穿<EFBFBD><EFBFBD>臬炏蝡见朖銝贝蝸嚗?,
buttons: ['<27>?, '<EFBFBD>?]
}).then((result) => {
if (result.response === 0) {
autoUpdater.downloadUpdate();
}
});
});
// 銝贝蝸摰峕<E691B0>
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({
type: 'info',
title: '<27>湔鰵撌脣停蝏?,
message: '<EFBFBD>啁<EFBFBD><EFBFBD>砍歇銝贝蝸嚗峕糓<EFBFBD>衣<EFBFBD><EFBFBD>喳<EFBFBD>鋆<EFBFBD><EFBFBD>',
buttons: ['蝡见朖摰㕑<EFBFBD>', '蝔滚<EFBFBD>']
}).then((result) => {
if (result.response === 0) {
autoUpdater.quitAndInstall();
}
});
});
}
<EFBFBD><EFBFBD> <20>餌<EFBFBD>撖寞<E69296>
銝厩<EFBFBD><EFBFBD>函蔡<EFBFBD>孵<EFBFBD>撖寞<EFBFBD>
| 蝏游漲 | 鈭𤑳垢SaaS | <EFBFBD>祉<EFBFBD>鈭批<EFBFBD><EFBFBD>? | Electron<EFBFBD>閙㦤<EFBFBD>? |
|---|---|---|---|
| <EFBFBD>函蔡<EFBFBD>孵<EFBFBD> | 鈭𤑳垢<EFBFBD>滚𦛚<EFBFBD>? | Docker摰孵膥 | <EFBFBD>砍𧑐摰㕑<EFBFBD> |
| <EFBFBD>唳旿摮睃<EFBFBD> | 鈭𤑳垢PostgreSQL | <EFBFBD>砍𧑐PostgreSQL | <EFBFBD>砍𧑐SQLite |
| *蝵𤑳<EFBFBD><EFBFBD><EFBFBD>瘙? | 敹<EFBFBD>◆<EFBFBD>𠉛<EFBFBD> | <EFBFBD>舐氖蝥選<EFBFBD>LLM<EFBFBD>文<EFBFBD>嚗? | 摰<EFBFBD><EFBFBD>蝳餌瑪 |
| <EFBFBD>湔鰵<EFBFBD>孵<EFBFBD> | <EFBFBD>䭾<EFBFBD><EFBFBD>交凒<EFBFBD>? | Docker<EFBFBD>𨅯<EFBFBD><EFBFBD>湔鰵 | 摨𠉛鍂<EFBFBD><EFBFBD>凒<EFBFBD>? |
| 摰㕑<EFBFBD><EFBFBD>曉漲 | <EFBFBD>𣳇<EFBFBD>摰㕑<EFBFBD> | Docker<EFBFBD>函蔡 | 銝<EFBFBD><EFBFBD>桀<EFBFBD>鋆? |
| 隞<EFBFBD><EFBFBD>憭滨鍂 | 100% | 80%嚗<>移蝞<E7A7BB><E89D9E><EFBFBD><EFBFBD> | 90% |
| <EFBFBD><EFBFBD>鍂摰X<EFBFBD> | 銝芯犖<EFBFBD><EFBFBD><EFBFBD><EFBFBD>箸<EFBFBD> | <EFBFBD>駁堺<EFBFBD><EFBFBD>之<EFBFBD>箸<EFBFBD> | 銝芯犖<EFBFBD>餌<EFBFBD> |
| <EFBFBD><EFBFBD><EFBFBD>璅∪<EFBFBD> | 霈a<EFBFBD><EFBFBD>? | 銝<EFBFBD>甈⊥<EFBFBD>兵icense | 銝<EFBFBD>甈⊥<EFBFBD>扯揚銋? |
| 蝏湔擪<EFBFBD>鞉𧋦 | 雿? | 銝? | 擃? |
<EFBFBD>㴓 <20><>蝏<EFBFBD>遣霈?
<EFBFBD><EFBFBD>𧫴畾萄<EFBFBD><EFBFBD>?
<EFBFBD>嗆挾銝<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>?6銝芣<E98A9D>嚗㚁<E59A97>
- <EFBFBD>?銝𤘪釣鈭𤑳垢SaaS<61>?
- <EFBFBD>?摰<><E691B0>7銝芯<E98A9D><E88AAF>⊥芋<E28AA5>?
- <EFBFBD>?撱箇<E692B1>Monorepo<70>嗆<EFBFBD>嚗<EFBFBD>蛹<EFBFBD>芣䔉<E88AA3>枏抅蝖<E68A85>嚗?
<EFBFBD>嗆挾鈭䕘<EFBFBD>6-12銝芣<E98A9D>嚗㚁<E59A97>
- <EFBFBD>?撘<><E69298>𤑳𡠺蝡衤漣<E8A1A4><E6BCA3><EFBFBD>嚗<EFBFBD>恣蝔輻頂蝏麄<E89D8F><E9BA84>I<EFBFBD><49>讃嚗?
- <EFBFBD>?<3F>舀<EFBFBD>Docker<65>砍𧑐<E7A08D>㚚<EFBFBD>蝵?
- <EFBFBD>?撉諹<E69289><E8ABB9><EFBFBD><EFBFBD>璅∪<E79285>
<EFBFBD>嗆挾銝㚁<EFBFBD>12-18銝芣<E98A9D>嚗㚁<E59A97>
- <EFBFBD>?撘<><E69298>䫿lectron<6F>閙㦤<E99699><E3A6A4><EFBFBD>憒<EFBFBD><E68692><EFBFBD><EFBFBD>瘙<EFBFBD><E79899>
- <EFBFBD>?<3F>舀<EFBFBD>摰<EFBFBD><E691B0>蝳餌瑪雿輻鍂
- <EFBFBD>?<3F>拙<EFBFBD>銝芯犖<E88AAF>冽<EFBFBD>撣<EFBFBD>㦤
<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>楛<EFBFBD>亙𪑛銝芣䲮獢<EFBFBD><EFBFBD>
- 璅∪<EFBFBD><EFBFBD>祉<EFBFBD><EFBFBD>函蔡<EFBFBD><EFBFBD>祕蝏<EFBFBD><EFBFBD><EFBFBD>踝<EFBFBD>
- Electron<EFBFBD>閙㦤<EFBFBD><EFBFBD><EFBFBD>撘<EFBFBD><EFBFBD>𤏸恣<EFBFBD>𡜐<EFBFBD>
- Monorepo<EFBFBD>嗆<EFBFBD><EFBFBD><EFBFBD>挽霈∴<EFBFBD>