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%)
1353 lines
43 KiB
Markdown
1353 lines
43 KiB
Markdown
# DC璅∪<E79285> Tool-B 撘<><E69298>𤏸恣<F0A48FB8>?
|
||
> **<2A><>﹝<EFBFBD><EFB99D>𧋦嚗?* V2.0 (MVP摰峕<E691B0>)
|
||
> **<2A>𥕦遣<F0A595A6>交<EFBFBD>嚗?* 2025-12-02
|
||
> **摰峕<E691B0><E5B395>交<EFBFBD>嚗?* 2025-12-03
|
||
> **摰鮋<E691B0><E9AE8B>冽<EFBFBD>嚗?* 2銝芸極雿𨀣𠯫
|
||
> **<2A>嗆<EFBFBD><E59786><EFBFBD>** <20>?MVP摰峕<E691B0>
|
||
|
||
---
|
||
|
||
## <20><> MVP摰峕<E691B0><E5B395>𡁜<EFBFBD>嚗?025-12-03嚗?
|
||
**Tool B<><42><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖MVP<56><50>𧋦撌脣<E6928C><E884A3>琜<EFBFBD>**
|
||
|
||
- <20>?<3F>滨垢5甇亙極雿𨀣<E99BBF>摰峕㟲摰䂿緵嚗ǚ1400銵䕘<E98AB5>
|
||
- <20>?8銝服PI蝡舐<E89DA1><E88890>券<EFBFBD>撖寞𦻖撟嗆<E6929F>霂閖<E99C82>朞<EFBFBD>
|
||
- <20>?LLM<4C>峕芋<E5B395>𧢲<EFBFBD><F0A7A2B2>㚚<EFBFBD>霂<EFBFBD><E99C82><EFBFBD><EFBFBD><EFBFBD>DeepSeek-V3 + Qwen-Max嚗?- <20>?<3F>笔<EFBFBD><E7AC94>唳旿瘚贝<E7989A>嚗?<3F>∠<EFBFBD><E288A0><EFBFBD>𥁒<EFBFBD>𦠜<EFBFBD><F0A6A09C>𡝗<EFBFBD><F0A19D97>?- <20>?Excel撖澆枂<E6BE86>蠘<EFBFBD><E8A098>舐鍂
|
||
- <20>𩤃<EFBFBD> 4銝芣<E98A9D><E88AA3>臬<EFBFBD>箏𦛚敺<F0A69B9A><E695BA><EFBFBD><EFBFBD><EFBFBD>閫<EFBFBD>07-<2D><><EFBFBD>臬<EFBFBD>箏𦛚/Tool-B<><42><EFBFBD>臬<EFBFBD>箏𦛚皜<F0A69B9A><E79A9C>.md`嚗?
|
||
**摰峕<E691B0>霂行<E99C82>嚗?* <20><><EFBFBD> `06-撘<><E69298>𤏸扇敶?Tool-B-MVP摰峕<E691B0><E5B395>餌<EFBFBD>-2025-12-03.md`
|
||
|
||
---
|
||
|
||
## <20>笔<EFBFBD>撘<EFBFBD><E69298>𤏸恣<F0A48FB8>?
|
||
> **<2A>格<EFBFBD>嚗?* 摰峕<E691B0>Tool-B嚗<42><E59A97><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>箏膥鈭綽<E988AD><E7B6BD><EFBFBD><EFBFBD>蝡臬<E89DA1><E887AC>穃<EFBFBD>摰峕㟲<E5B395>蠘<EFBFBD><E8A098><EFBFBD><EFBFBD>
|
||
|
||
---
|
||
|
||
## <20><> 銝<><E98A9D><EFBFBD>★<EFBFBD>桀<EFBFBD><E6A180>滨𠶖<E6BBA8><F0A0B696><EFBFBD><EFBFBD>娍<EFBFBD>餌<EFBFBD>
|
||
|
||
### 1.1 <20>𡒊垢隞<E59EA2><E99A9E><EFBFBD>嗆<EFBFBD>?<3F>?100%摰峕<E691B0>
|
||
|
||
#### <20>𡁶鍂<F0A181B6>賢<EFBFBD>撟喳蝱嚗<E89DB1>虾憭滨鍂嚗?<3F>箔<EFBFBD> `backend/src/common/` 撟喳蝱<E596B3>箇<EFBFBD>霈暹鴌嚗<E9B48C>歇摰峕㟲摰䂿緵嚗?
|
||
| <20>賢<EFBFBD>璅∪<E79285> | 撖澆<E69296>頝臬<E9A09D> | <20>蠘<EFBFBD>霂湔<E99C82> | <20>嗆<EFBFBD>?|
|
||
|---------|---------|---------|------|
|
||
| **摮睃<E691AE><E79D83>滚𦛚** | `@/common/storage` | <20><>辣銝𠹺<E98A9D>/銝贝蝸嚗𡿨ocal <20>?OSS嚗?| <20>?摰峕<E691B0> |
|
||
| **<EFBFBD>亙<EFBFBD>蝟餌<EFBFBD>** | `@/common/logging` | 蝏𤘪<E89D8F><F0A498AA>𡝗𠯫敹梹<E695B9>Winston嚗?| <20>?摰峕<E691B0> |
|
||
| **蝻枏<E89DBB><E69E8F>滚𦛚** | `@/common/cache` | 蝻枏<E89DBB>嚗㇈emory <20>?Redis嚗?| <20>?摰峕<E691B0> |
|
||
| **撘<>郊隞餃𦛚** | `@/common/jobs` | <20>踵𧒄<E8B8B5>港遙<E6B8AF>⊿<EFBFBD><E28ABF>?| <20>?摰峕<E691B0> |
|
||
| **LLM撌亙<E6928C>** | `@/common/llm/adapters/LLMFactory` | 蝏煺<E89D8F>LLM靚<4D>鍂嚗㇄eepSeek/Qwen/GPT/Claude嚗?| <20>?摰峕<E691B0> |
|
||
| **<EFBFBD>唳旿摨?* | `@/config/database` | Prisma餈墧𦻖瘙?| <20>?摰峕<E691B0> |
|
||
|
||
**憭滨鍂蝑𣇉裦**嚗?- <20>?Tool B<>𡒊垢隞<E59EA2><E99A9E>撌?00%憭滨鍂撟喳蝱<E596B3>賢<EFBFBD>
|
||
- <20>?<3F>滨垢撘<E59EA2><E69298>穃<EFBFBD><E7A983><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝡舀芋撘𧶏<E69298>憭滨鍂<E6BBA8>滨垢<E6BBA8>曹澈蝏<E6BE88>辣
|
||
|
||
---
|
||
|
||
#### Tool B<>𡒊垢摰䂿緵<E482BF>嗆<EFBFBD>?
|
||
**隞<><E99A9E>雿滨蔭**嚗䫤backend/src/modules/dc/tool-b/`
|
||
|
||
| <20><>辣 | <20>蠘<EFBFBD> | 隞<><E99A9E><EFBFBD>?| <20>嗆<EFBFBD>?| 憭滨鍂<E6BBA8>賢<EFBFBD> |
|
||
|-----|------|--------|------|---------|
|
||
| **services/HealthCheckService.ts** | Excel<65>亙熒璉<E78692><E79289>?| ~190銵?| <20>?摰峕<E691B0> | storage, logger, cache, prisma |
|
||
| **services/TemplateService.ts** | 憸<>挽璅⊥踎蝞∠<E89D9E> | ~243銵?| <20>?摰峕<E691B0> | logger, prisma |
|
||
| **services/DualModelExtractionService.ts** | <20>峕芋<E5B395>𧢲<EFBFBD><F0A7A2B2>?| ~390銵?| <20>?摰峕<E691B0> | LLMFactory, logger, prisma |
|
||
| **services/ConflictDetectionService.ts** | <20>脩<EFBFBD>璉<EFBFBD>瘚讠<E7989A>瘜?| ~215銵?| <20>?摰峕<E691B0> | logger |
|
||
| **controllers/ExtractionController.ts** | API<50>批<EFBFBD><E689B9>?| ~388銵?| <20>?摰峕<E691B0> | <20>券<EFBFBD><E588B8>滚𦛚 |
|
||
| **routes/index.ts** | 頝舐眏<E88890>滨蔭 | ~115銵?| <20>?摰峕<E691B0> | - |
|
||
| **index.ts** | 璅∪<E79285><E288AA>亙藁 | ~117銵?| <20>?摰峕<E691B0> | - |
|
||
|
||
**<2A>餉恣**嚗𡁶漲1,658銵䕘<E98AB5>7銝芣<E98A9D>隞塚<E99A9E>100%摰峕<E691B0>
|
||
|
||
---
|
||
|
||
#### API蝡舐<E89DA1>皜<EFBFBD><E79A9C>
|
||
|
||
**Base URL**: `/api/v1/dc/tool-b`
|
||
|
||
| <20>寞<EFBFBD> | 頝臬<E9A09D> | <20>蠘<EFBFBD> | 霂瑟<E99C82>雿?| <20>滚<EFBFBD> | <20>嗆<EFBFBD>?|
|
||
|------|------|------|--------|------|------|
|
||
| **POST** | `/health-check` | Excel<65>堒<EFBFBD>摨瑟<E691A8><E7919F>?| `{fileKey, columnName}` | <20>亙熒摨行𥁒<E8A18C>?| <20>?摰峕<E691B0> |
|
||
| **GET** | `/templates` | <20>瑕<EFBFBD>憸<EFBFBD>挽璅⊥踎<E28AA5>𡑒” | - | 璅⊥踎<E28AA5>啁<EFBFBD> | <20>?摰峕<E691B0> |
|
||
| **POST** | `/tasks` | <20>𥕦遣<F0A595A6>𣂼<EFBFBD>隞餃𦛚 | `{projectName, fileKey, textColumn, diseaseType, reportType}` | `{taskId}` | <20>?摰峕<E691B0> |
|
||
| **GET** | `/tasks/:taskId/progress` | <20>亥砭隞餃𦛚餈𥕦漲 | - | 餈𥕦漲霂行<E99C82> | <20>?摰峕<E691B0> |
|
||
| **GET** | `/tasks/:taskId/items` | <20>瑕<EFBFBD>撉諹<E69289>蝵烐聢<E78390>唳旿 | `?status=conflict&page=1` | <20><>△<EFBFBD>唳旿 | <20>?摰峕<E691B0> |
|
||
| **POST** | `/items/:itemId/resolve` | 鋆<><E98B86><EFBFBD>脩<EFBFBD> | `{resolvedData}` | <20>𣂼<EFBFBD><F0A382BC>嗆<EFBFBD>?| <20>?摰峕<E691B0> |
|
||
|
||
**憸<>挽璅⊥踎**嚗?銝迎<E98A9D>嚗?1. <20>箇<EFBFBD><E7AE87><EFBFBD><EFBFBD><EFBFBD>亙<EFBFBD>嚗Ǒlung_cancer/pathology`嚗? 5銝芸<E98A9D>畾?2. 蝟硋倏<E7A18B><E5808F><EFBFBD><EFBFBD>Z扇敶𤏪<E695B6>`diabetes/admission`嚗? 5銝芸<E98A9D>畾?3. 擃䁅<E69383><E48185>钅秄霂羓<E99C82><E7BE93><EFBFBD><EFBFBD>`hypertension/outpatient`嚗? 5銝芸<E98A9D>畾?
|
||
---
|
||
|
||
### 1.2 <20>唳旿摨梶𠶖<E6A2B6>?<3F>?撌脤<E6928C>霂<EFBFBD><E99C82><EFBFBD>琜<EFBFBD>2025-12-02嚗?
|
||
**Schema**: `dc_schema`嚗<EFBFBD>𡠺蝡钅<EFBFBD>蝳鳴<EFBFBD>
|
||
|
||
| 銵典<E98AB5> | <20>券<EFBFBD>?| 摮埈挾<E59F88>?| <20>喲睸摮埈挾 | <20>嗆<EFBFBD>?| <20>唳旿<E594B3>?|
|
||
|------|------|--------|---------|------|--------|
|
||
| **dc_health_checks** | <20>亙熒璉<E78692><E79289>亥扇敶?| 10 | status, emptyRate, avgLength | <20>?撌脣<E6928C>撱?| 2<>?|
|
||
| **dc_templates** | 憸<>挽璅⊥踎 | 7 | diseaseType, reportType, fields | <20>?撌脣<E6928C>撱?| **3<>?* |
|
||
| **dc_extraction_tasks** | <20>𣂼<EFBFBD>隞餃𦛚 | 21 | status, totalCount, processedCount | <20>?撌脣<E6928C>撱?| 1<>?|
|
||
| **dc_extraction_items** | <20>𣂼<EFBFBD><F0A382BC>𡒊<EFBFBD> | 15 | resultA, resultB, conflictFields | <20>?撌脣<E6928C>撱?| 4<>?|
|
||
|
||
**<EFBFBD>?撉諹<E69289>蝏𤘪<E89D8F>嚗?025-12-02嚗?*嚗?- <20>?**dc_schema撌脣<E6928C><E884A3>?*
|
||
- <20>?**4銝芾”<E88ABE>券<EFBFBD><E588B8>𥕦遣<F0A595A6>𣂼<EFBFBD>**
|
||
- <20>?**3銝芷<E98A9D>霈暹芋<E69AB9>踹歇<E8B8B9>嘥<EFBFBD><E598A5>?*嚗? 1. <20>箇<EFBFBD><E7AE87><EFBFBD><EFBFBD><EFBFBD>亙<EFBFBD> (lung_cancer/pathology)
|
||
2. 蝟硋倏<E7A18B><E5808F><EFBFBD><EFBFBD>Z扇敶?(diabetes/admission)
|
||
3. 擃䁅<E69383><E48185>钅秄霂羓<E99C82><E7BE93>?(hypertension/outpatient)
|
||
- <20>?**<2A>㗇<EFBFBD>霂閙㺭<E99699>桀虾<E6A180>其<EFBFBD>撘<EFBFBD><E69298>𤏸<EFBFBD>霂?*
|
||
|
||
**撉諹<E69289><E8ABB9>𡁏𧋦**嚗?```bash
|
||
cd backend
|
||
node scripts/check-dc-tables.mjs # <20>扯<EFBFBD><E689AF>唳旿摨栞”璉<E2809D><E79289>亥<EFBFBD><E4BAA5>?```
|
||
|
||
**蝏栞捏**嚗尠<E59A97> <20>唳旿摨枏<E691A8><E69E8F>典<EFBFBD>憭<EFBFBD>停蝏迎<E89D8F><E8BF8E>臭誑撘<E8AA91>憪见<E686AA>蝡臬<E89DA1><E887AC>𡢅<EFBFBD>
|
||
|
||
---
|
||
|
||
### 1.3 <20>滨垢隞<E59EA2><E99A9E><EFBFBD>嗆<EFBFBD>?<3F>?0%嚗<><E59A97>Placeholder嚗?
|
||
**隞<><E99A9E>雿滨蔭**嚗䫤frontend-v2/src/modules/dc/`
|
||
|
||
```
|
||
frontend-v2/src/modules/dc/
|
||
<EFBFBD>鎿<EFBFBD><EFBFBD><EFBFBD> index.tsx # <20>?隞<>laceholder嚗?4銵䕘<E98AB5>
|
||
<EFBFBD>鎿<EFBFBD><EFBFBD><EFBFBD> components/ # <20><> 蝛?<3F>鎿<EFBFBD><E98EBF><EFBFBD> pages/ # <20><> 蝛箸<E89D9B>隞嗅允蝏𤘪<E89D8F>
|
||
<EFBFBD>? <20>鎿<EFBFBD><E98EBF><EFBFBD> tool-a/ # <20><> 蝛?<3F>? <20>鎿<EFBFBD><E98EBF><EFBFBD> tool-b/ # <20><> 蝛?<3F>? <20>婙<EFBFBD><E5A999><EFBFBD> tool-c/ # <20><> 蝛?<3F>婙<EFBFBD><E5A999><EFBFBD> types/ # <20><> 蝛?```
|
||
|
||
**敶枏<E695B6><E69E8F><EFBFBD>捆**嚗?```typescript
|
||
// frontend-v2/src/modules/dc/index.tsx
|
||
import Placeholder from '@/shared/components/Placeholder'
|
||
|
||
const DCModule = () => {
|
||
return (
|
||
<Placeholder
|
||
title="<22>唳旿皜<E697BF><E79A9C>璅∪<E79285>"
|
||
description="<22>蠘<EFBFBD>閫<EFBFBD><E996AB>銝哨<E98A9D>撠<EFBFBD><E692A0>靘𥟇惣<F0A59F87>賣㺭<E8B3A3>格<EFBFBD>瘣堒<E798A3><E5A092>渡<EFBFBD>撌亙<E6928C>"
|
||
moduleName="DC - Data Cleaning"
|
||
/>
|
||
)
|
||
}
|
||
export default DCModule
|
||
```
|
||
|
||
---
|
||
|
||
### 1.4 <20>滨垢<E6BBA8>嗆<EFBFBD>霈曇恣 <20>?撌脫<E6928C>蝖?
|
||
#### 蝟餌<E89D9F>蝥扳沲<E689B3>?- **撖潸⏛璅∪<E79285>**嚗𡁻▲<F0A181BB>典紡<E585B8>?- **頝舐眏頝臬<E9A09D>**嚗䫤/data-cleaning`
|
||
- **<2A><><EFBFBD>舀<EFBFBD>**嚗鑹eact 19 + TypeScript + Vite + Ant Design 5
|
||
|
||
#### DC璅∪<E79285><E288AA>嗆<EFBFBD><E59786>寞<EFBFBD>
|
||
|
||
**<EFBFBD>㗇𥋘嚗𡁏䲮獢㇁ - <20>祉<EFBFBD>Portal憿菟𢒰**嚗<>綫<EFBFBD>琜<EFBFBD>
|
||
|
||
```
|
||
/data-cleaning (Portal撌乩<E6928C><E4B9A9>?- <20>餉<EFBFBD>憿?
|
||
<20>鎿<EFBFBD><E98EBF><EFBFBD> 敹恍<E695B9>笔鍳<E7AC94>典躹嚗?銝芸極<E88AB8>瑕㨃<E79195><E3A883><EFBFBD>
|
||
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> [頞<>漣<EFBFBD><E6BCA3>僎<EFBFBD>沘 <20>?/data-cleaning/tool-a
|
||
<20>? <20>鎿<EFBFBD><E98EBF><EFBFBD> [<5B><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𨭐 <20>?/data-cleaning/tool-b
|
||
<20>? <20>婙<EFBFBD><E5A999><EFBFBD> [<5B>唳旿蝻𤥁<E89DBB><F0A4A581>沘 <20>?/data-cleaning/tool-c
|
||
<20>鎿<EFBFBD><E98EBF><EFBFBD> <20><>餈睲遙<E79DB2>∪<EFBFBD>銵剁<E98AB5>摰墧𧒄餈𥕦漲嚗? <20>婙<EFBFBD><E5A999><EFBFBD> <20>唳旿韏<E697BF>漣摨橒<E691A8><E6A992><EFBFBD>辣蝞∠<E89D9E>嚗?
|
||
/data-cleaning/tool-b (Tool B - <20>典<EFBFBD>5甇交<E79487>蝔?
|
||
<20>鎿<EFBFBD><E98EBF><EFBFBD> Step 1: 銝𠹺<E98A9D>銝𤾸<E98A9D>摨瑟<E691A8><E7919F>? <20>鎿<EFBFBD><E98EBF><EFBFBD> Step 2: <20>箄<EFBFBD>璅⊥踎<E28AA5>滨蔭
|
||
<20>鎿<EFBFBD><E98EBF><EFBFBD> Step 3: <20>𣬚𤩅<F0A3AC9A>𣂼<EFBFBD>餈𥕦漲
|
||
<20>鎿<EFBFBD><E98EBF><EFBFBD> Step 4: <20>脩<EFBFBD>撉諹<E69289>蝵烐聢 潃?<3F>詨<EFBFBD>
|
||
<20>婙<EFBFBD><E5A999><EFBFBD> Step 5: 蝏𤘪<E89D8F>撖澆枂
|
||
```
|
||
|
||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>芋<EFBFBD>?*嚗?- ASL璅∪<E79285>嚗Ǒfrontend-v2/src/modules/asl/`嚗? - <20>匧<EFBFBD><E58CA7>渡<EFBFBD>撣<EFBFBD><E692A3><EFBFBD><EFBFBD>△<EFBFBD>U<EFBFBD><EFBCB5><EFBFBD>隞嗥<E99A9E><E597A5>? - 雿輻鍂React Router撋<72><E6928B>頝舐眏
|
||
- 撌虫儒撖潸⏛ + <20>喃儒<E59683><E58492>捆<EFBFBD>?
|
||
---
|
||
|
||
## <20>㴓 鈭䎚<E988AD><E48E9A><EFBFBD><EFBFBD>𤏸恣<F0A48FB8>埝<EFBFBD>餉<EFBFBD>
|
||
|
||
### 2.1 撘<><E69298>煾𧫴畾萄<E795BE><E89084>?
|
||
| <20>嗆挾 | 隞餃𦛚 | 憸<>恣撌交𧒄 | 隡睃<E99AA1>蝥?| <20>格<EFBFBD> |
|
||
|------|------|---------|--------|------|
|
||
| **Phase 1** | Portal撌乩<E6928C><E4B9A9>圈△<E59C88>?| 4-6h | P0 | DC璅∪<E79285><E288AA>亙藁 |
|
||
| **Phase 2** | Tool B - Step 1&2 | 6h | P0 | 銝𠹺<E98A9D>+<2B>滨蔭 |
|
||
| **Phase 3** | Tool B - Step 3 | 3h | P0 | 餈𥕦漲<F0A595A6>烐綉 |
|
||
| **Phase 4** | Tool B - Step 4 | 9h | P0 | <20>脩<EFBFBD>撉諹<E69289>蝵烐聢潃?|
|
||
| **Phase 5** | Tool B - Step 5 | 3h | P0 | 蝏𤘪<E89D8F>撖澆枂 |
|
||
| **Phase 6** | <20><><EFBFBD>瘚贝<E7989A> | 4h | P1 | 蝡臬<E89DA1>蝡舫<E89DA1>霂?|
|
||
|
||
**<2A>餉恣**嚗𡁶漲29-31撠𤩺𧒄嚗?-5銝芸極雿𨀣𠯫嚗?
|
||
---
|
||
|
||
### 2.2 <20>𣬚<EFBFBD>蝣烐𧒄<E78390>渲”
|
||
|
||
| <20>𣬚<EFBFBD>蝣?| 摰峕<E691B0><E5B395><EFBFBD><EFBFBD> | 憸<>恣摰峕<E691B0> |
|
||
|--------|---------|---------|
|
||
| **M1: Portal銝羓瑪** | <20>冽<EFBFBD><E586BD>航挪<E888AA>唏C璅∪<E79285><E288AA>亙藁 | Day 1 |
|
||
| **M2: Tool B<>舐鍂** | Step1-5<>券<EFBFBD>摰峕<E691B0> | Day 4 |
|
||
| **M3: <20><><EFBFBD>瘚贝<E7989A><E8B49D>朞<EFBFBD>** | 蝡臬<E89DA1>蝡舀<E89DA1>蝔𧢲<E89D94>霂閖<E99C82>朞<EFBFBD> | Day 5 |
|
||
| **M4: <20><>﹝摰<EFB99D><E691B0>** | 撘<><E69298>烐<EFBFBD>獢<EFBFBD><E78DA2><EFBFBD>冽<EFBFBD><E586BD><EFBFBD>﹝ | Day 6 |
|
||
|
||
---
|
||
|
||
## <20><> 銝剹<E98A9D><E589B9>hase 1: Portal撌乩<E6928C><E4B9A9>啣<EFBFBD><E595A3>𡢅<EFBFBD>Day 1嚗?
|
||
### 3.1 <20>格<EFBFBD>
|
||
<EFBFBD>𥕦遣DC璅∪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>△<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝟餌<EFBFBD>憿園<EFBFBD>撖潸⏛嚗峕<EFBFBD>靘𥕦極<EFBFBD>瑕鍳<EFBFBD>具<EFBFBD><EFBFBD>遙<EFBFBD>∠<EFBFBD><EFBFBD>批<EFBFBD><EFBFBD><EFBFBD>辣蝞∠<EFBFBD><EFBFBD>蠘<EFBFBD><EFBFBD>?
|
||
### 3.2 霈曇恣<E69B87><E681A3><EFBFBD>?- **<2A>笔<EFBFBD><E7AC94><EFBFBD>辣**嚗䫤docs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/03-UI霈曇恣/<2F>箄<EFBFBD><E7AE84>唳旿皜<E697BF><E79A9C>撌乩<E6928C><E4B9A9>訓2.html`
|
||
- **PRD<52><44>﹝**嚗䫤docs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/01-<2D><>瘙<EFBFBD><E79899><EFBFBD>?PRD嚗𡁏惣<F0A1818F>賣㺭<E8B3A3>格<EFBFBD>瘣堒極雿𨅯蝱 (The Data Cleaning Portal).md`
|
||
|
||
### 3.3 <20>蠘<EFBFBD>皜<EFBFBD><E79A9C>
|
||
|
||
#### 3.3.1 敹恍<E695B9>笔鍳<E7AC94>典躹嚗?銝芸極<E88AB8>瑕㨃<E79195><E3A883><EFBFBD>
|
||
**蝏<>辣**嚗䫤components/ToolCard.tsx`
|
||
|
||
```typescript
|
||
interface ToolCardProps {
|
||
id: 'tool-a' | 'tool-b' | 'tool-c';
|
||
title: string;
|
||
description: string;
|
||
icon: ReactNode;
|
||
color: 'blue' | 'purple' | 'emerald';
|
||
status: 'ready' | 'disabled';
|
||
onClick: () => void;
|
||
}
|
||
```
|
||
|
||
**<2A>∠<EFBFBD><E288A0><EFBFBD>捆**嚗?1. **Tool A - 頞<>漣<EFBFBD><E6BCA3>僎<EFBFBD>?*
|
||
- <20>暹<EFBFBD>嚗鎄ileSpreadsheet嚗<74><E59A97><EFBFBD>莎<EFBFBD>
|
||
- <20>讛膩嚗?閫<><E996AB>憭𡁏<E686AD><F0A1818F>唳旿<E594B3>園𡢿頧游笆朣鞾𠗕憸?
|
||
- <20>嗆<EFBFBD><E59786><EFBFBD>disabled嚗<64><E59A97><EFBFBD>芸<EFBFBD><E88AB8>𡢅<EFBFBD>
|
||
|
||
2. **Tool B - <20><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖** 潃?<3F>祆活撘<E6B4BB><E69298>? - <20>暹<EFBFBD>嚗鋳ot嚗<74>換<EFBFBD>莎<EFBFBD>
|
||
- <20>讛膩嚗?<3F>拍鍂憭扳芋<E689B3>𧢲<EFBFBD><F0A7A2B2>㚚<EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗<EFBFBD><F0A19D97>?
|
||
- <20>嗆<EFBFBD><E59786><EFBFBD>ready
|
||
- <20>孵稬頝唾蓮嚗䫤/data-cleaning/tool-b`
|
||
|
||
3. **Tool C - 蝘𤑳<E89D98><F0A491B3>唳旿蝻𤥁<E89DBB><F0A4A581>?*
|
||
- <20>暹<EFBFBD>嚗関able2嚗<32>遛<EFBFBD>莎<EFBFBD>
|
||
- <20>讛膩嚗?Excel憌擧聢<E693A7><E881A2>銁蝥踵<E89DA5>瘣堒極<E5A092>?
|
||
- <20>嗆<EFBFBD><E59786><EFBFBD>disabled嚗<64><E59A97><EFBFBD>芸<EFBFBD><E88AB8>𡢅<EFBFBD>
|
||
|
||
---
|
||
|
||
#### 3.3.2 <20><>餈睲遙<E79DB2>∪<EFBFBD>銵?**蝏<>辣**嚗䫤components/TaskList.tsx`
|
||
|
||
**API**嚗䫤GET /api/v1/dc/tasks/recent`嚗<><E59A97><EFBFBD>𡒊垢<F0A1928A>啣<EFBFBD>嚗?
|
||
**<2A>唳旿蝏𤘪<E89D8F>**嚗?```typescript
|
||
interface Task {
|
||
id: string;
|
||
name: string;
|
||
tool: 'tool-a' | 'tool-b' | 'tool-c';
|
||
status: 'pending' | 'processing' | 'completed' | 'failed';
|
||
progress: number; // 0-100
|
||
createdAt: string;
|
||
completedAt?: string;
|
||
}
|
||
```
|
||
|
||
**<2A>蠘<EFBFBD>**嚗?- <20>曄內<E69B84><E585A7>餈?0<>∩遙<E288A9>?- 摰墧𧒄頧株砭餈𥕦漲嚗īrocessing<6E>嗆<EFBFBD><E59786>𧒄嚗峕<E59A97>5蝘坿蔭霂g<E99C82>
|
||
- <20>箄<EFBFBD>瘚<EFBFBD>蓮<EFBFBD>厰僼嚗? - Tool A摰峕<E691B0> <20>?[銝贝蝸] + [<5B>翠I<E7BFA0>𣂼<EFBFBD>]嚗<>歲Tool B嚗? - Tool B摰峕<E691B0> <20>?[銝贝蝸] + [<5B>餅<EFBFBD>瘣㻩嚗<E3BBA9>歲Tool C嚗? - Tool C摰峕<E691B0> <20>?[銝贝蝸]
|
||
|
||
---
|
||
|
||
#### 3.3.3 <20>唳旿韏<E697BF>漣摨?**蝏<>辣**嚗䫤components/AssetLibrary.tsx`
|
||
|
||
**API**嚗䫤GET /api/v1/dc/assets`嚗<><E59A97><EFBFBD>𡒊垢<F0A1928A>啣<EFBFBD>嚗?
|
||
**Tab<61><62>掩**嚗?- **<2A>券<EFBFBD>**嚗𡁏<E59A97><F0A1818F>㗇<EFBFBD>隞?- **憭<><E686AD>蝏𤘪<E89D8F>**嚗𡁜極<F0A1819C>嫂/B/C<><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞塚<E99A9E>蝏輯𠧧/<2F>肽𠧧<E882BD>暹<EFBFBD>嚗?- **<2A>笔<EFBFBD>銝𠹺<E98A9D>**嚗𡁶鍂<F0A181B6>瑞凒<E7919E>乩<EFBFBD>隡删<E99AA1>摨閗”嚗<E2809D><E59A97><EFBFBD>脣㦛<E884A3><E3A69B><EFBFBD>
|
||
|
||
**<2A>蠘<EFBFBD>**嚗?- <20><>辣<EFBFBD>∠<EFBFBD><E288A0>曄內嚗<E585A7><E59A97>隞嗅<E99A9E><E59785><EFBFBD><EFBFBD><EFBFBD>啜<EFBFBD><E5959C><EFBFBD>蝑整<E89D91><E695B4>耨<EFBFBD>寞𧒄<E5AF9E>湛<EFBFBD>
|
||
- 敹急㭘<E680A5>滢<EFBFBD>嚗靀銝贝蝸] [<5B>餃<EFBFBD><E9A483><EFBFBD> [<5B><><EFBFBD>]
|
||
- 摨閖<E691A8><E99696>箏<EFBFBD><E7AE8F>厰僼嚗靀+ 銝𠹺<E98A9D><F0A0B9BA>笔<EFBFBD><E7AC94><EFBFBD>辣<EFBFBD>啣<EFBFBD>]
|
||
|
||
---
|
||
|
||
### 3.4 <20><><EFBFBD>臬<EFBFBD><E887AC>?
|
||
#### 3.4.1 <20>桀<EFBFBD>蝏𤘪<E89D8F>
|
||
```
|
||
frontend-v2/src/modules/dc/
|
||
<EFBFBD>鎿<EFBFBD><EFBFBD><EFBFBD> pages/
|
||
<EFBFBD>? <20>婙<EFBFBD><E5A999><EFBFBD> Portal.tsx # 潃?Portal銝駁△<E9A781>?<3F>鎿<EFBFBD><E98EBF><EFBFBD> components/
|
||
<EFBFBD>? <20>鎿<EFBFBD><E98EBF><EFBFBD> ToolCard.tsx # 撌亙<E6928C><E4BA99>∠<EFBFBD>
|
||
<EFBFBD>? <20>鎿<EFBFBD><E98EBF><EFBFBD> TaskList.tsx # 隞餃𦛚<E9A483>𡑒”
|
||
<EFBFBD>? <20>婙<EFBFBD><E5A999><EFBFBD> AssetLibrary.tsx # <20>唳旿韏<E697BF>漣摨?<3F>鎿<EFBFBD><E98EBF><EFBFBD> hooks/
|
||
<EFBFBD>? <20>鎿<EFBFBD><E98EBF><EFBFBD> useRecentTasks.ts # 隞餃𦛚<E9A483>𡑒”Hook
|
||
<EFBFBD>? <20>婙<EFBFBD><E5A999><EFBFBD> useAssets.ts # 韏<>漣<EFBFBD>𡑒”Hook
|
||
<EFBFBD>鎿<EFBFBD><EFBFBD><EFBFBD> services/
|
||
<EFBFBD>? <20>婙<EFBFBD><E5A999><EFBFBD> portalApi.ts # Portal API撠<49><E692A0>
|
||
<EFBFBD>婙<EFBFBD><EFBFBD><EFBFBD> types/
|
||
<20>婙<EFBFBD><E5A999><EFBFBD> portal.ts # Portal蝐餃<E89D90>摰帋<E691B0>
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.2 頝舐眏<E88890>滨蔭
|
||
```typescript
|
||
// frontend-v2/src/modules/dc/index.tsx
|
||
import { Routes, Route } from 'react-router-dom';
|
||
import Portal from './pages/Portal';
|
||
import ToolBModule from './pages/tool-b';
|
||
|
||
const DCModule = () => {
|
||
return (
|
||
<Routes>
|
||
<Route path="" element={<Portal />} />
|
||
<Route path="tool-b/*" element={<ToolBModule />} />
|
||
{/* <20>芣䔉<E88AA3>拙<EFBFBD> */}
|
||
<Route path="tool-a/*" element={<ToolAPlaceholder />} />
|
||
<Route path="tool-c/*" element={<ToolCPlaceholder />} />
|
||
</Routes>
|
||
);
|
||
};
|
||
|
||
export default DCModule;
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.3 API撖寞𦻖
|
||
|
||
**<2A><>閬<EFBFBD><E996AC>蝡舀鰵憓䂿<E68693>API**嚗?```typescript
|
||
// GET /api/v1/dc/tasks/recent
|
||
interface GetRecentTasksResponse {
|
||
tasks: Task[];
|
||
}
|
||
|
||
// GET /api/v1/dc/assets
|
||
interface GetAssetsResponse {
|
||
assets: Asset[];
|
||
}
|
||
```
|
||
|
||
**銝湔𧒄<E6B994>寞<EFBFBD>**嚗<><E59A97>蝡涉PI<50>芸<EFBFBD><E88AB8>烐𧒄嚗㚁<E59A97>
|
||
- 雿輻鍂Mock<63>唳旿
|
||
- <20>𡒊賒<F0A1928A>踵揢銝箇<E98A9D>摰麫PI
|
||
|
||
---
|
||
|
||
### 3.5 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
|
||
|
||
- [ ] Portal憿菟𢒰<E88F9F>航挪<E888AA>殷<EFBFBD>`http://localhost:3000/data-cleaning`嚗?- [ ] 3銝芸極<E88AB8>瑕㨃<E79195><E3A883>迤蝖格遬蝷?- [ ] Tool B<>∠<EFBFBD><E288A0>舐<EFBFBD><E88890>餉歲頧穿<E9A0A7><E7A9BF>嗡<EFBFBD>銝支葵<E694AF>曄內disabled嚗?- [ ] 隞餃𦛚<E9A483>𡑒”<F0A19192>曄內Mock<63>唳旿
|
||
- [ ] <20>唳旿韏<E697BF>漣摨孏ab<61><62>揢甇<E68FA2>虜
|
||
- [ ] <20>港<EFBFBD><E6B8AF>瑕<EFBFBD>蝚血<E89D9A>蝟餌<E89D9F>霈曇恣閫<E681A3><E996AB>
|
||
|
||
---
|
||
|
||
## <20><>儭?<3F>䜘<EFBFBD><E49C98>hase 2: Tool B - Step 1&2嚗㇄ay 2嚗?
|
||
### 4.1 Step 1: <20><>辣銝𠹺<E98A9D>銝𤾸<E98A9D>摨瑟<E691A8><E7919F>伐<EFBFBD>3撠𤩺𧒄嚗?
|
||
#### 4.1.1 憿菟𢒰霈曇恣
|
||
**蝏<>辣**嚗䫤pages/tool-b/Step1Upload.tsx`
|
||
|
||
**UI<55><49><EFBFBD>?*嚗𡁜<E59A97><F0A1819C>鰦4蝚?60-310銵?
|
||
**撣<><E692A3>**嚗?1. <20><>辣靽⊥<E99DBD><E28AA5>∠<EFBFBD>嚗<EFBFBD>遬蝷箏歇銝𠹺<E98A9D><F0A0B9BA><EFBFBD>辣嚗?2. <20>烾<EFBFBD>㗇𥋘銝𧢲<E98A9D>獢?3. <20>亙熒璉<E78692><E79289>亦<EFBFBD><E4BAA6>𨅯㨃<F0A885AF><E3A883><EFBFBD><EFBFBD>冽<EFBFBD><E586BD>遬蝷綽<E89DB7>
|
||
|
||
---
|
||
|
||
#### 4.1.2 <20>蠘<EFBFBD>摰䂿緵
|
||
|
||
**1. Excel<65><6C>辣銝𠹺<E98A9D>**
|
||
```typescript
|
||
// 雿輻鍂Ant Design Upload蝏<64>辣
|
||
import { Upload } from 'antd';
|
||
|
||
// 銝𠹺<E98A9D><F0A0B9BA>訕torage
|
||
const handleUpload = async (file: File) => {
|
||
const formData = new FormData();
|
||
formData.append('file', file);
|
||
|
||
const response = await fetch('/api/v1/storage/upload', {
|
||
method: 'POST',
|
||
body: formData
|
||
});
|
||
|
||
const { fileKey } = await response.json();
|
||
setFileKey(fileKey); // 靽嘥<E99DBD>fileKey<65>其<EFBFBD><E585B6>𡒊賒甇仿炊
|
||
};
|
||
```
|
||
|
||
**2. <20>烾<EFBFBD>㗇𥋘銝𤾸<E98A9D>摨瑟<E691A8><E7919F>?*
|
||
```typescript
|
||
const [columns, setColumns] = useState<string[]>([]);
|
||
const [selectedColumn, setSelectedColumn] = useState('');
|
||
const [healthResult, setHealthResult] = useState<HealthCheckResult | null>(null);
|
||
|
||
// <20>芸𢆡璉<F0A286A1>瘚见<E7989A><E8A781>㵪<EFBFBD><E3B5AA>舫<EFBFBD>㚁<EFBFBD>隞𤾸<E99A9E>蝡航繮<E888AA>吔<EFBFBD>
|
||
useEffect(() => {
|
||
if (fileKey) {
|
||
// TODO: 靚<>鍂API<50>瑕<EFBFBD>Excel<65>堒<EFBFBD>
|
||
// <20>硋<EFBFBD>蝡航圾<E888AA>𨆼xcel嚗<6C>蝙<EFBFBD>肝lsx摨橒<E691A8>
|
||
}
|
||
}, [fileKey]);
|
||
|
||
// <20>亙熒璉<E78692><E79289>?const handleHealthCheck = async (columnName: string) => {
|
||
setIsChecking(true);
|
||
try {
|
||
const response = await fetch('/api/v1/dc/tool-b/health-check', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ fileKey, columnName })
|
||
});
|
||
|
||
const result = await response.json();
|
||
setHealthResult(result.data);
|
||
} finally {
|
||
setIsChecking(false);
|
||
}
|
||
};
|
||
```
|
||
|
||
**3. <20>亙熒摨行遬蝷?*
|
||
```typescript
|
||
// <20>寞旿status<75>曄內銝滚<E98A9D><E6BB9A>瑕<EFBFBD>
|
||
{healthResult?.status === 'good' && (
|
||
<Alert
|
||
type="success"
|
||
icon={<CheckCircle2 />}
|
||
message="<22>亙熒摨虫<E691A8>蝘<EFBFBD>嚗屸<E59A97><E5B1B8><EFBFBD><EFBFBD>𣂼<EFBFBD>"
|
||
description={
|
||
<div className="mt-2">
|
||
<span>撟喳<EFBFBD>摮㛖泵: {healthResult.avgLength}</span>
|
||
<span className="ml-4">蝛箏<EFBFBD>潛<EFBFBD>: {(healthResult.emptyRate * 100).toFixed(1)}%</span>
|
||
<span className="ml-4 text-purple-600 font-bold">
|
||
憸<EFBFBD>恣Token: {healthResult.estimatedTokens.toLocaleString()}
|
||
</span>
|
||
</div>
|
||
}
|
||
/>
|
||
)}
|
||
|
||
{healthResult?.status === 'bad' && (
|
||
<Alert
|
||
type="error"
|
||
icon={<AlertTriangle />}
|
||
message="霅血<E99C85>嚗朞砲<E69C9E>𦯀<EFBFBD><F0A6AF80><EFBFBD><EFBFBD>AI憭<49><E686AD>"
|
||
description={healthResult.message}
|
||
/>
|
||
)}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.2 Step 2: <20>箄<EFBFBD>璅⊥踎<E28AA5>滨蔭嚗?撠𤩺𧒄嚗?
|
||
#### 4.2.1 憿菟𢒰霈曇恣
|
||
**蝏<>辣**嚗䫤pages/tool-b/Step2Schema.tsx`
|
||
|
||
**UI<55><49><EFBFBD>?*嚗𡁜<E59A97><F0A1819C>鰦4蝚?13-372銵?
|
||
**撣<><E692A3>**嚗?1. <20>曄<EFBFBD>蝐餃<E89D90>銝擧𥁒<E693A7>羓掩<E7BE93>钅<EFBFBD>㗇𥋘嚗<F0A58B98>漣<EFBFBD>䈑<EFBFBD>
|
||
2. 摮埈挾<E59F88>𡑒”嚗<E2809D>椰靘改<E99D98><E694B9>舐<EFBFBD>颲𡢅<E9A2B2>
|
||
3. Prompt憸<74><E686B8>嚗<EFBFBD>𢰧靘改<E99D98>隞<EFBFBD><E99A9E>擃䀝漁嚗?
|
||
---
|
||
|
||
#### 4.2.2 <20>蠘<EFBFBD>摰䂿緵
|
||
|
||
**1. <20>瑕<EFBFBD>璅⊥踎<E28AA5>𡑒”**
|
||
```typescript
|
||
const [templates, setTemplates] = useState<Template[]>([]);
|
||
const [diseaseType, setDiseaseType] = useState('');
|
||
const [reportType, setReportType] = useState('');
|
||
const [fields, setFields] = useState<Field[]>([]);
|
||
|
||
useEffect(() => {
|
||
// <20>瑕<EFBFBD><E79195><EFBFBD><EFBFBD>㗇芋<E39787>? fetch('/api/v1/dc/tool-b/templates')
|
||
.then(res => res.json())
|
||
.then(data => setTemplates(data.data.templates));
|
||
}, []);
|
||
|
||
// 敶㯄<E695B6>㗇𥋘<E39787>曄<EFBFBD>蝐餃<E89D90><E9A483>峕𥁒<E5B395>羓掩<E7BE93>𧢲𧒄嚗諹䌊<E8ABB9>典<EFBFBD>頧賢<E9A0A7>畾?useEffect(() => {
|
||
if (diseaseType && reportType) {
|
||
const template = templates.find(
|
||
t => t.diseaseType === diseaseType && t.reportType === reportType
|
||
);
|
||
if (template) {
|
||
setFields(template.fields);
|
||
}
|
||
}
|
||
}, [diseaseType, reportType, templates]);
|
||
```
|
||
|
||
**2. 摮埈挾蝻𤥁<E89DBB>**
|
||
```typescript
|
||
// 瘛餃<E7989B>摮埈挾
|
||
const handleAddField = () => {
|
||
setFields([...fields, {
|
||
id: `custom_${Date.now()}`,
|
||
name: '<27>啣<EFBFBD>畾?,
|
||
desc: '摮埈挾<E59F88>讛膩',
|
||
width: 'w-32'
|
||
}]);
|
||
};
|
||
|
||
// <20>𣳇膄摮埈挾
|
||
const handleDeleteField = (id: string) => {
|
||
setFields(fields.filter(f => f.id !== id));
|
||
};
|
||
|
||
// 蝻𤥁<E89DBB>摮埈挾
|
||
const handleEditField = (id: string, key: 'name' | 'desc', value: string) => {
|
||
setFields(fields.map(f =>
|
||
f.id === id ? { ...f, [key]: value } : f
|
||
));
|
||
};
|
||
```
|
||
|
||
**3. Prompt憸<74><E686B8>**
|
||
```typescript
|
||
// <20>冽<EFBFBD><E586BD><EFBFBD><EFBFBD>辥rompt憸<74><E686B8>
|
||
const generatePrompt = () => {
|
||
return `You are an expert in ${diseaseType.replace('_', ' ')} pathology.
|
||
Extract fields in JSON format:
|
||
|
||
{
|
||
${fields.map(f => ` "${f.name}": "string", // ${f.desc}`).join('\n')}
|
||
}
|
||
|
||
Original text:
|
||
{originalText}
|
||
|
||
Output JSON only.`;
|
||
};
|
||
|
||
// 雿輻鍂隞<E98D82><E99A9E>擃䀝漁摨橒<E691A8>憒<EFBFBD>eact-syntax-highlighter嚗?<SyntaxHighlighter language="javascript" style={atomOneDark}>
|
||
{generatePrompt()}
|
||
</SyntaxHighlighter>
|
||
```
|
||
|
||
---
|
||
|
||
### 4.3 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
|
||
|
||
**Step 1:**
|
||
- [ ] Excel銝𠹺<E98A9D><F0A0B9BA>𣂼<EFBFBD>嚗諹繮<E8ABB9>餻ileKey
|
||
- [ ] <20>堒<EFBFBD><E5A092>𡑒”甇<E2809D>&<EFBFBD>曄內
|
||
- [ ] <20>亙熒璉<E78692><E79289>丕PI靚<49>鍂<EFBFBD>𣂼<EFBFBD>
|
||
- [ ] <20>亙熒摨血㨃<E8A180><E3A883>覔<EFBFBD>桃<EFBFBD><E6A183>𨀣迤蝖格遬蝷綽<E89DB7>蝏輯𠧧/蝥Z𠧧嚗?- [ ] Token憸<6E>摯<EFBFBD>啣<EFBFBD>潭迤蝖?- [ ] 蝛箏<E89D9B>潛<EFBFBD>>50%<25>嗥<EFBFBD>甇Z<E79487><EFBCBA>乩<EFBFBD>銝<EFBFBD>甇?
|
||
**Step 2:**
|
||
- [ ] 璅⊥踎<E28AA5>𡑒”<F0A19192>㰘蝸<E3B098>𣂼<EFBFBD>
|
||
- [ ] <20>曄<EFBFBD>蝐餃<E89D90><E9A483>峕𥁒<E5B395>羓掩<E7BE93>钅<EFBFBD>㗇𥋘獢<F0A58B98>迤撣?- [ ] <20>㗇𥋘璅⊥踎<E28AA5>𤾸<EFBFBD>畾菔䌊<E88F94>典<EFBFBD>頧?- [ ] 摮埈挾<E59F88>舀<EFBFBD>瘛餃<E7989B>/<2F>𣳇膄/蝻𤥁<E89DBB>
|
||
- [ ] Prompt憸<74><E686B8>摰墧𧒄<E5A2A7>湔鰵
|
||
- [ ] 隞<><E99A9E>擃䀝漁甇<E6BC81>&<EFBFBD>曄內
|
||
|
||
---
|
||
|
||
## <20>辷<EFBFBD> 鈭𢛵<E988AD><F0A29BB5>hase 3: Tool B - Step 3嚗㇄ay 3銝𠰴<E98A9D>嚗?
|
||
### 5.1 憭<><E686AD>餈𥕦漲<F0A595A6>烐綉嚗?撠𤩺𧒄嚗?
|
||
#### 5.1.1 憿菟𢒰霈曇恣
|
||
**蝏<>辣**嚗䫤pages/tool-b/Step3Processing.tsx`
|
||
|
||
**UI<55><49><EFBFBD>?*嚗𡁜<E59A97><F0A1819C>鰦4蝚?75-400銵?
|
||
**撣<><E692A3>**嚗?1. <20><>耦餈𥕦漲<F0A595A6>荔<EFBFBD><E88D94>峕芋<E5B395>见𢆡<E8A781>鳴<EFBFBD>
|
||
2. 餈𥕦漲<F0A595A6>曉<EFBFBD>瘥𥪜<E798A5><F0A5AA9C><EFBFBD>𧋦
|
||
3. <20>亙<EFBFBD>皛𡁜𢆡<F0A1819C>箏<EFBFBD>
|
||
|
||
---
|
||
|
||
#### 5.1.2 <20>蠘<EFBFBD>摰䂿緵
|
||
|
||
**1. <20>𥕦遣隞餃𦛚**
|
||
```typescript
|
||
const handleStartExtraction = async () => {
|
||
const response = await fetch('/api/v1/dc/tool-b/tasks', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
projectName: 'Test Project',
|
||
sourceFileKey: fileKey,
|
||
textColumn: selectedColumn,
|
||
diseaseType,
|
||
reportType,
|
||
modelA: 'deepseek-v3',
|
||
modelB: 'qwen-max'
|
||
})
|
||
});
|
||
|
||
const { taskId } = await response.json();
|
||
setTaskId(taskId);
|
||
|
||
// 撘<>憪贝蔭霂? startPolling(taskId);
|
||
};
|
||
```
|
||
|
||
**2. 餈𥕦漲頧株砭**
|
||
```typescript
|
||
const startPolling = (taskId: string) => {
|
||
const interval = setInterval(async () => {
|
||
const response = await fetch(`/api/v1/dc/tool-b/tasks/${taskId}/progress`);
|
||
const data = await response.json();
|
||
|
||
setProgress(data.progress); // <20>曉<EFBFBD>瘥? setLogs(prevLogs => [...prevLogs, data.latestLog]); // <20>啣<EFBFBD><E595A3>亙<EFBFBD>
|
||
|
||
if (data.status === 'completed') {
|
||
clearInterval(interval);
|
||
// 頝唾蓮<E594BE>訕tep 4
|
||
setTimeout(() => navigate(`/data-cleaning/tool-b/verify/${taskId}`), 800);
|
||
} else if (data.status === 'failed') {
|
||
clearInterval(interval);
|
||
message.error('<27>𣂼<EFBFBD>隞餃𦛚憭梯揖');
|
||
}
|
||
}, 5000); // 瘥?蝘坿蔭霂?
|
||
return () => clearInterval(interval);
|
||
};
|
||
```
|
||
|
||
**3. 餈𥕦漲<F0A595A6>函𤫇**
|
||
```typescript
|
||
// 雿輻鍂Ant Design Progress蝏<73>辣<EFBFBD>𤥁䌊摰帋<E691B0>SVG
|
||
<Progress
|
||
type="circle"
|
||
percent={progress}
|
||
format={percent => (
|
||
<div>
|
||
<div className="text-2xl font-bold">{percent}%</div>
|
||
<div className="text-sm text-gray-500"><EFBFBD>𣬚𤩅<EFBFBD>𣂼<EFBFBD>銝?/div>
|
||
</div>
|
||
)}
|
||
strokeColor={{
|
||
'0%': '#9333ea',
|
||
'100%': '#4f46e5'
|
||
}}
|
||
/>
|
||
|
||
// <20>峕芋<E5B395>见𢆡<E8A781>鳴<EFBFBD>銝支葵撠讐<E692A0>頝喳𢆡嚗?<div className="flex gap-2">
|
||
<div className="w-3 h-3 bg-blue-500 rounded-full animate-bounce" />
|
||
<div className="w-3 h-3 bg-orange-500 rounded-full animate-bounce delay-200" />
|
||
</div>
|
||
```
|
||
|
||
**4. <20>亙<EFBFBD><E4BA99>曄內**
|
||
```typescript
|
||
<div className="h-40 overflow-y-auto bg-slate-50 p-4 rounded font-mono text-xs">
|
||
{logs.map((log, i) => (
|
||
<div key={i} className="mb-1 text-slate-600">
|
||
<span className="text-slate-400">[{log.timestamp}]</span> {log.message}
|
||
</div>
|
||
))}
|
||
<div className="animate-pulse text-purple-500">_</div>
|
||
</div>
|
||
```
|
||
|
||
---
|
||
|
||
### 5.2 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
|
||
|
||
- [ ] <20>孵稬"撘<>憪𧢲<E686AA><F0A7A2B2>?<3F>擧<EFBFBD><E693A7>笔<EFBFBD>撱箔遙<E7AE94>?- [ ] <20>瑕<EFBFBD><E79195>配askId
|
||
- [ ] 餈𥕦漲頧株砭甇<E7A0AD>虜嚗<E8999C><E59A97>5蝘𡜐<E89D98>
|
||
- [ ] 餈𥕦漲<F0A595A6>∪<EFBFBD><E288AA>嗆凒<E59786>?- [ ] <20>亙<EFBFBD>皛𡁜𢆡<F0A1819C>箏<EFBFBD>甇<EFBFBD>虜<EFBFBD>曄內
|
||
- [ ] 隞餃𦛚摰峕<E691B0><E5B395>舘䌊<E88898>刻歲頧砍<E9A0A7>Step 4
|
||
- [ ] 隞餃𦛚憭梯揖<E6A2AF>嗆遬蝷粹<E89DB7>霂舀<E99C82>蝷?
|
||
---
|
||
|
||
## <20>㴓 <20>准<EFBFBD><E58786>hase 4: Tool B - Step 4嚗㇄ay 3銝见<E98A9D>+Day 4嚗争<E59A97> <20>詨<EFBFBD>
|
||
|
||
### 6.1 <20>脩<EFBFBD>撉諹<E69289>蝵烐聢嚗?撠𤩺𧒄嚗?
|
||
餈蹱糓<EFBFBD>港葵Tool B<><42>憭齿<E686AD><E9BDBF><EFBFBD><EFBFBD><EFBFBD>詨<EFBFBD><E8A9A8><EFBFBD>△<EFBFBD>g<EFBFBD>
|
||
|
||
#### 6.1.1 憿菟𢒰霈曇恣
|
||
**蝏<>辣**嚗䫤pages/tool-b/Step4Verify.tsx`
|
||
|
||
**UI<55><49><EFBFBD>?*嚗𡁜<E59A97><F0A1819C>鰦4蝚?02-569銵?
|
||
**撣<><E692A3>**嚗?```
|
||
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?Toolbar: 蝏蠘恣靽⊥<E99DBD> + [撖澆枂][摰峕<E691B0>] <20>?<3F>鎿<EFBFBD><E98EBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>? <20>?<3F>? <20>冽艶撉諹<E69289>蝵烐聢嚗<E881A2>”<EFBFBD>潘<EFBFBD> <20>?<3F>? <20>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>砂<EFBFBD><E7A082><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>砂<EFBFBD><E7A082><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>砂<EFBFBD><E7A082><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>砂<EFBFBD><E7A082><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?<3F>? <20>?# <20>?<3F><><EFBFBD><EFBFBD>䁅<EFBFBD> <20>?摮埈挾1 <20>?摮埈挾2 <20>?<3F>嗆<EFBFBD>?<3F>? <20>?<3F>? <20>鎿<EFBFBD><E98EBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>潑<EFBFBD><E6BD91><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>潑<EFBFBD><E6BD91><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>潑<EFBFBD><E6BD91><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>潑<EFBFBD><E6BD91><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?<3F>? <20>?1 <20>?<3F><><EFBFBD>霂𦠜鱏.. <20>?<3F>脩<EFBFBD><E884A9>訫<EFBFBD><E8A8AB>潘<EFBFBD>A/B<>厰僼嚗争<E59A97>敺<EFBFBD><E695BA><EFBFBD>喇<EFBFBD> <20>?<3F>? <20>?2 <20>?<3F><><EFBFBD>蝏<EFBFBD><E89D8F>.. <20>?蝏輯𠧧嚗<F0A0A7A7><E59A97><EFBFBD>湛<EFBFBD><E6B99B>?蝏輯𠧧 <20>?<3F>朞<EFBFBD> <20>? <20>?<3F>? <20>婙<EFBFBD><E5A999><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><E6B0AF><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><E6B0AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?<3F>? <20>?<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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?<3F>孵稬銵?<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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?靘扯器<E689AF>𧶏<EFBFBD>Drawer嚗? <20>?<3F>?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?<3F>?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂行<E99C82> <20>?<3F>? <20>?<3F>?<3F><><EFBFBD>霂𦠜鱏嚗?<3F>唾<EFBFBD>銝𠰴蠏)瘚豢隋<E8B1A2>扯<EFBFBD><E689AF>?.. <20>?<3F>?<3F>輻𠈔憭批<E686AD> 3.2*2.5*2.0cm... <20>?<3F>?... <20>?<3F>? <20>?<3F>?[<5B>喲𡡒] <20>?<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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?```
|
||
|
||
---
|
||
|
||
#### 6.1.2 <20><><EFBFBD>舫<EFBFBD>匧<EFBFBD>
|
||
|
||
**<2A>寞<EFBFBD><E5AF9E>㗇𥋘**嚗?
|
||
**Option 1: Ant Design Table**嚗<>綫<EFBFBD>琜<EFBFBD><E7909C>唳旿<E594B3>?1000銵䕘<E98AB5>
|
||
- 隡条<E99AA1>嚗𡁜<E59A97>蝞勗朖<E58B97>剁<EFBFBD>API<50>见末嚗峕甅撘讐<E69298>銝<EFBFBD>
|
||
- 蝻箇<E89DBB>嚗𡁏㺭<F0A1818F>桅<EFBFBD>憭扳𧒄<E689B3>航<EFBFBD><E888AA>⊿▼
|
||
- <20><>鍂<EFBFBD>箸艶嚗𡁜之<F0A1819C>典<EFBFBD><E585B8>箸艶嚗<E889B6><E59A97>霈⊥㺭<E28AA5>桅<EFBFBD><500銵䕘<E98AB5>
|
||
|
||
**Option 2: TanStack Table**嚗<><E59A97><EFBFBD>扯<EFBFBD>嚗峕㺭<E5B395>桅<EFBFBD>>1000銵䕘<E98AB5>
|
||
- 隡条<E99AA1>嚗朞<E59A97><E69C9E><EFBFBD><EFBFBD><EFBFBD>剁<EFBFBD><E58981>扯<EFBFBD><E689AF><EFBFBD>蔔
|
||
- 蝻箇<E89DBB>嚗䥅eadless<73><73><EFBFBD>芸楛摰䂿緵UI
|
||
- <20><>鍂<EFBFBD>箸艶嚗𡁜<E59A97><F0A1819C><EFBFBD>之<EFBFBD>唳旿<E594B3>?
|
||
**<2A>喟<EFBFBD>**嚗𡁜<E59A97><F0A1819C>杗nt Design Table嚗<65><E59A97><EFBFBD>扯<EFBFBD>銝滢蔔<E6BBA2>滩<EFBFBD>蝘餃<E89D98>TanStack Table
|
||
|
||
---
|
||
|
||
#### 6.1.3 <20>詨<EFBFBD><E8A9A8>唳旿蝏𤘪<E89D8F>
|
||
|
||
```typescript
|
||
interface VerifyRow {
|
||
id: string;
|
||
rowIndex: number;
|
||
originalText: string; // <20><><EFBFBD><EFBFBD>䁅<EFBFBD>嚗<EFBFBD><E59A97>50摮梹<E691AE>
|
||
fullText: string; // <20><><EFBFBD><EFBFBD>冽<EFBFBD>嚗<EFBFBD>儒颲寞<E9A2B2><E5AF9E>曄內嚗? results: Record<string, {
|
||
A: string; // DeepSeek蝏𤘪<E89D8F>
|
||
B: string; // Qwen蝏𤘪<E89D8F>
|
||
chosen: string | null; // <20>冽<EFBFBD><E586BD><EFBFBD>熙<EFBFBD><E78699><EFBFBD>潘<EFBFBD>null=<3D>芾圾<E88ABE>喉<EFBFBD>
|
||
}>;
|
||
status: 'clean' | 'conflict' | 'resolved';
|
||
conflictFields: string[]; // <20>脩<EFBFBD>摮埈挾<E59F88>滨妍<E6BBA8>𡑒”
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 6.1.4 <20>蠘<EFBFBD>摰䂿緵
|
||
|
||
**1. <20>瑕<EFBFBD>撉諹<E69289><E8ABB9>唳旿**
|
||
```typescript
|
||
const [rows, setRows] = useState<VerifyRow[]>([]);
|
||
const [pagination, setPagination] = useState({ page: 1, pageSize: 20, total: 0 });
|
||
|
||
useEffect(() => {
|
||
fetch(`/api/v1/dc/tool-b/tasks/${taskId}/items?status=conflict&page=${pagination.page}`)
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
setRows(data.data.items);
|
||
setPagination({ ...pagination, total: data.data.pagination.total });
|
||
});
|
||
}, [taskId, pagination.page]);
|
||
```
|
||
|
||
**2. 銵冽聢<E586BD>烾<EFBFBD>蝵?*
|
||
```typescript
|
||
const columns: ColumnsType<VerifyRow> = [
|
||
{
|
||
title: '#',
|
||
dataIndex: 'rowIndex',
|
||
width: 60,
|
||
fixed: 'left',
|
||
},
|
||
{
|
||
title: '<27><><EFBFBD><EFBFBD>䁅<EFBFBD>',
|
||
dataIndex: 'originalText',
|
||
width: 200,
|
||
render: (text, record) => (
|
||
<div className="flex items-center gap-2">
|
||
<FileText size={14} className="text-slate-300" />
|
||
<Tooltip title={text}>
|
||
<span className="truncate w-40">{text}</span>
|
||
</Tooltip>
|
||
</div>
|
||
),
|
||
},
|
||
// <20>冽<EFBFBD><E586BD><EFBFBD>畾萄<E795BE>嚗<EFBFBD>覔<EFBFBD>格芋<E6A0BC>輻<EFBFBD><E8BCBB>琜<EFBFBD>
|
||
...fields.map(field => ({
|
||
title: field.name,
|
||
dataIndex: ['results', field.name],
|
||
width: 180,
|
||
render: (cellData: { A: string; B: string; chosen: string | null }, record: VerifyRow) => {
|
||
const isConflict = cellData.A !== cellData.B && cellData.chosen === null;
|
||
|
||
if (isConflict) {
|
||
return <ConflictCell
|
||
fieldName={field.name}
|
||
valueA={cellData.A}
|
||
valueB={cellData.B}
|
||
onAdopt={(value) => handleAdopt(record.id, field.name, value)}
|
||
/>;
|
||
}
|
||
|
||
return <CleanCell value={cellData.chosen || cellData.A} />;
|
||
},
|
||
})),
|
||
{
|
||
title: '<27>嗆<EFBFBD>?,
|
||
dataIndex: 'status',
|
||
width: 100,
|
||
fixed: 'right',
|
||
render: (status) => {
|
||
if (status === 'clean' || status === 'resolved') {
|
||
return <Tag color="success"><3E>朞<EFBFBD></Tag>;
|
||
}
|
||
return <Tag color="warning" className="animate-pulse">敺<><E695BA><EFBFBD>?/Tag>;
|
||
},
|
||
},
|
||
];
|
||
```
|
||
|
||
**3. <20>脩<EFBFBD><E884A9>訫<EFBFBD><E8A8AB>潛<EFBFBD>隞?* 潃?<3F>詨<EFBFBD>
|
||
```typescript
|
||
// components/ConflictCell.tsx
|
||
interface ConflictCellProps {
|
||
fieldName: string;
|
||
valueA: string;
|
||
valueB: string;
|
||
onAdopt: (value: string) => void;
|
||
}
|
||
|
||
const ConflictCell: React.FC<ConflictCellProps> = ({ fieldName, valueA, valueB, onAdopt }) => {
|
||
return (
|
||
<div className="flex flex-col gap-1.5 bg-orange-50 p-2 rounded">
|
||
{/* <20>厰★A - DeepSeek */}
|
||
<button
|
||
className="text-left text-xs px-2 py-1.5 rounded border border-blue-200 bg-white hover:bg-blue-50 hover:border-blue-400 transition-all flex justify-between group"
|
||
onClick={() => onAdopt(valueA)}
|
||
>
|
||
<Tooltip title={valueA}>
|
||
<span className="truncate max-w-[100px]">{valueA}</span>
|
||
</Tooltip>
|
||
<Badge className="text-[10px] text-blue-400 group-hover:text-blue-600">DS</Badge>
|
||
</button>
|
||
|
||
{/* <20>厰★B - Qwen */}
|
||
<button
|
||
className="text-left text-xs px-2 py-1.5 rounded border border-orange-200 bg-white hover:bg-orange-50 hover:border-orange-400 transition-all flex justify-between group"
|
||
onClick={() => onAdopt(valueB)}
|
||
>
|
||
<Tooltip title={valueB}>
|
||
<span className="truncate max-w-[100px]">{valueB}</span>
|
||
</Tooltip>
|
||
<Badge className="text-[10px] text-orange-400 group-hover:text-orange-600">QW</Badge>
|
||
</button>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
**4. 鋆<><E98B86><EFBFBD>餉<EFBFBD>**
|
||
```typescript
|
||
const handleAdopt = async (itemId: string, fieldName: string, value: string) => {
|
||
// 銋鞱<E98A8B><E99EB1>湔鰵UI
|
||
setRows(prevRows =>
|
||
prevRows.map(row => {
|
||
if (row.id !== itemId) return row;
|
||
|
||
const newResults = { ...row.results };
|
||
newResults[fieldName].chosen = value;
|
||
|
||
// 璉<><E79289>亥砲銵峕糓<E5B395>西<EFBFBD><E8A5BF>㗇𧊋閫<F0A78A8B><E996AB><EFBFBD><EFBFBD><EFBFBD>蝒? const hasConflict = Object.values(newResults).some(
|
||
cell => cell.chosen === null && cell.A !== cell.B
|
||
);
|
||
|
||
return {
|
||
...row,
|
||
results: newResults,
|
||
status: hasConflict ? 'conflict' : 'resolved',
|
||
};
|
||
})
|
||
);
|
||
|
||
// 靚<>鍂API
|
||
try {
|
||
await fetch(`/api/v1/dc/tool-b/items/${itemId}/resolve`, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
resolvedData: { [fieldName]: value }
|
||
})
|
||
});
|
||
} catch (error) {
|
||
message.error('鋆<><E98B86>憭梯揖');
|
||
// <20>墧<EFBFBD>UI
|
||
// TODO: 摰䂿緵<E482BF>墧<EFBFBD><E5A2A7>餉<EFBFBD>
|
||
}
|
||
};
|
||
```
|
||
|
||
**5. 靘扯器<E689AF>誩<EFBFBD><E8AAA9><EFBFBD>遬蝷?*
|
||
```typescript
|
||
const [selectedRowId, setSelectedRowId] = useState<string | null>(null);
|
||
|
||
// <20>孵稬銵峕𧒄<E5B395>枏<EFBFBD>靘扯器<E689AF>?const onRow = (record: VerifyRow) => ({
|
||
onClick: () => setSelectedRowId(record.id),
|
||
});
|
||
|
||
// Drawer蝏<72>辣
|
||
<Drawer
|
||
title="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂行<E99C82>"
|
||
placement="right"
|
||
width={400}
|
||
open={!!selectedRowId}
|
||
onClose={() => setSelectedRowId(null)}
|
||
>
|
||
{(() => {
|
||
const row = rows.find(r => r.id === selectedRowId);
|
||
if (!row) return null;
|
||
|
||
return (
|
||
<div className="prose">
|
||
<p className="whitespace-pre-wrap font-serif leading-7">
|
||
{row.fullText}
|
||
</p>
|
||
|
||
<Divider />
|
||
|
||
<div className="flex flex-wrap gap-2">
|
||
{Object.keys(row.results).map(fieldName => (
|
||
<Tag
|
||
key={fieldName}
|
||
color={row.conflictFields.includes(fieldName) ? 'orange' : 'default'}
|
||
>
|
||
{fieldName}
|
||
</Tag>
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
})()}
|
||
</Drawer>
|
||
```
|
||
|
||
**6. Toolbar蝏蠘恣**
|
||
```typescript
|
||
const conflictCount = rows.filter(r => r.status === 'conflict').length;
|
||
const resolvedCount = rows.filter(r => r.status === 'resolved').length;
|
||
const cleanCount = rows.filter(r => r.status === 'clean').length;
|
||
|
||
<div className="flex items-center gap-4 mb-4">
|
||
<div className="bg-slate-100 px-3 py-1.5 rounded">
|
||
<20>餅㺭<E9A485>? <strong>{rows.length}</strong>
|
||
</div>
|
||
|
||
{conflictCount > 0 ? (
|
||
<div className="bg-orange-50 px-3 py-1.5 rounded text-orange-700 animate-pulse">
|
||
<AlertTriangle size={16} className="inline mr-1" />
|
||
<strong>{conflictCount}</strong> <20>∪<EFBFBD>蝒<EFBFBD><E89D92>鋆<EFBFBD><E98B86>
|
||
</div>
|
||
) : (
|
||
<div className="bg-emerald-50 px-3 py-1.5 rounded text-emerald-700">
|
||
<CheckCircle2 size={16} className="inline mr-1" />
|
||
<20><><EFBFBD>匧<EFBFBD>蝒<EFBFBD>歇閫<E6AD87><E996AB>
|
||
</div>
|
||
)}
|
||
|
||
<Button onClick={handleExport}>撖澆枂敶枏<E695B6>蝏𤘪<E89D8F></Button>
|
||
<Button type="primary" onClick={handleComplete}>摰峕<E691B0>撟嗅<E6929F>摨?/Button>
|
||
</div>
|
||
```
|
||
|
||
---
|
||
|
||
### 6.2 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
|
||
|
||
**<2A>唳旿<E594B3>㰘蝸**嚗?- [ ] <20>𣂼<EFBFBD><F0A382BC>瑕<EFBFBD>撉諹<E69289><E8ABB9>唳旿
|
||
- [ ] 銵冽聢<E586BD>埈覔<E59F88>格芋<E6A0BC>踹𢆡<E8B8B9><F0A286A1><EFBFBD><EFBFBD>?- [ ] <20><>△<EFBFBD>蠘<EFBFBD>甇<EFBFBD>虜
|
||
|
||
**<2A>脩<EFBFBD><E884A9>訫<EFBFBD><E8A8AB>?*嚗?- [ ] <20>脩<EFBFBD><E884A9>訫<EFBFBD><E8A8AB>潭遬蝷態/B銝支葵<E694AF>厰僼
|
||
- [ ] <20>厰僼<E58EB0>曄內甇<E585A7>&<EFBFBD><EFBC86><EFBFBD>澆<EFBFBD>璅∪<E79285><E288AA><EFBFBD><EFBFBD>嚗㇄S/QW嚗?- [ ] <20>孵稬<E5ADB5>厰僼<E58EB0>𡡞<EFBFBD>蝥喳<E89DA5>?- [ ] UI銋鞱<E98A8B><E99EB1>湔鰵嚗<E9B0B5><E59A97><EFBFBD>喟<EFBFBD><E5969F><EFBFBD><EFBFBD>
|
||
- [ ] API靚<49>鍂<EFBFBD>𣂼<EFBFBD>
|
||
|
||
**靘扯器<E689AF>?*嚗?- [ ] <20>孵稬銵峕𧒄靘扯器<E689AF>𤩺<EFBFBD><F0A4A9BA>?- [ ] <20>曄內摰峕㟲<E5B395><E39FB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
- [ ] <20>曄內摮埈挾<E59F88><E68CBE>倌嚗<E5808C><E59A97>蝒<EFBFBD><E89D92>畾菟<E795BE>鈭殷<E988AD>
|
||
- [ ] <20>孵稬<E5ADB5>喲𡡒<E596B2>厰僼<E58EB0>硋<EFBFBD><E7A18B>典躹<E585B8>笔<EFBFBD><E7AC94>凋儒颲寞<E9A2B2>
|
||
|
||
**Toolbar**嚗?- [ ] <20>脩<EFBFBD><E884A9>啁<EFBFBD>霈⊥迤蝖?- [ ] 摰墧𧒄<E5A2A7>湔鰵嚗<E9B0B5><E59A97><EFBFBD>喳<EFBFBD><E596B3>誩<EFBFBD>嚗?- [ ] 撖澆枂<E6BE86>厰僼<E58EB0>舐<EFBFBD><E88890>?- [ ] 摰峕<E691B0><E5B395>厰僼頝唾蓮<E594BE>訕tep 5
|
||
|
||
---
|
||
|
||
## <20>𣑐 銝<><E98A9D><EFBFBD>hase 5: Tool B - Step 5嚗㇄ay 5銝𠰴<E98A9D>嚗?
|
||
### 7.1 蝏𤘪<E89D8F>撖澆枂嚗?撠𤩺𧒄嚗?
|
||
#### 7.1.1 憿菟𢒰霈曇恣
|
||
**蝏<>辣**嚗䫤pages/tool-b/Step5Result.tsx`
|
||
|
||
**UI<55><49><EFBFBD>?*嚗𡁜<E59A97><F0A1819C>鰦4蝚?72-607銵?
|
||
**撣<><E692A3>**嚗?1. 摰峕<E691B0><E5B395>暹<EFBFBD><E69AB9>峕<EFBFBD>憸?2. 蝏蠘恣<E8A098>∠<EFBFBD>嚗?銝迎<E98A9D>
|
||
3. <20>滢<EFBFBD><E6BBA2>厰僼嚗<E583BC><E59A97>頧賬<E9A0A7><E8B3AC><EFBFBD>頧穿<E9A0A7>
|
||
|
||
---
|
||
|
||
#### 7.1.2 <20>蠘<EFBFBD>摰䂿緵
|
||
|
||
**1. 蝏蠘恣<E8A098>唳旿<E594B3>瑕<EFBFBD>**
|
||
```typescript
|
||
const [stats, setStats] = useState({
|
||
totalCount: 0,
|
||
cleanCount: 0,
|
||
conflictCount: 0,
|
||
failedCount: 0,
|
||
totalTokens: 0,
|
||
totalCost: 0,
|
||
});
|
||
|
||
useEffect(() => {
|
||
fetch(`/api/v1/dc/tool-b/tasks/${taskId}/progress`)
|
||
.then(res => res.json())
|
||
.then(data => setStats(data.data));
|
||
}, [taskId]);
|
||
```
|
||
|
||
**2. Excel撖澆枂**
|
||
```typescript
|
||
const handleExport = async () => {
|
||
try {
|
||
const response = await fetch(`/api/v1/dc/tool-b/tasks/${taskId}/export`, {
|
||
method: 'POST'
|
||
});
|
||
|
||
const blob = await response.blob();
|
||
const url = window.URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `extraction_result_${taskId}.xlsx`;
|
||
a.click();
|
||
|
||
message.success('撖澆枂<E6BE86>𣂼<EFBFBD>');
|
||
} catch (error) {
|
||
message.error('撖澆枂憭梯揖');
|
||
}
|
||
};
|
||
```
|
||
|
||
**3. 瘚<>蓮<EFBFBD>啣極<E595A3>嵩**
|
||
```typescript
|
||
const handleGoToToolC = () => {
|
||
// 頝唾蓮<E594BE>啣極<E595A3>嵩嚗䔶<E59A97><E494B6>㦙askId
|
||
navigate(`/data-cleaning/tool-c?sourceTaskId=${taskId}`);
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
### 7.2 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
|
||
|
||
- [ ] 蝏蠘恣<E8A098>∠<EFBFBD><E288A0>唳旿甇<E697BF>&<EFBFBD>曄內
|
||
- [ ] Token瘨<6E><E798A8>堒<EFBFBD><E5A092>鞉𧋦霈∠<E99C88>甇<EFBFBD>&
|
||
- [ ] 銝贝蝸<E8B49D>厰僼閫血<E996AB>Excel撖澆枂
|
||
- [ ] Excel<65><6C>辣<EFBFBD><E8BEA3>鉄4銝杵heet嚗<74><E59A97><EFBFBD>渡<EFBFBD><E6B8A1>栶<EFBFBD><E6A0B6><EFBFBD><EFBFBD>脩<EFBFBD><E884A9><EFBFBD><EFBFBD>蝒<EFBFBD>★<EFBFBD><E29885>仃韐仿★嚗?- [ ] 瘚<>蓮<EFBFBD>啣極<E595A3>嵩<EFBFBD>厰僼<E58EB0>舐<EFBFBD><E88890>鳴<EFBFBD><E9B3B4>鞟內<E99E9F><E585A7>𧊋撘<F0A78A8B><E69298>𡢅<EFBFBD>
|
||
- [ ] 餈𥪜<E9A488>Portal<61>厰僼<E58EB0>舐<EFBFBD><E88890>?
|
||
---
|
||
|
||
## <20>妒 <20>怒<EFBFBD><E68092>hase 6: <20><><EFBFBD>瘚贝<E7989A>嚗㇄ay 5銝见<E98A9D>嚗?
|
||
### 8.1 蝡臬<E89DA1>蝡舀<E89DA1>霂閙<E99C82><E99699>?
|
||
#### 8.1.1 摰峕㟲瘚<E39FB2><E7989A>瘚贝<E7989A>
|
||
|
||
**瘚贝<E7989A><E8B49D>箸艶**嚗朞<E59A97><E69C9E>𣬚<EFBFBD><F0A3AC9A><EFBFBD>𥁒<EFBFBD>𦠜<EFBFBD><F0A6A09C>?
|
||
**瘚贝<E7989A>甇仿炊**嚗?1. [ ] 霈輸䔮Portal憿菟𢒰嚗Ǒ/data-cleaning`嚗?2. [ ] <20>孵稬Tool B<>∠<EFBFBD>嚗諹歲頧砍<E9A0A7>Step 1
|
||
3. [ ] 銝𠹺<E98A9D>瘚贝<E7989A>Excel<65><6C>辣嚗<E8BEA3><E59A97><EFBFBD>怎<EFBFBD><E6808E><EFBFBD>𥁒<EFBFBD>𠰴<EFBFBD>嚗?4. [ ] <20>㗇𥋘"<22><><EFBFBD><EFBFBD>亙<EFBFBD>"<22>梹<EFBFBD>閫血<E996AB><E8A180>亙熒璉<E78692><E79289>?5. [ ] 撉諹<E69289><E8ABB9>亙熒摨行遬蝷箔蛹"蝏輯𠧧 - 隡条<E99AA1>"
|
||
6. [ ] 餈𥕦<E9A488>Step 2嚗屸<E59A97>㗇𥋘"<22>箇<EFBFBD> + <20><><EFBFBD><EFBFBD>亙<EFBFBD>"
|
||
7. [ ] 撉諹<E69289>摮埈挾<E59F88>芸𢆡<E88AB8>㰘蝸嚗?銝芸<E98A9D>畾蛛<E795BE>
|
||
8. [ ] 蝻𤥁<E89DBB>銝<EFBFBD>銝芸<E98A9D>畾蛛<E795BE>靽格㺿<E6A0BC>讛膩嚗?9. [ ] 餈𥕦<E9A488>Step 3嚗𣬚<E59A97><F0A3AC9A>?撘<>憪𧢲<E686AA><F0A7A2B2>?
|
||
10. [ ] 撉諹<E69289>餈𥕦漲<F0A595A6>∪<EFBFBD>憪𧢲凒<F0A7A2B2>?11. [ ] 撉諹<E69289><E8ABB9>亙<EFBFBD>皛𡁜𢆡<F0A1819C>曄內
|
||
12. [ ] 蝑匧<E89D91>隞餃𦛚摰峕<E691B0>嚗<EFBFBD><E59A97>璅⊥<E79285>摰峕<E691B0>嚗?13. [ ] <20>芸𢆡頝唾蓮<E594BE>訕tep 4
|
||
14. [ ] 撉諹<E69289>撉諹<E69289>蝵烐聢<E78390>㰘蝸<E3B098>唳旿
|
||
15. [ ] <20>曉<EFBFBD>銝<EFBFBD>銝芸<E98A9D>蝒<EFBFBD><E89D92><EFBFBD><EFBFBD>聢嚗𣬚<E59A97><F0A3AC9A>?DS"<22>厰僼<E58EB0><E583BC>熙
|
||
16. [ ] 撉諹<E69289><E8ABB9>脩<EFBFBD><E884A9>啣<EFBFBD>1
|
||
17. [ ] <20>孵稬<E5ADB5>鞱<EFBFBD>嚗屸<E59A97>霂<EFBFBD>儒颲寞<E9A2B2><E5AF9E>曄內<E69B84><E585A7><EFBFBD>
|
||
18. [ ] <20>孵稬"摰峕<E691B0>撟嗅<E6929F>摨?嚗諹歲頧砍<E9A0A7>Step 5
|
||
19. [ ] 撉諹<E69289>蝏蠘恣<E8A098>∠<EFBFBD><E288A0>唳旿甇<E697BF>&
|
||
20. [ ] <20>孵稬"銝贝蝸"嚗屸<E59A97>霂<EFBFBD>xcel銝贝蝸<E8B49D>𣂼<EFBFBD>
|
||
|
||
---
|
||
|
||
#### 8.1.2 撘<>虜<EFBFBD>箸艶瘚贝<E7989A>
|
||
|
||
**瘚贝<E7989A><E8B49D>箸艶1嚗𡁜<E59A97>摨瑟<E691A8><E7919F>亙仃韐?*
|
||
- [ ] 銝𠹺<E98A9D>Excel嚗屸<E59A97>㗇𥋘蝛箏<E89D9B>潛<EFBFBD>>50%<25><><EFBFBD>
|
||
- [ ] 撉諹<E69289><E8ABB9>亙熒摨行遬蝷箔蛹"蝥Z𠧧 - 霅血<E99C85>"
|
||
- [ ] 撉諹<E69289>"銝衤<E98A9D>甇?<3F>厰僼鋡怎<E98BA1><E6808E>?
|
||
**瘚贝<E7989A><E8B49D>箸艶2嚗帋遙<E5B88B>∪仃韐?*
|
||
- [ ] 璅⊥<E79285>API餈𥪜<E9A488>憭梯揖<E6A2AF>嗆<EFBFBD>?- [ ] 撉諹<E69289><E8ABB9>躰秤<E8BAB0>鞟內<E99E9F>曄內
|
||
- [ ] 撉諹<E69289><E8ABB9>臭誑<E887AD>齿鰵撠肽<E692A0>
|
||
|
||
**瘚贝<E7989A><E8B49D>箸艶3嚗𡁶<E59A97>蝏𣈯<E89D8F>霂?*
|
||
- [ ] <20>剔<EFBFBD><E58994>𡒊<EFBFBD><F0A1928A>?銝衤<E98A9D>甇?
|
||
- [ ] 撉諹<E69289><E8ABB9>躰秤<E8BAB0>鞟內<E99E9F>曄內
|
||
- [ ] <20>齿鰵<E9BDBF>𠉛<EFBFBD><F0A0899B>𤾸虾蝏抒賒
|
||
|
||
---
|
||
|
||
### 8.2 <20>扯<EFBFBD>瘚贝<E7989A>
|
||
|
||
**瘚贝<E7989A><E8B49D>箸艶**嚗𡁜之<F0A1819C>唳旿<E594B3>誯<EFBFBD>霂<EFBFBD><E99C82><EFBFBD>?
|
||
**瘚贝<E7989A>甇仿炊**嚗?1. [ ] <20>㰘蝸500銵峕㺭<E5B395>?2. [ ] 撉諹<E69289>銵冽聢皛𡁜𢆡瘚<F0A286A1><E7989A>嚗<EFBFBD><E59A97><EFBFBD>⊿▼嚗?3. [ ] 撉諹<E69289><E8ABB9><EFBFBD>△<EFBFBD>蠘<EFBFBD>甇<EFBFBD>虜
|
||
4. [ ] 撉諹<E69289><E8ABB9>鍦<EFBFBD>/蝑偦<E89D91>匧<EFBFBD><E58CA7>踝<EFBFBD>憒<EFBFBD><E68692><EFBFBD>堆<EFBFBD>
|
||
|
||
**<2A>扯<EFBFBD><E689AF><EFBFBD><EFBFBD>**嚗?- [ ] 擐硋<E69390><E7A18B>㰘蝸<E3B098>園𡢿 < 2蝘?- [ ] 銵冽聢皛𡁜𢆡撣抒<E692A3> > 30fps
|
||
- [ ] 鋆<><E98B86><EFBFBD>滢<EFBFBD><E6BBA2>滚<EFBFBD><E6BB9A>園𡢿 < 500ms
|
||
|
||
---
|
||
|
||
### 8.3 <20>澆捆<E6BE86>扳<EFBFBD>霂?
|
||
**瘚讛<E7989A><E8AE9B>?*嚗?- [ ] Chrome 120+
|
||
- [ ] Edge 120+
|
||
- [ ] Firefox 120+
|
||
- [ ] Safari 17+嚗㇈ac嚗?
|
||
**<2A><>儘<EFBFBD>?*嚗?- [ ] 1920x1080嚗<30>虜閫<E8999C><E996AB>
|
||
- [ ] 1440x900嚗<30><E59A97>霈唳𧋦嚗?- [ ] 2560x1440嚗<30><E59A97><EFBFBD><EFBFBD><EFBFBD>嚗?
|
||
---
|
||
|
||
## <20><> 銋腈<E98A8B><E88588><EFBFBD>獢<EFBFBD><E78DA2><EFBFBD><EFBFBD><EFBFBD>Day 6嚗?
|
||
### 9.1 撘<><E69298>烐<EFBFBD>獢?
|
||
**<2A><>閬<EFBFBD>‘<EFBFBD><E28098><EFBFBD><EFBFBD><EFBFBD>﹝**嚗?1. [ ] **<2A>滨垢隞<E59EA2><E99A9E>蝏𤘪<E89D8F>霂湔<E99C82>**嚗Ǒdocs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/02-<2D><><EFBFBD>航挽霈?<3F>滨垢<E6BBA8>嗆<EFBFBD>霈曇恣.md`嚗?2. [ ] **蝏<>辣雿輻鍂<E8BCBB><E98D82>﹝**嚗Ǒfrontend-v2/src/modules/dc/README.md`嚗?3. [ ] **API撖寞𦻖<E5AF9E><F0A6BB96>﹝**嚗<>‘<EFBFBD><E28098><EFBFBD><EFBFBD>唳<EFBFBD>API霈曇恣<E69B87><E681A3>﹝嚗?4. [ ] **<EFBFBD>砍<EFBFBD><EFBFBD>𤏸恣<EFBFBD>垍<EFBFBD>摰峕<EFBFBD><EFBFBD>餌<EFBFBD>**嚗Ǒdocs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/06-撘<><E69298>𤏸扇敶?Tool-B撘<42><E69298>穃<EFBFBD><E7A983>鞉<EFBFBD>餌<EFBFBD>.md`嚗?
|
||
---
|
||
|
||
### 9.2 <20>冽<EFBFBD><E586BD><EFBFBD>﹝嚗<EFB99D>虾<EFBFBD>㚁<EFBFBD>
|
||
|
||
**<2A><>閬<EFBFBD><E996AC>撱箇<E692B1><E7AE87><EFBFBD>﹝**嚗?1. [ ] **Tool B雿輻鍂<E8BCBB><E98D82><EFBFBD>**嚗Ǒdocs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/07-<2D>冽<EFBFBD><E586BD>见<EFBFBD>/Tool-B雿輻鍂<E8BCBB><E98D82><EFBFBD>.md`嚗?2. [ ] **撣貉<E692A3><E8B289>桅<EFBFBD>FAQ**嚗Ǒdocs/03-銝𡁜𦛚璅∪<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD>渡<EFBFBD>/07-<2D>冽<EFBFBD><E586BD>见<EFBFBD>/FAQ.md`嚗?
|
||
---
|
||
|
||
## <20>㴓 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>格<EFBFBD><E6A0BC>航<EFBFBD><E888AA>?
|
||
### 10.1 敹<>◆<EFBFBD>萄<EFBFBD><E89084><EFBFBD><EFBFBD><EFBFBD>?
|
||
#### 鈭穃<E988AD><E7A983>蠘<EFBFBD><E8A098>?潃?撘箏<E69298>
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>`docs/04-撘<><E69298>𤏸<EFBFBD><F0A48FB8>?08-鈭穃<E988AD><E7A983>笔<EFBFBD><E7AC94>𤏸<EFBFBD><F0A48FB8>?md`
|
||
|
||
**蝳<>迫**嚗?- <20>?雿輻鍂`fs.writeFile()`蝑㗇𧋦<E39787>唳<EFBFBD>隞嗆<E99A9E>雿?- <20>?雿輻鍂<E8BCBB>典<EFBFBD><E585B8>㗛<EFBFBD>蝻枏<E89DBB><E69E8F>唳旿
|
||
- <20>?蝖祉<E89D96><E7A589><EFBFBD><EFBFBD>蝵殷<E89DB5>IP<49><50><EFBFBD><EFBFBD>亦<EFBFBD>嚗?- <20>?<3F>峕郊<E5B395>蹂遙<E8B982>∴<EFBFBD>>10蝘𡜐<E89D98>
|
||
- <20>?<3F>滚<EFBFBD>摰䂿緵撟喳蝱<E596B3>賢<EFBFBD>
|
||
|
||
**敹<>◆**嚗?- <20>?雿輻鍂`storage`<60>滚𦛚摮睃<E691AE><E79D83><EFBFBD>辣
|
||
- <20>?雿輻鍂`cache`<60>滚𦛚蝻枏<E89DBB><E69E8F>唳旿
|
||
- <20>?雿輻鍂<E8BCBB>臬<EFBFBD><E887AC>㗛<EFBFBD><E3979B>滨蔭
|
||
- <20>?撘<>郊隞餃𦛚 + 餈𥕦漲頧株砭
|
||
- <20>?憭滨鍂撟喳蝱<E596B3>箇<EFBFBD>霈暹鴌
|
||
|
||
---
|
||
|
||
### 10.2 憭滨鍂蝑𣇉裦
|
||
|
||
#### <20>𡒊垢憭滨鍂嚗<E98D82><E59A97><EFBFBD><EFBFBD><EFBFBD>
|
||
```typescript
|
||
// <20>?甇<>&嚗𡁜<E59A97><F0A1819C>典像<E585B8>啗<EFBFBD><E59597>?import { storage } from '@/common/storage';
|
||
import { logger } from '@/common/logging';
|
||
import { cache } from '@/common/cache';
|
||
import { LLMFactory } from '@/common/llm/adapters/LLMFactory';
|
||
```
|
||
|
||
#### <20>滨垢憭滨鍂嚗<E98D82><E59A97>摰䂿緵嚗?```typescript
|
||
// 憭滨鍂ASL璅∪<E79285><E288AA><EFBFBD><EFBFBD>隞嗅<E99A9E>Hook
|
||
import { usePolling } from '@/shared/hooks/usePolling';
|
||
import { FileUploader } from '@/shared/components/FileUploader';
|
||
import { ProgressBar } from '@/shared/components/ProgressBar';
|
||
```
|
||
|
||
---
|
||
|
||
### 10.3 <20>嗆<EFBFBD><E59786>恣<EFBFBD>?
|
||
**<2A>刻<EFBFBD><E588BB>寞<EFBFBD>**嚗鑹eact Query嚗㇁SL璅∪<E79285>雿輻鍂嚗?
|
||
```typescript
|
||
// 雿輻鍂React Query蝞∠<E89D9E>API靚<49>鍂
|
||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||
|
||
// <20>瑕<EFBFBD>隞餃𦛚餈𥕦漲
|
||
const { data: progress } = useQuery({
|
||
queryKey: ['task-progress', taskId],
|
||
queryFn: () => fetch(`/api/v1/dc/tool-b/tasks/${taskId}/progress`).then(res => res.json()),
|
||
refetchInterval: 5000, // 瘥?蝘坿蔭霂? enabled: !!taskId && status === 'processing',
|
||
});
|
||
|
||
// 鋆<><E98B86><EFBFBD>脩<EFBFBD>
|
||
const resolveMutation = useMutation({
|
||
mutationFn: ({ itemId, resolvedData }) =>
|
||
fetch(`/api/v1/dc/tool-b/items/${itemId}/resolve`, {
|
||
method: 'POST',
|
||
body: JSON.stringify({ resolvedData }),
|
||
}),
|
||
onSuccess: () => {
|
||
queryClient.invalidateQueries(['task-items', taskId]);
|
||
message.success('鋆<><E98B86><EFBFBD>𣂼<EFBFBD>');
|
||
},
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
### 10.4 TypeScript蝐餃<E89D90>摰帋<E691B0>
|
||
|
||
**蝏煺<E89D8F>蝐餃<E89D90><E9A483><EFBFBD>辣**嚗䫤frontend-v2/src/modules/dc/types/toolB.ts`
|
||
|
||
```typescript
|
||
// <20>亙熒璉<E78692><E79289>亦<EFBFBD><E4BAA6>?export interface HealthCheckResult {
|
||
status: 'good' | 'bad';
|
||
emptyRate: number;
|
||
avgLength: number;
|
||
totalRows: number;
|
||
estimatedTokens: number;
|
||
message: string;
|
||
}
|
||
|
||
// 璅⊥踎摰帋<E691B0>
|
||
export interface Template {
|
||
id: string;
|
||
diseaseType: string;
|
||
reportType: string;
|
||
displayName: string;
|
||
fields: Field[];
|
||
}
|
||
|
||
export interface Field {
|
||
id: string;
|
||
name: string;
|
||
desc: string;
|
||
width?: string;
|
||
}
|
||
|
||
// 隞餃𦛚<E9A483>嗆<EFBFBD>?export interface Task {
|
||
id: string;
|
||
projectName: string;
|
||
status: 'pending' | 'processing' | 'completed' | 'failed';
|
||
totalCount: number;
|
||
processedCount: number;
|
||
cleanCount: number;
|
||
conflictCount: number;
|
||
failedCount: number;
|
||
totalTokens: number;
|
||
totalCost: number;
|
||
}
|
||
|
||
// 撉諹<E69289>銵?export interface VerifyRow {
|
||
id: string;
|
||
rowIndex: number;
|
||
originalText: string;
|
||
fullText: string;
|
||
results: Record<string, {
|
||
A: string;
|
||
B: string;
|
||
chosen: string | null;
|
||
}>;
|
||
status: 'clean' | 'conflict' | 'resolved';
|
||
conflictFields: string[];
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>抵<EFBFBD>隡唬<E99AA1>摨𥪜笆
|
||
|
||
### 11.1 <20><><EFBFBD>舫<EFBFBD><E888AB>?
|
||
| 憌𡡞埯 | 璁<><E79281> | 敶勗<E695B6> | 摨𥪜笆<F0A5AA9C>芣鴌 |
|
||
|------|------|------|---------|
|
||
| **<EFBFBD>唳旿摨栞”<EFBFBD>芸<EFBFBD>撱?* | 銝?| 擃?| 蝡见朖<E8A781>扯<EFBFBD>`npx prisma db push`撉諹<EFBFBD> |
|
||
| **<EFBFBD>𡒊垢API<EFBFBD>芣<EFBFBD>霂?* | 銝?| 擃?| 撘<><E69298>穃<EFBFBD><E7A983><EFBFBD>鍂REST Client瘚贝<E7989A>6銝芰垢<E88AB0>?|
|
||
| **<EFBFBD>扯<EFBFBD><EFBFBD>桅<EFBFBD>嚗<EFBFBD>之<EFBFBD>唳旿<EFBFBD>𧶏<EFBFBD>** | 雿?| 銝?| 憸<><E686B8>TanStack Table餈<65>宏<EFBFBD>寞<EFBFBD> |
|
||
| **Excel閫<6C><E996AB>憭梯揖** | 雿?| 銝?| 雿輻鍂xlsx摨橒<E691A8>憓𧼮<E68693><F0A7BCAE>躰秤憭<E7A7A4><E686AD> |
|
||
| **LLM靚<4D>鍂頞<E98D82>𧒄** | 雿?| 銝?| <20>𡒊垢撌脣<E6928C><E884A3>圈<EFBFBD>霂閙㦤<E99699>?|
|
||
|
||
---
|
||
|
||
### 11.2 <20>園𡢿憌𡡞埯
|
||
|
||
| 憌𡡞埯 | 璁<><E79281> | 敶勗<E695B6> | 摨𥪜笆<F0A5AA9C>芣鴌 |
|
||
|------|------|------|---------|
|
||
| **Step 4撘<34><E69298>𤏸<EFBFBD><F0A48FB8>?* | 銝?| 擃?| 憸<><E686B8>2憭抬<E686AD>9撠𤩺𧒄嚗㚁<E59A97><E39A81>舀<EFBFBD><E88880><EFBFBD><EFBFBD>隞餃𦛚 |
|
||
| **<EFBFBD><EFBFBD><EFBFBD>瘚贝<EFBFBD><EFBFBD>𤑳緵<EFBFBD>桅<EFBFBD>** | 銝?| 銝?| 憸<><E686B8>1憭拍<E686AD><E68B8D>脫𧒄<E884AB>?|
|
||
| **<EFBFBD>笔<EFBFBD>銝𡡞<EFBFBD>瘙<EFBFBD><EFBFBD>蝚?* | 雿?| 擃?| 撘<><E69298>穃<EFBFBD>銝𦒘漣<F0A69298><E6BCA3>&霈文<E99C88><E69687>?|
|
||
|
||
---
|
||
|
||
### 11.3 靘肽<E99D98>憌𡡞埯
|
||
|
||
| 憌𡡞埯 | 璁<><E79281> | 敶勗<E695B6> | 摨𥪜笆<F0A5AA9C>芣鴌 |
|
||
|------|------|------|---------|
|
||
| **<EFBFBD>𡒊垢API<EFBFBD>䀹凒** | 雿?| 擃?| 雿輻鍂TypeScript蝐餃<E89D90>嚗𣬚<E59A97>霂烐𧒄璉<F0A79284><E79289>?|
|
||
| **撟喳蝱<E596B3>賢<EFBFBD>Bug** | 雿?| 銝?| 撌脣<E6928C><E884A3>湔<EFBFBD>霂𤏪<E99C82>憌𡡞埯雿?|
|
||
| **霈曇恣<E69B87>䀹凒** | 雿?| 銝?| 蝏<>辣<EFBFBD>𤥁挽霈∴<E99C88><E288B4>㮖<EFBFBD>靽格㺿 |
|
||
|
||
---
|
||
|
||
## <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||
### 12.1 鈭支<E988AD><E694AF>拇<EFBFBD><E68B87>?
|
||
**隞<><E99A9E>**嚗?- [ ] Portal撌乩<E6928C><E4B9A9>圈△<E59C88>g<EFBFBD>摰峕㟲嚗?- [ ] Tool B 5銝杵tep憿菟𢒰嚗<F0A292B0><E59A97><EFBFBD>湛<EFBFBD>
|
||
- [ ] <20>曹澈蝏<E6BE88>辣摨橒<E691A8>TaskList<73><74>ssetLibrary<72><79>onflictCell蝑㚁<E89D91>
|
||
- [ ] API<50>滚𦛚撠<F0A69B9A><E692A0>嚗ōoolBApi.ts<74><73>ortalApi.ts嚗?- [ ] TypeScript蝐餃<E89D90>摰帋<E691B0>嚗<EFBFBD><E59A97><EFBFBD>湛<EFBFBD>
|
||
- [ ] <20>瑕<EFBFBD><E79195><EFBFBD>辣嚗㇍ailwindCSS + Ant Design嚗?
|
||
**<2A><>﹝**嚗?- [ ] <20>滨垢<E6BBA8>嗆<EFBFBD>霈曇恣<E69B87><E681A3>﹝
|
||
- [ ] 蝏<>辣雿輻鍂<E8BCBB><E98D82>﹝
|
||
- [ ] API撖寞𦻖<E5AF9E><F0A6BB96>﹝
|
||
- [ ] 撘<><E69298>穃<EFBFBD><E7A983>鞉<EFBFBD>餌<EFBFBD>
|
||
- [ ] <20>冽<EFBFBD>雿輻鍂<E8BCBB><E98D82><EFBFBD>嚗<EFBFBD>虾<EFBFBD>㚁<EFBFBD>
|
||
|
||
**瘚贝<E7989A>**嚗?- [ ] 蝡臬<E89DA1>蝡舀<E89DA1>霂閙𥁒<E99699>?- [ ] <20>扯<EFBFBD>瘚贝<E7989A><E8B49D>亙<EFBFBD>
|
||
- [ ] <20>澆捆<E6BE86>扳<EFBFBD>霂閙𥁒<E99699>?
|
||
---
|
||
|
||
### 12.2 <20>蠘<EFBFBD>摰峕㟲<E5B395>?
|
||
**Portal撌乩<E6928C><E4B9A9>?*嚗?- <20>?3銝芸極<E88AB8>瑕㨃<E79195><E3A883><EFBFBD>Tool B<>舐鍂嚗?- <20>?<3F><>餈睲遙<E79DB2>∪<EFBFBD>銵剁<E98AB5>摰墧𧒄頧株砭嚗?- <20>?<3F>唳旿韏<E697BF>漣摨橒<E691A8>Tab<61><62>揢嚗?
|
||
**Tool B - <20><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖**嚗?- <20>?Step 1: Excel銝𠹺<E98A9D> + <20>亙熒璉<E78692><E79289>?- <20>?Step 2: <20>箄<EFBFBD>璅⊥踎<E28AA5>滨蔭嚗?銝芷<E98A9D>霈暹芋<E69AB9>選<EFBFBD>
|
||
- <20>?Step 3: <20>𣬚𤩅<F0A3AC9A>𣂼<EFBFBD>餈𥕦漲<F0A595A6>烐綉
|
||
- <20>?Step 4: <20>脩<EFBFBD>撉諹<E69289>蝵烐聢嚗<E881A2>𣈲<EFBFBD><F0A388B2><EFBFBD><EFBFBD>喉<EFBFBD>
|
||
- <20>?Step 5: 蝏𤘪<E89D8F>撖澆枂嚗𠄌xcel + 瘚<>蓮嚗?
|
||
---
|
||
|
||
### 12.3 隞<><E99A9E>韐券<E99F90>
|
||
|
||
**隞<><E99A9E>閫<EFBFBD><E996AB>**嚗?- <20>?<3F>萄<EFBFBD>鈭穃<E988AD><E7A983>笔<EFBFBD><E7AC94>𤏸<EFBFBD><F0A48FB8>?- <20>?TypeScript蝐餃<E89D90>摰匧<E691B0>
|
||
- <20>?ESLint<6E>𣳇<EFBFBD>霂?- <20>?隞<><E99A9E>瘜券<E7989C>摰<EFBFBD><E691B0>
|
||
|
||
**<EFBFBD>扯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**嚗?- <20>?擐硋<E69390><E7A18B>㰘蝸 < 2s
|
||
- <20>?銵冽聢皛𡁜𢆡瘚<F0A286A1><E7989A>
|
||
- <20>?鋆<><E98B86><EFBFBD>滚<EFBFBD> < 500ms
|
||
- <20>?<3F><><EFBFBD><EFBFBD>删鍂 < 200MB
|
||
|
||
**<EFBFBD>冽<EFBFBD>雿㯄<EFBFBD>**嚗?- <20>?瘚<><E7989A><EFBFBD>?甇交<E79487>蝔?- <20>?摰墧𧒄餈𥕦漲<F0A595A6>漤<EFBFBD>
|
||
- <20>?<3F>渲<EFBFBD><E6B8B2><EFBFBD><EFBFBD>蝒<EFBFBD><E89D92>霂<EFBFBD><E99C82><EFBFBD>?- <20>?<3F>见末<E8A781><E69CAB><EFBFBD>霂舀<E99C82>蝷?
|
||
---
|
||
|
||
## <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銝<EFBFBD>甇亥<E79487><E4BAA5>?
|
||
### 13.1 蝡见朖<E8A781>扯<EFBFBD>嚗㇄ay 0嚗?
|
||
**1. 撉諹<E69289><E8ABB9>唳旿摨栞”**
|
||
```bash
|
||
cd AIclinicalresearch/backend
|
||
npx prisma db push --skip-generate
|
||
npx prisma studio # <20>航<EFBFBD><E888AA>㚚<EFBFBD>霂?```
|
||
|
||
**2. 瘚贝<E7989A><E8B49D>𡒊垢API**
|
||
```bash
|
||
# <20>臬𢆡<E887AC>𡒊垢<F0A1928A>滚𦛚
|
||
npm run dev
|
||
|
||
# 雿輻鍂REST Client瘚贝<E7989A>6銝服PI蝡舐<E89DA1>
|
||
# <20>碶蝙<E7A2B6>沌ostman/Insomnia
|
||
```
|
||
|
||
**3. Git<69>𣂷漱霈∪<E99C88>**
|
||
```bash
|
||
# 撱箄悅瘥誩<E798A5><E8AAA9>𣂷<EFBFBD>銝枉hase撠望<E692A0>鈭?git commit -m "feat(dc): Complete Portal page (Phase 1)"
|
||
git commit -m "feat(dc/tool-b): Complete Step1&2 (Phase 2)"
|
||
git commit -m "feat(dc/tool-b): Complete Step4 conflict grid (Phase 4)"
|
||
```
|
||
|
||
---
|
||
|
||
### 13.2 撘<><E69298>穃鍳<E7A983>剁<EFBFBD>Day 1嚗?
|
||
**隞餃𦛚1嚗𡁜<E59A97>撱摺ortal憿菟𢒰撉冽沲**
|
||
```bash
|
||
cd frontend-v2/src/modules/dc
|
||
mkdir -p pages components hooks services types
|
||
|
||
# <20>𥕦遣Portal.tsx
|
||
touch pages/Portal.tsx
|
||
|
||
# <20>𥕦遣頝舐眏<E88890>滨蔭
|
||
# 靽格㺿 index.tsx
|
||
```
|
||
|
||
**隞餃𦛚2嚗𡁜<E59A97><F0A1819C>?銝芸極<E88AB8>瑕㨃<E79195>?*
|
||
```bash
|
||
# <20>𥕦遣ToolCard蝏<64>辣
|
||
touch components/ToolCard.tsx
|
||
```
|
||
|
||
**隞餃𦛚3嚗𡁜<E59A97><F0A1819C>唬遙<E594AC>∪<EFBFBD>銵剁<E98AB5>雿輻鍂Mock<63>唳旿嚗?*
|
||
```bash
|
||
# <20>𥕦遣TaskList蝏<74>辣
|
||
touch components/TaskList.tsx
|
||
|
||
# <20>𥕦遣useRecentTasks Hook
|
||
touch hooks/useRecentTasks.ts
|
||
```
|
||
|
||
---
|
||
|
||
### 13.3 <20><>賒頝蠘<E9A09D>
|
||
|
||
**瘥𤩺𠯫璉<F0A0AFAB><E79289>亦<EFBFBD>**嚗?- [ ] 隞<><E99A9E><EFBFBD>臬炏Git<69>𣂷漱
|
||
- [ ] Todo<64>𡑒”<F0A19192>臬炏<E887AC>湔鰵
|
||
- [ ] <20><><EFBFBD><EFBFBD><EFBFBD>䔮憸䀹糓<E480B9>西扇敶?- [ ] API靚<49>鍂<EFBFBD>臬炏甇<E7828F>虜
|
||
|
||
**瘥誩𪂹璉<F0AA82B9><E79289>亦<EFBFBD>**嚗?- [ ] <20>蠘<EFBFBD>摰峕<E691B0>摨行糓<E8A18C>衣泵<E8A1A3><E6B3B5><EFBFBD><EFBFBD>?- [ ] <20>臬炏<E887AC><E7828F>閬<EFBFBD><E996AC><EFBFBD>渲恣<E6B8B2>?- [ ] <20>臬炏<E887AC><E7828F>閬<EFBFBD><E996AC>憭𤥁<E686AD>皞?
|
||
---
|
||
|
||
## <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝟颱<E89D9F><E9A2B1>舀<EFBFBD>
|
||
|
||
### 14.1 <20><><EFBFBD>舀𣈲<E88880>?
|
||
**<2A><><EFBFBD><EFBFBD>桅<EFBFBD><E6A185>?*嚗?1. <20>仿<EFBFBD>撟喳蝱<E596B3>箇<EFBFBD>霈暹鴌<E69AB9><E9B48C>﹝嚗Ǒbackend/src/common/README.md`嚗?2. <20>仿<EFBFBD>鈭穃<E988AD><E7A983>笔<EFBFBD><E7AC94>𤏸<EFBFBD><F0A48FB8><EFBFBD><EFBFBD>`docs/04-撘<><E69298>𤏸<EFBFBD><F0A48FB8>?08-鈭穃<E988AD><E7A983>笔<EFBFBD><E7AC94>𤏸<EFBFBD><F0A48FB8>?md`嚗?3. <20><><EFBFBD><EFBFBD>SL璅∪<E79285>隞<EFBFBD><E99A9E>嚗Ǒfrontend-v2/src/modules/asl/`嚗?4. <20>亦<EFBFBD><E4BAA6>𡒊垢API隞<49><E99A9E>嚗Ǒbackend/src/modules/dc/tool-b/`嚗?
|
||
### 14.2 隞<><E99A9E>摰⊥䰻
|
||
|
||
**<EFBFBD>𣂷漱<EFBFBD>滩䌊璉<EFBFBD>**嚗?- [ ] <20>臬炏<E887AC>萄<EFBFBD>鈭穃<E988AD><E7A983>蠘<EFBFBD><E8A098>?- [ ] <20>臬炏憭滨鍂撟喳蝱<E596B3>賢<EFBFBD>
|
||
- [ ] TypeScript蝐餃<E89D90><E9A483>臬炏摰峕㟲
|
||
- [ ] <20>臬炏<E887AC>凤ODO/FIXME瘜券<E7989C>
|
||
- [ ] <20>臬炏<E887AC>実onsole.log嚗<67><E59A97>雿輻鍂logger嚗?
|
||
---
|
||
|
||
## <20>㴓 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>餌<EFBFBD>
|
||
|
||
### <20>詨<EFBFBD><E8A9A8>格<EFBFBD>
|
||
摰峕<EFBFBD>DC璅∪<EFBFBD>Tool B<><42><EFBFBD>蝡臬<E89DA1><E887AC>𡢅<EFBFBD>摰䂿緵隞擧<E99A9E>隞嗡<E99A9E>隡惩<E99AA1>蝏𤘪<E89D8F>撖澆枂<E6BE86><E69E82><EFBFBD><EFBFBD>?甇交<E79487>蝔页<E89D94><E9A1B5>孵<EFBFBD><E5ADB5>?*<2A>脩<EFBFBD>撉諹<E69289>蝵烐聢**餈嗘<E9A488><E59798>詨<EFBFBD><E8A9A8>蠘<EFBFBD><E8A098>?
|
||
### <20>喲睸<E596B2>𣂼<EFBFBD><F0A382BC>删<EFBFBD>
|
||
1. <20>?**<2A>𡒊垢撌?00%摰峕<E691B0>**嚗<><E59A97>蝡臬虾銝𤘪釣UI<55>䔶漱鈭?2. <20>?**撟喳蝱<E596B3>賢<EFBFBD>摰<EFBFBD><E691B0>**嚗<>虾<EFBFBD>湔𦻖憭滨鍂嚗峕<E59A97><E5B395><EFBFBD><EFBFBD>滚<EFBFBD>撘<EFBFBD><E69298>?3. <20>?**霈曇恣<E69B87><E681A3>﹝朣𣂼<E69CA3>**嚗峕<E59A97>皜<EFBFBD>苊<EFBFBD><E88B8A><EFBFBD><EFBFBD>见<EFBFBD><E8A781><EFBFBD>瘙?4. <20>?**<2A><><EFBFBD><EFBFBD>芋<EFBFBD>埈<EFBFBD><E59F88>?*嚗淾SL璅∪<E79285><E288AA>臭<EFBFBD>銝箏<E98A9D><E7AE8F>?5. <20>?**<2A>嗆<EFBFBD><E59786>寞<EFBFBD><E5AF9E>𡒊&**嚗屸<E59A97><E5B1B8>冽䲮獢㇁嚗<E38781>𡠺蝡閪ortal嚗?
|
||
### 憸<><E686B8><EFBFBD>嗥<EFBFBD>
|
||
- **<2A>冽<EFBFBD>隞瑕<E99A9E>?*嚗𡁏<E59A97>靘𡩅I撽勗𢆡<E58B97><F0A286A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>賢<EFBFBD>嚗<EFBFBD><E59A97>璅∪<E79285>鈭文<E988AD>撉諹<E69289><E8ABB9>鞾<EFBFBD><E99EBE>唳旿韐券<E99F90>
|
||
- **<2A><><EFBFBD>臭遠<E887AD>?*嚗𡁜<E59A97><F0A1819C>渡<EFBFBD><E6B8A1>滨垢璅∪<E79285><E288AA>𡝗沲<F0A19D97><E6B2B2><EFBFBD><EFBFBD>臬<EFBFBD><E887AC>函<EFBFBD>隞嗅<E99A9E>
|
||
- **<2A><><EFBFBD>隞瑕<E99A9E>?*嚗関ool B<>舐𡠺蝡钅<E89DA1><E99285>殷<EFBFBD>皛∟雲<E2889F>餌<EFBFBD><E9A48C>唳旿憭<E697BF><E686AD><EFBFBD><EFBFBD>瘙?
|
||
---
|
||
|
||
**撘<><E69298>𤏸恣<F0A48FB8>鍦<EFBFBD>摰𡁜<E691B0><F0A1819C>琜<EFBFBD>** <20>?
|
||
**銝衤<E98A9D>甇?*嚗𡁻<E59A97>霂<EFBFBD>㺭<EFBFBD>桀<EFBFBD>銵?<3F>?瘚贝<E7989A><E8B49D>𡒊垢API <20>?撘<>憪閪hase 1嚗㇊ortal憿菟𢒰撘<F0A292B0><E69298>𡢅<EFBFBD>
|
||
|
||
**憸<>恣摰峕<E691B0><E5B395>園𡢿**嚗?-6銝芸極雿𨀣𠯫
|
||
|
||
**蟡嘥<E89FA1><E598A5>煾◇<E785BE>抬<EFBFBD>** <20><>
|
||
|