north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
@@ -1,6 +1,7 @@ <template> <div> <button @click="handlePrint" style="position: fixed; bottom: 20px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">打印版图</button> <el-button id="button" type="primary" @click="handlePrint">打印版图</el-button> <RectRenderer ref="rectRenderer" :layoutData="layoutData" @@ -12,13 +13,47 @@ </template> <script setup> import { ref } from 'vue'; import { ref,onMounted } from 'vue'; import RectRenderer from './page/RectRenderer.vue'; import mockLayoutData from '../../../components/pp/MockData'; const layoutData = ref(mockLayoutData); import request from "@/utils/request"; import { useI18n } from "vue-i18n"; //const layoutData = ref(mockLayoutData); const rectRenderer = ref(null); const savedProjectNo = localStorage.getItem('projectNo'); const processId = savedProjectNo; const layoutData = ref(null); const selectLayout = () => { request.post(`/glassOptimize/selectOptimizeResult/${processId}`) .then((res) => { if (res.code == 200) { try { const parsedData = JSON.parse(res.data.data[0].Layouts); layoutData.value = parsedData; } catch (error) { } } else { } }) .catch((error) => { console.error("请求失败:", error); ElMessage.error(t('basicData.msg.requestFailed')); }); } onMounted(() => { selectLayout(); }); const handlePrint = () => { // 创建一个隐藏的iframe const iframe = document.createElement('iframe'); north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
@@ -15,7 +15,7 @@ </template> <script setup> import { ref } from 'vue'; import { ref,onMounted } from 'vue'; import RectRenderer from './page/RectRenderer.vue'; import mockLayoutData from '../../../components/pp/MockData'; import request from "@/utils/request"; @@ -23,7 +23,52 @@ import { ElMessage } from "element-plus"; const { t } = useI18n(); const layoutData = ref(mockLayoutData); // const layoutData = ref(mockLayoutData); const savedProjectNo = localStorage.getItem('projectNo'); const processId = savedProjectNo; const layoutData = ref(null); const selectLayout = () => { request.post(`/glassOptimize/selectOptimizeResult/${processId}`) .then((res) => { if (res.code == 200) { try { const parsedData = JSON.parse(res.data.data[0].Layouts); layoutData.value = parsedData; } catch (error) { } } else { } }) .catch((error) => { console.error("请求失败:", error); ElMessage.error(t('basicData.msg.requestFailed')); }); } onMounted(() => { selectLayout(); }); const submitLayouts = async () => { try { north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -53,7 +53,8 @@ > <div class="rect-content"> <div class="size">{{ rect.w }}×{{ rect.h }}</div> <div class="jia-hao">{{ rect.JiaHao }}</div> <div v-if="showJiaHao" class="jia-hao">{{ rect.JiaHao }}</div> <div v-if="showProcessId" class="liuchengka">{{ rect.liuchengka }}</div> </div> </div> </div> @@ -72,7 +73,13 @@ import request from "@/utils/request"; import { useI18n } from "vue-i18n"; import { ElMessage, ElMessageBox } from "element-plus"; import useUserInfoStore from "@/stores/userInfo"; const { t } = useI18n(); const userStore = useUserInfoStore() const username = userStore.user.userName const props = defineProps({ layoutData: { type: Object, required: true }, gw: { type: Number, default: 1000 }, @@ -93,7 +100,9 @@ const dragging = ref(false); const dragStartPos = ref({ x: 0, y: 0 }); const dragRect = ref(null); const showJiaHao = ref(false); // 新增:控制jia-hao的显示状态 const showProcessId= ref(false); const themeColor=ref(null) // 提交布局数据到后端 const submitLayouts = async () => { layouts.value.forEach(layout => { @@ -119,6 +128,44 @@ } }); }; //获取优化设置 const fetchSettings = async (username) => { try { const response = await request.post(`/glassOptimize/selectOptimizeParms/${username}`); if (response.code == 200) { if (!response.data) { console.error('响应数据为空'); return; } const parsedData = JSON.parse(response.data); console.log(parsedData.display.frameNumber) if (parsedData.display && parsedData.display.frameNumber) { showJiaHao.value = parsedData.display.frameNumber; } if (parsedData.display && parsedData.display.orderNumber) { showProcessId.value = parsedData.display.orderNumber; } if (parsedData.display ) { themeColor.value = parsedData.display.themeColor; } console.log( parsedData); } else { console.error('请求失败,状态码:', response.code); } } catch (error) { console.error('请求发生错误:', error); } }; const showAddDialog = (layoutIndex, rectIndex) => { ElMessageBox.prompt('请输入成品的宽度和高度', '添加成品', { @@ -146,8 +193,8 @@ y: 0, w: values[0], h: values[1], isRemain: false, JiaHao: `新成品` isRemain: false }; addNewRect(layoutIndex, newRect); }) @@ -210,7 +257,7 @@ top: `${rect.y * scale}px`, width: `${rect.w * scale}px`, height: `${rect.h * scale}px`, backgroundColor: rect.isRemain ? '#f0f0f0' : '#a0d8ef', backgroundColor: rect.isRemain ? '#f0f0f0' : themeColor.value, border: '1px solid #000', cursor: 'pointer', draggable: !rect.isRemain, @@ -354,38 +401,6 @@ contextMenu.style.padding = '5px'; contextMenu.style.zIndex = 1001; const mergeLeftItem = document.createElement('div'); mergeLeftItem.textContent = '向左合并'; mergeLeftItem.style.cursor = 'pointer'; mergeLeftItem.addEventListener('click', () => { mergeGrayRects(layoutIndex, rectIndex, 'left'); document.body.removeChild(contextMenu); }); const mergeRightItem = document.createElement('div'); mergeRightItem.textContent = '向右合并'; mergeRightItem.style.cursor = 'pointer'; mergeRightItem.addEventListener('click', () => { mergeGrayRects(layoutIndex, rectIndex, 'right'); document.body.removeChild(contextMenu); }); const mergeUpItem = document.createElement('div'); mergeUpItem.textContent = '向上合并'; mergeUpItem.style.cursor = 'pointer'; mergeUpItem.addEventListener('click', () => { mergeGrayRects(layoutIndex, rectIndex, 'up'); document.body.removeChild(contextMenu); }); const mergeDownItem = document.createElement('div'); mergeDownItem.textContent = '向下合并'; mergeDownItem.style.cursor = 'pointer'; mergeDownItem.addEventListener('click', () => { mergeGrayRects(layoutIndex, rectIndex, 'down'); document.body.removeChild(contextMenu); }); const addItem = document.createElement('div'); addItem.textContent = '添加成品'; addItem.style.cursor = 'pointer'; @@ -394,10 +409,6 @@ document.body.removeChild(contextMenu); }); contextMenu.appendChild(mergeLeftItem); contextMenu.appendChild(mergeRightItem); contextMenu.appendChild(mergeUpItem); contextMenu.appendChild(mergeDownItem); contextMenu.appendChild(addItem); document.body.appendChild(contextMenu); @@ -480,7 +491,7 @@ rect.y = Math.round(rect.y); // 只调整位置对齐,不调整大小 //adjustAlignmentPosition(layoutIndex, rectIndex); adjustAlignmentPosition(layoutIndex, rectIndex); // 调整灰色矩形 adjustGrayRectangles(layoutIndex); @@ -513,49 +524,6 @@ }); }; const mergeGrayRects = (layoutIndex, rectIndex, direction) => { const layout = layouts.value[layoutIndex]; const rect = layout.rects[rectIndex]; const grayRects = layout.rects.filter(r => r.isRemain); let targetRect = null; switch (direction) { case 'left': targetRect = grayRects.find(r => r.x + r.w === rect.x && r.y === rect.y && r.h === rect.h); break; case 'right': targetRect = grayRects.find(r => r.x === rect.x + rect.w && r.y === rect.y && r.h === rect.h); break; case 'up': targetRect = grayRects.find(r => r.y + r.h === rect.y && r.x === rect.x && r.w === rect.w); break; case 'down': targetRect = grayRects.find(r => r.y === rect.y + rect.h && r.x === rect.x && r.w === rect.w); break; } if (targetRect) { const mergedRect = { x: Math.min(rect.x, targetRect.x), y: Math.min(rect.y, targetRect.y), w: Math.max(rect.x + rect.w, targetRect.x + targetRect.w) - Math.min(rect.x, targetRect.x), h: Math.max(rect.y + rect.h, targetRect.y + targetRect.h) - Math.min(rect.y, targetRect.y), isRemain: true }; const index = layout.rects.indexOf(rect); layout.rects.splice(index, 1); const targetIndex = layout.rects.indexOf(targetRect); layout.rects.splice(targetIndex, 1); layout.rects.push(mergedRect); adjustGrayRectangles(layoutIndex); } else { ElMessage.warning('无法合并,没有相邻的灰色矩形'); } }; const mergeAdjacentGrayRects = (rects) => { const grayRects = rects.filter(r => r.isRemain); let merged = []; @@ -585,7 +553,7 @@ current.x === last.x && current.w === last.w) { last.h += current.h; last.x = Math.round(last); last.x = Math.round(last.x); last.y = Math.round(last.y); last.w = Math.round(last.w); last.h = Math.round(last.h); @@ -745,7 +713,7 @@ rect.x -= actualStep; break; case 'right': rect.x += actualStep; rect.x +=actualStep; break; } @@ -861,14 +829,33 @@ layouts.value = props.layoutData.Layouts; }; let clickEventListener = null; onMounted(() => { setTimeout(updateLayout, 1000); fetchSettings(username); setTimeout(updateLayout, 500); selectedLayoutIndex.value = 0; // 添加全局点击事件监听器 clickEventListener = (event) => { // 检查是否存在右键菜单 const contextMenus = document.querySelectorAll('.context-menu'); if (contextMenus.length > 0) { // 移除所有右键菜单 contextMenus.forEach(menu => menu.remove()); } }; document.addEventListener('click', clickEventListener); }); onUnmounted(() => { rectsElements.value = {}; // 移除全局点击事件监听器 if (clickEventListener) { document.removeEventListener('click', clickEventListener); } }); </script> @@ -876,6 +863,10 @@ .layout-wrapper { position: relative; margin-top: 50px; } .layout-rect { user-select: none; } .layout-container { @@ -907,7 +898,7 @@ font-size: 12px; } .jia-hao { .jia-hao .liuchengka { grid-row: 2; grid-column: 1; margin: auto; north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
@@ -117,7 +117,7 @@ }; onMounted(() => { updateLayout(); setTimeout(updateLayout, 500); }); onUnmounted(() => { north-glass-erp/src/main/java/com/example/erp/entity/pp/LayoutsData.java
@@ -29,6 +29,12 @@ public int getWidth() { return width; } public int getSameCount() { return sameCount; } public String getWuliao() { return material; } public int getHeight() { return height; @@ -43,7 +49,7 @@ @JsonProperty("isRemain") private boolean isRemain; @JsonProperty("h") private int height; private int h; @JsonProperty("DM2") private int dm2; @JsonProperty("xuhao") @@ -59,7 +65,7 @@ @JsonProperty("LM1") private int lm1; @JsonProperty("w") private int width; private int W; @JsonProperty("x") private int x; @JsonProperty("y") @@ -68,15 +74,40 @@ private int rowNumber; public int getWidth() { return width; return W; } public int getHeight() { return height; return h; } public String getProcessCard() { return processCard; } public int getW() { return W; } public int getX() { return x; } public int getY() { return y; } public String getJiaHao() { return jiaHao; } public int getH() { return h; } public boolean isRemain() { return isRemain; } } } north-glass-erp/src/main/java/com/example/erp/service/pp/JsonToOptConverter.java
@@ -4,8 +4,13 @@ import com.example.erp.entity.pp.LayoutsData.*; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; /** * @author SNG-012 */ public class JsonToOptConverter { public static String convertToJson(LayoutsData layoutsData) throws IOException { @@ -18,15 +23,20 @@ addHeader(optContent); addSignatures(optContent); addPatterns(optContent, layoutsData); addCuttings(optContent, layoutsData); addShapes(optContent, layoutsData); addInfos(optContent, layoutsData); return optContent.toString(); } private static void addHeader(StringBuilder optContent) { optContent.append("[OPT_Header]\n"); optContent.append("OPTCutVersion=4.0\n"); optContent.append("OPTCutVersion=5.0\n"); optContent.append("Dimension=mm\n"); optContent.append("Date=2025/2/25\n\n"); Date currentDate = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"); String formattedDate = sdf.format(currentDate); optContent.append("Date=" + formattedDate + "\n\n"); } private static void addSignatures(StringBuilder optContent) { @@ -36,70 +46,92 @@ private static void addPatterns(StringBuilder optContent, LayoutsData layoutsData) { optContent.append("[OPT_Pattern]\n"); optContent.append("GlassID=FL4\n"); optContent.append("GlassThickness=4.00\n"); optContent.append("GlassCoated=0\n"); optContent.append("GlassType=0\n"); optContent.append("Pieces=" + layoutsData.getLayouts().size() + "\n"); optContent.append("Width=" + layoutsData.getLayouts().get(0).getWidth() + ".0\n"); optContent.append("Height=" + layoutsData.getLayouts().get(0).getHeight() + ".0\n"); optContent.append("TrimLeft=0.0\n"); optContent.append("TrimBottom=0.0\n"); optContent.append("LoaderRack=\n\n"); } private static void addCuttings(StringBuilder optContent, LayoutsData layoutsData) { optContent.append("[Cuttings]\n"); for (Layout layout : layoutsData.getLayouts()) { optContent.append("GlassID=32\n"); optContent.append("GlassDescription=32\n"); optContent.append("GlassType=0\n"); optContent.append("GlassThickness=5\n"); optContent.append("Pieces=100\n"); optContent.append("Width=").append(layout.getWidth()).append("\n"); optContent.append("Height=").append(layout.getHeight()).append("\n"); optContent.append("TrimLeft=15\n"); optContent.append("TrimBottom=0\n"); optContent.append("TrimRight=0\n"); optContent.append("TrimTop=0\n"); optContent.append("MinCutDistance=10\n"); optContent.append("Priority=0\n"); optContent.append("TravType=XY\n\n"); for (Rect rect : layout.getRects()) { if (!rect.isRemain()) { optContent.append("x=" + rect.getX() + ".00 y=" + rect.getY() + ".00 "); optContent.append("X=" + (rect.getX() + rect.getW()) + ".00 Y=" + rect.getY() + ".00 "); optContent.append("x=" + (rect.getX() + rect.getW()) + ".00 y=" + (rect.getY() + rect.getH()) + ".00 "); optContent.append("X=" + rect.getX() + ".00 Y=" + (rect.getY() + rect.getH()) + ".00 "); optContent.append("x=" + rect.getX() + ".00 y=" + rect.getY() + ".00\n"); } } } optContent.append("\n"); } private static void addShapes(StringBuilder optContent, LayoutsData layoutsData) { int shapeId = 1; for (Layout layout : layoutsData.getLayouts()) { for (Rect rect : layout.getRects()) { if (!rect.isRemain()) { optContent.append("[Shape]\n"); optContent.append("Id=" + shapeId + "\n"); optContent.append("Description=" + rect.getJiaHao() + " ShapeName=" + rect.getJiaHao() + "\n"); optContent.append("x=" + rect.getW() + ".0 y=" + rect.getH() + ".0\n"); optContent.append("X=0.0 Y=0.0 C=1\n"); shapeId++; } } } optContent.append("\n"); } private static void addInfos(StringBuilder optContent, LayoutsData layoutsData) { int id = 1; int infoId = 1; for (Layout layout : layoutsData.getLayouts()) { for (Rect rect : layout.getRects()) { optContent.append("[Info]\n"); optContent.append("Id=").append(id++).append("\n"); optContent.append("SecondGlassReference=\n"); optContent.append("RackNo=0\n"); optContent.append("SheetWidth=").append(rect.getWidth()).append("\n"); optContent.append("SheetHeight=").append(rect.getHeight()).append("\n"); optContent.append("Customer=\n"); optContent.append("PosNo=\n"); optContent.append("OrderNo=").append(rect.getProcessCard()).append("-1-").append(id - 1).append("\n"); optContent.append("RackCode=0\n"); optContent.append("PieceStandardPz=\n"); optContent.append("UMPz=\n"); optContent.append("IDPz=\n"); optContent.append("RealDimXPz=").append(rect.getWidth()).append(".00\n"); optContent.append("RealDimYPz=").append(rect.getHeight()).append(".00\n"); optContent.append("GrindingPz=\n"); optContent.append("GrindingPzX1=0\n"); optContent.append("GrindingPzY1=0\n"); optContent.append("GrindingPzX2=0\n"); optContent.append("GrindingPzY2=0\n"); optContent.append("BendingPz=\n"); optContent.append("QuantityPz=77\n"); optContent.append("LabelsPz=\n"); optContent.append("LabelsPzCounter=\n"); optContent.append("RotationAllowed=1\n"); optContent.append("PreferencePz=\n"); optContent.append("DescMatCompPz=\n"); optContent.append("DeliveryDatePz=\n"); optContent.append("PzNOTE=3C.orzx\n"); optContent.append("PzNOTE1=\n"); optContent.append("PzNOTE2=").append(rect.getWidth()).append("\n"); optContent.append("PzNOTE3=").append(rect.getHeight()).append("\n"); optContent.append("PzNOTE4=右下-30-30\n"); optContent.append("PzNOTE5=false-true-false\n"); optContent.append("PzNOTE6=true-true\n"); optContent.append("PzNOTE7=").append(rect.getProcessCard()).append("-1-").append(id - 1).append("\n"); for (int i = 8; i <= 20; i++) { optContent.append("PzNOTE").append(i).append("=\n"); if (!rect.isRemain()) { optContent.append("[Info]\n"); optContent.append("Id=" + infoId + "\n"); optContent.append("SecondGlassReference=FL4\n"); optContent.append("RackNo=0\n"); optContent.append("SheetWidth=" + rect.getW() + ".0\n"); optContent.append("SheetHeight=" + rect.getH() + ".0\n"); optContent.append("Customer=\n"); optContent.append("PosNo=" + infoId + "\n"); optContent.append("OrderNo=\n"); optContent.append("RackCode=\n"); optContent.append("PieceStandardPz=0\n"); optContent.append("UMPz=mm\n"); optContent.append("IDPz=\n"); optContent.append("RealDimXPz=" + rect.getW() + ".0\n"); optContent.append("RealDimYPz=" + rect.getH() + ".0\n"); optContent.append("GrindingPz=0.0\n"); optContent.append("GrindingPzX1=0.0\n"); optContent.append("GrindingPzY1=0.0\n"); optContent.append("GrindingPzX2=0.0\n"); optContent.append("GrindingPzY2=0.0\n"); optContent.append("BendingPz=0.0\n"); optContent.append("QuantityPz=1\n"); optContent.append("PriorityPz=0\n"); optContent.append("LabelsPz=0\n"); optContent.append("LabelsPzCounter=0\n"); optContent.append("RotationAllowed=1\n"); optContent.append("PreferencePz=0\n"); optContent.append("DescMatCompPz=\n"); optContent.append("DeliveryDatePz=" + new SimpleDateFormat("dd-MM-yyyy").format(new Date()) + "\n"); optContent.append("PzNOTE=\n"); for (int i = 1; i <= 20; i++) { optContent.append("PzNOTE" + i + "=\n"); } infoId++; } optContent.append("\n"); } } } }