Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/02-技术设计/API设计文档-DC模块(完整版).md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
Major Changes:
- Add StreamingService with OpenAI Compatible format
- Upgrade Chat component V2 with Ant Design X integration
- Implement AIA module with 12 intelligent agents
- Update API routes to unified /api/v1 prefix
- Update system documentation

Backend (~1300 lines):
- common/streaming: OpenAI Compatible adapter
- modules/aia: 12 agents, conversation service, streaming integration
- Update route versions (RVW, PKB to v1)

Frontend (~3500 lines):
- modules/aia: AgentHub + ChatWorkspace (100% prototype restoration)
- shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook
- Update API endpoints to v1

Documentation:
- AIA module status guide
- Universal capabilities catalog
- System overview updates
- All module documentation sync

Tested: Stream response verified, authentication working
Status: AIA V2.0 core completed (85%)
2026-01-14 19:15:01 +08:00

16 KiB
Raw Blame History

API霈曇恣<EFBFBD><EFBFBD>﹝ - 撌亙<E6928C>B嚗<42><E59A97><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>箏膥鈭綽<E988AD>

<EFBFBD>: DC<44>唳旿皜<E697BF><E79A9C><EFBFBD><EFBFBD> - 撌亙<E6928C>B
<EFBFBD><EFBFBD>𧋦: V2.0 (MVP)
Base URL: /api/v1/dc/tool-b
<EFBFBD>湔鰵<EFBFBD><EFBFBD>: 2025-12-03
**<2A><EFBFBD>?*: <20>?MVP摰峕<E691B0>嚗?銝服PI蝡舐<E89DA1><E88890><EFBFBD><E588B8>舐鍂嚗<E98D82>歇撉諹<E69289>嚗?


<EFBFBD><EFBFBD> <20><EFBFBD>


<EFBFBD><EFBFBD><EFBFBD>PI璁<EFBFBD><EFBFBD>

1.1 蝡舐<E89DA1><E88890>𡑒”

# <EFBFBD><EFBFBD> 頝臬<EFBFBD> 霂湔<EFBFBD> <EFBFBD>𡒊垢<EFBFBD><EFBFBD>? <EFBFBD>滨垢<EFBFBD><EFBFBD>? 瘚贝<EFBFBD><EFBFBD><EFBFBD>?
0 POST /upload <EFBFBD><EFBFBD>辣銝𠹺<EFBFBD> <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
1 POST /health-check <EFBFBD>亙熒璉<EFBFBD><EFBFBD>? <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
2 GET /templates <EFBFBD><EFBFBD>璅⊥踎<EFBFBD>𡑒” <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
3 POST /tasks <EFBFBD>𥕦遣<EFBFBD>𣂼<EFBFBD>隞餃𦛚 <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
4 GET /tasks/:taskId/progress <EFBFBD>亥砭隞餃𦛚餈𥕦漲 <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
5 GET /tasks/:taskId/items <EFBFBD><EFBFBD>撉諹<EFBFBD>蝵烐聢<EFBFBD>唳旿 <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
6 POST /items/:itemId/resolve <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>
7 GET /tasks/:taskId/export 撖澆枂Excel蝏𤘪<EFBFBD> <EFBFBD>?撌脣<E6928C><E884A3>? <EFBFBD>?撌脣笆<E884A3>? <EFBFBD>?<3F><EFBFBD>

**<2A>?MVP摰峕<E691B0><E5B395><EFBFBD><E59786><EFBFBD>2025-12-03嚗?*嚗?- <20>𡒊垢隞<E59EA2><E99A9E>嚗鰺2200銵䕘<E98AB5><E49598>俟ervice<63><65>ontroller<65><72>outes嚗?- <20>滨垢隞<E59EA2><E99A9E>嚗鰺1400銵䕘<E98AB5>5甇亙極雿𨀣<E99BBF>摰峕㟲摰䂿緵嚗?- <20>唳旿摨栞”嚗?撘㰘”撌脣<E6928C>撱綽<E692B1>3銝芷<E98A9D>霈暹芋<E69AB9>踹歇撠梁貌

  • API撖寞𦻖嚗?銝芰垢<E88AB0><EFBFBD><E5ADB5><EFBFBD><E588B8>𣂼僎瘚贝<E7989A><E8B49D><EFBFBD>
  • LLM靚<EFBFBD>鍂嚗鋽eepSeek-V3 + Qwen-Max <20>峕芋<E5B395><EFBFBD><EFBFBD><E99C82><EFBFBD>?- <20><EFBFBD>瘚贝<E7989A>嚗?<3F><EFBFBD><E288A0><EFBFBD><EFBFBD><EFBFBD><E6A0BC>𡝗<EFBFBD><F0A19D97><EFBFBD><EFBFBD>Token瘨<6E><E798A8>煫10k
  • **撌脩䰻<E884A9><EFBFBD>**嚗?銝芣<E98A9D><E88AA3><EFBFBD>箏𦛚嚗<F0A69B9A><E59A97>07-<2D><><EFBFBD><EFBFBD>箏𦛚/Tool-B<><42><EFBFBD><EFBFBD>箏𦛚皜<F0A69B9A><E79A9C>.md嚗?

