import React, { useState } from 'react'; import { Table2, Calculator, CalendarClock, Split, Filter, Download, ArrowRight, Trash2, AlertCircle, BarChart3, Hash, Type, Calendar, ChevronDown, Undo2, Redo2, Save, Wand2, Settings, FileUp, Search, ArrowLeftRight // 新增图标 } from 'lucide-react'; // --- 模拟数据 --- const MOCK_DATA = [ { id: 'P001', age: 45, gender: 'Male', bmi: 24.5, admission_date: '2023-01-12', lab_val: '4.5' }, { id: 'P002', age: 62, gender: 'Female', bmi: 28.1, admission_date: '2023-01-15', lab_val: '5.1' }, { id: 'P003', age: 205, gender: 'Male', bmi: null, admission_date: '2023-02-01', lab_val: '<0.1' }, { id: 'P004', age: 58, gender: 'F', bmi: 22.4, admission_date: '2023-02-10', lab_val: '4.8' }, { id: 'P005', age: 34, gender: 'Male', bmi: 21.0, admission_date: '2023-03-05', lab_val: '5.2' }, { id: 'P006', age: 71, gender: 'Female', bmi: 30.5, admission_date: '2023-03-12', lab_val: '6.0' }, { id: 'P007', age: null, gender: 'Male', bmi: 25.3, admission_date: '2023-04-01', lab_val: '4.9' }, { id: 'P008', age: 49, gender: 'Male', bmi: 26.8, admission_date: '2023-04-05', lab_val: '5.5' }, { id: 'P009', age: 55, gender: 'Female', bmi: 23.9, admission_date: '2023-04-10', lab_val: '4.2' }, { id: 'P010', age: 66, gender: 'Male', bmi: 29.1, admission_date: '2023-04-12', lab_val: '5.8' }, ]; const COLUMNS = [ { id: 'id', name: '病人ID', type: 'text', locked: true }, { id: 'age', name: '年龄', type: 'number' }, { id: 'gender', name: '性别', type: 'category' }, { id: 'bmi', name: 'BMI指数', type: 'number' }, { id: 'admission_date', name: '入院日期', type: 'date' }, { id: 'lab_val', name: '肌酐', type: 'text' }, ]; const ToolC_EditorV2 = () => { const [selectedColId, setSelectedColId] = useState(null); const [showSidebar, setShowSidebar] = useState(false); const [showModal, setShowModal] = useState<'calc' | 'recode' | 'pivot' | null>(null); // 新增 pivot 状态 const selectedCol = COLUMNS.find(c => c.id === selectedColId); const handleColClick = (colId: string) => { if (selectedColId === colId) { setShowSidebar(!showSidebar); } else { setSelectedColId(colId); setShowSidebar(true); } }; // --- 组件:顶部工具按钮 --- const ToolbarButton = ({ icon: Icon, label, desc, colorClass = "text-slate-600 bg-slate-50 hover:bg-slate-100", onClick }: { icon: any, label: string, desc: string, colorClass?: string, onClick?: () => void }) => ( ); return (
{/* 1. Header (基础操作) */}
科研数据编辑器
肺癌数据集_2023.csv (未保存)
{/* 2. Top Toolbar (扁平化核心功能) */}
setShowModal('calc')} /> {/* 新增:长宽转换按钮 */} setShowModal('pivot')} />
{/* Spacer */}
{/* 3. Main Grid Area */}
{/* Grid */}
{COLUMNS.map((col) => (
handleColClick(col.id)} >
{col.type === 'number' && } {col.type === 'text' && } {col.type === 'category' && } {col.type === 'date' && } {col.name}
))}
{MOCK_DATA.map((row, idx) => (
{COLUMNS.map((col) => { const val = row[col.id as keyof typeof row]; const isNull = val === null || val === ''; const isOutlier = col.id === 'age' && (val as number) > 120; const isDirty = col.id === 'lab_val' && typeof val === 'string' && val.includes('<'); return (
{isNull ? NULL : val}
); })}
))}
{/* 4. Smart Sidebar (基于列类型的操作聚合) */} {showSidebar && selectedCol && (
{/* Header */}
当前选中列

{selectedCol.name} {selectedCol.id}

{/* A. 数值列操作 */} {selectedCol.type === 'number' && ( <>

分布直方图

{/* 图表 */}
{[10, 25, 45, 80, 50, 30, 15, 5, 2, 1].map((h, i) => (
))}
Min: 34 Max: 205
{/* 异常值卡片 */}
发现异常值
205 显著偏离分布。

针对此列的操作

)} {/* B. 分类/文本列操作 */} {(selectedCol.type === 'category' || selectedCol.type === 'text') && ( <>

频次统计

{['Male (50%)', 'Female (40%)', 'F (10%)'].map((label, i) => (
{label.split(' ')[0]} {label.split(' ')[1]}
))}

针对此列的操作

)}
)}
{/* Modals (Mock) */} {showModal === 'calc' && (

生成新变量 (Formula)

[体重] / ([身高] / 100) ^ 2
)} {/* Recode Modal */} {showModal === 'recode' && (

数值映射 (Recode)

将源值映射为新的统计数值:
Male
Female
F
)} {/* 新增:Pivot Modal (长宽转换) */} {showModal === 'pivot' && (

长宽表转换 (Pivot)

将"一人多行"转换为"一人一行",适用于重复测量分析。

{/* 列 1: 主键 */}

转换后,每个ID只保留一行。

{/* 列 2: 区分列 */}

生成列名如: 白细胞_20230101

{/* 列 3: 值列 */}
{/* 预览图示 */}
转换预览:
ID | 时间 | 值
P1 | T1 | A
P1 | T2 | B
ID | 值_T1 | 值_T2
P1 | A | B
)}
); }; export default ToolC_EditorV2;