From 6b1425d541da0babcebc3b30d4f16d82c39f69d0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 21 May 2026 00:58:45 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=88mes=EF=BC=89:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20md=20item=20=E7=9A=84=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/mes/md/item/components/index.ts | 2 + .../item/components/md-item-select-dialog.vue | 188 +++++++ .../mes/md/item/components/md-item-select.vue | 132 +++++ apps/web-antd/src/views/mes/md/item/data.ts | 474 +++++++++++++++++ apps/web-antd/src/views/mes/md/item/index.vue | 233 +++++++++ .../src/views/mes/md/item/modules/form.vue | 169 +++++++ .../views/mes/md/item/modules/import-form.vue | 103 ++++ .../item/modules/item-batch-config-form.vue | 125 +++++ .../mes/md/item/modules/product-bom-form.vue | 238 +++++++++ .../md/item/modules/product-media-list.vue | 231 +++++++++ .../mes/md/item/modules/product-sip-form.vue | 14 + .../mes/md/item/modules/product-sop-form.vue | 14 + .../mes/md/unitmeasure/components/index.ts | 1 + .../components/md-unit-measure-select.vue | 116 +++++ .../views/mes/pro/process/components/index.ts | 1 + .../process/components/pro-process-select.vue | 111 ++++ .../wm/barcode/components/barcode-detail.vue | 174 +++++++ .../mes/wm/barcode/components/barcode.vue | 54 ++ .../views/mes/wm/barcode/components/index.ts | 3 + .../wm/barcode/components/printer-label.vue | 30 ++ apps/web-ele/src/api/mes/pro/process/index.ts | 38 ++ apps/web-ele/src/api/mes/wm/barcode/index.ts | 65 +++ .../src/views/mes/md/item/components/index.ts | 2 + .../item/components/md-item-select-dialog.vue | 191 +++++++ .../mes/md/item/components/md-item-select.vue | 130 +++++ apps/web-ele/src/views/mes/md/item/data.ts | 478 ++++++++++++++++++ apps/web-ele/src/views/mes/md/item/index.vue | 241 +++++++++ .../src/views/mes/md/item/modules/form.vue | 169 +++++++ .../views/mes/md/item/modules/import-form.vue | 103 ++++ .../item/modules/item-batch-config-form.vue | 125 +++++ .../mes/md/item/modules/product-bom-form.vue | 249 +++++++++ .../md/item/modules/product-media-list.vue | 251 +++++++++ .../mes/md/item/modules/product-sip-form.vue | 14 + .../mes/md/item/modules/product-sop-form.vue | 14 + .../mes/md/unitmeasure/components/index.ts | 1 + .../components/md-unit-measure-select.vue | 119 +++++ .../views/mes/pro/process/components/index.ts | 1 + .../process/components/pro-process-select.vue | 116 +++++ .../wm/barcode/components/barcode-detail.vue | 175 +++++++ .../mes/wm/barcode/components/barcode.vue | 54 ++ .../views/mes/wm/barcode/components/index.ts | 3 + .../wm/barcode/components/printer-label.vue | 30 ++ 42 files changed, 4982 insertions(+) create mode 100644 apps/web-antd/src/views/mes/md/item/components/index.ts create mode 100644 apps/web-antd/src/views/mes/md/item/components/md-item-select-dialog.vue create mode 100644 apps/web-antd/src/views/mes/md/item/components/md-item-select.vue create mode 100644 apps/web-antd/src/views/mes/md/item/data.ts create mode 100644 apps/web-antd/src/views/mes/md/item/index.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/form.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/import-form.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/item-batch-config-form.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/product-bom-form.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/product-media-list.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/product-sip-form.vue create mode 100644 apps/web-antd/src/views/mes/md/item/modules/product-sop-form.vue create mode 100644 apps/web-antd/src/views/mes/md/unitmeasure/components/index.ts create mode 100644 apps/web-antd/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue create mode 100644 apps/web-antd/src/views/mes/pro/process/components/index.ts create mode 100644 apps/web-antd/src/views/mes/pro/process/components/pro-process-select.vue create mode 100644 apps/web-antd/src/views/mes/wm/barcode/components/barcode-detail.vue create mode 100644 apps/web-antd/src/views/mes/wm/barcode/components/barcode.vue create mode 100644 apps/web-antd/src/views/mes/wm/barcode/components/index.ts create mode 100644 apps/web-antd/src/views/mes/wm/barcode/components/printer-label.vue create mode 100644 apps/web-ele/src/api/mes/pro/process/index.ts create mode 100644 apps/web-ele/src/api/mes/wm/barcode/index.ts create mode 100644 apps/web-ele/src/views/mes/md/item/components/index.ts create mode 100644 apps/web-ele/src/views/mes/md/item/components/md-item-select-dialog.vue create mode 100644 apps/web-ele/src/views/mes/md/item/components/md-item-select.vue create mode 100644 apps/web-ele/src/views/mes/md/item/data.ts create mode 100644 apps/web-ele/src/views/mes/md/item/index.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/form.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/import-form.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/item-batch-config-form.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/product-bom-form.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/product-media-list.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/product-sip-form.vue create mode 100644 apps/web-ele/src/views/mes/md/item/modules/product-sop-form.vue create mode 100644 apps/web-ele/src/views/mes/md/unitmeasure/components/index.ts create mode 100644 apps/web-ele/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue create mode 100644 apps/web-ele/src/views/mes/pro/process/components/index.ts create mode 100644 apps/web-ele/src/views/mes/pro/process/components/pro-process-select.vue create mode 100644 apps/web-ele/src/views/mes/wm/barcode/components/barcode-detail.vue create mode 100644 apps/web-ele/src/views/mes/wm/barcode/components/barcode.vue create mode 100644 apps/web-ele/src/views/mes/wm/barcode/components/index.ts create mode 100644 apps/web-ele/src/views/mes/wm/barcode/components/printer-label.vue diff --git a/apps/web-antd/src/views/mes/md/item/components/index.ts b/apps/web-antd/src/views/mes/md/item/components/index.ts new file mode 100644 index 000000000..e5aa3ce08 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/components/index.ts @@ -0,0 +1,2 @@ +export { default as MdItemSelectDialog } from './md-item-select-dialog.vue'; +export { default as MdItemSelect } from './md-item-select.vue'; diff --git a/apps/web-antd/src/views/mes/md/item/components/md-item-select-dialog.vue b/apps/web-antd/src/views/mes/md/item/components/md-item-select-dialog.vue new file mode 100644 index 000000000..4f36d9260 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/components/md-item-select-dialog.vue @@ -0,0 +1,188 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/components/md-item-select.vue b/apps/web-antd/src/views/mes/md/item/components/md-item-select.vue new file mode 100644 index 000000000..dee1e1370 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/components/md-item-select.vue @@ -0,0 +1,132 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/data.ts b/apps/web-antd/src/views/mes/md/item/data.ts new file mode 100644 index 000000000..8c8d57624 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/data.ts @@ -0,0 +1,474 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesMdItemApi } from '#/api/mes/md/item'; +import type { MesMdProductBomApi } from '#/api/mes/md/item/productBom'; + +import { h, markRaw } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { Button } from 'ant-design-vue'; + +import { z } from '#/adapter/form'; +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { MdItemTypeSelect } from '#/views/mes/md/item/type/components'; +import { MdUnitMeasureSelect } from '#/views/mes/md/unitmeasure/components'; +import { MesAutoCodeRuleCode } from '#/views/mes/utils/constants'; + +/** 新增/修改物料产品的表单 */ +export function useFormSchema(formApi?: any): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + maxLength: 64, + placeholder: '请输入物料编码', + }, + rules: z.string().min(1, '物料编码不能为空').max(64), + suffix: () => + h( + Button, + { + type: 'default', + onClick: async () => { + try { + const code = await generateAutoCode( + MesAutoCodeRuleCode.MD_ITEM_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '生成' }, + ), + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + maxLength: 255, + placeholder: '请输入物料名称', + }, + rules: z.string().min(1, '物料名称不能为空').max(255), + }, + { + fieldName: 'specification', + label: '规格型号', + component: 'Input', + componentProps: { + maxLength: 255, + placeholder: '请输入规格型号', + }, + }, + { + fieldName: 'unitMeasureId', + label: '单位', + component: markRaw(MdUnitMeasureSelect), + componentProps: { + placeholder: '请选择计量单位', + }, + rules: 'selectRequired', + }, + { + fieldName: 'itemTypeId', + label: '物料分类', + component: markRaw(MdItemTypeSelect), + componentProps: { + onChange: async (itemType: any) => { + await formApi?.setFieldValue('itemOrProduct', itemType?.itemOrProduct); + }, + }, + rules: 'selectRequired', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + buttonStyle: 'solid', + disabled: true, + optionType: 'button', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.DISABLE), + }, + { + fieldName: 'highValue', + label: '高值物料', + component: 'Switch', + componentProps: { + checkedChildren: '是', + unCheckedChildren: '否', + }, + rules: z.boolean().default(false), + }, + { + fieldName: 'batchFlag', + label: '批次管理', + component: 'Switch', + componentProps: { + checkedChildren: '是', + unCheckedChildren: '否', + }, + rules: z.boolean().default(true), + }, + { + fieldName: 'safeStockFlag', + label: '安全库存', + component: 'Switch', + componentProps: { + checkedChildren: '是', + unCheckedChildren: '否', + }, + rules: z.boolean().default(false), + }, + { + fieldName: 'minStock', + label: '最低库存量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + min: 0, + precision: 2, + }, + dependencies: { + triggerFields: ['safeStockFlag'], + show: (values) => Boolean(values.safeStockFlag), + }, + rules: z.number().default(0), + }, + { + fieldName: 'maxStock', + label: '最高库存量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + min: 0, + precision: 2, + }, + dependencies: { + triggerFields: ['safeStockFlag'], + show: (values) => Boolean(values.safeStockFlag), + }, + rules: z.number().default(0), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'itemOrProduct', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入物料编码', + }, + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入物料名称', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + }, + }, + ]; +} + +/** 物料导入表单 */ +export function useImportFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'file', + label: '物料数据', + component: 'Upload', + rules: 'required', + help: '仅允许导入 xls、xlsx 格式文件', + }, + { + fieldName: 'updateSupport', + label: '是否覆盖', + component: 'Switch', + componentProps: { + checkedChildren: '是', + unCheckedChildren: '否', + }, + rules: z.boolean().default(false), + help: '是否更新已经存在的物料数据', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: MesMdItemApi.Item, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'code', + title: '物料编码', + minWidth: 160, + slots: { default: 'code' }, + }, + { + field: 'name', + title: '物料名称', + minWidth: 160, + }, + { + field: 'specification', + title: '规格型号', + minWidth: 160, + }, + { + field: 'unitMeasureName', + title: '单位', + width: 100, + align: 'center', + }, + { + field: 'itemTypeName', + title: '物料分类', + minWidth: 140, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'safeStockFlag', + title: '安全库存', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'status', + title: '状态', + width: 120, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + checkedValue: CommonStatusEnum.ENABLE, + unCheckedValue: CommonStatusEnum.DISABLE, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 物料选择弹窗搜索表单 */ +export function useItemSelectGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入物料编码', + }, + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入物料名称', + }, + }, + ]; +} + +/** 物料选择弹窗列表字段 */ +export function useItemSelectGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 50 }, + { + field: 'code', + title: '物料编码', + width: 180, + }, + { + field: 'name', + title: '物料名称', + minWidth: 160, + align: 'left', + }, + { + field: 'specification', + title: '规格型号', + minWidth: 140, + align: 'left', + }, + { + field: 'unitMeasureName', + title: '单位', + width: 90, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 110, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'itemTypeName', + title: '所属分类', + width: 140, + align: 'center', + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} + +/** 产品 BOM 子表字段 */ +export function useProductBomGridColumns( + isReadOnly = false, +): VxeTableGridOptions['columns'] { + const columns: VxeTableGridOptions['columns'] = [ + { + field: 'bomItemCode', + title: '物料编码', + minWidth: 160, + align: 'center', + }, + { + field: 'bomItemName', + title: '物料名称', + minWidth: 160, + align: 'center', + }, + { + field: 'bomItemSpecification', + title: '规格型号', + minWidth: 140, + align: 'center', + }, + { + field: 'unitMeasureName', + title: '单位', + width: 80, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 110, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'quantity', + title: '用量比例', + width: 100, + align: 'center', + }, + { + field: 'remark', + title: '备注', + minWidth: 140, + align: 'center', + }, + ]; + + if (!isReadOnly) { + columns.push({ + field: 'actions', + title: '操作', + width: 120, + align: 'center', + fixed: 'right', + slots: { default: 'actions' }, + }); + } + + return columns; +} diff --git a/apps/web-antd/src/views/mes/md/item/index.vue b/apps/web-antd/src/views/mes/md/item/index.vue new file mode 100644 index 000000000..3184639df --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/index.vue @@ -0,0 +1,233 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/form.vue b/apps/web-antd/src/views/mes/md/item/modules/form.vue new file mode 100644 index 000000000..3d52a4e9e --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/form.vue @@ -0,0 +1,169 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/import-form.vue b/apps/web-antd/src/views/mes/md/item/modules/import-form.vue new file mode 100644 index 000000000..053b4e4e9 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/import-form.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/item-batch-config-form.vue b/apps/web-antd/src/views/mes/md/item/modules/item-batch-config-form.vue new file mode 100644 index 000000000..d41aa7ce6 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/item-batch-config-form.vue @@ -0,0 +1,125 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/product-bom-form.vue b/apps/web-antd/src/views/mes/md/item/modules/product-bom-form.vue new file mode 100644 index 000000000..f4ce385ac --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/product-bom-form.vue @@ -0,0 +1,238 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/product-media-list.vue b/apps/web-antd/src/views/mes/md/item/modules/product-media-list.vue new file mode 100644 index 000000000..c9d0ba3a9 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/product-media-list.vue @@ -0,0 +1,231 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/product-sip-form.vue b/apps/web-antd/src/views/mes/md/item/modules/product-sip-form.vue new file mode 100644 index 000000000..8607155be --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/product-sip-form.vue @@ -0,0 +1,14 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/modules/product-sop-form.vue b/apps/web-antd/src/views/mes/md/item/modules/product-sop-form.vue new file mode 100644 index 000000000..e5c8d8515 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/modules/product-sop-form.vue @@ -0,0 +1,14 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/unitmeasure/components/index.ts b/apps/web-antd/src/views/mes/md/unitmeasure/components/index.ts new file mode 100644 index 000000000..59e066096 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/unitmeasure/components/index.ts @@ -0,0 +1 @@ +export { default as MdUnitMeasureSelect } from './md-unit-measure-select.vue'; diff --git a/apps/web-antd/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue b/apps/web-antd/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue new file mode 100644 index 000000000..f88b4ed73 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue @@ -0,0 +1,116 @@ + + + diff --git a/apps/web-antd/src/views/mes/pro/process/components/index.ts b/apps/web-antd/src/views/mes/pro/process/components/index.ts new file mode 100644 index 000000000..e0cca7d22 --- /dev/null +++ b/apps/web-antd/src/views/mes/pro/process/components/index.ts @@ -0,0 +1 @@ +export { default as ProProcessSelect } from './pro-process-select.vue'; diff --git a/apps/web-antd/src/views/mes/pro/process/components/pro-process-select.vue b/apps/web-antd/src/views/mes/pro/process/components/pro-process-select.vue new file mode 100644 index 000000000..5f2d8e8b0 --- /dev/null +++ b/apps/web-antd/src/views/mes/pro/process/components/pro-process-select.vue @@ -0,0 +1,111 @@ + + + diff --git a/apps/web-antd/src/views/mes/wm/barcode/components/barcode-detail.vue b/apps/web-antd/src/views/mes/wm/barcode/components/barcode-detail.vue new file mode 100644 index 000000000..885756ac3 --- /dev/null +++ b/apps/web-antd/src/views/mes/wm/barcode/components/barcode-detail.vue @@ -0,0 +1,174 @@ + + + diff --git a/apps/web-antd/src/views/mes/wm/barcode/components/barcode.vue b/apps/web-antd/src/views/mes/wm/barcode/components/barcode.vue new file mode 100644 index 000000000..ab8f78649 --- /dev/null +++ b/apps/web-antd/src/views/mes/wm/barcode/components/barcode.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/web-antd/src/views/mes/wm/barcode/components/index.ts b/apps/web-antd/src/views/mes/wm/barcode/components/index.ts new file mode 100644 index 000000000..87168be0a --- /dev/null +++ b/apps/web-antd/src/views/mes/wm/barcode/components/index.ts @@ -0,0 +1,3 @@ +export { default as BarcodeDetail } from './barcode-detail.vue'; +export { default as Barcode } from './barcode.vue'; +export { default as PrinterLabel } from './printer-label.vue'; diff --git a/apps/web-antd/src/views/mes/wm/barcode/components/printer-label.vue b/apps/web-antd/src/views/mes/wm/barcode/components/printer-label.vue new file mode 100644 index 000000000..52218299c --- /dev/null +++ b/apps/web-antd/src/views/mes/wm/barcode/components/printer-label.vue @@ -0,0 +1,30 @@ + + + diff --git a/apps/web-ele/src/api/mes/pro/process/index.ts b/apps/web-ele/src/api/mes/pro/process/index.ts new file mode 100644 index 000000000..5a3893b18 --- /dev/null +++ b/apps/web-ele/src/api/mes/pro/process/index.ts @@ -0,0 +1,38 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace MesProProcessApi { + /** MES 生产工序 */ + export interface Process { + id: number; + code?: string; + name?: string; + attention?: string; + status?: number; + remark?: string; + createTime?: Date; + } +} + +/** 查询生产工序分页 */ +export function getProcessPage(params: PageParam) { + return requestClient.get>( + '/mes/pro/process/page', + { params }, + ); +} + +/** 查询生产工序精简列表 */ +export function getProcessSimpleList() { + return requestClient.get( + '/mes/pro/process/simple-list', + ); +} + +/** 查询生产工序详情 */ +export function getProcess(id: number) { + return requestClient.get( + `/mes/pro/process/get?id=${id}`, + ); +} diff --git a/apps/web-ele/src/api/mes/wm/barcode/index.ts b/apps/web-ele/src/api/mes/wm/barcode/index.ts new file mode 100644 index 000000000..6cbf8a51e --- /dev/null +++ b/apps/web-ele/src/api/mes/wm/barcode/index.ts @@ -0,0 +1,65 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace MesWmBarcodeApi { + /** MES 条码清单 */ + export interface Barcode { + id?: number; + configId?: number; + format?: number; + bizType?: number; + content?: string; + bizId?: number; + bizCode?: string; + bizName?: string; + status?: number; + remark?: string; + createTime?: Date; + } +} + +/** 查询条码分页 */ +export function getBarcodePage(params: PageParam) { + return requestClient.get>( + '/mes/wm/barcode/page', + { params }, + ); +} + +/** 查询条码详情 */ +export function getBarcode(id: number) { + return requestClient.get( + `/mes/wm/barcode/get?id=${id}`, + ); +} + +/** 根据业务对象获取条码 */ +export function getBarcodeByBusiness(bizType: number, bizId: number) { + return requestClient.get( + '/mes/wm/barcode/get-by-business', + { params: { bizType, bizId } }, + ); +} + +/** 新增条码 */ +export function createBarcode(data: MesWmBarcodeApi.Barcode) { + return requestClient.post('/mes/wm/barcode/create', data); +} + +/** 修改条码 */ +export function updateBarcode(data: MesWmBarcodeApi.Barcode) { + return requestClient.put('/mes/wm/barcode/update', data); +} + +/** 删除条码 */ +export function deleteBarcode(id: number) { + return requestClient.delete(`/mes/wm/barcode/delete?id=${id}`); +} + +/** 生成条码内容 */ +export function generateBarcodeContent(bizType: number, bizCode: string) { + return requestClient.get('/mes/wm/barcode/generate-content', { + params: { bizType, bizCode }, + }); +} diff --git a/apps/web-ele/src/views/mes/md/item/components/index.ts b/apps/web-ele/src/views/mes/md/item/components/index.ts new file mode 100644 index 000000000..e5aa3ce08 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/components/index.ts @@ -0,0 +1,2 @@ +export { default as MdItemSelectDialog } from './md-item-select-dialog.vue'; +export { default as MdItemSelect } from './md-item-select.vue'; diff --git a/apps/web-ele/src/views/mes/md/item/components/md-item-select-dialog.vue b/apps/web-ele/src/views/mes/md/item/components/md-item-select-dialog.vue new file mode 100644 index 000000000..12c9a7eb1 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/components/md-item-select-dialog.vue @@ -0,0 +1,191 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/components/md-item-select.vue b/apps/web-ele/src/views/mes/md/item/components/md-item-select.vue new file mode 100644 index 000000000..b3079762a --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/components/md-item-select.vue @@ -0,0 +1,130 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/data.ts b/apps/web-ele/src/views/mes/md/item/data.ts new file mode 100644 index 000000000..2ba58e653 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/data.ts @@ -0,0 +1,478 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesMdItemApi } from '#/api/mes/md/item'; +import type { MesMdProductBomApi } from '#/api/mes/md/item/productBom'; + +import { h, markRaw } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { ElButton } from 'element-plus'; + +import { z } from '#/adapter/form'; +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { MdItemTypeSelect } from '#/views/mes/md/item/type/components'; +import { MdUnitMeasureSelect } from '#/views/mes/md/unitmeasure/components'; +import { MesAutoCodeRuleCode } from '#/views/mes/utils/constants'; + +/** 新增/修改物料产品的表单 */ +export function useFormSchema(formApi?: any): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + maxLength: 64, + placeholder: '请输入物料编码', + }, + rules: z.string().min(1, '物料编码不能为空').max(64), + suffix: () => + h( + ElButton, + { + type: 'default', + onClick: async () => { + try { + const code = await generateAutoCode( + MesAutoCodeRuleCode.MD_ITEM_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '生成' }, + ), + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + maxLength: 255, + placeholder: '请输入物料名称', + }, + rules: z.string().min(1, '物料名称不能为空').max(255), + }, + { + fieldName: 'specification', + label: '规格型号', + component: 'Input', + componentProps: { + maxLength: 255, + placeholder: '请输入规格型号', + }, + }, + { + fieldName: 'unitMeasureId', + label: '单位', + component: markRaw(MdUnitMeasureSelect), + componentProps: { + placeholder: '请选择计量单位', + }, + rules: 'selectRequired', + }, + { + fieldName: 'itemTypeId', + label: '物料分类', + component: markRaw(MdItemTypeSelect), + componentProps: { + onChange: async (itemType: any) => { + await formApi?.setFieldValue('itemOrProduct', itemType?.itemOrProduct); + }, + }, + rules: 'selectRequired', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + disabled: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.DISABLE), + }, + { + fieldName: 'highValue', + label: '高值物料', + component: 'Switch', + componentProps: { + activeText: '是', + inactiveText: '否', + inlinePrompt: true, + }, + rules: z.boolean().default(false), + }, + { + fieldName: 'batchFlag', + label: '批次管理', + component: 'Switch', + componentProps: { + activeText: '是', + inactiveText: '否', + inlinePrompt: true, + }, + rules: z.boolean().default(true), + }, + { + fieldName: 'safeStockFlag', + label: '安全库存', + component: 'Switch', + componentProps: { + activeText: '是', + inactiveText: '否', + inlinePrompt: true, + }, + rules: z.boolean().default(false), + }, + { + fieldName: 'minStock', + label: '最低库存量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + precision: 2, + }, + dependencies: { + triggerFields: ['safeStockFlag'], + show: (values) => Boolean(values.safeStockFlag), + }, + rules: z.number().default(0), + }, + { + fieldName: 'maxStock', + label: '最高库存量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + precision: 2, + }, + dependencies: { + triggerFields: ['safeStockFlag'], + show: (values) => Boolean(values.safeStockFlag), + }, + rules: z.number().default(0), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + formItemClass: 'col-span-3', + }, + { + fieldName: 'itemOrProduct', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入物料编码', + }, + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入物料名称', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + placeholder: '请选择状态', + }, + }, + ]; +} + +/** 物料导入表单 */ +export function useImportFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'file', + label: '物料数据', + component: 'Upload', + rules: 'required', + help: '仅允许导入 xls、xlsx 格式文件', + }, + { + fieldName: 'updateSupport', + label: '是否覆盖', + component: 'Switch', + componentProps: { + activeText: '是', + inactiveText: '否', + inlinePrompt: true, + }, + rules: z.boolean().default(false), + help: '是否更新已经存在的物料数据', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onStatusChange?: ( + newStatus: number, + row: MesMdItemApi.Item, + ) => PromiseLike, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'code', + title: '物料编码', + minWidth: 160, + slots: { default: 'code' }, + }, + { + field: 'name', + title: '物料名称', + minWidth: 160, + }, + { + field: 'specification', + title: '规格型号', + minWidth: 160, + }, + { + field: 'unitMeasureName', + title: '单位', + width: 100, + align: 'center', + }, + { + field: 'itemTypeName', + title: '物料分类', + minWidth: 140, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'safeStockFlag', + title: '安全库存', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'status', + title: '状态', + width: 120, + align: 'center', + cellRender: { + attrs: { beforeChange: onStatusChange }, + name: 'CellSwitch', + props: { + inactiveValue: CommonStatusEnum.DISABLE, + activeValue: CommonStatusEnum.ENABLE, + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 物料选择弹窗搜索表单 */ +export function useItemSelectGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '物料编码', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入物料编码', + }, + }, + { + fieldName: 'name', + label: '物料名称', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入物料名称', + }, + }, + ]; +} + +/** 物料选择弹窗列表字段 */ +export function useItemSelectGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 50 }, + { + field: 'code', + title: '物料编码', + width: 180, + }, + { + field: 'name', + title: '物料名称', + minWidth: 160, + align: 'left', + }, + { + field: 'specification', + title: '规格型号', + minWidth: 140, + align: 'left', + }, + { + field: 'unitMeasureName', + title: '单位', + width: 90, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 110, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'itemTypeName', + title: '所属分类', + width: 140, + align: 'center', + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} + +/** 产品 BOM 子表字段 */ +export function useProductBomGridColumns( + isReadOnly = false, +): VxeTableGridOptions['columns'] { + const columns: VxeTableGridOptions['columns'] = [ + { + field: 'bomItemCode', + title: '物料编码', + minWidth: 160, + align: 'center', + }, + { + field: 'bomItemName', + title: '物料名称', + minWidth: 160, + align: 'center', + }, + { + field: 'bomItemSpecification', + title: '规格型号', + minWidth: 140, + align: 'center', + }, + { + field: 'unitMeasureName', + title: '单位', + width: 80, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 110, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'quantity', + title: '用量比例', + width: 100, + align: 'center', + }, + { + field: 'remark', + title: '备注', + minWidth: 140, + align: 'center', + }, + ]; + + if (!isReadOnly) { + columns.push({ + field: 'actions', + title: '操作', + width: 120, + align: 'center', + fixed: 'right', + slots: { default: 'actions' }, + }); + } + + return columns; +} diff --git a/apps/web-ele/src/views/mes/md/item/index.vue b/apps/web-ele/src/views/mes/md/item/index.vue new file mode 100644 index 000000000..da06eeab9 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/index.vue @@ -0,0 +1,241 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/form.vue b/apps/web-ele/src/views/mes/md/item/modules/form.vue new file mode 100644 index 000000000..539c07014 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/form.vue @@ -0,0 +1,169 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/import-form.vue b/apps/web-ele/src/views/mes/md/item/modules/import-form.vue new file mode 100644 index 000000000..227826dd0 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/import-form.vue @@ -0,0 +1,103 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/item-batch-config-form.vue b/apps/web-ele/src/views/mes/md/item/modules/item-batch-config-form.vue new file mode 100644 index 000000000..dbbcc7539 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/item-batch-config-form.vue @@ -0,0 +1,125 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/product-bom-form.vue b/apps/web-ele/src/views/mes/md/item/modules/product-bom-form.vue new file mode 100644 index 000000000..3f1ff71be --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/product-bom-form.vue @@ -0,0 +1,249 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/product-media-list.vue b/apps/web-ele/src/views/mes/md/item/modules/product-media-list.vue new file mode 100644 index 000000000..a0ad8eef1 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/product-media-list.vue @@ -0,0 +1,251 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/product-sip-form.vue b/apps/web-ele/src/views/mes/md/item/modules/product-sip-form.vue new file mode 100644 index 000000000..8607155be --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/product-sip-form.vue @@ -0,0 +1,14 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/modules/product-sop-form.vue b/apps/web-ele/src/views/mes/md/item/modules/product-sop-form.vue new file mode 100644 index 000000000..e5c8d8515 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/modules/product-sop-form.vue @@ -0,0 +1,14 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/unitmeasure/components/index.ts b/apps/web-ele/src/views/mes/md/unitmeasure/components/index.ts new file mode 100644 index 000000000..59e066096 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/unitmeasure/components/index.ts @@ -0,0 +1 @@ +export { default as MdUnitMeasureSelect } from './md-unit-measure-select.vue'; diff --git a/apps/web-ele/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue b/apps/web-ele/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue new file mode 100644 index 000000000..3d7282589 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/unitmeasure/components/md-unit-measure-select.vue @@ -0,0 +1,119 @@ + + + diff --git a/apps/web-ele/src/views/mes/pro/process/components/index.ts b/apps/web-ele/src/views/mes/pro/process/components/index.ts new file mode 100644 index 000000000..e0cca7d22 --- /dev/null +++ b/apps/web-ele/src/views/mes/pro/process/components/index.ts @@ -0,0 +1 @@ +export { default as ProProcessSelect } from './pro-process-select.vue'; diff --git a/apps/web-ele/src/views/mes/pro/process/components/pro-process-select.vue b/apps/web-ele/src/views/mes/pro/process/components/pro-process-select.vue new file mode 100644 index 000000000..a2b86ffa6 --- /dev/null +++ b/apps/web-ele/src/views/mes/pro/process/components/pro-process-select.vue @@ -0,0 +1,116 @@ + + + diff --git a/apps/web-ele/src/views/mes/wm/barcode/components/barcode-detail.vue b/apps/web-ele/src/views/mes/wm/barcode/components/barcode-detail.vue new file mode 100644 index 000000000..dff9d23c5 --- /dev/null +++ b/apps/web-ele/src/views/mes/wm/barcode/components/barcode-detail.vue @@ -0,0 +1,175 @@ + + + diff --git a/apps/web-ele/src/views/mes/wm/barcode/components/barcode.vue b/apps/web-ele/src/views/mes/wm/barcode/components/barcode.vue new file mode 100644 index 000000000..ab8f78649 --- /dev/null +++ b/apps/web-ele/src/views/mes/wm/barcode/components/barcode.vue @@ -0,0 +1,54 @@ + + + diff --git a/apps/web-ele/src/views/mes/wm/barcode/components/index.ts b/apps/web-ele/src/views/mes/wm/barcode/components/index.ts new file mode 100644 index 000000000..87168be0a --- /dev/null +++ b/apps/web-ele/src/views/mes/wm/barcode/components/index.ts @@ -0,0 +1,3 @@ +export { default as BarcodeDetail } from './barcode-detail.vue'; +export { default as Barcode } from './barcode.vue'; +export { default as PrinterLabel } from './printer-label.vue'; diff --git a/apps/web-ele/src/views/mes/wm/barcode/components/printer-label.vue b/apps/web-ele/src/views/mes/wm/barcode/components/printer-label.vue new file mode 100644 index 000000000..cfa892f01 --- /dev/null +++ b/apps/web-ele/src/views/mes/wm/barcode/components/printer-label.vue @@ -0,0 +1,30 @@ + + +