From d2cd585f4d3b015789a5f6c8d75e352605932f85 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 21 八月 2026 13:44:30 +0800
Subject: [PATCH] feat(mes): 新增袋码作废时间和原因字段及破损替换功能
---
src/views/mes/pro/bagCode/index.vue | 97 ++++++++++++++++++
src/views/mes/pro/bagCode/modules/replace-form.vue | 105 +++++++++++++++++++++
src/api/mes/pro/bagCode/index.ts | 48 +++++++++
src/views/mes/pro/bagCode/data.ts | 11 ++
src/views/mes/pro/components/qr-trace-modal.vue | 20 ++++
5 files changed, 277 insertions(+), 4 deletions(-)
diff --git a/src/api/mes/pro/bagCode/index.ts b/src/api/mes/pro/bagCode/index.ts
index 70d332c..5c381e9 100644
--- a/src/api/mes/pro/bagCode/index.ts
+++ b/src/api/mes/pro/bagCode/index.ts
@@ -17,6 +17,8 @@
palletCode?: string; // 鎵樼洏鐮�
status?: number; // 鐘舵�侊紙瀛楀吀 mes_pro_bag_code_status锛�
printTime?: string; // 瀵煎嚭锛堜氦浠樺嵃鍒凤級鏃堕棿
+ cancelTime?: string; // 浣滃簾鏃堕棿
+ cancelReason?: string; // 浣滃簾鍘熷洜
remark?: string; // 澶囨敞
createTime?: string; // 鍒涘缓鏃堕棿
}
@@ -45,6 +47,39 @@
ids: number[]; // 琚嬬爜缂栧彿鍒楄〃
}
+ /** 鐮存崯琚嬬爜鏇挎崲璇锋眰 */
+ export interface ReplaceParams {
+ batchId: number; // 鐢熶骇鎵规缂栧彿
+ oldIds: number[]; // 寰呮浛鎹㈡棫琚嬬爜缂栧彿鍒楄〃
+ reason: string; // 鏇挎崲鍘熷洜
+ }
+
+ /** 鐮存崯琚嬬爜鏇挎崲鏄庣粏 */
+ export interface ReplaceItem {
+ oldBagCodeId?: number;
+ oldCode?: string;
+ oldBagNo?: number;
+ oldStatus?: number;
+ oldPalletId?: number;
+ oldPalletCode?: string;
+ newBagCodeId?: number;
+ newCode?: string;
+ newBagNo?: number;
+ newPalletId?: number;
+ newPalletCode?: string;
+ reason?: string;
+ replaceTime?: string;
+ }
+
+ /** 鐮存崯琚嬬爜鏇挎崲缁撴灉 */
+ export interface ReplaceResult {
+ replaceUuid?: string;
+ batchId?: number;
+ batchCode?: string;
+ count?: number;
+ items?: ReplaceItem[];
+ }
+
/** 鎵爜杩芥函淇℃伅 */
export interface BagCodeTrace {
id?: number; // 琚嬬爜缂栧彿
@@ -52,6 +87,11 @@
bagNo?: number; // 琚嬪簭鍙�
status?: number; // 琚嬬爜鐘舵��
printTime?: string; // 瀵煎嚭鍗板埛鏃堕棿
+ cancelTime?: string; // 浣滃簾鏃堕棿
+ cancelReason?: string; // 浣滃簾鍘熷洜
+ replacementUuid?: string; // 鏇挎崲缁� UUID
+ replacedByCode?: string; // 鏇挎崲鍚庣殑鏂拌鐮�
+ replacementOfCode?: string; // 琚浛鎹㈢殑鏃ц鐮�
batchId?: number; // 鎵规缂栧彿
batchCode?: string; // 鎵规鍙�
batchStatus?: number; // 鎵规鐘舵��
@@ -89,6 +129,14 @@
return requestClient.put('/mes/pro/bag-code/unbind-pallet', data);
}
+/** 浣滃簾鐮存崯琚嬬爜骞剁敓鎴愮瓑閲忔浛鎹㈣鐮� */
+export function replaceBagCodes(data: MesProBagCodeApi.ReplaceParams) {
+ return requestClient.post<MesProBagCodeApi.ReplaceResult>(
+ '/mes/pro/bag-code/replace',
+ data,
+ );
+}
+
/** 鏌ヨ琚嬬爜璇︽儏 */
export function getBagCode(id: number) {
return requestClient.get<MesProBagCodeApi.BagCode>(
diff --git a/src/views/mes/pro/bagCode/data.ts b/src/views/mes/pro/bagCode/data.ts
index 09b3d69..a2b312e 100644
--- a/src/views/mes/pro/bagCode/data.ts
+++ b/src/views/mes/pro/bagCode/data.ts
@@ -115,6 +115,17 @@
formatter: 'formatDateTime',
},
{
+ field: 'cancelTime',
+ title: '浣滃簾鏃堕棿',
+ width: 170,
+ formatter: 'formatDateTime',
+ },
+ {
+ field: 'cancelReason',
+ title: '浣滃簾鍘熷洜',
+ minWidth: 160,
+ },
+ {
field: 'createTime',
title: '鍒涘缓鏃堕棿',
width: 170,
diff --git a/src/views/mes/pro/bagCode/index.vue b/src/views/mes/pro/bagCode/index.vue
index f4ffa22..910602c 100644
--- a/src/views/mes/pro/bagCode/index.vue
+++ b/src/views/mes/pro/bagCode/index.vue
@@ -6,7 +6,7 @@
import { MesProBagCodeStatusEnum } from "@vben/constants";
import { downloadFileFromBlobPart } from "@vben/utils";
- import { message } from "ant-design-vue";
+ import { message, Modal } from "ant-design-vue";
import { ACTION_ICON, TableAction, useVbenVxeGrid } from "#/adapter/vxe-table";
import {
@@ -21,6 +21,7 @@
import { useGridColumns, useGridFormSchema } from "./data";
import BindPalletModal from "./modules/bind-pallet.vue";
import GenerateModal from "./modules/generate-form.vue";
+ import ReplaceModal from "./modules/replace-form.vue";
import QrTraceModal from "../components/qr-trace-modal.vue";
defineOptions({ name: "MesProBagCode" });
@@ -32,6 +33,11 @@
const [BindPalletFormModal, bindPalletFormModalApi] = useVbenModal({
connectedComponent: BindPalletModal,
+ destroyOnClose: true,
+ });
+
+ const [ReplaceFormModal, replaceFormModalApi] = useVbenModal({
+ connectedComponent: ReplaceModal,
destroyOnClose: true,
});
@@ -48,6 +54,12 @@
/** 鐢熸垚鏁版嵁鍖� */
function handleGenerate() {
generateFormModalApi.open();
+ }
+
+ /** 鏇挎崲鎴愬姛鍚庡睍绀虹粨鏋滃苟鍒锋柊鍒楄〃 */
+ function handleReplaceSuccess(result: MesProBagCodeApi.ReplaceResult) {
+ showReplaceResult(result);
+ handleRefresh();
}
/** 鎵爜杩芥函 */
@@ -88,12 +100,82 @@
/** 鑾峰彇鍕鹃�夌殑琚嬬爜璁板綍 */
function getSelectedRecords(): MesProBagCodeApi.BagCode[] | undefined {
- const records = gridApi.grid.getCheckboxRecords() as MesProBagCodeApi.BagCode[];
- if (records.length === 0) {
+ const records = [
+ ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
+ ...(gridApi.grid.getCheckboxRecords?.() ?? []),
+ ] as MesProBagCodeApi.BagCode[];
+ const uniqueRecords = [
+ ...new Map(records.map((record) => [record.id, record])).values(),
+ ];
+ if (uniqueRecords.length === 0) {
message.warning("璇疯嚦灏戝嬀閫変竴鏉¤鐮佽褰�");
return undefined;
}
- return records;
+ return uniqueRecords;
+ }
+
+ /** 灞曠ず鏇挎崲缁撴灉 */
+ function showReplaceResult(result: MesProBagCodeApi.ReplaceResult) {
+ const items = result.items ?? [];
+ const content = items.length
+ ? items
+ .map(
+ (item) =>
+ `${item.oldCode ?? "-"} 鈫� ${item.newCode ?? "-"}${
+ item.newPalletCode ? `锛堟墭鐩橈細${item.newPalletCode}锛塦 : ""
+ }`,
+ )
+ .join("\n")
+ : "鏇挎崲鏄庣粏鏆傛棤";
+ Modal.success({
+ title: "鐮存崯琚嬬爜鏇挎崲鎴愬姛",
+ content: `鎵规锛�${result.batchCode ?? "-"}\n鏇挎崲鏁伴噺锛�${
+ result.count ?? items.length
+ }\n${content}`,
+ centered: true,
+ });
+ }
+
+ /** 鎵归噺鏇挎崲鐮存崯琚嬬爜 */
+ async function handleReplace() {
+ const records = getSelectedRecords();
+ if (!records) return;
+ if (records.length > 200) {
+ message.warning("鍗曟鏈�澶氭浛鎹� 200 涓鐮�");
+ return;
+ }
+ const batchIds = new Set(records.map((record) => record.batchId));
+ if (batchIds.size > 1 || !records[0]?.batchId) {
+ message.warning("璇烽�夋嫨鍚屼竴鎵规涓嬬殑琚嬬爜杩涜鏇挎崲");
+ return;
+ }
+ if (
+ records.some(
+ (record) =>
+ record.status !== MesProBagCodeStatusEnum.GENERATED &&
+ record.status !== MesProBagCodeStatusEnum.PRINTED,
+ )
+ ) {
+ message.warning("浠呭凡鐢熸垚鎴栧凡瀵煎嚭鍗板埛鐨勮鐮佸厑璁告浛鎹�");
+ return;
+ }
+ if (records.some((record) => !record.id)) {
+ message.warning("鎵�閫夎鐮佺己灏戠紪鍙凤紝鏃犳硶鏇挎崲");
+ return;
+ }
+ try {
+ await confirm(`纭浣滃簾鎵�閫� ${records.length} 涓鐮佸苟鐢熸垚绛夐噺鏂扮爜鍚楋紵`);
+ } catch {
+ return;
+ }
+ const first = records[0]!;
+ replaceFormModalApi
+ .setData({
+ batchId: first.batchId!,
+ batchCode: first.batchCode,
+ ids: records.map((record) => record.id!),
+ })
+ .open();
}
/** 鎵归噺缁戝畾鎵樼洏 */
@@ -200,6 +282,7 @@
<Page auto-content-height>
<GenerateFormModal @success="handleRefresh" />
<BindPalletFormModal @success="handleRefresh" />
+ <ReplaceFormModal @success="handleReplaceSuccess" />
<QrTraceQueryModal />
<Grid table-title="琚嬬爜鍒楄〃锛堜竴琚嬩竴鐮侊級">
<template #toolbar-tools>
@@ -218,6 +301,12 @@
onClick: handleBindPallet,
},
{
+ label: '鐮存崯鏇挎崲',
+ type: 'primary',
+ auth: ['mes:pro-bag-code:replace'],
+ onClick: handleReplace,
+ },
+ {
label: '瑙g粦鎵樼洏',
auth: ['mes:pro-bag-code:update'],
onClick: handleUnbindPallet,
diff --git a/src/views/mes/pro/bagCode/modules/replace-form.vue b/src/views/mes/pro/bagCode/modules/replace-form.vue
new file mode 100644
index 0000000..99df840
--- /dev/null
+++ b/src/views/mes/pro/bagCode/modules/replace-form.vue
@@ -0,0 +1,105 @@
+<script lang="ts" setup>
+ import type { VbenFormSchema } from "#/adapter/form";
+ import type { MesProBagCodeApi } from "#/api/mes/pro/bagCode";
+
+ import { useVbenModal } from "@vben/common-ui";
+
+ import { message } from "ant-design-vue";
+
+ import { useVbenForm } from "#/adapter/form";
+ import { replaceBagCodes } from "#/api/mes/pro/bagCode";
+
+ defineOptions({ name: "MesProBagCodeReplaceForm" });
+
+ interface ModalData {
+ batchId: number;
+ batchCode?: string;
+ ids: number[];
+ }
+
+ const emit = defineEmits<{
+ success: [result: MesProBagCodeApi.ReplaceResult];
+ }>();
+
+ const schema: VbenFormSchema[] = [
+ {
+ fieldName: "batchCode",
+ label: "鐢熶骇鎵规",
+ component: "Input",
+ componentProps: {
+ disabled: true,
+ },
+ },
+ {
+ fieldName: "bagCount",
+ label: "鏇挎崲琚嬫暟",
+ component: "InputNumber",
+ componentProps: {
+ class: "!w-full",
+ disabled: true,
+ },
+ },
+ {
+ fieldName: "reason",
+ label: "鐮存崯鍘熷洜",
+ component: "Textarea",
+ formItemClass: "col-span-2",
+ componentProps: {
+ maxlength: 255,
+ placeholder: "璇疯緭鍏ョ牬鎹熷師鍥�",
+ rows: 3,
+ showCount: true,
+ },
+ rules: "required",
+ },
+ ];
+
+ const [Form, formApi] = useVbenForm({
+ commonConfig: {
+ componentProps: {
+ class: "w-full",
+ },
+ labelWidth: 100,
+ },
+ layout: "horizontal",
+ schema,
+ showDefaultActions: false,
+ });
+
+ const [Modal, modalApi] = useVbenModal({
+ async onConfirm() {
+ const { valid } = await formApi.validate();
+ if (!valid) return;
+ const data = modalApi.getData<ModalData>();
+ const values = await formApi.getValues();
+ modalApi.lock();
+ try {
+ const result = await replaceBagCodes({
+ batchId: data.batchId,
+ oldIds: data.ids,
+ reason: values.reason,
+ });
+ message.success(`宸叉垚鍔熸浛鎹� ${result.count ?? data.ids.length} 涓鐮乣);
+ emit("success", result);
+ await modalApi.close();
+ } finally {
+ modalApi.unlock();
+ }
+ },
+ onOpenChange(isOpen: boolean) {
+ if (!isOpen) return;
+ const data = modalApi.getData<ModalData>();
+ void formApi.setValues({
+ bagCount: data.ids.length,
+ batchCode: data.batchCode,
+ reason: undefined,
+ });
+ },
+ });
+</script>
+
+<template>
+ <Modal title="鐮存崯琚嬬爜鏇挎崲" class="w-2/5">
+ <Form class="mx-4" />
+ </Modal>
+</template>
diff --git a/src/views/mes/pro/components/qr-trace-modal.vue b/src/views/mes/pro/components/qr-trace-modal.vue
index 44813d4..710a2e7 100644
--- a/src/views/mes/pro/components/qr-trace-modal.vue
+++ b/src/views/mes/pro/components/qr-trace-modal.vue
@@ -328,6 +328,26 @@
field: "printTime",
label: "瀵煎嚭鍗板埛鏃堕棿",
},
+ {
+ field: "cancelTime",
+ label: "浣滃簾鏃堕棿",
+ },
+ {
+ field: "cancelReason",
+ label: "浣滃簾鍘熷洜",
+ },
+ {
+ field: "replacementUuid",
+ label: "鏇挎崲缁� UUID",
+ },
+ {
+ field: "replacedByCode",
+ label: "鏇挎崲鍚庤鐮�",
+ },
+ {
+ field: "replacementOfCode",
+ label: "鏇挎崲鏉ユ簮琚嬬爜",
+ },
],
});
--
Gitblit v1.9.3