fix(dc/tool-c): Fix special character handling and improve UX

Major fixes:
- Fix pivot transformation with special characters in column names
- Fix compute column validation for Chinese punctuation
- Fix recode dialog to fetch unique values from full dataset via new API
- Add column mapping mechanism to handle special characters

Database migration:
- Add column_mapping field to dc_tool_c_sessions table
- Migration file: 20251208_add_column_mapping

UX improvements:
- Darken table grid lines for better visibility
- Reduce column width by 40% with tooltip support
- Insert new columns next to source columns
- Preserve original row order after operations
- Add notice about 50-row preview limit

Modified files:
- Backend: SessionService, SessionController, QuickActionService, routes
- Python: pivot.py, compute.py, recode.py, binning.py, conditional.py
- Frontend: DataGrid, RecodeDialog, index.tsx, ag-grid-custom.css
- Database: schema.prisma, migration SQL

Status: Code complete, database migrated, ready for testing
This commit is contained in:
2025-12-08 23:20:55 +08:00
parent f729699510
commit 91cab452d1
90 changed files with 735 additions and 45 deletions

View File

@@ -41,35 +41,55 @@ const RecodeDialog: React.FC<RecodeDialogProps> = ({
const [loading, setLoading] = useState(false);
const [extracting, setExtracting] = useState(false);
// 当选择列时,取唯一值
// 当选择列时,从后端获取唯一值
useEffect(() => {
if (!selectedColumn || !data || data.length === 0) {
if (!selectedColumn || !sessionId) {
setUniqueValues([]);
setMappingTable([]);
return;
}
setExtracting(true);
const fetchUniqueValues = async () => {
setExtracting(true);
try {
// ✨ 调用后端API获取唯一值从完整数据中提取不受前端50行限制
const response = await fetch(
`/api/v1/dc/tool-c/sessions/${sessionId}/unique-values?column=${encodeURIComponent(selectedColumn)}`
);
const result = await response.json();
if (!result.success) {
throw new Error(result.error || '获取唯一值失败');
}
const unique = result.data.uniqueValues;
setUniqueValues(unique);
// 初始化映射表
const initialMapping = unique.map((val: any) => ({
originalValue: val,
newValue: '',
}));
setMappingTable(initialMapping);
// 生成默认新列名
setNewColumnName(`${selectedColumn}_编码`);
} catch (error: any) {
console.error('[RecodeDialog] 获取唯一值失败:', error);
message.error(error.message || '获取唯一值失败');
setUniqueValues([]);
setMappingTable([]);
} finally {
setExtracting(false);
}
};
// 提取唯一值
const values = data.map((row) => row[selectedColumn]);
const unique = Array.from(new Set(values)).filter(v => v !== null && v !== undefined && v !== '');
setUniqueValues(unique);
// 初始化映射表
const initialMapping = unique.map((val) => ({
originalValue: val,
newValue: '',
}));
setMappingTable(initialMapping);
// 生成默认新列名
setNewColumnName(`${selectedColumn}_编码`);
setExtracting(false);
}, [selectedColumn, data]);
fetchUniqueValues();
}, [selectedColumn, sessionId, message]);
// 更新映射值
const updateMapping = (originalValue: any, newValue: string) => {