1.2 <20>𡁶鍂閫<E98D82><E996AB>

**霂瑟<E99C82>憭?*嚗?```http Content-Type: application/json Authorization: Bearer {token} # <20>芣䔉摰䂿緵


**<2A><EFBFBD><E6BB9A><EFBFBD>**嚗?```json
{
  "data": {...},      // <20>𣂼<EFBFBD><F0A382BC><EFBFBD><E59789>?  "error": "...",     // 憭梯揖<E6A2AF><EFBFBD><E59789>?  "code": 200
}

**HTTP<54><EFBFBD><E59786><EFBFBD>**嚗?- 200: <20>𣂼<EFBFBD>

  • 400: 霂瑟<E99C82><E7919F><EFBFBD><EFBFBD>躰秤
  • 401: <20>芾恕霂?- 403: <20><EFBFBD><E4ADBE>?- 404: 韏<><E99F8F>銝滚<E98A9D><E6BB9A>?- 500: <20>滚𦛚<E6BB9A><EFBFBD><E585B8><EFBFBD>霂?

鈭䎚<EFBFBD><EFBFBD>恕霂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

2.1 霈方<E99C88><E696B9><EFBFBD>

**敶枏<E695B6><E69E8F>嗆挾嚗㇈VP嚗?*嚗?- <20>?<3F><><EFBFBD>摰䂿緵霈方<E99C88>

  • 雿輻鍂銝湔𧒄userId<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂瑟<EFBFBD>銝𠹺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

**<2A>芣䔉摰䂿緵嚗Ā1.0嚗?*嚗?```http Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...


### 2.2 <20><><EFBFBD><E79285>

| <20><EFBFBD> | <20><><EFBFBD><EFBFBD><E996AC> | 霂湔<E99C82> |
|------|---------|------|
| <20>亙熒璉<E78692><E79289>?| user | <20><><EFBFBD>厩鍂<E58EA9>?|
| <20><EFBFBD>璅⊥踎 | user | <20><><EFBFBD>厩鍂<E58EA9>?|
| <20>𥕦遣隞餃𦛚 | user | <20><><EFBFBD>厩鍂<E58EA9>?|
| <20>亥砭隞餃𦛚 | owner | 隞<><EFBFBD><EFBFBD>撱箄<E692B1>?|
| 鋆<><E98B86><EFBFBD><EFBFBD> | owner | 隞<><EFBFBD><EFBFBD>撱箄<E692B1>?|

---

## 銝剹<E98A9D><E589B9>PI蝡舐<E89DA1>霂行<E99C82>

### 3.1 <20>亙熒璉<E78692><E79289>?
**蝡舐<E89DA1>**: `POST /api/v1/dc/tool-b/health-check`

**<2A><EFBFBD>?*: 璉<><E79289>乍xcel<65><EFBFBD><E39B96>唳旿韐券<E99F90>嚗峕㜃<E5B395><EFBFBD>韐券<E99F90><E588B8>唳旿

**霂瑟<E99C82>雿?*嚗?```json
{
  "fileKey": "uploads/user123/data.xlsx",
  "columnName": "<22><><EFBFBD><EFBFBD><EFBFBD>𧋦"
}

霂瑟<EFBFBD><EFBFBD><EFBFBD>嚗?

摮埈挾 蝐餃<EFBFBD> <EFBFBD> 霂湔<EFBFBD>
fileKey string <EFBFBD>? Storage銝剔<EFBFBD><EFBFBD><EFBFBD>辣頝臬<EFBFBD>
columnName string <EFBFBD>? <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

**<2A><EFBFBD>**嚗<><E59A97><EFBFBD>?- 200嚗㚁<E59A97>

