From df013ac69c9deb3ca5c47462604aae99ed0220e6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 14 May 2026 09:07:26 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=88wms=EF=BC=89=EF=BC=9A=E5=87=BA?= =?UTF-8?q?=E5=BA=93=E7=AE=A1=E7=90=86=EF=BC=8C=E8=B0=83=E6=95=B4=E5=90=88?= =?UTF-8?q?=E8=AE=A1=E9=87=91=E9=A2=9D=E3=80=81=E6=95=B0=E9=87=8F=E7=9A=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=B8=8E=E4=BA=A4=E4=BA=92=E3=80=82=EF=BC=88?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E8=B4=9F=E8=B4=A3=E5=B1=95=E7=A4=BA=EF=BC=8C?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E8=B4=9F=E8=B4=A3=E8=AE=A1=E7=AE=97=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/wms/order/shipment/detail/index.ts | 3 +- src/api/wms/order/shipment/index.ts | 2 +- .../wms/order/receipt/ReceiptOrderForm.vue | 20 +-- .../order/shipment/ShipmentOrderDetail.vue | 25 ++-- .../wms/order/shipment/ShipmentOrderForm.vue | 135 +++++++++++------- .../wms/order/shipment/ShipmentOrderPrint.vue | 43 +++++- src/views/wms/order/shipment/index.vue | 27 +++- src/views/wms/utils/format.ts | 21 +++ 8 files changed, 180 insertions(+), 96 deletions(-) diff --git a/src/api/wms/order/shipment/detail/index.ts b/src/api/wms/order/shipment/detail/index.ts index 30e48f4da..4f2d5c0e9 100644 --- a/src/api/wms/order/shipment/detail/index.ts +++ b/src/api/wms/order/shipment/detail/index.ts @@ -13,6 +13,7 @@ export interface ShipmentOrderDetailVO { warehouseName?: string quantity?: number availableQuantity?: number - amount?: number + price?: number + totalPrice?: number createTime?: Date } diff --git a/src/api/wms/order/shipment/index.ts b/src/api/wms/order/shipment/index.ts index ccbcfb85b..2f1b0ea49 100644 --- a/src/api/wms/order/shipment/index.ts +++ b/src/api/wms/order/shipment/index.ts @@ -15,7 +15,7 @@ export interface ShipmentOrderVO { warehouseId?: number warehouseName?: string totalQuantity?: number - totalAmount?: number + totalPrice?: number details?: ShipmentOrderDetailVO[] createTime?: Date creator?: string diff --git a/src/views/wms/order/receipt/ReceiptOrderForm.vue b/src/views/wms/order/receipt/ReceiptOrderForm.vue index eb5e672f7..cbf74e395 100644 --- a/src/views/wms/order/receipt/ReceiptOrderForm.vue +++ b/src/views/wms/order/receipt/ReceiptOrderForm.vue @@ -198,9 +198,11 @@ import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vu import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue' import { OrderStatusEnum, OrderUpdateStatusList } from '@/views/wms/utils/constants' import { + dividePrice, formatPrice, formatSumPrice, formatSumQuantity, + multiplyPrice, PRICE_PRECISION, QUANTITY_PRECISION, sumPrice @@ -296,24 +298,6 @@ const normalizeDetails = (details: ReceiptOrderDetailVO[]) => totalPrice: detail.totalPrice ?? multiplyPrice(detail.quantity, detail.price) })) -const roundPrice = (value: number) => { - return Number.isFinite(value) ? Number(value.toFixed(PRICE_PRECISION)) : undefined -} - -const multiplyPrice = (quantity?: number, price?: number) => { - if (!quantity || price === undefined || price === null) { - return undefined - } - return roundPrice(Number(quantity) * Number(price)) -} - -const dividePrice = (totalPrice?: number, quantity?: number) => { - if (totalPrice === undefined || totalPrice === null || !quantity) { - return undefined - } - return roundPrice(Number(totalPrice) / Number(quantity)) -} - /** 添加商品 */ const handleAddDetail = () => { skuSelectRef.value?.open(getSelectedSkuIds()) diff --git a/src/views/wms/order/shipment/ShipmentOrderDetail.vue b/src/views/wms/order/shipment/ShipmentOrderDetail.vue index 96ff3f899..42b75317f 100644 --- a/src/views/wms/order/shipment/ShipmentOrderDetail.vue +++ b/src/views/wms/order/shipment/ShipmentOrderDetail.vue @@ -37,7 +37,7 @@ {{ formatQuantity(detailData.totalQuantity) || '-' }} - {{ formatPrice(detailData.totalAmount) || '-' }} + {{ formatPrice(detailData.totalPrice) || '-' }} {{ formatNullableDate(detailData.createTime) }} @@ -80,14 +80,14 @@ - + - + @@ -111,7 +111,7 @@ import { defineOptions({ name: 'WmsShipmentOrderDetail' }) interface DetailRow extends ShipmentOrderDetailVO { - unitPrice?: number + totalPrice?: number } const loading = ref(false) // 加载中 @@ -120,9 +120,9 @@ const detailData = ref({}) // 详情数据 const detailRows = computed(() => (detailData.value.details || []).map((detail) => ({ ...detail, - unitPrice: - detail.amount != null && detail.quantity - ? Number(detail.amount) / Number(detail.quantity) + totalPrice: + detail.price != null && detail.quantity + ? Number(detail.price) * Number(detail.quantity) : undefined })) ) @@ -135,8 +135,11 @@ const getSummaries = ({ columns, data }: { columns: any[]; data: DetailRow[] }) if (column.property === 'quantity') { return formatSumQuantity(data, (detail) => detail.quantity) } - if (column.property === 'amount') { - return formatSumPrice(data, (detail) => detail.amount) + if (column.property === 'price') { + return formatSumPrice(data, (detail) => detail.price) + } + if (column.property === 'totalPrice') { + return formatSumPrice(data, (detail) => detail.totalPrice) } return '' }) diff --git a/src/views/wms/order/shipment/ShipmentOrderForm.vue b/src/views/wms/order/shipment/ShipmentOrderForm.vue index 48cf029b5..793ab2b86 100644 --- a/src/views/wms/order/shipment/ShipmentOrderForm.vue +++ b/src/views/wms/order/shipment/ShipmentOrderForm.vue @@ -56,7 +56,7 @@ - + - - - - - - - - - -
@@ -101,7 +84,13 @@
- + - + - + + + + @@ -205,11 +208,15 @@ import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vu import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue' import { OrderStatusEnum, OrderUpdateStatusList } from '@/views/wms/utils/constants' import { + dividePrice, + formatPrice, formatQuantity, + formatSumPrice, + formatSumQuantity, + multiplyPrice, PRICE_PRECISION, QUANTITY_PRECISION, - sumPrice, - sumQuantity + sumPrice } from '@/views/wms/utils/format' import { generateOrderNo } from '@/views/wms/utils/order' @@ -233,8 +240,6 @@ const formData = ref({ bizOrderNo: undefined, merchantId: undefined, warehouseId: undefined, - totalQuantity: 0, - totalAmount: 0, remark: undefined, details: [] }) @@ -242,15 +247,12 @@ const formRules = reactive({ no: [{ required: true, message: '出库单号不能为空', trigger: 'blur' }], type: [{ required: true, message: '出库类型不能为空', trigger: 'change' }], orderTime: [{ required: true, message: '单据日期不能为空', trigger: 'change' }], - warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'change' }], - totalQuantity: [{ required: true, message: '出库数量不能为空', trigger: 'change' }], - totalAmount: [{ required: true, message: '总金额不能为空', trigger: 'blur' }] + warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'change' }] }) const formRef = ref() // 表单 Ref const inventorySelectRef = ref() // 库存选择弹窗 Ref -const totalQuantity = computed(() => sumQuantity(formData.value.details || [], (detail) => detail.quantity)) -const detailTotalAmount = computed(() => sumPrice(formData.value.details || [], (detail) => detail.amount)) +const detailPriceSum = computed(() => sumPrice(formData.value.details || [], (detail) => detail.price)) const isPrepareOrder = computed( () => !formData.value.id || @@ -276,7 +278,7 @@ const open = async (type: string, id?: number) => { const order = await ShipmentOrderApi.getShipmentOrder(id) formData.value = { ...order, - details: order.details || [] + details: normalizeDetails(order.details || []) } } finally { formLoading.value = false @@ -300,9 +302,16 @@ const buildDetail = (inventory: InventorySelectRow): ShipmentOrderDetailVO => ({ warehouseName: inventory.warehouseName, quantity: undefined, availableQuantity: inventory.availableQuantity, - amount: undefined + price: undefined, + totalPrice: undefined }) +const normalizeDetails = (details: ShipmentOrderDetailVO[]) => + details.map((detail) => ({ + ...detail, + totalPrice: detail.totalPrice ?? multiplyPrice(detail.quantity, detail.price) + })) + /** 添加商品 */ const handleAddDetail = () => { inventorySelectRef.value?.open() @@ -320,7 +329,6 @@ const handleSelectInventory = (inventories: InventorySelectRow[]) => { } formData.value.details!.push(buildDetail(inventory)) }) - refreshTotalAmount() } /** 判断库存是否已选择 */ @@ -336,24 +344,49 @@ const isInventorySelected = (inventory: InventorySelectRow) => { /** 删除明细 */ const handleDeleteDetail = (index: number) => { formData.value.details?.splice(index, 1) - refreshTotalAmount() } /** 仓库变化 */ const handleWarehouseChange = () => { formData.value.details = [] - refreshTotalAmount() +} + +/** 明细数量变化 */ +const handleDetailQuantityChange = (detail: ShipmentOrderDetailVO) => { + if (detail.price !== undefined && detail.price !== null) { + detail.totalPrice = multiplyPrice(detail.quantity, detail.price) + return + } + detail.price = dividePrice(detail.totalPrice, detail.quantity) +} + +/** 明细单价变化 */ +const handleDetailPriceChange = (detail: ShipmentOrderDetailVO) => { + detail.totalPrice = multiplyPrice(detail.quantity, detail.price) } /** 明细金额变化 */ -const handleDetailAmountChange = () => { - refreshTotalAmount() +const handleDetailTotalPriceChange = (detail: ShipmentOrderDetailVO) => { + detail.price = dividePrice(detail.totalPrice, detail.quantity) } -/** 汇总明细金额 */ -const refreshTotalAmount = () => { - formData.value.totalAmount = detailTotalAmount.value -} +/** 明细合计 */ +const getDetailSummaries = ({ columns, data }: { columns: any[]; data: ShipmentOrderDetailVO[] }) => + columns.map((column, index) => { + if (index === 0) { + return '合计' + } + if (column.property === 'quantity') { + return formatSumQuantity(data, (detail) => detail.quantity) + } + if (column.property === 'price') { + return formatPrice(detailPriceSum.value) + } + if (column.property === 'totalPrice') { + return formatSumPrice(data, (detail) => detail.totalPrice) + } + return '' + }) /** 校验明细 */ const validateDetails = (required: boolean) => { @@ -383,13 +416,13 @@ const validateDetails = (required: boolean) => { } /** 构建提交数据 */ -const buildSubmitData = () => - ({ - ...formData.value, - totalQuantity: totalQuantity.value, - totalAmount: formData.value.totalAmount, - details: formData.value.details || [] - }) as ShipmentOrderVO +const buildSubmitData = () => { + const { totalQuantity: _totalQuantity, totalPrice: _totalPrice, details, ...order } = formData.value + return { + ...order, + details: (details || []).map(({ totalPrice: _rowTotalPrice, ...detail }) => detail) + } as ShipmentOrderVO +} /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 @@ -467,8 +500,6 @@ const resetForm = () => { bizOrderNo: undefined, merchantId: undefined, warehouseId: undefined, - totalQuantity: 0, - totalAmount: 0, remark: undefined, details: [] } diff --git a/src/views/wms/order/shipment/ShipmentOrderPrint.vue b/src/views/wms/order/shipment/ShipmentOrderPrint.vue index 7e1145d90..b60f12dd5 100644 --- a/src/views/wms/order/shipment/ShipmentOrderPrint.vue +++ b/src/views/wms/order/shipment/ShipmentOrderPrint.vue @@ -15,7 +15,7 @@
客户:{{ printData.merchantName || '-' }}
业务单号:{{ printData.bizOrderNo || '-' }}
总数量:{{ formatQuantity(printData.totalQuantity) || '-' }}
-
总金额:{{ formatPrice(printData.totalAmount) || '-' }}
+
总金额:{{ formatPrice(printData.totalPrice) || '-' }}
创建时间:{{ formatNullableDate(printData.createTime) }}
备注:{{ printData.remark || '-' }}
@@ -25,11 +25,12 @@ 商品信息 规格信息 数量 + 单价(元) 金额(元) - +
{{ detail.itemName || '-' }}
编号:{{ detail.itemCode }}
@@ -42,10 +43,25 @@ {{ formatQuantity(detail.quantity) || '-' }} - {{ formatPrice(detail.amount) || '-' }} + {{ formatPrice(detail.price) || '-' }} + + + {{ formatPrice(detail.totalPrice) || '-' }} - + + 合计 + + {{ formatSumQuantity(printRows, (detail) => detail.quantity) }} + + + {{ formatSumPrice(printRows, (detail) => detail.price) }} + + + {{ formatSumPrice(printRows, (detail) => detail.totalPrice) }} + + + ({}) // 打印数据 const printButtonRef = ref() // 打印按钮 -const tableColumnCount = 4 +const tableColumnCount = 5 const printObj = ref({ id: 'wmsShipmentOrderPrint', popTitle: ' ', @@ -79,6 +96,20 @@ const printObj = ref({ zIndex: 20003 }) +interface PrintRow extends ShipmentOrderDetailVO { + totalPrice?: number +} + +const printRows = computed(() => + (printData.value.details || []).map((detail) => ({ + ...detail, + totalPrice: + detail.price != null && detail.quantity + ? Number((Number(detail.price) * Number(detail.quantity)).toFixed(2)) + : undefined + })) +) + /** 打印出库单 */ const print = async (id: number) => { printData.value = await ShipmentOrderApi.getShipmentOrder(id) diff --git a/src/views/wms/order/shipment/index.vue b/src/views/wms/order/shipment/index.vue index 74a88ed0c..1b4af26f4 100644 --- a/src/views/wms/order/shipment/index.vue +++ b/src/views/wms/order/shipment/index.vue @@ -80,10 +80,10 @@ /> - +
+ + + @@ -305,7 +310,7 @@
金额: - {{ formatPrice(scope.row.totalAmount) }} + {{ formatPrice(scope.row.totalPrice) }}
@@ -460,8 +465,8 @@ const getDefaultQueryParams = () => ({ orderTime: undefined as string[] | undefined, totalQuantityMin: undefined as number | undefined, totalQuantityMax: undefined as number | undefined, - totalAmountMin: undefined as number | undefined, - totalAmountMax: undefined as number | undefined, + totalPriceMin: undefined as number | undefined, + totalPriceMax: undefined as number | undefined, type: undefined as number | undefined, bizOrderNo: undefined as string | undefined, creator: undefined as number | undefined, @@ -532,6 +537,14 @@ const handleWarehouseChange = () => { handleQuery() } +/** 计算明细金额 */ +const getDetailTotalPrice = (detail: ShipmentOrderDetailVO) => { + if (!detail.quantity || detail.price === undefined || detail.price === null) { + return undefined + } + return Number(detail.quantity) * Number(detail.price) +} + /** 展开明细 */ const handleExpandChange = async (row: ShipmentOrderVO) => { if (!row.id || detailMap[row.id]) { diff --git a/src/views/wms/utils/format.ts b/src/views/wms/utils/format.ts index 4f2a3b338..b5dd5d780 100644 --- a/src/views/wms/utils/format.ts +++ b/src/views/wms/utils/format.ts @@ -48,6 +48,27 @@ export const formatPrice = (value?: number | string | null) => { return decimalValue === undefined ? '' : decimalValue.toFixed(PRICE_PRECISION) } +/** 金额四舍五入 */ +export const roundPrice = (value: number) => { + return Number.isFinite(value) ? Number(value.toFixed(PRICE_PRECISION)) : undefined +} + +/** 数量 * 单价,计算金额 */ +export const multiplyPrice = (quantity?: number, price?: number) => { + if (!quantity || price === undefined || price === null) { + return undefined + } + return roundPrice(Number(quantity) * Number(price)) +} + +/** 金额 / 数量,反算单价 */ +export const dividePrice = (totalPrice?: number, quantity?: number) => { + if (totalPrice === undefined || totalPrice === null || !quantity) { + return undefined + } + return roundPrice(Number(totalPrice) / Number(quantity)) +} + /** 汇总数量 */ export const sumQuantity = (list: T[], getter: (item: T) => DecimalValue) => { return sumDecimal(list, getter)