203 lines
6.7 KiB
TypeScript
Executable File
203 lines
6.7 KiB
TypeScript
Executable File
'use client'
|
||
|
||
import { useState } from 'react'
|
||
import { useRouter } from 'next/navigation'
|
||
import { useForm } from 'react-hook-form'
|
||
import { useAuth } from '@/components/providers/auth-provider'
|
||
import { Button } from '@nice/ui/components/button'
|
||
import { Input } from '@nice/ui/components/input'
|
||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@nice/ui/components/form'
|
||
import { Alert, AlertDescription } from '@nice/ui/components/alert'
|
||
import { DeptSelect } from '@/components/selector/dept-select'
|
||
import Link from 'next/link'
|
||
|
||
interface RegisterForm {
|
||
username: string
|
||
password: string
|
||
confirmPassword: string
|
||
email?: string
|
||
organizationId?: string
|
||
}
|
||
|
||
export default function RegisterPage() {
|
||
const router = useRouter()
|
||
const { register: registerUser, isLoading } = useAuth()
|
||
|
||
const [error, setError] = useState<string | null>(null)
|
||
|
||
const form = useForm<RegisterForm>({
|
||
defaultValues: {
|
||
username: '',
|
||
password: '',
|
||
confirmPassword: '',
|
||
email: '',
|
||
organizationId: ''
|
||
}
|
||
})
|
||
|
||
const handleSubmit = async (data: RegisterForm) => {
|
||
// 验证密码确认
|
||
if (data.password !== data.confirmPassword) {
|
||
form.setError('confirmPassword', { message: '两次输入的密码不一致' })
|
||
return
|
||
}
|
||
|
||
setError(null)
|
||
try {
|
||
await registerUser({
|
||
data: {
|
||
username: data.username,
|
||
password: data.password,
|
||
organizationId: data.organizationId,
|
||
}
|
||
})
|
||
// 注册成功,跳转到登录页
|
||
router.push('/auth/login?message=register_success')
|
||
} catch (err) {
|
||
setError(err instanceof Error ? err.message : '注册失败,请重试')
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="w-full">
|
||
{/* 欢迎标题 */}
|
||
<div className="text-center mb-12">
|
||
<h1 className="text-3xl font-bold text-gray-900 mb-3">注册风火账号</h1>
|
||
|
||
{/* 错误消息 */}
|
||
{error && (
|
||
<Alert className="mb-4 border-red-200 bg-red-50">
|
||
<AlertDescription className="text-red-800">
|
||
{error}
|
||
</AlertDescription>
|
||
</Alert>
|
||
)}
|
||
</div>
|
||
|
||
{/* 注册表单 */}
|
||
<Form {...form}>
|
||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
|
||
{/* 用户名输入 */}
|
||
<FormField
|
||
control={form.control}
|
||
name="username"
|
||
rules={{
|
||
required: '请输入用户名',
|
||
minLength: { value: 2, message: '用户名至少2个字符' },
|
||
pattern: {
|
||
value: /^[\u4e00-\u9fa5a-zA-Z0-9_@.-]+$/,
|
||
message: '用户名只能包含中文、字母、数字、下划线、@、点和横线'
|
||
}
|
||
}}
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel className="text-base text-gray-700 font-medium">用户名</FormLabel>
|
||
<FormControl>
|
||
<Input
|
||
type="text"
|
||
placeholder="请输入用户名"
|
||
className="h-12 text-base focus-visible:ring-1 focus-visible:ring-blue-500 focus-visible:border-blue-500"
|
||
autoComplete="username"
|
||
disabled={isLoading}
|
||
{...field}
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
|
||
{/* 所属部门选择 */}
|
||
<FormField
|
||
control={form.control}
|
||
name="organizationId"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel className="text-base text-gray-700 font-medium">所属部门 (可选)</FormLabel>
|
||
<FormControl>
|
||
<DeptSelect
|
||
value={field.value}
|
||
onValueChange={field.onChange}
|
||
placeholder="选择所属部门"
|
||
className="w-full h-12"
|
||
disabled={isLoading}
|
||
allowClear={true}
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
|
||
{/* 密码输入 */}
|
||
<FormField
|
||
control={form.control}
|
||
name="password"
|
||
rules={{
|
||
required: '请输入密码',
|
||
minLength: { value: 6, message: '密码至少6个字符' }
|
||
}}
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel className="text-base text-gray-700 font-medium">密码</FormLabel>
|
||
<FormControl>
|
||
<Input
|
||
type="password"
|
||
placeholder="请输入密码(至少6个字符)"
|
||
className="h-12 text-base focus-visible:ring-1 focus-visible:ring-blue-500 focus-visible:border-blue-500"
|
||
autoComplete="new-password"
|
||
disabled={isLoading}
|
||
{...field}
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
|
||
{/* 确认密码输入 */}
|
||
<FormField
|
||
control={form.control}
|
||
name="confirmPassword"
|
||
rules={{
|
||
required: '请确认密码',
|
||
minLength: { value: 6, message: '密码至少6个字符' }
|
||
}}
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<FormLabel className="text-base text-gray-700 font-medium">确认密码</FormLabel>
|
||
<FormControl>
|
||
<Input
|
||
type="password"
|
||
placeholder="请再次输入密码"
|
||
className="h-12 text-base focus-visible:ring-1 focus-visible:ring-blue-500 focus-visible:border-blue-500"
|
||
autoComplete="new-password"
|
||
disabled={isLoading}
|
||
{...field}
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
{/* 注册按钮 */}
|
||
<Button
|
||
type="submit"
|
||
className="w-full h-12 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium text-base transition-colors mt-8"
|
||
disabled={isLoading}
|
||
>
|
||
{isLoading ? '注册中...' : '注册账号'}
|
||
</Button>
|
||
</form>
|
||
</Form>
|
||
|
||
{/* 登录链接 */}
|
||
<div className="text-center mt-8">
|
||
<span className="text-base text-gray-600">已有账号?</span>
|
||
<Link href="/auth/login" className="text-base text-blue-600 hover:underline ml-2">
|
||
立即登录
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|