# 工具C - Bug修复与优化总结 **修复日期**: 2025-12-08 **修复人**: AI Assistant **修复范围**: 7个严重问题 + 5个体验优化 --- ## 📋 修复清单 ### ✅ 问题1:表头特殊字符导致功能异常 #### 1-1. Pivot转换只有1列 🔴 **已修复** **问题描述**: - 表头包含括号、等号等特殊字符(如`体重(kg)`、`1.高血压病(无=0,有=1)`) - 导致Pivot转换时列名处理失败,只生成1列而不是按透视列展开 **根本原因**: - Python的`pivot_table`列名展平逻辑无法处理特殊字符 **解决方案**: ```python # 文件: extraction_service/operations/pivot.py (73-95行) # 增强列名展平逻辑,清理特殊字符 if len(value_columns) == 1: value_col_clean = str(value_columns[0]).replace('(', '').replace(')', '').strip() df_pivot.columns = [f'{value_col_clean}___{str(col).replace(" ", "_")}' for col in df_pivot.columns] ``` #### 1-2. 计算列功能报错 🔴 **已修复** **问题描述**: - 点击"执行计算"报错:"公式包含不允许的字符" - 无法使用包含中文括号、等号、冒号的列名 **根本原因**: - `compute.py`的正则验证过于严格,只允许英文括号 **解决方案**: ```python # 文件: extraction_service/operations/compute.py (63-67行) # 1. 放宽字符验证,支持中文括号、等号、冒号 allowed_chars = r'[a-zA-Z0-9_\u4e00-\u9fa5\s\+\-\*/\(\)\[\]\{\}\.,:\*\*=()【】、。:;!?]' # 2. 使用列名映射,将特殊字符列名替换为安全变量名 for i, col in enumerate(result.columns): safe_var = f'col_{i}' formula_safe = re.sub(rf'\b{re.escape(col)}\b', safe_var, formula_safe) env[safe_var] = result[col] ``` --- ### ✅ 问题2:数值映射只提取1个唯一值 🔴 **已修复** #### 2-1. 婚姻状况只显示1个值(实际有4种)🔴 **已修复** **问题描述**: - 选择"婚姻状况"列时,只提取到1个唯一值 - 实际数据有4种:已婚、未婚、其他、(空白) **根本原因**: - 前端从`data`数组提取唯一值,但`data`只有前50行 - 完整数据有3668行,婚姻状况的分布不均 **解决方案**: ```typescript // 文件: frontend-v2/src/modules/dc/pages/tool-c/components/RecodeDialog.tsx (45-72行) // 调用后端API从完整数据中提取唯一值 const response = await fetch( `/api/v1/dc/tool-c/sessions/${sessionId}/unique-values?column=${encodeURIComponent(selectedColumn)}` ); ``` ```typescript // 新增API: backend/src/modules/dc/tool-c/controllers/SessionController.ts (366-428行) // GET /api/v1/dc/tool-c/sessions/:id/unique-values?column=xxx async getUniqueValues(...) { const data = await sessionService.getFullData(id); const cleanedValues = values.map((val) => typeof val === 'string' ? val.trim() : val ); return Array.from(new Set(cleanedValues)).filter(v => v !== null).sort(); } ``` #### 2-2. 研究中心:只显示1个值(实际有4种)🔴 **已修复** 同上,使用相同解决方案。 --- ### ✅ 体验优化(5项) #### ✅ 优化1:表格线框颜色加深 ⚪ **已完成** **需求**: 线框太淡,看不清楚 **修改**: ```css /* 文件: frontend-v2/src/modules/dc/pages/tool-c/components/ag-grid-custom.css (24-26行) */ --ag-border-color: #d1d5db; /* 原#e5e7eb -> #d1d5db */ --ag-row-border-color: #e5e7eb; /* 原#f1f5f9 -> #e5e7eb */ border-bottom: 2px solid #d1d5db; /* 表头底部边框加深 */ ``` #### ✅ 优化2:表头宽度减小40% + Tooltip ⚪ **已完成** **需求**: 列宽太大,同一屏无法显示太多列 **修改**: ```typescript // 文件: frontend-v2/src/modules/dc/pages/tool-c/components/DataGrid.tsx (32-53行) { headerName: col.name, headerTooltip: col.name, // ✅ 鼠标悬停显示完整列名 width: 90, // ✅ 原150 -> 90(减少40%) minWidth: 60, // ✅ 原100 -> 60 } ``` #### ✅ 优化3:新列显示在原列旁边 ⚪ **已完成** **需求**: 生成新列时,希望紧邻原列,方便对比 **修改**: - `binning.py` (139-148行): 分组列插入到原列旁边 - `recode.py` (56-63行): 编码列插入到原列旁边 - `compute.py` (149-161行): 计算列插入到第一个引用列旁边 - `conditional.py` (131-139行): 条件列插入到参考列旁边 ```python # 示例: binning.py original_col_index = result.columns.get_loc(column) cols = list(result.columns) cols.remove(new_column_name) cols.insert(original_col_index + 1, new_column_name) result = result[cols] ``` #### ✅ 优化4:保持原始行顺序 ⚪ **已完成** **需求**: 数据处理后,行顺序要保持与原Excel一致 **修改**: ```python # 文件: extraction_service/operations/pivot.py (90-97行) # Pivot后按原始顺序排序 original_order = result[index_column].drop_duplicates().tolist() order_map = {val: idx for idx, val in enumerate(original_order)} df_pivot['_sort_order'] = df_pivot[index_column].map(order_map) df_pivot = df_pivot.sort_values('_sort_order').drop(columns=['_sort_order']) ``` #### ✅ 优化5:提示只显示前50行 ⚪ **已完成** **需求**: 用户担心数据处理时数据丢失 **修改**: ```typescript // 文件: frontend-v2/src/modules/dc/pages/tool-c/index.tsx (256-264行)