From 1bdc0d992f86d181af85017ed2559c0ef72bde31 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 19 May 2026 22:20:13 +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=20type=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/api/mes/md/autocode/record/index.ts | 9 + .../src/api/mes/md/item/type/index.ts | 54 +++++ .../mes/md/item/type/components/index.ts | 2 + .../type/components/md-item-type-select.vue | 120 ++++++++++ .../type/components/md-item-type-tree.vue | 128 ++++++++++ .../src/views/mes/md/item/type/data.ts | 219 ++++++++++++++++++ .../src/views/mes/md/item/type/index.vue | 160 +++++++++++++ .../views/mes/md/item/type/modules/form.vue | 97 ++++++++ .../web-antd/src/views/mes/utils/constants.ts | 16 ++ .../src/api/mes/md/autocode/record/index.ts | 9 + .../web-ele/src/api/mes/md/item/type/index.ts | 54 +++++ .../mes/md/item/type/components/index.ts | 2 + .../type/components/md-item-type-select.vue | 120 ++++++++++ .../type/components/md-item-type-tree.vue | 128 ++++++++++ .../src/views/mes/md/item/type/data.ts | 216 +++++++++++++++++ .../src/views/mes/md/item/type/index.vue | 161 +++++++++++++ .../views/mes/md/item/type/modules/form.vue | 97 ++++++++ apps/web-ele/src/views/mes/utils/constants.ts | 16 ++ 18 files changed, 1608 insertions(+) create mode 100644 apps/web-antd/src/api/mes/md/autocode/record/index.ts create mode 100644 apps/web-antd/src/api/mes/md/item/type/index.ts create mode 100644 apps/web-antd/src/views/mes/md/item/type/components/index.ts create mode 100644 apps/web-antd/src/views/mes/md/item/type/components/md-item-type-select.vue create mode 100644 apps/web-antd/src/views/mes/md/item/type/components/md-item-type-tree.vue create mode 100644 apps/web-antd/src/views/mes/md/item/type/data.ts create mode 100644 apps/web-antd/src/views/mes/md/item/type/index.vue create mode 100644 apps/web-antd/src/views/mes/md/item/type/modules/form.vue create mode 100644 apps/web-antd/src/views/mes/utils/constants.ts create mode 100644 apps/web-ele/src/api/mes/md/autocode/record/index.ts create mode 100644 apps/web-ele/src/api/mes/md/item/type/index.ts create mode 100644 apps/web-ele/src/views/mes/md/item/type/components/index.ts create mode 100644 apps/web-ele/src/views/mes/md/item/type/components/md-item-type-select.vue create mode 100644 apps/web-ele/src/views/mes/md/item/type/components/md-item-type-tree.vue create mode 100644 apps/web-ele/src/views/mes/md/item/type/data.ts create mode 100644 apps/web-ele/src/views/mes/md/item/type/index.vue create mode 100644 apps/web-ele/src/views/mes/md/item/type/modules/form.vue create mode 100644 apps/web-ele/src/views/mes/utils/constants.ts diff --git a/apps/web-antd/src/api/mes/md/autocode/record/index.ts b/apps/web-antd/src/api/mes/md/autocode/record/index.ts new file mode 100644 index 000000000..6110249ee --- /dev/null +++ b/apps/web-antd/src/api/mes/md/autocode/record/index.ts @@ -0,0 +1,9 @@ +import { requestClient } from '#/api/request'; + +/** 生成 MES 编码 */ +export function generateAutoCode(ruleCode: string, inputChar?: string) { + return requestClient.post('/mes/md/auto-code-record/generate', { + inputChar, + ruleCode, + }); +} diff --git a/apps/web-antd/src/api/mes/md/item/type/index.ts b/apps/web-antd/src/api/mes/md/item/type/index.ts new file mode 100644 index 000000000..edbcd7abd --- /dev/null +++ b/apps/web-antd/src/api/mes/md/item/type/index.ts @@ -0,0 +1,54 @@ +import { requestClient } from '#/api/request'; + +export namespace MesMdItemTypeApi { + /** MES 物料产品分类 */ + export interface ItemType { + id?: number; + parentId?: number; + code?: string; + name?: string; + itemOrProduct?: string; + sort?: number; + status?: number; + remark?: string; + createTime?: Date; + children?: ItemType[]; + } +} + +/** 查询物料产品分类列表 */ +export function getItemTypeList(params?: any) { + return requestClient.get( + '/mes/md/item-type/list', + { params }, + ); +} + +/** 查询物料产品分类精简列表 */ +export function getItemTypeSimpleList() { + return requestClient.get( + '/mes/md/item-type/simple-list', + ); +} + +/** 查询物料产品分类详情 */ +export function getItemType(id: number) { + return requestClient.get( + `/mes/md/item-type/get?id=${id}`, + ); +} + +/** 新增物料产品分类 */ +export function createItemType(data: MesMdItemTypeApi.ItemType) { + return requestClient.post('/mes/md/item-type/create', data); +} + +/** 修改物料产品分类 */ +export function updateItemType(data: MesMdItemTypeApi.ItemType) { + return requestClient.put('/mes/md/item-type/update', data); +} + +/** 删除物料产品分类 */ +export function deleteItemType(id: number) { + return requestClient.delete(`/mes/md/item-type/delete?id=${id}`); +} diff --git a/apps/web-antd/src/views/mes/md/item/type/components/index.ts b/apps/web-antd/src/views/mes/md/item/type/components/index.ts new file mode 100644 index 000000000..c5d4dd2c4 --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/components/index.ts @@ -0,0 +1,2 @@ +export { default as MdItemTypeSelect } from './md-item-type-select.vue'; +export { default as MdItemTypeTree } from './md-item-type-tree.vue'; diff --git a/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-select.vue b/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-select.vue new file mode 100644 index 000000000..939225e0f --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-select.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-tree.vue b/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-tree.vue new file mode 100644 index 000000000..79efa3b2e --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/components/md-item-type-tree.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/type/data.ts b/apps/web-antd/src/views/mes/md/item/type/data.ts new file mode 100644 index 000000000..fba2543bf --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/data.ts @@ -0,0 +1,219 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesMdItemTypeApi } from '#/api/mes/md/item/type'; + +import { h } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { Button } from 'ant-design-vue'; + +import { z } from '#/adapter/form'; +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { getItemTypeList } from '#/api/mes/md/item/type'; +import { + MesAutoCodeRuleCode, + MesItemOrProductEnum, +} from '#/views/mes/utils/constants'; + +/** 新增/修改物料分类的表单 */ +export function useFormSchema(formApi?: any): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级分类', + component: 'ApiTreeSelect', + componentProps: { + allowClear: true, + api: async () => { + const data = await getItemTypeList(); + return [ + { + id: 0, + name: '顶级分类', + children: handleTree(data), + }, + ]; + }, + childrenField: 'children', + labelField: 'name', + placeholder: '请选择上级分类', + treeDefaultExpandAll: true, + treeNodeFilterProp: 'name', + valueField: 'id', + }, + rules: 'selectRequired', + }, + { + 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_TYPE_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '自动生成' }, + ), + }, + { + fieldName: 'name', + label: '分类名称', + component: 'Input', + componentProps: { + placeholder: '请输入分类名称', + }, + rules: 'required', + }, + { + fieldName: 'itemOrProduct', + label: '物料/产品标识', + component: 'RadioGroup', + componentProps: { + buttonStyle: 'solid', + optionType: 'button', + options: getDictOptions(DICT_TYPE.MES_MD_ITEM_OR_PRODUCT), + }, + rules: z.string().default(MesItemOrProductEnum.ITEM.value), + }, + { + fieldName: 'sort', + label: '显示排序', + component: 'InputNumber', + componentProps: { + class: '!w-full', + min: 0, + precision: 0, + }, + rules: z.number().default(0), + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + buttonStyle: 'solid', + optionType: 'button', + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + 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 useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '分类名称', + minWidth: 200, + align: 'left', + treeNode: true, + }, + { + field: 'code', + title: '分类编码', + width: 160, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 130, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'sort', + title: '排序', + width: 100, + align: 'center', + }, + { + field: 'status', + title: '状态', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/mes/md/item/type/index.vue b/apps/web-antd/src/views/mes/md/item/type/index.vue new file mode 100644 index 000000000..6b2906f1a --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/index.vue @@ -0,0 +1,160 @@ + + + diff --git a/apps/web-antd/src/views/mes/md/item/type/modules/form.vue b/apps/web-antd/src/views/mes/md/item/type/modules/form.vue new file mode 100644 index 000000000..7ea21bbbf --- /dev/null +++ b/apps/web-antd/src/views/mes/md/item/type/modules/form.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-antd/src/views/mes/utils/constants.ts b/apps/web-antd/src/views/mes/utils/constants.ts new file mode 100644 index 000000000..1e28f3d91 --- /dev/null +++ b/apps/web-antd/src/views/mes/utils/constants.ts @@ -0,0 +1,16 @@ +/** MES 物料/产品标识枚举 */ +export const MesItemOrProductEnum = { + ITEM: { + label: '物料', + value: 'ITEM', + }, + PRODUCT: { + label: '产品', + value: 'PRODUCT', + }, +} as const; + +/** MES 自动编码规则 Code 枚举 */ +export const MesAutoCodeRuleCode = { + MD_ITEM_TYPE_CODE: 'MD_ITEM_TYPE_CODE', +} as const; diff --git a/apps/web-ele/src/api/mes/md/autocode/record/index.ts b/apps/web-ele/src/api/mes/md/autocode/record/index.ts new file mode 100644 index 000000000..6110249ee --- /dev/null +++ b/apps/web-ele/src/api/mes/md/autocode/record/index.ts @@ -0,0 +1,9 @@ +import { requestClient } from '#/api/request'; + +/** 生成 MES 编码 */ +export function generateAutoCode(ruleCode: string, inputChar?: string) { + return requestClient.post('/mes/md/auto-code-record/generate', { + inputChar, + ruleCode, + }); +} diff --git a/apps/web-ele/src/api/mes/md/item/type/index.ts b/apps/web-ele/src/api/mes/md/item/type/index.ts new file mode 100644 index 000000000..edbcd7abd --- /dev/null +++ b/apps/web-ele/src/api/mes/md/item/type/index.ts @@ -0,0 +1,54 @@ +import { requestClient } from '#/api/request'; + +export namespace MesMdItemTypeApi { + /** MES 物料产品分类 */ + export interface ItemType { + id?: number; + parentId?: number; + code?: string; + name?: string; + itemOrProduct?: string; + sort?: number; + status?: number; + remark?: string; + createTime?: Date; + children?: ItemType[]; + } +} + +/** 查询物料产品分类列表 */ +export function getItemTypeList(params?: any) { + return requestClient.get( + '/mes/md/item-type/list', + { params }, + ); +} + +/** 查询物料产品分类精简列表 */ +export function getItemTypeSimpleList() { + return requestClient.get( + '/mes/md/item-type/simple-list', + ); +} + +/** 查询物料产品分类详情 */ +export function getItemType(id: number) { + return requestClient.get( + `/mes/md/item-type/get?id=${id}`, + ); +} + +/** 新增物料产品分类 */ +export function createItemType(data: MesMdItemTypeApi.ItemType) { + return requestClient.post('/mes/md/item-type/create', data); +} + +/** 修改物料产品分类 */ +export function updateItemType(data: MesMdItemTypeApi.ItemType) { + return requestClient.put('/mes/md/item-type/update', data); +} + +/** 删除物料产品分类 */ +export function deleteItemType(id: number) { + return requestClient.delete(`/mes/md/item-type/delete?id=${id}`); +} diff --git a/apps/web-ele/src/views/mes/md/item/type/components/index.ts b/apps/web-ele/src/views/mes/md/item/type/components/index.ts new file mode 100644 index 000000000..c5d4dd2c4 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/components/index.ts @@ -0,0 +1,2 @@ +export { default as MdItemTypeSelect } from './md-item-type-select.vue'; +export { default as MdItemTypeTree } from './md-item-type-tree.vue'; diff --git a/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-select.vue b/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-select.vue new file mode 100644 index 000000000..6616dd2f3 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-select.vue @@ -0,0 +1,120 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-tree.vue b/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-tree.vue new file mode 100644 index 000000000..afeba53bb --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/components/md-item-type-tree.vue @@ -0,0 +1,128 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/type/data.ts b/apps/web-ele/src/views/mes/md/item/type/data.ts new file mode 100644 index 000000000..7bdd9df98 --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/data.ts @@ -0,0 +1,216 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesMdItemTypeApi } from '#/api/mes/md/item/type'; + +import { h } from 'vue'; + +import { CommonStatusEnum, DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { ElButton } from 'element-plus'; + +import { z } from '#/adapter/form'; +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { getItemTypeList } from '#/api/mes/md/item/type'; +import { + MesAutoCodeRuleCode, + MesItemOrProductEnum, +} from '#/views/mes/utils/constants'; + +/** 新增/修改物料分类的表单 */ +export function useFormSchema(formApi?: any): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'parentId', + label: '上级分类', + component: 'ApiTreeSelect', + componentProps: { + clearable: true, + api: async () => { + const data = await getItemTypeList(); + return [ + { + id: 0, + name: '顶级分类', + children: handleTree(data), + }, + ]; + }, + checkStrictly: true, + childrenField: 'children', + defaultExpandAll: true, + labelField: 'name', + placeholder: '请选择上级分类', + valueField: 'id', + }, + rules: 'selectRequired', + }, + { + 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_TYPE_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '自动生成' }, + ), + }, + { + fieldName: 'name', + label: '分类名称', + component: 'Input', + componentProps: { + placeholder: '请输入分类名称', + }, + rules: 'required', + }, + { + fieldName: 'itemOrProduct', + label: '物料/产品标识', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.MES_MD_ITEM_OR_PRODUCT), + }, + rules: z.string().default(MesItemOrProductEnum.ITEM.value), + }, + { + fieldName: 'sort', + label: '显示排序', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + precision: 0, + }, + rules: z.number().default(0), + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + 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 useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '分类名称', + minWidth: 200, + align: 'left', + treeNode: true, + }, + { + field: 'code', + title: '分类编码', + width: 160, + align: 'center', + }, + { + field: 'itemOrProduct', + title: '物料/产品', + width: 130, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_MD_ITEM_OR_PRODUCT }, + }, + }, + { + field: 'sort', + title: '排序', + width: 100, + align: 'center', + }, + { + field: 'status', + title: '状态', + width: 120, + align: 'center', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 260, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mes/md/item/type/index.vue b/apps/web-ele/src/views/mes/md/item/type/index.vue new file mode 100644 index 000000000..e334a5eec --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/index.vue @@ -0,0 +1,161 @@ + + + diff --git a/apps/web-ele/src/views/mes/md/item/type/modules/form.vue b/apps/web-ele/src/views/mes/md/item/type/modules/form.vue new file mode 100644 index 000000000..a4e53b91e --- /dev/null +++ b/apps/web-ele/src/views/mes/md/item/type/modules/form.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-ele/src/views/mes/utils/constants.ts b/apps/web-ele/src/views/mes/utils/constants.ts new file mode 100644 index 000000000..1e28f3d91 --- /dev/null +++ b/apps/web-ele/src/views/mes/utils/constants.ts @@ -0,0 +1,16 @@ +/** MES 物料/产品标识枚举 */ +export const MesItemOrProductEnum = { + ITEM: { + label: '物料', + value: 'ITEM', + }, + PRODUCT: { + label: '产品', + value: 'PRODUCT', + }, +} as const; + +/** MES 自动编码规则 Code 枚举 */ +export const MesAutoCodeRuleCode = { + MD_ITEM_TYPE_CODE: 'MD_ITEM_TYPE_CODE', +} as const;