Merge remote-tracking branch 'origin/feature/20260716/wms-module' into feature/20260716/wms-module

This commit is contained in:
zhouz
2026-07-27 14:56:27 +08:00
67 changed files with 2214 additions and 723 deletions

View File

@@ -92,5 +92,3 @@ export function operateTransportTask(data: {
}) {
return requestClient.post('/task/transport-task/operate', data);
}

View File

@@ -14,5 +14,7 @@ export const ACTION_ICON = {
BOOK: 'lucide:book',
AUDIT: 'lucide:file-check',
SEND: 'lucide:send',
CIRCLE_CHECK: 'lucide:circle-check',
CIRCLE_X: 'lucide:circle-x',
CANCEL: 'lucide:ban',
};

View File

@@ -1,12 +1,12 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { BaseMaterialBaseApi } from '#/api/base/materialbase';
import type {VbenFormSchema} from '#/adapter/form';
import type {VxeTableGridOptions} from '#/adapter/vxe-table';
import type {BaseMaterialBaseApi} from '#/api/base/materialbase';
import { handleTree } from '@vben/utils';
import {handleTree} from '@vben/utils';
import { getClassStandardList, getClassStandardListByCode } from '#/api/base/classstandard';
import { getSimpleMeasureUnitList } from '#/api/base/measureunit';
import { getRangePickerDefaultProps } from '#/utils';
import {getClassStandardList, getClassStandardListByCode} from '#/api/base/classstandard';
import {getSimpleMeasureUnitList} from '#/api/base/measureunit';
import {getRangePickerDefaultProps} from '#/utils';
// ========== 分类映射classId → className ==========
const classNameMap: Record<number, string> = {};
@@ -46,102 +46,218 @@ async function loadMeasureUnitList() {
// ========== 新增/修改的表单 ==========
export function useFormSchema(): VbenFormSchema[] {
return [
{ fieldName: 'materialId', component: 'Input', dependencies: { triggerFields: [''], show: () => false } },
{ fieldName: 'materialCode', label: '物料编码', rules: 'required', component: 'Input', componentProps: { placeholder: '请输入物料编码' } },
{ fieldName: 'materialName', label: '物料名称', rules: 'required', component: 'Input', componentProps: { placeholder: '请输入物料名称' } },
{ fieldName: 'materialSpec', label: '规格', component: 'Input', componentProps: { placeholder: '请输入规格' } },
{ fieldName: 'materialModel', label: '型号', component: 'Input', componentProps: { placeholder: '请输入型号' } },
{ fieldName: 'englishName', label: '外文名称', component: 'Input', componentProps: { placeholder: '请输入外文名称' } },
{
fieldName: 'materialId',
component: 'Input',
dependencies: {triggerFields: [''], show: () => false}
},
{
fieldName: 'materialCode',
label: '物料编码',
rules: 'required',
component: 'Input',
componentProps: {placeholder: '请输入物料编码'}
},
{
fieldName: 'materialName',
label: '物料名称',
rules: 'required',
component: 'Input',
componentProps: {placeholder: '请输入物料名称'}
},
{
fieldName: 'materialSpec',
label: '规格',
component: 'Input',
componentProps: {placeholder: '请输入规格'}
},
{
fieldName: 'materialModel',
label: '型号',
component: 'Input',
componentProps: {placeholder: '请输入型号'}
},
{
fieldName: 'englishName',
label: '外文名称',
component: 'Input',
componentProps: {placeholder: '请输入外文名称'}
},
{
fieldName: 'materialTypeId', label: '物料分类',
component: 'ApiTreeSelect',
componentProps: { api: loadMaterialTypeTree, labelField: 'className', valueField: 'classId', childrenField: 'children', placeholder: '请选择物料分类', allowClear: true, treeDefaultExpandAll: true },
componentProps: {
api: loadMaterialTypeTree,
labelField: 'className',
valueField: 'classId',
childrenField: 'children',
placeholder: '请选择物料分类',
allowClear: true,
treeDefaultExpandAll: true
},
},
{
fieldName: 'baseUnitId', label: '基本计量单位', rules: 'required',
component: 'ApiSelect',
componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择基本计量单位', allowClear: true },
componentProps: {
api: loadMeasureUnitList,
labelField: 'unitCode',
valueField: 'measureUnitId',
placeholder: '请选择基本计量单位',
allowClear: true
},
},
{
fieldName: 'assUnitId', label: '辅助计量单位',
component: 'ApiSelect',
componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择辅助计量单位', allowClear: true },
componentProps: {
api: loadMeasureUnitList,
labelField: 'unitCode',
valueField: 'measureUnitId',
placeholder: '请选择辅助计量单位',
allowClear: true
},
},
{
fieldName: 'lenUnitId', label: '长度单位',
component: 'ApiSelect',
componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择长度单位', allowClear: true },
componentProps: {
api: loadMeasureUnitList,
labelField: 'unitCode',
valueField: 'measureUnitId',
placeholder: '请选择长度单位',
allowClear: true
},
},
{
fieldName: 'weightUnitId', label: '重量单位',
component: 'ApiSelect',
componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择重量单位', allowClear: true },
componentProps: {
api: loadMeasureUnitList,
labelField: 'unitCode',
valueField: 'measureUnitId',
placeholder: '请选择重量单位',
allowClear: true
},
},
{
fieldName: 'cubageUnitId', label: '体积单位',
component: 'ApiSelect',
componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择体积单位', allowClear: true },
componentProps: {
api: loadMeasureUnitList,
labelField: 'unitCode',
valueField: 'measureUnitId',
placeholder: '请选择体积单位',
allowClear: true
},
},
{
fieldName: 'isUsed', label: '是否启用', rules: 'required',
component: 'RadioGroup',
componentProps: { options: [{ label: '是', value: '1' }, { label: '否', value: '0' }], buttonStyle: 'solid', optionType: 'button' },
componentProps: {
options: [{label: '是', value: '1'}, {label: '否', value: '0'}],
buttonStyle: 'solid',
optionType: 'button'
},
},
{
fieldName: 'extId',
label: '外部标识',
component: 'Input',
componentProps: {placeholder: '请输入外部标识'}
},
{ fieldName: 'extId', label: '外部标识', component: 'Input', componentProps: { placeholder: '请输入外部标识' } },
];
}
// ========== 列表的搜索表单 ==========
export function useGridFormSchema(): VbenFormSchema[] {
return [
{ fieldName: 'materialCode', label: '物料编码', component: 'Input', componentProps: { allowClear: true, placeholder: '请输入物料编码' } },
{ fieldName: 'materialName', label: '物料名称', component: 'Input', componentProps: { allowClear: true, placeholder: '请输入物料名称' } },
{
fieldName: 'materialCode',
label: '物料编码',
component: 'Input',
componentProps: {allowClear: true, placeholder: '请输入物料编码'}
},
{
fieldName: 'materialName',
label: '物料名称',
component: 'Input',
componentProps: {allowClear: true, placeholder: '请输入物料名称'}
},
{
fieldName: 'materialTypeId', label: '物料分类',
component: 'ApiTreeSelect',
componentProps: { api: loadMaterialTypeTree, labelField: 'className', valueField: 'classId', childrenField: 'children', placeholder: '请选择物料分类', allowClear: true },
componentProps: {
api: loadMaterialTypeTree,
labelField: 'className',
valueField: 'classId',
childrenField: 'children',
placeholder: '请选择物料分类',
allowClear: true
},
},
{
fieldName: 'createTime',
label: '创建时间',
component: 'RangePicker',
componentProps: {...getRangePickerDefaultProps(), allowClear: true}
},
{
fieldName: 'isUsed',
label: '是否启用',
component: 'Select',
componentProps: {
allowClear: true,
placeholder: '请选择',
options: [{label: '是', value: '1'}, {label: '否', value: '0'}]
}
},
{ fieldName: 'createTime', label: '创建时间', component: 'RangePicker', componentProps: { ...getRangePickerDefaultProps(), allowClear: true } },
{ fieldName: 'isUsed', label: '是否启用', component: 'Select', componentProps: { allowClear: true, placeholder: '请选择', options: [{ label: '是', value: '1' }, { label: '否', value: '0' }] } },
];
}
// ========== 列表的字段 ==========
export function useGridColumns(): VxeTableGridOptions<BaseMaterialBaseApi.MaterialBase>['columns'] {
return [
{ type: 'checkbox', width: 40 },
{ field: 'materialCode', title: '物料编码', minWidth: 120 },
{ field: 'materialName', title: '物料名称', minWidth: 200 },
{ field: 'materialSpec', title: '规格', minWidth: 120 },
{ field: 'materialModel', title: '型号', minWidth: 120 },
{ field: 'englishName', title: '外文名称', minWidth: 120 },
{type: 'checkbox', width: 40},
{field: 'materialCode', title: '物料编码', minWidth: 120},
{field: 'materialName', title: '物料名称', minWidth: 200},
{field: 'materialSpec', title: '规格', minWidth: 120},
{field: 'materialModel', title: '型号', minWidth: 120},
{field: 'englishName', title: '外文名称', minWidth: 120},
{
field: 'materialTypeId', title: '物料分类', minWidth: 150,
formatter: ({ cellValue }: { cellValue: number }) => classNameMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: {
cellValue: number
}) => classNameMap[cellValue] || cellValue || '-',
},
{
field: 'baseUnitId', title: '基本计量单位', minWidth: 120,
formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
},
{
field: 'assUnitId', title: '辅助计量单位', minWidth: 120,
formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
},
{
field: 'lenUnitId', title: '长度单位', minWidth: 120,
formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
},
{
field: 'weightUnitId', title: '重量单位', minWidth: 120,
formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
},
{
field: 'cubageUnitId', title: '体积单位', minWidth: 120,
formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-',
},
{ field: 'createTime', title: '创建时间', minWidth: 180, formatter: 'formatDateTime' },
{ field: 'isUsed', title: '是否启用', minWidth: 100, formatter: ({ cellValue }: { cellValue: string }) => (cellValue === '1' ? '是' : '否') },
{ field: 'extId', title: '外部标识', minWidth: 120 },
{ title: '操作', width: 200, fixed: 'right', slots: { default: 'actions' } },
{field: 'createTime', title: '创建时间', minWidth: 180, formatter: 'formatDateTime'},
{
field: 'isUsed',
title: '是否启用',
minWidth: 100,
formatter: ({cellValue}: { cellValue: string }) => (cellValue === '1' ? '是' : '否')
},
{field: 'extId', title: '外部标识', minWidth: 120},
{title: '操作', width: 200, fixed: 'right', slots: {default: 'actions'}},
];
}

