| | |
| | | import CheckInventory from "@/views/pp/glassOptimize/page/CheckInventory.vue"; |
| | | import request from "@/utils/request"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {useRoute} from 'vue-router'; |
| | | import {useRoute, useRouter} from 'vue-router'; |
| | | import useUserInfoStore from "@/stores/userInfo"; |
| | | import useOrderInfoStore from "@/stores/sd/order/orderInfo"; |
| | | import {addListener,toolbarButtonClickEvent} from "@/hook/mouseMove"; |
| | |
| | | const userStore = useUserInfoStore() |
| | | const orderInfo = useOrderInfoStore() |
| | | const username = userStore.user.userName |
| | | const router = useRouter() |
| | | |
| | | let cellArea = ref() |
| | | const xGrid = ref() |
| | |
| | | {field: 'width', |
| | | width: 100, |
| | | title: t('order.width'), |
| | | editRender: { name: 'input' }, |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'height', |
| | | width: 100, |
| | | title: t('order.height'), |
| | | editRender: { name: 'input' }, |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | | width: 150, |
| | | title: t('order.quantity'), |
| | | editRender: { name: 'input' }, |
| | | filters: [{data: ''}], |
| | | slots: {filter: 'num1_filter'}, |
| | | sortable: true |
| | |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'product_name', |
| | | field: 'productName', |
| | | width: 150, |
| | | title: t('order.product'), |
| | | filters: [{data: ''}], |
| | |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'building_number', |
| | | field: 'buildingNumber', |
| | | width: 150, |
| | | title: '楼层号', |
| | | filters: [{data: ''}], |
| | |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'icon', |
| | | field: 'markIcon', |
| | | width: 150, |
| | | title: '印标类型', |
| | | filters: [{data: ''}], |
| | |
| | | body: { |
| | | options: [ |
| | | [ |
| | | {code: 'setAmount', name: '设置统一磨量',}, |
| | | {code: 'setAmount', name: '设置统一磨量',prefixIcon:'vxe-icon-edit'}, |
| | | {code: 'addRow', name: '添加临时小片', prefixIcon: 'vxe-icon-add', visible: true, disabled: false}, |
| | | {code: 'displayProcessCard', name: '显示流程卡',}, |
| | | {code: 'hideProcessCard', name: '隐藏流程卡',}, |
| | | {code: 'setShape', name: '设置图形',}, |
| | | {code: 'Export', name: '数据导出', prefixIcon: 'vxe-icon-download', visible: true, disabled: false}, |
| | | {code: 'safeDXF', name: '图形另存为DXF',}, |
| | | {code: 'exportOPTIMA', name: '导出数据到OPTIMA',}, |
| | | {code: 'copyChecked', name: t('basicData.selectSame'), prefixIcon: 'vxe-icon-copy', visible: true, disabled: false }, |
| | | {code: 'copyAll', name: t('basicData.sameAfterwards'), prefixIcon: 'vxe-icon-feedback', visible: true, disabled: false }, |
| | | { |
| | | code: 'copyChecked', |
| | | name: t('basicData.selectSame'), |
| | | prefixIcon: 'vxe-icon-copy', |
| | | visible: true, |
| | | disabled: false |
| | | }, |
| | | { |
| | | code: 'copyAll', |
| | | name: t('basicData.sameAfterwards'), |
| | | prefixIcon: 'vxe-icon-feedback', |
| | | visible: true, |
| | | disabled: false |
| | | }, |
| | | ], |
| | | [] |
| | | ] |
| | |
| | | |
| | | }, |
| | | }); |
| | | |
| | | const checkAutoRedirectToOptimize = () => { |
| | | // 检查路由中是否有自动跳转标识 |
| | | if (route.query.redirect === 'optimizeControl') { |
| | | setTimeout(() => { |
| | | const projectNo = route.params.projectNo || localStorage.getItem('currentProjectNo'); |
| | | if (projectNo) { |
| | | router.push({ |
| | | name: 'OptimizeControl', |
| | | params: { |
| | | processId: projectNo |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | |
| | | // 右键菜单 |
| | | const operationConfigs = [ |
| | |
| | | } |
| | | }, |
| | | { |
| | | code: 'Export', // 导出文件操作的配置 |
| | | successMsg: '文件导出成功!', |
| | | code: 'addRow', |
| | | successMsg: '已添加', |
| | | gridRef: xGrid, |
| | | requiresRow: false, |
| | | addNewRow: async () => { |
| | | // 获取当前的磨量配置 |
| | | let currentGrindConfig = null; |
| | | try { |
| | | const res = await request.post(`/glassOptimize/getConfiguration/磨量/${username}`); |
| | | if (res.code == "200" && res.data.data && res.data.data.length > 0) { |
| | | const rawData = res.data.data[0]; |
| | | currentGrindConfig = {}; |
| | | for (const key in rawData) { |
| | | if (typeof rawData[key] === 'string') { |
| | | currentGrindConfig[key] = rawData[key].replace(/^\"|\"$/g, ''); |
| | | } else { |
| | | currentGrindConfig[key] = rawData[key]; |
| | | } |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.warn('获取磨量配置失败:', error); |
| | | } |
| | | |
| | | // 根据磨量配置设置默认值 |
| | | let defaultLongGrind1 = 0; |
| | | let defaultLongGrind2 = 0; |
| | | let defaultShortGrind1 = 0; |
| | | let defaultShortGrind2 = 0; |
| | | |
| | | if (currentGrindConfig) { |
| | | defaultLongGrind1 = parseFloat(currentGrindConfig.leftEdge) || 0; |
| | | defaultLongGrind2 = parseFloat(currentGrindConfig.rightEdge) || 0; |
| | | defaultShortGrind1 = parseFloat(currentGrindConfig.upEdge) || 0; |
| | | defaultShortGrind2 = parseFloat(currentGrindConfig.downEdge) || 0; |
| | | } |
| | | |
| | | // 创建新行数据,将 width、height、quantity 设置为数值类型 |
| | | const newRow = { |
| | | order_number: 0, |
| | | width: 0, |
| | | height: 0, |
| | | quantity: 0, |
| | | longGrind1: defaultLongGrind1, |
| | | longGrind2: defaultLongGrind2, |
| | | shortGrind1: defaultShortGrind1, |
| | | shortGrind2: defaultShortGrind2, |
| | | shape: '', |
| | | process_id: '', |
| | | productName: '', |
| | | price: 0, |
| | | remark: '', |
| | | buildingNumber: '', |
| | | perimeter: 0, |
| | | area: 0, |
| | | rackNo: 1, |
| | | layer: 1, |
| | | glass_child: '', |
| | | markIcon: '', |
| | | processId: '', |
| | | totalLayer: 0, |
| | | patchState: 0, |
| | | heatLayoutId: 0, |
| | | process: '', |
| | | orderNo: '', |
| | | customerName: '', |
| | | processingNote: '', |
| | | projectName: '' |
| | | }; |
| | | |
| | | // 将新行添加到表格数据中 |
| | | const currentData = gridOptions.data || []; |
| | | const updatedData = [...currentData, newRow]; |
| | | gridOptions.data = updatedData; |
| | | xGrid.value.loadData(updatedData); |
| | | |
| | | // 获取新添加行的索引 |
| | | const newIndex = updatedData.length - 1; |
| | | |
| | | // 选中并编辑新行 |
| | | await nextTick(); |
| | | xGrid.value.setActiveRow(newRow); |
| | | } |
| | | }, |
| | | { |
| | | code: 'safeDXF', |
| | |
| | | if (config.code === 'Export') { |
| | | config.gridRef.value.exportData(); |
| | | ElMessage.success(config.successMsg); |
| | | return; |
| | | } |
| | | if (config.code === 'addRow') { |
| | | // 添加确认提示弹窗,询问用户是否进行当前操作 |
| | | ElMessageBox.confirm('是否添加临时小片?', '确认操作', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | config.addNewRow(); |
| | | ElMessage.success(config.successMsg); |
| | | }).catch(() => { |
| | | ElMessage.info('已取消操作'); |
| | | }); |
| | | return; |
| | | } |
| | | if (config.code === 'copyChecked') { |
| | |
| | | }; |
| | | |
| | | const handleCommand = async (command) => { |
| | | await emit('changeDialog', command) |
| | | } |
| | | if (command === 3) { |
| | | // 执行模拟计算 |
| | | await emit('changeDialog', command); |
| | | |
| | | } else { |
| | | // 其他命令直接执行 |
| | | await emit('changeDialog', command); |
| | | } |
| | | }; |
| | | |
| | | let originalFilm=ref(true) |
| | | let surplusMaterial=ref(false) |
| | |
| | | } |
| | | emit('getSmallPieceData', 1); |
| | | optimizeData.value.glassDetails = []; |
| | | // 从后端接口获取 glassDetail 数据,而不是从表格中读取 |
| | | fetchGlassDetailData(); |
| | | // 从表格中获取 glassDetail 数据,而不是从后端接口读取 |
| | | const tableData = xGrid.value.getTableData().fullData; |
| | | let totalQuantity = 0; |
| | | let totalArea = 0; |
| | | |
| | | // xGrid.value.getTableData().fullData.forEach(items=>{ |
| | | // let rackNoValue = 0; |
| | | // if (items.rackNo !== undefined && items.rackNo !== null && items.rackNo !== '') { |
| | | // rackNoValue = items.rackNo; |
| | | // } |
| | | // const detail={ |
| | | // width :null, |
| | | // height :null, |
| | | // processId :null, |
| | | // layer :null, |
| | | // totalLayer :null, |
| | | // orderSort :null, |
| | | // markIcon :null, |
| | | // quantity:null, |
| | | // patchState :null, |
| | | // upGrind :null, |
| | | // downGrind :null, |
| | | // leftGrind:null, |
| | | // rightGrind :null, |
| | | // rackNo: rackNoValue |
| | | // } |
| | | // detail.width=items.width |
| | | // detail.height=items.height |
| | | // detail.processId=items.process_ids |
| | | // detail.layer=items.layer |
| | | // detail.totalLayer=items.total_layer |
| | | // detail.orderSort=items.order_number |
| | | // detail.markIcon=items.icon |
| | | // detail.patchState=items.patch_state |
| | | // detail.quantity=items.quantity |
| | | // detail.upGrind=items.longGrind1 |
| | | // detail.downGrind=items.longGrind2 |
| | | // detail.leftGrind=items.shortGrind1 |
| | | // detail.rightGrind=items.shortGrind2 |
| | | // detail.rackNo=items.rackNo |
| | | // |
| | | // optimizeData.value.glassDetails .push(detail) |
| | | // }) |
| | | tableData.forEach(item => { |
| | | const width = parseFloat(item.width) || 0; |
| | | const height = parseFloat(item.height) || 0; |
| | | const quantity = parseInt(item.quantity) || 0; |
| | | |
| | | // 使用长×宽×数量来计算总面积 |
| | | totalArea += (width * height * quantity) / 1000000; // 转换为平方米 |
| | | totalQuantity += quantity; |
| | | }); |
| | | |
| | | quantitys.value = totalQuantity; |
| | | areas.value = totalArea; |
| | | const glassDetailData = tableData.map(item => { |
| | | let rackNoValue = 0; |
| | | if (item.rackNo !== undefined && item.rackNo !== null && item.rackNo !== '') { |
| | | rackNoValue = item.rackNo; |
| | | } |
| | | return { |
| | | width: parseFloat(item.width) || 0, |
| | | height: parseFloat(item.height) || 0, |
| | | processId: item.processId, |
| | | layer: item.layer, |
| | | totalLayer: item.totalLayer, |
| | | orderSort: item.order_number, |
| | | markIcon: item.markIcon, |
| | | quantity: parseInt(item.quantity) || 0, |
| | | patchState: item.patchState, |
| | | upGrind: item.longGrind1, |
| | | downGrind: item.longGrind2, |
| | | leftGrind: item.shortGrind1, |
| | | rightGrind: item.shortGrind2, |
| | | heatLayoutId: item.heatLayoutId, |
| | | process: item.process, |
| | | orderNo: item.orderNo, |
| | | customerName: item.customerName, |
| | | processingNote: item.processingNote, |
| | | projectName: item.projectName, |
| | | productName: item.productName, |
| | | buildingNumber: item.buildingNumber, |
| | | rackNo: rackNoValue |
| | | }; |
| | | }); |
| | | |
| | | // 更新 optimizeData 中的 glassDetails |
| | | optimizeData.value.glassDetails = glassDetailData; |
| | | |
| | | // 打开优化对话框 |
| | | dialogVisible.value[4] = true; |
| | | |
| | | }else{ |
| | | dialogVisible.value[index] = true; |
| | | } |
| | | }; |
| | | |
| | | const fetchGlassDetailData = async () => { |
| | | try { |
| | | const res = await request.post(`/glassOptimize/optimizeInfo/${projectNo.value}/${username}`); |
| | | console.log(res); |
| | | if (res.code === "200" && res.data && res.data.data) { |
| | | // 处理从后端获取的数据 |
| | | const glassDetailData = res.data.data.map(item => { |
| | | let rackNoValue = 0; |
| | | if (item.rackNo !== undefined && item.rackNo !== null && item.rackNo !== '') { |
| | | rackNoValue = item.rackNo; |
| | | } |
| | | return { |
| | | width: item.width, |
| | | height: item.height, |
| | | processId: item.processId, |
| | | layer: item.layer, |
| | | totalLayer: item.totalLayer, |
| | | orderSort: item.order_number, |
| | | markIcon: item.markIcon, |
| | | quantity: item.quantity, |
| | | patchState: item.patchState, |
| | | upGrind: item.upGrind, |
| | | downGrind: item.downGrind, |
| | | leftGrind: item.leftGrind, |
| | | rightGrind:item.rightGrind, |
| | | layoutId:item.layoutId, |
| | | rackNo: rackNoValue |
| | | }; |
| | | }); |
| | | |
| | | // 更新 optimizeData 中的 glassDetails |
| | | optimizeData.value.glassDetails = glassDetailData; |
| | | |
| | | // 打开优化对话框 |
| | | dialogVisible.value[4] = true; |
| | | |
| | | console.log('获取到的 glassDetail 数据:', glassDetailData); |
| | | } else { |
| | | ElMessage.error('获取玻璃详情数据失败'); |
| | | } |
| | | } catch (error) { |
| | | console.error('获取 glassDetail 数据出错:', error); |
| | | ElMessage.error('获取玻璃详情数据时发生错误'); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | //右键菜单统一修边 |
| | | const props = defineProps({ |
| | | TrimmingDialogVisible: Boolean, |
| | | CheckboxChangeData: null |
| | | TrimmingDialogVisible: { |
| | | type: [Boolean, Object], |
| | | required: false, |
| | | default: null |
| | | }, |
| | | CheckboxChangeData: { |
| | | type: Array, |
| | | required: false, |
| | | default: null |
| | | } |
| | | }); |
| | | |
| | | |
| | | const selectedGlassDataForTrimming = ref([]); |
| | | |
| | | /*watch(() => props.TrimmingDialogVisible, (newValue) => { |
| | | if (newValue === true) { |
| | | dialogVisible.value[3] = newValue; |
| | |
| | | });*/ |
| | | |
| | | watch( |
| | | ()=> [props.TrimmingDialogVisible,props.CheckboxChangeData], |
| | | ([newValue, oldValue])=> { |
| | | if (props.TrimmingDialogVisible!=null){ |
| | | dialogVisible.value[3] = newValue; |
| | | () => props.TrimmingDialogVisible, |
| | | (newVal, oldVal) => { |
| | | // 处理打开修边对话框的逻辑 |
| | | if (newVal != null && typeof newVal === 'object' && newVal.action === 'open-trimming-dialog') { |
| | | dialogVisible.value[3] = true; |
| | | |
| | | // 更新选中的玻璃数据 |
| | | if (newVal.selectedData && newVal.selectedData.length > 0) { |
| | | selectedGlassDataForTrimming.value = newVal.selectedData; |
| | | } else { |
| | | selectedGlassDataForTrimming.value = []; |
| | | } |
| | | } |
| | | if (props.CheckboxChangeData!=null && props.CheckboxChangeData.length>0){ |
| | | } |
| | | ); |
| | | // 单独处理选中原片数据的逻辑 |
| | | watch( |
| | | () => props.CheckboxChangeData, |
| | | (newData, oldData) => { |
| | | // 只有当有选中数据时才处理 |
| | | if (newData != null && newData.length > 0) { |
| | | optimizeData.value.materialDetails = []; |
| | | props.CheckboxChangeData.forEach(items=>{ |
| | | const detail={ |
| | | width :null, |
| | | height :null, |
| | | stockCode :null, |
| | | quantity :null, |
| | | upTrim :null, |
| | | downTrim :null, |
| | | leftTrim :null, |
| | | rightTrim:null, |
| | | priority:0 |
| | | newData.forEach(items => { |
| | | const detail = { |
| | | width: null, |
| | | height: null, |
| | | stockCode: null, |
| | | quantity: null, |
| | | upTrim: null, |
| | | downTrim: null, |
| | | leftTrim: null, |
| | | rightTrim: null, |
| | | priority: 0 |
| | | } |
| | | detail.width=items.width |
| | | detail.height=items.height |
| | | detail.stockCode=items.id |
| | | detail.quantity=items.available_quantity |
| | | detail.upTrim=items.upTrim |
| | | detail.downTrim=items.downTrim |
| | | detail.leftTrim=items.leftTrim |
| | | detail.rightTrim=items.rightTrim |
| | | detail.width = items.width |
| | | detail.height = items.height |
| | | detail.stockCode = items.id |
| | | detail.quantity = items.available_quantity |
| | | detail.upTrim = items.upTrim |
| | | detail.downTrim = items.downTrim |
| | | detail.leftTrim = items.leftTrim |
| | | detail.rightTrim = items.rightTrim |
| | | |
| | | optimizeData.value.materialDetails.push(detail) |
| | | }) |
| | | dialogVisible.value[4] = true; |
| | | }else{ |
| | | } else if (newData !== null && newData.length === 0) { |
| | | // 只有当明确传入空数组时才提示选择原片 |
| | | ElMessage.warning('请选择原片'); |
| | | } |
| | | console.log(optimizeData.value) |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | |
| | | const route = useRoute(); |
| | |
| | | localStorage.setItem('projectNo', projectNo.value); |
| | | }); |
| | | |
| | | const saveOptimizeData = () => { |
| | | if(orderInfo.optimizeData!==null){ |
| | | if(quantitys.value===orderInfo.optimizeData.optimalResults.glassTotalQuantity){ |
| | | console.log("保存数据1",orderInfo.optimizeData) |
| | | request.post(`/glassOptimize/saveOptimizeData/${projectNo.value}`,orderInfo.optimizeData).then((res) => { |
| | | if ((Number(res.code) === 200)) { |
| | | ElMessage.success("保存成功"); |
| | | } else { |
| | | ElMessage.warning(res.msg); |
| | | } |
| | | const saveOptimizeData = async () => { |
| | | try { |
| | | // 先从后端查询工程状态 |
| | | const stateRes = await request.post(`/glassOptimize/getProjectState/${projectNo.value}`); |
| | | if (Number(stateRes.code) === 200) { |
| | | const projectData = stateRes.data.data; |
| | | |
| | | }).catch((error) => { |
| | | console.error("获取数据出错:", error); |
| | | }); |
| | | }else{ |
| | | ElMessage.warning("原片不足,小片未全部优化"); |
| | | // 检查 optimize_state 状态 |
| | | if (projectData.optimize_state === 1) { |
| | | // 如果已完成优化,提示用户并阻止继续执行 |
| | | ElMessage.warning('已完成优化保存,不允许重复提交'); |
| | | return; |
| | | } |
| | | } else { |
| | | ElMessage.warning(stateRes.msg); |
| | | return; |
| | | } |
| | | |
| | | }else { |
| | | ElMessage.warning("数据未优化"); |
| | | if(orderInfo.optimizeData!==null){ |
| | | if(quantitys.value===orderInfo.optimizeData.optimalResults.glassTotalQuantity){ |
| | | console.log("保存数据1",orderInfo.optimizeData) |
| | | request.post(`/glassOptimize/saveOptimizeData/${projectNo.value}`,orderInfo.optimizeData).then((res) => { |
| | | if ((Number(res.code) === 200)) { |
| | | ElMessage.success("保存成功"); |
| | | } else { |
| | | ElMessage.warning(res.msg); |
| | | } |
| | | }).catch((error) => { |
| | | console.error("获取数据出错:", error); |
| | | }); |
| | | }else{ |
| | | ElMessage.warning("原片不足,小片未全部优化"); |
| | | } |
| | | }else { |
| | | ElMessage.warning("数据未优化"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('检查工程状态失败,请稍后重试'); |
| | | console.error('检查工程状态失败:', error); |
| | | } |
| | | |
| | | } |
| | | |
| | | const fetchData = () => { |
| | | //启用表格拖动选中 |
| | | addListener(xGrid.value,gridOptions,cellArea.value) |
| | | request.post(`/glassOptimize/projectInfo/${projectNo.value}/${username}`).then((res) => { |
| | | request.post(`/glassOptimize/optimizeInfo/${projectNo.value}/${username}`).then((res) => { |
| | | if ((Number(res.code) === 200)) { |
| | | let data = res.data.data; |
| | | const grindingTrimming = res.data.grindingTrimming; |
| | |
| | | |
| | | xGrid.value.loadData(data); |
| | | gridOptions.data = data; |
| | | projectName.value = data[0].project_name; |
| | | projectName.value = res.data.project.project_name; |
| | | quantitys.value=res.data.project.glass_total |
| | | areas.value=res.data.project.glass_total_area |
| | | |
| | |
| | | orderInfo.projectNo=route.params |
| | | fetchData(); |
| | | firstLoading(); |
| | | checkAutoRedirectToOptimize(); |
| | | }else if(orderInfo.projectNo!==null){ |
| | | projectNo.value=orderInfo.projectNo.projectNo |
| | | model.value=orderInfo.projectNo.model |
| | | thickNess.value=orderInfo.projectNo.thickNess |
| | | fetchData(); |
| | | firstLoading(); |
| | | checkAutoRedirectToOptimize(); |
| | | } |
| | | }); |
| | | |
| | |
| | | <el-button id="button" type="primary" @click="openDialog(3)">设置修边</el-button> |
| | | <el-dialog v-model="dialogVisible[3]" title="设置修边(mm)" destroy-on-close |
| | | style="width: 35%;height:80%;margin-top: 3vh;"> |
| | | <set-trimming :closeDialog="closeDialog" @send-data-event="handleTrimmingData"/> |
| | | <set-trimming |
| | | :closeDialog="closeDialog" |
| | | :selected-glass-data="selectedGlassDataForTrimming" |
| | | @send-data-event="handleTrimmingData"/> |
| | | </el-dialog> |
| | | <el-button id="button" type="primary" @click="saveOptimizeData()">保存</el-button> |
| | | <el-button id="button" type="primary" @click="openDialog(4)">优化</el-button> |