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%)
This commit is contained in:
2026-01-14 19:15:01 +08:00
parent 3d35e9c58b
commit 1b53ab9d52
386 changed files with 52096 additions and 65238 deletions

View File

@@ -2,35 +2,26 @@
## <20><><>
**目标**在4个核心功能中添加对NA空值/缺失值)的显式处理,让用户能够明确看到并处理缺失值。
**NA显示名称**`空值/NA`(中英文结合)
**<EFBFBD><EFBFBD>**嚗𡁜銁4銝芣瓲敹<E793B2><E695B9><EFBFBD>賭葉瘛餃<E7989B>撖遑A嚗<41><EFBFBD>?蝻箏仃<E7AE8F><EFBFBD><E6BD98><EFBFBD>遬撘誩<E69298><E8AAA9><EFBFBD><EFBFBD>霈拍鍂<E68B8D><EFBFBD><EFBFBD><E686AD>蝖桃<E89D96><E6A183>啣僎憭<E5838E><E686AD>蝻箏仃<E7AE8F><EFBFBD>?
**NA<4E>曄內<E69B84>滨妍**嚗䫤蝛箏<E89D9B>?NA`嚗<><EFBFBD><EFBFBD>蝏枏<E89D8F>嚗?
---
## ✅ 已完成:Python后端100%
### 1. recode.py - 数值映射 ✅
**新增参数**
- `na_handling`: 'keep' | 'map' | 'drop'
## <EFBFBD>?撌脣<E6928C><E884A3><EFBFBD>Python<EFBFBD>𡒊垢嚗?00%嚗?
### 1. recode.py - <20><EFBFBD><EFBFBD>撠?<3F>?
**<2A><EFBFBD><E595A3><EFBFBD>㺭**嚗?- `na_handling`: 'keep' | 'map' | 'drop'
- `keep`: 靽脲<E99DBD>銝摸A嚗<41><E59A97>霈歹<E99C88>
- `map`: 映射为指定值
- `drop`: 删除包含NA的行
- `map`: <20><EFBFBD>銝箸<E98A9D>摰𡁜<E691B0>? - `drop`: <20>𣳇膄<F0A3B387><E88684>鉄NA<4E><41><EFBFBD>
- `na_value`: NA<4E><EFBFBD><E683A9><EFBFBD>敶忛a_handling='map'<27>嗡蝙<E597A1><EFBFBD>
**实现逻辑**
```python
**摰䂿緵<EFBFBD><EFBFBD>**嚗?```python
if original_na_count > 0:
na_mask = result[column].isna()
if na_handling == 'keep':
# 保持为NA已经是NA无需操作
print(f'📊 NA处理保持为NA{original_na_count}个)')
# 靽脲<EFBFBD>銝摸A嚗<EFBFBD>歇蝏𤩺糓NA嚗峕<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗? print(f'<27><> NA憭<41><E686AD>嚗帋<E59A97><E5B88B><EFBFBD>蛹NA嚗ùoriginal_na_count}銝迎<E98A9D>')
elif na_handling == 'map':
# 映射为指定值
result.loc[na_mask, target_column] = na_value
# <EFBFBD><EFBFBD>銝箸<EFBFBD>摰𡁜<EFBFBD>? result.loc[na_mask, target_column] = na_value
print(f'<27><> NA憭<41><E686AD>嚗𡁏<E59A97><EFBFBD>蛹 {na_value}嚗ùoriginal_na_count}銝迎<E98A9D>')
elif na_handling == 'drop':
@@ -38,10 +29,8 @@ if original_na_count > 0:
result = result[~na_mask].copy()
```
### 2. filter.py - 高级筛选 ✅
**已支持**`is_null``not_null` 运算符
### 2. filter.py - 擃条漣蝑偦<EFBFBD>?<3F>?
**撌脫𣈲<E884AB>?*嚗䫤is_null` <20>?`not_null` 餈鞟<E9A488>蝚?
<EFBFBD>𣳇<EFBFBD>靽格㺿嚗<EFBFBD><EFBFBD><EFBFBD>劐誨<EFBFBD><EFBFBD>歇蝏𤩺𣈲<EFBFBD><EFBFBD><EFBFBD>
```python
@@ -51,18 +40,14 @@ elif operator == 'not_null':
mask = df[column].notna()
```
### 3. binning.py - 生成分类变量 ✅
**新增参数**
- `na_handling`: 'keep' | 'label' | 'assign'
### 3. binning.py - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>?
**<2A><EFBFBD><E595A3><EFBFBD>㺭**嚗?- `na_handling`: 'keep' | 'label' | 'assign'
- `keep`: 靽脲<E99DBD>銝摸A嚗<41><E59A97>霈歹<E99C88>
- `label`: 标记为指定标签(如"缺失"
- `assign`: 分配到指定组
- `label`: <EFBFBD><EFBFBD>扇銝箸<EFBFBD>摰𡁏<EFBFBD>蝑橘<EFBFBD>憒?蝻箏仃"嚗? - `assign`: <20><><EFBFBD><EFBFBD><EFBFBD>摰𡁶<E691B0>
- `na_label`: NA<4E><41>倌嚗<E5808C><E59A97>na_handling='label'<27>嗡蝙<E597A1><EFBFBD>
- `na_assign_to`: NA<4E><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD>揣撘𤏪<E69298>敶忛a_handling='assign'<27>嗡蝙<E597A1><EFBFBD>
**实现逻辑**
```python
**摰䂿緵<EFBFBD><EFBFBD>**嚗?```python
if original_na_count > 0:
na_mask = result[column].isna()
@@ -71,8 +56,7 @@ if original_na_count > 0:
print(f'<27><> NA憭<41><E686AD>嚗帋<E59A97><E5B88B><EFBFBD>蛹NA嚗ùoriginal_na_count}銝迎<E98A9D>')
elif na_handling == 'label':
# 标记为指定标签
label_to_use = na_label if na_label else '空值/NA'
# <EFBFBD><EFBFBD>扇銝箸<EFBFBD>摰𡁏<EFBFBD>蝑? label_to_use = na_label if na_label else '蝛箏<E89D9B>?NA'
result.loc[na_mask, new_column_name] = label_to_use
print(f'<27><> NA憭<41><E686AD>嚗𡁏<E59A97>霈唬蛹 "{label_to_use}"嚗ùoriginal_na_count}銝迎<E98A9D>')
@@ -82,34 +66,27 @@ if original_na_count > 0:
result.loc[na_mask, new_column_name] = labels[na_assign_to]
```
### 4. conditional.py - 条件生成列 ✅
**新增支持**`is_null``not_null` 运算符
### 4. conditional.py - <EFBFBD>∩辣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?
**<2A><EFBFBD><E595A3><EFBFBD>**嚗䫤is_null` <20>?`not_null` 餈鞟<E9A488>蝚?
```python
elif operator == 'is_null': # ✨ 新增:为空
mask = result[column].isna()
elif operator == 'not_null': # ✨ 新增:不为空
elif operator == 'is_null': # <EFBFBD>?<3F><EFBFBD>嚗帋蛹蝛? mask = result[column].isna()
elif operator == 'not_null': # <20>?<3F><EFBFBD>嚗帋<E59A97>銝箇征
mask = result[column].notna()
```
### 5. main.py - API请求模型 ✅
**RecodeRequest**
```python
### 5. main.py - API霂瑟<EFBFBD><EFBFBD> <20>?
**RecodeRequest**嚗?```python
na_handling: str = 'keep'
na_value: Any = None
```
**BinningRequest**
```python
**BinningRequest**嚗?```python
na_handling: str = 'keep'
na_label: str = None
na_assign_to: int = None
```
**FilterRequest ConditionalRequest**
无需修改,已支持
**FilterRequest <EFBFBD>?ConditionalRequest**嚗?<3F>𣳇<EFBFBD>靽格㺿嚗<E3BABF><EFBFBD><EFBFBD>
---
@@ -117,22 +94,19 @@ na_assign_to: int = None
### QuickActionService.ts
**需要更新的接口**
1. **RecodeParams**
```typescript
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>亙藁**嚗?
1. **RecodeParams**嚗?```typescript
interface RecodeParams {
column: string;
mapping: Record<string, any>;
createNewColumn?: boolean;
newColumnName?: string;
naHandling?: 'keep' | 'map' | 'drop'; // ✨ 新增
naValue?: any; // ✨ 新增
naHandling?: 'keep' | 'map' | 'drop'; // <EFBFBD>?<3F><EFBFBD>
naValue?: any; // <EFBFBD>?<3F><EFBFBD>
}
```
2. **BinningParams**
```typescript
2. **BinningParams**嚗?```typescript
interface BinningParams {
column: string;
method: 'custom' | 'equal_width' | 'equal_freq';
@@ -140,106 +114,57 @@ interface BinningParams {
bins?: number[];
labels?: string[];
numBins?: number;
naHandling?: 'keep' | 'label' | 'assign'; // ✨ 新增
naLabel?: string; // ✨ 新增
naAssignTo?: number; // ✨ 新增
naHandling?: 'keep' | 'label' | 'assign'; // <EFBFBD>?<3F><EFBFBD>
naLabel?: string; // <EFBFBD>?<3F><EFBFBD>
naAssignTo?: number; // <EFBFBD>?<3F><EFBFBD>
}
```
**API调用**(自动传递所有参数,无需特殊处理)
**API<EFBFBD>鍂**嚗<><EFBFBD><EFBFBD><E585B6><EFBFBD><E59F9D><EFBFBD><E58CA7><EFBFBD><E5A086>𣳇<EFBFBD><F0A3B387><EFBFBD><EFBFBD><E686AD>嚗?
---
## <20>綫 敺<><E695BA><EFBFBD><EFBFBD><E7909C>滨垢UI
### 1. RecodeDialog.tsx - 数值映射
### 1. RecodeDialog.tsx - <EFBFBD><EFBFBD><EFBFBD>撠?
**UI霈曇恣**嚗?```
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?<3F><EFBFBD><EFBFBD>撠? [X] <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>?<3F>?<3F>㗇𥋘<E39787><EFBFBD>[憍𡁜宏<F0A1819C><EFBFBD><E59785><20>?<3F>? <20>?<3F>?<3F><EFBFBD><E887AD><EFBFBD><EFBFBD><E692A0> <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>? <20>?<3F>?<3F>?<3F><EFBFBD><E7AC94>? <20>?<3F><EFBFBD>? <20>? <20>?<3F>?<3F>?撌脣<E6928C> <20>?[1 ] <20>? <20>?<3F>?<3F>?<3F><EFBFBD> <20>?[0 ] <20>? <20>?<3F>?<3F>?蝛箏<E89D9B>?NA <20>?[<5B><20>?潃鐥<E6BD83>
<EFBFBD>?<3F>? <20><EFBFBD> 靽脲<E99DBD>銝摸A嚗<41><E59A97>霈歹<E99C88> <20>? <20>?<3F>?<3F>? <20><EFBFBD> <20><EFBFBD>銝綽<E98A9D>[____] <20>? <20>?<3F>?<3F>? <20><EFBFBD> <20>𣳇膄霂亥<E99C82> <20>? <20>?<3F>?<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>? <20>?<3F>? <20>?<3F>?<3F><EFBFBD> 敶枏<E695B6><E69E8F>?25銝芰征<E88AB0><EFBFBD>15.6%嚗? <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>?```
**UI设计**
```
┌─────────────────────────────────────┐
│ 数值映射 [X] │
├─────────────────────────────────────┤
│ 选择列:[婚姻状况▼] │
│ │
│ 唯一值映射: │
│ ┌──────────────────────────────┐ │
│ │ 原始值 → 新值 │ │
│ │ 已婚 → [1 ] │ │
│ │ 未婚 → [0 ] │ │
│ │ 空值/NA → [▼] │ ⭐│
│ │ ├─ 保持为NA默认 │ │
│ │ ├─ 映射为:[____] │ │
│ │ └─ 删除该行 │ │
│ └──────────────────────────────┘ │
│ │
当前有125个空值15.6%
└─────────────────────────────────────┘
**摰䂿緵閬<EFBFBD><EFBFBD>**嚗?1. 靚<>鍂`/api/v1/dc/tool-c/sessions/:id/unique-values`<60><EFBFBD><EFBFBD>瘚𧢲糓<F0A7A2B2><EFBFBD>NA
2. 憒<><E68692><EFBFBD>会A嚗峕遬蝷?蝛箏<E89D9B>?NA"<22><EFBFBD>銵?3. <20>𣂷<EFBFBD>3蝘漤<E89D98>㗇𥋘嚗帋<E59A97><E5B88B><EFBFBD>A / <20><EFBFBD>銝箸<E98A9D>摰𡁜<E691B0>?/ <20>𣳇膄銵?
### 2. FilterDialog.tsx - 擃条漣蝑偦<E89D91>?
**UI霈曇恣**嚗?```
<EFBFBD>∩辣嚗?[憍𡁜宏<F0A1819C><EFBFBD><E59785>奭 [餈鞟<E9A488>蝚色䲰]
<20>?蝑劐<E89D91>
<20>?銝滨<E98A9D>鈭? <20>?銝箇征 <20>?<3F>?<3F><EFBFBD>
<20>?銝滢蛹蝛? <20>?<3F>?<3F><EFBFBD>
<20>?...
```
**实现要点**
1. 调用`/api/v1/dc/tool-c/sessions/:id/unique-values`检测是否有NA
2. 如果有NA显示"空值/NA"特殊行
3. 提供3种选择保持NA / 映射为指定值 / 删除行
### 2. FilterDialog.tsx - 高级筛选
**UI设计**
```
条件:
[婚姻状况▼] [运算符▼]
• 等于
• 不等于
• 为空 ← ✨ 新增
• 不为空 ← ✨ 新增
• ...
```
**实现要点**
1. 在运算符下拉菜单中添加"为空"和"不为空"选项
2. 当选择这两个运算符时,隐藏"值"输入框(不需要输入值)
**摰䂿緵閬<EFBFBD><EFBFBD>**嚗?1. <20><EFBFBD>蝞㛖泵銝𧢲<E98A9D><F0A7A2B2>𨅯<EFBFBD>銝剜溶<E5899C>?銝箇征"<22>?銝滢蛹蝛?<3F>厰★
2. 敶㯄<E695B6>㗇𥋘餈嗘舅銝芾<E98A9D>蝞㛖泵<E39B96><EFBFBD><E5A19A><EFBFBD>"<22>?颲枏<E9A2B2><EFBFBD><E78DA2>銝漤<E98A9D><EFBFBD><E996AC><EFBFBD><EFBFBD><EFBFBD>
### 3. BinningDialog.tsx - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
**UI设计**
```
┌─────────────────────────────────────┐
│ 生成分类变量 [X] │
├─────────────────────────────────────┤
│ 原始列:[年龄▼] │
│ ...分组规则... │
│ │
│ ⚠️ 空值处理: │ ⭐
│ ⚪ 保持为空(默认) │
│ ⚪ 标记为:[缺失___] │
│ ⚪ 分配到组:[第1组▼] │
│ │
当前有25个空值3.1%
└─────────────────────────────────────┘
```
**UI霈曇恣**嚗?```
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><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>?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [X] <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>?<3F>?<3F><EFBFBD><E7AC94><EFBFBD>[撟湧<E6929F><E6B9A7><20>?<3F>?...<2E><><EFBFBD><EFBFBD><E996AB>... <20>?<3F>? <20>?<3F>?<3F>𩤃<EFBFBD> 蝛箏<E89D9B><EFBFBD><E6BE86><EFBFBD><EFBFBD> <20>?潃?<3F>?<3F>?靽脲<E99DBD>銝箇征嚗<E5BE81><E59A97>霈歹<E99C88> <20>?<3F>?<3F>?<3F><>扇銝綽<E98A9D>[蝻箏仃___] <20>?<3F>?<3F>?<3F><><EFBFBD><EFBFBD><EFBFBD>嚗靀蝚?蝏<>䲰] <20>?<3F>? <20>?<3F>?<3F><EFBFBD> 敶枏<E695B6><E69E8F>?5銝芰征<E88AB0><EFBFBD>3.1%嚗? <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>?```
**实现要点**
1. 添加Radio Group for NA处理方式
**摰䂿緵閬<EFBFBD><EFBFBD>**嚗?1. 瘛餃<E7989B>Radio Group for NA憭<41><E686AD><EFBFBD><EFBFBD>
2. <20>寞旿<E5AF9E>㗇𥋘<E39787>曄內<E69B84><EFBFBD><E8A9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3. 隡𣳇<E99AA1>嚒naHandling`<EFBFBD><EFBFBD>naLabel`<60><>naAssignTo`<EFBFBD><EFBFBD>
### 4. ConditionalDialog.tsx - 条件生成列
**UI设计**
```
规则1
如果 [婚姻状况▼] [运算符▼]
• 等于
• 不等于
• 为空 ← ✨ 新增
• 不为空 ← ✨ 新增
• ...
则填充:[低风险 ]
### 4. ConditionalDialog.tsx - <EFBFBD>∩辣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
**UI霈曇恣**嚗?```
<EFBFBD><EFBFBD>1嚗?憒<><E68692> [憍𡁜宏<F0A1819C><EFBFBD><E59785>奭 [餈鞟<E9A488>蝚色䲰]
<20>?蝑劐<E89D91>
<20>?銝滨<E98A9D>鈭? <20>?銝箇征 <20>?<3F>?<3F><EFBFBD>
<20>?銝滢蛹蝛? <20>?<3F>?<3F><EFBFBD>
<EFBFBD>?...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>[雿𡡞<E99BBF><F0A1A19E>? ]
```
**实现要点**
1. 与FilterDialog类似在运算符下拉菜单中添加"为空"和"不为空"
2. 这两个运算符不需要输入值
**摰䂿緵閬<EFBFBD><EFBFBD>**嚗?1. 銝榢ilterDialog蝐颱撮嚗<E692AE>銁餈鞟<E9A488>蝚虫<E89D9A><E899AB><EFBFBD><E39591>蓥葉瘛餃<E7989B>"銝箇征"<22>?銝滢蛹蝛?
2. 餈嗘舅銝芾<E98A9D>蝞㛖泵銝漤<E98A9D><EFBFBD><E996AC><EFBFBD><EFBFBD>?
---
## <20>妒 瘚贝<E7989A><E8B49D><EFBFBD>
@@ -247,10 +172,9 @@ interface BinningParams {
### 瘚贝<E7989A><E8B49D>唳旿<E594B3><E697BF><EFBFBD>
```csv
ID,婚姻状况,年龄,收缩压
1,已婚,45,120
ID,憍𡁜宏<F0A1819C><EFBFBD>,撟湧<E6929F>,<2C>嗥憬<E597A5>?1,撌脣<E6928C>,45,120
2,<2C><EFBFBD>,35,130
3,,50, # ← NA
3,,50, # <20>?NA
4,蝳餃<E89DB3>,60,
5,,NA,140
```
@@ -259,81 +183,62 @@ ID,婚姻状况,年龄,收缩压
| 蝻硋噡 | <20><EFBFBD> | 瘚贝<E7989A><E8B49D>箸艶 | 憸<><E686B8>蝏𤘪<E89D8F> |
|------|------|----------|----------|
| TC-1 | 数值映射 - 保持NA | 婚姻状况:已婚=1未婚=0NA=保持 | NA行的新列为NA ✅ |
| TC-2 | 数值映射 - 映射NA | 婚姻状况:已婚=1未婚=0NA=映射为9 | NA行的新列为9 ✅ |
| TC-3 | 数值映射 - 删除NA | 婚姻状况:已婚=1未婚=0NA=删除 | NA行被删除总行数减少 ✅ |
| TC-4 | 高级筛选 - 为空 | 筛选"婚姻状况"为空 | 只保留NA行 ✅ |
| TC-5 | 高级筛选 - 不为空 | 筛选"婚姻状况"不为空 | 只保留非NA行 ✅ |
| TC-6 | 生成分类变量 - 保持NA | 年龄分组NA保持 | NA行的新列为NA ✅ |
| TC-7 | 生成分类变量 - 标记NA | 年龄分组NA标记为"缺失" | NA行的新列为"缺失" ✅ |
| TC-8 | 生成分类变量 - 分配NA | 年龄分组NA分配到第1组 | NA行的新列为第1组标签 ✅ |
| TC-9 | 条件生成列 - 为空 | 如果婚姻状况为空,则"未知" | NA行的新列为"未知" ✅ |
| TC-10 | 条件生成列 - 不为空 | 如果婚姻状况不为空,则"已知" | 非NA行的新列为"已知" ✅ |
| TC-1 | <EFBFBD><EFBFBD><EFBFBD>撠?- 靽脲<E99DBD>NA | 憍𡁜宏<F0A1819C><EFBFBD>嚗𡁜歇憍?1嚗峕𧊋憍?0嚗𨨲A=靽脲<E99DBD> | NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝摸A <20>?|
| TC-2 | <EFBFBD><EFBFBD><EFBFBD>撠?- <20><EFBFBD>NA | 憍𡁜宏<F0A1819C><EFBFBD>嚗𡁜歇憍?1嚗峕𧊋憍?0嚗𨨲A=<3D><EFBFBD>銝? | NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝? <20>?|
| TC-3 | <EFBFBD><EFBFBD><EFBFBD>撠?- <20>𣳇膄NA | 憍𡁜宏<F0A1819C><EFBFBD>嚗𡁜歇憍?1嚗峕𧊋憍?0嚗𨨲A=<3D>𣳇膄 | NA銵諹◤<E8ABB9>𣳇膄嚗峕<E59A97><EFBFBD><E9A489><EFBFBD>撠?<3F>?|
| TC-4 | 擃条漣蝑偦<EFBFBD>?- 銝箇征 | 蝑偦<E89D91>?憍𡁜宏<F0A1819C><EFBFBD>"銝箇征 | <20><EFBFBD><E88AAF>䇏A銵?<3F>?|
| TC-5 | 擃条漣蝑偦<EFBFBD>?- 銝滢蛹蝛?| 蝑偦<E89D91>?憍𡁜宏<F0A1819C><EFBFBD>"銝滢蛹蝛?| <20><EFBFBD><E88AAF><EFBFBD>NA銵?<3F>?|
| TC-6 | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - 靽脲<E99DBD>NA | 撟湧<E6929F><E6B9A7><EFBFBD><EFBFBD>嚗𨨲A靽脲<E99DBD> | NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝摸A <20>?|
| TC-7 | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><>扇NA | 撟湧<E6929F><E6B9A7><EFBFBD><EFBFBD>嚗𨨲A<F0A8A8B2><41>扇銝?蝻箏仃" | NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝?蝻箏仃" <20>?|
| TC-8 | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD>NA | 撟湧<E6929F><E6B9A7><EFBFBD><EFBFBD>嚗𨨲A<F0A8A8B2><41><EFBFBD><EFBFBD>啁洵1蝏?| NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝箇洵1蝏<31><E89D8F>蝑?<3F>?|
| TC-9 | <EFBFBD>∩辣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?- 銝箇征 | 憒<><E68692>憍𡁜宏<F0A1819C><EFBFBD>銝箇征嚗<E5BE81><E59A97>"<22>芰䰻" | NA銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝?<3F>芰䰻" <20>?|
| TC-10 | <EFBFBD>∩辣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?- 銝滢蛹蝛?| 憒<><E68692>憍𡁜宏<F0A1819C><EFBFBD>銝滢蛹蝛綽<E89D9B><E7B6BD>?撌脩䰻" | <20>啩A銵𣬚<E98AB5><F0A3AC9A><EFBFBD>銝?撌脩䰻" <20>?|
---
## 📊 开发进度
| 阶段 | 状态 | 备注 |
## <EFBFBD><EFBFBD><><E69298>𤏸<EFBFBD>摨?
| <20>嗆挾 | <20><EFBFBD>?| 憭<>釣 |
|------|------|------|
| Python后端 - recode.py | 100% | 已完成 |
| Python后端 - filter.py | 100% | 已支持(无需修改) |
| Python后端 - binning.py | 100% | 已完成 |
| Python后端 - conditional.py | 100% | 已完成 |
| Python后端 - main.py | 100% | 已完成 |
| Node.js后端 | 100% | 已完成(参数传递) |
| 前端 - RecodeDialog | 100% | 已完成NA处理下拉菜单 |
| 前端 - FilterDialog | 100% | 已完成已支持is_null/not_null |
| 前端 - BinningDialog | 100% | 已完成NA处理Radio Group |
| 前端 - ConditionalDialog | 100% | 已完成(添加is_null/not_null |
| 测试 | ⏳ 待测试 | 等待用户测试验证 |
| Python<EFBFBD>𡒊垢 - recode.py | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD>?|
| Python<EFBFBD>𡒊垢 - filter.py | <EFBFBD>?100% | 撌脫𣈲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𣳇<EFBFBD>靽格㺿嚗?|
| Python<EFBFBD>𡒊垢 - binning.py | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD>?|
| Python<EFBFBD>𡒊垢 - conditional.py | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD>?|
| Python<EFBFBD>𡒊垢 - main.py | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD>?|
| Node.js<EFBFBD>𡒊垢 | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㺭隡𣳇<EFBFBD>𡜐<EFBFBD> |
| <EFBFBD>滨垢 - RecodeDialog | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD><EFBFBD>NA憭<EFBFBD><EFBFBD>銝𧢲<EFBFBD><EFBFBD>𨅯<EFBFBD>嚗?|
| <EFBFBD>滨垢 - FilterDialog | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD><EFBFBD>撌脫𣈲<EFBFBD><EFBFBD>s_null/not_null嚗?|
| <EFBFBD>滨垢 - BinningDialog | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD><EFBFBD>NA憭<EFBFBD><EFBFBD>Radio Group嚗?|
| <EFBFBD>滨垢 - ConditionalDialog | <EFBFBD>?100% | 撌脣<EFBFBD><EFBFBD><EFBFBD>瘛餃<EFBFBD>is_null/not_null嚗?|
| 瘚贝<EFBFBD> | <20>?敺<><E695BA>霂?| 蝑匧<E89D91><E58CA7><EFBFBD>瘚贝<E7989A>撉諹<E69289> |
---
## 🎯 下一步行动
1. **Node.js后端**预计15分钟
- 更新RecodeParams接口
## <EFBFBD>㴓 銝衤<E98A9D>甇亥<E79487><E4BAA5>?
1. **Node.js<6A>𡒊垢**嚗<><E59A97>霈?5<><35><EFBFBD>嚗? - <20>湔鰵RecodeParams<6D>亙藁
- <20>湔鰵BinningParams<6D>亙藁
- FilterParams和ConditionalParams无需修改)
2. **前端UI**预计2小时
- RecodeDialog添加NA处理下拉菜单45分钟
- FilterDialog添加"为空"/"不为空"运算符15分钟
- BinningDialog添加NA处理Radio Group30分钟
- ConditionalDialog添加"为空"/"不为空"运算符30分钟
3. **测试**预计30分钟
- 执行10个测试用例
- 修复发现的问题
- 嚗㇅ilterParams<EFBFBD>onditionalParams<EFBFBD>𣳇<EFBFBD>靽格㺿嚗?
2. **<2A>滨垢UI**嚗<><E59A97>霈?撠𤩺𧒄嚗? - RecodeDialog嚗𡁏溶<F0A1818F>賫A憭<41><E686AD>銝𧢲<E98A9D><F0A7A2B2>𨅯<EFBFBD>嚗?5<><35><EFBFBD>嚗? - FilterDialog嚗𡁏溶<F0A1818F>?銝箇征"/"銝滢蛹蝛?餈鞟<E9A488>蝚佗<E89D9A>15<31><35><EFBFBD>嚗? - BinningDialog嚗𡁏溶<F0A1818F>賫A憭<41><E686AD>Radio Group嚗?0<><30><EFBFBD>嚗? - ConditionalDialog嚗𡁏溶<F0A1818F>?銝箇征"/"銝滢蛹蝛?餈鞟<E9A488>蝚佗<E89D9A>30<33><30><EFBFBD>嚗?
3. **瘚贝<E7989A>**嚗<><E59A97>霈?0<><30><EFBFBD>嚗? - <20><EFBFBD>10銝芣<E98A9D>霂閧鍂靘? - 靽桀<E99DBD><E6A180>𤑳緵<F0A491B3><E7B7B5>䔮憸?
**<2A>餉恣<E9A489><EFBFBD><E68B90>園𡢿嚗𡁶漲3撠𤩺𧒄**
---
## 📝 技术要点
### Python端
- 使用`df[column].isna()`检测NA
## <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><E888AA>?
### Python蝡?- 雿輻鍂`df[column].isna()`璉<>瘚𨶙A
- 雿輻鍂`df.loc[mask, col] = value`憛怠<E6869B>NA
- 使用`df[~mask]`删除NA行
- 统计并打印NA处理信息
### 前端端
- 在获取unique values时检测NA
- 使用`<空值/NA>`作为显示名称
- 根据用户选择构造请求参数
- 显示NA统计信息如"当前有125个空值"
- 雿輻鍂`df[~mask]`<60>𣳇膄NA銵?- 蝏蠘恣撟嗆<E6929F><E59786>衹A憭<41><E686AD>靽⊥<E99DBD>
### <20>滨垢蝡?- <20>刻繮<E588BB>䮐nique values<65><EFBFBD>瘚𨶙A
- 雿輻鍂`<蝛箏<E89D9B>?NA>`雿靝蛹<E99D9D>曄內<E69B84>滨妍
- <20>寞旿<E5AF9E><EFBFBD><E586BD>㗇𥋘<E39787><F0A58B98><EFBFBD>㰘窈瘙<E7AA88><E79899><EFBFBD>?- <20>曄內NA蝏蠘恣靽⊥<E99DBD><EFBFBD><E59A97>"敶枏<E695B6><E69E8F>?25銝芰征<E88AB0>?嚗?
### 撉峕𤣰<E5B395><F0A4A3B0><EFBFBD>
- ✅ 用户能明确看到NA的存在
- ✅ 用户能选择如何处理NA
- ✅ 处理后的结果符合用户选择
- ✅ 所有功能的NA处理方式清晰统一
- <EFBFBD>?<3F><EFBFBD><E586BD><EFBFBD>蝖桃<E89D96><E6A183>衹A<E8A1B9><41><EFBFBD><EFBFBD>?- <20>?<3F><EFBFBD><E586BD><EFBFBD>㗇𥋘憒<F0A58B98><E68692><EFBFBD><E686AD>NA
- <EFBFBD>?憭<><E686AD><EFBFBD>𡒊<EFBFBD>蝏𤘪<E89D8F>蝚血<E89D9A><E8A180><EFBFBD><E586BD>㗇𥋘
- <EFBFBD>?<3F><><EFBFBD><EFBFBD><E58CA7><EFBFBD>NA憭<41><E686AD><EFBFBD><EFBFBD><EFBFBD>苊蝏煺<E89D8F>
---
**文档创建时间**2025-12-09
**Python后端开发状态**:✅ 已完成
**<EFBFBD><EFBFBD><EFBFBD>𥕦遣<EFBFBD>園𡢿**嚗?025-12-09
**Python<EFBFBD>𡒊垢撘<EFBFBD><EFBFBD>𤑳𠶖<EFBFBD>?*嚗尠<E59A97> 撌脣<E6928C><E884A3>?
**<EFBFBD><EFBFBD>撌乩<EFBFBD>**嚗鐭ode.js<6A>𡒊垢 + <20>滨垢UI + 瘚贝<E7989A>