From 33dbc6a161554f3a897f9e9273feb4f2c1b47381 Mon Sep 17 00:00:00 2001
From: chenlu <1320612696@qq.com>
Date: 星期一, 15 十二月 2025 17:04:27 +0800
Subject: [PATCH] Merge branch 'master' of http://10.153.19.25:10105/r/ERP_override

---
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue |  460 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 339 insertions(+), 121 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 8136c3d..5a9490e 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
@@ -1,16 +1,80 @@
 <template>
   <div style="display: flex; height: 90vh;">
     <!-- Sidebar -->
-    <div class="sidebar" style="width: 200px; background: #f4f4f4; padding: 10px;">
-      <div
-        v-for="(layout, layoutIndex) in layouts"
-        :key="layoutIndex"
-        class="sidebar-item"
-        @click="selectLayout(layoutIndex)"
-        :class="{ 'selected': selectedLayoutIndex === layoutIndex }"
-      >
-        {{ layout.realWidth }} 脳 {{ layout.realHeight }} 脳 {{ layout.quantity  }}
+    <div class="sidebar" style="width: 200px; background: #f4f4f4; padding: 10px; height: 93%; overflow-y: auto; max-height: 90vh; border-radius: 8px;">
+      <div class="folder">
+        <div
+          class="folder-header"          style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
+        >
+          <span @click="toggleFolder('pending')" style="flex: 1; cursor: pointer;">寰呭垏鍓插師鐗�</span>
+          <button
+            @click="toggleFolder('pending')"            style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
+            :title="openFolders.pending ? '鏀惰捣' : '灞曞紑'"
+          >
+            <el-icon v-if="openFolders.pending"><ArrowUp /></el-icon>
+            <el-icon v-else><ArrowDown /></el-icon>
+          </button>
+        </div>
+        <div v-show="openFolders.pending" class="folder-content" style="padding-left: 15px;">
+          <div
+            v-for="(layout, layoutIndex) in layouts"
+            :key="layoutIndex"
+            class="sidebar-item"
+            @click="selectLayout(layoutIndex)"
+            :class="{ 'selected': selectedLayoutIndex === layoutIndex }"            style="margin-bottom: 5px;"
+          >
+            {{ layout.realWidth }} 脳 {{ layout.realHeight }} 脳 {{ layout.quantity }}
+          </div>
+        </div>
       </div>
+
+<!-- 寰呰ˉ鐗囬槦鍒楁枃浠跺す -->
+      <div class="folder">
+        <div
+          class="folder-header"          style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
+        >
+          <span @click="toggleFolder('patchQueue')" style="flex: 1; cursor: pointer;">寰呰ˉ鐗囬槦鍒�</span>
+          <button
+            @click="toggleFolder('patchQueue')"            style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
+            :title="openFolders.patchQueue ? '鏀惰捣' : '灞曞紑'"
+          >
+            <el-icon v-if="openFolders.patchQueue"><ArrowUp /></el-icon>
+            <el-icon v-else><ArrowDown /></el-icon>
+          </button>
+        </div>
+        <div v-show="openFolders.patchQueue" class="folder-content" style="padding-left: 15px;">
+          <div style="padding: 10px; color: #666; font-style: italic;">
+            鏆傛棤琛ョ墖浠诲姟
+          </div>
+        </div>
+      </div>
+
+      <!-- 娣诲姞鑷畾涔夊昂瀵告枃浠跺す -->
+      <div class="folder">
+        <div
+          class="folder-header"          style="padding: 8px; background: #e0e0e0; margin-bottom: 5px; border-radius: 4px; user-select: none; display: flex; justify-content: space-between; align-items: center;"
+        >
+          <span @click="toggleFolder('customSize')" style="flex: 1; cursor: pointer;">娣诲姞鑷畾涔夊昂瀵�</span>
+          <button
+            @click="toggleFolder('customSize')"            style="background: none; border: none; cursor: pointer; font-size: 14px; padding: 2px 5px; border-radius: 3px;"
+            :title="openFolders.customSize ? '鏀惰捣' : '灞曞紑'"
+          >
+            <el-icon v-if="openFolders.customSize"><ArrowUp /></el-icon>
+            <el-icon v-else><ArrowDown /></el-icon>
+          </button>
+        </div>
+        <div v-show="openFolders.customSize" class="folder-content" style="padding-left: 15px;">
+          <div style="padding: 10px;">
+            <button
+              @click="showAddCustomSizeDialog"              style="width: 100%; padding: 8px; background: #409eff; color: white; border: none; border-radius: 4px; cursor: pointer;"
+            >
+              + 娣诲姞鑷畾涔夊昂瀵�
+            </button>
+          </div>
+        </div>
+      </div>
+
+
     </div>
 
     <!-- Main Layout Panel -->
