feature: 新增全新登录页布局与主题切换入口
This commit is contained in:
+278
-159
@@ -1,10 +1,12 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Button, Card, Space, Typography, message, Spin, Form, Input, Tabs } from 'antd';
|
import { Alert, Button, Card, Col, Divider, Form, Input, Layout, Row, Space, Spin, Tag, Typography, message, theme } from 'antd';
|
||||||
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
import { BookOutlined, LockOutlined, RobotOutlined, SafetyCertificateOutlined, TeamOutlined, ThunderboltOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
import { authApi } from '../services/api';
|
import { authApi } from '../services/api';
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
import AnnouncementModal from '../components/AnnouncementModal';
|
import AnnouncementModal from '../components/AnnouncementModal';
|
||||||
|
|
||||||
|
import ThemeSwitch from '../components/ThemeSwitch';
|
||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
@@ -15,8 +17,11 @@ export default function Login() {
|
|||||||
const [localAuthEnabled, setLocalAuthEnabled] = useState(false);
|
const [localAuthEnabled, setLocalAuthEnabled] = useState(false);
|
||||||
const [linuxdoEnabled, setLinuxdoEnabled] = useState(false);
|
const [linuxdoEnabled, setLinuxdoEnabled] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const alphaColor = (color: string, alpha: number) => `color-mix(in srgb, ${color} ${(alpha * 100).toFixed(0)}%, transparent)`;
|
||||||
|
const primaryButtonShadow = `0 8px 20px ${alphaColor(token.colorPrimary, 0.28)}`;
|
||||||
|
const hoverButtonShadow = `0 12px 28px ${alphaColor(token.colorPrimary, 0.36)}`;
|
||||||
const [showAnnouncement, setShowAnnouncement] = useState(false);
|
const [showAnnouncement, setShowAnnouncement] = useState(false);
|
||||||
const [activeLoginMethod, setActiveLoginMethod] = useState<'local' | 'linuxdo'>('local');
|
|
||||||
|
|
||||||
// 检查是否已登录和获取认证配置
|
// 检查是否已登录和获取认证配置
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -97,9 +102,9 @@ export default function Login() {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
minHeight: '100vh',
|
minHeight: '100vh',
|
||||||
background: 'var(--color-bg-base)',
|
background: token.colorBgLayout,
|
||||||
}}>
|
}}>
|
||||||
<Spin size="large" style={{ color: 'var(--color-primary)' }} />
|
<Spin size="large" style={{ color: token.colorPrimary }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -108,47 +113,52 @@ export default function Login() {
|
|||||||
const renderLocalLogin = () => (
|
const renderLocalLogin = () => (
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
|
layout="vertical"
|
||||||
onFinish={handleLocalLogin}
|
onFinish={handleLocalLogin}
|
||||||
size="large"
|
size="large"
|
||||||
style={{ marginTop: '24px' }}
|
style={{ marginTop: '16px' }}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="username"
|
name="username"
|
||||||
rules={[{ required: true, message: '请输入用户名' }]}
|
label="管理账号"
|
||||||
|
rules={[{ required: true, message: '请输入管理账号' }]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
prefix={<UserOutlined style={{ color: '#999' }} />}
|
prefix={<UserOutlined style={{ color: token.colorTextTertiary }} />}
|
||||||
placeholder="用户名"
|
placeholder="请输入管理账号"
|
||||||
autoComplete="username"
|
autoComplete="username"
|
||||||
|
style={{ height: 46, borderRadius: 12 }}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="password"
|
name="password"
|
||||||
rules={[{ required: true, message: '请输入密码' }]}
|
label="访问密钥"
|
||||||
|
rules={[{ required: true, message: '请输入访问密钥' }]}
|
||||||
>
|
>
|
||||||
<Input.Password
|
<Input.Password
|
||||||
prefix={<LockOutlined style={{ color: '#999' }} />}
|
prefix={<LockOutlined style={{ color: token.colorTextTertiary }} />}
|
||||||
placeholder="密码"
|
placeholder="请输入访问密钥"
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
|
style={{ height: 46, borderRadius: 12 }}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item style={{ marginBottom: 0 }}>
|
<Form.Item style={{ marginBottom: 0, marginTop: 8 }}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
block
|
block
|
||||||
style={{
|
style={{
|
||||||
height: 48,
|
height: 46,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
background: 'var(--color-primary)',
|
background: `linear-gradient(90deg, ${token.colorPrimary} 0%, ${alphaColor(token.colorPrimary, 0.86)} 100%)`,
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
boxShadow: 'var(--shadow-primary)',
|
boxShadow: primaryButtonShadow,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
登录
|
登录系统
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
@@ -156,7 +166,7 @@ export default function Login() {
|
|||||||
|
|
||||||
// 渲染LinuxDO登录
|
// 渲染LinuxDO登录
|
||||||
const renderLinuxDOLogin = () => (
|
const renderLinuxDOLogin = () => (
|
||||||
<div style={{ padding: '24px 0 8px' }}>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -176,25 +186,25 @@ export default function Login() {
|
|||||||
onClick={handleLinuxDOLogin}
|
onClick={handleLinuxDOLogin}
|
||||||
block
|
block
|
||||||
style={{
|
style={{
|
||||||
height: 52,
|
height: 46,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
background: 'var(--color-primary)',
|
background: `linear-gradient(90deg, ${token.colorPrimary} 0%, ${alphaColor(token.colorPrimary, 0.86)} 100%)`,
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
boxShadow: 'var(--shadow-primary)',
|
boxShadow: primaryButtonShadow,
|
||||||
transition: 'all 0.3s ease',
|
transition: 'all 0.3s ease',
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
e.currentTarget.style.transform = 'translateY(-2px)';
|
e.currentTarget.style.transform = 'translateY(-2px)';
|
||||||
e.currentTarget.style.boxShadow = 'var(--shadow-elevated)';
|
e.currentTarget.style.boxShadow = hoverButtonShadow;
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
e.currentTarget.style.transform = 'translateY(0)';
|
e.currentTarget.style.transform = 'translateY(0)';
|
||||||
e.currentTarget.style.boxShadow = 'var(--shadow-primary)';
|
e.currentTarget.style.boxShadow = primaryButtonShadow;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
使用 LinuxDO 登录
|
使用 LinuxDO OAuth 登录
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -216,11 +226,34 @@ export default function Login() {
|
|||||||
localStorage.setItem('announcement_hide_forever', 'true');
|
localStorage.setItem('announcement_hide_forever', 'true');
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentLoginMethod = localAuthEnabled && linuxdoEnabled
|
const loginTips = [
|
||||||
? activeLoginMethod
|
'本地登录默认账号:admin / admin123',
|
||||||
: localAuthEnabled
|
'首次 LinuxDO 登录会自动创建账号',
|
||||||
? 'local'
|
'系统采用多用户数据隔离机制,每位用户拥有独立的创作空间与配置。',
|
||||||
: 'linuxdo';
|
];
|
||||||
|
|
||||||
|
const featureItems = [
|
||||||
|
{
|
||||||
|
icon: <RobotOutlined />,
|
||||||
|
title: '多 AI 模型协同',
|
||||||
|
description: '支持 OpenAI、Gemini、Claude 等主流模型,按场景灵活切换。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <ThunderboltOutlined />,
|
||||||
|
title: '智能向导驱动',
|
||||||
|
description: '自动生成大纲、角色与世界观,快速搭建完整故事骨架。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <TeamOutlined />,
|
||||||
|
title: '角色组织管理',
|
||||||
|
description: '人物关系、组织架构可视化管理,复杂设定也能清晰掌控。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <BookOutlined />,
|
||||||
|
title: '章节创作闭环',
|
||||||
|
description: '支持章节生成、编辑、重写与润色,持续提升内容质量。',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -230,155 +263,241 @@ export default function Login() {
|
|||||||
onDoNotShowToday={handleDoNotShowToday}
|
onDoNotShowToday={handleDoNotShowToday}
|
||||||
onNeverShow={handleNeverShow}
|
onNeverShow={handleNeverShow}
|
||||||
/>
|
/>
|
||||||
<div style={{
|
<Layout style={{ minHeight: '100vh', background: token.colorBgLayout }}>
|
||||||
display: 'flex',
|
<div
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
minHeight: '100vh',
|
|
||||||
background: 'var(--color-bg-base)',
|
|
||||||
padding: '20px',
|
|
||||||
position: 'relative',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}>
|
|
||||||
{/* 装饰性背景元素 */}
|
|
||||||
<div style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: '-10%',
|
|
||||||
right: '-5%',
|
|
||||||
width: '400px',
|
|
||||||
height: '400px',
|
|
||||||
background: 'var(--color-primary)',
|
|
||||||
opacity: 0.1,
|
|
||||||
borderRadius: '50%',
|
|
||||||
filter: 'blur(60px)',
|
|
||||||
}} />
|
|
||||||
<div style={{
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: '-10%',
|
|
||||||
left: '-5%',
|
|
||||||
width: '350px',
|
|
||||||
height: '350px',
|
|
||||||
background: 'var(--color-success)',
|
|
||||||
opacity: 0.08,
|
|
||||||
borderRadius: '50%',
|
|
||||||
filter: 'blur(60px)',
|
|
||||||
}} />
|
|
||||||
|
|
||||||
<Card
|
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
position: 'fixed',
|
||||||
maxWidth: 420,
|
top: 20,
|
||||||
background: 'var(--color-bg-container)',
|
right: 20,
|
||||||
backdropFilter: 'blur(20px)',
|
zIndex: 10,
|
||||||
WebkitBackdropFilter: 'blur(20px)',
|
padding: '8px 10px',
|
||||||
boxShadow: 'var(--shadow-card)',
|
borderRadius: 12,
|
||||||
border: '1px solid var(--color-border)',
|
background: alphaColor(token.colorBgContainer, 0.9),
|
||||||
borderRadius: '16px',
|
border: `1px solid ${token.colorBorderSecondary}`,
|
||||||
position: 'relative',
|
backdropFilter: 'blur(6px)',
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
bodyStyle={{
|
|
||||||
padding: '40px 32px',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Space direction="vertical" size="large" style={{ width: '100%', textAlign: 'center' }}>
|
<ThemeSwitch size="small" />
|
||||||
{/* Logo区域 */}
|
</div>
|
||||||
<div style={{ marginBottom: '8px' }}>
|
<Row style={{ minHeight: '100vh' }}>
|
||||||
<div style={{
|
<Col xs={0} lg={11}>
|
||||||
width: '72px',
|
<section
|
||||||
height: '72px',
|
style={{
|
||||||
margin: '0 auto 20px',
|
height: '100%',
|
||||||
background: 'var(--color-primary)',
|
padding: '44px 64px 88px',
|
||||||
borderRadius: '20px',
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundColor: alphaColor(token.colorBgContainer, 0.78),
|
||||||
|
backgroundImage: `linear-gradient(${alphaColor(token.colorTextSecondary, 0.06)} 1px, transparent 1px), linear-gradient(90deg, ${alphaColor(token.colorTextSecondary, 0.06)} 1px, transparent 1px)`,
|
||||||
|
backgroundSize: '68px 68px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
background: `radial-gradient(circle at 25% 20%, ${alphaColor(token.colorPrimary, 0.12)} 0%, transparent 50%)`,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
gap: 34,
|
||||||
|
width: '100%',
|
||||||
|
// flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Space align="center" size={14}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 46,
|
||||||
|
height: 46,
|
||||||
|
borderRadius: 14,
|
||||||
|
background: `linear-gradient(135deg, ${token.colorPrimary} 0%, ${alphaColor(token.colorPrimary, 0.7)} 100%)`,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
boxShadow: 'var(--shadow-primary)',
|
boxShadow: primaryButtonShadow,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src="/logo.svg"
|
src="/logo.svg"
|
||||||
alt="Logo"
|
alt="MuMuAINovel"
|
||||||
style={{
|
style={{ width: 26, height: 26, filter: 'brightness(0) invert(1)' }}
|
||||||
width: '48px',
|
|
||||||
height: '48px',
|
|
||||||
filter: 'brightness(0) invert(1)',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Title level={2} style={{
|
<Title level={3} style={{ margin: 0, color: token.colorText }}>
|
||||||
marginBottom: 8,
|
MuMuAINovel
|
||||||
color: 'var(--color-primary)',
|
|
||||||
fontWeight: 700,
|
|
||||||
}}>
|
|
||||||
AI小说创作助手
|
|
||||||
</Title>
|
</Title>
|
||||||
<Paragraph style={{
|
</Space>
|
||||||
color: 'var(--color-text-secondary)',
|
|
||||||
fontSize: '14px',
|
<Space direction="vertical" size={32} style={{ width: '100%' }}>
|
||||||
|
<div style={{ maxWidth: 'min(860px, 100%)' }}>
|
||||||
|
<Title
|
||||||
|
level={1}
|
||||||
|
style={{
|
||||||
|
marginBottom: 22,
|
||||||
|
color: token.colorText,
|
||||||
|
lineHeight: 1.12,
|
||||||
|
fontWeight: 800,
|
||||||
|
fontSize: 'clamp(52px, 3vw, 78px)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
基于 AI 的
|
||||||
|
<br />
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
backgroundImage: `linear-gradient(90deg, ${token.colorPrimary} 0%, #d946ef 100%)`,
|
||||||
|
WebkitBackgroundClip: 'text',
|
||||||
|
backgroundClip: 'text',
|
||||||
|
WebkitTextFillColor: 'transparent',
|
||||||
|
color: token.colorPrimary,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
智能小说创作助手
|
||||||
|
</span>
|
||||||
|
</Title>
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
fontSize: 'clamp(18px, 1vw, 22px)',
|
||||||
|
lineHeight: 1.85,
|
||||||
|
color: token.colorTextSecondary,
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
}}>
|
maxWidth: 800,
|
||||||
{localAuthEnabled && linuxdoEnabled ? '选择登录方式' :
|
}}
|
||||||
localAuthEnabled ? '使用账户密码登录' :
|
>
|
||||||
'使用 LinuxDO 账号登录'}
|
从灵感到成稿,围绕「多模型协同、创作流程自动化、角色关系管理、章节精修」构建一体化创作工作台。
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 登录方式 */}
|
<Row gutter={[20, 20]} style={{ width: '100%', maxWidth: 'min(920px, 100%)' }}>
|
||||||
{localAuthEnabled && linuxdoEnabled ? (
|
{featureItems.map((item) => (
|
||||||
<Tabs
|
<Col span={12} key={item.title}>
|
||||||
activeKey={activeLoginMethod}
|
<Card
|
||||||
onChange={(key) => setActiveLoginMethod(key as 'local' | 'linuxdo')}
|
size="small"
|
||||||
centered
|
bordered={false}
|
||||||
items={[
|
style={{
|
||||||
{
|
height: '100%',
|
||||||
key: 'local',
|
minHeight: 120,
|
||||||
label: '账户密码',
|
borderRadius: 16,
|
||||||
children: renderLocalLogin(),
|
background: alphaColor(token.colorBgContainer, 0.9),
|
||||||
},
|
}}
|
||||||
{
|
bodyStyle={{ padding: 16 }}
|
||||||
key: 'linuxdo',
|
>
|
||||||
label: 'LinuxDO',
|
<Space direction="vertical" size={8}>
|
||||||
children: renderLinuxDOLogin(),
|
<Space size={10} style={{ color: token.colorPrimary, fontWeight: 700, fontSize: 15 }}>
|
||||||
},
|
{item.icon}
|
||||||
]}
|
<span>{item.title}</span>
|
||||||
/>
|
</Space>
|
||||||
) : localAuthEnabled ? (
|
<Paragraph style={{ marginBottom: 0, color: token.colorTextSecondary, fontSize: 14, lineHeight: 1.65 }}>
|
||||||
renderLocalLogin()
|
{item.description}
|
||||||
) : (
|
|
||||||
renderLinuxDOLogin()
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 提示信息 */}
|
|
||||||
<div style={{
|
|
||||||
padding: '16px',
|
|
||||||
background: 'rgba(77, 128, 136, 0.08)',
|
|
||||||
borderRadius: '12px',
|
|
||||||
border: '1px solid var(--color-border)',
|
|
||||||
}}>
|
|
||||||
<Paragraph style={{
|
|
||||||
fontSize: 13,
|
|
||||||
color: 'var(--color-text-secondary)',
|
|
||||||
marginBottom: 0,
|
|
||||||
lineHeight: 1.6,
|
|
||||||
}}>
|
|
||||||
{currentLoginMethod === 'linuxdo' ? (
|
|
||||||
<>
|
|
||||||
🎉 首次登录将自动创建账号
|
|
||||||
<br />
|
|
||||||
🔒 每个用户拥有独立的数据空间
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
🧪 默认账号:admin / admin123
|
|
||||||
<br />
|
|
||||||
🔒 每个用户拥有独立的数据空间
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</div>
|
|
||||||
</Space>
|
</Space>
|
||||||
</Card>
|
</Card>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<Space size={[10, 14]} wrap style={{ maxWidth: 'min(860px, 100%)' }}>
|
||||||
|
<Tag color="blue">OpenAI</Tag>
|
||||||
|
<Tag color="geekblue">Gemini</Tag>
|
||||||
|
<Tag color="purple">Claude</Tag>
|
||||||
|
<Tag color="cyan">LinuxDO OAuth</Tag>
|
||||||
|
<Tag color="green">Docker Compose</Tag>
|
||||||
|
<Tag color="gold">PostgreSQL</Tag>
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
fontSize: 12,
|
||||||
|
color: token.colorTextTertiary,
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 1,
|
||||||
|
letterSpacing: 0.4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
© 2026 MuMuAINovel · GPLv3 License
|
||||||
|
</Paragraph>
|
||||||
|
</section>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col xs={24} lg={13}>
|
||||||
|
<section
|
||||||
|
style={{
|
||||||
|
minHeight: '100vh',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: '48px min(7vw, 72px)',
|
||||||
|
background: token.colorBgLayout,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: '100%', maxWidth: 480 }}>
|
||||||
|
<Space direction="vertical" size={4}>
|
||||||
|
<Title level={2} style={{ marginBottom: 0, fontWeight: 700, color: token.colorText }}>
|
||||||
|
欢迎回来
|
||||||
|
</Title>
|
||||||
|
<Paragraph style={{ marginBottom: 0, color: token.colorTextSecondary }}>
|
||||||
|
登录 MuMuAINovel,继续你的小说创作项目。
|
||||||
|
</Paragraph>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<div style={{ marginTop: 22 }}>
|
||||||
|
{localAuthEnabled ? renderLocalLogin() : null}
|
||||||
|
|
||||||
|
{linuxdoEnabled && localAuthEnabled ? (
|
||||||
|
<>
|
||||||
|
<Divider style={{ margin: '18px 0 16px' }}>或</Divider>
|
||||||
|
{renderLinuxDOLogin()}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{!localAuthEnabled && linuxdoEnabled ? renderLinuxDOLogin() : null}
|
||||||
|
|
||||||
|
{!localAuthEnabled && !linuxdoEnabled ? (
|
||||||
|
<Alert
|
||||||
|
type="warning"
|
||||||
|
showIcon
|
||||||
|
message="当前未启用可用登录方式"
|
||||||
|
description="请联系管理员在系统配置中启用本地登录或 LinuxDO OAuth 登录。"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<Divider style={{ margin: '20px 0 14px' }} />
|
||||||
|
<Alert
|
||||||
|
type="info"
|
||||||
|
showIcon
|
||||||
|
icon={<SafetyCertificateOutlined />}
|
||||||
|
style={{ background: alphaColor(token.colorPrimary, 0.06), borderRadius: 12 }}
|
||||||
|
message="登录说明"
|
||||||
|
description={(
|
||||||
|
<ul style={{ margin: 0, paddingLeft: 18 }}>
|
||||||
|
{loginTips.map((tip) => (
|
||||||
|
<li key={tip} style={{ marginBottom: 4 }}>
|
||||||
|
{tip}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Layout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user