Artifact 75843bc6ddf913e9ca3260f000a23cbd9cb4312c800e2cb96cb89516b4116e12:
- File
web/src/pages/Inventory.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: 2959)
import { useEffect, useState } from 'react' import { api, qty, type Warehouse } from '../api' import { useSession } from '../session' import { Banner, Empty, Field, Page } from '../ui' type Batch = { location_code: string goods_code: string batch_no: string produced_on: string expires_on: string qty: number } export function Inventory() { const { user } = useSession() const [warehouses, setWarehouses] = useState<Warehouse[]>([]) const [warehouseId, setWarehouseId] = useState(0) const [rows, setRows] = useState<Batch[]>([]) const [error, setError] = useState('') useEffect(() => { api<{ warehouses: Warehouse[] }>('/api/warehouses') .then((data) => { const operational = data.warehouses.filter((row) => row.operational) setWarehouses(operational) const current = operational.find((row) => row.id === user?.current_warehouse_id) setWarehouseId((current ?? operational[0])?.id ?? 0) }) .catch((err: unknown) => setError(err instanceof Error ? err.message : '加载失败')) }, [user?.current_warehouse_id]) useEffect(() => { if (!warehouseId) return api<{ batches: Batch[] }>(`/api/inventory?warehouse_id=${warehouseId}`) .then((data) => setRows(data.batches)) .catch((err: unknown) => setError(err instanceof Error ? err.message : '库存加载失败')) }, [warehouseId]) return ( <Page title="库存"> <Banner kind="error" text={error} /> <Field label="作业仓库"> <select value={warehouseId || ''} onChange={(event) => setWarehouseId(Number(event.target.value))}> {warehouses.map((row) => ( <option key={row.id} value={row.id}> {row.name}({row.code}) </option> ))} </select> </Field> {warehouseId === 0 ? ( <Empty text="没有可查看库存的作业仓库" /> ) : rows.length === 0 ? ( <Empty text="这个仓库还没有批次库存。采购入库单上架后才会出现。" /> ) : ( <div className="table-wrap"> <table> <thead> <tr> <th>库位</th> <th>商品编码</th> <th>批次</th> <th>生产日期</th> <th>到期日</th> <th>数量</th> </tr> </thead> <tbody> {rows.map((row) => ( <tr key={`${row.location_code}-${row.batch_no}-${row.produced_on}`}> <td className="mono">{row.location_code}</td> <td className="mono">{row.goods_code}</td> <td className="mono">{row.batch_no}</td> <td>{row.produced_on}</td> <td>{row.expires_on}</td> <td>{qty(row.qty)}</td> </tr> ))} </tbody> </table> </div> )} </Page> ) }