{
  "status": "good",
  "emptyRate": 0.12,
  "avgLength": 256.8,
  "totalRows": 500,
  "estimatedTokens": 150000,
  "message": "<22>亙熒摨西<E691A8>憟踝<E6869F><EFBFBD>恣瘨<E681A3><E798A8>㛖漲 150.0k Token嚗<EFBFBD><EFBFBD><EFBFBD>蝥?300.0k Token嚗?
}

**<2A><EFBFBD>**嚗<>仃韐?- 200雿<30>tatus=bad嚗㚁<E59A97>

{
  "status": "bad",
  "emptyRate": 0.85,
  "avgLength": 256.8,
  "totalRows": 500,
  "estimatedTokens": 0,
  "message": "蝛箏<E89D9B><EFBFBD><EFBFBD><E9A488>嚗?5.0%嚗㚁<E59A97>霂亙<E99C82>銝漤<E98A9D><E6BCA4><EFBFBD><EFBFBD>𣂼<EFBFBD>"
}

<EFBFBD><EFBFBD>摮埈挾嚗?

摮埈挾 蝐餃<EFBFBD> 霂湔<EFBFBD>
status string good <20>?bad
emptyRate number 蝛箏<EFBFBD><EFBFBD> (0-1)
avgLength number 撟喳<EFBFBD><EFBFBD><EFBFBD>𧋦<EFBFBD>踹漲
totalRows number <EFBFBD><EFBFBD><EFBFBD>?
estimatedTokens number <EFBFBD>摯Token<EFBFBD>?
message string <EFBFBD>鞟內靽⊥<EFBFBD>

**銝𡁜𦛚閫<F0A69B9A><E996AB>**嚗?- 蝛箏<E89D9B><EFBFBD> > 80% <20>?status = 'bad'

  • 撟喳<EFBFBD><EFBFBD>踹漲 < 10 <20>?status = 'bad'
  • <EFBFBD><EFBFBD><EFBFBD><EFBFBD>100銵䕘<EFBFBD><EFBFBD><EFBFBD>隡睃<EFBFBD>嚗? **<2A>躰秤<E8BAB0><EFBFBD>**嚗?```json { "error": "<22>?<3F><><EFBFBD><EFBFBD><EFBFBD>𧋦'銝滚<E98A9D><E6BB9A>?, "code": 400 }

---

### 3.2 <20><EFBFBD>璅⊥踎<E28AA5>𡑒”

**蝡舐<E89DA1>**: `GET /api/v1/dc/tool-b/templates`

**<2A><EFBFBD>?*: <20><EFBFBD><E79195><EFBFBD><EFBFBD><EFBFBD>霈曄<E99C88><E69B84>𣂼<EFBFBD>璅⊥踎

**霂瑟<E99C82>**: <20><EFBFBD><E683A9>?
**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>
```json
{
  "templates": [
    {
      "diseaseType": "lung_cancer",
      "reportType": "pathology",
      "displayName": "<22><EFBFBD><E7AE87><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
      "fields": [
        {
          "name": "<22><><EFBFBD>蝐餃<E89D90>",
          "desc": "憒<><E68692>瘚豢隋<E8B1A2><EFBFBD><E689AF><EFBFBD><E48E9A><EFBFBD><EFBFBD><EFBFBD><E597A5><EFBFBD>",
          "width": "w-40"
        },
        {
          "name": "<22><><EFBFBD>蝔见漲",
          "desc": "擃?銝?雿𤾸<E99BBF><F0A4BEB8>?,
          "width": "w-32"
        }
      ]
    },
    {
      "diseaseType": "diabetes",
      "reportType": "admission",
      "displayName": "蝟硋倏<E7A18B><E5808F><EFBFBD><EFBFBD>扇敶?,
      "fields": [...]
    }
  ]
}

<EFBFBD><EFBFBD>摮埈挾嚗?

摮埈挾 蝐餃<EFBFBD> 霂湔<EFBFBD>
templates array 璅⊥踎<EFBFBD>𡑒”
templates[].diseaseType string <EFBFBD><EFBFBD>蝐餃<EFBFBD>
templates[].reportType string <EFBFBD><EFBFBD>蝐餃<EFBFBD>
templates[].displayName string <EFBFBD>曄內<EFBFBD>滨妍
templates[].fields array <EFBFBD>𣂼<EFBFBD>摮埈挾<EFBFBD>滨蔭

