Login.tsx
4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { login } from '@/api/usr'
import { BizError } from '@/api/request'
import { useAppDispatch, useAppSelector } from '@/store'
import { loginSucceeded } from '@/store/auth'
import { IconAntler, IconAvatar, IconLock } from '@/components/icons'
import type { ErrorPayload } from '@/api/types'
export default function Login() {
const navigate = useNavigate()
const dispatch = useAppDispatch()
const existingToken = useAppSelector(s => s.auth.token)
const [userName, setUserName] = useState('')
const [password, setPassword] = useState('')
const [version] = useState<'standard'>('standard')
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState('')
useEffect(() => {
if (existingToken) navigate('/', { replace: true })
}, [existingToken, navigate])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!userName.trim() || !password) {
setError('请输入用户名和密码')
return
}
setError('')
setSubmitting(true)
try {
const res = await login({ sUserName: userName.trim(), sPassword: password, sVersion: version })
dispatch(loginSucceeded({ token: res.accessToken, user: res.user }))
navigate('/', { replace: true })
} catch (err) {
if (err instanceof BizError) {
if (err.code === 40101) setError('用户名或密码错误')
else if (err.code === 40301) {
const payload = err.payload as ErrorPayload | undefined
const sec = payload?.cooldownSeconds
setError(`账户已锁定,请 ${sec ? Math.ceil(sec / 60) + ' 分钟' : '稍后'}后重试`)
} else if (err.code === 40010) setError(err.message || '请求参数无效')
else setError(err.message || '登录失败')
} else {
setError('网络错误,请检查后端服务')
}
} finally {
setSubmitting(false)
}
}
return (
<div className="login-wrap">
<div className="login-head">
<span className="lg" style={{ color: '#0e1216' }}>
<IconAntler width={42} height={42} />
</span>
<span className="name">Antler ERP</span>
<span className="sub">欢迎登录EBC平台</span>
</div>
<form className="login-hero" onSubmit={handleSubmit}>
<div className="login-text">
<div className="en">Enterprise Business Capability</div>
<div className="zh">企业业务能力平台</div>
<div className="erp">ERP</div>
</div>
<div className="login-card">
<h3>用户登录</h3>
<div className="lf">
<span className="ic"><IconAvatar /></span>
<span className="div"></span>
<input
type="text"
placeholder="请输入你的用户名"
value={userName}
onChange={e => setUserName(e.target.value)}
autoFocus
/>
</div>
<div className="lf">
<span className="ic"><IconLock /></span>
<span className="div"></span>
<input
type="password"
placeholder="请输入你的密码"
value={password}
onChange={e => setPassword(e.target.value)}
/>
</div>
<div className="lf dropdown">
<input type="text" value="标准版" readOnly style={{ cursor: 'pointer' }} />
</div>
<div className="err">{error}</div>
<button className="submit" type="submit" disabled={submitting}>
{submitting ? '登 录 中…' : '登 录'}
</button>
</div>
</form>
<div className="login-foot">
🛠 ©Copyright Antler Software | 印刷智慧工厂 | 印刷MES | 印刷ERP | 印刷电商平台 | 文件智能处理 | 印前自动化 | 400-880-6237
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, marginLeft: 6 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="#3a6cb6">
<path d="M12 2l9 4v6c0 5-4 9-9 10-5-1-9-5-9-10V6z" />
</svg>
沪ICP备14034791号-1
</span>
</div>
</div>
)
}