lty/qy-lty-admin/components/users/user-form-dialog.tsx
2026-03-17 13:17:02 +08:00

289 lines
9.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type React from "react"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Loader2, UserPlus } from "lucide-react"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
// 表单验证模式
const formSchema = z.object({
name: z
.string()
.min(2, {
message: "用户名至少需要2个字符",
})
.max(30, {
message: "用户名不能超过30个字符",
}),
email: z.string().email({
message: "请输入有效的邮箱地址",
}),
phone: z.string().optional(),
role: z.string({
required_error: "请选择用户角色",
}),
status: z.enum(["活跃", "未激活", "已禁用"], {
required_error: "请选择用户状态",
}),
address: z.string().optional(),
})
type UserFormDialogProps = {
open?: boolean
onOpenChange?: (open: boolean) => void
onSubmit: (data: z.infer<typeof formSchema>) => Promise<void>
defaultValues?: Partial<z.infer<typeof formSchema>>
mode: "add" | "edit"
roles: Array<{ id: string; name: string }>
trigger?: React.ReactNode
}
export function UserFormDialog({
open,
onOpenChange,
onSubmit,
defaultValues,
mode,
roles,
trigger,
}: UserFormDialogProps) {
const [isSubmitting, setIsSubmitting] = useState(false)
const [dialogOpen, setDialogOpen] = useState(open || false)
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
email: "",
phone: "",
role: "",
status: "未激活",
address: "",
...defaultValues,
},
})
// 当defaultValues改变时重置表单
useEffect(() => {
if (defaultValues) {
form.reset({
name: defaultValues.name || "",
email: defaultValues.email || "",
phone: defaultValues.phone || "",
role: defaultValues.role || "",
status: defaultValues.status || "未激活",
address: defaultValues.address || "",
})
}
}, [defaultValues, form])
// 同步内部状态和外部状态
useEffect(() => {
if (open !== undefined) {
setDialogOpen(open)
}
}, [open])
const handleOpenChange = (newOpen: boolean) => {
setDialogOpen(newOpen)
if (onOpenChange) {
onOpenChange(newOpen)
}
// 如果对话框关闭,重置表单
if (!newOpen) {
form.reset()
}
}
const handleSubmit = async (data: z.infer<typeof formSchema>) => {
setIsSubmitting(true)
try {
await onSubmit(data)
handleOpenChange(false)
} catch (error) {
console.error("提交失败:", error)
} finally {
setIsSubmitting(false)
}
}
return (
<Dialog open={dialogOpen} onOpenChange={handleOpenChange}>
<DialogTrigger asChild>
{trigger || (
<Button className="bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 transition-all duration-300 shadow-md hover:shadow-lg">
<UserPlus className="mr-2 h-4 w-4" />
</Button>
)}
</DialogTrigger>
<DialogContent className="sm:max-w-[550px]">
<DialogHeader>
<DialogTitle className="text-xl font-bold flex items-center">
<span className="bg-clip-text text-transparent bg-gradient-to-r from-purple-600 to-pink-600">
{mode === "add" ? "添加用户" : "编辑用户"}
</span>
</DialogTitle>
<DialogDescription>{mode === "add" ? "创建新的系统用户" : "修改用户信息"}</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4 py-4">
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input placeholder="输入用户名" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input placeholder="输入邮箱地址" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input placeholder="输入电话号码(可选)" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="role"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value} value={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="选择用户角色" />
</SelectTrigger>
</FormControl>
<SelectContent>
{roles.map((role) => (
<SelectItem key={role.id} value={role.name}>
{role.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value} value={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="选择用户状态" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="活跃"></SelectItem>
<SelectItem value="未激活"></SelectItem>
<SelectItem value="已禁用"></SelectItem>
</SelectContent>
</Select>
<FormDescription></FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="address"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl>
<Input placeholder="输入地址(可选)" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{mode === "add" && (
<div className="bg-blue-50 p-3 rounded-md text-sm text-blue-700">
<p className="font-medium"></p>
<p></p>
</div>
)}
<DialogFooter className="pt-4">
<Button type="button" variant="outline" onClick={() => handleOpenChange(false)} disabled={isSubmitting}>
</Button>
<Button
type="submit"
disabled={isSubmitting}
className="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700"
>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>{mode === "add" ? "创建用户" : "保存修改"}</>
)}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
)
}