diff --git a/app/register/page.tsx b/app/register/page.tsx index b32cbc8..7840cd1 100644 --- a/app/register/page.tsx +++ b/app/register/page.tsx @@ -8,6 +8,12 @@ import { PASSWORD_POLICY_DESCRIPTION, validatePasswordStrength } from '@/lib/pas const DEFAULT_LOGIN_LOGO = process.env.NEXT_PUBLIC_DEFAULT_LOGIN_LOGO_URL || '' +type PublicSystemSettings = { + loginLogoUrl?: string | null + siteName?: string | null + enableRegistration?: boolean | null +} + export default function RegisterPage() { const router = useRouter() const searchParams = useSearchParams() @@ -21,15 +27,69 @@ export default function RegisterPage() { const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [logoError, setLogoError] = useState(false) + const [loginLogoUrl, setLoginLogoUrl] = useState(DEFAULT_LOGIN_LOGO) + const [siteName, setSiteName] = useState('FLNXI素材库') + const [registrationEnabled, setRegistrationEnabled] = useState(false) + const [settingsLoaded, setSettingsLoaded] = useState(false) const pageClass = 'min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-950 p-4' const panelClass = 'w-full max-w-md rounded-lg border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 shadow-sm p-6' const inputClass = 'w-full px-4 py-3 rounded-lg border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-900 dark:text-white placeholder:text-slate-400 dark:placeholder:text-slate-500 focus:border-slate-900 dark:focus:border-slate-500 focus:ring-2 focus:ring-slate-200 dark:focus:ring-slate-700 outline-none transition-colors' const buttonClass = 'w-full py-3 rounded-lg bg-slate-900 dark:bg-slate-100 text-white dark:text-slate-900 hover:bg-slate-800 dark:hover:bg-white font-medium transition-colors disabled:opacity-60' + const isRegistrationClosed = settingsLoaded && !registrationEnabled && !inviteCode useEffect(() => { - fetchDepartments() + const loadSettings = async () => { + try { + const response = await fetch('/api/system-settings') + if (response.ok) { + const settings = await response.json() as PublicSystemSettings + setLoginLogoUrl(settings.loginLogoUrl || DEFAULT_LOGIN_LOGO) + setSiteName(settings.siteName || 'FLNXI素材库') + setRegistrationEnabled(settings.enableRegistration === true) + setLogoError(false) + } + } catch (error) { + console.error('加载系统设置失败:', error) + } finally { + setSettingsLoaded(true) + } + } + loadSettings() }, []) + useEffect(() => { + if (!loginLogoUrl) return + + if (loginLogoUrl.startsWith('/')) { + setLogoError(false) + return + } + + try { + const parsed = new URL(loginLogoUrl) + const host = parsed.hostname.toLowerCase() + const isLocal = host === 'localhost' || host === '127.0.0.1' + if (isLocal && typeof window !== 'undefined') { + const currentHost = window.location.hostname.toLowerCase() + if (currentHost !== host) { + console.warn( + `[Register] Logo 地址 ${loginLogoUrl} 指向本地服务,但当前访问域名为 ${currentHost},自动降级为占位符` + ) + setLogoError(true) + } + } + } catch (error) { + console.warn('[Register] Logo 地址解析失败,自动降级为占位符:', loginLogoUrl, error) + setLogoError(true) + } + }, [loginLogoUrl]) + + useEffect(() => { + if (!settingsLoaded) return + if (!inviteCode && !registrationEnabled) return + fetchDepartments() + }, [inviteCode, registrationEnabled, settingsLoaded]) + const fetchDepartments = async () => { try { const response = await fetch('/api/departments') @@ -46,6 +106,11 @@ export default function RegisterPage() { e.preventDefault() setError('') + if (!inviteCode && !registrationEnabled) { + setError('注册入口未开放,请使用邀请链接或联系管理员开通账号') + return + } + if (password !== confirmPassword) { setError('两次输入的密码不一致') return @@ -89,10 +154,10 @@ export default function RegisterPage() { {/* Logo */}
{inviteCode ? '受邀加入团队素材库' : '申请加入团队素材库'}
@@ -113,6 +178,23 @@ export default function RegisterPage() { {/* Register Form */}