| | |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | @change="handleUnitQuantityChange" |
| | | :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" /> |
| | | </el-form-item> |
| | | </template> |
| | |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" /> |
| | | :disabled="true" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | }); |
| | | }; |
| | | |
| | | const toQuantityNumber = (value: any) => { |
| | | const numberValue = Number(value); |
| | | if (!Number.isFinite(numberValue)) { |
| | | return 0; |
| | | } |
| | | return Number(numberValue.toFixed(2)); |
| | | }; |
| | | |
| | | const syncDemandedQuantityTree = ( |
| | | items: any[], |
| | | parentDemandedQuantity: number | null = null |
| | | ) => { |
| | | items.forEach((item: any) => { |
| | | if (parentDemandedQuantity !== null) { |
| | | item.demandedQuantity = toQuantityNumber( |
| | | parentDemandedQuantity * toQuantityNumber(item.unitQuantity) |
| | | ); |
| | | } |
| | | |
| | | if (Array.isArray(item.children) && item.children.length > 0) { |
| | | syncDemandedQuantityTree( |
| | | item.children, |
| | | toQuantityNumber(item.demandedQuantity) |
| | | ); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const recalculateDemandedQuantities = () => { |
| | | if (!isOrderPage.value) { |
| | | return; |
| | | } |
| | | |
| | | syncDemandedQuantityTree(dataValue.dataList); |
| | | }; |
| | | |
| | | const buildSubmitTree = (items: any[]) => { |
| | | return items.map((item: any) => { |
| | | const current = { ...item }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | const findSiblings = (items: any[], tempId: string): any[] | null => { |
| | | if (!items || items.length === 0) return null; |
| | | // 检查当前层级 |
| | | if (items.some(item => item.tempId === tempId)) { |
| | | return items; |
| | | } |
| | | // 递归查找子级 |
| | | for (const item of items) { |
| | | if (item.children && item.children.length > 0) { |
| | | const result = findSiblings(item.children, tempId); |
| | | if (result) return result; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const handleProcessChange = (row: any, value: any) => { |
| | | row.processId = value || ""; |
| | | syncProcessOperationFields(row); |
| | | |
| | | // 同一层级只能选一样的工序 |
| | | const siblings = findSiblings(dataValue.dataList, row.tempId); |
| | | if (siblings && value) { |
| | | siblings.forEach(sibling => { |
| | | if (sibling.tempId !== row.tempId) { |
| | | sibling.processId = value; |
| | | syncProcessOperationFields(sibling); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const handleUnitQuantityChange = () => { |
| | | recalculateDemandedQuantities(); |
| | | }; |
| | | |
| | | const tableData = reactive([ |
| | |
| | | const { data } = await listProcessBom({ orderId: routeOrderId.value }); |
| | | dataValue.dataList = (data as any) || []; |
| | | normalizeTreeData(dataValue.dataList); |
| | | recalculateDemandedQuantities(); |
| | | } else { |
| | | // 非订单情况:使用原来的接口 |
| | | const { data } = await queryList(routeId.value); |
| | |
| | | const validateAll = () => { |
| | | let isValid = true; |
| | | |
| | | // 校验一组兄弟节点的工序是否都相同 |
| | | const checkProcessUniqueness = (items: any[]) => { |
| | | if (!items || items.length === 0 || !isValid) return; |
| | | |
| | | // 获取第一个非空的工序ID作为参考 |
| | | const firstProcessId = items.find(item => item.processId)?.processId; |
| | | |
| | | // 如果有工序ID,检查所有项是否都使用相同的工序 |
| | | if (firstProcessId) { |
| | | for (const item of items) { |
| | | if (item.processId && item.processId !== firstProcessId) { |
| | | const option1 = getProcessOptionById(firstProcessId); |
| | | const option2 = getProcessOptionById(item.processId); |
| | | const processName1 = option1?.name || "未知工序"; |
| | | const processName2 = option2?.name || "未知工序"; |
| | | ElMessage.error( |
| | | `当前层级下工序不一致,请使用相同的工序。存在「${processName1}」和「${processName2}」` |
| | | ); |
| | | isValid = false; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 递归校验子级的兄弟节点 |
| | | for (const item of items) { |
| | | if (item.children && item.children.length > 0) { |
| | | checkProcessUniqueness(item.children); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 校验函数 |
| | | const validateItem = (item: any, isTopLevel = false) => { |
| | | if (!isValid) return; |
| | | // 校验当前项的必填字段 |
| | | if (!item.model) { |
| | | ElMessage.error("请选择规格"); |
| | |
| | | // return; |
| | | // } |
| | | |
| | | // 递归校验子项 |
| | | // 递归校验子项字段 |
| | | if (item.children && item.children.length > 0) { |
| | | item.children.forEach(child => { |
| | | validateItem(child, false); |
| | |
| | | } |
| | | }; |
| | | |
| | | // 遍历所有顶层项 |
| | | // 1. 首先校验同一父级下的同层消耗工序是否唯一 |
| | | checkProcessUniqueness(dataValue.dataList); |
| | | if (!isValid) return false; |
| | | |
| | | // 2. 然后遍历校验所有顶层项的字段必填情况 |
| | | dataValue.dataList.forEach(item => { |
| | | validateItem(item, true); |
| | | }); |
| | |
| | | const submit = () => { |
| | | dataValue.loading = true; |
| | | normalizeTreeData(dataValue.dataList); |
| | | recalculateDemandedQuantities(); |
| | | |
| | | // 先进行表单校验 |
| | | const valid = validateAll(); |
| | |
| | | |
| | | tempId: new Date().getTime(), |
| | | }); |
| | | recalculateDemandedQuantities(); |
| | | return; |
| | | } |
| | | addchildItem(item, tempId); |
| | |
| | | unit: "", |
| | | tempId: new Date().getTime(), |
| | | }); |
| | | recalculateDemandedQuantities(); |
| | | return true; |
| | | } |
| | | if (item.children && item.children.length > 0) { |
| | |
| | | await fetchProcessOptions(); |
| | | await fetchData(); |
| | | }); |
| | | </script> |
| | | </script> |