127 lines
3.9 KiB
TypeScript
127 lines
3.9 KiB
TypeScript
import { useRouter } from "@tanstack/react-router";
|
||
import { zodResolver } from "@hookform/resolvers/zod";
|
||
import { useForm } from "react-hook-form";
|
||
import { z } from "zod";
|
||
import {
|
||
Form,
|
||
FormField,
|
||
FormItem,
|
||
FormLabel,
|
||
FormControl,
|
||
FormMessage,
|
||
} from "@/components/ui/form";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Input } from "@/components/ui/input";
|
||
import { Spinner } from "@/components/ui/spinner";
|
||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||
import { TriangleAlert } from "lucide-react";
|
||
import { initUserPassword } from "@/apis/user";
|
||
import { useMutation } from "@tanstack/react-query";
|
||
import { toast } from "sonner";
|
||
import logo from "@/assets/image/logo.png";
|
||
import { useUserStore } from "@/stores/user";
|
||
|
||
const formSchema = z.object({
|
||
rePassword: z.string().nonempty({
|
||
message: "确认密码不能为空",
|
||
}),
|
||
password: z.string().nonempty({
|
||
message: "密码不能为空",
|
||
}),
|
||
});
|
||
|
||
const title = import.meta.env.VITE_APP_TITLE;
|
||
|
||
export function InitPassword() {
|
||
const router = useRouter();
|
||
const user = useUserStore((state) => state.user);
|
||
|
||
const form = useForm<z.infer<typeof formSchema>>({
|
||
resolver: zodResolver(formSchema),
|
||
defaultValues: {
|
||
password: "",
|
||
rePassword: "",
|
||
},
|
||
});
|
||
|
||
const { mutateAsync, isPending } = useMutation({
|
||
mutationFn: initUserPassword,
|
||
onSuccess() {
|
||
router.navigate({ to: "/", replace: true });
|
||
},
|
||
});
|
||
|
||
const onSubmit = (values: z.infer<typeof formSchema>) => {
|
||
toast.promise(mutateAsync({ ...values, username: user?.username }), {
|
||
loading: "提交中...",
|
||
success: "设置成功",
|
||
});
|
||
};
|
||
|
||
return (
|
||
<div className="flex items-center justify-center min-h-screen box-border">
|
||
<div>
|
||
<div className="flex justify-center items-center mb-4 gap-2">
|
||
<img
|
||
src={logo}
|
||
alt=""
|
||
className="size-12 object-contain rounded-full bg-white overflow-hidden"
|
||
/>
|
||
<div className="text-3xl">{title}</div>
|
||
</div>
|
||
<div className="w-[480px] p-10 bg-white rounded-xl">
|
||
<div className="text-center text-2xl">设置密码</div>
|
||
<Alert variant="warning" className="mt-4">
|
||
<TriangleAlert />
|
||
<AlertTitle>首次登录请设置新密码</AlertTitle>
|
||
<AlertDescription>
|
||
设置成功后即可正常使用系统。密码长度 6-32 位,支持字母、数字和特殊字符
|
||
</AlertDescription>
|
||
</Alert>
|
||
<Form {...form}>
|
||
<form
|
||
onSubmit={form.handleSubmit(onSubmit)}
|
||
className="space-y-8 mt-6"
|
||
>
|
||
<FormField
|
||
control={form.control}
|
||
name="password"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel>密码</FormLabel>
|
||
<FormControl>
|
||
<Input type="password" placeholder="密码" {...field} />
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
<FormField
|
||
control={form.control}
|
||
name="rePassword"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel>确认密码</FormLabel>
|
||
<FormControl>
|
||
<Input
|
||
type="password"
|
||
placeholder="确认密码"
|
||
{...field}
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
<Button type="submit" className="w-full" disabled={isPending}>
|
||
{isPending && <Spinner />}
|
||
提交
|
||
</Button>
|
||
</form>
|
||
</Form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|