import React, { useState } from 'react'; import { Modal, Input, Button, Alert, Collapse, Tag, App } from 'antd'; import { Calculator, Lightbulb, BookOpen } from 'lucide-react'; interface Props { visible: boolean; onClose: () => void; onApply: (newData: any[]) => void; columns: Array<{ id: string; name: string }>; sessionId: string | null; } const ComputeDialog: React.FC = ({ visible, onClose, onApply, columns, sessionId, }) => { const { message } = App.useApp(); const [newColumnName, setNewColumnName] = useState('新列'); const [formula, setFormula] = useState(''); const [loading, setLoading] = useState(false); // 公式示例 const examples = [ { name: 'BMI计算', formula: '体重 / (身高/100)**2', description: '需要身高(cm)和体重(kg)列', }, { name: '年龄分组', formula: 'round(年龄 / 10) * 10', description: '按10岁为一组', }, { name: '综合得分', formula: '(FMA得分 * 0.6 + ADL得分 * 0.4)', description: '加权平均分', }, { name: '变化率(%)', formula: '(随访值 - 基线值) / 基线值 * 100', description: '计算变化百分比', }, { name: '对数转换', formula: 'log(值 + 1)', description: '对数变换(处理偏态分布)', }, ]; // 支持的函数 const functions = [ { name: 'abs(x)', desc: '绝对值' }, { name: 'round(x)', desc: '四舍五入' }, { name: 'sqrt(x)', desc: '平方根' }, { name: 'log(x)', desc: '自然对数' }, { name: 'log10(x)', desc: '常用对数' }, { name: 'exp(x)', desc: '指数函数' }, { name: 'floor(x)', desc: '向下取整' }, { name: 'ceil(x)', desc: '向上取整' }, { name: 'min(a,b)', desc: '最小值' }, { name: 'max(a,b)', desc: '最大值' }, ]; // 使用示例公式 const useExample = (exampleFormula: string) => { setFormula(exampleFormula); }; // 执行 const handleApply = async () => { if (!sessionId) { message.error('Session ID不存在'); return; } if (!newColumnName.trim()) { message.warning('请输入新列名'); return; } if (!formula.trim()) { message.warning('请输入计算公式'); return; } setLoading(true); try { const response = await fetch('/api/v1/dc/tool-c/quick-action', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId, action: 'compute', params: { newColumnName: newColumnName.trim(), formula: formula.trim(), }, }), }); const result = await response.json(); if (!result.success) { throw new Error(result.error || '计算列失败'); } message.success('计算列成功!'); // 更新父组件数据 if (result.data?.newDataPreview) { onApply(result.data.newDataPreview); } // 成功后关闭 onClose(); } catch (error: any) { message.error(error.message || '执行失败'); } finally { setLoading(false); } }; return ( 计算列 } open={visible} onCancel={onClose} width={800} footer={[ , , ]} >
{/* 说明 */}
• 基于现有列计算新列
• 支持四则运算(+, -, *, /)和幂运算(**)
• 支持常用数学函数(abs, round, sqrt, log等)
• 列名直接引用,如:体重, 身高, 年龄
} type="info" showIcon className="mb-4" /> {/* 新列名 */}
setNewColumnName(e.target.value)} size="large" />
{/* 计算公式 */}
setFormula(e.target.value)} rows={3} size="large" className="font-mono" />
直接使用列名,支持 +、-、*、/、**(幂)、()(括号)
{/* 可用列名 */}
可用列名(点击复制):
{columns.map((col) => ( { setFormula(formula + (formula ? ' ' : '') + col.name); }} > {col.name} ))}
{/* 公式示例 */} 公式示例(点击使用) ), children: (
{examples.map((example, index) => (
useExample(example.formula)} >
{example.name}
{example.description}
{example.formula}
))}
), }, { key: 'functions', label: (
支持的函数
), children: (
{functions.map((func, index) => (
{func.name} {func.desc}
))}
), }, ]} defaultActiveKey={['examples']} className="bg-white" /> {/* 温馨提示 */} 提示
• 列名区分大小写,需与数据表中完全一致
• 除零会产生无穷大或NaN值
• log、sqrt等函数对负数/零会产生NaN
• 建议先用简单公式测试,再使用复杂公式
} type="warning" showIcon={false} className="bg-yellow-50 border-yellow-200" />
); }; export default ComputeDialog;