初始提交:全国记者站管理系统
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import { useState } from 'react'
|
||||
import { ShieldCheck, LogIn, Loader2 } from 'lucide-react'
|
||||
import { useRole } from '../../context'
|
||||
import { api } from '../../api'
|
||||
|
||||
/**
|
||||
* 登录页面 — 支持工号/姓名登录,演示模式可切换角色
|
||||
*/
|
||||
export function LoginPage() {
|
||||
const { login, setRole } = useRole()
|
||||
const [code, setCode] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
const handleLogin = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (!code.trim()) { setError('请输入工号或姓名'); return }
|
||||
setLoading(true)
|
||||
setError('')
|
||||
try {
|
||||
const res = await api.auth.login(code.trim())
|
||||
login(res.token, res.role, res.name, res.station)
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : '登录失败')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDemo = (role: 'headquarters' | 'station' | 'reporter') => {
|
||||
const demoNames: Record<typeof role, { name: string; station: string | null }> = {
|
||||
headquarters: { name: '林致远', station: null },
|
||||
station: { name: '苏明远', station: '北京记者站' },
|
||||
reporter: { name: '林晓', station: '北京记者站' },
|
||||
}
|
||||
const demo = demoNames[role]
|
||||
localStorage.setItem('auth_role', role)
|
||||
localStorage.setItem('auth_name', demo.name)
|
||||
localStorage.setItem('auth_station', String(demo.station))
|
||||
setRole(role)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="login-page">
|
||||
<div className="login-card">
|
||||
<div className="login-header">
|
||||
<div className="login-logo">
|
||||
<ShieldCheck size={32} />
|
||||
</div>
|
||||
<h1>全国记者站管理系统</h1>
|
||||
<p>请输入工号或姓名登录</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleLogin} className="login-form">
|
||||
<div className="form-field">
|
||||
<label htmlFor="code">工号 / 姓名</label>
|
||||
<input
|
||||
id="code"
|
||||
type="text"
|
||||
value={code}
|
||||
onChange={e => setCode(e.target.value)}
|
||||
placeholder="如:PERSON_001 或 林晓"
|
||||
disabled={loading}
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
{error && <div className="login-error">{error}</div>}
|
||||
<button type="submit" className="login-btn" disabled={loading}>
|
||||
{loading ? <Loader2 size={18} className="spin" /> : <LogIn size={18} />}
|
||||
<span>{loading ? '登录中...' : '登 录'}</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="login-divider">
|
||||
<span>或使用演示模式</span>
|
||||
</div>
|
||||
|
||||
<div className="demo-buttons">
|
||||
<button onClick={() => handleDemo('reporter')} className="demo-btn">
|
||||
记者视角
|
||||
</button>
|
||||
<button onClick={() => handleDemo('station')} className="demo-btn">
|
||||
分站负责人
|
||||
</button>
|
||||
<button onClick={() => handleDemo('headquarters')} className="demo-btn">
|
||||
总部管理员
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="login-hint">
|
||||
<p>可尝试登录:PERSON_001(记者)、PERSON_006(分站负责人)、PERSON_007(总部管理员)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user