import React, { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Label } from '@/components/ui/label'; import { useToast } from '@/components/ui/use-toast'; 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; } // Zod 表单验证 Schema const edgeConditionSchema = z.object({ type: z.enum(['EXPRESSION', 'DEFAULT'], { required_error: '请选择条件类型', }), expression: z.string().optional(), priority: z.number() .min(1, '优先级最小为 1') .max(999, '优先级最大为 999'), }).refine((data) => { // 如果是表达式类型,expression 必填 if (data.type === 'EXPRESSION') { return data.expression && data.expression.trim().length > 0; } return true; }, { message: '请输入条件表达式', path: ['expression'], }); type EdgeConditionFormValues = z.infer; /** * 边条件配置弹窗 * 使用 shadcn/ui Dialog + react-hook-form */ const EdgeConfigModal: React.FC = ({ visible, edge, onOk, onCancel }) => { const { toast } = useToast(); const [conditionType, setConditionType] = useState<'EXPRESSION' | 'DEFAULT'>('EXPRESSION'); const form = useForm({ resolver: zodResolver(edgeConditionSchema), defaultValues: { type: 'EXPRESSION', expression: '', priority: 10, }, }); // 当 edge 变化时,更新表单值 useEffect(() => { if (visible && edge) { const condition = edge.data?.condition; const values = { type: (condition?.type || 'EXPRESSION') as 'EXPRESSION' | 'DEFAULT', expression: condition?.expression || '', priority: condition?.priority || 10, }; form.reset(values); setConditionType(values.type); } }, [visible, edge, form]); const handleSubmit = (values: EdgeConditionFormValues) => { if (!edge) return; // 检查表达式是否包含变量引用 if (values.type === 'EXPRESSION' && values.expression) { const hasVariable = /\$\{[\w.]+\}/.test(values.expression); if (!hasVariable) { toast({ title: '提示', description: '表达式建议包含变量引用,格式:${变量名}', }); } } onOk(edge.id, values); handleClose(); }; const handleClose = () => { form.reset(); setConditionType('EXPRESSION'); onCancel(); }; return ( !open && handleClose()}> 配置边条件 设置流程分支的条件表达式和优先级
( 条件类型
{ field.onChange(e.target.value); setConditionType('EXPRESSION'); }} className="h-4 w-4" />
{ field.onChange(e.target.value); setConditionType('DEFAULT'); }} className="h-4 w-4" />
)} /> {conditionType === 'EXPRESSION' ? ( ( 条件表达式