diff --git a/frontend/src/components/approval/ApprovalCreateDialog.tsx b/frontend/src/components/approval/ApprovalCreateDialog.tsx new file mode 100644 index 0000000..7b685c1 --- /dev/null +++ b/frontend/src/components/approval/ApprovalCreateDialog.tsx @@ -0,0 +1,212 @@ +import { useState } from 'react'; +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Textarea } from '@/components/ui/textarea'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Loader2 } from 'lucide-react'; +import { toast } from 'sonner'; +import { approvalApi } from '@/services/api'; +import { parseFields, APPROVAL_TYPE_OPTIONS } from './helpers'; + +interface ApprovalCreateDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + templates: any[]; + onSuccess: () => void; +} + +// 新建资源申请弹窗 — 选择申请类型 + 动态表单填写,状态自包含 // Logan.Li +export function ApprovalCreateDialog({ + open, + onOpenChange, + templates, + onSuccess, +}: ApprovalCreateDialogProps) { + const [selectedTemplate, setSelectedTemplate] = useState(null); + const [formData, setFormData] = useState>({}); + const [submitting, setSubmitting] = useState(false); + + // 提交新建申请 // Logan.Li + const handleSubmit = async () => { + if (!selectedTemplate) { + toast.error('请先选择申请类型'); + return; + } + const fields = parseFields(selectedTemplate.form_schema); + for (const f of fields) { + if (f.required && !formData[f.key]) { + toast.error(`请填写${f.label}`); + return; + } + } + setSubmitting(true); + try { + await approvalApi.createProcess({ + template_id: selectedTemplate.id, + title: formData.app_name || selectedTemplate.name, + form_data: JSON.stringify(formData), + }); + toast.success('申请已提交'); + onOpenChange(false); + setSelectedTemplate(null); + setFormData({}); + onSuccess(); + } catch (e: any) { + toast.error('提交失败', { description: e?.message }); + } finally { + setSubmitting(false); + } + }; + + return ( + { + // 关闭弹窗时重置内部状态 // Logan.Li + if (!v) { + setSelectedTemplate(null); + setFormData({}); + } + onOpenChange(v); + }} + > + + + 新建资源申请 + + {selectedTemplate ? '请填写申请信息' : '请选择申请类型'} + + + + {!selectedTemplate ? ( + /* 步骤一:选择申请类型 */ +
+ {APPROVAL_TYPE_OPTIONS.map((opt) => { + const tpl = templates.find( + (t) => t.type === opt.value && (t.enabled !== false) + ); + const Icon = opt.icon; + return ( + + ); + })} +
+ ) : ( + /* 步骤二:动态表单 */ +
+
+ +
+
+ {parseFields(selectedTemplate.form_schema).map((field: any) => { + const isTextarea = field.type === 'textarea'; + return ( +
+ + {field.type === 'select' ? ( + + ) : field.type === 'textarea' ? ( +