Artifact c19521e83487440d2da576845ba16cea6e50f4afc1de90bac3b89c33d417d37d:
- File
web/src/session.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: 2049)
import { createContext, useContext, useEffect, useState, type ReactNode, } from 'react' import { TOKEN_KEY, api, type SessionUser } from './api' type SessionValue = { user: SessionUser | null loading: boolean login: (username: string, password: string) => Promise<void> logout: () => Promise<void> setUser: (user: SessionUser) => void } const SessionContext = createContext<SessionValue | null>(null) export function SessionProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState<SessionUser | null>(null) const [loading, setLoading] = useState(true) useEffect(() => { const token = localStorage.getItem(TOKEN_KEY) if (!token) { setLoading(false) return } api<{ user: SessionUser }>('/api/auth/me') .then((data) => setUser(data.user)) .catch(() => { localStorage.removeItem(TOKEN_KEY) setUser(null) }) .finally(() => setLoading(false)) }, []) useEffect(() => { const onUnauthorized = () => setUser(null) window.addEventListener('swiftflow-unauthorized', onUnauthorized) return () => window.removeEventListener('swiftflow-unauthorized', onUnauthorized) }, []) async function login(username: string, password: string) { const data = await api<{ token: string; user: SessionUser }>('/api/auth/login', { method: 'POST', body: JSON.stringify({ username, password, terminal: 'web' }), }) localStorage.setItem(TOKEN_KEY, data.token) setUser(data.user) } async function logout() { try { await api('/api/auth/logout', { method: 'POST' }) } catch { // 令牌已经失效时,本地仍然退出。 } localStorage.removeItem(TOKEN_KEY) setUser(null) } return ( <SessionContext.Provider value={{ user, loading, login, logout, setUser }}> {children} </SessionContext.Provider> ) } export function useSession() { const value = useContext(SessionContext) if (!value) throw new Error('SessionProvider 缺失') return value }