| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import { useForm } from 'react-hook-form';
- import { zodResolver } from '@hookform/resolvers/zod';
- import { z } from 'zod';
- import { Link, useNavigate } from 'react-router-dom';
- import { useAuth } from '@/client/home/hooks/AuthProvider';
- import { toast } from 'sonner';
- import { authClient } from '@/client/api';
- import { Button } from '@/client/components/ui/button';
- import { Input } from '@/client/components/ui/input';
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/client/components/ui/card';
- import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/client/components/ui/form';
- import { User, Lock } from 'lucide-react';
- const registerSchema = z.object({
- username: z.string()
- .min(3, '用户名至少3个字符')
- .max(20, '用户名不能超过20个字符')
- .regex(/^[a-zA-Z0-9_-]+$/, '用户名只能包含字母、数字、下划线和连字符'),
- password: z.string()
- .min(6, '密码至少6个字符')
- .max(30, '密码不能超过30个字符'),
- confirmPassword: z.string(),
- }).refine((data) => data.password === data.confirmPassword, {
- message: '两次密码输入不一致',
- path: ['confirmPassword'],
- });
- type RegisterFormData = z.infer<typeof registerSchema>;
- const RegisterPage: React.FC = () => {
- const { login } = useAuth();
- const navigate = useNavigate();
-
- const form = useForm<RegisterFormData>({
- resolver: zodResolver(registerSchema),
- defaultValues: {
- username: '',
- password: '',
- confirmPassword: '',
- },
- });
- const onSubmit = async (data: RegisterFormData) => {
- try {
- const response = await authClient.register.$post({
- json: {
- username: data.username,
- password: data.password,
- }
- });
-
- if (response.status !== 201) {
- const result = await response.json();
- throw new Error(result.message || '注册失败');
- }
-
- // 注册成功后自动登录
- await login(data.username, data.password);
- toast.success('注册成功!正在为您登录...');
- navigate('/');
- } catch (error) {
- toast.error(error instanceof Error ? error.message : '注册失败,请稍后重试');
- }
- };
- return (
- <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 px-4 py-12">
- <Card className="w-full max-w-md border-0 shadow-xl">
- <CardHeader className="space-y-1">
- <CardTitle className="text-2xl font-bold text-center">创建账号</CardTitle>
- <CardDescription className="text-center">
- 填写以下信息创建新账号
- </CardDescription>
- </CardHeader>
-
- <CardContent>
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
- <FormField
- control={form.control}
- name="username"
- render={({ field }) => (
- <FormItem>
- <FormLabel>用户名</FormLabel>
- <FormControl>
- <div className="relative">
- <User className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
- <Input
- placeholder="请输入用户名"
- className="pl-10"
- {...field}
- />
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name="password"
- render={({ field }) => (
- <FormItem>
- <FormLabel>密码</FormLabel>
- <FormControl>
- <div className="relative">
- <Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
- <Input
- type="password"
- placeholder="请输入密码"
- className="pl-10"
- {...field}
- />
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name="confirmPassword"
- render={({ field }) => (
- <FormItem>
- <FormLabel>确认密码</FormLabel>
- <FormControl>
- <div className="relative">
- <Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
- <Input
- type="password"
- placeholder="请再次输入密码"
- className="pl-10"
- {...field}
- />
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <Button
- type="submit"
- className="w-full"
- disabled={form.formState.isSubmitting}
- >
- {form.formState.isSubmitting ? '注册中...' : '注册账号'}
- </Button>
- </form>
- </Form>
- </CardContent>
- <CardFooter className="flex flex-col space-y-4">
- <div className="text-sm text-center">
- <span className="text-muted-foreground">已有账号?</span>
- <Button
- variant="link"
- className="px-1"
- asChild
- >
- <Link to="/login">立即登录</Link>
- </Button>
- </div>
-
- <div className="text-xs text-center text-muted-foreground">
- <p>注册即表示您同意我们的服务条款</p>
- </div>
- </CardFooter>
- </Card>
- </div>
- );
- };
- export default RegisterPage;
|