From 751a6c80da8c3d241a16aecfa7234d742b85ffde Mon Sep 17 00:00:00 2001 From: xs Date: Tue, 25 Mar 2025 15:58:38 +0800 Subject: [PATCH] =?UTF-8?q?1.3.0=20=E7=BB=93=E6=9E=84bom=E5=92=8C=E7=89=A9?= =?UTF-8?q?=E6=96=99bom=E5=89=8D=E7=AB=AF=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/mes/baseStructureBom/types.ts | 5 + src/api/mes/materialBom/index.ts | 12 + .../mes/baseMaterialInfo/addMaterial.vue | 1 - src/views/mes/baseStructureBom/index.vue | 240 ++++++++++++----- src/views/mes/materialBom/index.vue | 246 ++++++++++++------ 5 files changed, 356 insertions(+), 148 deletions(-) diff --git a/src/api/mes/baseStructureBom/types.ts b/src/api/mes/baseStructureBom/types.ts index fa95f44..6c606c9 100644 --- a/src/api/mes/baseStructureBom/types.ts +++ b/src/api/mes/baseStructureBom/types.ts @@ -238,4 +238,9 @@ export interface BaseStructureBomTreeVO { */ children: []; + /** + * 树节点键 + */ + treeKey: string | number; + } diff --git a/src/api/mes/materialBom/index.ts b/src/api/mes/materialBom/index.ts index 071c9f6..ccdb9ad 100644 --- a/src/api/mes/materialBom/index.ts +++ b/src/api/mes/materialBom/index.ts @@ -64,6 +64,18 @@ export const delMaterialBom = (materialBomId: string | number | Array { + return request({ + url: '/mes/materialBom/deleteMaterialBoms', + method: 'post', + data: data + }); +}; + /** * 下拉框查询物料BOM信息列表 diff --git a/src/views/mes/baseMaterialInfo/addMaterial.vue b/src/views/mes/baseMaterialInfo/addMaterial.vue index 329666d..02f61bb 100644 --- a/src/views/mes/baseMaterialInfo/addMaterial.vue +++ b/src/views/mes/baseMaterialInfo/addMaterial.vue @@ -495,7 +495,6 @@ const handleRowClick = (row) =>{ }; defineExpose({tableRef}) onMounted(() => { - alert(materialTypeId.value) if(materialTypeId.value){ queryParams.value.materialTypeId = materialTypeId.value; } diff --git a/src/views/mes/baseStructureBom/index.vue b/src/views/mes/baseStructureBom/index.vue index f074194..bbdfefd 100644 --- a/src/views/mes/baseStructureBom/index.vue +++ b/src/views/mes/baseStructureBom/index.vue @@ -20,15 +20,22 @@ - 物料类型 - + 父物料类型 + - - {{ parentParentMaterialTypeName }} - - - {{ parentMaterialTypeName }} + + + + + @@ -36,27 +43,27 @@ 子级物料类型 - -
- - - - - - - - - - 搜索 - 重置 - - - -
-
+ + + + + + + + + + + + + + + + + + + + + - + @@ -104,12 +111,12 @@ @@ -168,10 +175,16 @@ import { addBaseStructureBom, updateBaseStructureBom, getMaterialTypeList } from "@/api/mes/baseStructureBom"; -import {BaseStructureBomVO, BaseStructureBomTreeVO,BaseStructureBomQuery, BaseStructureBomForm} from '@/api/mes/baseStructureBom/types'; +import { + BaseStructureBomVO, + BaseStructureBomTreeVO, + BaseStructureBomQuery, + BaseStructureBomForm +} from '@/api/mes/baseStructureBom/types'; import {BaseMaterialTypeVO} from '@/api/mes/baseMaterialType/types'; import {to} from 'await-to-js'; import {nextTick} from "vue"; +import {MaterialBomVO} from "@/api/mes/materialBom/types"; const router = useRouter(); const {proxy} = getCurrentInstance() as ComponentInternalInstance; @@ -191,6 +204,9 @@ const structureBomOptions = ref([]); const materialTypeOptions = ref([]); const parentMaterialTypeName = ref(''); const parentParentMaterialTypeName = ref(''); +const focusKeyNode = ref; +const parentMaterialTypeDisabled = ref(true); + // 列显隐信息 const columns = ref([ {key: 0, label: `BOM结构编号`, visible: true, children: []}, @@ -200,6 +216,8 @@ const columns = ref([ {key: 4, label: `更新时间`, visible: true, children: []} ]); + +const parentStructureBomFormRef = ref(); const structureBomTreeRef = ref(); const queryFormRef = ref(); const structureBomFormRef = ref(); @@ -224,8 +242,24 @@ const initFormData: BaseStructureBomForm = { remark: undefined, } +const initParentFormData: BaseStructureBomForm = { + structureBomId: undefined, + parentId: undefined, + materialTypeId: undefined, + materialTypeName: undefined, + structureBomDesc: undefined, + structureBomVersion: undefined, + ancestors: undefined, + level: undefined, + topFlag: undefined, + activeFlag: '1', + remark: undefined, +} + + const data = reactive>({ form: {...initFormData}, + parentForm: {...initParentFormData}, queryParams: { structureBomId: undefined, parentId: undefined, @@ -247,7 +281,7 @@ const data = reactive>({ } }); -const {queryParams, form, rules} = toRefs(data); +const {queryParams, form, rules, parentForm} = toRefs(data); /** 通过条件过滤节点 */ @@ -269,32 +303,47 @@ watchEffect( const getTreeSelect = async () => { treeLoading.value = true; loading.value = true; + const res = await structureBomTreeSelect(); // structureBomOptions.value = res.data; structureBomOptions.value = []; + const virtualTopNodeId = -1; const initialTree: BaseStructureBomTreeVO = { - id: 1, + id: virtualTopNodeId, parentId: -1, - materialTypeId: 0, label: "制造BOM结构", children: res.data }; structureBomOptions.value.push(initialTree); console.log(structureBomOptions); - if (queryParams.value.parentId === null || queryParams.value.parentId === undefined) { - const topStructureBom = structureBomOptions.value.find(item => item.parentId === -1); - if (topStructureBom != null){ - parentMaterialTypeName.value = topStructureBom.label; + // if (queryParams.value.parentId === null || queryParams.value.parentId === undefined) { + // const topStructureBom = structureBomOptions.value.find(item => item.parentId === -1); + // if (topStructureBom != null){ + // parentMaterialTypeName.value = topStructureBom.label; + // } + // queryParams.value.parentId = 1; + // parentParentMaterialTypeName.value = "顶级"; + // } + + // alert(JSON.stringify(focusKeyNode.value)) + if (!focusKeyNode.value) {//如果之前没有focus + focusKeyNode.value = {id: virtualTopNodeId}; + } else { + const allIds = structureBomOptions.value.flatMap(item => getAllIds(item)); + if (!allIds || allIds.length <= 0) { + focusKeyNode.value = {id: virtualTopNodeId}; } - queryParams.value.parentId = 1; - parentParentMaterialTypeName.value = "顶级"; + // console.log(JSON.stringify(materialBomOptions.value)) } nextTick(function () { - structureBomTreeRef.value?.setCurrentKey(queryParams.value.parentId, true); - handleQuery(); + structureBomTreeRef.value?.setCurrentKey(focusKeyNode.value.id, true); }) + treeLoading.value = false; + loading.value = false; + handleNodeClick(focusKeyNode.value); + // const dd = {"id":"1","parentId":-1,"label":"dd"}; // alert(materialTypeOptions.value[0]) // materialTypeOptions.value[0].children.push(dd); @@ -313,20 +362,47 @@ const getList = async () => { /** 节点单击事件 */ const handleNodeClick = (data: BaseStructureBomTreeVO) => { - queryParams.value.parentId = data.id; - parentMaterialTypeName.value = data.label; - if (data.parentId === -1) { - parentParentMaterialTypeName.value = "顶级"; - } else if (data.parentId === 1) { - parentParentMaterialTypeName.value = "制造BOM结构"; - } else { - const findMaterialType = materialTypeOptions.value.find(item => item.matrialTypeId === data.parentId); - parentParentMaterialTypeName.value = findMaterialType.matrialTypeName; + structureBomList.value = []; + parentMaterialTypeDisabled.value = true; + resetParentForm(); + resetQueryParams(); + focusKeyNode.value = data; + // alert(JSON.stringify(focusKeyNode.value)) + if (data.id && data.id != 0 && data.id != -1) { + parentForm.value.parentId = data.id;//是当前节点的materialTypeId + queryParams.value.parentId = data.id; + handleQuery(); } + parentMaterialTypeDisabled.value = focusKeyNode.value.id != -1; - handleQuery(); + + // if (data.parentId === -1) { + // parentParentMaterialTypeName.value = "顶级"; + // } else if (data.parentId === 1) { + // parentParentMaterialTypeName.value = "制造BOM结构"; + // } else { + // const findMaterialType = materialTypeOptions.value.find(item => item.matrialTypeId === data.parentId); + // if(findMaterialType){ + // parentParentMaterialTypeName.value = findMaterialType.matrialTypeName; + // }else{ + // parentParentMaterialTypeName.value = undefined; + // } + // } }; +/** + * 重置父级表单 + */ +const resetParentForm = () => { + parentStructureBomFormRef.value?.resetFields(); + parentStructureBomFormRef.value?.clearValidate(); +}; + +const resetQueryParams = () => { + queryParams.value.parentId = undefined;//materialtypeid +} + + /** 搜索按钮操作 */ const handleQuery = () => { // queryParams.value.pageNum = 1; @@ -348,12 +424,12 @@ const handleDelete = async (row?: BaseStructureBomVO) => { const [err] = await to(proxy?.$modal.confirm('是否确认删除BOM结构编号为"' + structureBomIds + '"的数据项?') as any); if (!err) { await delBaseStructureBom(structureBomIds) - await getTreeSelect(); - handleQuery(); proxy?.$modal.msgSuccess('删除成功'); + await getTreeSelect(); } }; + /** 选择条数 */ const handleSelectionChange = (selection: BaseStructureBomVO[]) => { ids.value = selection.map((item) => item.structureBomId); @@ -387,12 +463,19 @@ const cancel = () => { /** 新增按钮操作 */ const handleAdd = async () => { + if (!parentForm.value.parentId) { + proxy?.$modal.msgWarning('请先选择父物料类型'); + return; + } reset(); + await initMaterialTypeData(); + const findMaterialType = materialTypeOptions.value.find(item => item.matrialTypeId === parentForm.value.parentId); + parentMaterialTypeName.value = findMaterialType.matrialTypeName; + form.value.parentId = parentForm.value.parentId; // alert(JSON.stringify(data)) dialog.visible = true; dialog.title = '新增'; - await initMaterialTypeData(); - form.value.parentId = queryParams.value.parentId; + }; /** 修改按钮操作 */ @@ -422,7 +505,6 @@ const submitForm = () => { form.value.structureBomId ? await updateBaseStructureBom(form.value) : await addBaseStructureBom(form.value); proxy?.$modal.msgSuccess('操作成功'); await getTreeSelect(); - handleQuery(); dialog.visible = false; submitLoading.value = false; } catch { @@ -459,6 +541,26 @@ onMounted(() => { initMaterialTypeData(); }); + +const getAllIds = (obj) => { + let ids = []; + + // 如果当前对象有 id,并且与之前focus的id相同,则收集 + // console.log(JSON.stringify(obj)) + if (obj.id !== undefined && obj.id === focusKeyNode.value.id) { + ids.push(obj.id); + } + + // 如果有 children,递归遍历 + if (obj.children && Array.isArray(obj.children)) { + obj.children.forEach(child => { + ids = ids.concat(getAllIds(child)); // 递归获取子级 id + }); + } + + return ids; +} + // async function handleDeptChange(value: number | string) { // const response = await optionselect(value); // materialTypeOptions.value = response.data; diff --git a/src/views/mes/materialBom/index.vue b/src/views/mes/materialBom/index.vue index 00621d1..ec5e6aa 100644 --- a/src/views/mes/materialBom/index.vue +++ b/src/views/mes/materialBom/index.vue @@ -16,35 +16,44 @@ highlight-current default-expand-all @node-click="handleNodeClick" - /> + > + +
父级物料 - + - + - + + style="width:260px" @change="getList" suffix-icon="Search" readonly + :disabled="parentMaterialDisabled"/> - + + placeholder="请选择" style="width:200px"> - + style="width:200px"/> - + + prop="standardAmount" :show-overflow-tooltip="true" width="220px"> @@ -191,12 +200,12 @@ - - + ([]); +const toDeleteMaterialBoms = ref([]); const single = ref(true); const multiple = ref(true); const total = ref(0); @@ -276,6 +286,8 @@ const unitInfoOptions = ref([]); const focusKeyNode = ref; +const parentMaterialDisabled = ref(true); + const globalSelectMode = ref(''); const SELECT_MATERIAL_MODEL = ref({ PARENT_SELECT: '1',//父级物料选择 @@ -309,7 +321,7 @@ const dialog = reactive({ const initParentFormData: MaterialBomForm = { materialBomId: undefined, parentId: undefined, - parentStandardAmount: undefined, + parentStandardAmount: 1, unitId: undefined, parentUnitId: undefined, materialId: undefined, @@ -381,7 +393,23 @@ const data = reactive>({ standardAmount: [ {required: true, message: "子物料数量不能为空", trigger: "blur"} ] + }, + + parentRules: { + parentMaterialName: [ + {required: true, message: "父物料名称不能为空", trigger: "blur"} + ], + materialBomVersion: [ + {required: true, message: "BOM版本不能为空", trigger: "blur"} + ], + parentStandardAmount: [ + {required: true, message: "父物料数量不能为空", trigger: "blur"} + ], + parentUnitId: [ + {required: true, message: "父物料单位不能为空", trigger: "blur"} + ] } + }); @@ -395,7 +423,7 @@ const parentQueryParams = ref({ params: {} }) -const {queryParams, form, rules, parentForm} = toRefs(data); +const {queryParams, form, rules, parentForm, parentRules} = toRefs(data); /** 通过条件过滤节点 */ const filterNode = (value: string, data: any) => { @@ -415,6 +443,7 @@ watchEffect( /** 查询物料类型bom结构树下拉树结构 */ const getTreeSelect = async () => { treeLoading.value = true; + loading.value = true; const res = await materialBomTreeSelect(); materialBomOptions.value = []; const virtualTopNodeId = -1; @@ -430,21 +459,38 @@ const getTreeSelect = async () => { console.log(materialBomOptions); // materialBomOptions.value = res.data; - if (!focusKeyNode.value) {//如果之前没有focus focusKeyNode.value = {treeKey: virtualTopNodeId}; } else { - alert(23) - alert(focusKeyNode.value.treeKey) - console.log(JSON.stringify(materialBomOptions.value)) + const clickNode = findObjectByTreeKey(materialBomOptions.value, focusKeyNode.value.treeKey) + if (!clickNode) { + focusKeyNode.value = undefined; + focusKeyNode.value = {treeKey: virtualTopNodeId}; + } + + // if (!allTreeKeys || allTreeKeys.length <= 0) { + // focusKeyNode.value = { + // treeKey: virtualTopNodeId, + // id: virtualTopNodeId + // }; + // } + + // const focusKeyNodeIndex = JSON.stringify(materialBomOptions.value).indexOf(focusKeyNode.value.treeKey); + // if (focusKeyNodeIndex < 0) { + // focusKeyNode.value = {treeKey: virtualTopNodeId}; + // } + // const focusKeyNodeIndex = materialBomOptions.value.findIndex((optionItem) => focusKeyNode.value.treeKey === optionItem.treeKey);//有嵌套children的,有可能找不到 } nextTick(function () { materialBomTreeRef.value?.setCurrentKey(focusKeyNode.value.treeKey, true); }) - handleNodeClick(focusKeyNode.value); + loading.value = false; treeLoading.value = false; + handleNodeClick(focusKeyNode.value); + + // const dd = {"id":"1","parentId":-1,"label":"dd"}; // materialTypeOptions.value[0].children.push(dd); }; @@ -471,6 +517,7 @@ const resetQueryParams = () => { /** 节点单击事件 */ const handleNodeClick = (data: MaterialBomVO) => { materialBomList.value = []; + parentMaterialDisabled.value = true; resetParentForm(); resetQueryParams(); resetParentQueryParams(); @@ -489,6 +536,7 @@ const handleNodeClick = (data: MaterialBomVO) => { queryParams.value.materialBomVersion = materialBomVersionOptions.value[0].materialBomVersion; } } + parentMaterialDisabled.value = focusKeyNode.value.treeKey != -1; }; @@ -520,20 +568,30 @@ const resetQuery = () => { /** 删除按钮操作 */ const handleDelete = async (row?: MaterialBomVO) => { btnLoading.value = true; - const materialBomIds = []; + const toDeleteIndexes = []; selectedMaterialBoms.value.forEach(item => { - if (item.materialBomId && item.materialBomId !== '') { - materialBomIds.push(item.materialBomId); - } else { - deleteReset(item); - } + // const index = materialBomList.value.findIndex((optionItem) => item.materialBomId === optionItem.materialBomId); + const index = materialBomList.value.indexOf(item); + toDeleteIndexes.push(parseInt(index + 1)); }); - if (materialBomIds.length > 0) { + + if (toDeleteIndexes.length > 0) { try { - const [err] = await to(proxy?.$modal.confirm('是否确认删除生产BOM编号为"' + materialBomIds + '"的数据项?') as any); + const [err] = await to(proxy?.$modal.confirm('是否确认删除序号为"' + toDeleteIndexes + '"的数据项?') as any); if (!err) { - await delMaterialBom(materialBomIds) - await getTreeSelect(); + selectedMaterialBoms.value.forEach(item => { + if (item.materialBomId && item.materialBomId !== '') { + toDeleteMaterialBoms.value.push(item); + } else { + deleteReset(item); + } + }); + // alert(JSON.stringify(toDeleteMaterialBoms.value)) + if (toDeleteMaterialBoms.value.length > 0) { + await deleteMaterialBoms(toDeleteMaterialBoms.value) + await getTreeSelect(); + } + proxy?.$modal.msgSuccess('删除成功'); } } catch { @@ -548,6 +606,7 @@ const deleteReset = (item) => { item.materialName = undefined; item.materialBomVersion = undefined; item.standardAmount = undefined; + item.unitId = undefined; }; /** 选择条数 */ @@ -706,55 +765,58 @@ const submitMaterialForm = () => { const submitBatchSaveMaterialBoms = async () => { - try { - btnLoading.value = true; - saveMaterialBomList.value = []; - for (let i = 0; i < materialBomList.value.length; i++) { - let item = materialBomList.value[i]; - if (item.materialId) { + parentMaterialBomFormRef.value?.validate(async (valid: boolean) => { + if (valid) { + try { + btnLoading.value = true; + saveMaterialBomList.value = []; + for (let i = 0; i < materialBomList.value.length; i++) { + let item = materialBomList.value[i]; + if (item.materialId) { - if (!item.standardAmount) { - proxy?.$modal.msgWarning('序号为[' + i + 1 + '],请填写子物料数量'); - btnLoading.value = false; - return; - } - if (!item.unitId) { - proxy?.$modal.msgWarning('序号为[' + i + 1 + '],请选择单位'); + if (!item.standardAmount) { + proxy?.$modal.msgWarning('序号为[' + (parseInt(i) + 1) + '],请填写子物料数量'); + btnLoading.value = false; + return; + } + if (!item.unitId) { + proxy?.$modal.msgWarning('序号为[' + (parseInt(i) + 1) + '],请选择单位'); + btnLoading.value = false; + return; + } + + item.parentId = parentForm.value.parentId; + item.parentUnitId = parentForm.value.parentUnitId; + item.materialBomVersion = parentForm.value.materialBomVersion; + item.parentStandardAmount = parentForm.value.parentStandardAmount; + item.parentMaterialTypeId = parentForm.value.parentMaterialTypeId; + saveMaterialBomList.value.push(item); + } + } + if (saveMaterialBomList.value.length <= 0) { + proxy?.$modal.msgWarning('无可保存子级物料'); btnLoading.value = false; return; } + await addBatchMaterialBom(saveMaterialBomList.value); + proxy?.$modal.msgSuccess('操作成功'); - item.parentId = parentForm.value.parentId; - item.parentUnitId = parentForm.value.parentUnitId; - item.materialBomVersion = parentForm.value.materialBomVersion; - item.parentStandardAmount = parentForm.value.parentStandardAmount; - item.parentMaterialTypeId = parentForm.value.parentMaterialTypeId; - saveMaterialBomList.value.push(item); + focusKeyNode.value.treeKey = parentForm.value.parentId + "-" + parentForm.value.materialBomVersion; + focusKeyNode.value.materialBomVersion = parentForm.value.materialBomVersion; + focusKeyNode.value.parentUnitId = parentForm.value.parentUnitId; + focusKeyNode.value.parentStandardAmount = parentForm.value.parentStandardAmount; + + resetParentQueryParams(); + resetQueryParams(); + resetParentForm(); + await getTreeSelect(); + btnLoading.value = false; + } catch (e) { + proxy?.$modal.msgWarning(e); + btnLoading.value = false; } } - if (saveMaterialBomList.value.length <= 0) { - proxy?.$modal.msgWarning('无可保存子级物料'); - btnLoading.value = false; - return; - } - await addBatchMaterialBom(saveMaterialBomList.value); - proxy?.$modal.msgSuccess('操作成功'); - - focusKeyNode.value.treeKey = parentForm.value.parentId + "-" + parentForm.value.materialBomVersion; - focusKeyNode.value.materialBomVersion = parentForm.value.materialBomVersion; - focusKeyNode.value.parentUnitId = parentForm.value.parentUnitId; - focusKeyNode.value.parentStandardAmount = parentForm.value.parentStandardAmount; - - - await getTreeSelect(); - resetParentQueryParams(); - resetQueryParams(); - resetParentForm(); - btnLoading.value = false; - } catch (e) { - proxy?.$modal.msgWarning(e); - btnLoading.value = false; - } + }); } @@ -790,6 +852,34 @@ const getParentMaterialBomInfo = async () => { }; + +const findObjectByTreeKey = (list, targetTreeKey) => { + for (const item of list) { + if (item.treeKey === targetTreeKey) return item; + if (item.children) { + const found = findObjectByTreeKey(item.children, targetTreeKey); + if (found) return found; + } + } + return null; +} + + +// const getClickNode = (obj) => { +// // 如果当前对象有 id,并且与之前focus的id相同,则收集 +// // console.log(JSON.stringify(obj)) +// if (obj.treeKey !== undefined && obj.treeKey === focusKeyNode.value.treeKey) { +// return obj; +// } +// +// // 如果有 children,递归遍历 +// if (obj.children && Array.isArray(obj.children)) { +// obj.children.forEach(child => { +// getClickNode(child); // 递归获取 +// }); +// } +// +// }