From e8d0130a17ada98b553bb4d1641fc4b60c6dddca Mon Sep 17 00:00:00 2001 From: hwj Date: Mon, 1 Jun 2026 11:39:30 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat=EF=BC=9A=E4=BA=A7=E5=93=81=E7=89=A9?= =?UTF-8?q?=E6=96=99=E5=88=86=E7=B1=BB-=E6=B7=BB=E5=8A=A0=E4=BA=A7?= =?UTF-8?q?=E5=93=81/=E7=89=A9=E6=96=99=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/erp/product/category/index.ts | 5 +-- src/locales/en.ts | 6 ++-- src/locales/zh-CN.ts | 6 ++-- src/utils/dict.ts | 1 + .../product/category/ProductCategoryForm.vue | 36 ++++++++++++++++--- src/views/erp/product/category/index.vue | 25 +++++++++++-- 6 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/api/erp/product/category/index.ts b/src/api/erp/product/category/index.ts index d67ccffd..72cca0c9 100644 --- a/src/api/erp/product/category/index.ts +++ b/src/api/erp/product/category/index.ts @@ -8,13 +8,14 @@ export interface ProductCategoryVO { code: string // 分类编码 sort: number // 分类排序 status: number // 开启状态 + type: number // 类型 } // ERP 产品分类 API export const ProductCategoryApi = { // 查询产品分类列表 - getProductCategoryList: async () => { - return await request.get({ url: `/erp/product-category/list` }) + getProductCategoryList: async (type?: number) => { + return await request.get({ url: `/erp/product-category/list`, params: { type } }) }, // 查询产品分类精简列表 diff --git a/src/locales/en.ts b/src/locales/en.ts index 08e3518d..928d2cb5 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -1990,17 +1990,19 @@ export default { dialogCodePlaceholder: 'Please enter code', dialogNameLabel: 'Name', dialogNamePlaceholder: 'Please enter name', + dialogTypeLabel: 'Type', dialogSortLabel: 'Sort', dialogSortPlaceholder: 'Please enter sort', dialogStatusLabel: 'Status', dialogCancelButton: 'Cancel', dialogSubmitButton: 'Confirm', - treeRootName: 'Top Product Category', + treeRootName: 'Top Category', validatorParentRequired: 'Parent category can not be empty', validatorNameRequired: 'Name can not be empty', validatorCodeRequired: 'Code can not be empty', validatorSortRequired: 'Sort can not be empty', - validatorStatusRequired: 'Status can not be empty' + validatorStatusRequired: 'Status can not be empty', + validatorTypeRequired: 'Type can not be empty' }, ProductInformation: { moduleName: 'Product Material Information', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 1a70f1e9..068dd775 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -2855,17 +2855,19 @@ export default { dialogCodePlaceholder: '请输入编码', dialogNameLabel: '名称', dialogNamePlaceholder: '请输入名称', + dialogTypeLabel: '类型', dialogSortLabel: '排序', dialogSortPlaceholder: '请输入排序', dialogStatusLabel: '状态', dialogCancelButton: '取 消', dialogSubmitButton: '确 定', - treeRootName: '顶级产品分类', + treeRootName: '顶级分类', validatorParentRequired: '上级编号不能为空', validatorNameRequired: '名称不能为空', validatorCodeRequired: '编码不能为空', validatorSortRequired: '排序不能为空', - validatorStatusRequired: '状态不能为空' + validatorStatusRequired: '状态不能为空', + validatorTypeRequired: '类型不能为空' }, ProductInformation: { moduleName: '产品物料信息', diff --git a/src/utils/dict.ts b/src/utils/dict.ts index 826fac82..e2dc5ad9 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -234,6 +234,7 @@ export enum DICT_TYPE { ERP_AUTOCODE_PADDING_TYPE = "erp_autocode_padding_type", ERP_AUTOCODE_CYCLEMETHOD = "erp_autocode_cyclemethod", ERP_AUTOCODE_PARTTYPE = "erp_autocode_parttype", + MATERIAL_CLASSIFICATION_TYPE = 'material_classification_type', // ========== MES - 生产管理模块 ========== diff --git a/src/views/erp/product/category/ProductCategoryForm.vue b/src/views/erp/product/category/ProductCategoryForm.vue index 7c55e10b..e63c4754 100644 --- a/src/views/erp/product/category/ProductCategoryForm.vue +++ b/src/views/erp/product/category/ProductCategoryForm.vue @@ -7,6 +7,17 @@ label-width="120px" v-loading="formLoading" > + + + + {{ dict.label }} + + + - + @@ -66,14 +77,16 @@ const formData = ref({ name: undefined, code: undefined, sort: undefined, - status: CommonStatusEnum.ENABLE + status: CommonStatusEnum.ENABLE, + type: undefined }) const formRules = reactive({ parentId: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorParentRequired'), trigger: 'blur' }], name: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorNameRequired'), trigger: 'blur' }], code: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorCodeRequired'), trigger: 'blur' }], sort: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorSortRequired'), trigger: 'blur' }], - status: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorStatusRequired'), trigger: 'blur' }] + status: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorStatusRequired'), trigger: 'blur' }], + type: [{ required: true, message: t('FactoryModeling.ProductCategory.validatorTypeRequired'), trigger: 'change' }] }) const formRef = ref() // 表单 Ref const productCategoryTree = ref() // 树形结构 @@ -84,6 +97,12 @@ const open = async (type: string, id?: number) => { dialogTitle.value = t('action.' + type) formType.value = type resetForm() + if (!id) { + const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) + if (typeOptions.length > 0) { + formData.value.type = typeOptions[0].value + } + } // 修改时,设置数据 if (id) { formLoading.value = true @@ -129,7 +148,8 @@ const resetForm = () => { name: undefined, code: undefined, sort: undefined, - status: CommonStatusEnum.ENABLE + status: CommonStatusEnum.ENABLE, + type: undefined } formRef.value?.resetFields() } @@ -137,9 +157,15 @@ const resetForm = () => { /** 获得产品分类树 */ const getProductCategoryTree = async () => { productCategoryTree.value = [] - const data = await ProductCategoryApi.getProductCategoryList() + const data = await ProductCategoryApi.getProductCategoryList(formData.value.type) const root: Tree = { id: 0, name: t('FactoryModeling.ProductCategory.treeRootName'), children: [] } root.children = handleTree(data, 'id', 'parentId') productCategoryTree.value.push(root) } + +/** 类型变更时刷新上级编号树 */ +const handleTypeChange = async () => { + formData.value.parentId = undefined + await getProductCategoryTree() +} diff --git a/src/views/erp/product/category/index.vue b/src/views/erp/product/category/index.vue index 738fa5b8..5977c153 100644 --- a/src/views/erp/product/category/index.vue +++ b/src/views/erp/product/category/index.vue @@ -61,6 +61,14 @@ + + + ([]) // 列表的数据 +const activeTab = ref('') // 激活的 tab const queryParams = reactive({ name: undefined, - status: undefined + status: undefined, + type: undefined }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 @@ -147,7 +157,7 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - const data = await ProductCategoryApi.getProductCategoryList(queryParams) + const data = await ProductCategoryApi.getProductCategoryList(queryParams.type) list.value = handleTree(data, 'id', 'parentId') } finally { loading.value = false @@ -160,6 +170,12 @@ const handleQuery = () => { getList() } +/** Tab 切换操作 */ +const handleTabChange = (name: string) => { + queryParams.type = name ? Number(name) : undefined + getList() +} + /** 重置按钮操作 */ const resetQuery = () => { queryFormRef.value.resetFields() @@ -212,6 +228,11 @@ const toggleExpandAll = async () => { /** 初始化 **/ onMounted(() => { + const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) + if (typeOptions.length > 0) { + activeTab.value = String(typeOptions[0].value) + queryParams.type = typeOptions[0].value + } getList() }) From f887843d412786a0969cc028c76db18637ac4bd2 Mon Sep 17 00:00:00 2001 From: hwj Date: Mon, 1 Jun 2026 15:14:06 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat=EF=BC=9A=E4=BA=A7=E5=93=81=E7=89=A9?= =?UTF-8?q?=E6=96=99=E4=BF=A1=E6=81=AF-=E6=B7=BB=E5=8A=A0=E4=BA=A7?= =?UTF-8?q?=E5=93=81/=E7=89=A9=E6=96=99=E7=B1=BB=E5=9E=8B=E5=88=86?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/erp/product/category/index.ts | 4 +- src/locales/en.ts | 1 + src/locales/zh-CN.ts | 2 + src/views/erp/product/product/ProductForm.vue | 34 +++++++++++++++-- src/views/erp/product/product/index.vue | 38 +++++++++---------- 5 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/api/erp/product/category/index.ts b/src/api/erp/product/category/index.ts index 72cca0c9..69dc93ab 100644 --- a/src/api/erp/product/category/index.ts +++ b/src/api/erp/product/category/index.ts @@ -19,8 +19,8 @@ export const ProductCategoryApi = { }, // 查询产品分类精简列表 - getProductCategorySimpleList: async () => { - return await request.get({ url: `/erp/product-category/simple-list` }) + getProductCategorySimpleList: async (type?: number) => { + return await request.get({ url: `/erp/product-category/simple-list`, params: { type } }) }, // 查询产品分类详情 diff --git a/src/locales/en.ts b/src/locales/en.ts index 928d2cb5..14687bef 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -2055,6 +2055,7 @@ export default { validatorNameRequired: 'Product name can not be empty', validatorBarCodeRequired: 'Product barcode can not be empty', validatorCategoryRequired: 'Product category id can not be empty', + validatorCategoryTypeRequired: 'Type can not be empty', validatorUnitRequired: 'Unit id can not be empty', validatorStatusRequired: 'Product status can not be empty' }, diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 068dd775..bc78ea6f 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -2894,6 +2894,7 @@ export default { dialogBarCodePlaceholder: '请输入编码', dialogNameLabel: '名称', dialogNamePlaceholder: '请输入名称', + dialogCategoryTypeLabel: '类型', dialogCategoryLabel: '分类', dialogCategoryPlaceholder: '请选择分类', dialogUnitLabel: '单位', @@ -2920,6 +2921,7 @@ export default { validatorNameRequired: '产品名称不能为空', validatorBarCodeRequired: '产品条码不能为空', validatorCategoryRequired: '产品分类编号不能为空', + validatorCategoryTypeRequired: '类型不能为空', validatorUnitRequired: '单位编号不能为空', validatorStatusRequired: '产品状态不能为空' }, diff --git a/src/views/erp/product/product/ProductForm.vue b/src/views/erp/product/product/ProductForm.vue index 545033a5..f397106c 100644 --- a/src/views/erp/product/product/ProductForm.vue +++ b/src/views/erp/product/product/ProductForm.vue @@ -31,6 +31,19 @@ + + + + + {{ dict.label }} + + + + @@ -253,6 +266,7 @@ const formData = ref({ isCode: undefined, qrcodeUrl: undefined, templateJson: undefined, + categoryType: undefined, categoryId: undefined, unitId: undefined, status: undefined, @@ -432,6 +446,7 @@ const validateBarCode = (_rule, value, callback) => { callback() } const formRules = reactive({ + categoryType: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryTypeRequired'), trigger: 'change' }], name: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorNameRequired'), trigger: 'blur' }], barCode: [{ validator: validateBarCode, trigger: ['blur', 'change'] }], categoryId: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryRequired'), trigger: 'blur' }], @@ -449,9 +464,12 @@ const open = async (type: string, id?: number) => { dialogTitle.value = t('action.' + type) formType.value = type resetForm() - const categoryData = await ProductCategoryApi.getProductCategorySimpleList() - categoryList.value = handleTree(categoryData, 'id', 'parentId') - unitList.value = await ProductUnitApi.getProductUnitSimpleList() + if (!id) { + const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) + if (typeOptions.length > 0) { + formData.value.categoryType = typeOptions[0].value + } + } if (id) { formLoading.value = true try { @@ -485,6 +503,9 @@ const open = async (type: string, id?: number) => { formLoading.value = false } } + const categoryData = await ProductCategoryApi.getProductCategorySimpleList(formData.value.categoryType) + categoryList.value = handleTree(categoryData, 'id', 'parentId') + unitList.value = await ProductUnitApi.getProductUnitSimpleList() } defineExpose({ open }) @@ -507,6 +528,12 @@ const handleCodeAutoChange = (value: boolean) => { formRef.value?.clearValidate('barCode') } +const handleCategoryTypeChange = async () => { + formData.value.categoryId = undefined + const categoryData = await ProductCategoryApi.getProductCategorySimpleList(formData.value.categoryType) + categoryList.value = handleTree(categoryData, 'id', 'parentId') +} + const getQrcodeRefreshUrl = () => { if (!formData.value.id || !formData.value.barCode) return '' return `/erp/product/regenerate-code?id=${formData.value.id}&code=${encodeURIComponent(String(formData.value.barCode))}` @@ -572,6 +599,7 @@ const resetForm = () => { barCode: undefined, isCode: true, qrcodeUrl: undefined, + categoryType: undefined, categoryId: undefined, unitId: undefined, status: CommonStatusEnum.ENABLE, diff --git a/src/views/erp/product/product/index.vue b/src/views/erp/product/product/index.vue index 28214408..aec2349c 100644 --- a/src/views/erp/product/product/index.vue +++ b/src/views/erp/product/product/index.vue @@ -33,8 +33,13 @@ - - + + ([]) -const parentList = ref([]) const formVisible = ref(false) const formType = ref('') @@ -161,21 +163,17 @@ const handleExport = async () => { } onMounted(async () => { - queryParams.categoryId = 2 - await getList() - const categoryData = await ProductCategoryApi.getProductCategorySimpleList() - categoryList.value = handleTree(categoryData, 'id', 'parentId') - for (let i = 0; i < categoryData.length; i++) { - if (categoryData[i].parentId === 0) { - parentList.value.push(categoryData[i]); - } + const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) + if (typeOptions.length > 0) { + activeName = String(typeOptions[0].value) + queryParams.categoryType = typeOptions[0].value } - parentList.value.sort((a, b) => a.sort - b.sort); + await getList() }) -let activeName = '2' -const handleTabClick = (tab: TabsPaneContext) => { - queryParams.categoryId = tab.paneName +let activeName = '' +const handleTabChange = (name: string) => { + queryParams.categoryType = name ? Number(name) : undefined handleQuery() } From 057df9cdb9a7810e987b51d4c69ae3ce295c4785 Mon Sep 17 00:00:00 2001 From: hwj Date: Mon, 1 Jun 2026 16:03:47 +0800 Subject: [PATCH 3/3] =?UTF-8?q?style=EF=BC=9A=E4=BA=A7=E5=93=81BOM?= =?UTF-8?q?=E6=A8=A1=E5=9D=97-=E4=BA=A7=E5=93=81=E4=B8=8B=E6=8B=89?= =?UTF-8?q?=E6=A1=86=E6=B7=BB=E5=8A=A0=E4=BA=A7=E5=93=81=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/erp/product/product/index.ts | 4 ++-- src/views/mes/bom/BomForm.vue | 2 +- src/views/mes/bom/index.vue | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/erp/product/product/index.ts b/src/api/erp/product/product/index.ts index 3b8fbb3d..38eaa599 100644 --- a/src/api/erp/product/product/index.ts +++ b/src/api/erp/product/product/index.ts @@ -49,8 +49,8 @@ export const ProductApi = { return await request.get({ url: `/erp/product/simple-list-order` }) }, // 查询所有商品精简列表 - getMesProductSimpleList: async () => { - return await request.get({ url: `/erp/product/simple-list-product` }) + getMesProductSimpleList: async (params?: { categoryType?: number }) => { + return await request.get({ url: `/erp/product/simple-list-product`, params }) }, // 查询备件精简列表 getComponentSimpleList: async () => { diff --git a/src/views/mes/bom/BomForm.vue b/src/views/mes/bom/BomForm.vue index 98696afa..826d5c4e 100644 --- a/src/views/mes/bom/BomForm.vue +++ b/src/views/mes/bom/BomForm.vue @@ -117,7 +117,7 @@ const open = async (type: string, id?: number) => { } } unitList.value = await ProductUnitApi.getProductUnitSimpleList() - productList.value = await ProductApi.getMesProductSimpleList() + productList.value = await ProductApi.getMesProductSimpleList({ categoryType: 1 }) } defineExpose({ open }) diff --git a/src/views/mes/bom/index.vue b/src/views/mes/bom/index.vue index cfbdad2e..b6653035 100644 --- a/src/views/mes/bom/index.vue +++ b/src/views/mes/bom/index.vue @@ -256,6 +256,6 @@ const handleExport = async () => { /** 初始化 **/ onMounted(async () => { await getList() - productList.value = await ProductApi.getMesProductSimpleList() + productList.value = await ProductApi.getMesProductSimpleList({ categoryType: 1 }) })