From d9a1b07f0711f4e7e5f18c5682739a0f416af3a1 Mon Sep 17 00:00:00 2001 From: hwj Date: Mon, 8 Jun 2026 16:32:38 +0800 Subject: [PATCH] =?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=E6=A0=91?= =?UTF-8?q?=E7=8A=B6=E7=BB=93=E6=9E=84?= 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 | 5 +- src/locales/zh-CN.ts | 5 +- .../product/category/ProductCategoryForm.vue | 9 +- src/views/erp/product/product/index.vue | 258 ++++++++++++++---- 5 files changed, 232 insertions(+), 50 deletions(-) diff --git a/src/api/erp/product/category/index.ts b/src/api/erp/product/category/index.ts index 69dc93ab..bf70d21c 100644 --- a/src/api/erp/product/category/index.ts +++ b/src/api/erp/product/category/index.ts @@ -13,6 +13,11 @@ export interface ProductCategoryVO { // ERP 产品分类 API export const ProductCategoryApi = { + // 查询产品分类分组树 + getProductCategoryGroupTree: async () => { + return await request.get({ url: `/erp/product-category/group-tree` }) + }, + // 查询产品分类列表 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 69cc15d2..3a8cd776 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -2058,7 +2058,10 @@ export default { 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' + validatorStatusRequired: 'Product status can not be empty', + categoryTree: 'Category Tree', + addCategory: 'Add Category', + refreshTree: 'Refresh' }, AutocodeRule: { moduleName: 'Code Rules', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 0761e82a..f360eab9 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -3209,7 +3209,10 @@ export default { validatorCategoryRequired: '产品分类编号不能为空', validatorCategoryTypeRequired: '类型不能为空', validatorUnitRequired: '单位编号不能为空', - validatorStatusRequired: '产品状态不能为空' + validatorStatusRequired: '产品状态不能为空', + categoryTree: '产品分类树', + addCategory: '新增分类', + refreshTree: '刷新' }, AutocodeRule: { moduleName: '编码规则', diff --git a/src/views/erp/product/category/ProductCategoryForm.vue b/src/views/erp/product/category/ProductCategoryForm.vue index e63c4754..8323ba28 100644 --- a/src/views/erp/product/category/ProductCategoryForm.vue +++ b/src/views/erp/product/category/ProductCategoryForm.vue @@ -92,12 +92,17 @@ const formRef = ref() // 表单 Ref const productCategoryTree = ref() // 树形结构 /** 打开弹窗 */ -const open = async (type: string, id?: number) => { +const open = async (type: string, id?: number, defaultData?: any) => { dialogVisible.value = true dialogTitle.value = t('action.' + type) formType.value = type resetForm() - if (!id) { + // 设置默认值 + if (defaultData) { + if (defaultData.type !== undefined) formData.value.type = defaultData.type + if (defaultData.parentId !== undefined) formData.value.parentId = defaultData.parentId + } + if (!id && !defaultData) { const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) if (typeOptions.length > 0) { formData.value.type = typeOptions[0].value diff --git a/src/views/erp/product/product/index.vue b/src/views/erp/product/product/index.vue index aec2349c..ca9ab690 100644 --- a/src/views/erp/product/product/index.vue +++ b/src/views/erp/product/product/index.vue @@ -32,52 +32,96 @@ - - - - - - - - - - - - - - - - + + + @@ -85,7 +129,9 @@ import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' import { ProductApi, ProductVO } from '@/api/erp/product/product' +import { ProductCategoryApi } from '@/api/erp/product/category' import ProductForm from './ProductForm.vue' +import ProductCategoryForm from '../category/ProductCategoryForm.vue' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import BomForm from "@/views/mes/bom/BomForm.vue"; @@ -111,6 +157,69 @@ const exportLoading = ref(false) const formVisible = ref(false) const formType = ref('') +/** 分类树数据 */ +const groupTreeData = ref([]) +const treeRef = ref() +const typeDict = computed(() => getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)) + +const treeData = computed(() => { + return (groupTreeData.value || []).map((group: any) => { + const dictItem = typeDict.value.find((d: any) => d.value === group.type) + const name = dictItem?.label || String(group.type) + return { + nodeKey: `type_${group.type}`, + name, + type: group.type, + isType: true, + children: (group.children || []).map((child: any) => ({ + ...child, + nodeKey: `cat_${child.id}`, + isType: false + })) + } + }) +}) + +const fetchGroupTree = async () => { + const res = await ProductCategoryApi.getProductCategoryGroupTree() + groupTreeData.value = res +} + +/** 树节点点击 - 筛选产品 */ +const handleTreeNodeClick = (data: any) => { + if (data.isType) { + queryParams.categoryType = data.type + queryParams.categoryId = undefined + } else { + queryParams.categoryType = data.type + queryParams.categoryId = data.id + } + handleQuery() +} + +/** 分类增删改 */ +const categoryFormRef = ref() +const openCategoryForm = (type: string, data?: any) => { + const treeData = type === 'update' ? data : undefined + const defaultData = data && !treeData ? { ...data } : undefined + nextTick(() => { + categoryFormRef.value.open(type, treeData?.id, defaultData) + }) +} + +const handleCategoryDelete = async (data: any) => { + try { + await message.delConfirm() + await ProductCategoryApi.deleteProductCategory(data.id) + message.success(t('common.delSuccess')) + await fetchGroupTree() + } catch {} +} + +const handleCategorySuccess = () => { + fetchGroupTree() +} + const getList = async () => { loading.value = true try { @@ -163,20 +272,14 @@ const handleExport = async () => { } onMounted(async () => { + await fetchGroupTree() const typeOptions = getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE) if (typeOptions.length > 0) { - activeName = String(typeOptions[0].value) queryParams.categoryType = typeOptions[0].value } await getList() }) -let activeName = '' -const handleTabChange = (name: string) => { - queryParams.categoryType = name ? Number(name) : undefined - handleQuery() -} - const bomFormRef = ref() const openBomForm = (type: string, id?: number) => { formVisible.value = true @@ -191,3 +294,66 @@ const handleFormClosed = () => { formType.value = '' } + +