蝻枏<EFBFBD>蝑𣇉裦嚗?- 摰<E691B0>蝡舐<E89DA1>摮矋<E691AE>1撠𤩺𧒄

  • <EFBFBD>滚𦛚蝡舐<EFBFBD>摮矋<EFBFBD>瘞訾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

3.3 <20>𥕦遣<F0A595A6>𣂼<EFBFBD>隞餃𦛚

蝡舐<EFBFBD>: POST /api/v1/dc/tool-b/tasks

**<2A><EFBFBD>?*: <20>𥕦遣<F0A595A6><EFBFBD><E5AFA5>𣂼<EFBFBD>隞餃𦛚嚗峕綫<E5B395><E7B6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

**霂瑟<E99C82>雿?*嚗?```json { "projectName": "<22><EFBFBD><E7AE87><EFBFBD><EFBFBD><EFBFBD>唳旿<E594B3>𣂼<EFBFBD>-2025Q1", "fileKey": "uploads/user123/lung_cancer_pathology.xlsx", "textColumn": "<22><><EFBFBD><EFBFBD><EFBFBD>𧋦", "diseaseType": "lung_cancer", "reportType": "pathology", "targetFields": [ { "name": "<22><><EFBFBD>蝐餃<E89D90>", "desc": "憒<><E68692>瘚豢隋<E8B1A2><EFBFBD><E689AF><EFBFBD><E48E9A><EFBFBD><EFBFBD><EFBFBD><E597A5><EFBFBD>" }, { "name": "<22><><EFBFBD>蝔见漲", "desc": "擃?銝?雿𤾸<E99BBF><F0A4BEB8>? } ] }


**霂瑟<E99C82><E7919F><EFBFBD>㺭**嚗?
| 摮埈挾 | 蝐餃<E89D90> | 敹<> | 霂湔<E99C82> |
|------|------|------|------|
| `projectName` | string | <20>?| 隞餃𦛚<E9A483>滨妍 |
| `fileKey` | string | <20>?| Storage銝剔<E98A9D><E58994><EFBFBD>辣頝臬<E9A09D> |
| `textColumn` | string | <20>?| <20><>𧋦<EFBFBD><EFBFBD> |
| `diseaseType` | string | <20>?| <20><EFBFBD>蝐餃<E89D90> |
| `reportType` | string | <20>?| <20><EFBFBD>蝐餃<E89D90> |
| `targetFields` | array | <20>?| <20>𣂼<EFBFBD>摮埈挾<E59F88>滨蔭 |

**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>
```json
{
  "taskId": "550e8400-e29b-41d4-a716-446655440000"
}

**瘚<><E7989A>**嚗?1. 撉諹<E69289><E8ABB9><EFBFBD>辣摮睃銁 2. 閫<><E996AB>Excel嚗𣬚<E59A97>霈⊥<E99C88><EFBFBD><E9A489>?3. <20>𥕦遣隞餃𦛚霈啣<E99C88>嚗ìtatus=pending嚗?4. <20><EFBFBD><E588B8><EFBFBD>BullMQ<4D><EFBFBD> 5. 蝡见朖餈𥪜<E9A488>taskId

**<2A>躰秤<E8BAB0><EFBFBD>**嚗?```json { "error": "<22><>辣銝滚<E98A9D><E6BB9A>? uploads/user123/lung_cancer_pathology.xlsx", "code": 404 }


---

### 3.4 <20>亥砭隞餃𦛚餈𥕦漲

**蝡舐<E89DA1>**: `GET /api/v1/dc/tool-b/tasks/:taskId/progress`

**<2A><EFBFBD>?*: 摰墧𧒄<E5A2A7>亥砭隞餃𦛚憭<F0A69B9A><E686AD>餈𥕦漲

**霂瑟<E99C82>**: 

GET /api/v1/dc/tool-b/tasks/550e8400-e29b-41d4-a716-446655440000/progress


**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>
```json
{
  "taskId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "progress": 50,
  "totalCount": 500,
  "processedCount": 250,
  "cleanCount": 200,
  "conflictCount": 45,
  "failedCount": 5,
  "totalTokens": 75000,
  "totalCost": 0.135,
  "startedAt": "2025-11-27T10:00:00.000Z",
  "completedAt": null
}

<EFBFBD><EFBFBD>摮埈挾嚗?

