Artifact 3ecf300708844e7c5b6b3e805c1b45ded4614da8fc80dc7476d95039f72b4c3c:
- File
web/src/pages/Login.tsx
— part of check-in
[dfa747c1ad]
at
2026-10-23 06:08:28
on branch trunk
— Web 管理控制台
- 用 Vite 和 React 做完整的 Web 端:登录、按权限显示菜单、切换当前作业仓库 - 覆盖来肯同步、仓库、库位规划、商品、销售订单、采购入库与批次码、采购订单、库存、用户授权和审计日志 - 开发时由 Vite 把 /api 代理到本机后端 - SQLite 写入和页面读取冲突时自动重试,避免请求进程因数据库忙碌直接崩溃 (user: pluto size: 1617)
import { useState, type FormEvent } from 'react' import { Banner, Field } from '../ui' import { useSession } from '../session' export function Login() { const { login } = useSession() const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [error, setError] = useState('') const [pending, setPending] = useState(false) async function onSubmit(event: FormEvent) { event.preventDefault() setPending(true) setError('') try { await login(username, password) } catch (err) { setError(err instanceof Error ? err.message : '登录失败') } finally { setPending(false) } } return ( <div className="login-screen"> <div className="login-card"> <h1>SwiftFlow</h1> <p className="sub">仓储管理控制台</p> <form onSubmit={onSubmit}> <Banner kind="error" text={error} /> <Field label="账号"> <input autoFocus autoComplete="username" value={username} onChange={(event) => setUsername(event.target.value)} /> </Field> <Field label="密码"> <input type="password" autoComplete="current-password" value={password} onChange={(event) => setPassword(event.target.value)} /> </Field> <button type="submit" disabled={pending || !username || !password}> {pending ? '正在登录…' : '登录'} </button> </form> </div> </div> ) }