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%)
240 lines
5.6 KiB
Markdown
240 lines
5.6 KiB
Markdown
# 工具C - Pivot列顺åº<C3A5>优化总结
|
||
|
||
## 📋 问题æ<CB9C><C3A6>è¿°
|
||
|
||
**用户需æ±?*:长宽转æ<C2AC>¢å<C2A2>Žï¼Œåˆ—的排åº<C3A5>åº”è¯¥ä¸Žä¸Šä¼ æ–‡ä»¶æ—¶çš„åˆ—é¡ºåº<C3A5>ä¿<C3A4>æŒ<C3A6>一致ã€?
|
||
|
||
**当å‰<C3A5>问题**ï¼šç³»ç»ŸæŒ‰å—æ¯<C3A6>顺åº<C3A5>排列转æ<C2AC>¢å<C2A2>Žçš„列,导致顺åº<C3A5>与原文件ä¸<C3A4>一致ã€?
|
||
|
||
---
|
||
|
||
## 🎯 解决方案:方案A - Python端排�
|
||
|
||
### æ ¸å¿ƒæ€<C3A6>è·¯
|
||
1. Node.jså<73>Žç«¯ä»Žsession获å<C2B7>–**原始列顺åº?*
|
||
2. Node.jså<73>Žç«¯ä»Žæ•°æ<C2B0>®ä¸æ<C2AD><C3A6>å<EFBFBD>–**é€<C3A9>视列值的原始顺åº<C3A5>**(按首次出现顺åº<C3A5>ï¼?
|
||
3. ä¼ é€’ç»™Python
|
||
4. Python在pivotå<74>Žï¼ŒæŒ‰åŽŸå§‹é¡ºåº<C3A5>é‡<C3A9>排列
|
||
|
||
---
|
||
|
||
## 🛠�实现细节
|
||
|
||
### 1. Python端(pivot.py�
|
||
|
||
**新增å<C5BE>‚æ•°**ï¼?
|
||
- `original_column_order: List[str]`:原始列顺åº<EFBFBD>(如`['Record ID', 'Event Name', 'FMA', '体é‡<C3A9>', '收缩åŽ?, ...]`ï¼?
|
||
- `pivot_value_order: List[str]`:é€<EFBFBD>视列值的原始顺åº<EFBFBD>(如`['基线', '1个月', '2个月', ...]`ï¼?
|
||
|
||
**排åº<C3A5>逻辑**ï¼?
|
||
```python
|
||
if original_column_order:
|
||
# 1. 索引列始终在最å‰<C3A5>é<EFBFBD>¢
|
||
final_cols = [index_column]
|
||
|
||
# 2. 按原始列顺åº<C3A5>æ·»åŠ è½¬æ<C2AC>¢å<C2A2>Žçš„åˆ?
|
||
for orig_col in original_column_order:
|
||
if orig_col in value_columns:
|
||
# 找出所有属于这个原列的新列
|
||
related_cols = [c for c in df_pivot.columns if c.startswith(f'{orig_col}___')]
|
||
|
||
# âœ?按é€<C3A9>视列的原始顺åº<C3A5>排åº<C3A5>
|
||
if pivot_value_order:
|
||
pivot_order_map = {val: idx for idx, val in enumerate(pivot_value_order)}
|
||
related_cols_sorted = sorted(
|
||
related_cols,
|
||
key=lambda c: pivot_order_map.get(c.split('___')[1], 999)
|
||
)
|
||
else:
|
||
related_cols_sorted = sorted(related_cols)
|
||
|
||
final_cols.extend(related_cols_sorted)
|
||
|
||
# 3. æ·»åŠ æœªé€‰æ‹©çš„åˆ—ï¼ˆä¿<C3A4>æŒ<C3A6>原始顺åº<C3A5>)
|
||
if keep_unused_columns:
|
||
for orig_col in original_column_order:
|
||
if orig_col in df_pivot.columns and orig_col not in final_cols:
|
||
final_cols.append(orig_col)
|
||
|
||
# 4. é‡<C3A9>排åˆ?
|
||
df_pivot = df_pivot[final_cols]
|
||
```
|
||
|
||
### 2. Python端(main.py�
|
||
|
||
**PivotRequest模型**�
|
||
```python
|
||
class PivotRequest(BaseModel):
|
||
# ... åŽŸæœ‰å—æ®µ ...
|
||
original_column_order: List[str] = [] # �新增
|
||
pivot_value_order: List[str] = [] # �新增
|
||
```
|
||
|
||
**调用pivot_long_to_wide**�
|
||
```python
|
||
result_df = pivot_long_to_wide(
|
||
df,
|
||
request.index_column,
|
||
request.pivot_column,
|
||
request.value_columns,
|
||
request.aggfunc,
|
||
request.column_mapping,
|
||
request.keep_unused_columns,
|
||
request.unused_agg_method,
|
||
request.original_column_order, # �新增
|
||
request.pivot_value_order # �新增
|
||
)
|
||
```
|
||
|
||
### 3. Node.jså<73>Žç«¯ï¼ˆQuickActionController.tsï¼?
|
||
|
||
**获å<C2B7>–原始列顺åº?*ï¼?
|
||
```typescript
|
||
const originalColumnOrder = session.columns || [];
|
||
```
|
||
|
||
**获å<C2B7>–é€<C3A9>视列值的原始顺åº<C3A5>**ï¼?
|
||
```typescript
|
||
const pivotColumn = params.pivotColumn;
|
||
const seenPivotValues = new Set();
|
||
const pivotValueOrder: string[] = [];
|
||
|
||
for (const row of fullData) {
|
||
const pivotValue = row[pivotColumn];
|
||
if (pivotValue !== null && pivotValue !== undefined && !seenPivotValues.has(pivotValue)) {
|
||
seenPivotValues.add(pivotValue);
|
||
pivotValueOrder.push(String(pivotValue));
|
||
}
|
||
}
|
||
```
|
||
|
||
**ä¼ é€’ç»™QuickActionService**ï¼?
|
||
```typescript
|
||
executeResult = await quickActionService.executePivot(
|
||
fullData,
|
||
params,
|
||
session.columnMapping,
|
||
originalColumnOrder, // �新增
|
||
pivotValueOrder // �新增
|
||
);
|
||
```
|
||
|
||
### 4. Node.jså<73>Žç«¯ï¼ˆQuickActionService.tsï¼?
|
||
|
||
**方法ç¾å<C2BE><C3A5>**ï¼?
|
||
```typescript
|
||
async executePivot(
|
||
data: any[],
|
||
params: PivotParams,
|
||
columnMapping?: any[],
|
||
originalColumnOrder?: string[], // �新增
|
||
pivotValueOrder?: string[] // �新增
|
||
): Promise<OperationResult>
|
||
```
|
||
|
||
**ä¼ é€’ç»™Python**ï¼?
|
||
```typescript
|
||
const response = await axios.post(`${PYTHON_SERVICE_URL}/api/operations/pivot`, {
|
||
// ... 原有å<E280B0>‚æ•° ...
|
||
original_column_order: originalColumnOrder || [], // �新增
|
||
pivot_value_order: pivotValueOrder || [], // �新增
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 效果对比
|
||
|
||
### 修改å‰<C3A5>ï¼ˆæŒ‰å—æ¯<C3A6>顺åº<C3A5>)
|
||
```
|
||
Record ID | FMA___基线 | FMA___1个月 | 收缩压___基线 | 收缩压___1个月 | 体é‡<C3A9>___基线 | 体é‡<C3A9>___1个月
|
||
� � � � � � �
|
||
索引� F开� F开� S开�拼音) S开� T开� T开�
|
||
```
|
||
|
||
### 修改å<C2B9>Žï¼ˆæŒ‰åŽŸå§‹é¡ºåº<C3A5>)
|
||
```
|
||
Record ID | FMA___基线 | FMA___1个月 | 体é‡<C3A9>___基线 | 体é‡<C3A9>___1个月 | 收缩压___基线 | 收缩压___1个月
|
||
� � � � � � �
|
||
索引� 原文件第3� 原文件第3� 原文件第4� 原文件第4� 原文件第5� 原文件第5�
|
||
```
|
||
|
||
### é€<C3A9>视值内部顺åº<C3A5>(按原始出现顺åº<C3A5>)
|
||
```
|
||
FMA___基线 | FMA___1个月 | FMA___2个月
|
||
� � �
|
||
首次出现 第二次出� 第三次出�
|
||
(而ä¸<EFBFBD>是按"1个月"ã€?2个月"ã€?基线"çš„å—æ¯<C3A6>顺åº<C3A5>)
|
||
```
|
||
|
||
---
|
||
|
||
## âœ?å¼€å<E282AC>‘完æˆ?
|
||
|
||
### 修改文件清å<E280A6>•
|
||
1. �`extraction_service/operations/pivot.py`
|
||
2. �`extraction_service/main.py`
|
||
3. �`backend/src/modules/dc/tool-c/controllers/QuickActionController.ts`
|
||
4. �`backend/src/modules/dc/tool-c/services/QuickActionService.ts`
|
||
|
||
### 优势
|
||
- âœ?列顺åº<C3A5>与原文件一致(用户熟悉ï¼?
|
||
- âœ?é€<C3A9>视值顺åº<C3A5>按时间顺åº<C3A5>(基线→1个月â†?个月ï¼?
|
||
- âœ?未选择的列也ä¿<C3A4>æŒ<C3A6>原始顺åº?
|
||
- âœ?导出Excel时顺åº<C3A5>æ£ç¡?
|
||
|
||
---
|
||
|
||
**å¼€å<E282AC>‘æ—¶é—?*ï¼?025-12-09
|
||
**状æ€?*:✅ 已完æˆ<C3A6>,ç‰å¾…测试
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|