摮埈挾 蝐餃<EFBFBD> 霂湔<EFBFBD>
status string pending/processing/completed/failed
progress number 餈𥕦漲<EFBFBD><EFBFBD>瘥?(0-100)
totalCount number <EFBFBD>餉扇敶閙㺭
processedCount number 撌脣<EFBFBD><EFBFBD><EFBFBD>
cleanCount number <EFBFBD><EFBFBD>渲扇敶閙㺭
conflictCount number <EFBFBD><EFBFBD>霈啣<EFBFBD><EFBFBD>?
failedCount number 憭梯揖霈啣<EFBFBD><EFBFBD>?
totalTokens number 蝝航恣Token<EFBFBD>?
totalCost number 蝝航恣<EFBFBD>鞉𧋦($)

頧株砭撱箄悅嚗?- 摰<E691B0>蝡舀<E89DA1>3蝘坿蔭霂<E99C82>甈?- 敶𨦨status = 'completed'`<60><EFBFBD>蔭霂?

3.5 <20><EFBFBD>撉諹<E69289>蝵烐聢<E78390>唳旿

蝡舐<EFBFBD>: GET /api/v1/dc/tool-b/tasks/:taskId/items

**<2A><EFBFBD>?*: <20><EFBFBD><E79195>峕芋<E5B395>𧢲<EFBFBD><F0A7A2B2>𣇉<EFBFBD><F0A38789><EFBFBD><E9A0A3><EFBFBD>鈭箏極鋆<E6A5B5><E98B86>

霂瑟<EFBFBD>:

GET /api/v1/dc/tool-b/tasks/550e8400.../items?page=1&limit=50&status=conflict

<EFBFBD>亥砭<EFBFBD><EFBFBD>嚗?

<EFBFBD><EFBFBD> 蝐餃<EFBFBD> <EFBFBD> 暺䁅恕<EFBFBD>? 霂湔<EFBFBD>
page number <EFBFBD>? 1 憿萇<EFBFBD>
limit number <EFBFBD>? 50 瘥誯△<EFBFBD><EFBFBD>
status string <EFBFBD>? - <EFBFBD><EFBFBD><EFBFBD>?

**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>

{
  "items": [
    {
      "id": "item-123",
      "rowIndex": 5,
      "originalText": "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>45撗<35><E69297>霂𦠜鱏銝箸絡瘨行<E798A8><EFBFBD><E689AF><EFBFBD>銝剖<E98A9D><E58996><EFBFBD><E59094>輻𠈔<E8BCBB><F0A08894>憭批<E686AD>3cm...",
      "resultA": {
        "<22><><EFBFBD>蝐餃<E89D90>": "瘚豢隋<E8B1A2><EFBFBD><E689AF>?,
        "<EFBFBD><EFBFBD><EFBFBD>蝔见漲": "銝剖<EFBFBD><EFBFBD>?,
        "<22>輻𠈔憭批<E686AD>": "3cm"
      },
      "resultB": {
        "<22><><EFBFBD>蝐餃<E89D90>": "瘚豢隋<E8B1A2><EFBFBD><E689AF>?,
        "<EFBFBD><EFBFBD><EFBFBD>蝔见漲": "銝剖<EFBFBD><EFBFBD>?,
        "<22>輻𠈔憭批<E686AD>": "3.0cm"
      },
      "status": "conflict",
      "conflictFields": ["<22>輻𠈔憭批<E686AD>"],
      "finalResult": null
    }
  ],
  "pagination": {
    "total": 45,
    "page": 1,
    "pageSize": 50,
    "totalPages": 1
  }
}

<EFBFBD><EFBFBD>摮埈挾嚗?

摮埈挾 蝐餃<EFBFBD> 霂湔<EFBFBD>
items array 霈啣<EFBFBD><EFBFBD>𡑒”
items[].status string clean/conflict/resolved/failed
items[].conflictFields array <EFBFBD><EFBFBD>摮埈挾<EFBFBD>𡑒”
pagination object <EFBFBD><EFBFBD>△靽⊥<EFBFBD>

3.6 鋆<><E98B86><EFBFBD><EFBFBD>

蝡舐<EFBFBD>: POST /api/v1/dc/tool-b/items/:itemId/resolve

**<2A><EFBFBD>?*: 鈭箏極<E7AE8F>㗇𥋘甇<F0A58B98><EFBFBD><EFBC86><EFBFBD><EFBFBD>𣇉<EFBFBD><F0A38789>? 霂瑟<EFBFBD>:

{
  "field": "<22>輻𠈔憭批<E686AD>",
  "chosenValue": "3cm"
}

霂瑟<EFBFBD><EFBFBD><EFBFBD>嚗?

摮埈挾 蝐餃<EFBFBD> <EFBFBD> 霂湔<EFBFBD>
field string <EFBFBD>? <EFBFBD><EFBFBD>摮埈挾<EFBFBD>?
chosenValue string <EFBFBD>? <EFBFBD>㗇𥋘<EFBFBD><EFBFBD><EFBFBD>?

**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>

{
  "success": true
}

**銝𡁜𦛚<F0A1819C><EFBFBD>**嚗?1. <20>湔鰵finalResult[field] = chosenValue 2. 隞𥳾conflictFields銝剔宏<EFBFBD>方砲摮埈挾 3. 憒<><E68692><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E59689>湔鰵status = 'resolved'`


