feat(mes): 迁移(wm-packages)相关迁移(优化代码)

pull/350/head
YunaiV 2026-05-29 23:50:48 +08:00
parent f1523e417b
commit 7ee42b9888
14 changed files with 311 additions and 167 deletions

View File

@ -0,0 +1,44 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesProCardApi {
/** MES 生产流转卡 */
export interface Card {
id?: number; // 编号
code?: string; // 流转卡编码
workOrderId?: number; // 生产工单编号
workOrderCode?: string; // 工单编码
workOrderName?: string; // 工单名称
batchCode?: string; // 批次号
itemId?: number; // 产品物料编号
itemCode?: string; // 产品编码
itemName?: string; // 产品名称
specification?: string; // 规格型号
unitMeasureName?: string; // 单位名称
transferedQuantity?: number; // 流转数量
status?: number; // 状态
remark?: string; // 备注
}
/** MES 生产流转卡分页查询参数 */
export interface PageParams extends PageParam {
code?: string;
workOrderId?: number;
itemId?: number;
batchCode?: string;
}
}
/** 查询生产流转卡分页 */
export function getCardPage(params: MesProCardApi.PageParams) {
return requestClient.get<PageResult<MesProCardApi.Card>>(
'/mes/pro/card/page',
{ params },
);
}
/** 查询生产流转卡详情 */
export function getCard(id: number) {
return requestClient.get<MesProCardApi.Card>(`/mes/pro/card/get?id=${id}`);
}

View File