@@ -53,10 +117,6 @@
             class="layout-glassDetail"
             :style="rectStyle(glassDetail, layoutIndex)"
             @contextmenu.prevent="handleRectRightClick(layoutIndex, rectIndex)"
-            @mousedown="handleRectDragStart(layoutIndex, rectIndex)"
-            @mousemove="handleRectDragging"
-            @mouseup="handleRectDragEnd"
-            @mouseleave="handleRectDragEnd"
             @click="handleRectClick(layoutIndex, rectIndex)"
           >
             <div class="glassDetail-content">
@@ -71,8 +131,7 @@
       </div>
     </div>
 
-    <!-- 鎻愪氦鎸夐挳 -->
-    <button @click="submitLayouts" style="position: fixed; top: 90px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
+    <button @click="submitLayouts" style="position: fixed; top: 90px; right: 20px; padding: 10px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;">
       淇濆瓨璋冩暣
     </button>
   </div>
@@ -80,9 +139,10 @@
 
 <script setup>
 import { ref, reactive, onMounted, onUnmounted } from 'vue';
-import { useRouter } from 'vue-router'; // 娣诲姞杩欒
+import { useRouter } from 'vue-router';
+import { ArrowUp, ArrowDown } from '@element-plus/icons-vue'
 import request from "@/utils/request";
-const router = useRouter(); // 娣诲姞杩欒
+const router = useRouter();
 import { useI18n } from "vue-i18n";
 import { ElMessage, ElMessageBox } from "element-plus";
 import useUserInfoStore from "@/stores/userInfo";
@@ -109,9 +169,9 @@
 const rectClass = ref('layout-glassDetail');
 const selectedLayoutIndex = ref(0);
 const currentRect = ref(null);
-const dragging = ref(false);
-const dragStartPos = ref({ x: 0, y: 0 });
-const dragRect = ref(null);
+// const dragging = ref(false);
+// const dragStartPos = ref({ x: 0, y: 0 });
+// const dragRect = ref(null);
 const showJiaHao = ref(false);
 const showProcessId = ref(false);
 const themeColor = ref(null);
@@ -120,10 +180,10 @@
 const submitLayouts = async () => {
   layouts.value.forEach(layout => {
     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);
+      glassDetail.x = parseFloat(glassDetail.x.toFixed(2));
+      glassDetail.y = parseFloat(glassDetail.y.toFixed(2));
+      glassDetail.width = parseFloat(glassDetail.width.toFixed(2));
+      glassDetail.height = parseFloat(glassDetail.height.toFixed(2));
     });
   });
   const savedProjectNo = localStorage.getItem('projectNo');
@@ -153,6 +213,30 @@
       ElMessage.warning(res.msg);
     }
   });
+};
+
+const openFolders = ref({
+  pending: true,  // 榛樿灞曞紑"寰呭垏鍓插師鐗�"鏂囦欢澶�
+   patchQueue: false,   // 榛樿鏀惰捣"寰呰ˉ鐗囬槦鍒�"鏂囦欢澶�
+  customSize: false   // 榛樿鏀惰捣"娣诲姞鑷畾涔夊昂瀵�"鏂囦欢澶�
+});
+
+// 鍒囨崲鏂囦欢澶瑰睍寮�/鏀惰捣鐘舵��
+const toggleFolder = (folderName) => {
+  openFolders.value[folderName] = !openFolders.value[folderName];
+};
+
+
+
+const showAddCustomSizeDialog = () => {
+  // 妫�鏌ユ槸鍚﹂�夋嫨浜嗙増鍥�
+  if (selectedLayoutIndex.value === null || layouts.value.length === 0) {
+    ElMessage.warning('璇峰厛閫夋嫨涓�涓増鍥�');
+    return;
+  }
+
+  // 浣跨敤鐜版湁鐨勬坊鍔犳垚鍝侀�昏緫锛屼紶鍏ュ綋鍓嶉�変腑鐨勭増鍥剧储寮�
+  showAddDialog(selectedLayoutIndex.value);
 };
 
 //鏌ヨ璁剧疆鐨勫熀纭�淇℃伅鏋跺彿锛岀煩褰㈤鑹诧紝璁㈠崟搴忓彿绛�
