From 0246fa1ebc14504a4eeb9adbb0df3ee7c8eec8b3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 17 May 2026 23:09:18 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=88wms=EF=BC=89=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20order=20receipt=20=E7=9A=84=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=EF=BC=8C=E5=AF=B9=E9=BD=90=20vue3=20+=20ep=20=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/wms/order/receipt/data.ts | 167 ++++-- .../src/views/wms/order/receipt/index.vue | 43 +- .../wms/order/receipt/modules/detail.vue | 125 +++++ .../views/wms/order/receipt/modules/form.vue | 474 ++++++++++++++++++ .../views/wms/order/receipt/modules/print.vue | 218 ++++++++ 5 files changed, 965 insertions(+), 62 deletions(-) create mode 100644 apps/web-antd/src/views/wms/order/receipt/modules/detail.vue create mode 100644 apps/web-antd/src/views/wms/order/receipt/modules/form.vue create mode 100644 apps/web-antd/src/views/wms/order/receipt/modules/print.vue diff --git a/apps/web-antd/src/views/wms/order/receipt/data.ts b/apps/web-antd/src/views/wms/order/receipt/data.ts index 335162883..84854af93 100644 --- a/apps/web-antd/src/views/wms/order/receipt/data.ts +++ b/apps/web-antd/src/views/wms/order/receipt/data.ts @@ -1,53 +1,29 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; -import { markRaw } from 'vue'; +import { h, markRaw } from 'vue'; import { DICT_TYPE } from '@vben/constants'; import { getDictOptions } from '@vben/hooks'; +import { formatDate, formatDateTime } from '@vben/utils'; import { z } from '#/adapter/form'; import { getSimpleUserList } from '#/api/system/user'; +import { DictTag } from '#/components/dict-tag'; +import { buildNumberRangeSchema } from '#/components/number-range-input'; import { getRangePickerDefaultProps } from '#/utils'; import { WmsMerchantSelect } from '#/views/wms/md/merchant/components'; import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components'; import { + formatPrice, + formatQuantity, + formatSumPrice, + formatSumQuantity, PRICE_PRECISION, QUANTITY_PRECISION, } from '#/views/wms/utils/format'; -import NumberRangeInput from './modules/number-range-input.vue'; - -function splitNumberRange(minFieldName: string, maxFieldName: string) { - return ( - value: [number | undefined, number | undefined] | undefined, - setValue: (fieldName: string, value: any) => void, - ) => { - setValue(minFieldName, value?.[0]); - setValue(maxFieldName, value?.[1]); - return undefined; - }; -} - -function buildNumberRangeSchema( - label: string, - fieldName: string, - minFieldName: string, - maxFieldName: string, - precision: number, -): VbenFormSchema { - return { - component: markRaw(NumberRangeInput), - componentProps: { - min: 0, - precision, - }, - fieldName, - label, - valueFormat: splitNumberRange(minFieldName, maxFieldName), - }; -} - /** 列表的搜索表单 */ export function useGridFormSchema(): VbenFormSchema[] { return [ @@ -247,10 +223,97 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { ]; } +/** 详情的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'no', + label: '入库单号', + render: (val) => val || '-', + }, + { + field: 'type', + label: '入库类型', + render: (val) => + val === undefined || val === null + ? '-' + : h(DictTag, { + type: DICT_TYPE.WMS_RECEIPT_ORDER_TYPE, + value: val, + }), + }, + { + field: 'warehouseName', + label: '仓库', + render: (val) => val || '-', + }, + { + field: 'status', + label: '单据状态', + render: (val) => + val === undefined || val === null + ? '-' + : h(DictTag, { + type: DICT_TYPE.WMS_ORDER_STATUS, + value: val, + }), + }, + { + field: 'orderTime', + label: '单据日期', + render: (val) => formatDate(val, 'YYYY-MM-DD') || '-', + }, + { + field: 'merchantName', + label: '供应商', + render: (val) => val || '-', + }, + { + field: 'bizOrderNo', + label: '业务单号', + render: (val) => val || '-', + }, + { + field: 'totalQuantity', + label: '总数量', + render: (val) => formatQuantity(val) || '-', + }, + { + field: 'totalPrice', + label: '总金额', + render: (val) => formatPrice(val) || '-', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) || '-', + }, + { + field: 'creatorName', + label: '创建人', + render: (val, data) => val || data?.creator || '-', + }, + { + field: 'updateTime', + label: '更新时间', + render: (val) => formatDateTime(val) || '-', + }, + { + field: 'updaterName', + label: '更新人', + render: (val, data) => val || data?.updater || '-', + }, + { + field: 'remark', + label: '备注', + render: (val) => val || '-', + span: 2, + }, + ]; +} + /** 表单的配置项 */ -export function useFormSchema( - handleWarehouseChange: () => Promise | void, -): VbenFormSchema[] { +export function useFormSchema(): VbenFormSchema[] { return [ { component: 'Input', @@ -283,9 +346,6 @@ export function useFormSchema( }, { component: markRaw(WmsWarehouseSelect), - componentProps: { - onChange: handleWarehouseChange, - }, fieldName: 'warehouseId', label: '仓库', rules: 'required', @@ -332,3 +392,32 @@ export function useFormSchema( }, ]; } + +interface ReceiptOrderDetailFooterRow { + quantity?: number; + totalPrice?: number; +} + +/** 明细表格的合计行 */ +export function getDetailFooter({ + columns, + data, +}: { + columns: Array<{ field?: string }>; + data: ReceiptOrderDetailFooterRow[]; +}) { + return [ + columns.map((column, index) => { + if (index === 0) { + return '合计'; + } + if (column.field === 'quantity') { + return formatSumQuantity(data, (detail) => detail.quantity); + } + if (column.field === 'totalPrice') { + return formatSumPrice(data, (detail) => detail.totalPrice); + } + return ''; + }), + ]; +} diff --git a/apps/web-antd/src/views/wms/order/receipt/index.vue b/apps/web-antd/src/views/wms/order/receipt/index.vue index 0b226fcb0..10ec0ef9d 100644 --- a/apps/web-antd/src/views/wms/order/receipt/index.vue +++ b/apps/web-antd/src/views/wms/order/receipt/index.vue @@ -3,9 +3,6 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { WmsReceiptOrderApi } from '#/api/wms/order/receipt'; import type { WmsReceiptOrderDetailApi } from '#/api/wms/order/receipt/detail'; -// TODO @AI:对齐 system user index.vue 的界面,function 上必要的注释,需要加; -// TODO @AI:row。id 这种防御性编程,建议都去掉,不存在这个情况;;; - import { reactive, ref } from 'vue'; import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; @@ -56,27 +53,24 @@ const [DetailModal, detailModalApi] = useVbenModal({ destroyOnClose: true, }); +/** 刷新表格 */ function handleRefresh() { gridApi.query(); } +/** 创建入库单 */ function handleCreate() { formModalApi.setData({ type: 'create' }).open(); } +/** 编辑入库单 */ function handleEdit(row: WmsReceiptOrderApi.ReceiptOrder) { - formModalApi.setData({ id: row.id, type: 'update' }).open(); + formModalApi.setData({ id: row.id!, type: 'update' }).open(); } +/** 查看入库单详情 */ function handleDetail(row: WmsReceiptOrderApi.ReceiptOrder) { - detailModalApi.setData({ id: row.id }).open(); -} - -function handlePrint(row: WmsReceiptOrderApi.ReceiptOrder) { - // TODO @AI:不用过度封装; - if (row.id) { - printRef.value?.print(row.id); - } + detailModalApi.setData({ id: row.id! }).open(); } /** 计算单据明细金额 */ @@ -86,31 +80,34 @@ function getDetailTotalPrice( return detail.totalPrice ?? multiplyPrice(detail.quantity, detail.price); } +/** 获取已展开行的明细 */ function getExpandedDetails(row: WmsReceiptOrderApi.ReceiptOrder) { - return row.id ? detailMap[row.id] || [] : []; + return detailMap[row.id!] || []; } /** 展开列表行时懒加载入库明细 */ -// TODO @AI:点击 > 才展开,不用整行点击都展开; async function handleExpandChange( row: WmsReceiptOrderApi.ReceiptOrder, expanded: boolean, ) { - if (!row.id || !expanded) { + if (!expanded) { return; } - delete detailMap[row.id]; - detailMap[row.id] = await getReceiptOrderDetailListByOrderId(row.id); + delete detailMap[row.id!]; + detailMap[row.id!] = await getReceiptOrderDetailListByOrderId(row.id!); } +/** 判断入库单是否可修改 */ function canUpdateReceiptOrder(status?: number) { return status !== undefined && OrderUpdateStatusList.includes(status); } +/** 判断入库单是否可删除 */ function canDeleteReceiptOrder(status?: number) { return status !== undefined && OrderDeleteStatusList.includes(status); } +/** 获取修改按钮禁用提示 */ function getReceiptOrderUpdateTip(status?: number) { if (canUpdateReceiptOrder(status)) { return undefined; @@ -124,6 +121,7 @@ function getReceiptOrderUpdateTip(status?: number) { return '当前状态无法修改'; } +/** 获取删除按钮禁用提示 */ function getReceiptOrderDeleteTip(status?: number) { if (canDeleteReceiptOrder(status)) { return undefined; @@ -134,16 +132,14 @@ function getReceiptOrderDeleteTip(status?: number) { return '当前状态无法删除'; } +/** 删除入库单 */ async function handleDelete(row: WmsReceiptOrderApi.ReceiptOrder) { - if (!row.id) { - return; - } const hideLoading = message.loading({ content: $t('ui.actionMessage.deleting', [row.no]), duration: 0, }); try { - await deleteReceiptOrder(row.id); + await deleteReceiptOrder(row.id!); message.success($t('ui.actionMessage.deleteSuccess', [row.no])); handleRefresh(); } finally { @@ -151,6 +147,7 @@ async function handleDelete(row: WmsReceiptOrderApi.ReceiptOrder) { } } +/** 导出入库单 */ async function handleExport() { const data = await exportReceiptOrder(await gridApi.formApi.getValues()); downloadFileFromBlobPart({ fileName: '入库单.xls', source: data }); @@ -165,7 +162,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ columns: useGridColumns(), expandConfig: { padding: true, - trigger: 'row', + trigger: 'default', }, height: 'auto', keepSource: true, @@ -331,7 +328,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ label: '打印', type: 'link', auth: ['wms:receipt-order:query'], - onClick: handlePrint.bind(null, row), + onClick: () => printRef?.print(row.id!), }, ]" /> diff --git a/apps/web-antd/src/views/wms/order/receipt/modules/detail.vue b/apps/web-antd/src/views/wms/order/receipt/modules/detail.vue new file mode 100644 index 000000000..a9ea3dda1 --- /dev/null +++ b/apps/web-antd/src/views/wms/order/receipt/modules/detail.vue @@ -0,0 +1,125 @@ + + + diff --git a/apps/web-antd/src/views/wms/order/receipt/modules/form.vue b/apps/web-antd/src/views/wms/order/receipt/modules/form.vue new file mode 100644 index 000000000..e7980994c --- /dev/null +++ b/apps/web-antd/src/views/wms/order/receipt/modules/form.vue @@ -0,0 +1,474 @@ + + + diff --git a/apps/web-antd/src/views/wms/order/receipt/modules/print.vue b/apps/web-antd/src/views/wms/order/receipt/modules/print.vue new file mode 100644 index 000000000..a0b98775d --- /dev/null +++ b/apps/web-antd/src/views/wms/order/receipt/modules/print.vue @@ -0,0 +1,218 @@ + + + + +