@ -36,6 +36,26 @@ export namespace MesWmBatchApi {
qualityStatus?: number; // 质量状态
remark?: string; // 备注
}
/** MES 批次分页查询参数 */
export interface PageParams extends PageParam {
code?: string;
itemId?: number;
vendorId?: number;
clientId?: number;
workOrderId?: number;
taskId?: number;
workstationId?: number;
toolId?: number;
moldId?: number;
salesOrderCode?: string;
purchaseOrderCode?: string;
lotNumber?: string;
qualityStatus?: number;
produceDate?: string[];
expireDate?: string[];
receiptDate?: string[];
}
}
/** 查询批次详情 */
@ -44,7 +64,7 @@ export function getBatch(id: number) {
}
/** 查询批次分页 */
export function getBatchPage(params: PageParam) {
export function getBatchPage(params: MesWmBatchApi.PageParams) {
return requestClient.get<PageResult<MesWmBatchApi.Batch>>(
'/mes/wm/batch/page',
{ params },

View File

@ -153,6 +153,8 @@ export const MesAutoCodeRuleCode = {
WM_LOCATION_CODE: 'WM_LOCATION_CODE',
WM_MISC_ISSUE_CODE: 'WM_MISC_ISSUE_CODE',
WM_MISC_RECEIPT_CODE: 'WM_MISC_RECEIPT_CODE',
WM_OUTSOURCE_ISSUE_CODE: 'WM_OUTSOURCE_ISSUE_CODE',
WM_OUTSOURCE_RECEIPT_CODE: 'WM_OUTSOURCE_RECEIPT_CODE',
WM_PACKAGE_CODE: 'WM_PACKAGE_CODE',
WM_WAREHOUSE_CODE: 'WM_WAREHOUSE_CODE',
} as const;
@ -173,6 +175,13 @@ export const MesProWorkOrderStatusEnum = {
CANCELLED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 工单类型枚举 */
export const MesProWorkOrderTypeEnum = {
SELF: 1, // 自行生产
OUTSOURCE: 2, // 代工
PURCHASE: 3, // 采购
} as const;
/** MES 生产任务状态枚举 */
export const MesProTaskStatusEnum = {
PREPARE: MesOrderStatusConstants.DRAFT,
@ -236,6 +245,24 @@ export const MesWmMiscReceiptStatusEnum = {
CANCELED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 外协发料单状态枚举 */
export const MesWmOutsourceIssueStatusEnum = {
PREPARE: MesOrderStatusConstants.DRAFT,
APPROVING: MesOrderStatusConstants.APPROVING,
APPROVED: MesOrderStatusConstants.APPROVED,
FINISHED: MesOrderStatusConstants.FINISHED,
CANCELLED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 外协入库单状态枚举 */
export const MesWmOutsourceReceiptStatusEnum = {
PREPARE: MesOrderStatusConstants.DRAFT,
APPROVING: MesOrderStatusConstants.APPROVING,
APPROVED: MesOrderStatusConstants.APPROVED,
FINISHED: MesOrderStatusConstants.FINISHED,
CANCELED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 质检结果值类型枚举 */
export const MesQcResultValueType = {
FLOAT: 1,

View File

@ -4,7 +4,7 @@ import type { MesWmPackageApi } from '#/api/mes/wm/packages';
import { nextTick, ref } from 'vue';
import { Alert, message, Modal } from 'ant-design-vue';
import { Alert, Button, message, Modal } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getPackagePage } from '#/api/mes/wm/packages';
@ -29,87 +29,72 @@ const emit = defineEmits<{
const open = ref(false); //
const multiple = ref(true); //
const syncingSingleSelection = ref(false); //
const selectedRows = ref<MesWmPackageApi.Package[]>([]); //
const preSelectedIds = ref<number[]>([]); //
/** 单选模式同步 VXE 勾选状态 */
async function syncSingleSelection(row?: MesWmPackageApi.Package) {
syncingSingleSelection.value = true;
await nextTick();
await gridApi.grid.clearCheckboxRow();
if (row) {
await gridApi.grid.setCheckboxRow(row, true);
}
await nextTick();
syncingSingleSelection.value = false;
/** 获取多选记录,包含 VXE reserve 跨页记录 */
function getMultipleSelectedRows() {
const selectedMap = new Map<number, MesWmPackageApi.Package>();
const records = [
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
...(gridApi.grid.getCheckboxRecords?.() ?? []),
] as MesWmPackageApi.Package[];
records.forEach((row) => {
if (row.id != null) {
selectedMap.set(row.id, row);
}
});
return [...selectedMap.values()];
}
/** 处理勾选变化 */
async function handleCheckboxChange({
checked,
records,
row,
}: {
checked: boolean;
records: MesWmPackageApi.Package[];
row?: MesWmPackageApi.Package;
}) {
if (syncingSingleSelection.value) {
return;
}
if (!multiple.value) {
const selected = checked && row ? [row] : [];
selectedRows.value = selected;
await syncSingleSelection(selected[0]);
return;
}
selectedRows.value = records;
function handleCheckboxSelectChange() {
selectedRows.value = getMultipleSelectedRows();
}
/** 处理全选变化 */
function handleCheckboxAll({
records,
}: {
records: MesWmPackageApi.Package[];
}) {
if (syncingSingleSelection.value) {
return;
}
selectedRows.value = records;
/** 处理单选变化 */
function handleRadioChange(row: MesWmPackageApi.Package) {
selectedRows.value = [row];
}
/** 双击行:单选直接确认;多选切换勾选 */
async function handleRowDblclick({ row }: { row: MesWmPackageApi.Package }) {
/** 多选模式下切换行勾选 */
async function toggleMultipleRow(row: MesWmPackageApi.Package) {
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
await gridApi.grid.setCheckboxRow(row, !selected);
selectedRows.value = getMultipleSelectedRows();
}
/** 处理行双击:单选直接确认;多选切换勾选 */
async function handleCellDblclick({ row }: { row: MesWmPackageApi.Package }) {
if (multiple.value) {
const checked = !gridApi.grid.isCheckedByCheckboxRow(row);
await gridApi.grid.setCheckboxRow(row, checked);
handleCheckboxChange({
checked,
records:
gridApi.grid.getCheckboxRecords() as MesWmPackageApi.Package[],
row,
});
await toggleMultipleRow(row);
return;
}
selectedRows.value = [row];
await syncSingleSelection(row);
await gridApi.grid.setRadioRow(row);
handleConfirm();
}
/** 回显预选 */
function applyPreSelection() {
/** 回显预选装箱单 */
async function applyPreSelection() {
if (preSelectedIds.value.length === 0) {
return;
}
const rows = gridApi.grid.getData() as MesWmPackageApi.Package[];
for (const row of rows) {
if (row.id && preSelectedIds.value.includes(row.id)) {
gridApi.grid.setCheckboxRow(row, true);
if (!multiple.value) {
selectedRows.value = [row];
}
if (row.id == null || !preSelectedIds.value.includes(row.id)) {
continue;
}
if (multiple.value) {
await gridApi.grid.setCheckboxRow(row, true);
} else {
await gridApi.grid.setRadioRow(row);
selectedRows.value = [row];
return;
}
}
if (multiple.value) {
selectedRows.value = getMultipleSelectedRows();
}
}
@ -118,7 +103,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useSelectGridFormSchema(),
},
gridOptions: {
columns: useSelectGridColumns(),
columns: useSelectGridColumns(true),
height: 480,
keepSource: true,
checkboxConfig: {
@ -126,6 +111,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
range: true,
reserve: true,
},
radioConfig: {
highlight: true,
trigger: 'row',
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
@ -157,9 +146,12 @@ const [Grid, gridApi] = useVbenVxeGrid({
},
} as VxeTableGridOptions<MesWmPackageApi.Package>,
gridEvents: {
cellDblclick: handleRowDblclick,
checkboxAll: handleCheckboxAll,
checkboxChange: handleCheckboxChange,
cellDblclick: handleCellDblclick,
checkboxAll: handleCheckboxSelectChange,
checkboxChange: handleCheckboxSelectChange,
radioChange: ({ row }: { row: MesWmPackageApi.Package }) => {
handleRadioChange(row);
},
},
});
@ -167,10 +159,12 @@ const [Grid, gridApi] = useVbenVxeGrid({
async function resetQueryState() {
selectedRows.value = [];
await gridApi.grid.clearCheckboxRow();
await gridApi.grid.clearCheckboxReserve();
await gridApi.grid.clearRadioRow();
await gridApi.formApi.resetForm();
}
/** 打开弹窗 */
/** 打开装箱单选择弹窗 */
async function openModal(
selectedIds?: number[],
options?: { multiple?: boolean },
@ -179,28 +173,28 @@ async function openModal(
multiple.value = options?.multiple ?? true;
preSelectedIds.value = selectedIds || [];
await nextTick();
gridApi.setGridOptions({
columns: useSelectGridColumns(multiple.value),
});
await resetQueryState();
await gridApi.query();
await nextTick();
applyPreSelection();
await applyPreSelection();
}
/** 关闭弹窗 */
async function closeModal() {
function closeModal() {
open.value = false;
await resetQueryState();
}
/** 确认选择 */
function handleConfirm() {
if (selectedRows.value.length === 0) {
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
if (rows.length === 0) {
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
return;
}
emit(
'selected',
multiple.value ? selectedRows.value : [selectedRows.value[0]!],
);
emit('selected', multiple.value ? rows : [rows[0]!]);
open.value = false;
}
@ -224,5 +218,9 @@ defineExpose({ open: openModal });
type="info"
/>
<Grid table-title="" />
<template #footer>
<Button @click="closeModal"></Button>
<Button type="primary" @click="handleConfirm"></Button>
</template>
</Modal>
</template>

View File

@ -569,10 +569,12 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
}
/** 选择弹窗的字段 */
export function useSelectGridColumns(): VxeTableGridOptions<MesWmPackageApi.Package>['columns'] {
export function useSelectGridColumns(
multiple = true,
): VxeTableGridOptions<MesWmPackageApi.Package>['columns'] {
return [
{
type: 'checkbox',
type: multiple ? 'checkbox' : 'radio',
width: 50,
},
{

View File

@ -72,18 +72,14 @@ const [Grid, gridApi] = useVbenVxeGrid({
columns: useGridColumns(),
height: 'auto',
keepSource: true,
pagerConfig: {
enabled: false,
},
proxyConfig: {
ajax: {
query: async (_, formValues) => {
const data = await getPackagePage({
pageNo: 1,
pageSize: 100,
query: async ({ page }, formValues) => {
return await getPackagePage({
pageNo: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
return { list: data.list || [] };
},
},
},

View File

@ -32,7 +32,6 @@ const originalSnapshot = ref(''); // 表单原始数据快照,用于 finish
const isEditable = computed(() =>
['create', 'update'].includes(formType.value),
);
// TODO @AI (
const canFinish = computed(
() =>
formType.value === 'update' &&

View File

@ -19,7 +19,7 @@ import { useLineFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MesWmPackageLineApi.PackageLine>();
const packageId = ref<number>(); // TODO @AI
const packageId = ref<number>(); //
const getTitle = computed(() =>
formData.value?.id
? $t('ui.actionTitle.edit', ['装箱明细'])

View File

@ -0,0 +1,44 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesProCardApi {
/** MES 生产流转卡 */
export interface Card {
id?: number; // 编号
code?: string; // 流转卡编码
workOrderId?: number; // 生产工单编号
workOrderCode?: string; // 工单编码
workOrderName?: string; // 工单名称
batchCode?: string; // 批次号
itemId?: number; // 产品物料编号
itemCode?: string; // 产品编码
itemName?: string; // 产品名称
specification?: string; // 规格型号
unitMeasureName?: string; // 单位名称
transferedQuantity?: number; // 流转数量
status?: number; // 状态
remark?: string; // 备注
}
/** MES 生产流转卡分页查询参数 */
export interface PageParams extends PageParam {
code?: string;
workOrderId?: number;
itemId?: number;
batchCode?: string;
}
}
/** 查询生产流转卡分页 */
export function getCardPage(params: MesProCardApi.PageParams) {
return requestClient.get<PageResult<MesProCardApi.Card>>(
'/mes/pro/card/page',
{ params },
);
}
/** 查询生产流转卡详情 */
export function getCard(id: number) {
return requestClient.get<MesProCardApi.Card>(`/mes/pro/card/get?id=${id}`);
}

View File

@ -36,6 +36,26 @@ export namespace MesWmBatchApi {
qualityStatus?: number; // 质量状态
remark?: string; // 备注
}
/** MES 批次分页查询参数 */
export interface PageParams extends PageParam {
code?: string;
itemId?: number;
vendorId?: number;
clientId?: number;
workOrderId?: number;
taskId?: number;
workstationId?: number;
toolId?: number;
moldId?: number;
salesOrderCode?: string;
purchaseOrderCode?: string;
lotNumber?: string;
qualityStatus?: number;
produceDate?: string[];
expireDate?: string[];
receiptDate?: string[];
}
}
/** 查询批次详情 */
@ -44,7 +64,7 @@ export function getBatch(id: number) {
}
/** 查询批次分页 */
export function getBatchPage(params: PageParam) {
export function getBatchPage(params: MesWmBatchApi.PageParams) {
return requestClient.get<PageResult<MesWmBatchApi.Batch>>(
'/mes/wm/batch/page',
{ params },

View File

@ -29,87 +29,72 @@ const emit = defineEmits<{
const open = ref(false); //
const multiple = ref(true); //
const syncingSingleSelection = ref(false); //
const selectedRows = ref<MesWmPackageApi.Package[]>([]); //
const preSelectedIds = ref<number[]>([]); //
/** 单选模式同步 VXE 勾选状态 */
async function syncSingleSelection(row?: MesWmPackageApi.Package) {
syncingSingleSelection.value = true;
await nextTick();
await gridApi.grid.clearCheckboxRow();
if (row) {
await gridApi.grid.setCheckboxRow(row, true);
}
await nextTick();
syncingSingleSelection.value = false;
/** 获取多选记录,包含 VXE reserve 跨页记录 */
function getMultipleSelectedRows() {
const selectedMap = new Map<number, MesWmPackageApi.Package>();
const records = [
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
...(gridApi.grid.getCheckboxRecords?.() ?? []),
] as MesWmPackageApi.Package[];
records.forEach((row) => {
if (row.id != null) {
selectedMap.set(row.id, row);
}
});
return [...selectedMap.values()];
}
/** 处理勾选变化 */
async function handleCheckboxChange({
checked,
records,
row,
}: {
checked: boolean;
records: MesWmPackageApi.Package[];
row?: MesWmPackageApi.Package;
}) {
if (syncingSingleSelection.value) {
return;
}
if (!multiple.value) {
const selected = checked && row ? [row] : [];
selectedRows.value = selected;
await syncSingleSelection(selected[0]);
return;
}
selectedRows.value = records;
function handleCheckboxSelectChange() {
selectedRows.value = getMultipleSelectedRows();
}
/** 处理全选变化 */
function handleCheckboxAll({
records,
}: {
records: MesWmPackageApi.Package[];
}) {
if (syncingSingleSelection.value) {
return;
}
selectedRows.value = records;
/** 处理单选变化 */
function handleRadioChange(row: MesWmPackageApi.Package) {
selectedRows.value = [row];
}
/** 双击行:单选直接确认;多选切换勾选 */
async function handleRowDblclick({ row }: { row: MesWmPackageApi.Package }) {
/** 多选模式下切换行勾选 */
async function toggleMultipleRow(row: MesWmPackageApi.Package) {
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
await gridApi.grid.setCheckboxRow(row, !selected);
selectedRows.value = getMultipleSelectedRows();
}
/** 处理行双击:单选直接确认;多选切换勾选 */
async function handleCellDblclick({ row }: { row: MesWmPackageApi.Package }) {
if (multiple.value) {
const checked = !gridApi.grid.isCheckedByCheckboxRow(row);
await gridApi.grid.setCheckboxRow(row, checked);
handleCheckboxChange({
checked,
records:
gridApi.grid.getCheckboxRecords() as MesWmPackageApi.Package[],
row,
});
await toggleMultipleRow(row);
return;
}
selectedRows.value = [row];
await syncSingleSelection(row);
await gridApi.grid.setRadioRow(row);
handleConfirm();
}
/** 回显预选 */
function applyPreSelection() {
/** 回显预选装箱单 */
async function applyPreSelection() {
if (preSelectedIds.value.length === 0) {
return;
}
const rows = gridApi.grid.getData() as MesWmPackageApi.Package[];
for (const row of rows) {
if (row.id && preSelectedIds.value.includes(row.id)) {
gridApi.grid.setCheckboxRow(row, true);
if (!multiple.value) {
selectedRows.value = [row];
}
if (row.id == null || !preSelectedIds.value.includes(row.id)) {
continue;
}
if (multiple.value) {
await gridApi.grid.setCheckboxRow(row, true);
} else {
await gridApi.grid.setRadioRow(row);
selectedRows.value = [row];
return;
}
}
if (multiple.value) {
selectedRows.value = getMultipleSelectedRows();
}
}
@ -118,7 +103,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useSelectGridFormSchema(),
},
gridOptions: {
columns: useSelectGridColumns(),
columns: useSelectGridColumns(true),
height: 480,
keepSource: true,
checkboxConfig: {
@ -126,6 +111,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
range: true,
reserve: true,
},
radioConfig: {
highlight: true,
trigger: 'row',
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
@ -157,9 +146,12 @@ const [Grid, gridApi] = useVbenVxeGrid({
},
} as VxeTableGridOptions<MesWmPackageApi.Package>,
gridEvents: {
cellDblclick: handleRowDblclick,
checkboxAll: handleCheckboxAll,
checkboxChange: handleCheckboxChange,
cellDblclick: handleCellDblclick,
checkboxAll: handleCheckboxSelectChange,
checkboxChange: handleCheckboxSelectChange,
radioChange: ({ row }: { row: MesWmPackageApi.Package }) => {
handleRadioChange(row);
},
},
});
@ -167,10 +159,12 @@ const [Grid, gridApi] = useVbenVxeGrid({
async function resetQueryState() {
selectedRows.value = [];
await gridApi.grid.clearCheckboxRow();
await gridApi.grid.clearCheckboxReserve();
await gridApi.grid.clearRadioRow();
await gridApi.formApi.resetForm();
}
/** 打开弹窗 */
/** 打开装箱单选择弹窗 */
async function openModal(
selectedIds?: number[],
options?: { multiple?: boolean },
@ -179,28 +173,28 @@ async function openModal(
multiple.value = options?.multiple ?? true;
preSelectedIds.value = selectedIds || [];
await nextTick();
gridApi.setGridOptions({
columns: useSelectGridColumns(multiple.value),
});
await resetQueryState();
await gridApi.query();
await nextTick();
applyPreSelection();
await applyPreSelection();
}
/** 关闭弹窗 */
async function closeModal() {
function closeModal() {
open.value = false;
await resetQueryState();
}
/** 确认选择 */
function handleConfirm() {
if (selectedRows.value.length === 0) {
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
if (rows.length === 0) {
ElMessage.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
return;
}
emit(
'selected',
multiple.value ? selectedRows.value : [selectedRows.value[0]!],
);
emit('selected', multiple.value ? rows : [rows[0]!]);
open.value = false;
}

View File

@ -576,10 +576,12 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
}
/** 选择弹窗的字段 */
export function useSelectGridColumns(): VxeTableGridOptions<MesWmPackageApi.Package>['columns'] {
export function useSelectGridColumns(
multiple = true,
): VxeTableGridOptions<MesWmPackageApi.Package>['columns'] {
return [
{
type: 'checkbox',
type: multiple ? 'checkbox' : 'radio',
width: 50,
},
{

View File

@ -71,18 +71,14 @@ const [Grid, gridApi] = useVbenVxeGrid({
columns: useGridColumns(),
height: 'auto',
keepSource: true,
pagerConfig: {
enabled: false,
},
proxyConfig: {
ajax: {
query: async (_, formValues) => {
const data = await getPackagePage({
pageNo: 1,
pageSize: 100,
query: async ({ page }, formValues) => {
return await getPackagePage({
pageNo: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
return { list: data.list || [] };
},
},
},

View File

@ -230,6 +230,8 @@ const MES_DICT = {
MES_WM_MISC_ISSUE_STATUS: 'mes_wm_misc_issue_status', // MES 杂项出库单状态
MES_WM_MISC_RECEIPT_TYPE: 'mes_wm_misc_receipt_type', // MES 杂项入库类型
MES_WM_MISC_RECEIPT_STATUS: 'mes_wm_misc_receipt_status', // MES 杂项入库单状态
MES_WM_OUTSOURCE_ISSUE_STATUS: 'mes_wm_outsource_issue_status', // MES 外协发料单状态
MES_WM_OUTSOURCE_RECEIPT_STATUS: 'mes_wm_outsource_receipt_status', // MES 外协入库单状态
} as const;
/** ========== WMS - 仓储管理模块 ========== */