View File

@@ -4,12 +4,31 @@ import type { TaskTransportTaskApi } from '#/api/task/transporttask';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { handleTree } from '@vben/utils';
import dayjs from 'dayjs';
import { getClassStandardListByCode } from '#/api/base/classstandard';
import { getRangePickerDefaultProps } from '#/utils';
const taskTypeNameMap: Record<string, string> = {};
async function loadTaskTypeTree() {
const data = await getClassStandardListByCode('0002');
if (!data || data.length === 0) return [];
return handleTree(data, 'classId', 'parentClassId');
}
/** 新增/修改的表单 */
export async function loadAllLookupData() {
const taskTypeData = await getClassStandardListByCode('0002');
taskTypeData?.forEach((item) => {
if (item.classCode) {
taskTypeNameMap[item.classCode] = item.className;
}
});
}
export function useFormSchema(): VbenFormSchema[] {
return [
{
@@ -369,11 +388,15 @@ export function useGridFormSchema(): VbenFormSchema[] {
{
fieldName: 'taskType',
label: '任务类型',
component: 'Select',
component: 'ApiTreeSelect',
componentProps: {
allowClear: true,
options: [],
api: loadTaskTypeTree,
childrenField: 'children',
labelField: 'className',
placeholder: '请选择任务类型',
treeDefaultExpandAll: true,
valueField: 'classCode',
},
},
{
@@ -588,6 +611,8 @@ export function useGridColumns(): VxeTableGridOptions<TaskTransportTaskApi.Trans
field: 'taskType',
title: '任务类型',
minWidth: 120,
formatter: ({ cellValue }: { cellValue: string }) =>
taskTypeNameMap[cellValue] || cellValue || '-',
},
{
field: 'acsTaskType',
@@ -608,6 +633,10 @@ export function useGridColumns(): VxeTableGridOptions<TaskTransportTaskApi.Trans
field: 'vehicleType',
title: '载具类型',
minWidth: 120,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.WMS_VEHICLE_TYPE },
},
},
{
field: 'vehicleQty',
@@ -632,6 +661,10 @@ export function useGridColumns(): VxeTableGridOptions<TaskTransportTaskApi.Trans
field: 'isAutoIssue',
title: '是否自动下发',
minWidth: 120,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.COMMON_IS_NO },
},
},
{
field: 'taskGroupId',
@@ -671,6 +704,10 @@ export function useGridColumns(): VxeTableGridOptions<TaskTransportTaskApi.Trans
field: 'createMode',
title: '生成方式',
minWidth: 120,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.TASK_CREATE_MODE },
},
},
{
field: 'requestParam',
@@ -706,10 +743,9 @@ export function useGridColumns(): VxeTableGridOptions<TaskTransportTaskApi.Trans
},
{
title: '操作',
width: 300,
width: 350,
fixed: 'right',
slots: { default: 'actions' },
},
];
}

