Artifact edc78ba93954d4875c3c00183efb6c25f479af14ae46da13a29292652ad3b1ad:
- File
web/src/pages/Documents.tsx
— part of check-in
[5ec5d40378]
at
2026-10-23 06:16:24
on branch trunk
— 上架推荐,并在 Web 控制台确认上架
- 同一批次优先集中;否则同品同到期日集中;新批次按到期先后放到相邻空库位 - 上架只在当前作业仓库进行,日期沿用该批次码已有的生产日期和到期日 - 采购入库单的批次码可进入上架页,没有库位时不推荐、也不能提交 (user: pluto size: 5819)
import { useEffect, useState } from 'react' import { Link, useNavigate, useParams } from 'react-router-dom' import { api, can, money, qty } from '../api' import { useSession } from '../session' import { Empty, Page, Pager } from '../ui' type Summary = { bill_id: number bill_code: string supplier_name: string warehouse_name: string warehouse_id: number bill_date: string status_name: string total_qty: number total_money: number remark: string } type Item = { bill_detail_id: number batch_code: string goods_code: string goods_name: string barcode: string base_qty: number base_unit: string position_code: string } const meta = { receipt: { title: '采购入库单', list: '/api/purchase-receipts', detail: '/api/purchase-receipts/detail', base: '/receipts', batch: true, }, order: { title: '采购订单', list: '/api/inbounds/pending', detail: '/api/inbounds/detail', base: '/inbounds', batch: false, }, } export function Documents({ kind }: { kind: 'receipt' | 'order' }) { const { billId } = useParams() if (billId) return <Detail kind={kind} billId={billId} /> return <List kind={kind} /> } function List({ kind }: { kind: 'receipt' | 'order' }) { const spec = meta[kind] const navigate = useNavigate() const [offset, setOffset] = useState(0) const [total, setTotal] = useState(0) const [rows, setRows] = useState<Summary[]>([]) const [error, setError] = useState('') const limit = 50 useEffect(() => { api<{ total: number; inbounds: Summary[] }>(`${spec.list}?limit=${limit}&offset=${offset}`) .then((data) => { setTotal(data.total) setRows(data.inbounds) }) .catch((err: unknown) => setError(err instanceof Error ? err.message : '加载失败')) }, [spec.list, offset]) return ( <Page title={spec.title}> {error && <p className="banner error">{error}</p>} {rows.length === 0 ? ( <Empty text="没有单据" /> ) : ( <div className="table-wrap"> <table> <thead> <tr> <th>单号</th> <th>供应商</th> <th>仓库</th> <th>日期</th> <th>状态</th> <th>数量</th> <th>金额</th> </tr> </thead> <tbody> {rows.map((row) => ( <tr key={row.bill_id} className="clickable" onClick={() => navigate(`${spec.base}/${row.bill_id}`)}> <td><Link to={`${spec.base}/${row.bill_id}`}>{row.bill_code}</Link></td> <td>{row.supplier_name}</td> <td>{row.warehouse_name}</td> <td>{row.bill_date}</td> <td>{row.status_name}</td> <td>{qty(row.total_qty)}</td> <td>{money(row.total_money)}</td> </tr> ))} </tbody> </table> </div> )} <Pager total={total} limit={limit} offset={offset} onPage={setOffset} /> </Page> ) } function Detail({ kind, billId }: { kind: 'receipt' | 'order'; billId: string }) { const spec = meta[kind] const { user } = useSession() const allowPutaway = spec.batch && can(user, 'putaway.execute') const [doc, setDoc] = useState<(Summary & { items: Item[] }) | null>(null) const [error, setError] = useState('') useEffect(() => { api<{ inbound: Summary & { items: Item[] } }>(`${spec.detail}/${billId}`) .then((data) => setDoc(data.inbound)) .catch((err: unknown) => setError(err instanceof Error ? err.message : '加载失败')) }, [spec.detail, billId]) return ( <Page title={doc ? doc.bill_code : spec.title}> <Link className="back" to={spec.base}>返回列表</Link> {error && <p className="banner error">{error}</p>} {doc && ( <> <div className="cards"> <div className="card"><span>供应商</span><strong>{doc.supplier_name}</strong></div> <div className="card"><span>仓库</span><strong>{doc.warehouse_name}</strong></div> <div className="card"><span>状态</span><strong>{doc.status_name}</strong></div> <div className="card"><span>数量</span><strong>{qty(doc.total_qty)}</strong></div> </div> {doc.remark && <p className="muted">备注:{doc.remark}</p>} <div className="table-wrap"> <table> <thead> <tr> {spec.batch && <th>批次码</th>} <th>商品</th> <th>编码</th> <th>条码</th> <th>数量</th> <th>来肯货位</th> </tr> </thead> <tbody> {doc.items.map((item) => ( <tr key={item.bill_detail_id}> {spec.batch && ( <td className="mono"> {allowPutaway && item.batch_code ? ( <Link to={`/putaway?code=${encodeURIComponent(item.batch_code)}`}> {item.batch_code} </Link> ) : ( item.batch_code )} </td> )} <td>{item.goods_name}</td> <td className="mono">{item.goods_code}</td> <td className="mono">{item.barcode}</td> <td>{qty(item.base_qty)} {item.base_unit}</td> <td>{item.position_code}</td> </tr> ))} </tbody> </table> </div> </> )} </Page> ) }