Merge branch 'master' of http://bore.pub:10439/r/ERP_override
New file |
| | |
| | | <script setup> |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | | <canvas id="canvas"></canvas> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | component: () => import('../views/pp/glassOptimize/OptimizeParms.vue'), |
| | | }, |
| | | { |
| | | path: '/optimizeProject/:projectNo/:thickNess/:model', |
| | | path: '/optimizeProject/:projectNo/:thickNess/:model/:quantity/:area/:optimizeState', |
| | | name: 'optimizeInfo', |
| | | component: () => import('../views/pp/glassOptimize/OptimizeProject.vue') |
| | | }, |
| | |
| | | } |
| | | } |
| | | |
| | | } |
| | | }, |
| | | projectNo:ref(), |
| | | optimizeData:{ |
| | | optimalResults:'', |
| | | originalFilm:'' |
| | | }, |
| | | |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | this.projectNo=null |
| | | this.optimizeData={ |
| | | optimalResults:null, |
| | | originalFilm:null |
| | | } |
| | | } |
| | | }, |
| | | persist: true |
| | |
| | | project : null |
| | | }); |
| | | |
| | | const state = ref() |
| | | const computed = ref(null); |
| | | const computedCard = ref(null); |
| | | const computedData = ref({ |
| | |
| | | } |
| | | |
| | | const handleSimulation = async () => { |
| | | const data=computeCardRef.value.selectFullData(); |
| | | let arry = computeCardRef.value.selectFullData(); |
| | | let data = arry; |
| | | data = data.reduce((acc, item) => { |
| | | if (item.tempering) { |
| | | acc.push(item); |
| | | } |
| | | return acc; |
| | | }, []); |
| | | |
| | | if(data.length===arry.length){ |
| | | state.value=1 |
| | | }else{ |
| | | state.value=2 |
| | | } |
| | | |
| | | if(props.project!=null){ |
| | | computed.value.glass_thickness=props.project.glass_thickness |
| | | computed.value.glass_type=props.project.glass_type |
| | | } |
| | | data.forEach(item=>{ |
| | | const processCard = { |
| | | process_no: item.processId, |
| | | layers: item.technologyNumber, |
| | | total_layers: item.total_layers, |
| | | total_num: item.total_num, |
| | | total_area: item.total_area, |
| | | is_must: true, |
| | | allow_rotate: item.allow_rotate, |
| | | priority_level: 0, |
| | | tempering: item.tempering, |
| | | curtain_wall: item.curtain_wall, |
| | | patch_state: item.patch_state, |
| | | merge: item.merge, |
| | | glass_details: [] |
| | | }; |
| | | if(data.length>0){ |
| | | data.forEach(item=>{ |
| | | const processCard = { |
| | | process_no: item.processId, |
| | | layers: item.technologyNumber, |
| | | total_layers: item.total_layers, |
| | | total_num: item.total_num, |
| | | total_area: item.total_area, |
| | | is_must: true, |
| | | allow_rotate: item.allow_rotate, |
| | | priority_level: 0, |
| | | tempering: item.tempering, |
| | | curtain_wall: item.curtain_wall, |
| | | patch_state: item.patch_state, |
| | | merge: item.merge, |
| | | glass_details: [] |
| | | }; |
| | | |
| | | request.post(`/glassOptimize/selectComputeDetail/${item.processId}/${item.technologyNumber}/${item.patch_state}`).then((res) => { |
| | | if(Number(res.code) === 200){ |
| | | res.data.data.forEach(items=>{ |
| | | const detail={ |
| | | process_id:null, |
| | | technology_number:null, |
| | | order_number:null, |
| | | layers_number:null, |
| | | max_width:null, |
| | | max_height:null, |
| | | child_width:null, |
| | | child_height:null, |
| | | quantity:null, |
| | | patch_state:null |
| | | } |
| | | detail.process_id=items.process_id |
| | | detail.technology_number=items.technology_number |
| | | detail.order_number=items.order_number |
| | | detail.layers_number=item.total_layers |
| | | detail.max_width=items.maxwidth |
| | | detail.max_height=items.maxheight |
| | | detail.child_width=items.width |
| | | detail.child_height=items.height |
| | | detail.quantity=items.quantity |
| | | detail.patch_state=item.patch_state |
| | | request.post(`/glassOptimize/selectComputeDetail/${item.processId}/${item.technologyNumber}/${item.patch_state}`).then((res) => { |
| | | if(Number(res.code) === 200){ |
| | | res.data.data.forEach(items=>{ |
| | | const detail={ |
| | | process_id:null, |
| | | technology_number:null, |
| | | order_number:null, |
| | | layers_number:null, |
| | | max_width:null, |
| | | max_height:null, |
| | | child_width:null, |
| | | child_height:null, |
| | | quantity:null, |
| | | patch_state:null |
| | | } |
| | | detail.process_id=items.process_id |
| | | detail.technology_number=items.technology_number |
| | | detail.order_number=items.order_number |
| | | detail.layers_number=item.total_layers |
| | | detail.max_width=items.maxwidth |
| | | detail.max_height=items.maxheight |
| | | detail.child_width=items.width |
| | | detail.child_height=items.height |
| | | detail.quantity=items.quantity |
| | | detail.patch_state=item.patch_state |
| | | |
| | | processCard.glass_details.push(detail) |
| | | }) |
| | | processCard.glass_details.push(detail) |
| | | }) |
| | | |
| | | |
| | | }else{ |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }else{ |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }) |
| | | computed.value.process_cards.push(processCard) |
| | | }) |
| | | computed.value.process_cards.push(processCard) |
| | | }) |
| | | console.log(computed.value) |
| | | console.log(computed.value) |
| | | }else{ |
| | | ElMessage.warning("没有需要钢化工艺的数据请直接保存") |
| | | state.value=3 |
| | | return |
| | | } |
| | | |
| | | |
| | | |
| | | /*request.post(`/glassOptimize/simulationCalculate`,computed.value).then((res) => { |
| | | if(Number(res.code) === 200){ |
| | |
| | | "angle": 0.0, |
| | | "glass_type": 3, |
| | | "height": 862, |
| | | "layers_number": 2, |
| | | "order_number": 33, |
| | | "process_id": "NG24120028A005", |
| | | "layers_number": 1, |
| | | "order_number": 1, |
| | | "process_id": "NG22091408A06", |
| | | "technology_number": 2, |
| | | "tempering_feed_sequence": 1, |
| | | "tempering_layout_id": 1, |
| | |
| | | "angle": 0.1, |
| | | "glass_type": 4, |
| | | "height": 862, |
| | | "layers_number": 2, |
| | | "order_number": 33, |
| | | "process_id": "NG24120028A005", |
| | | "layers_number": 1, |
| | | "order_number": 1, |
| | | "process_id": "NG22091408A06", |
| | | "technology_number": 2, |
| | | "tempering_feed_sequence": 2, |
| | | "tempering_layout_id": 1, |
| | |
| | | ], |
| | | "guidance": 15, |
| | | "rackinfos": [ |
| | | "NG24120026A003-2", |
| | | "NG24120027A003-2", |
| | | "NG24120028A005-2" |
| | | "NG24111432A004-1", |
| | | "NG25000086A001-1" |
| | | ], |
| | | "ratioResult": [ |
| | | { |
| | |
| | | <div style="width: 100%; height: 100%;"> |
| | | |
| | | <div id="compute"> |
| | | <compute :data="computedData" @fetch-data="handleFetchData" :project="props.project" @sendData="handleData" @simulate-click="handleSimulation" /> |
| | | <compute :data="computedData" :state="state" @fetch-data="handleFetchData" :project="props.project" @sendData="handleData" @simulate-click="handleSimulation" /> |
| | | </div> |
| | | |
| | | <div id="computeCard"> |
| | |
| | | import request from "@/utils/request";
|
| | | import { useI18n } from "vue-i18n";
|
| | | import { ElMessage } from "element-plus";
|
| | | import {useRoute} from "vue-router";
|
| | | import useOrderInfoStore from "@/stores/sd/order/orderInfo";
|
| | |
|
| | | const route = useRoute();
|
| | | const orderInfo = useOrderInfoStore()
|
| | | const { t } = useI18n();
|
| | | const savedProjectNo = localStorage.getItem('projectNo');
|
| | | const processId = savedProjectNo;
|
| | |
| | | }
|
| | |
|
| | | onMounted(() => {
|
| | | selectLayout();
|
| | | if(orderInfo.optimizeData.optimalResults!=null){
|
| | | layoutData.value=orderInfo.optimizeData.optimalResults
|
| | | dataLoaded.value = true;
|
| | | }else{
|
| | | selectLayout();
|
| | | }
|
| | | });
|
| | | </script>
|
| | |
| | | '4rows-2cols': { width: 1000, height: 1000 }, |
| | | '3rows-2cols': { width: 1000, height: 1000 }, |
| | | '3rows-1col': { width: 1000, height: 1000 }, |
| | | '2rows-2cols': { width: 1200, height: 1200 } |
| | | '2rows-2cols': { width: 1400, height: 800 } |
| | | }; |
| | | |
| | | // 当前布局的尺寸 |
| | |
| | | <div >
|
| | | <RectRenderer
|
| | | :layoutData="layoutData"
|
| | | :gw="1400" |
| | | :gh="1100" |
| | | :gw="1400"
|
| | | :gh="800"
|
| | | style="width: 1500px; height: 800px; position: relative;"
|
| | | v-if="dataLoaded"
|
| | | />
|
| | |
| | |
|
| | | const saveToDatabase = () => {
|
| | | console.log(settings)
|
| | | request.post(`/glassOptimize/optimizeParms`, settings).then((res) => {
|
| | | request.post(`/glassOptimize/optimizeParms/${username}`, settings).then((res) => {
|
| | | if (res.code == 200 && res.data === true) {
|
| | | ElMessage.success(t('basicData.msg.saveSuccess'))
|
| | | } else {
|
| | |
| | | const paramMapping = {
|
| | | yShapeJoinOptimization: { name: '异形拼接优化', type: 'checkbox' },
|
| | | autoMiddleEmptyPairing: { name: '自动中空配对', type: 'checkbox' },
|
| | | smallPieceRotationProhibited: { name: '小片禁止旋转', type: 'checkbox' },
|
| | | smallPieceRotationProhibited: { name: '小片旋转', type: 'checkbox' },
|
| | | maxFramesOnSite: { name: '现场最大可放架子数量', type: 'text' },
|
| | | bendEdgeDistance: { name: '掰边距(mm)', type: 'text' },
|
| | | positiveTolerance: { name: '正公差(mm)', type: 'text' },
|
| | | negativeTolerance: { name: '负公差(mm)', type: 'text' },
|
| | | cutterOriginPosition: { name: '切割机原点位置', type: 'select' },
|
| | | uniformShapeEdgeTrimAmount: { name: '统一设置异形修边量', type: 'text' },
|
| | | edgeTrimMode: { name: '修边模式', type: 'select' },
|
| | | parallelOptimizationChannels: { name: '并行优化的通道数量', type: 'text' },
|
| | | optimizationMethod: { name: '优化方式', type: 'select' },
|
| | | travType: { name: '横切', type: 'select' },
|
| | | optimizationIterations: { name: '重复优化次数', type: 'text' },
|
| | | finishedProductGrindingAmount: { name: '成品默认磨量', type: 'text' },
|
| | | rawPieceEdgeTrimAmount: { name: '原片默认修边量', type: 'text' },
|
| | | finishedSinglePieceBelowGrindingAmount: { name: '成品单片小于多少时磨量为', type: 'text' }
|
| | | finishedSinglePieceBelowGrindingAmount: { name: '成品单片小于多少时磨量为', type: 'text' },
|
| | | rackCycleQty: { name: '循环落架数', type: 'text' }
|
| | | };
|
| | |
|
| | | // 动态生成参数列表
|
| | |
| | | <input
|
| | | v-if="param.type === 'checkbox'"
|
| | | type="checkbox"
|
| | | :checked="settings.optimization[param.key] === '1'"
|
| | | @click="() => { settings.optimization[param.key] = settings.optimization[param.key] === '1' ? '0' : '1' }"
|
| | | :checked="settings.optimization[param.key] === true"
|
| | | @click="() => { settings.optimization[param.key] = settings.optimization[param.key]!==true }"
|
| | | >
|
| | | <select
|
| | | v-else-if="param.type === 'select'"
|
| | | :name="param.key"
|
| | | class="cs"
|
| | | v-model="settings.optimization[param.key]"
|
| | | >
|
| | | <option
|
| | | v-for="option in getOptions(param.key)"
|
| | |
| | | function getOptions(key) {
|
| | | const optionsMapping = {
|
| | | cutterOriginPosition: [
|
| | | { value: 'topLeft', label: '左上角' },
|
| | | { value: 'bottomLeft', label: '左下角' },
|
| | | { value: 'topRight', label: '右上角' },
|
| | | { value: 'bottomRight', label: '右下角' }
|
| | | { value: 2, label: '左上角' },
|
| | | { value: 1, label: '左下角' },
|
| | | { value: 4, label: '右上角' },
|
| | | { value: 3, label: '右下角' }
|
| | | ],
|
| | | edgeTrimMode: [
|
| | | { value: 'intelligent', label: '智能修边' },
|
| | | { value: 'complete', label: '完全修边' }
|
| | | optimizationMethod: [
|
| | | { value: 1, label: 'optima' },
|
| | | { value: 2, label: '北玻' }
|
| | | ],
|
| | | travType: [
|
| | | { value: 'X', label: 'X' },
|
| | | { value: 'Y', label: 'Y' },
|
| | | { value: 'XY', label: 'XY' }
|
| | | ]
|
| | | };
|
| | | return optionsMapping[key] || [];
|
| | |
| | | import ProjectMange from "@/views/pp/glassOptimize/ProjectMange.vue"; |
| | | |
| | | import {ref} from "vue"; |
| | | import {ElMessage} from "element-plus"; |
| | | let dialogVisible = ref(false) |
| | | let detailPage = ref(0) |
| | | const changeDialog = (value) => { |
| | |
| | | |
| | | //从工程管理获取工程号,并跳转 |
| | | const projectNumber = ref(); |
| | | |
| | | const glassInventoryRef=ref(null) |
| | | const switchDialog = (number) => { |
| | | projectNumber.value = number; |
| | | detailPage.value = 3; |
| | |
| | | isTrimmingDialogVisible.value = value; |
| | | }; |
| | | |
| | | let checkboxChangeData = ref(''); |
| | | const getSmallPieceData = () => { |
| | | checkboxChangeData.value=glassInventoryRef.value.checkboxChanges(); |
| | | }; |
| | | |
| | | |
| | | |
| | | |
| | | </script> |
| | | |
| | | <template > |
| | |
| | | <project-detail @changeDialog="changeDialog" |
| | | @forward-data-to-grandparent="handleProjectDetailData" |
| | | @send-inventory-to-op="handleInventoyData" |
| | | :TrimmingDialogVisible="isTrimmingDialogVisible" /> |
| | | @getSmallPieceData="getSmallPieceData" |
| | | :TrimmingDialogVisible="isTrimmingDialogVisible" :CheckboxChangeData="checkboxChangeData" /> |
| | | </div> |
| | | <div id="main-footer"> |
| | | <glass-inventory :receivedData="dataForGlassInventory" |
| | | <glass-inventory ref="glassInventoryRef" |
| | | :receivedData="dataForGlassInventory" |
| | | :InventoryData="sendDataGlassInventory" |
| | | @select-trimming="sendTrimming"/> |
| | | </div> |
| | |
| | | {field: 'thickness', width: 50, title: '厚度',}, |
| | | {field: 'type', width: 50, title: '类型',}, |
| | | {field: 'state', width: 50, title: '状态',}, |
| | | {field: 'temperingState', width: 50, title: '钢化状态',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged}, |
| | | {field: 'optimizeState', width: 50, title: '优化状态',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged}, |
| | | {field: 'quantity', width: 50, title: '数量',}, |
| | | {field: 'area', width: 50, title: '面积',}, |
| | | {field: 'processCardQuantity', width: 100, title: '流程卡数量',}, |
| | |
| | | [ |
| | | {code: 'openProject', name: '打开工程', prefixIcon: 'vxe-icon-folder-open'}, |
| | | {code: 'compute', name: '模拟计算', prefixIcon: 'vxe-icon-subtable'}, |
| | | {code: 'optimizeTypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'}, |
| | | //{code: 'optimizeTypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'}, |
| | | {code: 'production', name: '允许生产', prefixIcon: 'vxe-icon-square-checked'}, |
| | | {code: 'novisible', name: '生产不可见', prefixIcon: 'vxe-icon-eye-fill-close'}, |
| | | {code: 'copyproject', name: '复刻工程', prefixIcon: 'vxe-icon-copy'}, |
| | |
| | | const operationConfigs = [ |
| | | { |
| | | code: 'openProject', // 打开工程 |
| | | initialState: ['1','10', '20', '100', '200'], // |
| | | initialState: ['1', '100', '200'], // |
| | | targetState: null, |
| | | successMsg: '已打开!', |
| | | checkMessage: '当前工程状态不符合条件,请确认工程状态后再操作!', |
| | | requiresRow: true, |
| | | openFile: async ({row}) => { |
| | | orderInfo.optimizeData.optimalResults=null |
| | | orderInfo.optimizeData.originalFilm=null |
| | | const projectNumber = row.projectNumber; |
| | | const thickness = row.thickness; |
| | | const glassType = row.glassType; |
| | | const quantity = row.quantity; |
| | | const area = row.area; |
| | | const optimizeState = row.optimizeState; |
| | | await router.push({ |
| | | name: 'optimizeInfo', |
| | | params: { |
| | |
| | | thickNess: thickness, |
| | | model: glassType, |
| | | quantity: quantity, |
| | | area: area |
| | | area: area, |
| | | optimizeState:optimizeState |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | { |
| | | code: 'compute', // 打开模拟计算操作 |
| | | initialState: ['1', '2'], // |
| | | initialState: '1', |
| | | temperingState: '0', |
| | | targetState: null, |
| | | successMsg: '模拟计算已启动!', |
| | | checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!', |
| | |
| | | }, |
| | | { |
| | | code: 'optimizeTypography', |
| | | initialState: ['10', '20','100'], // |
| | | initialState: ['1','100'], // |
| | | targetState: null, |
| | | successMsg: '优化排版已启动!', |
| | | checkMessage: '当前工程状态不符合优化排版条件,请确认工程状态后再操作!', |
| | |
| | | const projectNumber = row.projectNumber; |
| | | const thickness = row.thickness; |
| | | const glassType = row.glassType; |
| | | const quantity = row.quantity; |
| | | const area = row.area; |
| | | const optimizeState = row.optimizeState; |
| | | await router.push({ |
| | | name: 'optimizeInfo', |
| | | params: { |
| | | projectNo: projectNumber, |
| | | thickNess: thickness, |
| | | model: glassType |
| | | model: glassType, |
| | | quantity: quantity, |
| | | area: area, |
| | | optimizeState:optimizeState |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | { |
| | | code: 'undoCompute', |
| | | initialState: '10', |
| | | targetState: 2, |
| | | initialState: 1, |
| | | temperingState: 1, |
| | | targetState: 0, |
| | | targetStates: 0, |
| | | successMsg: '撤销模拟计算成功,数据已更新!', |
| | | checkMessage: '当前工程状态不符合撤销模拟计算条件,请确认工程状态后再操作!', |
| | | requiresRow: true, |
| | | }, |
| | | { |
| | | code: 'undoOptimize', |
| | | initialState: '20', |
| | | targetState: 10, |
| | | initialState: 1, |
| | | optimizeState: 1, |
| | | targetState: 0, |
| | | targetStates: 0, |
| | | successMsg: '撤销优化成功,数据已更新!', |
| | | checkMessage: '当前工程状态不符合撤销优化条件,请确认工程状态后再操作!', |
| | | requiresRow: true, |
| | | }, |
| | | { |
| | | code: 'production', |
| | | initialState: '20', |
| | | initialState: 1, |
| | | temperingState: 1, |
| | | optimizeState: 1, |
| | | targetState: 100, |
| | | targetStates: 0, |
| | | successMsg: '设置成功,允许生产!', |
| | | checkMessage: '当前工程状态不符合允许生产条件,请确认工程状态后再操作!', |
| | | requiresRow: true, |
| | | }, |
| | | { |
| | | code: 'novisible', |
| | | initialState: '100', |
| | | targetState: 20, |
| | | initialState: 100, |
| | | temperingState: 1, |
| | | optimizeState: 1, |
| | | targetState: 1, |
| | | targetStates: 0, |
| | | successMsg: '设置成功,生产不可见!', |
| | | checkMessage: '当前工程状态不符合生产不可见条件,请确认工程状态后再操作!', |
| | | requiresRow: true, |
| | |
| | | }, |
| | | { |
| | | code: 'delProject', |
| | | initialState: ['1', '2', '10', '20', '100'], |
| | | initialState: ['1', '100'], |
| | | targetState: null, |
| | | successMsg: '工程删除成功!', |
| | | checkMessage: '当前工程状态不符合删除条件,请确认工程状态后再操作!', |
| | |
| | | function getOriginalState(targetState) { |
| | | // 根据工程状态返回对应的原始状态 |
| | | const stateMapping = { |
| | | 2: '10', |
| | | 10: '20', |
| | | 100: '200', |
| | | 200: '100', |
| | | 1: ['2', '10', '20'], |
| | | 1: '100', |
| | | 100: '1' |
| | | }; |
| | | return stateMapping[targetState] || targetState; |
| | | } |
| | |
| | | return; |
| | | } |
| | | if (config.code === 'compute') { |
| | | config.actionFunction({row}); |
| | | if(row.state===1 && row.temperingState===0){ |
| | | config.actionFunction({row}); |
| | | }else{ |
| | | ElMessage.warning(config.checkMessage); |
| | | } |
| | | return; |
| | | } |
| | | else if (config.code === 'openProject') { |
| | | handleSameDataOperation(row).then(({isRoutesEqual}) => { |
| | | if (!isRoutesEqual) { |
| | | config.openFile({row}); |
| | | ElMessage.success(config.successMsg); |
| | | |
| | | } |
| | | }); |
| | | return; |
| | | } |
| | | // 添加确认提示弹窗,询问用户是否进行当前操作 |
| | |
| | | return; |
| | | } |
| | | deleteProject(row.projectNumber, config); |
| | | } else if (!checkOperationCondition(config, row)) { |
| | | ElMessage.warning(config.checkMessage); |
| | | return; |
| | | } else { |
| | | if (config.code === 'openProject') { |
| | | handleSameDataOperation(row).then(({isRoutesEqual}) => { |
| | | if (!isRoutesEqual) { |
| | | config.openFile({row}); |
| | | ElMessage.success(config.successMsg); |
| | | } |
| | | }); |
| | | } else if (config.code === 'compute') { |
| | | config.actionFunction({row}); |
| | | } else if (config.code === 'optimizeTypography') { |
| | | }else { |
| | | if (config.code === 'optimizeTypography') { |
| | | handleSameDataOperation(row).then(({isRoutesEqual}) => { |
| | | if (!isRoutesEqual) { |
| | | config.Typography({row}); |
| | | ElMessage.success(config.successMsg); |
| | | return; |
| | | } |
| | | }); |
| | | } |
| | | else { |
| | | row.state = config.targetState; |
| | | let code=0 |
| | | |
| | | if(config.code === 'undoCompute'){ |
| | | if(row.temperingState==1&&row.state===1){ |
| | | row.temperingState = config.targetStates; |
| | | code=1 |
| | | }else{ |
| | | ElMessage.warning(config.checkMessage); |
| | | return; |
| | | } |
| | | }else if(config.code === 'undoOptimize'){ |
| | | if(row.optimizeState==1&&row.state===1){ |
| | | row.optimizeState = config.targetStates; |
| | | code=2 |
| | | }else{ |
| | | ElMessage.warning(config.checkMessage); |
| | | return; |
| | | } |
| | | } |
| | | else if(config.code === 'production'){ |
| | | if(row.temperingState==1&&row.optimizeState===1&&row.state===1){ |
| | | row.state = config.targetState; |
| | | code=3 |
| | | }else{ |
| | | ElMessage.warning(config.checkMessage); |
| | | return; |
| | | } |
| | | } |
| | | else if(config.code === 'novisible'){ |
| | | if(row.state===100){ |
| | | row.state = config.targetState; |
| | | code=4 |
| | | }else{ |
| | | ElMessage.warning(config.checkMessage); |
| | | return; |
| | | } |
| | | } |
| | | const index = produceList.value.findIndex(item => item === row); |
| | | if (index !== -1) { |
| | | produceList.value.splice(index, 1, {...row}); |
| | | xGrid.value.reloadData(produceList.value); |
| | | } |
| | | if(config.code === 'undoCompute'){ |
| | | code=1 |
| | | }else if(config.code === 'undoOptimize'){ |
| | | code=2 |
| | | } |
| | | else if(config.code === 'production'){ |
| | | code=3 |
| | | } |
| | | else if(config.code === 'novisible'){ |
| | | code=4 |
| | | } |
| | | else if(config.code === 'InitializeProject'){ |
| | | code=5 |
| | | } |
| | | updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,code, config.successMsg); |
| | | updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,config.targetStates,code, config.successMsg); |
| | | } |
| | | } |
| | | }).catch(() => { |
| | |
| | | }; |
| | | |
| | | // 公共处理函数,处理相同数据时的操作,并返回targetRoute对象(右键菜单和双击打开) |
| | | const handleSameDataOperation = async ({projectNumber, thickness, glassType}) => { |
| | | const handleSameDataOperation = async ({projectNumber, thickness, glassType,quantity,area,optimizeState}) => { |
| | | const targetRoute = { |
| | | name: 'optimizeInfo', |
| | | params: { |
| | | projectNo: projectNumber, |
| | | thickNess: String(thickness), |
| | | model: glassType |
| | | model: glassType, |
| | | quantity: quantity, |
| | | area: area, |
| | | optimizeState:optimizeState |
| | | } |
| | | }; |
| | | const currentRoute = router.currentRoute.value; |
| | | console.log(router.currentRoute.value) |
| | | console.log(targetRoute) |
| | | const isRoutesEqual = currentRoute.name === targetRoute.name && |
| | | currentRoute.params.projectNo === targetRoute.params.projectNo && |
| | | currentRoute.params.thickNess === targetRoute.params.thickNess && |
| | | currentRoute.params.model === targetRoute.params.model; |
| | | parseFloat(currentRoute.params.thickNess) === parseFloat(targetRoute.params.thickNess) && |
| | | currentRoute.params.model === targetRoute.params.model && |
| | | parseInt(currentRoute.params.quantity) === parseInt(targetRoute.params.quantity) && |
| | | parseFloat(currentRoute.params.area) === parseFloat(targetRoute.params.area)&& |
| | | parseFloat(currentRoute.params.optimizeState) === parseFloat(targetRoute.params.optimizeState); |
| | | if (isRoutesEqual) { |
| | | handleConfirm(); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | function updateProjectStateAndHandleResponse(row, projectNumber, targetState,code, successMsg) { |
| | | function updateProjectStateAndHandleResponse(row, projectNumber, targetState,targetStates,code, successMsg) { |
| | | const updateParams = { |
| | | projectNumber: projectNumber, |
| | | stateToUpdate: targetState |
| | | stateToUpdate: targetState, |
| | | targetStates: targetStates |
| | | }; |
| | | request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${code}`, updateParams, { |
| | | request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${targetStates}/${code}`, updateParams, { |
| | | headers: { |
| | | 'Content-Type': 'application/json' |
| | | } |
| | |
| | | value: '1', |
| | | label: '初始状态,1', |
| | | }, |
| | | { |
| | | /*{ |
| | | value: '2', |
| | | label: '第一次优化,2', |
| | | }, |
| | |
| | | { |
| | | value: '20', |
| | | label: '优化完成,20', |
| | | }, |
| | | },*/ |
| | | { |
| | | value: '100', |
| | | label: '生产可见,100', |
| | |
| | | const params = buildRequestParams(); |
| | | request.post(`/glassOptimize/optimizeProjectMange/${params.startSelectTime}/${params.endSelectTime}`, filterData.value).then((res) => { |
| | | if (res.code == 200) { |
| | | console.log(res.data.data) |
| | | produceList.value = deepClone(res.data.data); |
| | | gridOptions.data = produceList.value; |
| | | xGrid.value.loadData(produceList.value); |
| | |
| | | const props = defineProps({ |
| | | projectNo : String, |
| | | project: null, |
| | | state:null, |
| | | data: { |
| | | type: Array, |
| | | default: () => [] |
| | |
| | | |
| | | |
| | | const handleSave = () => { |
| | | |
| | | if (props.data) { |
| | | console.log(props.data) |
| | | if(props.state==3){ |
| | | |
| | | let projectData = ref({ |
| | | projectdetail: props.data.data[0].glass_details, |
| | | ratioResult: props.data.data[0].ratioResult, |
| | | rackinfos: props.data.data[0].rackinfos, |
| | | resultSum: props.data.data[0].resultSum, |
| | | guidance: props.data.data[0].guidance, |
| | | userName : username, |
| | | inputValues:inputValues |
| | | }) |
| | | |
| | | request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => { |
| | | if (res.code == 200 && res.data === true) { |
| | | ElMessage.success(t('basicData.msg.saveSuccess')) |
| | | |
| | | } else { |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }) |
| | | let projectData = ref({ |
| | | inputValues:inputValues, |
| | | userName : username, |
| | | state:props.state |
| | | }) |
| | | |
| | | request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => { |
| | | if (res.code == 200 && res.data === true) { |
| | | ElMessage.success(t('basicData.msg.saveSuccess')) |
| | | |
| | | } else { |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }) |
| | | |
| | | }else{ |
| | | if (props.data) { |
| | | |
| | | let projectData = ref({ |
| | | projectdetail: props.data.data[0].glass_details, |
| | | ratioResult: props.data.data[0].ratioResult, |
| | | rackinfos: props.data.data[0].rackinfos, |
| | | resultSum: props.data.data[0].resultSum, |
| | | guidance: props.data.data[0].guidance, |
| | | userName : username, |
| | | inputValues:inputValues, |
| | | state:props.state |
| | | }) |
| | | |
| | | request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => { |
| | | if (res.code == 200 && res.data === true) { |
| | | ElMessage.success(t('basicData.msg.saveSuccess')) |
| | | |
| | | } else { |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }) |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {useRoute} from "vue-router"; |
| | | import {addListener, toolbarButtonClickEvent} from "@/hook/mouseMove"; |
| | | import useOrderInfoStore from "@/stores/sd/order/orderInfo"; |
| | | const { t } = useI18n() |
| | | const orderInfo = useOrderInfoStore() |
| | | |
| | | const xGrid = ref() |
| | | const gridOptions = reactive({ |
| | |
| | | |
| | | columns:[ |
| | | {type:'seq',fixed:"left", title:' ', width: 50}, |
| | | {type: 'checkbox', fixed: "left", title: t('basicData.check'), width: 80}, |
| | | {type: 'checkbox', fixed: "left", title: t('basicData.check'), width: 80}, |
| | | {field: 'id', title: '物料编码',}, |
| | | {field:'width',editRender: { name: 'input',attrs: {disabled:true}}, title: t('order.width'),}, |
| | | {field: 'height',editRender: { name: 'input',attrs: {disabled:true}},title: t('order.height')}, |
| | |
| | | }, |
| | | }) |
| | | |
| | | const emit = defineEmits(['select-trimming']); |
| | | const emit = defineEmits(['select-trimming'],['checkboxChange']); |
| | | // 右键菜单 |
| | | const operationConfigs = [ |
| | | { |
| | |
| | | let type = ref(1); |
| | | |
| | | const selectMaterialStore = async () =>{ |
| | | request.get(`/glassOptimize/materialStore/${thickness.value}/${model.value}/${projectNo}?type=${type.value}`).then((res) => { |
| | | request.get(`/glassOptimize/materialStore/${thickness.value}/${model.value}/${projectNo.value}?type=${type.value}`).then((res) => { |
| | | if (Number(res.code) === 200) { |
| | | const rawData = res.data.data; |
| | | const edgeTrimming = res.data.edgeTrimming; |
| | |
| | | gridOptions.columns[10].editRender.attrs.disabled=true |
| | | gridOptions.columns[11].editRender.attrs.disabled=true |
| | | } |
| | | if(orderInfo.optimizeData.originalFilm!==null){ |
| | | formattedData.forEach(item => { |
| | | orderInfo.optimizeData.originalFilm.forEach(items => { |
| | | if(item.id===items.stockCode){ |
| | | item.processingQuantity=items.count |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | xGrid.value.loadData(formattedData); |
| | | gridOptions.data = formattedData; |
| | | } else { |
| | |
| | | onMounted(() => { |
| | | addListener(xGrid.value,gridOptions) |
| | | if(route.params.projectNo!=null){ |
| | | projectNo=route.params.projectNo |
| | | projectNo.value=route.params.projectNo |
| | | selectMaterialStore(); |
| | | }else if(orderInfo.projectNo!==null){ |
| | | projectNo.value=orderInfo.projectNo.projectNo |
| | | thickness.value=orderInfo.projectNo.thickNess |
| | | model.value=orderInfo.projectNo.model |
| | | selectMaterialStore(); |
| | | } |
| | | |
| | |
| | | }; |
| | | |
| | | |
| | | const checkboxChanges= () => { |
| | | return xGrid.value.getCheckboxRecords(); |
| | | } |
| | | |
| | | defineExpose({checkboxChanges}) |
| | | </script> |
| | | |
| | | <template> |
| | |
| | | @click="selectLayout(layoutIndex)"
|
| | | :class="{ 'selected': selectedLayoutIndex === layoutIndex }"
|
| | | >
|
| | | {{ layout.width }} × {{ layout.height }} × {{ layout.SameCount }}
|
| | | {{ layout.width }} × {{ layout.height }} × {{ layout.quantity }}
|
| | | </div>
|
| | | </div>
|
| | |
|
| | |
| | | <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
|
| | | <!-- 灰色矩形 -->
|
| | | <div
|
| | | v-for="(rect, rectIndex) in layout.rects.filter(r => r.isRemain)"
|
| | | v-for="(glassDetail, rectIndex) in layout.glassDetails.filter(r => r.isRemain)"
|
| | | :key="`gray-${rectIndex}`"
|
| | | :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
|
| | | class="layout-rect"
|
| | | :style="rectStyle(rect, layoutIndex)"
|
| | | @contextmenu.prevent="handleGrayRectRightClick(layoutIndex, rectIndex,rect)"
|
| | | class="layout-glassDetail"
|
| | | :style="rectStyle(glassDetail, layoutIndex)"
|
| | | @contextmenu.prevent="handleGrayRectRightClick(layoutIndex, rectIndex,glassDetail)"
|
| | | >
|
| | | <!-- <div class="rect-content">
|
| | | <div class="size">{{ rect.w }}×{{ rect.h }}</div>
|
| | | <div v-if="showJiaHao" class="jia-hao">{{ rect.JiaHao }}</div>
|
| | | <div v-if="showProcessId" class="liuchengka">{{ rect.liuchengka }}</div>
|
| | | <!-- <div class="glassDetail-content">
|
| | | <div class="size">{{ glassDetail.width }}×{{ glassDetail.height }}</div>
|
| | | <div v-if="showJiaHao" class="jia-hao">{{ glassDetail.JiaHao }}</div>
|
| | | <div v-if="showProcessId" class="liuchengka">{{ glassDetail.liuchengka }}</div>
|
| | | </div>-->
|
| | | </div>
|
| | |
|
| | | <!-- 蓝色矩形 -->
|
| | | <div
|
| | | v-for="(rect, rectIndex) in layout.rects.filter(r => !r.isRemain)"
|
| | | v-for="(glassDetail, rectIndex) in layout.glassDetails.filter(r => !r.isRemain)"
|
| | | :key="`blue-${rectIndex}`"
|
| | | :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
|
| | | class="layout-rect"
|
| | | :style="rectStyle(rect, layoutIndex)"
|
| | | class="layout-glassDetail"
|
| | | :style="rectStyle(glassDetail, layoutIndex)"
|
| | | @contextmenu.prevent="handleRectRightClick(layoutIndex, rectIndex)"
|
| | | @mousedown="handleRectDragStart(layoutIndex, rectIndex)"
|
| | | @mousemove="handleRectDragging"
|
| | |
| | | @mouseleave="handleRectDragEnd"
|
| | | @click="handleRectClick(layoutIndex, rectIndex)"
|
| | | >
|
| | | <div class="rect-content">
|
| | | <div class="size">{{ rect.w }}×{{ rect.h }}</div>
|
| | | <div class="glassDetail-content">
|
| | | <div class="size">{{ glassDetail.realWidth }}×{{ glassDetail.realHeight }}</div>
|
| | | <div>{{rectIndex }}</div>
|
| | | <div v-if="showJiaHao" class="jia-hao">{{ rect.JiaHao }}</div>
|
| | | <div v-if="showProcessId" class="liuchengka">{{ rect.liuchengka }}</div>
|
| | | <div v-if="showJiaHao" class="jia-hao">{{ glassDetail.rackNo }}</div>
|
| | | <div v-if="showProcessId" class="liuchengka">{{ glassDetail.processId }}</div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
| | | const rectsElements = ref({});
|
| | | const focusIndex = ref(null);
|
| | | const layouts = ref([]);
|
| | | const layoutsHead = ref();
|
| | | const panelClass = ref('');
|
| | | const panelStyle = ref(props.style);
|
| | | const rectClass = ref('layout-rect');
|
| | | const rectClass = ref('layout-glassDetail');
|
| | | const selectedLayoutIndex = ref(0);
|
| | | const currentRect = ref(null);
|
| | | const dragging = ref(false);
|
| | |
| | | //保存调整
|
| | | const submitLayouts = async () => {
|
| | | layouts.value.forEach(layout => {
|
| | | layout.rects.forEach(rect => {
|
| | | rect.x = Math.round(rect.x);
|
| | | rect.y = Math.round(rect.y);
|
| | | rect.w = Math.round(rect.w);
|
| | | rect.h = Math.round(rect.h);
|
| | | layout.glassDetails.forEach(glassDetail => {
|
| | | glassDetail.x = Math.round(glassDetail.x);
|
| | | glassDetail.y = Math.round(glassDetail.y);
|
| | | glassDetail.width = Math.round(glassDetail.width);
|
| | | glassDetail.height = Math.round(glassDetail.height);
|
| | | });
|
| | | });
|
| | | const savedProjectNo = localStorage.getItem('projectNo');
|
| | | const processId = savedProjectNo;
|
| | | const Layouts = layouts.value;
|
| | | request.post(`/glassOptimize/updateOptimizeResult/${processId}`, JSON.stringify({ Layouts }), {
|
| | | layoutsHead.value.Layouts=layouts.value
|
| | | request.post(`/glassOptimize/updateOptimizeResult/${processId}`, layoutsHead.value, {
|
| | | headers: {
|
| | | 'Content-Type': 'application/json'
|
| | | }
|
| | |
| | | const newRect = {
|
| | | x: 0,
|
| | | y: 0,
|
| | | w: values[0],
|
| | | h: values[1],
|
| | | width: values[0],
|
| | | height: values[1],
|
| | | isRemain: false
|
| | | };
|
| | | addNewRect(layoutIndex, newRect);
|
| | |
| | | if (bestFitPosition) {
|
| | | newRect.x = bestFitPosition.x;
|
| | | newRect.y = bestFitPosition.y;
|
| | | layout.rects.push(newRect);
|
| | | layout.glassDetails.push(newRect);
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | } else {
|
| | | ElMessage.warning('无法放置,没有足够的空间');
|
| | |
| | | //添加成品判断是否可以放下
|
| | | const findBestFitPosition = (layoutIndex, newRect) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const obstacles = layout.rects.filter(r => !r.isRemain);
|
| | | const obstacles = layout.glassDetails.filter(r => !r.isRemain);
|
| | | let bestFit = null;
|
| | | let minAreaDifference = Infinity;
|
| | |
|
| | | const remainingAreas = calculateRemainingAreas(layout.width, layout.height, obstacles);
|
| | | remainingAreas.forEach(area => {
|
| | | if (newRect.w <= area.w && newRect.h <= area.h) {
|
| | | const areaDifference = Math.abs(area.w * area.h - newRect.w * newRect.h);
|
| | | if (newRect.width <= area.width && newRect.height <= area.height) {
|
| | | const areaDifference = Math.abs(area.width * area.height - newRect.width * newRect.height);
|
| | | if (areaDifference < minAreaDifference) {
|
| | | minAreaDifference = areaDifference;
|
| | | bestFit = {
|
| | | x: area.x,
|
| | | y: area.y,
|
| | | w: newRect.w,
|
| | | h: newRect.h
|
| | | width: newRect.width,
|
| | | height: newRect.height
|
| | | };
|
| | | }
|
| | | }
|
| | |
| | | //版图内容样式加载
|
| | | const layoutContainerStyle = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | const scale = Math.min(0.25
|
| | | );
|
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${(props.gw - layout.width * scale) / 2}px`,
|
| | | top: `${(props.gh - layout.height * scale) / 2}px`,
|
| | | left: `20px`,
|
| | | top: `140px`,
|
| | | width: `${layout.width * scale}px`,
|
| | | height: `${layout.height * scale}px`,
|
| | | overflow: 'visible',
|
| | |
| | | //版图内容头部样式加载
|
| | | const layoutInfoStyle = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | const scale = Math.min(0.25
|
| | | );
|
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${(props.gw - layout.width * scale) / 2}px`,
|
| | | top: `${(props.gh - layout.height * scale) / 2 - 45}px`,
|
| | | left: `20px`,
|
| | | top: `100px`,
|
| | | background: 'none',
|
| | | textAlign: 'center',
|
| | | zIndex: 1000
|
| | |
| | | };
|
| | |
|
| | | //版图内容小片样式加载
|
| | | const rectStyle = (rect, layoutIndex) => {
|
| | | const rectStyle = (glassDetail, layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | const scale = Math.min(0.25
|
| | | );
|
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${rect.x * scale}px`,
|
| | | bottom: `${rect.y * scale}px`,
|
| | | width: `${rect.w * scale}px`,
|
| | | height: `${rect.h * scale}px`,
|
| | | backgroundColor: rect.isRemain ? '#f0f0f0' : themeColor.value,
|
| | | left: `${glassDetail.x * scale}px`,
|
| | | bottom: `${glassDetail.y * scale}px`,
|
| | | width: `${glassDetail.width * scale}px`,
|
| | | height: `${glassDetail.height * scale}px`,
|
| | | backgroundColor: glassDetail.isRemain ? '#f0f0f0' : themeColor.value,
|
| | | border: '1px solid #000',
|
| | | cursor: 'pointer',
|
| | | draggable: !rect.isRemain,
|
| | | zIndex: rect.isRemain ? 1 : 2
|
| | | draggable: !glassDetail.isRemain,
|
| | | zIndex: glassDetail.isRemain ? 1 : 2
|
| | | };
|
| | | };
|
| | |
|
| | |
| | |
|
| | | //小片右键菜单功能
|
| | | const handleRectRightClick = (layoutIndex, rectIndex) => {
|
| | | const rect = layouts.value[layoutIndex].rects[rectIndex];
|
| | | if (rect.isRemain) return;
|
| | | const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
|
| | | if (glassDetail.isRemain) return;
|
| | |
|
| | | const contextMenu = document.createElement('div');
|
| | | contextMenu.className = 'context-menu';
|
| | |
| | | };
|
| | |
|
| | | //余料右键菜单功能
|
| | | const handleGrayRectRightClick = (layoutIndex, rectIndex,rects) => {
|
| | | //const rect = rects[rectIndex];
|
| | | if (!rects.isRemain) return;
|
| | | const handleGrayRectRightClick = (layoutIndex, rectIndex,glassDetails) => {
|
| | | //const glassDetail = glassDetails[rectIndex];
|
| | | if (!glassDetails.isRemain) return;
|
| | |
|
| | | const contextMenu = document.createElement('div');
|
| | | contextMenu.className = 'context-menu';
|
| | |
| | | //小片鼠标按下事件
|
| | | const handleRectDragStart = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | if (rect.isRemain) return;
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | if (glassDetail.isRemain) return;
|
| | |
|
| | | dragging.value = true;
|
| | | dragRect.value = { layoutIndex, rectIndex };
|
| | |
| | | const layoutIndex = dragRect.value.layoutIndex;
|
| | | const rectIndex = dragRect.value.rectIndex;
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | |
| | | const deltaX = event.clientX - dragStartPos.value.x;
|
| | | const deltaY = event.clientY - dragStartPos.value.y;
|
| | |
|
| | | const newRect = { ...rect };
|
| | | const newRect = { ...glassDetail };
|
| | | newRect.x += deltaX / scale;
|
| | | newRect.y += deltaY / scale;
|
| | |
|
| | | const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
|
| | | const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
|
| | | let isValidMove = true;
|
| | |
|
| | | otherRects.forEach(otherRect => {
|
| | |
| | | });
|
| | |
|
| | | if (newRect.x < 0 || newRect.y < 0 ||
|
| | | newRect.x + newRect.w > layout.width ||
|
| | | newRect.y + newRect.h > layout.height) {
|
| | | newRect.x + newRect.width > layout.width ||
|
| | | newRect.y + newRect.height > layout.height) {
|
| | | isValidMove = false;
|
| | | }
|
| | |
|
| | | if (isValidMove) {
|
| | | rect.x = newRect.x;
|
| | | rect.y = newRect.y;
|
| | | glassDetail.x = newRect.x;
|
| | | glassDetail.y = newRect.y;
|
| | | dragStartPos.value = {
|
| | | x: event.clientX,
|
| | | y: event.clientY
|
| | |
| | | if (dragRect.value) {
|
| | | const layoutIndex = dragRect.value.layoutIndex;
|
| | | const rectIndex = dragRect.value.rectIndex;
|
| | | const rect = layouts.value[layoutIndex].rects[rectIndex];
|
| | | const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const scale = Math.min(
|
| | | (props.gw - 100) / layout.width,
|
| | | (props.gh - 100) / layout.height
|
| | | );
|
| | |
|
| | | rect.x = Math.round(rect.x);
|
| | | rect.y = Math.round(rect.y);
|
| | | glassDetail.x = Math.round(glassDetail.x);
|
| | | glassDetail.y = Math.round(glassDetail.y);
|
| | | adjustAlignmentPosition(layoutIndex, rectIndex);
|
| | | }
|
| | |
|
| | |
| | |
|
| | | const adjustAlignmentPosition = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const otherRects = layout.rects.filter((r, i) => i !== rectIndex);
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const otherRects = layout.glassDetails.filter((r, i) => i !== rectIndex);
|
| | |
|
| | | const threshold = Math.max(rect.w, rect.h) * 0.1;
|
| | | const threshold = Math.max(glassDetail.width, glassDetail.height) * 0.1;
|
| | |
|
| | | otherRects.forEach(otherRect => {
|
| | | // 水平对齐
|
| | | if (Math.abs(rect.x - otherRect.x) < threshold) {
|
| | | rect.x = Math.round((rect.x + otherRect.x) / 2);
|
| | | if (Math.abs(glassDetail.x - otherRect.x) < threshold) {
|
| | | glassDetail.x = Math.round((glassDetail.x + otherRect.x) / 2);
|
| | | }
|
| | | // 水平对齐右侧边缘
|
| | | if (Math.abs((rect.x + rect.w) - (otherRect.x + otherRect.w)) < threshold) {
|
| | | rect.x = Math.round((otherRect.x + otherRect.w - rect.w));
|
| | | if (Math.abs((glassDetail.x + glassDetail.width) - (otherRect.x + otherRect.width)) < threshold) {
|
| | | glassDetail.x = Math.round((otherRect.x + otherRect.width - glassDetail.width));
|
| | | }
|
| | | // 垂直对齐
|
| | | if (Math.abs(rect.y - otherRect.y) < threshold) {
|
| | | rect.y = Math.round((rect.y + otherRect.y) / 2);
|
| | | if (Math.abs(glassDetail.y - otherRect.y) < threshold) {
|
| | | glassDetail.y = Math.round((glassDetail.y + otherRect.y) / 2);
|
| | | }
|
| | | // 垂直对齐下边缘
|
| | | if (Math.abs((rect.y + rect.h) - (otherRect.y + otherRect.h)) < threshold) {
|
| | | rect.y = Math.round((otherRect.y + otherRect.h - rect.h));
|
| | | if (Math.abs((glassDetail.y + glassDetail.height) - (otherRect.y + otherRect.height)) < threshold) {
|
| | | glassDetail.y = Math.round((otherRect.y + otherRect.height - glassDetail.height));
|
| | | }
|
| | | });
|
| | |
|
| | | // 确保矩形不会超出布局边界
|
| | | rect.x = Math.max(0, rect.x);
|
| | | rect.y = Math.max(0, rect.y);
|
| | | rect.x = Math.min(rect.x, layout.width - rect.w);
|
| | | rect.y = Math.min(rect.y, layout.height - rect.h);
|
| | | glassDetail.x = Math.max(0, glassDetail.x);
|
| | | glassDetail.y = Math.max(0, glassDetail.y);
|
| | | glassDetail.x = Math.min(glassDetail.x, layout.width - glassDetail.width);
|
| | | glassDetail.y = Math.min(glassDetail.y, layout.height - glassDetail.height);
|
| | |
|
| | | // 调整后重新计算灰色余料
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | };
|
| | |
|
| | | const mergeAdjacentGrayRects = (rects,totalWidth,totalHeight) => {
|
| | | const grayRects = rects.filter(r => r.isRemain);
|
| | | const grayRects2 = rects.filter(r => r.isRemain);
|
| | | const mergeAdjacentGrayRects = (glassDetails,totalWidth,totalHeight) => {
|
| | | const grayRects = glassDetails.filter(r => r.isRemain);
|
| | | const grayRects2 = glassDetails.filter(r => r.isRemain);
|
| | | let merged = [];
|
| | |
|
| | | grayRects.sort((a, b) => {
|
| | |
| | | const current = grayRects[i];
|
| | |
|
| | |
|
| | | if (current.x === last.x + last.w &&
|
| | | if (current.x === last.x + last.width &&
|
| | | current.y === last.y &&
|
| | | current.h === last.h) {
|
| | | last.w += current.w;
|
| | | current.height === last.height) {
|
| | | last.width += current.width;
|
| | | last.x = Math.round(last.x);
|
| | | last.y = Math.round(last.y);
|
| | | last.w = Math.round(last.w);
|
| | | last.h = Math.round(last.h);
|
| | | } else if (current.y === last.y + last.h &&
|
| | | last.width = Math.round(last.width);
|
| | | last.height = Math.round(last.height);
|
| | | } else if (current.y === last.y + last.height &&
|
| | | current.x === last.x &&
|
| | | current.w === last.w) {
|
| | | last.h += current.h;
|
| | | current.width === last.width) {
|
| | | last.height += current.height;
|
| | | last.x = Math.round(last.x);
|
| | | last.y = Math.round(last.y);
|
| | | last.w = Math.round(last.w);
|
| | | last.h = Math.round(last.h);
|
| | | last.width = Math.round(last.width);
|
| | | last.height = Math.round(last.height);
|
| | | } else {
|
| | | merged.push({
|
| | | x: Math.round(current.x),
|
| | | y: Math.round(current.y),
|
| | | w: Math.round(current.w),
|
| | | h: Math.round(current.h),
|
| | | width: Math.round(current.width),
|
| | | height: Math.round(current.height),
|
| | | isRemain: true
|
| | | });
|
| | | }
|
| | | }
|
| | |
|
| | | const nonGray = rects.filter(r => !r.isRemain);
|
| | | const nonGray = glassDetails.filter(r => !r.isRemain);
|
| | | //删除原数组拼接新的小片跟余料
|
| | | rects.splice(0, rects.length, ...nonGray, ...merged);
|
| | | glassDetails.splice(0, glassDetails.length, ...nonGray, ...merged);
|
| | | };
|
| | |
|
| | | // 调整后重新计算灰色余料
|
| | | const adjustGrayRectangles = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rects = layout.rects;
|
| | | const glassDetails = layout.glassDetails;
|
| | | //小片的数据
|
| | | const nonGrayRects = rects.filter(rect => !rect.isRemain);
|
| | | const nonGrayRects = glassDetails.filter(glassDetail => !glassDetail.isRemain);
|
| | |
|
| | | //所有的小片余料坐标跟尺寸
|
| | | let remainingAreas = calculateRemainingAreas(layout.width, layout.height, nonGrayRects);
|
| | |
| | | new Set(remainingAreas.map(item => JSON.stringify(item)))
|
| | | ).map(item => JSON.parse(item));
|
| | | //余料的数据
|
| | | const currentGrayRects = rects.filter(r => r.isRemain);
|
| | | const currentGrayRects = glassDetails.filter(r => r.isRemain);
|
| | | //循环余料数据跟全部的对比
|
| | | currentGrayRects.forEach((_, index) => {
|
| | | if (index >= remainingAreas.length) {
|
| | | rects.splice(index, 1);
|
| | | glassDetails.splice(index, 1);
|
| | | }
|
| | | });
|
| | |
|
| | |
| | | if (index < currentGrayRects.length) {
|
| | | currentGrayRects[index].x = Math.round(area.x);
|
| | | currentGrayRects[index].y = Math.round(area.y);
|
| | | currentGrayRects[index].w = Math.round(area.w);
|
| | | currentGrayRects[index].h = Math.round(area.h);
|
| | | currentGrayRects[index].width = Math.round(area.width);
|
| | | currentGrayRects[index].height = Math.round(area.height);
|
| | | } else {
|
| | | rects.push({
|
| | | glassDetails.push({
|
| | | x: Math.round(area.x),
|
| | | y: Math.round(area.y),
|
| | | w: Math.round(area.w),
|
| | | h: Math.round(area.h),
|
| | | width: Math.round(area.width),
|
| | | height: Math.round(area.height),
|
| | | isRemain: true
|
| | | });
|
| | | }
|
| | | });
|
| | |
|
| | | mergeAdjacentGrayRects(rects,layout.width, layout.height);
|
| | | mergeAdjacentGrayRects(glassDetails,layout.width, layout.height);
|
| | | };
|
| | |
|
| | | //旋转方法
|
| | | const rotateRect = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const originalState = { ...rect };
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const originalState = { ...glassDetail };
|
| | |
|
| | | const temp = rect.w;
|
| | | rect.w = rect.h;
|
| | | rect.h = temp;
|
| | | const temp = glassDetail.width;
|
| | | glassDetail.width = glassDetail.height;
|
| | | glassDetail.height = temp;
|
| | |
|
| | | const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
|
| | | const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
|
| | | let isValidRotation = true;
|
| | |
|
| | | otherRects.forEach(otherRect => {
|
| | | if (checkOverlap(rect, otherRect)) {
|
| | | if (checkOverlap(glassDetail, otherRect)) {
|
| | | isValidRotation = false;
|
| | | }
|
| | | });
|
| | |
|
| | | if (rect.x + rect.w > layout.width || rect.y + rect.h > layout.height) {
|
| | | if (glassDetail.x + glassDetail.width > layout.width || glassDetail.y + glassDetail.height > layout.height) {
|
| | | isValidRotation = false;
|
| | | }
|
| | |
|
| | | if (isValidRotation) {
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | } else {
|
| | | rect.w = originalState.w;
|
| | | rect.h = originalState.h;
|
| | | glassDetail.width = originalState.width;
|
| | | glassDetail.height = originalState.height;
|
| | | ElMessage.warning('无法旋转,存在重叠或超出边界');
|
| | | }
|
| | | };
|
| | |
| | | //移动旋转方法
|
| | | const moveRectAndRotate = (layoutIndex, rectIndex, direction) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const grayRects = layout.rects.filter(r => r.isRemain);
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const grayRects = layout.glassDetails.filter(r => r.isRemain);
|
| | |
|
| | | const temp = rect.w;
|
| | | rect.w = rect.h;
|
| | | rect.h = temp;
|
| | | const temp = glassDetail.width;
|
| | | glassDetail.width = glassDetail.height;
|
| | | glassDetail.height = temp;
|
| | |
|
| | | const canPlace = grayRects.some(grayRect => {
|
| | | return grayRect.w >= rect.w && grayRect.h >= rect.h;
|
| | | return grayRect.width >= glassDetail.width && grayRect.height >= glassDetail.height;
|
| | | });
|
| | |
|
| | | if (!canPlace) {
|
| | | const temp = rect.w;
|
| | | rect.w = rect.h;
|
| | | rect.h = temp;
|
| | | const temp = glassDetail.width;
|
| | | glassDetail.width = glassDetail.height;
|
| | | glassDetail.height = temp;
|
| | | ElMessage.warning('无法旋转,没有足够的空间');
|
| | | return;
|
| | | }
|
| | |
| | | //移动方法
|
| | | const moveRect = (layoutIndex, rectIndex, direction) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const originalState = { ...rect };
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const originalState = { ...glassDetail };
|
| | |
|
| | | let maxStep = 0;
|
| | | const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
|
| | | const obstacles = layout.glassDetails.filter(r => r.isRemain || r !== glassDetail);
|
| | |
|
| | | switch (direction) {
|
| | | case 'up':
|
| | | maxStep = getAvailableSpaceUp(rect, layout, obstacles);
|
| | | maxStep = getAvailableSpaceUp(glassDetail, layout, obstacles);
|
| | | break;
|
| | | case 'down':
|
| | | maxStep = getAvailableSpaceDown(rect, layout, obstacles);
|
| | | maxStep = getAvailableSpaceDown(glassDetail, layout, obstacles);
|
| | | break;
|
| | | case 'left':
|
| | | maxStep = getAvailableSpaceLeft(rect, layout, obstacles);
|
| | | maxStep = getAvailableSpaceLeft(glassDetail, layout, obstacles);
|
| | | break;
|
| | | case 'right':
|
| | | maxStep = getAvailableSpaceRight(rect, layout, obstacles);
|
| | | maxStep = getAvailableSpaceRight(glassDetail, layout, obstacles);
|
| | | break;
|
| | | }
|
| | |
|
| | |
| | |
|
| | | switch (direction) {
|
| | | case 'up':
|
| | | rect.y += maxStep;
|
| | | glassDetail.y += maxStep;
|
| | | break;
|
| | | case 'down':
|
| | | rect.y -= maxStep;
|
| | | glassDetail.y -= maxStep;
|
| | | break;
|
| | | case 'left':
|
| | | rect.x -= maxStep;
|
| | | glassDetail.x -= maxStep;
|
| | | break;
|
| | | case 'right':
|
| | | rect.x += maxStep;
|
| | | glassDetail.x += maxStep;
|
| | | break;
|
| | | }
|
| | |
|
| | | const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
|
| | | const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
|
| | | let isValidMove = true;
|
| | |
|
| | | otherRects.forEach(otherRect => {
|
| | | if (checkOverlap(rect, otherRect)) {
|
| | | if (checkOverlap(glassDetail, otherRect)) {
|
| | | isValidMove = false;
|
| | | }
|
| | | });
|
| | |
|
| | | if (rect.x < 0 || rect.y < 0 ||
|
| | | rect.x + rect.w > layout.width ||
|
| | | rect.y + rect.h > layout.height) {
|
| | | if (glassDetail.x < 0 || glassDetail.y < 0 ||
|
| | | glassDetail.x + glassDetail.width > layout.width ||
|
| | | glassDetail.y + glassDetail.height > layout.height) {
|
| | | isValidMove = false;
|
| | | }
|
| | |
|
| | | if (isValidMove) {
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | } else {
|
| | | rect.x = originalState.x;
|
| | | rect.y = originalState.y;
|
| | | glassDetail.x = originalState.x;
|
| | | glassDetail.y = originalState.y;
|
| | | ElMessage.warning('无法移动,存在重叠或超出边界');
|
| | | }
|
| | | };
|
| | |
| | | //删除小片
|
| | | const deleteRect = (layoutIndex, rectIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | layout.rects.splice(rectIndex, 1);
|
| | | layout.glassDetails.splice(rectIndex, 1);
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | };
|
| | |
|
| | | //判断原片跟小片移动是否超出
|
| | | const checkOverlap = (rect1, rect2) => {
|
| | | return !(rect1.x + rect1.w <= rect2.x ||
|
| | | rect1.x >= rect2.x + rect2.w ||
|
| | | rect1.y + rect1.h <= rect2.y ||
|
| | | rect1.y >= rect2.y + rect2.h);
|
| | | return !(rect1.x + rect1.width <= rect2.x ||
|
| | | rect1.x >= rect2.x + rect2.width ||
|
| | | rect1.y + rect1.height <= rect2.y ||
|
| | | rect1.y >= rect2.y + rect2.height);
|
| | | };
|
| | |
|
| | | //重新计算余料坐标以及尺寸1
|
| | | const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
|
| | | let remaining = [{ x: 0, y: 0, w: totalWidth, h: totalHeight }];
|
| | | obstacles.forEach(rect => {
|
| | | remaining = cutRemainingAreas(remaining, rect,totalWidth,totalHeight);
|
| | | let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
|
| | | obstacles.forEach(glassDetail => {
|
| | | remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
|
| | | });
|
| | | return remaining;
|
| | | };
|
| | |
| | | newRemaining.push({
|
| | | x: area.x,
|
| | | y: area.y,
|
| | | w: obstacle.x - area.x,
|
| | | h: area.h
|
| | | width: obstacle.x - area.x,
|
| | | height: area.height
|
| | | });
|
| | | }
|
| | | if (obstacle.x + obstacle.w < area.x + area.w) {
|
| | | if (obstacle.x + obstacle.width < area.x + area.width) {
|
| | | newRemaining.push({
|
| | | x: obstacle.x + obstacle.w,
|
| | | x: obstacle.x + obstacle.width,
|
| | | y: area.y,
|
| | | w: area.w - (obstacle.x + obstacle.w - area.x),
|
| | | h: area.h
|
| | | width: area.width - (obstacle.x + obstacle.width - area.x),
|
| | | height: area.height
|
| | | });
|
| | | }
|
| | | if (obstacle.y > area.y) {
|
| | | newRemaining.push({
|
| | | x: area.x,
|
| | | y: area.y,
|
| | | w: area.w,
|
| | | h: obstacle.y - area.y
|
| | | width: area.width,
|
| | | height: obstacle.y - area.y
|
| | | });
|
| | | }
|
| | | if (obstacle.y + obstacle.h < area.y + area.h ) {
|
| | | if (obstacle.y + obstacle.height < area.y + area.height ) {
|
| | | newRemaining.push({
|
| | | x: area.x,
|
| | | y: obstacle.y + obstacle.h,
|
| | | w: area.w,
|
| | | h: area.h - (obstacle.y + obstacle.h - area.y)
|
| | | y: obstacle.y + obstacle.height,
|
| | | width: area.width,
|
| | | height: area.height - (obstacle.y + obstacle.height - area.y)
|
| | | });
|
| | |
|
| | | }
|
| | |
| | | //定义每个版图的综合内容
|
| | | const getCurrentRectInfo = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[focusIndex.value?.rectIndex || 0];
|
| | | if (!rect) return '';
|
| | | /* const glassDetail = layout.glassDetails[focusIndex.value?.rectIndex || 0];
|
| | | if (!glassDetail) return '';*/
|
| | | const totalRects = layouts.value.length;
|
| | | const currentRectIndex = layoutIndex + 1;
|
| | | const width = layout.width;
|
| | | const height = layout.height;
|
| | | const percentage = ((rect.w / layout.width) * 100).toFixed(1) + '%';
|
| | | const percentage = (layout.usageRate * 100).toFixed(2) + '%';
|
| | | return `${currentRectIndex}/${totalRects} ${width}×${height} ×1 ${percentage}`;
|
| | | };
|
| | |
|
| | |
| | | //把传输的数据赋值
|
| | | const updateLayout = () => {
|
| | | if (!layoutPanel.value) return;
|
| | | layouts.value = props.layoutData.Layouts;
|
| | | layoutsHead.value = props.layoutData;
|
| | | layouts.value = props.layoutData.layouts;
|
| | | };
|
| | |
|
| | | //向上移动计算坐标
|
| | | const getAvailableSpaceUp = (rect, layout, obstacles) => {
|
| | | let maxSpace = layout.height - (rect.y + rect.h);
|
| | | const getAvailableSpaceUp = (glassDetail, layout, obstacles) => {
|
| | | let maxSpace = layout.height - (glassDetail.y + glassDetail.height);
|
| | | obstacles.forEach(obstacle => {
|
| | | if (obstacle.y > rect.y + rect.h &&
|
| | | obstacle.x <= rect.x + rect.w &&
|
| | | obstacle.x + obstacle.w >= rect.x) {
|
| | | maxSpace = Math.min(maxSpace, obstacle.y - (rect.y + rect.h));
|
| | | if (obstacle.y > glassDetail.y + glassDetail.height &&
|
| | | obstacle.x <= glassDetail.x + glassDetail.width &&
|
| | | obstacle.x + obstacle.width >= glassDetail.x) {
|
| | | maxSpace = Math.min(maxSpace, obstacle.y - (glassDetail.y + glassDetail.height));
|
| | | }
|
| | | });
|
| | | return maxSpace;
|
| | | };
|
| | |
|
| | | //向下移动计算坐标
|
| | | const getAvailableSpaceDown = (rect, layout, obstacles) => {
|
| | | let maxSpace = rect.y;
|
| | | const getAvailableSpaceDown = (glassDetail, layout, obstacles) => {
|
| | | let maxSpace = glassDetail.y;
|
| | | obstacles.forEach(obstacle => {
|
| | | if (obstacle.y + obstacle.h < rect.y &&
|
| | | obstacle.x <= rect.x + rect.w &&
|
| | | obstacle.x + obstacle.w >= rect.x) {
|
| | | maxSpace = Math.min(maxSpace, rect.y - (obstacle.y + obstacle.h));
|
| | | if (obstacle.y + obstacle.height < glassDetail.y &&
|
| | | obstacle.x <= glassDetail.x + glassDetail.width &&
|
| | | obstacle.x + obstacle.width >= glassDetail.x) {
|
| | | maxSpace = Math.min(maxSpace, glassDetail.y - (obstacle.y + obstacle.height));
|
| | | }
|
| | | });
|
| | | return maxSpace;
|
| | | };
|
| | |
|
| | | //向左移动计算坐标
|
| | | const getAvailableSpaceLeft = (rect, layout, obstacles) => {
|
| | | let maxSpace = rect.x;
|
| | | const getAvailableSpaceLeft = (glassDetail, layout, obstacles) => {
|
| | | let maxSpace = glassDetail.x;
|
| | | obstacles.forEach(obstacle => {
|
| | | if (obstacle.x + obstacle.w < rect.x &&
|
| | | obstacle.y <= rect.y + rect.h &&
|
| | | obstacle.y + obstacle.h >= rect.y) {
|
| | | maxSpace = Math.min(maxSpace, rect.x - (obstacle.x + obstacle.w));
|
| | | if (obstacle.x + obstacle.width < glassDetail.x &&
|
| | | obstacle.y <= glassDetail.y + glassDetail.height &&
|
| | | obstacle.y + obstacle.height >= glassDetail.y) {
|
| | | maxSpace = Math.min(maxSpace, glassDetail.x - (obstacle.x + obstacle.width));
|
| | | }
|
| | | });
|
| | | return maxSpace;
|
| | | };
|
| | |
|
| | | //向右移动计算坐标
|
| | | const getAvailableSpaceRight = (rect, layout, obstacles) => {
|
| | | let maxSpace = layout.width - (rect.x + rect.w);
|
| | | const getAvailableSpaceRight = (glassDetail, layout, obstacles) => {
|
| | | let maxSpace = layout.width - (glassDetail.x + glassDetail.width);
|
| | | obstacles.forEach(obstacle => {
|
| | | if (obstacle.x > rect.x + rect.w &&
|
| | | obstacle.y <= rect.y + rect.h &&
|
| | | obstacle.y + obstacle.h >= rect.y) {
|
| | | maxSpace = Math.min(maxSpace, obstacle.x - (rect.x + rect.w));
|
| | | if (obstacle.x > glassDetail.x + glassDetail.width &&
|
| | | obstacle.y <= glassDetail.y + glassDetail.height &&
|
| | | obstacle.y + obstacle.height >= glassDetail.y) {
|
| | | maxSpace = Math.min(maxSpace, obstacle.x - (glassDetail.x + glassDetail.width));
|
| | | }
|
| | | });
|
| | | return maxSpace;
|
| | |
| | |
|
| | | const { layoutIndex, rectIndex } = focusIndex.value;
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[rectIndex];
|
| | | const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
|
| | | const glassDetail = layout.glassDetails[rectIndex];
|
| | | const obstacles = layout.glassDetails.filter(r => r.isRemain || r !== glassDetail);
|
| | |
|
| | | switch (event.key) {
|
| | | case 'ArrowUp':
|
| | |
| | | const mirrorLayoutX = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const width = layout.width;
|
| | | const rects = [...layout.rects]; // 创建副本避免直接修改
|
| | | const glassDetails = [...layout.glassDetails]; // 创建副本避免直接修改
|
| | |
|
| | | rects.forEach(rect => {
|
| | | glassDetails.forEach(glassDetail => {
|
| | | // 计算X镜像后的坐标
|
| | | const newX = width - rect.x - rect.w;
|
| | | const newY = rect.y;
|
| | | const newX = width - glassDetail.x - glassDetail.width;
|
| | | const newY = glassDetail.y;
|
| | |
|
| | | // 更新矩形位置
|
| | | rect.x = newX;
|
| | | rect.y = newY;
|
| | | glassDetail.x = newX;
|
| | | glassDetail.y = newY;
|
| | | });
|
| | |
|
| | | // 更新布局
|
| | | layout.rects = rects;
|
| | | layout.glassDetails = glassDetails;
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | };
|
| | |
|
| | |
| | | const mirrorLayoutY = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const height = layout.height;
|
| | | const rects = [...layout.rects]; // 创建副本避免直接修改
|
| | | const glassDetails = [...layout.glassDetails]; // 创建副本避免直接修改
|
| | |
|
| | | rects.forEach(rect => {
|
| | | glassDetails.forEach(glassDetail => {
|
| | | // 计算Y镜像后的坐标
|
| | | const newX = rect.x;
|
| | | const newY = height - rect.y - rect.h;
|
| | | const newX = glassDetail.x;
|
| | | const newY = height - glassDetail.y - glassDetail.height;
|
| | |
|
| | | // 更新矩形位置
|
| | | rect.y = newY;
|
| | | glassDetail.y = newY;
|
| | | });
|
| | |
|
| | | // 更新布局
|
| | | layout.rects = rects;
|
| | | layout.glassDetails = glassDetails;
|
| | | adjustGrayRectangles(layoutIndex);
|
| | | };
|
| | |
|
| | |
| | | margin-top: 50px;
|
| | | }
|
| | |
|
| | | .layout-rect {
|
| | | .layout-glassDetail {
|
| | | user-select: none;
|
| | | }
|
| | |
|
| | |
| | | font-weight: bold;
|
| | | }
|
| | |
|
| | | .rect-content {
|
| | | .glassDetail-content {
|
| | | display: flex;
|
| | | flex-direction: column;
|
| | | align-items: flex-start;
|
| | |
| | | <script setup> |
| | | import {ref, computed} from "vue"; |
| | | import {ref, computed, watch} from "vue"; |
| | | import {Connection} from "@element-plus/icons-vue"; |
| | | import {useRoute} from "vue-router"; |
| | | import {useRoute, useRouter} from "vue-router"; |
| | | import useOrderInfoStore from "@/stores/sd/order/orderInfo"; |
| | | |
| | | |
| | | const router = useRouter() |
| | | const orderInfo = useOrderInfoStore() |
| | | const props = defineProps({ |
| | | quantity : null, |
| | | area:null |
| | | area:null, |
| | | optimizeData:null |
| | | }); |
| | | //计时器 |
| | | let seconds = ref(0); |
| | |
| | | //优化进度条 |
| | | let progress = ref(0); |
| | | |
| | | let quantity = ref(0); |
| | | let area = ref(0); |
| | | let optimizeData = ref(); |
| | | |
| | | let originalFilm = ref([]); |
| | | let totalUtilizationRate = ref(''); |
| | | let tailPieceRate = ref(''); |
| | | |
| | | const mockData=ref(); |
| | | |
| | | //优化次数;时长;效率 |
| | | let progressValue1 = ref(10); |
| | | let progressValue2 = ref(1000); |
| | | let progressValue3 = ref(50); |
| | | |
| | | |
| | | const formattedTime = computed(() => { |
| | | const minutes = Math.floor(seconds.value / 60); |
| | |
| | | return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; |
| | | }); |
| | | const startTimer = () => { |
| | | console.log(props) |
| | | if (!isRunning.value) { |
| | | intervalId = setInterval(() => { |
| | | seconds.value++; |
| | | progress.value += 10; |
| | | if (progress.value >= 100) { |
| | | progress.value = 100; |
| | | clearInterval(intervalId); |
| | | } |
| | | }, 1000); |
| | | isRunning.value = true; |
| | | if(progress.value>0){ |
| | | seconds.value = 0; |
| | | progress.value = 0; |
| | | originalFilm.value=[] |
| | | totalUtilizationRate.value='' |
| | | tailPieceRate.value='' |
| | | isRunning.value = false; |
| | | } |
| | | |
| | | if(props.optimizeData!=null){ |
| | | document.getElementById("start").disabled=true |
| | | document.getElementById("complete").style.display="none" |
| | | console.log(props.optimizeData) |
| | | if (!isRunning.value) { |
| | | isRunning.value = true; |
| | | intervalId = setInterval(() => { |
| | | seconds.value++; |
| | | progress.value += 1; |
| | | if (progress.value >= 100) { |
| | | progress.value = 100; |
| | | clearInterval(intervalId); |
| | | } |
| | | }, 1000); |
| | | } |
| | | |
| | | |
| | | mockData.value = { |
| | | code: 200, |
| | | data: [{ |
| | | "projectNo":"P25041001", |
| | | "totalQuantity":1, |
| | | "glassTotalQuantity":1, |
| | | "glassTotalArea":1, |
| | | "avgCutRate":1, |
| | | "lastCutRate":1, |
| | | "validCutRate":1, |
| | | "layouts":[ |
| | | { |
| | | "stockId":3, |
| | | "usageRate":0.9, |
| | | "width":4500, |
| | | "height":2440, |
| | | "stockCode":11, |
| | | "upTrim":12, |
| | | "downTrim":12, |
| | | "leftTrim":12, |
| | | "rightTrim":12, |
| | | "quantity":1, |
| | | "glassQuantity":6, |
| | | "glassArea":45, |
| | | "materialType":1, |
| | | "mergeID":1, |
| | | "glassDetails":[ |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":1, |
| | | "markIcon":"", |
| | | "x":0, |
| | | "y":0, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":2, |
| | | "markIcon":"", |
| | | "x":2070, |
| | | "y":0, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":3, |
| | | "markIcon":"", |
| | | "x":0, |
| | | "y":725, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":4, |
| | | "markIcon":"", |
| | | "x":2070, |
| | | "y":725, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":5, |
| | | "markIcon":"", |
| | | "x":0, |
| | | "y":1450, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":false, |
| | | "width":2070, |
| | | "height":725, |
| | | "realWidth":2070, |
| | | "realHeight":725, |
| | | "layer":1, |
| | | "totalLayer":2, |
| | | "orderSort":1, |
| | | "processId":"NG22091408A06", |
| | | "stockSort":1, |
| | | "polySort":6, |
| | | "markIcon":"", |
| | | "x":2070, |
| | | "y":1450, |
| | | "patchState":0, |
| | | "isRotate":0, |
| | | "rackNo":1, |
| | | "glassPoint":{} |
| | | }, |
| | | {"isRemain":true, |
| | | "width":2070, |
| | | "height":265, |
| | | "x":0, |
| | | "y":2175 |
| | | }, |
| | | {"isRemain":true, |
| | | "width":2070, |
| | | "height":265, |
| | | "x":2070, |
| | | "y":2175 |
| | | }, |
| | | {"isRemain":true, |
| | | "width":360, |
| | | "height":2440, |
| | | "x":4140, |
| | | "y":0 |
| | | }] |
| | | } |
| | | ]}] |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | }; |
| | | const pauseTimer = () => { |
| | | if (isRunning.value) { |
| | |
| | | } |
| | | }; |
| | | const resetTimer = () => { |
| | | clearInterval(intervalId); |
| | | router.push({path: '/main/glassOptimize/Optimization'}) |
| | | /*clearInterval(intervalId); |
| | | isRunning.value = false; |
| | | seconds.value = 0; |
| | | progress.value = 0; |
| | | progress.value = 0;*/ |
| | | }; |
| | | |
| | | watch( |
| | | ()=> [progress.value], |
| | | ([newValue])=> { |
| | | if(progress.value===10){ |
| | | orderInfo.optimizeData.optimalResults=mockData.value.data[0] |
| | | mockData.value.data[0].layouts.forEach(items=>{ |
| | | |
| | | // 根据唯一标识(如 id)查找是否已存在 |
| | | const existingItem = originalFilm.value.find(item => item["width"] === items["width"]&&item["height"] === items["height"]); |
| | | if (existingItem) { |
| | | // 存在:数量加1(假设字段为 count) |
| | | existingItem.count += 1; |
| | | } else { |
| | | // 不存在:新增到数组(初始化 count=1) |
| | | const array={ |
| | | width:items["width"], |
| | | height:items["height"], |
| | | upTrim:items["upTrim"], |
| | | downTrim:items["downTrim"], |
| | | leftTrim:items["leftTrim"], |
| | | rightTrim:items["rightTrim"], |
| | | stockCode:items["stockCode"], |
| | | count:1 |
| | | } |
| | | originalFilm.value.push(array); |
| | | } |
| | | |
| | | }) |
| | | orderInfo.optimizeData.originalFilm=originalFilm.value |
| | | totalUtilizationRate.value=mockData.value.data[0].avgCutRate*100 |
| | | tailPieceRate.value=mockData.value.data[0].layouts*100 |
| | | pauseTimer() |
| | | document.getElementById("complete").style.display="block" |
| | | document.getElementById("start").disabled=false |
| | | } |
| | | }); |
| | | |
| | | </script> |
| | | |
| | |
| | | <span style="margin-left: -20px;">需切成品</span><br> |
| | | <div> |
| | | <span>总面积(m2):</span> |
| | | <vxe-input class="input" disabled placeholder=""></vxe-input> |
| | | <span>总数量(片):{{props.quantity}}</span> |
| | | <vxe-input class="input" disabled placeholder=""></vxe-input> |
| | | <vxe-input class="input" v-model="props.area" disabled ></vxe-input> |
| | | <span>总数量(片):</span> |
| | | <vxe-input class="input" v-model="props.quantity" disabled ></vxe-input> |
| | | <span>优化时长(秒):</span> |
| | | <span class="time-display">{{ formattedTime }}</span> |
| | | <el-button type="primary" style="margin-left: 20px" @click="startTimer">开始优化</el-button> |
| | | <el-button class="buttons" type="primary" @click="pauseTimer">暂停</el-button> |
| | | <el-button class="buttons" type="primary" @click="resetTimer">完成</el-button> |
| | | <el-button id="start" type="primary" style="margin-left: 20px" @click="startTimer">开始优化</el-button> |
| | | <!-- <el-button class="buttons" type="primary" @click="pauseTimer">暂停</el-button>--> |
| | | <el-button id="complete" class="buttons" type="primary" style="display: none" @click="resetTimer">完成</el-button> |
| | | </div> |
| | | <br> |
| | | <div style="display: flex;margin-top: -10px"> |
| | | <!-- <div style="display: flex;margin-top: -10px"> |
| | | <span>方案池 优化次数:</span> |
| | | <el-slider v-model="progressValue1" :min="2" :max="20" size="small" style="max-width: 200px;"></el-slider> |
| | | <span>单次优化时长:</span> |
| | |
| | | <span>钢化效率优先:</span> |
| | | <el-slider v-model="progressValue3" :show-tooltip="false" size="small" style="max-width: 200px;"></el-slider> |
| | | <span>切裁率优先</span> |
| | | </div> |
| | | </div>--> |
| | | </div> |
| | | </el-header> |
| | | </div> |
| | |
| | | striped-flow |
| | | duration="45"/> |
| | | </div> |
| | | <div style="height: 100px; margin-top: 20px; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;"> |
| | | <span style="font-weight: bold">耗用原片</span> |
| | | </div> |
| | | <div style="height: 130px; margin-top: 20px; display: flex; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;"> |
| | | <span style="font-weight: bold">当前结果</span> |
| | | <div style="margin-top: 5%"> |
| | | <div style="height: 250px; margin-top: 20px; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;"> |
| | | <span style="font-weight: bold">当前结果</span><br/> |
| | | <div v-for="(item, index) in originalFilm"> |
| | | <div>{{index+1}}:{{item.width}}x{{item.height}}={{item.count}}</div> |
| | | </div> |
| | | <div style="margin-top: 2%"> |
| | | <span>产生时间:{{ formattedTime }}</span> |
| | | <span style="margin-left: 20px">总利用率:0.0%</span> |
| | | <span style="margin-left: 20px">尾片:</span> |
| | | <span style="margin-left: 20px">总利用率:{{totalUtilizationRate}}%</span> |
| | | <span style="margin-left: 20px">尾片:{{tailPieceRate}}%</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | import request from "@/utils/request"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {useRoute} from 'vue-router'; |
| | | import useUserInfoStore from "@/stores/userInfo"; |
| | | import useOrderInfoStore from "@/stores/sd/order/orderInfo"; |
| | | |
| | | |
| | | const {t} = useI18n() |
| | | const { t } = useI18n(); |
| | | const userStore = useUserInfoStore() |
| | | const orderInfo = useOrderInfoStore() |
| | | const username = userStore.user.userName |
| | | |
| | | const xGrid = ref() |
| | | const gridOptions = reactive({ |
| | |
| | | sortable: true |
| | | }, |
| | | { |
| | | field: 'technology_number', |
| | | field: 'layer', |
| | | width: 150, |
| | | title: '层', |
| | | filters: [{data: ''}], |
| | |
| | | |
| | | //优化计算 |
| | | const dialogVisible = ref({}); |
| | | |
| | | const optimizeData = ref({ |
| | | projectNo:null, |
| | | allowRotate:null, |
| | | cutOrigin:null, |
| | | minCutDistance :null, |
| | | optimizeMode:null, |
| | | travType:null, |
| | | rackCycleQty:null, |
| | | glassDetails :[], |
| | | materialDetails:[] |
| | | }); |
| | | |
| | | |
| | | const openDialog = (index) => { |
| | | dialogVisible.value[index] = true; |
| | | if(index===4){ |
| | | if(parseInt(optimizeState.value)===1){ |
| | | ElMessage.warning("该工程已优化") |
| | | return; |
| | | } |
| | | emit('getSmallPieceData', 1); |
| | | xGrid.value.getTableData().fullData.forEach(items=>{ |
| | | 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:0 |
| | | } |
| | | detail.width=items.width |
| | | detail.height=items.height |
| | | detail.processId=items.process_id |
| | | 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 |
| | | |
| | | optimizeData.value.glassDetails .push(detail) |
| | | }) |
| | | |
| | | }else{ |
| | | dialogVisible.value[index] = true; |
| | | } |
| | | }; |
| | | //关闭弹窗 |
| | | const closeDialog = (index) => { |
| | |
| | | |
| | | //右键菜单统一修边 |
| | | const props = defineProps({ |
| | | TrimmingDialogVisible: Boolean |
| | | TrimmingDialogVisible: Boolean, |
| | | CheckboxChangeData: null |
| | | }); |
| | | watch(() => props.TrimmingDialogVisible, (newValue) => { |
| | | /*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; |
| | | } |
| | | if (props.CheckboxChangeData!=null && props.CheckboxChangeData.length>0){ |
| | | props.CheckboxChangeData.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 |
| | | |
| | | optimizeData.value.materialDetails.push(detail) |
| | | }) |
| | | dialogVisible.value[4] = true; |
| | | }else{ |
| | | ElMessage.warning('请选择原片'); |
| | | } |
| | | console.log(optimizeData.value) |
| | | }); |
| | | |
| | | |
| | | const route = useRoute(); |
| | | //工程号 |
| | |
| | | const model = ref(route.params.model); |
| | | const quantitys = ref(route.params.quantity); |
| | | const areas = ref(route.params.area); |
| | | const optimizeState = ref(route.params.optimizeState); |
| | | onBeforeUnmount(() => { |
| | | localStorage.setItem('projectNo', projectNo.value); |
| | | }); |
| | | |
| | | const saveOptimizeData = () => { |
| | | if(orderInfo.optimizeData!==null){ |
| | | 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("数据未优化"); |
| | | } |
| | | |
| | | } |
| | | |
| | | const fetchData = () => { |
| | | request.post(`/glassOptimize/projectInfo/${projectNo.value}`).then((res) => { |
| | | if ((Number(res.code) === 200)) { |
| | | const data = res.data.data; |
| | | const grindingTrimming = res.data.grindingTrimming; |
| | | optimizeState.value=res.data.optimizeState; |
| | | if(grindingTrimming!==null){ |
| | | const formattedData = grindingTrimming.map(item => { |
| | | const formattedItem = {}; |
| | |
| | | console.error("获取数据出错:", error); |
| | | }); |
| | | }; |
| | | |
| | | const firstLoading = async() => { |
| | | request.post(`/glassOptimize/selectOptimizeParms/${username}`).then((res) => { |
| | | if (res.code == "200") { |
| | | const parsedData = JSON.parse(res.data); |
| | | optimizeData.value.projectNo=projectNo.value |
| | | optimizeData.value.allowRotate=parsedData.optimization.smallPieceRotationProhibited |
| | | optimizeData.value.optimizeMode=parsedData.optimization.optimizationMethod |
| | | optimizeData.value.minCutDistance=parsedData.optimization.bendEdgeDistance |
| | | optimizeData.value.cutOrigin=parsedData.optimization.cutterOriginPosition |
| | | optimizeData.value.travType=parsedData.optimization.travType |
| | | optimizeData.value.rackCycleQty=parsedData.optimization.rackCycleQty |
| | | } else { |
| | | ElMessage.warning(res.msg) |
| | | } |
| | | }) |
| | | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (projectNo.value) { |
| | | orderInfo.projectNo=route.params |
| | | fetchData(); |
| | | firstLoading(); |
| | | }else if(orderInfo.projectNo!==null){ |
| | | projectNo.value=orderInfo.projectNo.projectNo |
| | | fetchData(); |
| | | firstLoading(); |
| | | } |
| | | }); |
| | | |
| | |
| | | style="width: 35%;height:80%;margin-top: 3vh;"> |
| | | <set-trimming :closeDialog="closeDialog" @send-data-event="handleTrimmingData"/> |
| | | </el-dialog> |
| | | <el-button id="button" type="primary">保存</el-button> |
| | | <el-button id="button" type="primary" @click="saveOptimizeData()">保存</el-button> |
| | | <el-button id="button" type="primary" @click="openDialog(4)">优化</el-button> |
| | | <el-dialog v-model="dialogVisible[4]" title="优化计算" destroy-on-close |
| | | style="width: 75%;height:90%;margin-top: 3vh;"> |
| | | <optimize-compute :quantity="quantitys" :area="areas" @send-data-event="handleTrimmingData"/> |
| | | <optimize-compute :quantity="quantitys" :area="areas" :optimizeData="optimizeData" |
| | | @send-data-event="handleTrimmingData"/> |
| | | </el-dialog> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
|
| | | <div class="grid-container" :class="`cols-${printColumns}`">
|
| | | <div
|
| | | v-for="(rect, rectIndex) in layout.rects"
|
| | | v-for="(glassDetail, rectIndex) in layout.glassDetails"
|
| | | :key="rectIndex"
|
| | | :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
|
| | | :class="rectClass"
|
| | | :style="rectStyle(rect, layoutIndex)"
|
| | | :style="rectStyle(glassDetail, layoutIndex)"
|
| | | @click="handleRectClick(layoutIndex, rectIndex)"
|
| | | >
|
| | | <div v-if="!rect.isRemain" class="rect-content">
|
| | | <div class="size">{{ rect.w }}×{{ rect.h }}</div>
|
| | | <div class="jia-hao">{{ rect.JiaHao }}</div>
|
| | | <div v-if="!glassDetail.isRemain" class="glassDetail-content">
|
| | | <div class="size">{{ glassDetail.realWidth }}×{{ glassDetail.realHeight }}</div>
|
| | | <div class="jia-hao">{{ glassDetail.rackNo}}</div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
| | | const props = defineProps({
|
| | | layoutData: { type: Object, required: true },
|
| | | gw: { type: Number, default: 1400 },
|
| | | gh: { type: Number, default: 1100 },
|
| | | gh: { type: Number, default: 800 },
|
| | | style: { type: String, default: 'width:100%;height:800px;display:block;background:gray' },
|
| | | printLayout: { type: String, default: '2rows-2cols' }, // 可选值:4rows-2cols, 3rows-2cols, 3rows-1col, 2rows-2cols
|
| | | fixedPageHeight: { type: Number, default: 1100 } // 固定页面高度
|
| | |
| | | const layouts = ref([]);
|
| | | const panelClass = ref('');
|
| | | const panelStyle = ref(props.style);
|
| | | const rectClass = ref('layout-rect');
|
| | | const processId = localStorage.getItem('projectNo');
|
| | | const rectClass = ref('layout-glassDetail');
|
| | | const processId = ref();
|
| | | const printColumns = ref(2); // 初始化为2列
|
| | | const layoutsPerPage = ref(4); // 默认每页显示4个布局(2行×2列)
|
| | |
|
| | |
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${x}px`,
|
| | | top: `${y}px`,
|
| | | top: `${y-25}px`,
|
| | | width: `${containerWidth}px`,
|
| | | height: `${containerHeight}px`,
|
| | | overflow: 'visible',
|
| | |
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${x}px`,
|
| | | top: `${y - 45}px`,
|
| | | top: `${y-25}px`,
|
| | | width: `${scale}px`,
|
| | | textAlign: 'center',
|
| | | zIndex: 1000,
|
| | |
| | | };
|
| | | };
|
| | |
|
| | | const rectStyle = (rect, layoutIndex) => {
|
| | | const rectStyle = (glassDetail, layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const containerWidth = (props.gw - 100) / printColumns.value;
|
| | | const containerHeight = (props.gh - 100) / Math.ceil(layoutsPerPage.value / printColumns.value);
|
| | | |
| | |
|
| | | // 根据当前打印布局获取放大比例
|
| | | const currentScale = layoutScales[props.printLayout] || 1.0;
|
| | | |
| | |
|
| | | const scale = Math.min(
|
| | | containerWidth / layout.width,
|
| | | containerHeight / layout.height
|
| | | ) * currentScale; // 应用当前布局的放大比例
|
| | | |
| | | ) ; // 应用当前布局的放大比例
|
| | |
|
| | | return {
|
| | | position: 'absolute',
|
| | | left: `${rect.x * scale}px`,
|
| | | top: `${rect.y * scale}px`,
|
| | | width: `${rect.w * scale}px`,
|
| | | height: `${rect.h * scale}px`,
|
| | | backgroundColor: rect.isRemain ? '#f0f0f0' : '#a0d8ef',
|
| | | left: `${glassDetail.x * scale}px`,
|
| | | bottom: `${glassDetail.y * scale}px`,
|
| | | width: `${glassDetail.width * scale}px`,
|
| | | height: `${glassDetail.height * scale}px`,
|
| | | backgroundColor: glassDetail.isRemain ? '#f0f0f0' : '#a0d8ef',
|
| | | border: '1px solid #000',
|
| | | cursor: 'pointer'
|
| | | };
|
| | | };
|
| | |
|
| | |
|
| | | const handleRectClick = (layoutIndex, rectIndex) => {
|
| | | focusIndex.value = { layoutIndex, rectIndex };
|
| | |
| | |
|
| | | const getCurrentRectInfo = (layoutIndex) => {
|
| | | const layout = layouts.value[layoutIndex];
|
| | | const rect = layout.rects[focusIndex.value?.rectIndex || 0];
|
| | | if (!rect) return '';
|
| | | const totalRects = layouts.value.length;
|
| | | const currentRectIndex = layoutIndex + 1;
|
| | | const width = layout.width;
|
| | | const height = layout.height;
|
| | | const sum = layout.rects.reduce((sum, r) => sum + (r.w * r.h), 0);
|
| | | const areaUtilization = ((sum / (width * height)) * 100).toFixed(2);
|
| | | return `${currentRectIndex}/${totalRects} ${height}X${width}X1 ${areaUtilization}%`;
|
| | | const sum = layout.glassDetails.reduce((sum, r) => sum + (width * height), 0);
|
| | | const percentage = (layout.usageRate * 100).toFixed(2) + '%';
|
| | | return `${currentRectIndex}/${totalRects} ${width}X${height}X${layout.quantity} ${percentage}`;
|
| | | };
|
| | |
|
| | | const adjustPrintLayout = () => {
|
| | |
| | |
|
| | | const updateLayout = () => {
|
| | | if (!layoutPanel.value) return;
|
| | | layouts.value = props.layoutData.Layouts;
|
| | | //layouts.value = props.layoutData.layouts;
|
| | | processId.value=props.layoutData.projectNo;
|
| | | let originalFilm = ref([])
|
| | | //layouts.value =
|
| | | props.layoutData.layouts.forEach(items=>{
|
| | | const existingItem = originalFilm.value.find(item => item.mergeId === items.mergeId);
|
| | | if (existingItem) {
|
| | | // 存在:数量加1(假设字段为 count)
|
| | | existingItem.quantity += 1;
|
| | | } else {
|
| | | originalFilm.value.push(items);
|
| | | }
|
| | | })
|
| | | layouts.value=originalFilm.value
|
| | | adjustPrintLayout();
|
| | | // 强制重新渲染
|
| | | layoutPanel.value.offsetHeight; // 触发布局更新
|
| | |
| | | overflow: visible;
|
| | | }
|
| | |
|
| | | .rect-content {
|
| | | .glassDetail-content {
|
| | | display: grid;
|
| | | grid-template-columns: 1fr;
|
| | | grid-template-rows: 1fr;
|
| | |
| | | {title: t('basicData.operate'), width: 110, slots: { default: 'button_slot' },fixed:"left",}, |
| | | {type: 'seq', title: t('basicData.number'), width: 80 ,fixed:"left",}, |
| | | {field:'basicName',title: t('orderBasicData.name'),filters: [{data: ''}],slots: {filter: 'num1_filter'},filterMethod: filterChanged}, |
| | | {field:'nickname',title: t('orderBasicData.alias')}, |
| | | {field:'nickname',title: t('orderBasicData.alias'),slots: { default: 'showNickname' }}, |
| | | {field:'createTime',title: t('basicData.creationTime')}, |
| | | |
| | | |
| | |
| | | </el-popconfirm> |
| | | </template> |
| | | |
| | | <template #showNickname="{ row }"> |
| | | <span v-if="row.basicCategory==='icon' && row.nickname!=null">picture</span> |
| | | <span v-else>{{row.nickname}}</span> |
| | | |
| | | </template> |
| | | |
| | | <template #num1_filter="{ column, $panel }"> |
| | | <div> |
| | | <div v-for="(option, index) in column.filters" :key="index"> |
| | |
| | | |
| | | //修改工程状态 |
| | | @ApiOperation("修改工程状态接口") |
| | | @PostMapping("/updateProjectState/{projectNumber}/{state}/{code}") |
| | | @PostMapping("/updateProjectState/{projectNumber}/{state}/{states}/{code}") |
| | | public Result updateProjectState( |
| | | @PathVariable String projectNumber, |
| | | @PathVariable Integer state, |
| | | @PathVariable Integer states, |
| | | @PathVariable Integer code |
| | | ) { |
| | | if (glassOptimizeService.updateProjectState(projectNumber, state,code)) { |
| | | if (glassOptimizeService.updateProjectState(projectNumber, state,states,code)) { |
| | | return Result.seccess(); |
| | | } else { |
| | | throw new ServiceException(Constants.Code_500, "修改失败"); |
| | |
| | | } |
| | | |
| | | @ApiOperation("优化设置保存") |
| | | @PostMapping("/optimizeParms") |
| | | public Result optimizeParmsSave(@RequestBody Map<String, Object> object) { |
| | | @PostMapping("/optimizeParms/{username}") |
| | | public Result optimizeParmsSave(@RequestBody Map<String, Object> object,@PathVariable String username) { |
| | | try { |
| | | return Result.seccess(glassOptimizeService.optimizeParmsSave(object)); |
| | | return Result.seccess(glassOptimizeService.optimizeParmsSave(object,username)); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return Result.error(); |
| | |
| | | |
| | | |
| | | @ApiOperation("保存优化结果接口") |
| | | @PostMapping("/saveOptimizeResult") |
| | | public Result saveOptimizeResult( |
| | | @PostMapping("/saveOptimizeData/{projectId}") |
| | | public Result saveOptimizeResult( @PathVariable String projectId, |
| | | @RequestBody Map<String,Object> object){ |
| | | return Result.seccess(glassOptimizeService.saveOptimizeResult(object)); |
| | | return Result.seccess(glassOptimizeService.saveOptimizeResult(object,projectId)); |
| | | } |
| | | |
| | | |
| | |
| | | private Double thickness; |
| | | private Integer type; |
| | | private Integer state; |
| | | private Integer temperingState; |
| | | private Integer optimizeState; |
| | | private Double quantity; |
| | | private Double area; |
| | | private Integer processCardQuantity; |
| | |
| | | |
| | | //修改工程状态 |
| | | Boolean updateProjectStateMp(String projectNumber,Integer state); |
| | | |
| | | Boolean updateProjectTemperingStateMp(String projectNumber,Integer states); |
| | | |
| | | Boolean updateProjectOptimizeStateMp(String projectNumber,Integer states); |
| | | |
| | | List<Map<String, Object>> getProjectListMp(); |
| | | |
| | | //删除工程 |
| | |
| | | int deleteOptimizeHeatLayout(String projectNumber); |
| | | |
| | | int deleteOptimizeDetail(String projectNumber); |
| | | |
| | | int deleteOptimizeLayout(String projectNumber); |
| | | |
| | | int deleteOptimizeProjectFile(String projectNumber); |
| | | |
| | | int updateOptimizeUse(String projectNumber); |
| | | |
| | | List<OptimizeHeatDetail> selectOptimizeHeatDetail(String projectNumber); |
| | | |
| | |
| | | //模拟计算流程卡详情 |
| | | List<Map<String, Object>> selectComputeDetailMp(String processId,Integer technologyNumber); |
| | | |
| | | |
| | | List<Map<String, Object>> selectComputeDetailMpPatchState(String processId,Integer technologyNumber); |
| | | |
| | | |
| | |
| | | void addratioResult(Map<String, Object> object); |
| | | //模拟计算保存 工程信息 |
| | | void addratioProjectResult(Map<String, Object> object); |
| | | |
| | | void insertOptimizeHeatDetail(String projectId,String processId,Integer technologyNumber,Integer patchState, |
| | | Integer orderNumber,Double width,Double height,Integer index,String username); |
| | | //优化设置保存 |
| | | void optimizeParmsSave(String jsonString); |
| | | void optimizeParmsSave(String jsonString,String username); |
| | | |
| | | void addOptimizeDetail(List<Map<String, Object>> object,String projectId); |
| | | |
| | | void addOptimizeLayout(List<Map<String, Object>> object,String projectId); |
| | | |
| | | void addOptimizeProjectFile(String object,String projectId,String name); |
| | | |
| | | void addOptimizeUse(List<Map<String, Object>> object,String projectId,String name); |
| | | |
| | | //优化结果保存 |
| | | void optimizeResultSave(String jsonString); |
| | |
| | | |
| | | Double getSelectAreaPatchLog(String processId, String technologyNumber); |
| | | |
| | | Integer selectPatchLogState(String processId, Integer technologyNumber,Integer orderNumber,String projectNo); |
| | | |
| | | Boolean addProjectMp(String projectId, String projectNmae, String glassThickness, String glassType, |
| | | Integer sumQuantity, Double sumArea, String userName,Integer processIdCount, String processId, Integer type); |
| | | |
| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.dynamic.datasource.annotation.DS; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.example.erp.common.RabbitMQUtil; |
| | | import com.example.erp.entity.pp.*; |
| | | import com.example.erp.entity.sd.Delivery; |
| | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.sql.Date; |
| | | import java.text.DecimalFormat; |
| | | import java.time.LocalDate; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeoutException; |
| | | import java.util.stream.Collectors; |
| | |
| | | try { |
| | | Map<String, Object> objectMap = (Map<String, Object>) object.get("inputValues"); |
| | | String projectNo = objectMap.get("project_no").toString(); |
| | | String userName = object.get("userName").toString(); |
| | | Map<String, Object> optimizeProjectMap = glassOptimizeMapper.selectProjectCount(projectNo); |
| | | glassOptimizeMapper.addSimulation(object); |
| | | glassOptimizeMapper.addratioResult(object); |
| | | glassOptimizeMapper.addratioProjectResult(object); |
| | | |
| | | if(Integer.valueOf(object.get("state").toString())==3){ |
| | | List<Map<String, Object>> flowCardList = glassOptimizeMapper.selectProjectComputeMp(projectNo); |
| | | int index=0; |
| | | for (Map<String, Object> flowCard:flowCardList){ |
| | | List<Map<String, Object>> glassDetailList=new ArrayList<>(); |
| | | if(Integer.valueOf(flowCard.get("patch_state").toString())==0){ |
| | | glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString())); |
| | | |
| | | }else{ |
| | | glassDetailList = glassOptimizeMapper.selectComputeDetailMpPatchState(flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString())); |
| | | } |
| | | for (Map<String, Object> glassDetail:glassDetailList){ |
| | | for(int i=0;i<Integer.valueOf(glassDetail.get("quantity").toString());i++){ |
| | | index+=1; |
| | | glassOptimizeMapper.insertOptimizeHeatDetail( |
| | | projectNo,flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString()), |
| | | Integer.valueOf(flowCard.get("patch_state").toString()), |
| | | Integer.valueOf(glassDetail.get("order_number").toString()), |
| | | Double.valueOf(glassDetail.get("width").toString()), |
| | | Double.valueOf(glassDetail.get("height").toString()),index,userName |
| | | ); |
| | | |
| | | } |
| | | } |
| | | glassOptimizeMapper.updateProjectTemperingStateMp(projectNo,1); |
| | | } |
| | | }else{ |
| | | List<Map<String, Object>> objectList = (List<Map<String, Object>>) object.get("projectdetail"); |
| | | for (Map<String, Object> objectMap1:objectList){ |
| | | Integer count = glassOptimizeMapper.selectPatchLogState(objectMap1.get("process_id").toString(), |
| | | Integer.valueOf(objectMap1.get("layers_number").toString()),Integer.valueOf(objectMap1.get("order_number").toString()),projectNo); |
| | | if(count>0){ |
| | | objectMap1.put("patchState",1); |
| | | }else { |
| | | objectMap1.put("patchState",0); |
| | | } |
| | | } |
| | | glassOptimizeMapper.addSimulation(object); |
| | | glassOptimizeMapper.addratioResult(object); |
| | | glassOptimizeMapper.addratioProjectResult(object); |
| | | |
| | | |
| | | if(Integer.valueOf(object.get("state").toString())==2){ |
| | | List<Map<String, Object>> flowCardList = glassOptimizeMapper.selectProjectComputeMp(projectNo); |
| | | List<String> rackinfosList = (List<String>) object.get("rackinfos"); |
| | | Iterator<Map<String, Object>> iterator = flowCardList.iterator(); |
| | | while (iterator.hasNext()) { |
| | | Map<String, Object> map = iterator.next(); |
| | | for(String rackinfos:rackinfosList){ |
| | | String processId=rackinfos.substring(0,14); |
| | | String processId1=map.get("processId").toString(); |
| | | Integer technologyNumber= Integer.valueOf(rackinfos.substring(15)); |
| | | Integer technologyNumber1= Integer.valueOf(map.get("technologyNumber").toString()); |
| | | if(map.get("processId").toString().equals(processId) && Integer.valueOf(map.get("technologyNumber").toString())==technologyNumber){ |
| | | iterator.remove(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | int index=0; |
| | | for (Map<String, Object> flowCard:flowCardList){ |
| | | List<Map<String, Object>> glassDetailList=new ArrayList<>(); |
| | | if(flowCard.get("patch_state").toString()=="0"){ |
| | | glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString())); |
| | | |
| | | }else{ |
| | | glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString())); |
| | | } |
| | | for (Map<String, Object> glassDetail:glassDetailList){ |
| | | for(int i=0;i<Integer.valueOf(glassDetail.get("quantity").toString());i++){ |
| | | index+=1; |
| | | glassOptimizeMapper.insertOptimizeHeatDetail( |
| | | projectNo,flowCard.get("processId").toString(), |
| | | Integer.valueOf(flowCard.get("technologyNumber").toString()), |
| | | Integer.valueOf(flowCard.get("patch_state").toString()), |
| | | Integer.valueOf(glassDetail.get("order_number").toString()), |
| | | Double.valueOf(glassDetail.get("width").toString()), |
| | | Double.valueOf(glassDetail.get("height").toString()),index,userName |
| | | ); |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | if(Integer.valueOf(optimizeProjectMap.get("optimize_state").toString())==1){ |
| | | List<OptimizeHeatDetail> optimizeHeatDetail = glassOptimizeMapper.selectOptimizeHeatDetail(projectNo); |
| | | for (OptimizeHeatDetail projectdetail:optimizeHeatDetail){ |
| | | OptimizeDetail optimizeDetail=glassOptimizeMapper.selectOptimizeDetailById(projectNo,projectdetail.getProcessId(), |
| | | projectdetail.getOrderSort(),projectdetail.getLayer()); |
| | | glassOptimizeMapper.updateOptimizeDetail(optimizeDetail.getId(),projectdetail.getLayoutId(),projectdetail.getSort()); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } catch (Exception e) { |
| | |
| | | |
| | | |
| | | //优化设置保存 |
| | | public Boolean optimizeParmsSave(Map<String, Object> object) { |
| | | public Boolean optimizeParmsSave(Map<String, Object> object,String username) { |
| | | try { |
| | | ObjectMapper mapper = new ObjectMapper(); |
| | | String jsonString = mapper.writeValueAsString(object); |
| | | |
| | | glassOptimizeMapper.optimizeParmsSave(jsonString); |
| | | glassOptimizeMapper.optimizeParmsSave(jsonString,username); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | |
| | | |
| | | |
| | | //优化调整结果保存 |
| | | public Boolean saveOptimizeResult(Map<String, Object> object) { |
| | | public Boolean saveOptimizeResult(Map<String, Object> object,String projectId) { |
| | | try { |
| | | Map<String, Object> optimalResults = (Map<String, Object>) object.get("optimalResults"); |
| | | List<Map<String, Object>> originalFilm = (List<Map<String, Object>>) object.get("originalFilm"); |
| | | glassOptimizeMapper.addOptimizeUse(originalFilm,projectId,"admin"); |
| | | |
| | | ObjectMapper mapper = new ObjectMapper(); |
| | | String jsonString = mapper.writeValueAsString(object); |
| | | glassOptimizeMapper.optimizeResultSave(jsonString); |
| | | String json = mapper.writeValueAsString(optimalResults); |
| | | glassOptimizeMapper.addOptimizeProjectFile(json,projectId,"admin"); |
| | | |
| | | List<Map<String, Object>> objectMapList = (List<Map<String, Object>>) optimalResults.get("layouts"); |
| | | glassOptimizeMapper.addOptimizeLayout(objectMapList,projectId); |
| | | for(Map<String, Object> objectMap:objectMapList){ |
| | | List<Map<String, Object>> objectMap2 = (List<Map<String, Object>>) objectMap.get("glassDetails"); |
| | | //迭代玻璃明细集合删除余料 |
| | | Iterator<Map<String, Object>> iterator = objectMap2.iterator(); |
| | | while (iterator.hasNext()) { |
| | | Map<String, Object> map = iterator.next(); |
| | | if (map.get("isRemain").toString()=="true") { |
| | | iterator.remove(); |
| | | } |
| | | } |
| | | |
| | | glassOptimizeMapper.addOptimizeDetail(objectMap2,projectId); |
| | | } |
| | | glassOptimizeMapper.updateProjectOptimizeStateMp(projectId,1); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | |
| | | public Map<String, Object> projectInfoSv(String projectNo) { |
| | | Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNo); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | if(Integer.parseInt(stringObjectMap.get("state").toString())<10){ |
| | | map.put("data", glassOptimizeMapper.firstOptimization(projectNo)); |
| | | map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming()); |
| | | }else if(stringObjectMap.get("state").equals(10)){ |
| | | if(Integer.parseInt(stringObjectMap.get("optimize_state").toString())==1||Integer.parseInt(stringObjectMap.get("tempering_state").toString())==1){ |
| | | map.put("optimizeState", Integer.parseInt(stringObjectMap.get("optimize_state").toString())); |
| | | map.put("data", glassOptimizeMapper.analogComputationOptimization(projectNo)); |
| | | map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming()); |
| | | }else{ |
| | | map.put("data", glassOptimizeMapper.analogComputationOptimization(projectNo)); |
| | | map.put("optimizeState", Integer.parseInt(stringObjectMap.get("optimize_state").toString())); |
| | | map.put("data", glassOptimizeMapper.firstOptimization(projectNo)); |
| | | map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming()); |
| | | } |
| | | return map; |
| | |
| | | public Map<String, Object> materialStoreSv(String thickness, String model, String projectNumber,Integer type) { |
| | | Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | if(Integer.parseInt(stringObjectMap.get("state").toString())<10){ |
| | | if(type==1){ |
| | | map.put("data", glassOptimizeMapper.materialStoreMp(thickness,model)); |
| | | }else if(type==2){ |
| | | map.put("data", glassOptimizeMapper.surplusMaterialsMp(thickness,model)); |
| | | }else{ |
| | | map.put("data", glassOptimizeMapper.materialStoreSurplusMp(thickness,model)); |
| | | } |
| | | map.put("edgeTrimming", glassOptimizeMapper.getEdgeTrimming()); |
| | | }else if(Integer.parseInt(stringObjectMap.get("state").toString())==10){ |
| | | if(Integer.parseInt(stringObjectMap.get("optimize_state").toString())==0){ |
| | | if(type==1){ |
| | | map.put("data", glassOptimizeMapper.materialStoreMp(thickness,model)); |
| | | }else if(type==2){ |
| | |
| | | } |
| | | |
| | | //修改排版状态 |
| | | public Boolean updateProjectState(String projectNumber, Integer state, Integer code) { |
| | | public Boolean updateProjectState(String projectNumber, Integer state,Integer states, Integer code) { |
| | | if (!projectNumber.isEmpty()) { |
| | | //撤销模拟计算 |
| | | if(code==1){ |
| | | glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber); |
| | | glassOptimizeMapper.updateProjectStateMp(projectNumber, state); |
| | | glassOptimizeMapper.updateProjectTemperingStateMp(projectNumber, states); |
| | | } |
| | | //撤销优化排版 |
| | | else if(code==2){ |
| | | glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber); |
| | | glassOptimizeMapper.updateProjectStateMp(projectNumber, state); |
| | | glassOptimizeMapper.deleteOptimizeDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeLayout(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeProjectFile(projectNumber); |
| | | glassOptimizeMapper.updateOptimizeUse(projectNumber); |
| | | glassOptimizeMapper.updateProjectOptimizeStateMp(projectNumber, states); |
| | | } |
| | | //允许生产 |
| | | else if(code==3){ |
| | |
| | | //删除工程 |
| | | public boolean deleteProject(String projectNumber,Integer type) { |
| | | Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber); |
| | | if(stringObjectMap.get("state").equals(10)){ |
| | | if(stringObjectMap.get("tempering_state").equals(1)){ |
| | | glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber); |
| | | }else if(stringObjectMap.get("state").equals(20)){ |
| | | } |
| | | if(stringObjectMap.get("optimize_state").equals(1)){ |
| | | glassOptimizeMapper.deleteOptimizeDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeLayout(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeLayout(projectNumber); |
| | | glassOptimizeMapper.updateOptimizeUse(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber); |
| | | glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber); |
| | | } |
| | |
| | | public Map<String, List<Object>> getOrderBasicData() { |
| | | //获取订单基本数据类型 |
| | | //创建Map对象 |
| | | Map<String, List<Object>> orderBasicDataMap = new HashMap<>(); ; |
| | | Map<String, List<Object>> orderBasicDataMap = new HashMap<>(); |
| | | //创建List对象 |
| | | orderBasicDataMap = getBasicDataByType("order"); |
| | | |
| | |
| | | <result property="thickness" column="thickness"/> |
| | | <result property="type" column="type"/> |
| | | <result property="state" column="state"/> |
| | | <result property="temperingState" column="Tempering state"/> |
| | | <result property="optimizeState" column="Optimize state"/> |
| | | <result property="quantity" column="quantity"/> |
| | | <result property="area" column="area"/> |
| | | <result property="processCardQuantity" column="process Card Quantity"/> |
| | |
| | | c.quantity, |
| | | o.shape, |
| | | concat( c.process_id, '-', c.technology_number ) AS 'process_id', |
| | | c.technology_number, |
| | | c.technology_number as layer, |
| | | c.layers_number as total_layer, |
| | | d.glass_child, |
| | | o.product_name, |
| | | o.price, |
| | |
| | | round( d.area * c.quantity, 4 ) as 'area', |
| | | c.order_number, |
| | | d.icon, |
| | | op.project_name |
| | | op.project_name, |
| | | 0 as patch_state |
| | | FROM |
| | | pp.flow_card c |
| | | LEFT JOIN sd.order_detail o ON c.order_id = o.order_id |
| | |
| | | c.patch_num as quantity, |
| | | o.shape, |
| | | concat( c.process_id, '-', c.technology_number ) AS 'process_id', |
| | | c.technology_number, |
| | | c.technology_number as layer, |
| | | fc.layers_number as total_layer, |
| | | d.glass_child, |
| | | o.product_name, |
| | | o.price, |
| | |
| | | round( d.area * c.patch_num, 4 ) as 'area', |
| | | c.order_sort as order_number, |
| | | d.icon, |
| | | op.project_name |
| | | op.project_name, |
| | | 1 as patch_state |
| | | FROM |
| | | pp.patch_log c |
| | | LEFT JOIN sd.order_detail o ON c.order_id = o.order_id |
| | |
| | | AND c.order_sort = d.order_number |
| | | AND c.technology_number = d.technology_number |
| | | INNER JOIN pp.optimize_project AS op ON op.project_no = c.project_no |
| | | LEFT JOIN pp.flow_card fc ON c.process_id = fc.process_id and fc.technology_number=c.technology_number |
| | | WHERE |
| | | c.project_no IS NOT NULL |
| | | and c.project_no = #{projectNo} |
| | |
| | | </select> |
| | | |
| | | |
| | | <!--第一次优化查询--> |
| | | <!--优化查询--> |
| | | <select id="analogComputationOptimization"> |
| | | SELECT |
| | | h.project_no, |
| | |
| | | count( 1 ) AS quantity, |
| | | o.shape, |
| | | concat( h.process_id, '-', h.layer ) AS 'process_id', |
| | | h.process_id as process_ids, |
| | | h.layer, |
| | | c.layers_number as total_layer, |
| | | d.glass_child, |
| | | o.product_name, |
| | | o.price, |
| | |
| | | round( d.area * count( 1 ), 4 ) AS 'area', |
| | | c.order_number, |
| | | d.icon, |
| | | o.price |
| | | o.price, |
| | | h.patch_state |
| | | from |
| | | pp.`optimize_heat_detail` h |
| | | LEFT JOIN pp.flow_card c ON h.process_id = c.process_id |
| | |
| | | i.id AS id, |
| | | i.producer AS producer, |
| | | i.available_quantity-i.plan_quantity AS available_quantity, |
| | | null as processingQuantity, |
| | | 1 as materialType, |
| | | JSON_EXTRACT(s.json, '$.width') AS width, |
| | | JSON_EXTRACT(s.json, '$.height') AS height, |
| | | JSON_EXTRACT(s.json, '$.thickness') AS thickness, |
| | |
| | | i.id AS id, |
| | | '' AS producer, |
| | | i.quantity AS available_quantity, |
| | | null as processingQuantity, |
| | | 0 as materialType, |
| | | i.width, |
| | | i.height, |
| | | i.thickness, |
| | |
| | | i.id AS id, |
| | | i.producer AS producer, |
| | | i.available_quantity-i.plan_quantity AS available_quantity, |
| | | null as processingQuantity, |
| | | 1 as materialType, |
| | | JSON_EXTRACT(s.json, '$.width') AS width, |
| | | JSON_EXTRACT(s.json, '$.height') AS height, |
| | | JSON_EXTRACT(s.json, '$.thickness') AS thickness, |
| | |
| | | i.id AS id, |
| | | '' AS producer, |
| | | i.quantity AS available_quantity, |
| | | null as processingQuantity, |
| | | 0 as materialType, |
| | | i.width, |
| | | i.height, |
| | | i.thickness, |
| | |
| | | p.`glass_thickness` AS `Thickness`, |
| | | p.`type` AS `Type`, |
| | | p.`state` AS `State`, |
| | | p.`tempering_state` AS `Tempering state`, |
| | | p.`optimize_state` AS `Optimize state`, |
| | | p.`glass_total` AS `Quantity`, |
| | | p.`glass_total_area` AS `Area`, |
| | | p.`process_qty` AS `Process Card Quantity`, |
| | |
| | | `p`.`update_time` AS `Modify time` |
| | | from pp.optimize_project as p |
| | | left join pp.optimize_admin as a on p.creater = a.Id |
| | | where (`p`.`state` > 1) |
| | | where (`p`.`state` > 0) |
| | | and (tempering_state>0 or optimize_state>0) |
| | | and DATE (`p`.`create_time`) BETWEEN #{startSelectTime} AND #{endSelectTime} |
| | | <if test="optimizeProjectMange.projectNumber != null and optimizeProjectMange.projectNumber != ''"> |
| | | and p.project_no regexp #{optimizeProjectMange.projectNumber} |
| | |
| | | <update id="updateProjectStateMp"> |
| | | update pp.optimize_project as p |
| | | set p.state = #{state} |
| | | where p.project_no = #{projectNumber} |
| | | </update> |
| | | |
| | | <!--修改模拟计算工程状态--> |
| | | <update id="updateProjectTemperingStateMp"> |
| | | update pp.optimize_project as p |
| | | set p.tempering_state = #{states} |
| | | where p.project_no = #{projectNumber} |
| | | </update> |
| | | |
| | | <!--修改优化工程状态--> |
| | | <update id="updateProjectOptimizeStateMp"> |
| | | update pp.optimize_project as p |
| | | set p.optimize_state = #{states} |
| | | where p.project_no = #{projectNumber} |
| | | </update> |
| | | |
| | |
| | | delete from pp.optimize_detail |
| | | where project_no = #{projectNumber} |
| | | </delete> |
| | | |
| | | <delete id="deleteOptimizeLayout"> |
| | | delete from pp.optimize_layout |
| | | where project_no = #{projectNumber} |
| | | </delete> |
| | | |
| | | <delete id="deleteOptimizeProjectFile"> |
| | | delete from pp.optimize_project_file |
| | | where project_no = #{projectNumber} |
| | | </delete> |
| | | |
| | | <update id="updateOptimizeUse"> |
| | | update pp.optimize_use set state=0 |
| | | where project_no = #{projectNumber} |
| | | </update> |
| | | |
| | | <select id="selectOptimizeDetailById"> |
| | | select * from pp.optimize_detail |
| | |
| | | p.creater = a.Id |
| | | ))) |
| | | WHERE |
| | | ( p.state = 1 ) |
| | | ( p.state = 1 ) and p.tempering_state=0 and optimize_state=0 |
| | | ORDER BY |
| | | p.create_time DESC, |
| | | p.project_no |
| | |
| | | `g`.`area`, |
| | | `g`.`icon` |
| | | </select> |
| | | |
| | | |
| | | <select id="selectComputeDetailMpPatchState"> |
| | | select `l`.`order_id` AS order_id, |
| | |
| | | group by process_id,technology_number |
| | | </select> |
| | | |
| | | <select id="selectPatchLogState"> |
| | | select |
| | | count(*) |
| | | from pp.patch_log |
| | | where process_id=#{processId} and technology_number=#{technologyNumber} and order_sort=#{orderNumber} and project_no=#{projectNo} |
| | | </select> |
| | | |
| | | <update id="updateProjectMp"> |
| | | update pp.optimize_project set project_name=#{projectNmae},glass_total=#{sumQuantity},glass_total_area= #{sumArea}, |
| | | type=#{type},process_qty=#{processIdCount},process_cards=#{processId} where project_no=#{projectId} |
| | |
| | | ); |
| | | </foreach> |
| | | </insert> |
| | | |
| | | <insert id="insertOptimizeHeatDetail"> |
| | | INSERT INTO pp.optimize_heat_detail ( |
| | | project_no, |
| | | process_id, |
| | | width, |
| | | height, |
| | | x_axis, |
| | | y_axis, |
| | | rotate_angle, |
| | | creater, |
| | | create_time, |
| | | update_time, |
| | | patch_state, |
| | | layer, |
| | | order_sort, |
| | | layout_id, |
| | | sort, |
| | | glass_id, |
| | | pair_width, |
| | | pair_height, |
| | | intRemark, |
| | | strRemark |
| | | ) VALUES ( |
| | | #{projectId}, |
| | | #{processId}, |
| | | #{width}, |
| | | #{height}, |
| | | 0, |
| | | 0, |
| | | 0, |
| | | #{username}, |
| | | NOW(), |
| | | NOW(), |
| | | #{patchState}, |
| | | #{technologyNumber}, |
| | | #{orderNumber}, |
| | | 0, |
| | | #{index}, |
| | | null, |
| | | #{width}, |
| | | #{height}, |
| | | null, |
| | | null |
| | | ); |
| | | </insert> |
| | | |
| | | <!--模拟计算结果保存--> |
| | | <insert id="addratioResult" parameterType="map"> |
| | | <foreach collection="ratioResult" item="glass"> |
| | |
| | | </foreach> |
| | | </insert> |
| | | |
| | | <!--优化小片保存--> |
| | | <insert id="addOptimizeDetail" parameterType="map"> |
| | | <foreach collection="object" item="glass"> |
| | | INSERT INTO pp.optimize_detail ( |
| | | project_no, |
| | | process_id, |
| | | layer, |
| | | total_layer, |
| | | order_sort, |
| | | stock_id, |
| | | polys_id, |
| | | o_width, |
| | | o_height, |
| | | width, |
| | | height, |
| | | x_axis, |
| | | y_axis, |
| | | patch_state, |
| | | mark_icon |
| | | ) VALUES ( |
| | | #{projectId}, |
| | | #{glass.processId}, |
| | | #{glass.layer}, |
| | | #{glass.totalLayer}, |
| | | #{glass.orderSort}, |
| | | #{glass.stockSort}, |
| | | #{glass.polySort}, |
| | | #{glass.realwidth}, |
| | | #{glass.realheight}, |
| | | #{glass.width}, |
| | | #{glass.height}, |
| | | #{glass.x}, |
| | | #{glass.y}, |
| | | #{glass.patchState}, |
| | | #{glass.markIcon} |
| | | ); |
| | | </foreach> |
| | | </insert> |
| | | |
| | | <!--优化结果json格式保存--> |
| | | <insert id="addOptimizeProjectFile" > |
| | | INSERT INTO pp.optimize_project_file ( |
| | | project_no, |
| | | type, |
| | | content, |
| | | create_time, |
| | | creater |
| | | ) VALUES ( |
| | | #{projectId}, |
| | | "优化结果", |
| | | #{object}, |
| | | now(), |
| | | #{name} |
| | | ); |
| | | </insert> |
| | | |
| | | <!--优化原片保存--> |
| | | <insert id="addOptimizeLayout" parameterType="map"> |
| | | <foreach collection="object " item="glass"> |
| | | INSERT INTO pp.optimize_layout ( |
| | | project_no, |
| | | stock_id, |
| | | width, |
| | | height, |
| | | usage_rate, |
| | | stock_code, |
| | | up_trim, |
| | | down_trim, |
| | | left_trim, |
| | | right_trim, |
| | | glass_count, |
| | | glass_area, |
| | | create_time |
| | | ) VALUES ( |
| | | #{projectId}, |
| | | #{glass.stockId}, |
| | | #{glass.width}, |
| | | #{glass.height}, |
| | | #{glass.usageRate}, |
| | | #{glass.stockCode}, |
| | | #{glass.upTrim}, |
| | | #{glass.downTrim}, |
| | | #{glass.leftTrim}, |
| | | #{glass.rightTrim}, |
| | | #{glass.glassCount}, |
| | | #{glass.glassArea}, |
| | | now() |
| | | ); |
| | | </foreach> |
| | | </insert> |
| | | |
| | | <!--优化原片保存--> |
| | | <insert id="addOptimizeUse" parameterType="map"> |
| | | <foreach collection="object " item="glass"> |
| | | INSERT INTO pp.optimize_use ( |
| | | project_no, |
| | | raw_stock_code, |
| | | type, |
| | | width, |
| | | height, |
| | | use_count, |
| | | not_use_count, |
| | | state, |
| | | left_trim, |
| | | down_trim, |
| | | right_trim, |
| | | up_trim, |
| | | creater, |
| | | create_time |
| | | ) VALUES ( |
| | | #{projectId}, |
| | | #{glass.stockCode}, |
| | | 1, |
| | | #{glass.width}, |
| | | #{glass.height}, |
| | | #{glass.count}, |
| | | #{glass.count}, |
| | | 1, |
| | | #{glass.leftTrim}, |
| | | #{glass.downTrim}, |
| | | #{glass.rightTrim}, |
| | | #{glass.upTrim}, |
| | | #{name}, |
| | | now() |
| | | ); |
| | | </foreach> |
| | | </insert> |
| | | |
| | | |
| | | <!--模拟计算工程更新--> |
| | | <update id="addratioProjectResult" parameterType="map"> |
| | | UPDATE pp.optimize_project |
| | | SET |
| | | state = 10, |
| | | tempering_state = 1, |
| | | furnaces_qty=#{resultSum[0]}, |
| | | load_rate=#{resultSum[1]}, |
| | | chaos_pct = #{inputValues.chaos_pct}, |
| | |
| | | project_no = #{inputValues.project_no} |
| | | |
| | | </update> |
| | | |
| | | <!--优化设置保存--> |
| | | <update id="optimizeParmsSave"> |
| | | update erp_user_info.user as u |
| | | set u.optimize_parms = #{jsonString} |
| | | set u.optimize_parms = #{jsonString} where user_name=#{username} |
| | | </update> |
| | | |
| | | <update id="updateOptimizeResult"> |
| | |
| | | <mapper namespace="com.example.erp.mapper.sd.BasicDateMapper"> |
| | | <select id="getOrderBasicData"> |
| | | select |
| | | * |
| | | id,basic_type,if(basic_category='icon',null,nickname) as 'nickname',basic_name,basic_category,create_time,update_time |
| | | from |
| | | basic_data as a |
| | | where a.basic_type=#{type} |