From 563f14617f4b5ee57e8d550bf3c1e34103263106 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期六, 18 四月 2026 15:18:03 +0800
Subject: [PATCH] 优化扫码出库功能,增强前端页面交互体验,更新API接口以支持更灵活的出库状态处理
---
src/pages/inventoryManagement/scanOut/scanOut.logic.ts | 86 ++++++++++++++++++++++++++++
src/pages/inventoryManagement/scanOut/scanOut.submit.ts | 56 ++++++++++++++++++
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/src/pages/inventoryManagement/scanOut/scanOut.logic.ts b/src/pages/inventoryManagement/scanOut/scanOut.logic.ts
new file mode 100644
index 0000000..05213fa
--- /dev/null
+++ b/src/pages/inventoryManagement/scanOut/scanOut.logic.ts
@@ -0,0 +1,86 @@
+import {
+ CONTRACT_KIND,
+ QUALITY_TYPE,
+} from "./scanOut.constants";
+import type { ContractKind, QualityType } from "./scanOut.constants";
+
+type AnyRow = Record<string, any>;
+
+export function parseOptionalNumber(raw: unknown): number | null {
+ if (raw === null || raw === undefined || raw === "") return null;
+ const n = Number(String(raw).trim());
+ return Number.isNaN(n) ? null : n;
+}
+
+export function parseRemainingQuantity(row: AnyRow): number | null {
+ const remRaw =
+ row?.remainingQuantity ??
+ row?.remaining_quantity ??
+ row?.remainQuantity ??
+ row?.remain_quantity;
+ return parseOptionalNumber(remRaw);
+}
+
+export function defaultStockedQuantityFromRow(row: AnyRow): string {
+ const rem = parseRemainingQuantity(row);
+ if (rem !== null) return String(Math.max(0, rem));
+
+ const avail = parseOptionalNumber(row?.availableQuality ?? row?.availableQuantity);
+ if (avail !== null) return String(Math.max(0, avail));
+
+ const qty = parseOptionalNumber(row?.quantity);
+ if (qty !== null) return String(Math.max(0, qty));
+
+ return "0";
+}
+
+/** 鏍规嵁浜岀淮鐮� JSON 鍒ゆ柇閿�鍞�(XS)/閲囪喘(CG) */
+export function resolveQrContractKind(scanData: AnyRow): ContractKind {
+ const t = scanData?.type;
+ const ts =
+ t !== null && t !== undefined && t !== "" ? String(t).trim().toUpperCase() : "";
+
+ if (ts === "CG" || t === 2 || t === "2") return CONTRACT_KIND.purchase;
+ if (ts === "XS" || t === 1 || t === "1") return CONTRACT_KIND.sales;
+
+ const pc = scanData?.purchaseContractNumber;
+ const sc = scanData?.salesContractNo;
+ if (pc != null && String(pc).trim() !== "" && (sc == null || String(sc).trim() === ""))
+ return CONTRACT_KIND.purchase;
+
+ return CONTRACT_KIND.sales;
+}
+
+export function resolveListTypeForDetail(contractKind: ContractKind): 1 | 2 {
+ return contractKind === CONTRACT_KIND.purchase ? 2 : 1;
+}
+
+export function resolveContractNo(scanData: AnyRow, contractKind: ContractKind): string {
+ const rawNo =
+ contractKind === CONTRACT_KIND.purchase
+ ? scanData.purchaseContractNumber
+ : scanData.salesContractNo;
+ return rawNo != null && String(rawNo).trim() !== "" ? String(rawNo).trim() : "";
+}
+
+export function buildSalesLedgerProductList(recordList: AnyRow[]): AnyRow[] {
+ return recordList.map((item: AnyRow) => {
+ const n = parseOptionalNumber(item.stockedQuantity);
+ const qty = n !== null && !Number.isNaN(n) ? Math.max(0, n) : 0;
+ const { stockedQuantity: _sq, ...rest } = item;
+ return { ...rest, stockedQuantity: qty };
+ });
+}
+
+export function hasAnyPositiveStockedQty(salesLedgerProductList: AnyRow[]): boolean {
+ return salesLedgerProductList.some((p: AnyRow) => Number(p.stockedQuantity) > 0);
+}
+
+export function resolveSubmitSceneKey(contractKind: ContractKind, qualityType: QualityType): string {
+ return `${contractKind}-${qualityType}`;
+}
+
+export function isQualified(qualityType: QualityType): boolean {
+ return qualityType === QUALITY_TYPE.qualified;
+}
+
diff --git a/src/pages/inventoryManagement/scanOut/scanOut.submit.ts b/src/pages/inventoryManagement/scanOut/scanOut.submit.ts
new file mode 100644
index 0000000..208fd58
--- /dev/null
+++ b/src/pages/inventoryManagement/scanOut/scanOut.submit.ts
@@ -0,0 +1,56 @@
+import {
+ CONTRACT_KIND,
+ QUALITY_TYPE,
+} from "./scanOut.constants";
+import type { ContractKind, QualityType } from "./scanOut.constants";
+import {
+ scanOutboundSales,
+ scanOutboundSalesUnqualified,
+} from "@/api/salesManagement/salesLedger";
+import {
+ scanOutboundPurchase,
+ scanOutboundPurchaseUnqualified,
+} from "@/api/procurementManagement/procurementLedger";
+
+type AnyRow = Record<string, any>;
+type AnyRef<T> = { value: T };
+
+type SubmitConfig = {
+ runApi: (data: any) => Promise<any>;
+ payloadBuilder: (list: AnyRow[]) => any;
+};
+
+export function createSubmitConfig(scanLedgerIdRef: AnyRef<string | number | null>) {
+ const cfg: Record<string, SubmitConfig> = {
+ [`${CONTRACT_KIND.sales}-${QUALITY_TYPE.qualified}`]: {
+ runApi: scanOutboundSales,
+ payloadBuilder: (list: AnyRow[]) => ({
+ salesLedgerId: scanLedgerIdRef.value,
+ salesLedgerProductList: list,
+ }),
+ },
+ [`${CONTRACT_KIND.sales}-${QUALITY_TYPE.unqualified}`]: {
+ runApi: scanOutboundSalesUnqualified,
+ payloadBuilder: (list: AnyRow[]) => ({
+ salesLedgerId: scanLedgerIdRef.value,
+ salesLedgerProductList: list,
+ }),
+ },
+ [`${CONTRACT_KIND.purchase}-${QUALITY_TYPE.qualified}`]: {
+ runApi: scanOutboundPurchase,
+ payloadBuilder: (list: AnyRow[]) => ({
+ purchaseLedgerId: scanLedgerIdRef.value,
+ salesLedgerProductList: list,
+ }),
+ },
+ [`${CONTRACT_KIND.purchase}-${QUALITY_TYPE.unqualified}`]: {
+ runApi: scanOutboundPurchaseUnqualified,
+ payloadBuilder: (list: AnyRow[]) => ({
+ purchaseLedgerId: scanLedgerIdRef.value,
+ salesLedgerProductList: list,
+ }),
+ },
+ };
+ return cfg;
+}
+
--
Gitblit v1.9.3