flnxi-Wu/app/register/page.tsx
WuYongJie d1c6efc79d
Some checks failed
CI Check / check (push) Has been cancelled
feat: NAS 部署与 Harbor 推送流程
2025-12-03 14:39:06 +08:00

209 lines
6.4 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="FLNXI素材库"
width={80}
height={80}
unoptimized
className="rounded-apple shadow-apple"
/>
</div>
<h1 className="text-3xl font-bold text-slate-900 dark:text-slate-100">FLNXI素材库</h1>
<p className="text-slate-600 dark:text-slate-400 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-slate-700 dark:text-slate-300 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-slate-700 dark:text-slate-300 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-slate-700 dark:text-slate-300 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-slate-500 dark:text-slate-400 mt-1">
暂无可选部门,请联系管理员添加
</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 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-slate-700 dark:text-slate-300 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-slate-600 dark:text-slate-400">
已有账号?{' '}
<Link
href="/login"
className="text-slate-900 dark:text-slate-100 hover:text-slate-700 dark:hover:text-slate-300 font-medium underline"
>
立即登录
</Link>
</p>
</div>
</div>
</div>
</div>
)
}