This commit is contained in:
魔方熊成祥
2026-04-29 21:38:16 +08:00
commit c7481718e4
45 changed files with 9530 additions and 0 deletions

227
src/pages/login/index.tsx Normal file
View File

@@ -0,0 +1,227 @@
import { useEffect, useState } from 'react'
import {
Button,
Card,
Checkbox,
Form,
Input,
Typography,
theme,
} from 'antd'
import {
LockOutlined,
LoginOutlined,
SafetyCertificateOutlined,
UserOutlined,
} from '@ant-design/icons'
import { useNavigate } from 'react-router-dom'
import { toast } from 'sonner'
import { apiUserLogin } from '@/apis/apisUser'
import { useUserStore } from '@/store/user'
const LOGIN_REMEMBER_KEY = 'mall-admin:remember-login'
interface LoginFormValues {
account: string
password: string
captcha: string
remember: boolean
}
interface RememberLoginData {
account: string
password: string
remember: boolean
}
const readRememberLogin = (): RememberLoginData => {
if (typeof window === 'undefined') {
return {
account: '',
password: '',
remember: true,
}
}
try {
const raw = window.localStorage.getItem(LOGIN_REMEMBER_KEY)
if (!raw) {
return {
account: '',
password: '',
remember: true,
}
}
const parsed = JSON.parse(raw) as Partial<RememberLoginData>
return {
account: parsed.account ?? '',
password: parsed.password ?? '',
remember: parsed.remember ?? true,
}
} catch {
return {
account: '',
password: '',
remember: true,
}
}
}
const persistRememberLogin = (values: RememberLoginData) => {
if (typeof window === 'undefined') {
return
}
if (!values.remember) {
window.localStorage.removeItem(LOGIN_REMEMBER_KEY)
return
}
window.localStorage.setItem(LOGIN_REMEMBER_KEY, JSON.stringify(values))
}
export default function LoginPage() {
const navigate = useNavigate()
const [form] = Form.useForm<LoginFormValues>()
const [loading, setLoading] = useState(false)
const token = useUserStore(state => state.token)
const setToken = useUserStore(state => state.setToken)
const { token: themeToken } = theme.useToken()
useEffect(() => {
if (token?.accessToken) {
navigate('/merchant-review', { replace: true })
return
}
form.setFieldsValue(readRememberLogin())
}, [form, navigate, token?.accessToken])
const onFinish = async (values: LoginFormValues) => {
try {
setLoading(true)
const res = await apiUserLogin({
account: values.account.trim(),
password: values.password,
captcha: values.captcha.trim(),
captchaId: '',
loginType: '0',
type: '0',
remember: values.remember,
})
persistRememberLogin({
account: values.account.trim(),
password: values.password,
remember: values.remember,
})
setToken(res.data)
toast.success('登录成功')
navigate('/merchant-review', { replace: true })
} catch (error) {
toast.error(error instanceof Error ? error.message : '登录失败')
} finally {
setLoading(false)
}
}
return (
<Card
bordered={false}
style={{
borderRadius: themeToken.borderRadiusLG,
boxShadow: '0 12px 40px rgba(0,0,0,0.08)',
}}
styles={{
body: {
padding: 22,
},
}}
>
<div style={{ marginBottom: 18 }}>
<Typography.Title level={3} style={{ marginTop: 4, marginBottom: 4 }}>
</Typography.Title>
</div>
<Form<LoginFormValues>
form={form}
layout="vertical"
requiredMark={false}
onFinish={onFinish}
initialValues={{
account: '',
password: '',
captcha: '',
remember: true,
}}
>
<Form.Item
name="account"
rules={[{ required: true, message: '请输入登陆账号' }]}
>
<Input placeholder="请输入登陆账号" autoComplete="username" prefix={<UserOutlined />} />
</Form.Item>
<Form.Item
name="password"
rules={[
{ required: true, message: '请输入登陆密码' },
]}
>
<Input.Password
placeholder="请输入登陆密码"
autoComplete="current-password"
prefix={<LockOutlined />}
/>
</Form.Item>
<Form.Item
name="captcha"
rules={[
{ required: true, message: '请输入谷歌验证码' },
]}
>
<Input
placeholder="谷歌验证码"
autoComplete="one-time-code"
inputMode="numeric"
prefix={<SafetyCertificateOutlined />}
/>
</Form.Item>
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 16,
}}
>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox></Checkbox>
</Form.Item>
<Button
type="link"
style={{ paddingInline: 0 }}
onClick={() => {
toast.info('忘记密码请联系管理员处理')
}}
>
?
</Button>
</div>
<Form.Item style={{ marginBottom: 0 }}>
<Button type="primary" htmlType="submit" block icon={<LoginOutlined />} loading={loading}>
</Button>
</Form.Item>
</Form>
</Card>
)
}