From 6c809d893b1162f1b35551cda9403bb2ec710c8c Mon Sep 17 00:00:00 2001 From: liu <2302563948@qq.com> Date: Mon, 31 Aug 2026 21:45:50 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=8D=95=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Mini/ProductController.php | 2 +- .../Controllers/Product/ProductController.php | 2 +- web/pages/purchase/order.tsx | 338 +++--------------- 3 files changed, 56 insertions(+), 286 deletions(-) diff --git a/app/Http/Controllers/Mini/ProductController.php b/app/Http/Controllers/Mini/ProductController.php index ce369b7..6c0f711 100644 --- a/app/Http/Controllers/Mini/ProductController.php +++ b/app/Http/Controllers/Mini/ProductController.php @@ -48,7 +48,7 @@ class ProductController extends BaseMiniController } $pageSize = (int) $request->input('pageSize', 10); - $paginator = $query->orderBy('sort') + $paginator = $query->orderBy('sort', 'desc') ->orderBy('id') ->paginate($pageSize); diff --git a/app/Http/Controllers/Product/ProductController.php b/app/Http/Controllers/Product/ProductController.php index 4f95ac0..7263047 100644 --- a/app/Http/Controllers/Product/ProductController.php +++ b/app/Http/Controllers/Product/ProductController.php @@ -51,7 +51,7 @@ class ProductController extends BaseController $params, ProductModel::query()->with(['category:id,name', 'supplier:id,name']) ) - ->orderBy('sort') + ->orderBy('sort', 'desc') ->orderBy('id', 'desc') ->paginate($pageSize); $data->getCollection()->makeVisible('cost_price'); diff --git a/web/pages/purchase/order.tsx b/web/pages/purchase/order.tsx index d3e53e2..5612377 100644 --- a/web/pages/purchase/order.tsx +++ b/web/pages/purchase/order.tsx @@ -5,7 +5,6 @@ import { Drawer, Empty, Form, - Image, Input, InputNumber, message, @@ -32,8 +31,6 @@ import type IPurchaseOrder from '@/domain/iPurchaseOrder.ts'; import type { IBill, IBillPrepare, - IPurchaseCell, - IPurchaseCellItem, IPurchaseDetail, IPurchaseDetailRow, IPurchaseStoreItem, @@ -43,7 +40,6 @@ import type { PurchaseStoreItemUpdateParams, } from '@/domain/iPurchaseOrder.ts'; import { PURCHASE_STATUS_MAP, BILL_STATUS_MAP } from '@/domain/iPurchaseOrder.ts'; -import { STORE_ORDER_STATUS_MAP } from '@/domain/iStoreOrder.ts'; import { addPurchaseStoreItem, exportPurchase, @@ -51,14 +47,11 @@ import { exportPurchaseSuppliers, generateBill, getBillPrepare, - getPurchaseCell, getPurchaseDetail, getPurchaseStoreSummary, removePurchaseStoreItem, type BillGenerateStoreParams, - type PurchaseCellUpdateParams, type PurchaseRowUpdateParams, - updatePurchaseCellItem, updatePurchaseRow, updatePurchaseStoreItem, } from '@/api/purchase/order.ts'; @@ -105,22 +98,9 @@ const PurchaseOrderPage: React.FC = () => { const [detailLoading, setDetailLoading] = useState(false); const [completing, setCompleting] = useState(false); - // 行内编辑:正在编辑的单元格(点击 品名/供应商/包规/单位/成本 进入编辑态) - const [editingCell, setEditingCell] = useState<{ productId: number; dataIndex: InlineEditField } | null>(null); + // 行内编辑:供应商选项(品名/供应商/包规/单位/成本与各门店订货量直接在表格中编辑) const [suppliers, setSuppliers] = useState([]); - // 单元格下钻弹窗(门店 × 商品订货明细) - const [cellOpen, setCellOpen] = useState(false); - const [cellLoading, setCellLoading] = useState(false); - const [cellData, setCellData] = useState(null); - const [cellQuery, setCellQuery] = useState<{ productId: number; storeId: number } | null>(null); - - // 单元格明细编辑(数量/称重) - const [cellItemOpen, setCellItemOpen] = useState(false); - const [cellItemTarget, setCellItemTarget] = useState(null); - const [cellItemSaving, setCellItemSaving] = useState(false); - const [cellItemForm] = Form.useForm(); - // 门店购买详情(按商品聚合的门店采购汇总) const [detailTab, setDetailTab] = useState('items'); const [storeId, setStoreId] = useState(0); @@ -243,13 +223,6 @@ const PurchaseOrderPage: React.FC = () => { getSupplierOptions().then((res) => setSuppliers(res.data.data ?? [])); }, []); - // 单元格下钻弹窗打开时加载明细 - useEffect(() => { - if (cellOpen && cellQuery) { - loadCell(); - } - }, [cellOpen, cellQuery]); - // 详情加载后默认选中第一个门店(当前选中门店仍在采购单内则保留) useEffect(() => { if (detail && detail.stores.length > 0) { @@ -375,75 +348,17 @@ const PurchaseOrderPage: React.FC = () => { await refreshAfterStoreItemChange(); }; - /** 打开单元格下钻:门店 + 商品 → 该采购单下全部订货明细 */ - const openCell = (row: IPurchaseDetailRow, store: { id: number; name: string }) => { - setCellQuery({ productId: row.product_id, storeId: store.id }); - setCellData(null); - setCellOpen(true); - }; - - /** 加载单元格明细 */ - const loadCell = async () => { - if (!detail || !cellQuery) { - return; - } - setCellLoading(true); - try { - const res = await getPurchaseCell(detail.purchase.id!, cellQuery.productId, cellQuery.storeId); - setCellData(res.data.data ?? null); - } finally { - setCellLoading(false); - } - }; - - /** 单元格明细修改/同步后:刷新弹窗、采购单详情与列表 */ - const refreshAfterCellChange = async () => { - await loadCell(); - if (detail) { - await loadDetail(detail.purchase.id!); - } - await tableRef.current?.reload(); - }; - - const openCellItemEdit = (item: IPurchaseCellItem) => { - setCellItemTarget(item); - cellItemForm.setFieldsValue({ - quantity: item.quantity, - price: Number(item.price ?? 0), - weight: Number(item.weight ?? 0), - }); - setCellItemOpen(true); - }; - - /** 提交单元格明细修改:级联重算明细金额、订货单与采购单汇总 */ - const handleCellItemSave = async (values: PurchaseCellUpdateParams) => { - if (!cellItemTarget?.id) { - return; - } - setCellItemSaving(true); - try { - await updatePurchaseCellItem(cellItemTarget.id, values); - message.success('明细已更新,订货单与采购单汇总已重算'); - setCellItemOpen(false); - setCellItemTarget(null); - await refreshAfterCellChange(); - } finally { - setCellItemSaving(false); - } - }; - /** 商品明细是否可行内编辑(进行中采购单 + 修改权限) */ const canUpdateRow = detail?.purchase.status === 0 && auth('purchase.order.update'); /** * 行内编辑保存:合并该行当前值整行提交(后端要求全字段);未变更 / 校验失败时不请求。 - * Enter 或失焦触发保存,保存后关闭编辑态并刷新详情与列表。 + * Enter 或失焦触发保存,保存后刷新详情与列表。 */ const handleInlineSave = async (row: IPurchaseDetailRow, dataIndex: InlineEditField, rawValue: string | number) => { if (!detail) { return; } - setEditingCell(null); const params: PurchaseRowUpdateParams = { product_name: row.product_name, @@ -492,7 +407,29 @@ const PurchaseOrderPage: React.FC = () => { await tableRef.current?.reload(); }; - /** 可编辑单元格:点击进入编辑态(文本 Input / 供应商 Select / 成本 InputNumber),Esc 取消 */ + /** + * 门店订货量保存:复用门店单品修改接口(仅提交订货量,单价/称重不改动), + * 同商品多笔订单明细合并到最早一条并级联重算;未变更 / 校验失败时不请求。 + */ + const handleStoreCellSave = async (row: IPurchaseDetailRow, storeId: number, rawValue: string) => { + if (!detail) { + return; + } + const quantity = Number(rawValue); + if (rawValue.trim() === '' || !Number.isInteger(quantity) || quantity < 0) { + message.warning('订货量无效,已取消修改'); + return; + } + if (quantity === row.cells[storeId]) { + return; + } + await updatePurchaseStoreItem(detail.purchase.id!, storeId, row.product_id, { quantity }); + message.success('订货量已更新,订货单与采购单汇总已重算'); + await loadDetail(detail.purchase.id!); + await tableRef.current?.reload(); + }; + + /** 行内编辑单元格:直接渲染编辑组件(文本 Input / 供应商 Select / 成本 InputNumber),Enter 或失焦保存 */ const renderEditableCell = ( row: IPurchaseDetailRow, dataIndex: InlineEditField, @@ -501,41 +438,17 @@ const PurchaseOrderPage: React.FC = () => { if (!canUpdateRow) { return display; } - const editing = editingCell?.productId === row.product_id && editingCell.dataIndex === dataIndex; - - if (!editing) { - return ( -
setEditingCell({ productId: row.product_id, dataIndex })} - > - {display} -
- ); - } - - const cancelOnEscape = { - onKeyDown: (e: React.KeyboardEvent) => { - if (e.key === 'Escape') { - setEditingCell(null); - } - }, - }; if (dataIndex === 'supplier_id') { return ( void handleInlineSave(row, dataIndex, (e.target as HTMLInputElement).value)} onBlur={(e) => void handleInlineSave(row, dataIndex, e.target.value)} - {...cancelOnEscape} /> ); }; @@ -653,7 +565,7 @@ const PurchaseOrderPage: React.FC = () => { title: '市场', fixed: 'left', dataIndex: 'market', - width: 90, + width: 110, align: 'center', filters: itemMarketOptions.map((m) => ({ text: m, value: m })), filteredValue: itemColumnFilters.market ?? null, @@ -663,7 +575,7 @@ const PurchaseOrderPage: React.FC = () => { { title: '单价', key: 'retail_price', - width: 100, + width: 110, align: 'center', render: (_, row) => { // 加权平均售价 ÷ 包规数值(无订货数量时无参考价) @@ -677,27 +589,27 @@ const PurchaseOrderPage: React.FC = () => { title: '包规', dataIndex: 'product_spec', align: 'center', - width: 90, + width: 110, render: (v, row) => renderEditableCell(row, 'product_spec', v || '-'), }, { title: '单位', dataIndex: 'unit', - width: 70, + width: 110, align: 'center', render: (v, row) => renderEditableCell(row, 'unit', v || '-'), }, { title: '成本', dataIndex: 'cost_price', - width: 100, + width: 110, align: 'center', render: (v, row) => renderEditableCell(row, 'cost_price', `¥${Number(v).toFixed(2)}`), }, { title: '合计数量', key: 'total_quantity', - width: 90, + width: 110, align: 'center', render: (_, row) => {row.quantity}, }, @@ -706,14 +618,27 @@ const PurchaseOrderPage: React.FC = () => { const storeColumns = (detail?.stores ?? []).map((store) => ({ title: {store.name}, key: `store-${store.id}`, - width: 100, align: 'center' as const, render: (_: unknown, row: IPurchaseDetailRow) => { const quantity = row.cells[store.id]; - return quantity !== undefined ? ( - openCell(row, store)}>{quantity} - ) : ( - - + if (quantity === undefined) { + return -; + } + if (!canUpdateRow) { + return quantity; + } + // 订货量直接在单元格编辑:Enter 或失焦保存(单价/称重不改动) + return ( + void handleStoreCellSave(row, store.id, (e.target as HTMLInputElement).value)} + onBlur={(e) => void handleStoreCellSave(row, store.id, e.target.value)} + /> ); }, })); @@ -1352,7 +1277,7 @@ const PurchaseOrderPage: React.FC = () => { {canUpdateRow && ( - 点击 品名/供应商/包规/单位/成本 单元格可直接修改;保存将同步该商品全部订货明细与商品档案,成本变化时各门店单价按等级上浮自动重算 + 修改保存将同步该商品全部订货明细与商品档案,成本变化时各门店单价按等级上浮自动重算 )} @@ -1373,161 +1298,6 @@ const PurchaseOrderPage: React.FC = () => { )} - {/* 单元格下钻 */} - setCellOpen(false)} - footer={null} - width={1000} - destroyOnHidden - styles={{ body: {paddingTop: 16} }} - > - - {cellData && ( - <> - {cellData.items.length === 0 ? ( - - ) : ( -
-
-
商品信息
-
单价
-
订货量
-
订货金额
-
重量
-
操作
-
- {cellData.items.map((item) => ( -
-
- - {item.image ? ( - - ) : ( -
- 暂无图片 -
- )} -
-
-
- {item.product_name} - - {STORE_ORDER_STATUS_MAP[item.order_status]?.text} - -
-
- 订单:{item.order_no} -
- {item.remark ? ( -
- 备注:{item.remark} -
- ) : null} -
-
-
¥{item.price}
-
{item.quantity}
-
- ¥{item.amount} -
-
- {item.weight ?? '-'} 斤 -
-
- {detail?.purchase.status === 0 ? ( - - - - - - ) : ( - - - )} -
-
- ))} -
- )} - {cellData.items.length > 0 && ( -
- - 合计数量: - {cellData.items.reduce((sum, item) => sum + item.quantity, 0)} - - - 合计订货金额: - - ¥ - {cellData.items - .reduce((sum, item) => sum + Number(item.amount), 0) - .toFixed(2)} - - -
- )} - - )} -
-
- - {/* 单元格明细编辑 */} - { - setCellItemOpen(false); - setCellItemTarget(null); - }} - onOk={() => cellItemForm.submit()} - confirmLoading={cellItemSaving} - okText="保存" - destroyOnHidden - > -
- 订单 {cellItemTarget?.order_no};修改保存后,系统将自动重算明细金额、订货单与采购单汇总。 -
-
- - - - - - - - - -
-
- {/* 生成账单:按门店填写配送费/周转筐/托盘数量与售后金额(商品金额只读,由订单汇总) */}