From 54398271dd26caf3b66b9ef2deff3af0277243d8 Mon Sep 17 00:00:00 2001
From: wuyouming666 <2265557248@qq.com>
Date: 星期三, 26 三月 2025 13:54:59 +0800
Subject: [PATCH] 键盘上下移动成品,余料自适应

---
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue |  306 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 211 insertions(+), 95 deletions(-)

diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
index ea5170a..dd5260b 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -50,6 +50,7 @@
             @mousemove="handleRectDragging"
             @mouseup="handleRectDragEnd"
             @mouseleave="handleRectDragEnd"
+            @click="handleRectClick(layoutIndex, rectIndex)"
           >
             <div class="rect-content">
               <div class="size">{{ rect.w }}脳{{ rect.h }}</div>
@@ -78,8 +79,7 @@
 const { t } = useI18n();
 const userStore = useUserInfoStore()
 const username = userStore.user.userName
-
-
+let clickEventListener = null;
 const props = defineProps({
   layoutData: { type: Object, required: true },
   gw: { type: Number, default: 1000 },
@@ -100,10 +100,10 @@
 const dragging = ref(false);
 const dragStartPos = ref({ x: 0, y: 0 });
 const dragRect = ref(null);
-const showJiaHao = ref(false); // 鏂板锛氭帶鍒秊ia-hao鐨勬樉绀虹姸鎬�
-const showProcessId= ref(false);
-const themeColor=ref(null)
-// 鎻愪氦甯冨眬鏁版嵁鍒板悗绔�
+const showJiaHao = ref(false);
+const showProcessId = ref(false);
+const themeColor = ref(null);
+
 const submitLayouts = async () => {
   layouts.value.forEach(layout => {
     layout.rects.forEach(rect => {
@@ -129,8 +129,6 @@
   });
 };
 
-
-//鑾峰彇浼樺寲璁剧疆
 const fetchSettings = async (username) => {
   try {
     const response = await request.post(`/glassOptimize/selectOptimizeParms/${username}`);
@@ -140,23 +138,15 @@
         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 ) {
+      if (parsedData.display) {
         themeColor.value = parsedData.display.themeColor;
-      
       }
-      
-      
-      
-      console.log( parsedData);
     } else {
       console.error('璇锋眰澶辫触锛岀姸鎬佺爜:', response.code);
     }
@@ -164,8 +154,6 @@
     console.error('璇锋眰鍙戠敓閿欒:', error);
   }
 };
-
-
 
 const showAddDialog = (layoutIndex, rectIndex) => {
   ElMessageBox.prompt('璇疯緭鍏ユ垚鍝佺殑瀹藉害鍜岄珮搴�', '娣诲姞鎴愬搧', {
@@ -186,32 +174,61 @@
     },
     inputErrorMessage: '杈撳叆鏍煎紡涓嶆纭�'
   })
-  .then(({ value }) => {
-    const values = value.split(',').map(v => parseFloat(v.trim()));
-    const newRect = {
-      x: 0,
-      y: 0,
-      w: values[0],
-      h: values[1],
-      isRemain: false
-     
-    };
-    addNewRect(layoutIndex, newRect);
-  })
-  .catch(() => {
-    // 鐢ㄦ埛鍙栨秷
-  });
+    .then(({ value }) => {
+      const values = value.split(',').map(v => parseFloat(v.trim()));
+      const newRect = {
+        x: 0,
+        y: 0,
+        w: values[0],
+        h: values[1],
+        isRemain: false
+      };
+      addNewRect(layoutIndex, newRect);
+    })
+    .catch(() => {
+      // 鐢ㄦ埛鍙栨秷
+    });
 };
 
 const addNewRect = (layoutIndex, newRect) => {
   const layout = layouts.value[layoutIndex];
-  layout.rects.push(newRect);
-  adjustGrayRectangles(layoutIndex);
+  const bestFitPosition = findBestFitPosition(layoutIndex, newRect);
+  if (bestFitPosition) {
+    newRect.x = bestFitPosition.x;
+    newRect.y = bestFitPosition.y;
+    layout.rects.push(newRect);
+    adjustGrayRectangles(layoutIndex);
+  } else {
+    ElMessage.warning('鏃犳硶鏀剧疆锛屾病鏈夎冻澶熺殑绌洪棿');
+  }
+};
+
+const findBestFitPosition = (layoutIndex, newRect) => {
+  const layout = layouts.value[layoutIndex];
+  const obstacles = layout.rects.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 (areaDifference < minAreaDifference) {
+        minAreaDifference = areaDifference;
+        bestFit = {
+          x: area.x,
+          y: area.y,
+          w: newRect.w,
+          h: newRect.h
+        };
+      }
+    }
+  });
+
+  return bestFit;
 };
 
 const layoutContainerStyle = (layoutIndex) => {
-  const containerWidth = (props.gw - 210) / 2;
-  const containerHeight = (props.gh - 100) / 3;
   const layout = layouts.value[layoutIndex];
   const scale = Math.min(
     (props.gw - 100) / layout.width,
@@ -442,22 +459,19 @@
   const deltaX = event.clientX - dragStartPos.value.x;
   const deltaY = event.clientY - dragStartPos.value.y;
 
-  // 鍙皟鏁翠綅缃紝涓嶈皟鏁村ぇ灏�
   const newRect = { ...rect };
   newRect.x += deltaX / scale;
   newRect.y += deltaY / scale;
 
-  // 妫�鏌ユ槸鍚︿笌鍏朵粬钃濊壊鐭╁舰閲嶅彔
   const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
   let isValidMove = true;
-  
+
   otherRects.forEach(otherRect => {
     if (checkOverlap(newRect, otherRect)) {
       isValidMove = false;
     }
   });
 
-  // 妫�鏌ユ槸鍚﹁秴鍑哄竷灞�杈圭晫
   if (newRect.x < 0 || newRect.y < 0 ||
       newRect.x + newRect.w > layout.width ||
       newRect.y + newRect.h > layout.height) {
@@ -486,14 +500,9 @@
       (props.gh - 100) / layout.height
     );
 
-    // 鎷栧姩缁撴潫鍚庤嚜鍔ㄥ榻愬埌鏈�杩戠殑鏁存暟浣嶇疆
     rect.x = Math.round(rect.x);
     rect.y = Math.round(rect.y);
-
-    // 鍙皟鏁翠綅缃榻愶紝涓嶈皟鏁村ぇ灏�
-    adjustAlignmentPosition(layoutIndex, rectIndex);
-
-    // 璋冩暣鐏拌壊鐭╁舰
+    //adjustAlignmentPosition(layoutIndex, rectIndex);
     adjustGrayRectangles(layoutIndex);
   }
 
@@ -509,25 +518,39 @@
   const threshold = Math.max(rect.w, rect.h) * 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((rect.x + rect.w) - (otherRect.x + otherRect.w)) < threshold) {
-      // 涓嶈皟鏁村搴�
+      rect.x = Math.round((otherRect.x + otherRect.w - rect.w));
     }
