150 lines
4.9 KiB
TypeScript
150 lines
4.9 KiB
TypeScript
import React, { useEffect } from 'react';
|
||
import { Modal, Form, Input, InputNumber, Radio, message } from 'antd';
|
||
import type { FlowEdge } from '../types';
|
||
|
||
interface EdgeConfigModalProps {
|
||
visible: boolean;
|
||
edge: FlowEdge | null;
|
||
onOk: (edgeId: string, condition: EdgeCondition) => void;
|
||
onCancel: () => void;
|
||
}
|
||
|
||
export interface EdgeCondition {
|
||
type: 'EXPRESSION' | 'DEFAULT';
|
||
expression?: string;
|
||
priority: number;
|
||
}
|
||
|
||
/**
|
||
* 边条件配置弹窗
|
||
* 复刻 Workflow/Design/ExpressionModal 功能
|
||
*/
|
||
const EdgeConfigModal: React.FC<EdgeConfigModalProps> = ({
|
||
visible,
|
||
edge,
|
||
onOk,
|
||
onCancel
|
||
}) => {
|
||
const [form] = Form.useForm();
|
||
|
||
// 当edge变化时,更新表单初始值
|
||
useEffect(() => {
|
||
if (visible && edge) {
|
||
const condition = edge.data?.condition;
|
||
form.setFieldsValue({
|
||
type: condition?.type || 'EXPRESSION',
|
||
expression: condition?.expression || '',
|
||
priority: condition?.priority || 10
|
||
});
|
||
}
|
||
}, [visible, edge, form]);
|
||
|
||
const handleOk = async () => {
|
||
if (!edge) return;
|
||
|
||
try {
|
||
const values = await form.validateFields();
|
||
|
||
// 验证表达式
|
||
if (values.type === 'EXPRESSION') {
|
||
if (!values.expression || values.expression.trim() === '') {
|
||
message.error('请输入条件表达式');
|
||
return;
|
||
}
|
||
|
||
// 检查是否包含变量引用 ${...}
|
||
const hasVariable = /\$\{[\w.]+\}/.test(values.expression);
|
||
if (!hasVariable) {
|
||
message.warning('表达式建议包含变量引用,格式:${变量名}');
|
||
}
|
||
}
|
||
|
||
onOk(edge.id, values);
|
||
} catch (error) {
|
||
console.error('表单验证失败:', error);
|
||
}
|
||
};
|
||
|
||
const handleCancel = () => {
|
||
form.resetFields();
|
||
onCancel();
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
title="配置边条件"
|
||
open={visible}
|
||
onOk={handleOk}
|
||
onCancel={handleCancel}
|
||
width={600}
|
||
okText="确定"
|
||
cancelText="取消"
|
||
>
|
||
<Form
|
||
form={form}
|
||
layout="vertical"
|
||
initialValues={{
|
||
type: 'EXPRESSION',
|
||
expression: '',
|
||
priority: 10
|
||
}}
|
||
>
|
||
<Form.Item
|
||
name="type"
|
||
label="条件类型"
|
||
rules={[{ required: true, message: '请选择条件类型' }]}
|
||
>
|
||
<Radio.Group>
|
||
<Radio value="EXPRESSION">表达式</Radio>
|
||
<Radio value="DEFAULT">默认路径</Radio>
|
||
</Radio.Group>
|
||
</Form.Item>
|
||
|
||
<Form.Item
|
||
noStyle
|
||
shouldUpdate={(prevValues, currentValues) => prevValues.type !== currentValues.type}
|
||
>
|
||
{({ getFieldValue }) => {
|
||
const type = getFieldValue('type');
|
||
return type === 'EXPRESSION' ? (
|
||
<Form.Item
|
||
name="expression"
|
||
label="条件表达式"
|
||
rules={[{ required: true, message: '请输入条件表达式' }]}
|
||
extra="支持使用 ${变量名} 引用流程变量,例如:${amount} > 1000"
|
||
>
|
||
<Input.TextArea
|
||
placeholder="请输入条件表达式,如:${amount} > 1000"
|
||
rows={4}
|
||
autoComplete="off"
|
||
/>
|
||
</Form.Item>
|
||
) : (
|
||
<div className="text-sm text-gray-500 mb-4">
|
||
默认路径:当没有其他条件分支满足时,将执行此路径
|
||
</div>
|
||
);
|
||
}}
|
||
</Form.Item>
|
||
|
||
<Form.Item
|
||
name="priority"
|
||
label="优先级"
|
||
rules={[{ required: true, message: '请设置优先级' }]}
|
||
extra="数字越小优先级越高(1-999)"
|
||
>
|
||
<InputNumber
|
||
min={1}
|
||
max={999}
|
||
className="w-full"
|
||
placeholder="请输入优先级"
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
</Modal>
|
||
);
|
||
};
|
||
|
||
export default EdgeConfigModal;
|
||
|