@@ -258,6 +342,12 @@
   return bestFit;
 };
 
+const isSelected = (layoutIndex, rectIndex) => {
+  return focusIndex.value &&
+         focusIndex.value.layoutIndex === layoutIndex &&
+         focusIndex.value.rectIndex === rectIndex;
+};
+
 //鐗堝浘鍐呭鏍峰紡鍔犺浇
 const layoutContainerStyle = (layoutIndex) => {
   const layout = layouts.value[layoutIndex];
@@ -309,9 +399,10 @@
 //鐗堝浘鍐呭灏忕墖鏍峰紡鍔犺浇
 const rectStyle = (glassDetail, layoutIndex) => {
   const layout = layouts.value[layoutIndex];
-  const scale = Math.min(0.25
-  );
-  return {
+  const scale = Math.min(0.25);
+  const isSelectedRect = isSelected(layoutIndex, layout.glassDetails.indexOf(glassDetail));
+
+  let style = {
     position: 'absolute',
     left: `${glassDetail.x * scale}px`,
     top: `${glassDetail.y * scale}px`,
@@ -323,13 +414,21 @@
     draggable: !glassDetail.isRemain,
     zIndex: glassDetail.isRemain ? 1 : 2
   };
+
+  // 濡傛灉琚�変腑锛屽垯娣诲姞鍐呬晶绾㈡
+  if (isSelectedRect) {
+    style.boxShadow = 'inset 0 0 0 2px red';
+  }
+
+  return style;
 };
 
 const rectStyle1 = (glassDetail, layoutIndex) => {
   const layout = layouts.value[layoutIndex];
-  const scale = Math.min(0.25
-  );
-  return {
+  const scale = Math.min(0.25);
+  const isSelectedRect = isSelected(layoutIndex, layout.glassDetails.indexOf(glassDetail));
+
+  let style = {
     position: 'absolute',
     left: `${glassDetail.x * scale}px`,
     top: `${glassDetail.y * scale}px`,
@@ -341,10 +440,21 @@
     draggable: !glassDetail.isRemain,
     zIndex: glassDetail.isRemain ? 1 : 2
   };
+
+  // 濡傛灉琚�変腑锛屽垯娣诲姞鍐呬晶绾㈡
+  if (isSelectedRect) {
+    style.boxShadow = 'inset 0 0 0 2px red';
+  }
+
+  return style;
 };
 
 //鐐瑰嚮灏忕墖
 const handleRectClick = (layoutIndex, rectIndex) => {
+  // if (dragging.value) {
+  //   return;
+  // }
+
   focusIndex.value = { layoutIndex, rectIndex };
   emit('rectClicked', layoutIndex, rectIndex);
 };
@@ -353,12 +463,13 @@
 const handleRectRightClick = (layoutIndex, rectIndex) => {
   const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
   if (glassDetail.isRemain) return;
+  document.querySelectorAll('.context-menu').forEach(el => el.remove());
 
   const contextMenu = document.createElement('div');
   contextMenu.className = 'context-menu';
   contextMenu.style.position = 'absolute';
   contextMenu.style.left = `${event.clientX}px`;
-  contextMenu.style.bottom = `${event.clientY}px`;
+  contextMenu.style.top = `${event.clientY}px`;
   contextMenu.style.backgroundColor = '#fff';
   contextMenu.style.border = '1px solid #ccc';
   contextMenu.style.padding = '5px';
@@ -489,12 +600,13 @@
 const handleGrayRectRightClick = (layoutIndex, rectIndex,glassDetails) => {
   //const glassDetail = glassDetails[rectIndex];
   if (!glassDetails.isRemain) return;
+  document.querySelectorAll('.context-menu').forEach(el => el.remove());
 
   const contextMenu = document.createElement('div');
   contextMenu.className = 'context-menu';
   contextMenu.style.position = 'absolute';
   contextMenu.style.left = `${event.clientX}px`;
-  contextMenu.style.bottom = `${event.clientY}px`;
+  contextMenu.style.top = `${event.clientY}px`;
   contextMenu.style.backgroundColor = '#fff';
   contextMenu.style.border = '1px solid #ccc';
   contextMenu.style.padding = '5px';
@@ -532,85 +644,122 @@
 };
 
 //灏忕墖榧犳爣鎸変笅浜嬩欢
-const handleRectDragStart = (layoutIndex, rectIndex) => {
-  const layout = layouts.value[layoutIndex];
-  const glassDetail = layout.glassDetails[rectIndex];
-  if (glassDetail.isRemain) return;
+// const handleRectDragStart = (layoutIndex, rectIndex) => {
+//   const layout = layouts.value[layoutIndex];
+//   const glassDetail = layout.glassDetails[rectIndex];
+//   if (glassDetail.isRemain) return;
+//
+//   dragRect.value = { layoutIndex, rectIndex };
+//   dragStartPos.value = {
+//     x: event.clientX,
+//     y: event.clientY
+//   };
+// };
 
-  dragging.value = true;
-  dragRect.value = { layoutIndex, rectIndex };
-  dragStartPos.value = {
-    x: event.clientX,
-    y: event.clientY
-  };
-};
+// //灏忕墖榧犳爣绉诲姩浜嬩欢
+// const handleRectDragging = (event) => {
+//   if (!dragRect.value) return;
+//
+//   // 濡傛灉杩樻病纭鏄嫋鎷斤紝鍒欏厛鍒ゆ柇鏄惁杈惧埌鎷栨嫿闃堝��(渚嬪5鍍忕礌)
+//   if (!dragging.value) {
+//     const deltaX = event.clientX - dragStartPos.value.x;
+//     const deltaY = event.clientY - dragStartPos.value.y;
+//     const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+//
+//     // 濡傛灉绉诲姩璺濈灏忎簬闃堝�硷紝鍒欒涓烘槸鐐瑰嚮鑰岄潪鎷栨嫿
+//     if (distance < 5) {
+//       return;
+//     }
+//
+//     // 杈惧埌闃堝�硷紝纭鏄嫋鎷芥搷浣�
+//     dragging.value = true;
+//   }
+//
+//   const layoutIndex = dragRect.value.layoutIndex;
+//   const rectIndex = dragRect.value.rectIndex;
+//   const layout = layouts.value[layoutIndex];
+//   const glassDetail = layout.glassDetails[rectIndex];
+//
+//   // 淇濆瓨鍘熷鍧愭爣鐢ㄤ簬璁$畻鍋忕Щ閲�
+//   const originalX = glassDetail.x;
+//   const originalY = glassDetail.y;
+//
+//   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 = { ...glassDetail };
+//   newRect.x += deltaX / scale;
+//   newRect.y += deltaY / scale;
+//
+//   const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
+//   let isValidMove = true;
+//
+//   otherRects.forEach(otherRect => {
+//     if (checkOverlap(newRect, otherRect)) {
+//       isValidMove = false;
+//     }
+//   });
+//
+//   if (newRect.x < 0 || newRect.y < 0 ||
+//       newRect.x + newRect.width > layout.width ||
+//       newRect.y + newRect.height > layout.height) {
+//     isValidMove = false;
+//   }
+//
+//   if (isValidMove) {
+//     glassDetail.x = newRect.x;
+//     glassDetail.y = newRect.y;
+//
+//     // 鏇存柊glassPoint鍧愭爣
+//     if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
+//       const offsetX = glassDetail.x - originalX;
+//       const offsetY = glassDetail.y - originalY;
+//
+//       glassDetail.glassPoint.forEach(point => {
+//         point.X += offsetX;
+//         point.Y += offsetY;
+//         // 娣诲姞绮惧害鎺у埗
+//         point.X = parseFloat(point.X.toFixed(2));
+//         point.Y = parseFloat(point.Y.toFixed(2));
+//       });
+//     }
+//
+//     dragStartPos.value = {
+//       x: event.clientX,
+//       y: event.clientY
+//     };
+//     adjustGrayRectangles(layoutIndex);
+//   }
+// };
 
-//灏忕墖榧犳爣绉诲姩浜嬩欢
-const handleRectDragging = (event) => {
-  if (!dragging.value || !dragRect.value) return;
-
-  const layoutIndex = dragRect.value.layoutIndex;
-  const rectIndex = dragRect.value.rectIndex;
-  const layout = layouts.value[layoutIndex];
-  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 = { ...glassDetail };
-  newRect.x += deltaX / scale;
-  newRect.y += deltaY / scale;
-
-  const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
-  let isValidMove = true;
-
-  otherRects.forEach(otherRect => {
-    if (checkOverlap(newRect, otherRect)) {
-      isValidMove = false;
-    }
-  });
-
-  if (newRect.x < 0 || newRect.y < 0 ||
-      newRect.x + newRect.width > layout.width ||
-      newRect.y + newRect.height > layout.height) {
-    isValidMove = false;
-  }
-
-  if (isValidMove) {
-    glassDetail.x = newRect.x;
-    glassDetail.y = newRect.y;
-    dragStartPos.value = {
-      x: event.clientX,
-      y: event.clientY
-    };
-    adjustGrayRectangles(layoutIndex);
-  }
-};
-
-//灏忕墖榧犳爣鏉惧紑浜嬩欢
-const handleRectDragEnd = () => {
-  if (dragRect.value) {
-    const layoutIndex = dragRect.value.layoutIndex;
-    const rectIndex = dragRect.value.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
-    );
-
-    glassDetail.x = Math.round(glassDetail.x);
-    glassDetail.y = Math.round(glassDetail.y);
-    adjustAlignmentPosition(layoutIndex, rectIndex);
-  }
-
-  dragging.value = false;
-  dragRect.value = null;
-};
+// //灏忕墖榧犳爣鏉惧紑浜嬩欢
+// const handleRectDragEnd = () => {
+//   dragging.value = false;
+//   dragRect.value = null;
+//   dragStartPos.value = { x: 0, y: 0 };
+//   if (dragRect.value) {
+//     const layoutIndex = dragRect.value.layoutIndex;
+//     const rectIndex = dragRect.value.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
+//     );
+//
+//     glassDetail.x = parseFloat(glassDetail.x.toFixed(2));
+//     glassDetail.y = parseFloat(glassDetail.y.toFixed(2));
+//     adjustAlignmentPosition(layoutIndex, rectIndex);
+//   }
+//
+//   dragging.value = false;
+//   dragRect.value = null;
+// };
 
 const adjustAlignmentPosition = (layoutIndex, rectIndex) => {
   const layout = layouts.value[layoutIndex];
@@ -684,10 +833,10 @@
     else {
       // 鏃犳硶鍚堝苟锛屼繚瀛樺綋鍓嶇煩褰紝寮�濮嬫柊鐨勫悎骞�
       merged.push({
-        x: Math.round(current.x),
-        y: Math.round(current.y),
-        width: Math.round(current.width),
-        height: Math.round(current.height),
+        x: current.x,
+        y: current.y,
+        width: current.width,
+        height: current.height,
         isRemain: true
       });
       current = { ...next };
@@ -696,10 +845,10 @@
 
   // 娣诲姞鏈�鍚庝竴涓煩褰�
   merged.push({
-    x: Math.round(current.x),
-    y: Math.round(current.y),
-    width: Math.round(current.width),
-    height: Math.round(current.height),
+    x: current.x,
+    y: current.y,
+    width: current.width,
+    height: current.height,
     isRemain: true
   });
 
@@ -755,10 +904,10 @@
   // 娣诲姞鏂扮殑浣欐枡鐭╁舰
   uniqueArr.forEach((area) => {
     newGlassDetails.push({
-      x: Math.round(area.x),
-      y: Math.round(area.y),
-      width: Math.round(area.width),
-      height: Math.round(area.height),
+      x: area.x,
+      y: area.y,
+      width: area.width,
+      height: area.height,
       isRemain: true
     });
   });
@@ -819,6 +968,25 @@
   }
 
   if (isValidRotation) {
+    // 鏇存柊glassPoint鍧愭爣锛堝鏋滃瓨鍦級
+    if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
+      // 淇濆瓨鍘熷鐐瑰潗鏍�
+      const originalPoints = JSON.parse(JSON.stringify(glassDetail.glassPoint));
+
+      // 鏃嬭浆鐐瑰潗鏍囷紙浠ョ煩褰㈠乏涓婅涓哄師鐐圭殑鏃嬭浆锛�
+      glassDetail.glassPoint.forEach((point, index) => {
+        // 璁$畻鐩稿浜庣煩褰㈠乏涓婅鐨勫潗鏍�
+        const relX = originalPoints[index].X - originalState.x;
+        const relY = originalPoints[index].Y - originalState.y;
+
+        // 鏃嬭浆90搴﹀悗鐨勫潗鏍囷紙椤烘椂閽堬級
+        point.X = originalState.x + relY;
+        point.Y = originalState.y + (originalState.width - relX);
+        // 娣诲姞绮惧害鎺у埗
+        point.X = parseFloat(point.X.toFixed(2));
+        point.Y = parseFloat(point.Y.toFixed(2));
+      });
+    }
     adjustGrayRectangles(layoutIndex);
   } else {
     glassDetail.width = originalState.width;
@@ -882,6 +1050,11 @@
     return;
   }
 
+
+  // 淇濆瓨鍘熷鍧愭爣
+  const originalX = glassDetail.x;
+  const originalY = glassDetail.y;
+
   switch (direction) {
     case 'up':
       glassDetail.y += maxStep;
@@ -913,6 +1086,19 @@
   }
 
   if (isValidMove) {
+    // 鏇存柊glassPoint鍧愭爣
+    if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
+      const offsetX = glassDetail.x - originalX;
+      const offsetY = glassDetail.y - originalY;
+
+      glassDetail.glassPoint.forEach(point => {
+        point.X += offsetX;
+        point.Y += offsetY;
+        // 娣诲姞绮惧害鎺у埗
+        point.X = parseFloat(point.X.toFixed(2));
+        point.Y = parseFloat(point.Y.toFixed(2));
+      });
+    }
     adjustGrayRectangles(layoutIndex);
   } else {
     glassDetail.x = originalState.x;
@@ -1161,6 +1347,15 @@
     // 鏇存柊鐭╁舰浣嶇疆
     glassDetail.x = newX;
     glassDetail.y = newY;
+
+    // 鏇存柊glassPoint鍧愭爣
+    if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
+      glassDetail.glassPoint.forEach(point => {
+        point.X = width - point.X;
+        point.X = parseFloat(point.X.toFixed(2));
+        point.Y = parseFloat(point.Y.toFixed(2));
+      });
+    }
   });
 
   // 鏇存柊甯冨眬
@@ -1181,6 +1376,16 @@
 
     // 鏇存柊鐭╁舰浣嶇疆
     glassDetail.y = newY;
+
+    // 鏇存柊glassPoint鍧愭爣
+    if (glassDetail.glassPoint && Array.isArray(glassDetail.glassPoint)) {
+      glassDetail.glassPoint.forEach(point => {
+        point.Y = height - point.Y;
+        // 娣诲姞绮惧害鎺у埗
+        point.X = parseFloat(point.X.toFixed(2));
+        point.Y = parseFloat(point.Y.toFixed(2));
+      });
+    }
   });
 
   // 鏇存柊甯冨眬
@@ -1292,4 +1497,17 @@
 .context-menu div:hover {
   background-color: #f0f0f0;
 }
+
+.folder-header {
+  font-weight: bold;
+}
+
+.folder-header:hover {
+  background-color: #d0d0d0 !important;
+}
+
+.folder-content {
+  border-left: 2px solid #ccc;
+  margin-left: 5px;
+}
 </style>

--
Gitblit v1.8.0