3.7 撖澆枂蝏𤘪<E89D8F>

蝡舐<EFBFBD>: GET /api/v1/dc/tool-b/tasks/:taskId/export

**<2A><EFBFBD>?*: 撖澆枂<E6BE86><E69E82><EFBFBD><E89D8F><EFBFBD>𣇉<EFBFBD><F0A38789>靝蛹Excel

霂瑟<EFBFBD>:

GET /api/v1/dc/tool-b/tasks/550e8400.../export?format=xlsx

<EFBFBD>亥砭<EFBFBD><EFBFBD>嚗?

<EFBFBD><EFBFBD> 蝐餃<EFBFBD> <EFBFBD> 暺䁅恕<EFBFBD>? 霂湔<EFBFBD>
format string <EFBFBD>? xlsx 撖澆枂<EFBFBD><EFBFBD>嚗䫤xlsx/csv`

**<2A><EFBFBD>**嚗?00嚗㚁<E59A97>

  • <EFBFBD><EFBFBD>辣瘚<EFBFBD><EFBFBD>頧?- Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • Content-Disposition: attachment; filename="extraction_result_2025-11-27.xlsx"

撖澆枂<EFBFBD><EFBFBD>嚗?- <20><><EFBFBD><EFBFBD><E7AC94>?+ <20><><EFBFBD><EFBFBD><E39787><EFBFBD>畾?- <20><EFBFBD><E88AB8>冑clean<EFBFBD>䈣resolved<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霈啣<EFBFBD>

  • <EFBFBD><EFBFBD>霈啣<EFBFBD>銝滚紡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭箏極鋆<EFBFBD><EFBFBD>嚗?

<EFBFBD><EFBFBD><EFBFBD><EFBFBD>格芋<EFBFBD>?

4.1 HealthCheckResult

interface HealthCheckResult {
  status: 'good' | 'bad';
  emptyRate: number;
  avgLength: number;
  totalRows: number;
  estimatedTokens: number;
  message: string;
}

4.2 Template

interface Template {
  diseaseType: string;
  reportType: string;
  displayName: string;
  fields: TemplateField[];
}

interface TemplateField {
  name: string;
  desc: string;
  width?: string;
}

4.3 ExtractionTask

interface ExtractionTask {
  id: string;
  userId: string;
  projectName: string;
  sourceFileKey: string;
  textColumn: string;
  
  diseaseType: string;
  reportType: string;
  targetFields: TemplateField[];
  
  status: 'pending' | 'processing' | 'completed' | 'failed';
  totalCount: number;
  processedCount: number;
  cleanCount: number;
  conflictCount: number;
  failedCount: number;
  
  totalTokens: number;
  totalCost: number;
  
  createdAt: Date;
  startedAt?: Date;
  completedAt?: Date;
}

4.4 ExtractionItem

interface ExtractionItem {
  id: string;
  taskId: string;
  rowIndex: number;
  originalText: string;
  
  resultA?: Record<string, any>;
  resultB?: Record<string, any>;
  
  status: 'pending' | 'clean' | 'conflict' | 'resolved' | 'failed';
  conflictFields: string[];
  
  finalResult?: Record<string, any>;
  
  tokensA: number;
  tokensB: number;
}

鈭𢛵<EFBFBD><EFBFBD><EFBFBD>霂臬<EFBFBD><EFBFBD>?

5.1 <20>躰秤<E8BAB0><EFBFBD><E6BB9A><EFBFBD>

{
  "error": "<22>躰秤<E8BAB0>讛膩",
  "code": 400,
  "details": {
    "field": "fileKey",
    "reason": "<22><>辣銝滚<E98A9D><E6BB9A>?
  }
}

5.2 撣貉<E692A3><E8B289>躰秤<E8BAB0>?

HTTP<EFBFBD><EFBFBD>? code 霂湔<EFBFBD> 蝷箔<EFBFBD>
400 INVALID_PARAMS <EFBFBD><EFBFBD><EFBFBD>躰秤 蝻箏<EFBFBD>fileKey
400 COLUMN_NOT_FOUND <EFBFBD>𦯀<EFBFBD>摮睃銁 <EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD>𧋦"銝滚<E98A9D><E6BB9A>?
400 BAD_HEALTH <EFBFBD>亙熒璉<EFBFBD><EFBFBD>交𧊋<EFBFBD><EFBFBD> 蝛箏<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
404 FILE_NOT_FOUND <EFBFBD><EFBFBD>辣銝滚<EFBFBD><EFBFBD>? <EFBFBD><EFBFBD>辣頝臬<EFBFBD><EFBFBD><EFBFBD>
404 TASK_NOT_FOUND 隞餃𦛚銝滚<EFBFBD><EFBFBD>? taskId<EFBFBD><EFBFBD>
403 FORBIDDEN <EFBFBD><EFBFBD>霈輸䔮 <EFBFBD><EFBFBD>霈輸䔮<EFBFBD>芸楛<EFBFBD><EFBFBD><EFBFBD>?
500 INTERNAL_ERROR <EFBFBD>滚𦛚<EFBFBD><EFBFBD>霂? <EFBFBD>唳旿摨栞<EFBFBD><EFBFBD>亙仃韐?

5.3 <20>躰秤憭<E7A7A4><E686AD><EFBFBD><EFBFBD>雿喳<E99BBF>頝?

**摰<E691B0>蝡?*嚗?```typescript try { const response = await fetch('/api/v1/dc/tool-b/health-check', { method: 'POST', body: JSON.stringify({ fileKey, columnName }) });

if (!response.ok) { const error = await response.json(); throw new Error(error.error); }

const data = await response.json();

if (data.status === 'bad') { alert(data.message); // <20>亙熒璉<E78692><E79289>交𧊋<E4BAA4><EFBFBD> return; }

// 蝏抒賒銝衤<E98A9D>甇?} catch (error) { console.error('<27>亙熒璉<E78692><E79289>亙仃韐?', error); }


---

## <20><EFBFBD><E58786><EFBFBD><EFBFBD><E689AF><EFBFBD><EFBFBD>

### 6.1 <20><EFBFBD><E6BB9A>園𡢿<E59C92><EFBFBD>

| API | <20><EFBFBD> | 霂湔<E99C82> |
|-----|------|------|
| `/health-check` | < 3蝘?| Excel閫<6C><E996AB>+蝏蠘恣 |
| `/templates` | < 100ms | <20><><EFBFBD>蝻枏<E89DBB> |
| `/tasks` (create) | < 500ms | 敹恍<E695B9><EFBFBD>撱箏僎餈𥪜<E9A488> |
| `/tasks/:id/progress` | < 100ms | <20>唳旿摨枏<E691A8><E69E8F>亥砭 |
| `/tasks/:id/items` | < 500ms | <20><><EFBFBD>亥砭 |
| `/items/:id/resolve` | < 200ms | <20><EFBFBD><E99697>湔鰵 |
| `/tasks/:id/export` | < 10蝘?| <20><><EFBFBD>Excel<65><6C>辣 |

### 6.2 撟嗅<E6929F><EFBFBD><E686AD><EFBFBD><EFBFBD>

- **<2A>亙熒璉<E78692><E79289>?*: 10 req/s嚗㇆O撖<4F><E69296>嚗?- **隞餃𦛚<E9A483>𥕦遣**: 5 req/s嚗<73><E59A97><EFBFBD>交㺭<E4BAA4><EFBFBD>嚗?- **餈𥕦漲<F0A595A6>亥砭**: 100 req/s嚗<73>粉撖<E7B289><E69296><EFBFBD>虾蝻枏<E89DBB>嚗?- **撉諹<E69289>蝵烐聢**: 50 req/s嚗<73><E59A97>憿菜䰻霂<E99C82>

### 6.3 隡睃<E99AA1>蝑𣇉裦

**蝻枏<E89DBB>**嚗?- `/templates` <20>?瘞訾<E7989E>蝻枏<E89DBB><EFBFBD><E59A97>摮矋<E691AE>
- `/tasks/:id/progress` <20>?Redis蝻枏<E89DBB>嚗?蝘塬TL嚗?
**撘<>郊憭<E9838A><E686AD>**嚗?- 隞餃𦛚憭<F0A69B9A><E686AD>雿輻鍂BullMQ<4D>𤾸蝱<F0A4BEB8><EFBFBD>
- <20><EFBFBD><E8B8B9><EFBFBD><E9A483><EFBFBD>霂瑟<E99C82>

**<2A><>△**嚗?- 撉諹<E69289>蝵烐聢暺䁅恕50<35>?憿?- <20><>憭?000<30>?憿?
---

## 銝<><E98A9D><EFBFBD><EFBFBD><EFBFBD>祆綉<E7A586>?
### 7.1 API<50><49>𧋦蝑𣇉裦

**敶枏<E695B6><E69E8F><EFBFBD>𧋦**: `v1`

**URL<52><EFBFBD>**: `/api/v1/dc/tool-b/*`

**<2A><EFBFBD><E7A983>澆捆<E6BE86>輯笑**嚗?- v1<76><31>𧋦<EFBFBD>?026撟游<E6929F>靽脲<E99DBD>蝔喳<E89D94>
- <20><EFBFBD><E595A3><EFBFBD><EFBFBD><E69C9E><EFBFBD><EFBFBD><E58CA7>唳溶<E594B3>?- <20><EFBFBD><E6B8B8><EFBFBD><E689B9><EFBFBD><EFBFBD>2

### 7.2 摨笔<E691A8><E7AC94>𡁶䰻

敶𨯗PI<50><49><EFBFBD><E996AC><EFBFBD>𧒄嚗?```http
HTTP/1.1 200 OK
X-API-Deprecated: true
X-API-Sunset: 2026-12-31
X-API-Replacement: /api/v2/dc/tool-b/health-check

<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂?

8.1 Postman Collection

摰峕㟲<EFBFBD><EFBFBD>PI瘚贝<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?``` docs/03-銝𡁜𦛚璅<E79285>/DC-<2D>唳旿皜<E697BF><E79A9C><EFBFBD><EFBFBD>/02-<2D><><EFBFBD>航挽霈?ToolB-API.postman_collection.json


### 8.2 蝷箔<E89DB7>霂瑟<E99C82>

**<2A>亙熒璉<E78692><E79289>?*嚗?```bash
curl -X POST http://localhost:3001/api/v1/dc/tool-b/health-check \
  -H "Content-Type: application/json" \
  -d '{
    "fileKey": "uploads/test.xlsx",
    "columnName": "<22><><EFBFBD><EFBFBD><EFBFBD>𧋦"
  }'

<EFBFBD><EFBFBD>璅⊥踎嚗?```bash curl http://localhost:3001/api/v1/dc/tool-b/templates


**<2A>𥕦遣隞餃𦛚**嚗?```bash
curl -X POST http://localhost:3001/api/v1/dc/tool-b/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "projectName": "瘚贝<E7989A>隞餃𦛚",
    "fileKey": "uploads/test.xlsx",
    "textColumn": "<22><><EFBFBD><EFBFBD><EFBFBD>𧋦",
    "diseaseType": "lung_cancer",
    "reportType": "pathology",
    "targetFields": [{"name": "<22><><EFBFBD>蝐餃<E89D90>", "desc": "..."}]
  }'

銋腈<EFBFBD><EFBFBD><EFBFBD>敶?

9.1 <20><EFBFBD><E8A9A8><EFBFBD>

  • [<5B>唳旿摨栞挽霈⊥<E99C88>獢β(./<2F>唳旿摨栞挽霈⊥<E99C88>獢?撌亙<E6928C>B.md)
  • [PRD<52><44>﹝](../01-<2D><><EFBFBD><E79899><EFBFBD>?PRD嚗関ool B - <20><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖 (The AI Structurer).md)
  • [撘<><E69298>𤏸恣<F0A48FB8>哋(../04-撘<><E69298>𤏸恣<F0A48FB8>?撌亙<E6928C>B撘<42><E69298>𤏸恣<F0A48FB8>?<3F><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖.md)

9.2 <20>䀹凒<E480B9><EFBFBD>

<EFBFBD><EFBFBD>𧋦 <EFBFBD><EFBFBD> <EFBFBD>䀹凒<EFBFBD><EFBFBD>
V1.0 2025-11-27 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>𧋦嚗?銝服PI蝡舐<E89DA1>

<EFBFBD><EFBFBD>﹝蝏𤘪<EFBFBD> <20>?