对齐注册页私有化入口
This commit is contained in:
parent
1920c05f51
commit
e04da3ea1e
@ -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 */}
|
||||
<div className="text-center mb-8">
|
||||
<div className="flex justify-center mb-4">
|
||||
{DEFAULT_LOGIN_LOGO && !logoError ? (
|
||||
{loginLogoUrl && !logoError ? (
|
||||
<Image
|
||||
src={DEFAULT_LOGIN_LOGO}
|
||||
alt="FLNXI素材库"
|
||||
src={loginLogoUrl}
|
||||
alt={siteName}
|
||||
width={80}
|
||||
height={80}
|
||||
unoptimized
|
||||
@ -101,11 +166,11 @@ export default function RegisterPage() {
|
||||
/>
|
||||
) : (
|
||||
<div className="w-20 h-20 rounded-lg border border-slate-200 dark:border-slate-700 shadow-sm bg-slate-900 dark:bg-slate-700 flex items-center justify-center">
|
||||
<span className="text-3xl font-bold text-white">F</span>
|
||||
<span className="text-3xl font-bold text-white">{siteName.charAt(0) || 'F'}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<h1 className="text-2xl font-semibold text-slate-900 dark:text-slate-100">FLNXI素材库</h1>
|
||||
<h1 className="text-2xl font-semibold text-slate-900 dark:text-slate-100">{siteName}</h1>
|
||||
<p className="text-slate-600 dark:text-slate-400 mt-2">
|
||||
{inviteCode ? '受邀加入团队素材库' : '申请加入团队素材库'}
|
||||
</p>
|
||||
@ -113,6 +178,23 @@ export default function RegisterPage() {
|
||||
|
||||
{/* Register Form */}
|
||||
<div className={panelClass}>
|
||||
{!settingsLoaded ? (
|
||||
<div className="rounded-lg border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600 dark:border-slate-700 dark:bg-slate-800/50 dark:text-slate-400">
|
||||
正在检查注册入口...
|
||||
</div>
|
||||
) : isRegistrationClosed ? (
|
||||
<div className="space-y-5">
|
||||
<div className="rounded-lg border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600 dark:border-slate-700 dark:bg-slate-800/50 dark:text-slate-400">
|
||||
注册入口未开放。请使用管理员发送的邀请链接,或联系管理员开通账号。
|
||||
</div>
|
||||
<Link
|
||||
href="/login"
|
||||
className="block w-full rounded-lg border border-slate-300 px-4 py-3 text-center text-sm font-medium text-slate-700 transition-colors hover:bg-slate-50 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
|
||||
>
|
||||
返回登录
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<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-lg text-sm">
|
||||
@ -215,6 +297,7 @@ export default function RegisterPage() {
|
||||
{loading ? '注册中...' : '注册'}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||
|
||||
@ -1161,6 +1161,7 @@ NAS 私有化系统可能在平板或窄屏浏览器里使用。模板编辑器
|
||||
- `app/login/page.tsx:295`:登录页已改为浅灰背景和中性表单,不再使用浅蓝渐变背景。
|
||||
- `app/login/page.tsx`、`app/register/page.tsx`:登录/注册页卡片、输入框、按钮和 Logo 占位已从 `rounded-xl` 收为 `rounded-lg`,减少通用 SaaS 模板感。
|
||||
- `app/register/page.tsx`:注册页会读取 URL 上的 `invite` 参数并随注册请求提交;无邀请参数时提示用户使用邀请链接或联系管理员开通账号。
|
||||
- `app/register/page.tsx`:注册页已和登录页一样读取系统名称、登录 Logo 和注册开关;无邀请码且公开注册关闭时不再展示完整自助注册表单,只提示使用邀请链接或联系管理员。
|
||||
- `app/api/auth/register/route.ts`:关闭公开注册时不再直接挡掉邀请链接;有效邀请码仍可完成注册并记录使用次数,无邀请码仍拒绝公开注册。
|
||||
- `app/api/auth/register/__tests__/route.test.ts`:新增测试覆盖“关闭公开注册时无邀请码拒绝、有有效邀请码允许注册”的私有化账号入口。
|
||||
- `app/register/page.tsx:21`:注册页已改为和登录页一致的浅灰背景。
|
||||
@ -1174,7 +1175,7 @@ NAS 私有化系统可能在平板或窄屏浏览器里使用。模板编辑器
|
||||
|
||||
建议动作:
|
||||
|
||||
- 登录、激活、回调、完善资料页统一成同一套私有化安装/访问风格;登录/注册页已完成第一轮圆角和口径收口,邀请注册链路已修复;钉钉回调页和激活页已完成第一轮视觉收口,激活页公网试用/购买口径已进一步隐藏。
|
||||
- 登录、激活、回调、完善资料页统一成同一套私有化安装/访问风格;登录/注册页已完成第一轮圆角、口径和系统名称/Logo 对齐,邀请注册链路已修复;钉钉回调页和激活页已完成第一轮视觉收口,激活页公网试用/购买口径已进一步隐藏。
|
||||
- 背景用纯色或轻灰,不用大面积渐变。
|
||||
- 登录页可以保留品牌感,但减少泛 SaaS 视觉:小 Logo、清晰表单、明确客户系统名称即可。
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user