diff --git a/web/src/index.css b/web/src/index.css index 03d34e6..087f399 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -124,6 +124,17 @@ input:-webkit-autofill:active { transition: background-color 50000s ease-in-out 0s; } +.login-dark-label { + display: block; + font-size: 12px; + font-weight: 600; + color: #cbd5e1; +} + +.login-form .ant-form-item .ant-form-item-label > label { + color: #cbd5e1; +} + .login-dark-input, .login-dark-input.ant-input-affix-wrapper, .login-dark-input.ant-input { diff --git a/web/src/pages/Login.tsx b/web/src/pages/Login.tsx index 50fc181..0d24bf4 100644 --- a/web/src/pages/Login.tsx +++ b/web/src/pages/Login.tsx @@ -1,72 +1,39 @@ -import { useState } from 'react' -import { Form, Input, Button, message } from 'antd' -import { - UserOutlined, LockOutlined, - SafetyCertificateOutlined, CrownOutlined, ArrowRightOutlined, - CheckCircleFilled, CustomerServiceOutlined, -} from '@ant-design/icons' -import { useNavigate } from 'react-router-dom' +import { useEffect, useState } from 'react' +import { Button, Form, Input, message } from 'antd' +import { UserOutlined, LockOutlined, ArrowRightOutlined, CheckCircleFilled } from '@ant-design/icons' +import { useNavigate, useSearchParams } from 'react-router-dom' import { useAuth } from '@/stores/auth' import { Logo, LogoIcon } from '@/components/common/Logo' -type DemoRole = { - key: string - title: string - username: string - pass: string - icon: typeof CrownOutlined +/** 历史版本遗留的记住密码/演示账号本地数据,进入登录页时统一清理 */ +function cleanupLegacyCredentials() { + const keys = ['kefu_remember_me', 'kefu_saved_username', 'kefu_saved_password'] + keys.forEach(key => localStorage.removeItem(key)) } -const demoRoles: DemoRole[] = [ - { key: 'tenant', title: '租户管理', username: 'kefu_admin', pass: 'kefu_admin123', icon: CrownOutlined }, - { key: 'admin', title: '平台管理', username: 'platform_admin', pass: 'kefu_admin123', icon: SafetyCertificateOutlined }, - { key: 'agent', title: '坐席人员', username: 'agent1', pass: 'kefu_admin123', icon: CustomerServiceOutlined }, -] - const Login = () => { const [form] = Form.useForm() const [loading, setLoading] = useState(false) - const [selectedRole, setSelectedRole] = useState('tenant') - - // 记住密码状态持久化 - const [remember, setRemember] = useState(() => { - return localStorage.getItem('kefu_remember_me') === 'true' - }) - - const [username, setUsername] = useState(() => { - const isRemembered = localStorage.getItem('kefu_remember_me') === 'true' - if (isRemembered) { - return localStorage.getItem('kefu_saved_username') || 'kefu_admin' - } - return 'kefu_admin' - }) - - const [password, setPassword] = useState(() => { - const isRemembered = localStorage.getItem('kefu_remember_me') === 'true' - if (isRemembered) { - return localStorage.getItem('kefu_saved_password') || 'kefu_admin123' - } - return 'kefu_admin123' - }) + const [searchParams] = useSearchParams() + const expired = searchParams.get('expired') === '1' const { login } = useAuth() const navigate = useNavigate() - const onFinish = async (values: { username?: string; password?: string }) => { + useEffect(() => { + cleanupLegacyCredentials() + }, []) + + useEffect(() => { + if (expired) { + message.warning('登录已过期,请重新登录') + } + }, [expired]) + + const onFinish = async (values: { username: string; password: string }) => { setLoading(true) - const u = (values.username || username).trim() - const p = (values.password || password).trim() try { - const user = await login(u, p) - if (remember) { - localStorage.setItem('kefu_remember_me', 'true') - localStorage.setItem('kefu_saved_username', u) - localStorage.setItem('kefu_saved_password', p) - } else { - localStorage.removeItem('kefu_remember_me') - localStorage.removeItem('kefu_saved_username') - localStorage.removeItem('kefu_saved_password') - } + const user = await login(values.username.trim(), values.password) message.success('登录成功') navigate(user.role === 'platform_admin' ? '/admin/dashboard' : '/agent/dashboard', { replace: true }) } catch { @@ -76,13 +43,6 @@ const Login = () => { } } - const selectDemoRole = (role: DemoRole) => { - setSelectedRole(role.key) - setUsername(role.username) - setPassword(role.pass) - form.setFieldsValue({ username: role.username, password: role.pass }) - } - return (
{/* 科技感深邃渐变背景 */} @@ -105,107 +65,58 @@ const Login = () => { {/* 核心登录卡片 */}
-
+
{/* 顶端亮色发光描边 */}
{/* 卡片头部 */} -
-
- +
+
+

登录客服云平台

-

全渠道多租户智能客服与运营管理

-
- - {/* 顶部一键填入演示账号切换 Tab */} -
-
- 快捷填入演示账号: - 点击自动填入 -
-
- {demoRoles.map(role => { - const Icon = role.icon - const active = selectedRole === role.key - return ( - - ) - })} -
+

全渠道多租户智能客服与运营管理

{/* 登录表单 */} -
+ 账号} name="username" rules={[{ required: true, message: '请输入用户名' }]} - className="!mb-4" + className="!mb-5" > -
- - { - setUsername(e.target.value) - form.setFieldsValue({ username: e.target.value }) - }} - prefix={} - placeholder="请输入登录账号" - className="login-dark-input !h-11 !rounded-xl !text-slate-100 placeholder:!text-slate-500 transition-all text-sm" - /> -
+ } + placeholder="请输入登录账号" + className="login-dark-input !h-11 !rounded-xl !text-slate-100 placeholder:!text-slate-500 transition-all text-sm" + />
密码} name="password" rules={[{ required: true, message: '请输入密码' }]} - className="!mb-4" + className="!mb-7" > -
- - { - setPassword(e.target.value) - form.setFieldsValue({ password: e.target.value }) - }} - prefix={} - placeholder="请输入登录密码" - className="login-dark-input !h-11 !rounded-xl !text-slate-100 placeholder:!text-slate-500 transition-all text-sm" - /> -
+ } + placeholder="请输入登录密码" + className="login-dark-input !h-11 !rounded-xl !text-slate-100 placeholder:!text-slate-500 transition-all text-sm" + />
- {/* 记住密码勾选栏 */} -
- - - 忘记密码请联系管理员 - -
- - + + +

+ 忘记密码请联系平台管理员 +