From 1c1af9b0fc10778ae5ac13cc68fd4030affbcfe1 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 09 九月 2026 10:59:53 +0800
Subject: [PATCH] feat(wm): 新增SN码管理和设备入库功能
---
src/views/wls/sn/index.vue | 298 +++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 228 insertions(+), 70 deletions(-)
diff --git a/src/views/wls/sn/index.vue b/src/views/wls/sn/index.vue
index c881303..f1c5572 100644
--- a/src/views/wls/sn/index.vue
+++ b/src/views/wls/sn/index.vue
@@ -2,10 +2,12 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesWmSnApi } from '#/api/mes/wm/sn';
+import { ref } from 'vue';
+
import { Page, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart } from '@vben/utils';
-import { message } from 'ant-design-vue';
+import { message, Tabs, Tag } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
@@ -13,12 +15,28 @@
exportSnDetailExcel,
exportSnGroupExcel,
getSnGroupPage,
+ getSnInStockPage,
} from '#/api/mes/wm/sn';
import { $t } from '#/locales';
-import { useGridColumns, useGridFormSchema } from './data';
+import {
+ useGridColumns,
+ useGridFormSchema,
+ useInStockGridColumns,
+ useInStockGridFormSchema,
+} from './data';
+import {
+ formatWmLocation,
+ getWmLocationMaps,
+ type WmLocationMaps,
+} from './location-maps';
import Detail from './modules/detail.vue';
import Form from './modules/form.vue';
+import InStockModal from './modules/in-stock-modal.vue';
+import OutStockModal from './modules/out-stock-modal.vue';
+import SnDetailModal from './modules/sn-detail-modal.vue';
+
+const activeKey = ref('group');
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
@@ -30,9 +48,25 @@
destroyOnClose: true,
});
-/** 鍒锋柊琛ㄦ牸 */
+const [InStockModalRef, inStockModalApi] = useVbenModal({
+ connectedComponent: InStockModal,
+ destroyOnClose: true,
+});
+
+const [OutStockModalRef, outStockModalApi] = useVbenModal({
+ connectedComponent: OutStockModal,
+ destroyOnClose: true,
+});
+
+const snDetailModalRef = ref<InstanceType<typeof SnDetailModal>>();
+
+/** 鍒锋柊褰撳墠椤电 */
function handleRefresh() {
- gridApi.query();
+ if (activeKey.value === 'group') {
+ gridApi.query();
+ } else {
+ inStockGridApi.query();
+ }
}
/** 鐢熸垚 SN 鐮� */
@@ -74,6 +108,34 @@
}
}
+/** 鍏ュ簱鐧昏 */
+function handleInStock() {
+ inStockModalApi.open();
+}
+
+/** 鍑哄簱鏍搁攢 */
+function handleOutStock() {
+ outStockModalApi.open();
+}
+
+/** 鏌ョ湅鍗曚欢璇︽儏 */
+function handleSnDetail(row: MesWmSnApi.Sn) {
+ snDetailModalRef.value?.open(row.code);
+}
+
+/** 鍦ㄥ簱鍗曚欢鍒楄〃浣嶇疆鍚嶇О鏄犲皠锛堟噿鍔犺浇锛岄娆¤闂椂鍒濆鍖栵級 */
+const locationMapsRef = ref<Awaited<ReturnType<typeof getWmLocationMaps>>>();
+const EMPTY_MAPS: WmLocationMaps = {
+ warehouseNameMap: {},
+ locationNameMap: {},
+ areaNameMap: {},
+};
+async function ensureLocationMaps() {
+ if (!locationMapsRef.value) {
+ locationMapsRef.value = await getWmLocationMaps();
+ }
+}
+
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: useGridFormSchema(),
@@ -103,75 +165,171 @@
},
} as VxeTableGridOptions<MesWmSnApi.SnGroup>,
});
+
+const [InStockGrid, inStockGridApi] = useVbenVxeGrid({
+ formOptions: {
+ schema: useInStockGridFormSchema(),
+ },
+ gridOptions: {
+ columns: useInStockGridColumns(),
+ height: 'auto',
+ keepSource: true,
+ proxyConfig: {
+ ajax: {
+ query: async ({ page }, formValues) => {
+ return await getSnInStockPage({
+ pageNo: page.currentPage,
+ pageSize: page.pageSize,
+ ...formValues,
+ });
+ },
+ },
+ },
+ rowConfig: {
+ keyField: 'id',
+ isHover: true,
+ },
+ toolbarConfig: {
+ refresh: true,
+ search: true,
+ },
+ } as VxeTableGridOptions<MesWmSnApi.Sn>,
+});
+
+// 棣栨鎸傝浇鏃堕鐑綅缃悕绉版槧灏勶紝渚涘垪琛ㄥ睍绀�
+void ensureLocationMaps();
</script>
<template>
- <Page auto-content-height><FormModal @success="handleRefresh" />
+ <Page auto-content-height>
+ <FormModal @success="handleRefresh" />
<DetailModal />
+ <InStockModalRef @success="handleRefresh" />
+ <OutStockModalRef @success="handleRefresh" />
+ <SnDetailModal ref="snDetailModalRef" />
- <Grid table-title="SN 鐮佸垪琛�">
- <template #toolbar-tools>
- <TableAction
- :actions="[
- {
- label: '鐢熸垚 SN 鐮�',
- type: 'primary',
- icon: ACTION_ICON.ADD,
- auth: ['mes:wm-sn:create'],
- onClick: handleCreate,
- },
- {
- label: $t('ui.actionTitle.export'),
- type: 'primary',
- icon: ACTION_ICON.DOWNLOAD,
- auth: ['mes:wm-sn:export'],
- onClick: handleExport,
- },
- ]"
- />
- </template>
- <template #count="{ row }">
- <TableAction
- :actions="[
- {
- label: `${row.count ?? 0}`,
- type: 'link',
- auth: ['mes:wm-sn:query'],
- onClick: handleDetail.bind(null, row),
- },
- ]"
- />
- </template>
- <template #actions="{ row }">
- <TableAction
- :actions="[
- {
- label: '鏌ョ湅鏄庣粏',
- type: 'link',
- auth: ['mes:wm-sn:query'],
- onClick: handleDetail.bind(null, row),
- },
- {
- label: '瀵煎嚭鏄庣粏',
- type: 'link',
- auth: ['mes:wm-sn:export'],
- onClick: handleExportDetail.bind(null, row),
- },
- {
- label: $t('common.delete'),
- type: 'link',
- danger: true,
- auth: ['mes:wm-sn:delete'],
- popConfirm: {
- title: $t('ui.actionMessage.deleteConfirm', [
- row.batchCode || row.itemName,
- ]),
- confirm: handleDelete.bind(null, row),
- },
- },
- ]"
- />
- </template>
- </Grid>
+ <Tabs v-model:active-key="activeKey" class="px-4 pt-1" type="card">
+ <Tabs.TabPane key="group" tab="SN 鐮佸垎缁�">
+ <Grid table-title="SN 鐮佸垪琛�">
+ <template #toolbar-tools>
+ <TableAction
+ :actions="[
+ {
+ label: '鐢熸垚 SN 鐮�',
+ type: 'primary',
+ icon: ACTION_ICON.ADD,
+ auth: ['mes:wm-sn:create'],
+ onClick: handleCreate,
+ },
+ {
+ label: $t('ui.actionTitle.export'),
+ type: 'primary',
+ icon: ACTION_ICON.DOWNLOAD,
+ auth: ['mes:wm-sn:export'],
+ onClick: handleExport,
+ },
+ ]"
+ />
+ </template>
+ <template #count="{ row }">
+ <TableAction
+ :actions="[
+ {
+ label: `${row.count ?? 0}`,
+ type: 'link',
+ auth: ['mes:wm-sn:query'],
+ onClick: handleDetail.bind(null, row),
+ },
+ ]"
+ />
+ </template>
+ <template #actions="{ row }">
+ <TableAction
+ :actions="[
+ {
+ label: '鏌ョ湅鏄庣粏',
+ type: 'link',
+ auth: ['mes:wm-sn:query'],
+ onClick: handleDetail.bind(null, row),
+ },
+ {
+ label: '瀵煎嚭鏄庣粏',
+ type: 'link',
+ auth: ['mes:wm-sn:export'],
+ onClick: handleExportDetail.bind(null, row),
+ },
+ {
+ label: $t('common.delete'),
+ type: 'link',
+ danger: true,
+ auth: ['mes:wm-sn:delete'],
+ popConfirm: {
+ title: $t('ui.actionMessage.deleteConfirm', [
+ row.batchCode || row.itemName,
+ ]),
+ confirm: handleDelete.bind(null, row),
+ },
+ },
+ ]"
+ />
+ </template>
+ </Grid>
+ </Tabs.TabPane>
+ <Tabs.TabPane key="in-stock" tab="鍦ㄥ簱鍗曚欢">
+ <InStockGrid table-title="SN 鍗曚欢鐘舵�佸垪琛�">
+ <template #toolbar-tools>
+ <TableAction
+ :actions="[
+ {
+ label: '鍏ュ簱鐧昏',
+ type: 'primary',
+ icon: ACTION_ICON.ADD,
+ auth: ['mes:wm-sn:update'],
+ onClick: handleInStock,
+ },
+ {
+ label: '鍑哄簱鏍搁攢',
+ type: 'primary',
+ danger: true,
+ icon: ACTION_ICON.DELETE,
+ auth: ['mes:wm-sn:update'],
+ onClick: handleOutStock,
+ },
+ ]"
+ />
+ </template>
+ <template #status="{ row }">
+ <Tag :color="row.status === 1 ? 'green' : 'orange'">
+ {{ row.status === 1 ? '鍦ㄥ簱' : '宸插嚭搴�' }}
+ </Tag>
+ </template>
+ <template #locations="{ row }">
+ <span v-if="row.status === 1">
+ {{
+ formatWmLocation(
+ locationMapsRef ?? EMPTY_MAPS,
+ row.warehouseId,
+ row.locationId,
+ row.areaId,
+ )
+ }}
+ </span>
+ <span v-else>-</span>
+ </template>
+ <template #actions="{ row }">
+ <TableAction
+ :actions="[
+ {
+ label: '璇︽儏',
+ type: 'link',
+ auth: ['mes:wm-sn:query'],
+ onClick: handleSnDetail.bind(null, row),
+ },
+ ]"
+ />
+ </template>
+ </InStockGrid>
+ </Tabs.TabPane>
+ </Tabs>
</Page>
-</template>
+</template>
\ No newline at end of file
--
Gitblit v1.9.3