import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { Separator } from '@/components/ui/separator'; import { FileText, Tag, Folder, AlignLeft, Copy, Loader2 } from 'lucide-react'; import { useToast } from '@/components/ui/use-toast'; import { createDefinition } from '../service'; import { getEnabledCategories } from '../../Category/service'; import type { FormDefinitionRequest } from '../types'; import type { FormCategoryResponse } from '../../Category/types'; interface CreateModalProps { visible: boolean; onClose: () => void; onSuccess: (id: number) => void; } /** * 表单定义创建弹窗(第一步:输入基本信息) */ const CreateModal: React.FC = ({ visible, onClose, onSuccess }) => { const navigate = useNavigate(); const { toast } = useToast(); const [submitting, setSubmitting] = useState(false); const [categories, setCategories] = useState([]); const [formData, setFormData] = useState({ name: '', key: '', categoryId: undefined as number | undefined, description: '', isTemplate: false, }); // 加载分类列表 useEffect(() => { if (visible) { loadCategories(); } }, [visible]); const loadCategories = async () => { try { const result = await getEnabledCategories(); setCategories(result || []); } catch (error) { console.error('加载分类失败:', error); } }; // 重置表单 const resetForm = () => { setFormData({ name: '', key: '', categoryId: undefined, description: '', isTemplate: false, }); }; // 关闭弹窗 const handleClose = () => { resetForm(); onClose(); }; // 提交表单 const handleSubmit = async () => { // 验证 if (!formData.name.trim()) { toast({ title: '验证失败', description: '请输入表单名称', variant: 'destructive' }); return; } if (!formData.key.trim()) { toast({ title: '验证失败', description: '请输入表单标识', variant: 'destructive' }); return; } // 验证表单标识格式(英文字母、数字、中划线) if (!/^[a-zA-Z0-9-]+$/.test(formData.key)) { toast({ title: '验证失败', description: '表单标识只能包含英文字母、数字和中划线', variant: 'destructive' }); return; } setSubmitting(true); try { // 创建表单定义(只保存基本信息,schema 为空) const request: FormDefinitionRequest = { name: formData.name, key: formData.key, categoryId: formData.categoryId, description: formData.description, isTemplate: formData.isTemplate, status: 'DRAFT', schema: { version: '1.0', formConfig: { labelAlign: 'right', size: 'middle' }, fields: [] } }; const result = await createDefinition(request); toast({ title: '创建成功', description: '表单基本信息已保存,现在可以开始设计表单' }); // 跳转到设计器页面 navigate(`/form/definitions/${result.id}/design`); handleClose(); onSuccess(result.id); } catch (error) { console.error('创建表单失败:', error); toast({ title: '创建失败', description: error instanceof Error ? error.message : '创建表单失败', variant: 'destructive' }); } finally { setSubmitting(false); } }; return ( 创建表单定义 第一步:输入表单的基本信息,然后点击"下一步"进入表单设计器
{/* 第一行:表单名称 + 表单标识 */}
setFormData(prev => ({ ...prev, name: e.target.value }))} className="h-10" />

将显示在表单列表和表单顶部

setFormData(prev => ({ ...prev, key: e.target.value }))} className="h-10 font-mono" />

英文字母、数字和中划线,用于 API 调用

{/* 第二行:分类 + 设为模板 */}

帮助用户快速找到相关表单

启用模板功能
setFormData(prev => ({ ...prev, isTemplate: checked }))} />

模板表单可以被其他表单引用和复制

{/* 第三行:描述 */}