View File

@@ -2,7 +2,7 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { TaskTransportTaskApi } from '#/api/task/transporttask';
import { ref } from 'vue';
import { onMounted, ref } from 'vue';
import { confirm, Page, useVbenModal } from '@vben/common-ui';
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
@@ -19,9 +19,15 @@ import {
} from '#/api/task/transporttask';
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import { loadAllLookupData, useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
const ready = ref(false);
onMounted(async () => {
await loadAllLookupData();
ready.value = true;
});
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
destroyOnClose: true,
@@ -141,7 +147,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
</script>
<template>
<Page auto-content-height>
<Page v-if="ready" auto-content-height>
<FormModal @success="handleRefresh" />
<Grid table-title="搬运任务列表">
<template #toolbar-tools>
@@ -170,23 +176,31 @@ const [Grid, gridApi] = useVbenVxeGrid({
<TableAction
:actions="[
{
label: '完成任务',
label: '下发',
type: 'link',
icon: ACTION_ICON.SEND,
auth: ['task:transport-task:issue'],
disabled: row.taskStatus !== '40',
onClick: handleOperate.bind(null, row, 'ISSUE', '下发任务'),
},
{
label: '完成',
type: 'link',
icon: ACTION_ICON.CIRCLE_CHECK,
auth: ['task:transport-task:finish'],
disabled: ['79', '89', '99'].includes(row.taskStatus),
disabled: ['79', '85', '89', '99'].includes(row.taskStatus),
onClick: handleOperate.bind(null, row, 'FINISHED', '完成任务'),
},
{
label: '取消任务',
label: '取消',
type: 'link',
icon: ACTION_ICON.CANCEL,
icon: ACTION_ICON.CIRCLE_X,
auth: ['task:transport-task:cancel'],
disabled: ['79', '89', '99'].includes(row.taskStatus),
disabled: ['75', '79', '89', '99'].includes(row.taskStatus),
onClick: handleOperate.bind(null, row, 'CANCELLED', '取消任务'),
},
{
label: '强制完成任务',
label: '强制完成',
type: 'link',
icon: ACTION_ICON.CANCEL,
auth: ['task:transport-task:cancel'],

View File

@@ -6,6 +6,7 @@ const COMMON_DICT = {
DATE_INTERVAL: 'date_interval', // 数据间隔
PRODUCT_AREA: 'product_area',
COMMON_TRUE_FALSE: 'common_true_false',
COMMON_IS_NO: 'common_is_no',
} as const;
/** ========== SYSTEM - 系统模块 ========== */
@@ -298,6 +299,7 @@ const TASK_DICT = {
TASK_FINISH_TYPE: 'task_finish_type',
TASK_STATUS: 'task_status', // 任务状态
TASK_ACS_TASK_TYPE: 'task_acs_task_type', // 任务状态
TASK_CREATE_MODE: 'task_create_mode', // 任务创建方式
} as const;
/** 字典类型枚举 - 统一导出 */