Artifact 8682882c52fbaff380281d036e3dc59817ed23cd4bff7995372a703c44ce4db1:
- File
web/src/pages/Warehouses.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: 2574)
import { useEffect, useState } from 'react' import { api, type Warehouse } from '../api' import { useSession } from '../session' import { Banner, Empty, Page } from '../ui' export function Warehouses() { const { user, setUser } = useSession() const [rows, setRows] = useState<Warehouse[]>([]) const [error, setError] = useState('') useEffect(() => { api<{ warehouses: Warehouse[] }>('/api/warehouses') .then((data) => setRows(data.warehouses)) .catch((err: unknown) => setError(err instanceof Error ? err.message : '加载失败')) }, []) async function select(row: Warehouse) { setError('') try { const data = await api<{ user: NonNullable<typeof user> }>('/api/auth/warehouse', { method: 'POST', body: JSON.stringify({ warehouse_id: row.id }), }) setUser(data.user) } catch (err) { setError(err instanceof Error ? err.message : '切换失败') } } return ( <Page title="仓库"> <Banner kind="error" text={error} /> <p className="muted">未列入库存采集范围的仓库只作显示,不能建库位,也不能作为作业仓库。</p> {rows.length === 0 ? ( <Empty text="还没有仓库。同步来肯单据后,仓库会随单据写入。" /> ) : ( <div className="table-wrap"> <table> <thead> <tr> <th>编码</th> <th>名称</th> <th>助记码</th> <th>用途</th> <th></th> </tr> </thead> <tbody> {rows.map((row) => ( <tr key={row.id}> <td className="mono">{row.code}</td> <td>{row.name}</td> <td>{row.easycode}</td> <td> <span className={row.operational ? 'tag ok' : 'tag'}> {row.operational ? '作业仓' : '仅显示'} </span> {user?.current_warehouse_id === row.id && <span className="tag ok">当前</span>} </td> <td className="row-actions"> {row.operational && user?.current_warehouse_id !== row.id && ( <button type="button" onClick={() => void select(row)}> 设为作业仓库 </button> )} </td> </tr> ))} </tbody> </table> </div> )} </Page> ) }