+    // 鍨傜洿瀵归綈
     if (Math.abs(rect.y - otherRect.y) < threshold) {
       rect.y = Math.round((rect.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));
     }
   });
+
+  // 纭繚鐭╁舰涓嶄細瓒呭嚭甯冨眬杈圭晫
+  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);
+
+  // 璋冩暣鍚庨噸鏂拌绠楃伆鑹蹭綑鏂�
+  adjustGrayRectangles(layoutIndex);
 };
+
 
 const mergeAdjacentGrayRects = (rects) => {
   const grayRects = rects.filter(r => r.isRemain);
   let merged = [];
-  
+
   grayRects.sort((a, b) => {
     if (a.x !== b.x) return a.x - b.x;
     return a.y - b.y;
@@ -541,16 +564,16 @@
     const last = merged[merged.length - 1];
     const current = grayRects[i];
 
-    if (current.x === last.x + last.w && 
-        current.y === last.y && 
+    if (current.x === last.x + last.w &&
+        current.y === last.y &&
         current.h === last.h) {
       last.w += current.w;
       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 && 
-               current.x === last.x && 
+    } else if (current.y === last.y + last.h &&
+               current.x === last.x &&
                current.w === last.w) {
       last.h += current.h;
       last.x = Math.round(last.x);
@@ -558,7 +581,7 @@
       last.w = Math.round(last.w);
       last.h = Math.round(last.h);
     } else {
-      merged.push({ 
+      merged.push({
         x: Math.round(current.x),
         y: Math.round(current.y),
         w: Math.round(current.w),
@@ -611,22 +634,18 @@
   const rect = layout.rects[rectIndex];
   const originalState = { ...rect };
 
-  // 鏃嬭浆鐭╁舰
   const temp = rect.w;
   rect.w = rect.h;
   rect.h = temp;
 
-  // 妫�鏌ユ棆杞悗鏄惁涓庡叾浠栬摑鑹茬煩褰㈤噸鍙�
   const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
   let isValidRotation = true;
 
   otherRects.forEach(otherRect => {
     if (checkOverlap(rect, otherRect)) {
-      isValidRotation = false;
-    }
+      isValidRotation = false    }
   });
 
-  // 妫�鏌ユ槸鍚﹁秴鍑哄竷灞�杈圭晫
   if (rect.x + rect.w > layout.width || rect.y + rect.h > layout.height) {
     isValidRotation = false;
   }
@@ -634,7 +653,6 @@
   if (isValidRotation) {
     adjustGrayRectangles(layoutIndex);
   } else {
-    // 鎭㈠鍘熺姸
     rect.w = originalState.w;
     rect.h = originalState.h;
     ElMessage.warning('鏃犳硶鏃嬭浆锛屽瓨鍦ㄩ噸鍙犳垨瓒呭嚭杈圭晫');
@@ -646,18 +664,15 @@
   const rect = layout.rects[rectIndex];
   const grayRects = layout.rects.filter(r => r.isRemain);
 
-  // 鏃嬭浆鐭╁舰
   const temp = rect.w;
   rect.w = rect.h;
   rect.h = temp;
 
-  // 妫�鏌ユ棆杞悗鐨勭煩褰㈡槸鍚﹀彲浠ユ斁缃湪鏌愪釜鐏拌壊鐭╁舰鐨勪綅缃�
   const canPlace = grayRects.some(grayRect => {
     return grayRect.w >= rect.w && grayRect.h >= rect.h;
   });
 
   if (!canPlace) {
-    // 濡傛灉涓嶈兘鏀剧疆锛屾仮澶嶅師鐘�
     const temp = rect.w;
     rect.w = rect.h;
     rect.h = temp;
@@ -665,10 +680,7 @@
     return;
   }
 
-  // 璋冩暣鐏拌壊鐭╁舰
   adjustGrayRectangles(layoutIndex);
-
-  // 绉诲姩鐭╁舰
   moveRect(layoutIndex, rectIndex, direction);
 };
 
@@ -677,47 +689,44 @@
   const rect = layout.rects[rectIndex];
   const originalState = { ...rect };
 
-  // 璁$畻鍓╀綑绌洪棿
-  const remainingAreas = calculateRemainingAreas(layout.width, layout.height, layout.rects.filter(r => !r.isRemain));
-  
-  // 鏍规嵁鏂瑰悜璁$畻鍙Щ鍔ㄧ殑鏈�澶ф闀�
   let maxStep = 0;
+  const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
+
   switch (direction) {
     case 'up':
-      maxStep = rect.y;
+      maxStep = getAvailableSpaceUp(rect, layout, obstacles);
       break;
     case 'down':
-      maxStep = layout.height - (rect.y + rect.h);
+      maxStep = getAvailableSpaceDown(rect, layout, obstacles);
       break;
     case 'left':
-      maxStep = rect.x;
+      maxStep = getAvailableSpaceLeft(rect, layout, obstacles);
       break;
     case 'right':
-      maxStep = layout.width - (rect.x + rect.w);
+      maxStep = getAvailableSpaceRight(rect, layout, obstacles);
       break;
   }
 
-  // 绉诲姩姝ラ暱锛屾牴鎹墿浣欑┖闂村姩鎬佽皟鏁�
-  const stepSize = maxStep;
-  const actualStep = Math.min(maxStep, stepSize);
+  if (maxStep <= 0) {
+    ElMessage.warning('鏃犳硶绉诲姩锛屾病鏈夎冻澶熺殑绌洪棿');
+    return;
+  }
 
-  // 绉诲姩鐭╁舰
   switch (direction) {
     case 'up':
-      rect.y -= actualStep;
+      rect.y -= maxStep;
       break;
     case 'down':
-      rect.y += actualStep;
+      rect.y += maxStep;
       break;
     case 'left':
-      rect.x -= actualStep;
+      rect.x -= maxStep;
       break;
     case 'right':
-      rect.x +=actualStep;
+      rect.x += maxStep;
       break;
   }
 
-  // 妫�鏌ユ槸鍚︿笌鍏朵粬钃濊壊鐭╁舰閲嶅彔
   const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
   let isValidMove = true;
 
@@ -727,7 +736,6 @@
     }
   });
 
-  // 妫�鏌ユ槸鍚﹁秴鍑哄竷灞�杈圭晫
   if (rect.x < 0 || rect.y < 0 ||
       rect.x + rect.w > layout.width ||
       rect.y + rect.h > layout.height) {
@@ -737,7 +745,6 @@
   if (isValidMove) {
     adjustGrayRectangles(layoutIndex);
   } else {
-    // 鎭㈠鍘熺姸
     rect.x = originalState.x;
     rect.y = originalState.y;
     ElMessage.warning('鏃犳硶绉诲姩锛屽瓨鍦ㄩ噸鍙犳垨瓒呭嚭杈圭晫');
@@ -829,35 +836,144 @@
   layouts.value = props.layoutData.Layouts;
 };
 
+const getAvailableSpaceUp = (rect, layout, obstacles) => {
+  let maxSpace = rect.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));
+    }
+  });
+  return maxSpace;
+};
 
-let clickEventListener = null;
+const getAvailableSpaceDown = (rect, layout, obstacles) => {
+  let maxSpace = layout.height - (rect.y + rect.h);
+  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));
+    }
+  });
+  return maxSpace;
+};
+
+const getAvailableSpaceLeft = (rect, layout, obstacles) => {
+  let maxSpace = rect.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));
+    }
+  });
+  return maxSpace;
+};
+
+const getAvailableSpaceRight = (rect, layout, obstacles) => {
+  let maxSpace = layout.width - (rect.x + rect.w);
+  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));
+    }
+  });
+  return maxSpace;
+};
+
+let moveInterval = null;
+
+const handleKeyDown = (event) => {
+  if (!focusIndex.value) return;
+
+  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);
+
+  switch (event.key) {
+    case 'ArrowUp':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'up');
+        }, 50);
+      }
+      break;
+    case 'ArrowDown':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'down');
+        }, 50);
+      }
+      break;
+    case 'ArrowLeft':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'left');
+        }, 50);
+      }
+      break;
+    case 'ArrowRight':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'right');
+        }, 50);
+      }
+      break;
+  }
+};
+
+const handleKeyUp = (event) => {
+  if (event.key === 'ArrowUp' || event.key === 'ArrowDown' ||
+      event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
+    if (moveInterval) {
+      clearInterval(moveInterval);
+      moveInterval = null;
+    }
+  }
+};
+
+
+
 onMounted(() => {
   fetchSettings(username);
   setTimeout(updateLayout, 500);
 
   selectedLayoutIndex.value = 0;
 
-   // 娣诲姞鍏ㄥ眬鐐瑰嚮浜嬩欢鐩戝惉鍣�
-   clickEventListener = (event) => {
-    // 妫�鏌ユ槸鍚﹀瓨鍦ㄥ彸閿彍鍗�
+  clickEventListener = (event) => {
     const contextMenus = document.querySelectorAll('.context-menu');
     if (contextMenus.length > 0) {
-      // 绉婚櫎鎵�鏈夊彸閿彍鍗�
       contextMenus.forEach(menu => menu.remove());
     }
   };
   document.addEventListener('click', clickEventListener);
 
+  document.addEventListener('keydown', handleKeyDown);
+  document.addEventListener('keyup', handleKeyUp);
 });
+
+
 
 onUnmounted(() => {
   rectsElements.value = {};
-   // 绉婚櫎鍏ㄥ眬鐐瑰嚮浜嬩欢鐩戝惉鍣�
-   if (clickEventListener) {
+  if (clickEventListener) {
     document.removeEventListener('click', clickEventListener);
+    clickEventListener = null;
   }
+  document.removeEventListener('keydown', handleKeyDown);
+  document.removeEventListener('keyup', handleKeyUp);
 });
+
 </script>
+
 
 <style scoped>
 .layout-wrapper {
@@ -898,7 +1014,7 @@
   font-size: 12px;
 }
 
-.jia-hao .liuchengka {
+.jia-hao, .liuchengka {
   grid-row: 2;
   grid-column: 1;
   margin: auto;

--
Gitblit v1.8.0