收口私有化注册入口口径
This commit is contained in:
parent
39ae249ce7
commit
7e9dee3817
@ -4,7 +4,6 @@ import { useState, useEffect } from 'react'
|
|||||||
import { signIn } from 'next-auth/react'
|
import { signIn } from 'next-auth/react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
// 默认登录页 Logo:优先使用构建时环境变量,否则使用内置静态资源
|
// 默认登录页 Logo:优先使用构建时环境变量,否则使用内置静态资源
|
||||||
const DEFAULT_LOGIN_LOGO =
|
const DEFAULT_LOGIN_LOGO =
|
||||||
@ -19,7 +18,6 @@ type DingtalkPublicConfig = {
|
|||||||
type PublicSystemSettings = {
|
type PublicSystemSettings = {
|
||||||
loginLogoUrl?: string | null
|
loginLogoUrl?: string | null
|
||||||
siteName?: string | null
|
siteName?: string | null
|
||||||
enableRegistration?: boolean | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
@ -34,7 +32,6 @@ export default function LoginPage() {
|
|||||||
// 系统设置
|
// 系统设置
|
||||||
const [loginLogoUrl, setLoginLogoUrl] = useState(DEFAULT_LOGIN_LOGO)
|
const [loginLogoUrl, setLoginLogoUrl] = useState(DEFAULT_LOGIN_LOGO)
|
||||||
const [siteName, setSiteName] = useState('FLNXI素材库')
|
const [siteName, setSiteName] = useState('FLNXI素材库')
|
||||||
const [registrationEnabled, setRegistrationEnabled] = useState(false)
|
|
||||||
const [dingtalkConfig, setDingtalkConfig] = useState<DingtalkPublicConfig>({
|
const [dingtalkConfig, setDingtalkConfig] = useState<DingtalkPublicConfig>({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
clientId: null,
|
clientId: null,
|
||||||
@ -82,7 +79,6 @@ export default function LoginPage() {
|
|||||||
const settings = await response.json() as PublicSystemSettings
|
const settings = await response.json() as PublicSystemSettings
|
||||||
setLoginLogoUrl(settings.loginLogoUrl || DEFAULT_LOGIN_LOGO)
|
setLoginLogoUrl(settings.loginLogoUrl || DEFAULT_LOGIN_LOGO)
|
||||||
setSiteName(settings.siteName || 'FLNXI素材库')
|
setSiteName(settings.siteName || 'FLNXI素材库')
|
||||||
setRegistrationEnabled(settings.enableRegistration === true)
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载系统设置失败:', error)
|
console.error('加载系统设置失败:', error)
|
||||||
@ -425,19 +421,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
<div className="mt-6 text-center">
|
<div className="mt-6 text-center">
|
||||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
{registrationEnabled ? (
|
没有账号?请联系管理员开通,或使用管理员发送的邀请链接。
|
||||||
<>
|
|
||||||
需要账号?请联系管理员,或{' '}
|
|
||||||
<Link
|
|
||||||
href="/register"
|
|
||||||
className="text-slate-900 dark:text-slate-100 hover:text-slate-700 dark:hover:text-slate-300 font-medium underline"
|
|
||||||
>
|
|
||||||
通过注册入口申请加入
|
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
'没有账号?请联系管理员开通'
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,7 +11,6 @@ const DEFAULT_LOGIN_LOGO = process.env.NEXT_PUBLIC_DEFAULT_LOGIN_LOGO_URL || ''
|
|||||||
type PublicSystemSettings = {
|
type PublicSystemSettings = {
|
||||||
loginLogoUrl?: string | null
|
loginLogoUrl?: string | null
|
||||||
siteName?: string | null
|
siteName?: string | null
|
||||||
enableRegistration?: boolean | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RegisterPage() {
|
export default function RegisterPage() {
|
||||||
@ -29,13 +28,12 @@ export default function RegisterPage() {
|
|||||||
const [logoError, setLogoError] = useState(false)
|
const [logoError, setLogoError] = useState(false)
|
||||||
const [loginLogoUrl, setLoginLogoUrl] = useState(DEFAULT_LOGIN_LOGO)
|
const [loginLogoUrl, setLoginLogoUrl] = useState(DEFAULT_LOGIN_LOGO)
|
||||||
const [siteName, setSiteName] = useState('FLNXI素材库')
|
const [siteName, setSiteName] = useState('FLNXI素材库')
|
||||||
const [registrationEnabled, setRegistrationEnabled] = useState(false)
|
|
||||||
const [settingsLoaded, setSettingsLoaded] = 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 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 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 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 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
|
const isRegistrationClosed = settingsLoaded && !inviteCode
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadSettings = async () => {
|
const loadSettings = async () => {
|
||||||
@ -45,7 +43,6 @@ export default function RegisterPage() {
|
|||||||
const settings = await response.json() as PublicSystemSettings
|
const settings = await response.json() as PublicSystemSettings
|
||||||
setLoginLogoUrl(settings.loginLogoUrl || DEFAULT_LOGIN_LOGO)
|
setLoginLogoUrl(settings.loginLogoUrl || DEFAULT_LOGIN_LOGO)
|
||||||
setSiteName(settings.siteName || 'FLNXI素材库')
|
setSiteName(settings.siteName || 'FLNXI素材库')
|
||||||
setRegistrationEnabled(settings.enableRegistration === true)
|
|
||||||
setLogoError(false)
|
setLogoError(false)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -86,9 +83,9 @@ export default function RegisterPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!settingsLoaded) return
|
if (!settingsLoaded) return
|
||||||
if (!inviteCode && !registrationEnabled) return
|
if (!inviteCode) return
|
||||||
fetchDepartments()
|
fetchDepartments()
|
||||||
}, [inviteCode, registrationEnabled, settingsLoaded])
|
}, [inviteCode, settingsLoaded])
|
||||||
|
|
||||||
const fetchDepartments = async () => {
|
const fetchDepartments = async () => {
|
||||||
try {
|
try {
|
||||||
@ -106,7 +103,7 @@ export default function RegisterPage() {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setError('')
|
setError('')
|
||||||
|
|
||||||
if (!inviteCode && !registrationEnabled) {
|
if (!inviteCode) {
|
||||||
setError('注册入口未开放,请使用邀请链接或联系管理员开通账号')
|
setError('注册入口未开放,请使用邀请链接或联系管理员开通账号')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -172,7 +169,7 @@ export default function RegisterPage() {
|
|||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-semibold text-slate-900 dark:text-slate-100">{siteName}</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">
|
<p className="text-slate-600 dark:text-slate-400 mt-2">
|
||||||
{inviteCode ? '受邀加入团队素材库' : '申请加入团队素材库'}
|
{inviteCode ? '受邀加入团队素材库' : '请使用邀请链接加入团队'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1181,11 +1181,11 @@ NAS 私有化系统可能在平板或窄屏浏览器里使用。模板编辑器
|
|||||||
证据:
|
证据:
|
||||||
|
|
||||||
- `app/login/page.tsx:11`:默认登录 Logo 不再指向不存在的 `/logo/logo2.png`,没有配置时直接走文字占位。
|
- `app/login/page.tsx:11`:默认登录 Logo 不再指向不存在的 `/logo/logo2.png`,没有配置时直接走文字占位。
|
||||||
- `app/api/system-settings/route.ts`、`app/login/page.tsx`:公共系统设置现在返回注册开关;登录页不再固定展示“立即注册”,注册开启时改为“需要账号?请联系管理员,或通过注册入口申请加入”,关闭时提示联系管理员开通。
|
- `app/api/system-settings/route.ts`、`app/login/page.tsx`:公共系统设置不再返回注册开关;登录页不展示普通自助注册入口,统一提示联系管理员开通账号或使用邀请链接。
|
||||||
- `app/login/page.tsx:295`:登录页已改为浅灰背景和中性表单,不再使用浅蓝渐变背景。
|
- `app/login/page.tsx:295`:登录页已改为浅灰背景和中性表单,不再使用浅蓝渐变背景。
|
||||||
- `app/login/page.tsx`、`app/register/page.tsx`:登录/注册页卡片、输入框、按钮和 Logo 占位已从 `rounded-xl` 收为 `rounded-lg`,减少通用 SaaS 模板感。
|
- `app/login/page.tsx`、`app/register/page.tsx`:登录/注册页卡片、输入框、按钮和 Logo 占位已从 `rounded-xl` 收为 `rounded-lg`,减少通用 SaaS 模板感。
|
||||||
- `app/register/page.tsx`:注册页会读取 URL 上的 `invite` 参数并随注册请求提交;无邀请参数时提示用户使用邀请链接或联系管理员开通账号。
|
- `app/register/page.tsx`:注册页会读取 URL 上的 `invite` 参数并随注册请求提交;无邀请参数时提示用户使用邀请链接或联系管理员开通账号。
|
||||||
- `app/register/page.tsx`:注册页已和登录页一样读取系统名称、登录 Logo 和注册开关;无邀请码且公开注册关闭时不再展示完整自助注册表单,只提示使用邀请链接或联系管理员。
|
- `app/register/page.tsx`:注册页已和登录页一样读取系统名称和登录 Logo;无邀请码时不展示完整自助注册表单,只提示使用邀请链接或联系管理员。
|
||||||
- `app/api/auth/register/route.ts`:关闭公开注册时不再直接挡掉邀请链接;有效邀请码仍可完成注册并记录使用次数,无邀请码仍拒绝公开注册。
|
- `app/api/auth/register/route.ts`:关闭公开注册时不再直接挡掉邀请链接;有效邀请码仍可完成注册并记录使用次数,无邀请码仍拒绝公开注册。
|
||||||
- `app/api/auth/register/__tests__/route.test.ts`:新增测试覆盖“关闭公开注册时无邀请码拒绝、有有效邀请码允许注册”的私有化账号入口。
|
- `app/api/auth/register/__tests__/route.test.ts`:新增测试覆盖“关闭公开注册时无邀请码拒绝、有有效邀请码允许注册”的私有化账号入口。
|
||||||
- `app/register/page.tsx:21`:注册页已改为和登录页一致的浅灰背景。
|
- `app/register/page.tsx:21`:注册页已改为和登录页一致的浅灰背景。
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user