flnxi-Wu/app/register/page.tsx
WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

208 lines
6.1 KiB
TypeScript
Raw 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 { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import Image from 'next/image'
import Link from 'next/link'
export default function RegisterPage() {
const router = useRouter()
const [email, setEmail] = useState('')
const [username, setUsername] = useState('')
const [department, setDepartment] = useState('')
const [departments, setDepartments] = useState<Array<{ id: string; name: string }>>([])
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
useEffect(() => {
fetchDepartments()
}, [])
const fetchDepartments = async () => {
try {
const response = await fetch('/api/departments')
if (response.ok) {
const data = await response.json()
setDepartments(data)
}
} catch (error) {
console.error('Error fetching departments:', error)
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError('')
if (password !== confirmPassword) {
setError('两次输入的密码不一致')
return
}
if (password.length < 6) {
setError('密码长度至少为6个字符')
return
}
setLoading(true)
try {
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, username, department, password }),
})
const data = await response.json()
if (response.ok) {
router.push('/login?registered=true')
} else {
setError(data.error || '注册失败')
}
} catch (error) {
console.error('Registration error:', error)
setError('注册失败,请稍后再试')
} finally {
setLoading(false)
}
}
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-primary-50 to-primary-100 p-4">
<div className="max-w-md w-full">
{/* Logo */}
<div className="text-center mb-8">
<div className="flex justify-center mb-4">
<Image
src={process.env.NEXT_PUBLIC_DEFAULT_LOGIN_LOGO_URL || ''}
alt="由壹点3D素材"
width={80}
height={80}
unoptimized
className="rounded-apple shadow-apple"
/>
</div>
<h1 className="text-3xl font-bold text-gray-900">由壹点3D素材</h1>
<p className="text-gray-600 mt-2">创建您的账号,开始分享3D素材</p>
</div>
{/* Register Form */}
<div className="card-apple p-8">
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="bg-red-50 border border-red-200 text-red-600 px-4 py-3 rounded-apple text-sm">
{error}
</div>
)}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
邮箱
</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="input-apple"
placeholder="your@email.com"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
用户名
</label>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="input-apple"
placeholder="选择一个用户名"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
部门
</label>
<select
value={department}
onChange={(e) => setDepartment(e.target.value)}
className="input-apple"
>
<option value="">请选择部门</option>
{departments.map((dept) => (
<option key={dept.id} value={dept.name}>
{dept.name}
</option>
))}
</select>
{departments.length === 0 && (
<p className="text-sm text-gray-500 mt-1">
暂无可选部门,请联系管理员添加
</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
密码
</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="input-apple"
placeholder="••••••••"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
确认密码
</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="input-apple"
placeholder="••••••••"
required
/>
</div>
<button
type="submit"
className="w-full btn-primary"
disabled={loading}
>
{loading ? '注册中...' : '注册'}
</button>
</form>
<div className="mt-6 text-center">
<p className="text-sm text-gray-600">
已有账号?{' '}
<Link
href="/login"
className="text-gray-900 hover:text-gray-700 font-medium underline"
>
立即登录
</Link>
</p>
</div>
</div>
</div>
</div>
)
}