From 768e16999a8ce4bb500490ee76c659aa61ea1783 Mon Sep 17 00:00:00 2001
From: 廖井涛 <2265517004@qq.com>
Date: 星期二, 25 三月 2025 10:08:13 +0800
Subject: [PATCH] Merge branch 'master' of http://bore.pub:10439/r/ERP_override

---
 north-glass-erp/northglass-erp/src/router/index.js                                       |   25 
 north-glass-erp/northglass-erp/src/components/pp/settings.json                           |   74 +
 .gitignore                                                                               |    3 
 north-glass-erp/src/main/java/com/example/erp/dto/pp/OrderNumberTransferDTO.java         |   45 
 north-glass-erp/src/main/java/com/example/erp/config/AppConfig.java                      |   13 
 north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java         |    8 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue            |  104 ++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue              |  522 ++++++++++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue      |  934 +++++++++++++++++
 north-glass-erp/northglass-erp/src/components/pp/MockData.js                             |    5 
 north-glass-erp/src/main/java/com/example/erp/entity/pp/ReportingWorkTransfer.java       |   28 
 north-glass-erp/northglass-erp/package-lock.json                                         |  170 +-
 north-glass-erp/src/main/java/com/example/erp/entity/sd/OrderDetail.java                 |    2 
 north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportingWorkController.java |    6 
 north-glass-erp/src/main/java/com/example/erp/controller/sd/OrderController.java         |    7 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimize.vue                   |    8 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue         |    5 
 north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java       |   51 
 north-glass-erp/src/main/java/com/example/erp/service/userInfo/UserService.java          |   10 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue          |   68 
 north-glass-erp/src/main/java/com/example/erp/mapper/userInfo/UserMapper.java            |    2 
 north-glass-erp/src/main/java/com/example/erp/entity/pp/LayoutsData.java                 |  113 ++
 north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportingWorkTransferMapper.java |    9 
 north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml                           |   22 
 north-glass-erp/src/main/resources/mapper/userInfo/User.xml                              |    7 
 north-glass-erp/src/main/java/com/example/erp/entity/pp/FlowCard.java                    |    4 
 north-glass-erp/src/main/java/com/example/erp/entity/userInfo/User.java                  |    1 
 north-glass-erp/src/main/java/com/example/erp/controller/userInfo/UserController.java    |    1 
 north-glass-erp/src/main/java/com/example/erp/service/pp/ReportingWorkService.java       |  243 ++++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeMove.vue               |  166 --
 north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java |   77 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue               |   59 +
 north-glass-erp/src/main/java/com/example/erp/service/pp/JsonToOptConverter.java         |  137 ++
 north-glass-erp/src/main/resources/mapper/pp/ReportingWork.xml                           |    4 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue      |  150 ++
 35 files changed, 2,769 insertions(+), 314 deletions(-)

diff --git a/.gitignore b/.gitignore
index ac70f6b..1bcc582 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,6 @@
 /north-glass-erp/.idea/uiDesigner.xml
 /north-glass-erp/.idea/vcs.xml
 /north-glass-erp/northglass-erp/public/*.apk
+/north-glass-erp/.idea
+/north-glass-erp/src/.idea
+/north-glass-erp/src/main/main.iml
diff --git a/north-glass-erp/northglass-erp/package-lock.json b/north-glass-erp/northglass-erp/package-lock.json
index 8c8f312..f76dec2 100644
--- a/north-glass-erp/northglass-erp/package-lock.json
+++ b/north-glass-erp/northglass-erp/package-lock.json
@@ -69,9 +69,9 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.25.0",
-      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.25.0.tgz",
-      "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
+      "version": "7.26.10",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.10.tgz",
+      "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
       "dependencies": {
         "regenerator-runtime": "^0.14.0"
       },
@@ -1439,12 +1439,6 @@
       "integrity": "sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA==",
       "license": "MIT"
     },
-    "node_modules/dompurify": {
-      "version": "2.5.6",
-      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.6.tgz",
-      "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==",
-      "optional": true
-    },
     "node_modules/element-plus": {
       "version": "2.9.3",
       "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.3.tgz",
@@ -1557,9 +1551,9 @@
       "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
     },
     "node_modules/fflate": {
-      "version": "0.4.8",
-      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.4.8.tgz",
-      "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
+      "version": "0.8.2",
+      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz",
+      "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
     },
     "node_modules/file-saver": {
       "version": "2.0.5",
@@ -1728,23 +1722,6 @@
       "version": "3.11.6",
       "resolved": "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.6.tgz",
       "integrity": "sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA=="
-    },
-    "node_modules/jspdf": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.1.tgz",
-      "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
-      "dependencies": {
-        "@babel/runtime": "^7.14.0",
-        "atob": "^2.1.2",
-        "btoa": "^1.2.1",
-        "fflate": "^0.4.8"
-      },
-      "optionalDependencies": {
-        "canvg": "^3.0.6",
-        "core-js": "^3.6.0",
-        "dompurify": "^2.2.0",
-        "html2canvas": "^1.0.0-rc.5"
-      }
     },
     "node_modules/local-pkg": {
       "version": "0.4.3",
@@ -7398,6 +7375,29 @@
         "socket.io-client": "^4.5.1"
       }
     },
+    "node_modules/vue-plugin-hiprint/node_modules/dompurify": {
+      "version": "2.5.8",
+      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.8.tgz",
+      "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==",
+      "optional": true
+    },
+    "node_modules/vue-plugin-hiprint/node_modules/jspdf": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.2.tgz",
+      "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.23.2",
+        "atob": "^2.1.2",
+        "btoa": "^1.2.1",
+        "fflate": "^0.8.1"
+      },
+      "optionalDependencies": {
+        "canvg": "^3.0.6",
+        "core-js": "^3.6.0",
+        "dompurify": "^2.5.4",
+        "html2canvas": "^1.0.0-rc.5"
+      }
+    },
     "node_modules/vue-router": {
       "version": "4.2.5",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",
@@ -7609,9 +7609,9 @@
       "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
     },
     "@babel/runtime": {
-      "version": "7.25.0",
-      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.25.0.tgz",
-      "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
+      "version": "7.26.10",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.10.tgz",
+      "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
       "requires": {
         "regenerator-runtime": "^0.14.0"
       },
@@ -8505,12 +8505,6 @@
       "resolved": "https://registry.npmmirror.com/dom-zindex/-/dom-zindex-1.0.6.tgz",
       "integrity": "sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA=="
     },
-    "dompurify": {
-      "version": "2.5.6",
-      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.6.tgz",
-      "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==",
-      "optional": true
-    },
     "element-plus": {
       "version": "2.9.3",
       "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.3.tgz",
@@ -8609,9 +8603,9 @@
       "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
     },
     "fflate": {
-      "version": "0.4.8",
-      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.4.8.tgz",
-      "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
+      "version": "0.8.2",
+      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz",
+      "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
     },
     "file-saver": {
       "version": "2.0.5",
@@ -8723,21 +8717,6 @@
       "version": "3.11.6",
       "resolved": "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.6.tgz",
       "integrity": "sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA=="
-    },
-    "jspdf": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.1.tgz",
-      "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
-      "requires": {
-        "@babel/runtime": "^7.14.0",
-        "atob": "^2.1.2",
-        "btoa": "^1.2.1",
-        "canvg": "^3.0.6",
-        "core-js": "^3.6.0",
-        "dompurify": "^2.2.0",
-        "fflate": "^0.4.8",
-        "html2canvas": "^1.0.0-rc.5"
-      }
     },
     "local-pkg": {
       "version": "0.4.3",
@@ -8882,9 +8861,9 @@
           "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
         },
         "@babel/runtime": {
-          "version": "7.25.0",
-          "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.25.0.tgz",
-          "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
+          "version": "7.26.10",
+          "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.10.tgz",
+          "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
           "requires": {
             "regenerator-runtime": "^0.14.0"
           },
@@ -9778,12 +9757,6 @@
           "resolved": "https://registry.npmmirror.com/dom-zindex/-/dom-zindex-1.0.6.tgz",
           "integrity": "sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA=="
         },
-        "dompurify": {
-          "version": "2.5.6",
-          "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.6.tgz",
-          "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==",
-          "optional": true
-        },
         "element-plus": {
           "version": "2.9.3",
           "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.3.tgz",
@@ -9882,9 +9855,9 @@
           "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
         },
         "fflate": {
-          "version": "0.4.8",
-          "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.4.8.tgz",
-          "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
+          "version": "0.8.2",
+          "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz",
+          "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
         },
         "file-saver": {
           "version": "2.0.5",
@@ -9996,21 +9969,6 @@
           "version": "3.11.6",
           "resolved": "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.6.tgz",
           "integrity": "sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA=="
-        },
-        "jspdf": {
-          "version": "2.5.1",
-          "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.1.tgz",
-          "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
-          "requires": {
-            "@babel/runtime": "^7.14.0",
-            "atob": "^2.1.2",
-            "btoa": "^1.2.1",
-            "canvg": "^3.0.6",
-            "core-js": "^3.6.0",
-            "dompurify": "^2.2.0",
-            "fflate": "^0.4.8",
-            "html2canvas": "^1.0.0-rc.5"
-          }
         },
         "local-pkg": {
           "version": "0.4.3",
@@ -15563,6 +15521,29 @@
             "jspdf": "^2.5.1",
             "nzh": "^1.0.8",
             "socket.io-client": "^4.5.1"
+          },
+          "dependencies": {
+            "dompurify": {
+              "version": "2.5.8",
+              "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.8.tgz",
+              "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==",
+              "optional": true
+            },
+            "jspdf": {
+              "version": "2.5.2",
+              "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.2.tgz",
+              "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
+              "requires": {
+                "@babel/runtime": "^7.23.2",
+                "atob": "^2.1.2",
+                "btoa": "^1.2.1",
+                "canvg": "^3.0.6",
+                "core-js": "^3.6.0",
+                "dompurify": "^2.5.4",
+                "fflate": "^0.8.1",
+                "html2canvas": "^1.0.0-rc.5"
+              }
+            }
           }
         },
         "vue-router": {
@@ -21168,6 +21149,29 @@
         "jspdf": "^2.5.1",
         "nzh": "^1.0.8",
         "socket.io-client": "^4.5.1"
+      },
+      "dependencies": {
+        "dompurify": {
+          "version": "2.5.8",
+          "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.8.tgz",
+          "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==",
+          "optional": true
+        },
+        "jspdf": {
+          "version": "2.5.2",
+          "resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-2.5.2.tgz",
+          "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
+          "requires": {
+            "@babel/runtime": "^7.23.2",
+            "atob": "^2.1.2",
+            "btoa": "^1.2.1",
+            "canvg": "^3.0.6",
+            "core-js": "^3.6.0",
+            "dompurify": "^2.5.4",
+            "fflate": "^0.8.1",
+            "html2canvas": "^1.0.0-rc.5"
+          }
+        }
       }
     },
     "vue-router": {
diff --git a/north-glass-erp/northglass-erp/src/components/pp/MockData.js b/north-glass-erp/northglass-erp/src/components/pp/MockData.js
index 132617b..e717154 100644
--- a/north-glass-erp/northglass-erp/src/components/pp/MockData.js
+++ b/north-glass-erp/northglass-erp/src/components/pp/MockData.js
@@ -1,7 +1,6 @@
 // MockData.js
 const mockLayoutData = {
-    result: "ok",
-    data: {
+   
       Layouts: [
         {
           mnumber: 9,
@@ -1484,7 +1483,7 @@
 		}
       ],
       method: "getResult"
-    }
+   
   };
   
   export default mockLayoutData;
diff --git a/north-glass-erp/northglass-erp/src/components/pp/settings.json b/north-glass-erp/northglass-erp/src/components/pp/settings.json
new file mode 100644
index 0000000..e6e53be
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/components/pp/settings.json
@@ -0,0 +1,74 @@
+{
+    "optimization": {
+        "yShapeJoinOptimization": "1",
+        "autoMiddleEmptyPairing": "1",
+        "smallPieceRotationProhibited": "1",
+        "maxFramesOnSite": "10",
+        "bendEdgeDistance": "5",
+        "positiveTolerance": "0",
+        "negativeTolerance": "0",
+        "cutterOriginPosition": "topLeft",
+        "uniformShapeEdgeTrimAmount": "5",
+        "edgeTrimMode": "intelligent",
+        "parallelOptimizationChannels": "2",
+        "optimizationIterations": "1",
+        "finishedProductGrindingAmount": "0",
+        "rawPieceEdgeTrimAmount": "0",
+        "finishedSinglePieceBelowGrindingAmount": "500"
+    },
+    "display": {
+        "themeColor": "#ffffff",
+        "includeProductEdge": true,
+        "includeIrregularEdge": true,
+        "mergeByFrameNumber": true,
+        "frameNumber": true,
+        "orderNumber": true,
+        "productName": true,
+        "processingInfo": true,
+        "remarks": true,
+        "floorNumber": true,
+        "edgeLength": true,
+        "manufacturingProcess": true,
+        "identifier": true
+    },
+    "cutting": {
+        "cutting_direction": true,
+        "show_cutting_path": true,
+        "force_continuous_cutting": true,
+        "min_radius": 5,
+        "min_parallel_offset": 0.1,
+        "t_shaped_recess": 2,
+        "down_cut_spacing": 0.5,
+        "lift_retract": 1
+    },
+    "server": {
+        "output_format": "json",
+        "save_location": "local",
+        "auto_save": true,
+        "save_interval": 60,
+        "engineering_file_save_path": "",
+        "cutting_code_save_path": "",
+        "open_folder_after_save": "",
+        "g_code_file_format": "",
+        "trf_file_save_path": "",
+        "btl_file_save_path": "",
+        "optima_file_save_path": "",
+        "optimization_depth_limit_enable": "",
+        "original_sheet_material_calculation": ""
+    },
+    "tempering": {
+        "tempering_temp": 600,
+        "cooling_rate": 50,
+        "annealing_time": 3600,
+        "furnaceLength": 0,
+        "furnaceWidth": 0,
+        "maxLoadingRate": 100,
+        "chaosLevel": 0,
+        "temperingTime": 1200,
+        "defaultTemperingMode": "auto",
+        "maxArea": 100,
+        "maxPieceCount": 100,
+        "xAxisInterval": 10,
+        "yAxisInterval": 10
+    }
+}
diff --git a/north-glass-erp/northglass-erp/src/router/index.js b/north-glass-erp/northglass-erp/src/router/index.js
index 05d332c..941701c 100644
--- a/north-glass-erp/northglass-erp/src/router/index.js
+++ b/north-glass-erp/northglass-erp/src/router/index.js
@@ -61,6 +61,10 @@
             }
           ]
         },
+{
+          path: '/main/glassOptimize/MoveManage',
+          component: () => import('@/views/pp/glassOptimize/MoveManage.vue')
+        },
         {
           path:'userPassWord',
           name: 'userPassWord',
@@ -337,9 +341,24 @@
               component: () => import('../views/pp/glassOptimize/OptimizePrint.vue'),
             },
             {
-              path: 'optimizeMove',
-              name: 'optimizeMove',
-              component: () => import('../views/pp/glassOptimize/OptimizeMove.vue'),
+              path: 'OptimizationRectPrint',
+              name: 'OptimizationRectPrint',
+              component: () => import('../views/pp/glassOptimize/OptimizationRectPrint.vue'),
+            },
+            {
+              path: 'OptimizeControl',
+              name: 'OptimizeControl',
+              component: () => import('../views/pp/glassOptimize/OptimizeControl.vue'),
+            },
+            {
+              path: 'Optimization',
+              name: 'Optimization',
+              component: () => import('../views/pp/glassOptimize/Optimization.vue'),
+            },
+            {
+              path: 'optimizeparms',
+              name: 'optimizeparms',
+              component: () => import('../views/pp/glassOptimize/OptimizeParms.vue'),
             },
             {
               path: '/optimizeProject/:projectNo/:thickNess/:model',
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue
new file mode 100644
index 0000000..b5c8977
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue
@@ -0,0 +1,59 @@
+<template>
+  <div>
+    <RectRenderer 
+      :layoutData="layoutData" 
+      :gw="1150" 
+      :gh="850" 
+      style="width: 1000px; height: 800px; position: relative;"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref,onMounted } from 'vue';
+import RectRenderer from './page/OptimizationRect.vue';
+import mockLayoutData from '../../../components/pp/MockData';
+import request from "@/utils/request";
+import { useI18n } from "vue-i18n";
+import { ElMessage } from "element-plus";
+
+const { t } = useI18n();
+//const layoutData = ref(mockLayoutData);
+// const processId = "P25030309";
+const savedProjectNo = localStorage.getItem('projectNo');
+const processId = savedProjectNo;
+console.log(processId)
+const layoutData = ref(null);
+
+const selectLayout = () => {
+request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
+.then((res) => {
+  if (res.code == 200) {
+    try {
+      // 灏嗗瓧绗︿覆鏁版嵁杞崲涓哄璞�
+      // console.log("鍘熷鏁版嵁:", res.data.data[0].Layouts);
+
+      const parsedData = JSON.parse(res.data.data[0].Layouts);
+      layoutData.value = parsedData;
+      // console.log("瑙f瀽鍚庣殑鏁版嵁:", layoutData.value);
+      // console.log("鏁版嵁绫诲瀷:", typeof parsedData);
+      ElMessage.success("鎵撳紑鐗堝浘鎴愬姛")
+    } catch (error) {
+      ElMessage.error("瑙f瀽鏁版嵁鏃跺嚭閿�:", error);
+     
+    }
+  } else {
+
+  }
+})
+.catch((error) => {
+  console.error("璇锋眰澶辫触:", error);
+  ElMessage.error(t('basicData.msg.requestFailed'));
+});
+}
+
+onMounted(() => {
+  selectLayout();
+
+});
+</script>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
new file mode 100644
index 0000000..85d592f
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
@@ -0,0 +1,150 @@
+<template>
+  <div>
+   
+    <el-button id="button" type="primary" @click="handlePrint">鎵撳嵃鐗堝浘</el-button>
+    <RectRenderer 
+      ref="rectRenderer"
+      :layoutData="layoutData" 
+      :gw="1400" 
+      :gh="1100" 
+      style="width: 100%; height: 800px; position: relative;"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref,onMounted } from 'vue';
+import RectRenderer from './page/RectRenderer.vue';
+import mockLayoutData from '../../../components/pp/MockData';
+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');
+  iframe.style.position = 'fixed';
+  iframe.style.top = '-100vh';
+  iframe.style.left = '-100vw';
+  iframe.style.width = '200%';
+  iframe.style.height = '200%';
+  document.body.appendChild(iframe);
+
+  // 灏哛ectRenderer鐨勫唴瀹瑰姞杞藉埌iframe涓�
+  const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
+  iframeDoc.open();
+  iframeDoc.write(`
+    <html>
+      <head>
+        <title>Print Layout</title>
+        <style>
+          @page {
+            size: A4 landscape;
+            margin: 20mm;
+          }
+          body {
+            margin: 0;
+            padding: 0;
+          }
+          .layout-wrapper {
+            display: flex;
+            flex-direction: column;
+          }
+          .layout-container {
+            page-break-inside: avoid;
+            break-inside: avoid;
+            page-break-after: auto;
+            margin-bottom: 20mm;
+          }
+          .layout-item {
+            page-break-inside: avoid;
+            break-inside: avoid;
+          }
+        </style>
+      </head>
+      <body>
+        <div class="layout-wrapper">
+          ${rectRenderer.value.$el.outerHTML}
+        </div>
+      </body>
+    </html>
+  `);
+  iframeDoc.close();
+
+  // 璁剧疆鎵撳嵃鏍峰紡
+  const printStyle = iframeDoc.createElement('style');
+  printStyle.type = 'text/css';
+  printStyle.innerHTML = `
+    @page {
+      size: A4 landscape;
+      margin: 20mm;
+    }
+    body {
+      -webkit-print-color-adjust: exact;
+    }
+    .layout-wrapper {
+      display: flex;
+      flex-direction: column;
+    }
+    .layout-container {
+      page-break-inside: avoid;
+      break-inside: avoid;
+      page-break-after: auto;
+      margin-bottom: 20mm;
+    }
+    .layout-item {
+      page-break-inside: avoid;
+      break-inside: avoid;
+    }
+  `;
+  iframeDoc.head.appendChild(printStyle);
+
+  // 璋冩暣iframe澶у皬浠ラ�傚簲鍐呭
+  const contentWidth = rectRenderer.value.$el.offsetWidth;
+  const contentHeight = rectRenderer.value.$el.offsetHeight;
+  iframe.width = contentWidth + 'px';
+  iframe.height = contentHeight + 'px';
+
+  // 鎵ц鎵撳嵃
+  iframe.contentWindow.print();
+
+  // 娓呯悊
+  setTimeout(() => {
+    document.body.removeChild(iframe);
+  }, 100);
+};
+</script>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimize.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimize.vue
index e40b358..e5ca0e2 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimize.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimize.vue
@@ -19,13 +19,13 @@
       <el-breadcrumb :separator-icon="ArrowRight">
         <el-breadcrumb-item @click="changeRouter(1)" :class="indexFlag===1?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizeProject' }">{{'宸ョ▼淇℃伅'}}</el-breadcrumb-item>
         <el-breadcrumb-item v-show="false" @click="changeRouter(2)" :class="indexFlag===2?'indexTag':''" :to="{ path: '/main/order/createOrder' }">{{$t('order.page.createOrder')}}</el-breadcrumb-item>
-        <el-breadcrumb-item @click="changeRouter(3)" :class="indexFlag===3?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizePrint' }">鎵撳嵃
+        <el-breadcrumb-item @click="changeRouter(3)" :class="indexFlag===3?'indexTag':''" :to="{ path: '/main/glassOptimize/OptimizationRectPrint' }">鎵撳嵃
         </el-breadcrumb-item>
-        <el-breadcrumb-item @click="changeRouter(4)" :class="indexFlag===4?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizeMove' }">璋冩暣
+        <el-breadcrumb-item @click="changeRouter(4)" :class="indexFlag===4?'indexTag':''" :to="{ path: '/main/glassOptimize/Optimization' }">璋冩暣
         </el-breadcrumb-item>
-        <el-breadcrumb-item @click="changeRouter(5)" :class="indexFlag===5?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizeMove' }">鏁版帶
+        <el-breadcrumb-item @click="changeRouter(5)" :class="indexFlag===5?'indexTag':''" :to="{ path: '/main/glassOptimize/OptimizeControl' }">鏁版帶
         </el-breadcrumb-item>
-        <el-breadcrumb-item @click="changeRouter(6)" :class="indexFlag===6?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizeMove' }">璁剧疆
+        <el-breadcrumb-item @click="changeRouter(6)" :class="indexFlag===6?'indexTag':''" :to="{ path: '/main/glassOptimize/optimizeparms' }">璁剧疆
         </el-breadcrumb-item>
         <el-breadcrumb-item></el-breadcrumb-item>
       </el-breadcrumb>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
new file mode 100644
index 0000000..bc81799
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
@@ -0,0 +1,104 @@
+<template>
+    <div >
+      <RectRenderer 
+    :layoutData="layoutData" 
+    :gw="1400" 
+    :gh="1100" 
+    style="width: 1500px; height: 800px; position: relative;"
+  />
+  
+  
+    </div>
+    <button @click="submitLayouts" style="position: fixed; bottom: 20px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
+      淇濆瓨OPT
+    </button>
+  </template>
+  
+  <script setup>
+  import { ref,onMounted } from 'vue';
+  import RectRenderer from './page/RectRenderer.vue';
+  import mockLayoutData from '../../../components/pp/MockData';
+  import request from "@/utils/request";
+import { useI18n } from "vue-i18n";
+import { ElMessage } from "element-plus";
+
+const { t } = useI18n();
+ // 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 {
+    const response = await request.post('/glassOptimize/generateOpt', {
+      Layouts: layoutData.value.Layouts 
+    }, {
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      responseType: 'blob' // 浠� blob 褰㈠紡鎺ユ敹鍝嶅簲
+    });
+
+    // 澶勭悊涓嬭浇
+    const downloadUrl = window.URL.createObjectURL(response);
+    const a = document.createElement('a');
+    a.href = downloadUrl;
+    a.download = 'output.opt';
+    document.body.appendChild(a);
+    a.click();
+    document.body.removeChild(a);
+    window.URL.revokeObjectURL(downloadUrl);
+    ElMessage.success('OPT鏂囦欢涓嬭浇鎴愬姛,璇烽�夋嫨鏂囦欢璺緞');
+  } catch (error) {
+    console.error('涓嬭浇澶辫触:', error);
+    // 鏄剧ず閿欒娑堟伅缁欑敤鎴�
+    ElMessage.error('涓嬭浇澶辫触锛岃绋嶅悗鍐嶈瘯');
+  }
+};
+
+
+
+  </script>
+  
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeMove.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeMove.vue
index 6f857f6..8e5ffa4 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeMove.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeMove.vue
@@ -1,159 +1,23 @@
 <template>
-    <div style="width:100%;height:2000px;">
-        <div class="layoutJSON">
-            Displayed as <code>[x, y, w, h]</code>:
-            <div class="columns">
-              <div v-for="item in layout" :key="item.i">
+    <div >
+      <RectRenderer 
+    :layoutData="layoutData" 
+    :gw="1400" 
+    :gh="1100" 
+    style="width: 1500px; height: 800px; position: relative;"
+  />
   
-                    <b>{{item.i}}</b>: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
-                </div>
-            </div>
-        </div>
-        <hr/>
-        <input type="checkbox" v-model="draggable"/> Draggable
-        <input type="checkbox" v-model="resizable"/> Resizable
-        <input type="checkbox" v-model="responsive"/> Responsive
-        <br/>
-        <div style="width:100%;margin-top: 10px;height:100%;">
-          <grid-layout v-model:layout="layout"
-               :col-num="12"
-               :row-height="30"
-               :is-draggable="draggable"
-               :is-resizable="resizable"
-               :vertical-compact="true"
-               :use-css-transforms="true"
-  >
   
-            <grid-item v-for="item in layout"
-             :key="item.i"  
-             :static="item.static"
-             :x="item.x"
-             :y="item.y"
-             :w="item.w"
-             :h="item.h"
-             :i="item.i"
-  >
-      <span class="text">{{item.i}}</span>
-  </grid-item>
-  
-            </grid-layout>
-        </div>
     </div>
   </template>
   
-  <script>
-  import { GridLayout, GridItem } from 'vue3-grid-layout';
+  <script setup>
+  import { ref } from 'vue';
+  import RectRenderer from './page/RectRenderer.vue';
+  import mockLayoutData from '../../../components/pp/MockData';
   
-  export default {
-    components: {
-      GridLayout,
-      GridItem,
-    },
-    data() {
-        return {
-            layout: [
-                {"x":0,"y":0,"w":2,"h":2,"i":"0666*343"},
-                {"x":2,"y":0,"w":2,"h":4,"i":"1"},
-                {"x":4,"y":0,"w":2,"h":5,"i":"2"},
-                {"x":6,"y":0,"w":2,"h":3,"i":"3"},
-                {"x":8,"y":0,"w":2,"h":3,"i":"4"},
-                {"x":10,"y":0,"w":2,"h":3,"i":"5"},
-                {"x":0,"y":5,"w":2,"h":5,"i":"6"},
-                {"x":2,"y":5,"w":2,"h":5,"i":"7"},
-                {"x":4,"y":5,"w":2,"h":5,"i":"8"},
-                {"x":6,"y":4,"w":2,"h":4,"i":"9"},
-                {"x":8,"y":4,"w":2,"h":4,"i":"10"},
-                {"x":10,"y":4,"w":2,"h":4,"i":"11"},
-                {"x":0,"y":10,"w":2,"h":5,"i":"12"},
-                {"x":2,"y":10,"w":2,"h":5,"i":"13"},
-                {"x":4,"y":8,"w":2,"h":4,"i":"14"},
-                {"x":6,"y":8,"w":2,"h":4,"i":"15"},
-                {"x":8,"y":10,"w":2,"h":5,"i":"16"},
-                {"x":10,"y":4,"w":2,"h":2,"i":"17"},
-                {"x":0,"y":9,"w":2,"h":3,"i":"18"},
-                {"x":2,"y":6,"w":2,"h":2,"i":"19"}
-            ],
-            draggable: true,
-            resizable: true,
-            responsive: true,
-            index: 0
-        }
-    },
-    methods: {
-    }
-  }
+  const layoutData = ref(mockLayoutData);
+  
+  
   </script>
-  
-  <style scoped>
-  .vue-grid-layout {
-    background: #eee;
-  }
-  
-  .vue-grid-item:not(.vue-grid-placeholder) {
-    background: #ccc;
-    border: 1px solid black;
-  }
-  
-  .vue-grid-item .resizing {
-    opacity: 0.9;
-  }
-  
-  .vue-grid-item .static {
-    background: #cce;
-  }
-  
-  .vue-grid-item .text {
-    font-size: 24px;
-    text-align: center;
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    margin: auto;
-    height: 100%;
-    width: 100%;
-  }
-  
-  .vue-grid-item .no-drag {
-    height: 100%;
-    width: 100%;
-  }
-  
-  .vue-grid-item .minMax {
-    font-size: 12px;
-  }
-  
-  .vue-grid-item .add {
-    cursor: pointer;
-  }
-  
-  .vue-draggable-handle {
-    position: absolute;
-    width: 20px;
-    height: 20px;
-    top: 0;
-    left: 0;
-    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>") no-repeat;
-    background-position: bottom right;
-    padding: 0 8px 8px 0;
-    background-repeat: no-repeat;
-    background-origin: content-box;
-    box-sizing: border-box;
-    cursor: pointer;
-  }
-  
-  .layoutJSON {
-    background: #ddd;
-    border: 1px solid black;
-    margin-top: 10px;
-    padding: 10px;
-  }
-  
-  .columns {
-    -moz-columns: 120px;
-    -webkit-columns: 120px;
-    columns: 120px;
-  }
-  
-  </style>
\ No newline at end of file
+  
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue
new file mode 100644
index 0000000..0e3f3df
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue
@@ -0,0 +1,522 @@
+<script setup>
+import { ref, reactive, onMounted, watch } from 'vue';
+import { useI18n } from "vue-i18n";
+import { ElMessage } from "element-plus";
+import request from "@/utils/request";
+import useUserInfoStore from "@/stores/userInfo";
+
+const { t } = useI18n();
+const userStore = useUserInfoStore()
+const username = userStore.user.userName
+
+const currentComponent = ref('optimization');
+
+const settings = reactive({
+  optimization: {},
+  display: {},
+  cutting: {},
+  server: {},
+  tempering: {}
+});
+
+const selectComponent = (component) => {
+  currentComponent.value = component;
+};
+
+const saveToDatabase = () => {
+  request.post(`/glassOptimize/optimizeParms`, settings).then((res) => {
+    if (res.code == 200 && res.data === true) {
+      ElMessage.success(t('basicData.msg.saveSuccess'))
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  });
+};
+
+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);
+      Object.assign(settings, parsedData);
+      console.log('璁剧疆宸叉洿鏂�:', settings);
+    } else {
+      console.error('璇锋眰澶辫触锛岀姸鎬佺爜:', response.code);
+    }
+  } catch (error) {
+    console.error('璇锋眰鍙戠敓閿欒:', error);
+  }
+};
+
+onMounted(() => {
+  fetchSettings(username);
+});
+
+// 鍙傛暟鏄犲皠琛紝鐢ㄤ簬灏嗚嫳鏂囧弬鏁板悕鏄犲皠涓轰腑鏂囧悕绉板拰绫诲瀷
+const paramMapping = {
+  yShapeJoinOptimization: { name: '寮傚舰鎷兼帴浼樺寲', type: 'checkbox' },
+  autoMiddleEmptyPairing: { name: '鑷姩涓┖閰嶅', type: 'checkbox' },
+  smallPieceRotationProhibited: { name: '灏忕墖绂佹鏃嬭浆', type: 'checkbox' },
+  maxFramesOnSite: { name: '鐜板満鏈�澶у彲鏀炬灦瀛愭暟閲�', type: 'text' },
+  bendEdgeDistance: { name: '鎺拌竟璺�(mm)', type: 'text' },
+  positiveTolerance: { name: '姝e叕宸�(mm)', type: 'text' },
+  negativeTolerance: { name: '璐熷叕宸�(mm)', type: 'text' },
+  cutterOriginPosition: { name: '鍒囧壊鏈哄師鐐逛綅缃�', type: 'select' },
+  uniformShapeEdgeTrimAmount: { name: '缁熶竴璁剧疆寮傚舰淇竟閲�', type: 'text' },
+  edgeTrimMode: { name: '淇竟妯″紡', type: 'select' },
+  parallelOptimizationChannels: { name: '骞惰浼樺寲鐨勯�氶亾鏁伴噺', type: 'text' },
+  optimizationIterations: { name: '閲嶅浼樺寲娆℃暟', type: 'text' },
+  finishedProductGrindingAmount: { name: '鎴愬搧榛樿纾ㄩ噺', type: 'text' },
+  rawPieceEdgeTrimAmount: { name: '鍘熺墖榛樿淇竟閲�', type: 'text' },
+  finishedSinglePieceBelowGrindingAmount: { name: '鎴愬搧鍗曠墖灏忎簬澶氬皯鏃剁(閲忎负', type: 'text' }
+};
+
+// 鍔ㄦ�佺敓鎴愬弬鏁板垪琛�
+const parameterList = ref(Object.keys(paramMapping).map(key => ({
+  key,
+  ...paramMapping[key]
+})));
+</script>
+
+<template>
+  <div class="settings-container">
+    <div class="sidebar">
+      <div
+        @click="selectComponent('optimization')"
+        :class="{ active: currentComponent === 'optimization' }"
+        class="sidebar-item"
+      >
+        <div class="sidebar-header">浼樺寲鍙傛暟</div>
+        <div class="sidebar-content">浼樺寲鍙傛暟璁剧疆</div>
+      </div>
+
+      <div
+        @click="selectComponent('display')"
+        :class="{ active: currentComponent === 'display' }"
+        class="sidebar-item"
+      >
+        <div class="sidebar-header">鐗堝浘鏄剧ず</div>
+        <div class="sidebar-content">鐗堝浘鏄剧ず璁剧疆</div>
+      </div>
+
+      <div
+        @click="selectComponent('cutting')"
+        :class="{ active: currentComponent === 'cutting' }"
+        class="sidebar-item"
+      >
+        <div class="sidebar-header">鍒�璺�</div>
+        <div class="sidebar-content">鍒�璺缃�</div>
+      </div>
+
+      <div
+        @click="selectComponent('server')"
+        :class="{ active: currentComponent === 'server' }"
+        class="sidebar-item"
+      >
+        <div class="sidebar-header">杈撳嚭</div>
+        <div class="sidebar-content">缁撴灉杈撳嚭璁剧疆</div>
+      </div>
+
+      <div
+        @click="selectComponent('tempering')"
+        :class="{ active: currentComponent === 'tempering' }"
+        class="sidebar-item"
+      >
+        <div class="sidebar-header">閽㈠寲</div>
+        <div class="sidebar-content">閽㈠寲璁剧疆</div>
+      </div>
+    </div>
+
+    <div class="main-content">
+      <template v-if="currentComponent === 'display'">
+        <div class="display-settings">
+          <h2>鐗堝浘鏄剧ず璁剧疆</h2>
+          <div class="form-group">
+            <label>鐭╁舰鎴愬搧鏄剧ず棰滆壊</label>
+            <input type="color" v-model="settings.display.themeColor" />
+          </div>
+          <div class="form-group">
+            <label>鎴愬搧灏哄鍖呭惈纾ㄨ竟閲�</label>
+            <input type="checkbox" v-model="settings.display.includeProductEdge" />
+          </div>
+          <div class="form-group">
+            <label>寮傚舰灏哄鍖呭惈纾ㄨ竟閲�</label>
+            <input type="checkbox" v-model="settings.display.includeIrregularEdge" />
+          </div>
+          <div class="form-group">
+            <label>鎸夋灦鍙峰悎骞剁増鍥�</label>
+            <input type="checkbox" v-model="settings.display.mergeByFrameNumber" />
+          </div>
+          <div style="border: 1px solid #d2d0d0; margin-top: 20px;">
+            <div style="background-color: #D5EAFF;">灏忕墖淇℃伅</div>
+            <div class="form-group">
+              <label>鏋跺彿</label>
+              <input type="checkbox" v-model="settings.display.frameNumber" />
+            </div>
+            <div class="form-group">
+              <label>璁㈠崟缂栧彿</label>
+              <input type="checkbox" v-model="settings.display.orderNumber" />
+            </div>
+            <div class="form-group">
+              <label>浜у搧鍚嶇О</label>
+              <input type="checkbox" v-model="settings.display.productName" />
+            </div>
+            <div class="form-group">
+              <label>鍔犲伐淇℃伅</label>
+              <input type="checkbox" v-model="settings.display.processingInfo" />
+            </div>
+            <div class="form-group">
+              <label>澶囨敞</label>
+              <input type="checkbox" v-model="settings.display.remarks" />
+            </div>
+            <div class="form-group">
+              <label>妤煎眰缂栧彿</label>
+              <input type="checkbox" v-model="settings.display.floorNumber" />
+            </div>
+            <div class="form-group">
+              <label>杈归暱</label>
+              <input type="checkbox" v-model="settings.display.edgeLength" />
+            </div>
+            <div class="form-group">
+              <label>宸ヨ壓</label>
+              <input type="checkbox" v-model="settings.display.manufacturingProcess" />
+            </div>
+            <div class="form-group">
+              <label>ID</label>
+              <input type="checkbox" v-model="settings.display.identifier" />
+            </div>
+          </div>
+        </div>
+      </template>
+
+      <template v-else-if="currentComponent === 'cutting'">
+        <div class="display-settings">
+          <h2>鍒�璺缃�</h2>
+          <div class="form-group">
+            <label>姝e悜鍒囧壊</label>
+            <input type="checkbox" v-model="settings.cutting.cutting_direction" />
+          </div>
+          <div class="form-group">
+            <label>鏄剧ず鍒囧壊鏂瑰悜</label>
+            <input type="checkbox" v-model="settings.cutting.show_cutting_path" />
+          </div>
+          <div class="form-group">
+            <label>寮哄埗寮х嚎鍜岀洿绾胯繛缁垏鍓�</label>
+            <input type="checkbox" v-model="settings.cutting.force_continuous_cutting" />
+          </div>
+          <div class="form-group">
+            <label>瀛旀礊鏈�灏忓垏鍓插崐寰�</label>
+            <input type="number" v-model="settings.cutting.min_radius" />
+          </div>
+          <div class="form-group">
+            <label>涓ゆ潯骞宠绾挎渶灏忛棿闅�</label>
+            <input type="number" v-model="settings.cutting.min_parallel_offset" />
+          </div>
+          <div class="form-group">
+            <label>T鍨嬮��缂�</label>
+            <input type="number" v-model="settings.cutting.t_shaped_recess" />
+          </div>
+          <div class="form-group">
+            <label>涓嬪垁闂磋窛</label>
+            <input type="number" v-model="settings.cutting.down_cut_spacing" />
+          </div>
+          <div class="form-group">
+            <label>鎶垁閫�缂�</label>
+            <input type="number" v-model="settings.cutting.lift_retract" />
+          </div>
+        </div>
+      </template>
+
+      <template v-else-if="currentComponent === 'server'">
+        <div class="display-settings">
+          <h2>缁撴灉杈撳嚭璁剧疆</h2>
+          <div class="form-group">
+            <label>宸ョ▼鏂囦欢淇濆瓨璺緞</label>
+            <input type="text" v-model="settings.server.output_format" />
+          </div>
+          <div class="form-group">
+            <label>鍒囧壊浠g爜淇濆瓨璺緞</label>
+            <input type="text" v-model="settings.server.cutting_code_save_path" />
+          </div>
+          <div class="form-group">
+            <label>淇濆瓨鏂囦欢鍚庢墦寮�鎵�鍦ㄦ枃浠跺す</label>
+            <input type="text" v-model="settings.server.open_folder_after_save" />
+          </div>
+          <div class="form-group">
+            <label>G浠g爜鏂囦欢鏍煎紡</label>
+            <input type="text" v-model="settings.server.g_code_file_format" />
+          </div>
+          <div class="form-group">
+            <label>TRF鏂囦欢淇濆瓨璺緞</label>
+            <input type="text" v-model="settings.server.trf_file_save_path" />
+          </div>
+          <div class="form-group">
+            <label>淇濈壒缃楁枃浠朵繚瀛樿矾寰�</label>
+            <input type="text" v-model="settings.server.btl_file_save_path" />
+          </div>
+          <div class="form-group">
+            <label>OPTIMA鏂囦欢淇濆瓨璺緞</label>
+            <input type="text" v-model="settings.server.optima_file_save_path" />
+          </div>
+          <div class="form-group">
+            <label>浼樺寲娣卞害闄愬埗鍚敤</label>
+            <input type="text" v-model="settings.server.optimization_depth_limit_enable" />
+          </div>
+          <div class="form-group">
+            <label>鍘熺墖鍒囨潗鐜囪绠�</label>
+            <input type="text" v-model="settings.server.original_sheet_material_calculation" />
+          </div>
+        </div>
+      </template>
+
+      <template v-else-if="currentComponent === 'tempering'">
+        <div class="display-settings">
+          <h2>閽㈠寲璁剧疆</h2>
+          <div class="form-group">
+            <label>鐐夐暱(mm)</label>
+            <input type="number" v-model="settings.tempering.furnaceLength" step="1" />
+          </div>
+          <div class="form-group">
+            <label>鐐夊(mm)</label>
+            <input type="number" v-model="settings.tempering.furnaceWidth" step="1" />
+          </div>
+          <div class="form-group">
+            <label>鏈�澶ц杞界巼(%)</label>
+            <input type="number" v-model="settings.tempering.maxLoadingRate" step="1" />
+          </div>
+          <div class="form-group">
+            <label>娣蜂贡绋嬪害(%)</label>
+            <input type="number" v-model="settings.tempering.chaosLevel" step="1" />
+          </div>
+          <div class="form-group">
+            <label>閽㈠寲鍔犵儹鏃堕棿(绉�)</label>
+            <input type="number" v-model="settings.tempering.temperingTime" step="1" />
+          </div>
+          <div class="form-group">
+            <label>榛樿閽㈠寲鎺ㄨ崘妯″紡</label>
+            <select v-model="settings.tempering.defaultTemperingMode">
+              <option value="auto">鑷姩鎺ㄨ崘</option>
+              <option value="manual">鎵嬪姩閫夋嫨</option>
+            </select>
+          </div>
+          <div class="form-group">
+            <label>鏈�澶ч潰绉缃�(銕�)</label>
+            <input type="number" v-model="settings.tempering.maxArea" step="0.1" />
+          </div>
+          <div class="form-group">
+            <label>鏈�澶х墖鏁拌缃�(鐗�)</label>
+            <input type="number" v-model="settings.tempering.maxPieceCount" step="1" />
+          </div>
+          <div class="form-group">
+            <label>X杞撮粯璁ら棿闅�(mm)</label>
+            <input type="number" v-model="settings.tempering.xAxisInterval" step="1" />
+          </div>
+          <div class="form-group">
+            <label>Y杞撮粯璁ら棿闅�(mm)</label>
+            <input type="number" v-model="settings.tempering.yAxisInterval" step="1" />
+          </div>
+        </div>
+      </template>
+
+      <template v-else>
+        <div class="display-settings">
+          <h2>浼樺寲鍙傛暟璁剧疆</h2>
+          <div class="parameter-list">
+            <div 
+              class="form-group" 
+              v-for="(param, index) in parameterList" 
+              :key="index"
+            >
+              <label class="parameter-name">{{ param.name }}</label>
+              <div class="parameter-control">
+                <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' }"
+                >
+                <select 
+                  v-else-if="param.type === 'select'" 
+                  :name="param.key" 
+                  class="cs"
+                >
+                  <option 
+                    v-for="option in getOptions(param.key)" 
+                    :key="option.value" 
+                    :selected="option.value === settings.optimization[param.key]"
+                  >
+                    {{ option.label }}
+                  </option>
+                </select>
+                <input 
+                  v-else 
+                  :type="param.type || 'text'" 
+                  :name="param.key" 
+                  class="cs" 
+                  v-model="settings.optimization[param.key]"
+                >
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
+    </div>
+
+    <button class="button" @click="saveToDatabase">淇濆瓨</button>
+  </div>
+</template>
+
+<style>
+.settings-container {
+  display: flex;
+  gap: 20px;
+  padding: 20px;
+  background-color: #f0f2f5;
+}
+
+.sidebar {
+  width: 300px;
+  background-color: white;
+  padding: 15px;
+  border-radius: 8px;
+  box-shadow: 0 2px 4 rgba(0, 0, 0, 0.1);
+}
+
+.sidebar-item {
+  cursor: pointer;
+  padding: 10px;
+  margin-bottom: 5px;
+  border-radius: 6px;
+  transition: all 0.3s ease;
+}
+
+.sidebar-item.active {
+  background-color: #f8f9fa;
+  transform: translateX(5px);
+}
+
+.sidebar-header {
+  font-size: 12px;
+  color: #666;
+  margin-bottom: 5px;
+}
+
+.sidebar-content {
+  font-size: 14px;
+  color:#333;
+}
+
+.main-content {
+  flex-grow: 1;
+  padding: 20px;
+}
+
+button {
+  padding: 10px 20px;
+  background-color: #5cadfe;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+@media (max-width: 768px) {
+  .settings-container {
+    flex-direction: column;
+  }
+
+  .sidebar {
+    order: -1;
+  }
+
+  .main-content {
+    margin-top: 20px;
+  }
+}
+
+.form-group {
+  margin-bottom: 15px;
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.form-group label {
+  font-weight: normal;
+  min-width: 120px;
+}
+
+.form-group input,
+.form-group select {
+  flex: 1;
+  padding: 5px;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+}
+
+.form-group select {
+  cursor: pointer;
+}
+
+.display-settings {
+  background-color: white;
+  padding: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.parameter-list {
+  display: flex;
+  flex-direction: column;
+  gap: 0px;
+}
+
+.parameter-item {
+  display: flex;
+  align-items: center;
+  gap: 0px;
+}
+
+.parameter-name {
+  font-weight: normal;
+  min-width: 120px;
+}
+
+.parameter-control {
+  flex: 1;
+}
+
+.button {
+  text-align: center;
+  width: 70px;
+  height: 28px;
+  border: none;
+  background-color: #5CADFE;
+  box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0), 0 6px 5px 0 rgba(0, 0, 0, 0.19);
+  margin-left: 500px;
+}
+</style>
+
+<script>
+// 杈呭姪鍑芥暟锛屾牴鎹弬鏁伴敭鑾峰彇閫夐」
+function getOptions(key) {
+  const optionsMapping = {
+    cutterOriginPosition: [
+      { value: 'topLeft', label: '宸︿笂瑙�' },
+      { value: 'bottomLeft', label: '宸︿笅瑙�' },
+      { value: 'topRight', label: '鍙充笂瑙�' },
+      { value: 'bottomRight', label: '鍙充笅瑙�' }
+    ],
+    edgeTrimMode: [
+      { value: 'intelligent', label: '鏅鸿兘淇竟' },
+      { value: 'complete', label: '瀹屽叏淇竟' }
+    ]
+  };
+  return optionsMapping[key] || [];
+}
+</script>
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
new file mode 100644
index 0000000..ea5170a
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -0,0 +1,934 @@
+<template>
+  <div style="display: flex; height: 100vh;">
+    <!-- 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.width }} 脳 {{ layout.height }} 脳 {{ layout.SameCount }}
+      </div>
+    </div>
+
+    <!-- Main Layout Panel -->
+    <div ref="layoutPanel" :class="panelClass" :style="panelStyle">
+      <div
+        v-for="(layout, layoutIndex) in layouts"
+        :key="layoutIndex"
+        class="layout-wrapper"
+        :style="{ display: selectedLayoutIndex === layoutIndex ? 'block' : 'none', top: '-150px' }"
+      >
+        <!-- Layout Info Label -->
+        <div class="layout-info" :style="layoutInfoStyle(layoutIndex)">
+          {{ getCurrentRectInfo(layoutIndex) }}
+        </div>
+
+        <!-- Layout Container -->
+        <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
+          <!-- 鐏拌壊鐭╁舰 -->
+          <div
+            v-for="(rect, rectIndex) in layout.rects.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)"
+          />
+
+          <!-- 钃濊壊鐭╁舰 -->
+          <div
+            v-for="(rect, rectIndex) in layout.rects.filter(r => !r.isRemain)"
+            :key="`blue-${rectIndex}`"
+            :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
+            class="layout-rect"
+            :style="rectStyle(rect, layoutIndex)"
+            @contextmenu.prevent="handleRectRightClick(layoutIndex, rectIndex)"
+            @mousedown="handleRectDragStart(layoutIndex, rectIndex)"
+            @mousemove="handleRectDragging"
+            @mouseup="handleRectDragEnd"
+            @mouseleave="handleRectDragEnd"
+          >
+            <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>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 鎻愪氦鎸夐挳 -->
+    <button @click="submitLayouts" style="position: fixed; bottom: 20px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
+      淇濆瓨璋冩暣
+    </button>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted } from 'vue';
+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 },
+  gh: { type: Number, default: 1000 },
+  style: { type: String, default: 'width:1000px;height:600px;display:block;background:gray' }
+});
+
+const emit = defineEmits(['rectClicked']);
+const layoutPanel = ref(null);
+const rectsElements = ref({});
+const focusIndex = ref(null);
+const layouts = ref([]);
+const panelClass = ref('');
+const panelStyle = ref(props.style);
+const rectClass = ref('layout-rect');
+const selectedLayoutIndex = ref(0);
+const currentRect = ref(null);
+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 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);
+    });
+  });
+  const savedProjectNo = localStorage.getItem('projectNo');
+  const processId = savedProjectNo;
+  const Layouts = layouts.value;
+  request.post(`/glassOptimize/updateOptimizeResult/${processId}`, JSON.stringify({ Layouts }), {
+    headers: {
+      'Content-Type': 'application/json'
+    }
+  }).then((res) => {
+    if (res.code == 200 && res.data === true) {
+      ElMessage.success(t('basicData.msg.saveSuccess'));
+    } else {
+      ElMessage.warning(res.msg);
+    }
+  });
+};
+
+
+//鑾峰彇浼樺寲璁剧疆
+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('璇疯緭鍏ユ垚鍝佺殑瀹藉害鍜岄珮搴�', '娣诲姞鎴愬搧', {
+    inputType: 'text',
+    inputValidator: (value) => {
+      const values = value.split(',').map(v => v.trim());
+      if (values.length !== 2) {
+        return '璇疯緭鍏ヤ袱涓暟瀛楋紝鐢ㄩ�楀彿鍒嗛殧';
+      }
+      const [width, height] = values;
+      if (isNaN(width) || isNaN(height)) {
+        return '璇疯緭鍏ユ湁鏁堢殑鏁板瓧';
+      }
+      if (width <= 0 || height <= 0) {
+        return '瀹藉害鍜岄珮搴﹀繀椤诲ぇ浜�0';
+      }
+      return true;
+    },
+    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(() => {
+    // 鐢ㄦ埛鍙栨秷
+  });
+};
+
+const addNewRect = (layoutIndex, newRect) => {
+  const layout = layouts.value[layoutIndex];
+  layout.rects.push(newRect);
+  adjustGrayRectangles(layoutIndex);
+};
+
+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,
+    (props.gh - 100) / layout.height
+  );
+  return {
+    position: 'absolute',
+    left: `${(props.gw - layout.width * scale) / 2}px`,
+    top: `${(props.gh - layout.height * scale) / 2}px`,
+    width: `${layout.width * scale}px`,
+    height: `${layout.height * scale}px`,
+    overflow: 'visible',
+    border: '1px solid #ccc',
+    background: '#fff'
+  };
+};
+
+const layoutInfoStyle = (layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const scale = Math.min(
+    (props.gw - 100) / layout.width,
+    (props.gh - 100) / layout.height
+  );
+  return {
+    position: 'absolute',
+    left: `${(props.gw - layout.width * scale) / 2}px`,
+    top: `${(props.gh - layout.height * scale) / 2 - 45}px`,
+    background: 'none',
+    textAlign: 'center',
+    zIndex: 1000
+  };
+};
+
+const rectStyle = (rect, layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const scale = Math.min(
+    (props.gw - 100) / layout.width,
+    (props.gh - 100) / layout.height
+  );
+  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' : themeColor.value,
+    border: '1px solid #000',
+    cursor: 'pointer',
+    draggable: !rect.isRemain,
+    zIndex: rect.isRemain ? 1 : 2
+  };
+};
+
+const handleRectClick = (layoutIndex, rectIndex) => {
+  focusIndex.value = { layoutIndex, rectIndex };
+  emit('rectClicked', layoutIndex, rectIndex);
+};
+
+const handleRectRightClick = (layoutIndex, rectIndex) => {
+  const rect = layouts.value[layoutIndex].rects[rectIndex];
+  if (rect.isRemain) return;
+
+  const contextMenu = document.createElement('div');
+  contextMenu.className = 'context-menu';
+  contextMenu.style.position = 'absolute';
+  contextMenu.style.left = `${event.clientX}px`;
+  contextMenu.style.top = `${event.clientY}px`;
+  contextMenu.style.backgroundColor = '#fff';
+  contextMenu.style.border = '1px solid #ccc';
+  contextMenu.style.padding = '5px';
+  contextMenu.style.zIndex = 1001;
+
+  const rotateItem = document.createElement('div');
+  rotateItem.textContent = '鏃嬭浆';
+  rotateItem.style.cursor = 'pointer';
+  rotateItem.addEventListener('click', () => {
+    rotateRect(layoutIndex, rectIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveUpAndRotateItem = document.createElement('div');
+  moveUpAndRotateItem.textContent = '鍚戜笂绉诲姩骞舵棆杞�';
+  moveUpAndRotateItem.style.cursor = 'pointer';
+  moveUpAndRotateItem.addEventListener('click', () => {
+    moveRectAndRotate(layoutIndex, rectIndex, 'up');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveDownAndRotateItem = document.createElement('div');
+  moveDownAndRotateItem.textContent = '鍚戜笅绉诲姩骞舵棆杞�';
+  moveDownAndRotateItem.style.cursor = 'pointer';
+  moveDownAndRotateItem.addEventListener('click', () => {
+    moveRectAndRotate(layoutIndex, rectIndex, 'down');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveLeftAndRotateItem = document.createElement('div');
+  moveLeftAndRotateItem.textContent = '鍚戝乏绉诲姩骞舵棆杞�';
+  moveLeftAndRotateItem.style.cursor = 'pointer';
+  moveLeftAndRotateItem.addEventListener('click', () => {
+    moveRectAndRotate(layoutIndex, rectIndex, 'left');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveRightAndRotateItem = document.createElement('div');
+  moveRightAndRotateItem.textContent = '鍚戝彸绉诲姩骞舵棆杞�';
+  moveRightAndRotateItem.style.cursor = 'pointer';
+  moveRightAndRotateItem.addEventListener('click', () => {
+    moveRectAndRotate(layoutIndex, rectIndex, 'right');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveUpItem = document.createElement('div');
+  moveUpItem.textContent = '鍚戜笂绉诲姩';
+  moveUpItem.style.cursor = 'pointer';
+  moveUpItem.addEventListener('click', () => {
+    moveRect(layoutIndex, rectIndex, 'up');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveDownItem = document.createElement('div');
+  moveDownItem.textContent = '鍚戜笅绉诲姩';
+  moveDownItem.style.cursor = 'pointer';
+  moveDownItem.addEventListener('click', () => {
+    moveRect(layoutIndex, rectIndex, 'down');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveLeftItem = document.createElement('div');
+  moveLeftItem.textContent = '鍚戝乏绉诲姩';
+  moveLeftItem.style.cursor = 'pointer';
+  moveLeftItem.addEventListener('click', () => {
+    moveRect(layoutIndex, rectIndex, 'left');
+    document.body.removeChild(contextMenu);
+  });
+
+  const moveRightItem = document.createElement('div');
+  moveRightItem.textContent = '鍚戝彸绉诲姩';
+  moveRightItem.style.cursor = 'pointer';
+  moveRightItem.addEventListener('click', () => {
+    moveRect(layoutIndex, rectIndex, 'right');
+    document.body.removeChild(contextMenu);
+  });
+
+  const deleteItem = document.createElement('div');
+  deleteItem.textContent = '鍒犻櫎';
+  deleteItem.style.cursor = 'pointer';
+  deleteItem.addEventListener('click', () => {
+    deleteRect(layoutIndex, rectIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  const addItem = document.createElement('div');
+  addItem.textContent = '娣诲姞鎴愬搧';
+  addItem.style.cursor = 'pointer';
+  addItem.addEventListener('click', () => {
+    showAddDialog(layoutIndex, rectIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  contextMenu.appendChild(rotateItem);
+  contextMenu.appendChild(moveUpAndRotateItem);
+  contextMenu.appendChild(moveDownAndRotateItem);
+  contextMenu.appendChild(moveLeftAndRotateItem);
+  contextMenu.appendChild(moveRightAndRotateItem);
+  contextMenu.appendChild(moveUpItem);
+  contextMenu.appendChild(moveDownItem);
+  contextMenu.appendChild(moveLeftItem);
+  contextMenu.appendChild(moveRightItem);
+  contextMenu.appendChild(deleteItem);
+  contextMenu.appendChild(addItem);
+
+  document.body.appendChild(contextMenu);
+};
+
+const handleGrayRectRightClick = (layoutIndex, rectIndex) => {
+  const rect = layouts.value[layoutIndex].rects[rectIndex];
+  if (!rect.isRemain) return;
+
+  const contextMenu = document.createElement('div');
+  contextMenu.className = 'context-menu';
+  contextMenu.style.position = 'absolute';
+  contextMenu.style.left = `${event.clientX}px`;
+  contextMenu.style.top = `${event.clientY}px`;
+  contextMenu.style.backgroundColor = '#fff';
+  contextMenu.style.border = '1px solid #ccc';
+  contextMenu.style.padding = '5px';
+  contextMenu.style.zIndex = 1001;
+
+  const addItem = document.createElement('div');
+  addItem.textContent = '娣诲姞鎴愬搧';
+  addItem.style.cursor = 'pointer';
+  addItem.addEventListener('click', () => {
+    showAddDialog(layoutIndex, rectIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  contextMenu.appendChild(addItem);
+
+  document.body.appendChild(contextMenu);
+};
+
+const handleRectDragStart = (layoutIndex, rectIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const rect = layout.rects[rectIndex];
+  if (rect.isRemain) return;
+
+  dragging.value = true;
+  dragRect.value = { layoutIndex, rectIndex };
+  dragStartPos.value = {
+    x: event.clientX,
+    y: event.clientY
+  };
+};
+
+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 rect = layout.rects[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 };
+  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) {
+    isValidMove = false;
+  }
+
+  if (isValidMove) {
+    rect.x = newRect.x;
+    rect.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 rect = layouts.value[layoutIndex].rects[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);
+
+    // 鍙皟鏁翠綅缃榻愶紝涓嶈皟鏁村ぇ灏�
+    adjustAlignmentPosition(layoutIndex, rectIndex);
+
+    // 璋冩暣鐏拌壊鐭╁舰
+    adjustGrayRectangles(layoutIndex);
+  }
+
+  dragging.value = false;
+  dragRect.value = null;
+};
+
+const adjustAlignmentPosition = (layoutIndex, rectIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const rect = layout.rects[rectIndex];
+  const otherRects = layout.rects.filter((r, i) => i !== rectIndex);
+
+  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) {
+      // 涓嶈皟鏁村搴�
+    }
+    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) {
+      // 涓嶈皟鏁撮珮搴�
+    }
+  });
+};
+
+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;
+  });
+
+  if (grayRects.length === 0) return;
+
+  merged.push({ ...grayRects[0] });
+
+  for (let i = 1; i < grayRects.length; i++) {
+    const last = merged[merged.length - 1];
+    const current = grayRects[i];
+
+    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 && 
+               current.w === last.w) {
+      last.h += current.h;
+      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 {
+      merged.push({ 
+        x: Math.round(current.x),
+        y: Math.round(current.y),
+        w: Math.round(current.w),
+        h: Math.round(current.h),
+        isRemain: true
+      });
+    }
+  }
+
+  const nonGray = rects.filter(r => !r.isRemain);
+  rects.splice(0, rects.length, ...nonGray, ...merged);
+};
+
+const adjustGrayRectangles = (layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const rects = layout.rects;
+  const nonGrayRects = rects.filter(rect => !rect.isRemain);
+
+  const remainingAreas = calculateRemainingAreas(layout.width, layout.height, nonGrayRects);
+
+  const currentGrayRects = rects.filter(r => r.isRemain);
+  currentGrayRects.forEach((_, index) => {
+    if (index >= remainingAreas.length) {
+      rects.splice(index, 1);
+    }
+  });
+
+  remainingAreas.forEach((area, index) => {
+    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);
+    } else {
+      rects.push({
+        x: Math.round(area.x),
+        y: Math.round(area.y),
+        w: Math.round(area.w),
+        h: Math.round(area.h),
+        isRemain: true
+      });
+    }
+  });
+
+  mergeAdjacentGrayRects(rects);
+};
+
+const rotateRect = (layoutIndex, rectIndex) => {
+  const layout = layouts.value[layoutIndex];
+  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;
+    }
+  });
+
+  // 妫�鏌ユ槸鍚﹁秴鍑哄竷灞�杈圭晫
+  if (rect.x + rect.w > layout.width || rect.y + rect.h > layout.height) {
+    isValidRotation = false;
+  }
+
+  if (isValidRotation) {
+    adjustGrayRectangles(layoutIndex);
+  } else {
+    // 鎭㈠鍘熺姸
+    rect.w = originalState.w;
+    rect.h = originalState.h;
+    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 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;
+    ElMessage.warning('鏃犳硶鏃嬭浆锛屾病鏈夎冻澶熺殑绌洪棿');
+    return;
+  }
+
+  // 璋冩暣鐏拌壊鐭╁舰
+  adjustGrayRectangles(layoutIndex);
+
+  // 绉诲姩鐭╁舰
+  moveRect(layoutIndex, rectIndex, direction);
+};
+
+const moveRect = (layoutIndex, rectIndex, direction) => {
+  const layout = layouts.value[layoutIndex];
+  const rect = layout.rects[rectIndex];
+  const originalState = { ...rect };
+
+  // 璁$畻鍓╀綑绌洪棿
+  const remainingAreas = calculateRemainingAreas(layout.width, layout.height, layout.rects.filter(r => !r.isRemain));
+  
+  // 鏍规嵁鏂瑰悜璁$畻鍙Щ鍔ㄧ殑鏈�澶ф闀�
+  let maxStep = 0;
+  switch (direction) {
+    case 'up':
+      maxStep = rect.y;
+      break;
+    case 'down':
+      maxStep = layout.height - (rect.y + rect.h);
+      break;
+    case 'left':
+      maxStep = rect.x;
+      break;
+    case 'right':
+      maxStep = layout.width - (rect.x + rect.w);
+      break;
+  }
+
+  // 绉诲姩姝ラ暱锛屾牴鎹墿浣欑┖闂村姩鎬佽皟鏁�
+  const stepSize = maxStep;
+  const actualStep = Math.min(maxStep, stepSize);
+
+  // 绉诲姩鐭╁舰
+  switch (direction) {
+    case 'up':
+      rect.y -= actualStep;
+      break;
+    case 'down':
+      rect.y += actualStep;
+      break;
+    case 'left':
+      rect.x -= actualStep;
+      break;
+    case 'right':
+      rect.x +=actualStep;
+      break;
+  }
+
+  // 妫�鏌ユ槸鍚︿笌鍏朵粬钃濊壊鐭╁舰閲嶅彔
+  const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
+  let isValidMove = true;
+
+  otherRects.forEach(otherRect => {
+    if (checkOverlap(rect, otherRect)) {
+      isValidMove = false;
+    }
+  });
+
+  // 妫�鏌ユ槸鍚﹁秴鍑哄竷灞�杈圭晫
+  if (rect.x < 0 || rect.y < 0 ||
+      rect.x + rect.w > layout.width ||
+      rect.y + rect.h > layout.height) {
+    isValidMove = false;
+  }
+
+  if (isValidMove) {
+    adjustGrayRectangles(layoutIndex);
+  } else {
+    // 鎭㈠鍘熺姸
+    rect.x = originalState.x;
+    rect.y = originalState.y;
+    ElMessage.warning('鏃犳硶绉诲姩锛屽瓨鍦ㄩ噸鍙犳垨瓒呭嚭杈圭晫');
+  }
+};
+
+const deleteRect = (layoutIndex, rectIndex) => {
+  const layout = layouts.value[layoutIndex];
+  layout.rects.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);
+};
+
+const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
+  let remaining = [{ x: 0, y: 0, w: totalWidth, h: totalHeight }];
+  obstacles.forEach(rect => {
+    remaining = cutRemainingAreas(remaining, rect);
+  });
+  return remaining;
+};
+
+const cutRemainingAreas = (remainingAreas, obstacle) => {
+  const newRemaining = [];
+  remainingAreas.forEach(area => {
+    if (checkOverlap(area, obstacle)) {
+      if (obstacle.x > area.x) {
+        newRemaining.push({
+          x: area.x,
+          y: area.y,
+          w: obstacle.x - area.x,
+          h: area.h
+        });
+      }
+      if (obstacle.x + obstacle.w < area.x + area.w) {
+        newRemaining.push({
+          x: obstacle.x + obstacle.w,
+          y: area.y,
+          w: area.w - (obstacle.x + obstacle.w - area.x),
+          h: area.h
+        });
+      }
+      if (obstacle.y > area.y) {
+        newRemaining.push({
+          x: area.x,
+          y: area.y,
+          w: area.w,
+          h: obstacle.y - area.y
+        });
+      }
+      if (obstacle.y + obstacle.h < area.y + area.h) {
+        newRemaining.push({
+          x: area.x,
+          y: obstacle.y + obstacle.h,
+          w: area.w,
+          h: area.h - (obstacle.y + obstacle.h - area.y)
+        });
+      }
+    } else {
+      newRemaining.push(area);
+    }
+  });
+  return newRemaining;
+};
+
+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 percentage = ((rect.w / layout.width) * 100).toFixed(1) + '%';
+  return `${currentRectIndex}/${totalRects} ${width}脳${height} 脳1 ${percentage}`;
+};
+
+const selectLayout = (layoutIndex) => {
+  selectedLayoutIndex.value = layoutIndex;
+};
+
+const updateLayout = () => {
+  if (!layoutPanel.value) return;
+  layouts.value = props.layoutData.Layouts;
+};
+
+
+let clickEventListener = null;
+onMounted(() => {
+  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>
+
+<style scoped>
+.layout-wrapper {
+  position: relative;
+  margin-top: 50px;
+}
+
+.layout-rect {
+  user-select: none;
+}
+
+.layout-container {
+  position: relative;
+  overflow: visible;
+}
+
+.layout-info {
+  color: #444;
+  font-size: 12px;
+  background-color: #ffffff;
+  padding: 5px 10px;
+  border-radius: 3px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  font-weight: bold;
+}
+
+.rect-content {
+  display: grid;
+  grid-template-columns: 1fr;
+  grid-template-rows: 1fr;
+  padding: 5px;
+}
+
+.size {
+  grid-row: 1;
+  grid-column: 1;
+  color: #444;
+  font-size: 12px;
+}
+
+.jia-hao .liuchengka {
+  grid-row: 2;
+  grid-column: 1;
+  margin: auto;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.sidebar-item {
+  padding: 10px;
+  cursor: pointer;
+}
+
+.sidebar-item.selected {
+  background: #ddd;
+}
+
+.context-menu {
+  position: absolute;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  padding: 5px;
+  z-index: 1001;
+}
+
+.context-menu div {
+  padding: 5px;
+  cursor: pointer;
+}
+
+.context-menu div:hover {
+  background-color: #f0f0f0;
+}
+</style>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue
index 4e837d0..97cb04b 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue
@@ -1,5 +1,5 @@
 <script setup>
-import {nextTick, onMounted, reactive, ref, watch} from "vue";
+import {nextTick, onMounted, reactive, ref, watch,onBeforeUnmount } from "vue";
 import {useI18n} from "vue-i18n";
 import {Folder, Plus, Setting, Operation,} from "@element-plus/icons-vue";
 import OptimizeCompute from "@/views/pp/glassOptimize/page/OptimizeCompute.vue";
@@ -378,6 +378,9 @@
 //宸ョ▼鍙�
 const projectNo = ref(route.params.projectNo);
 const projectName = ref('');
+onBeforeUnmount(() => {
+  localStorage.setItem('projectNo', projectNo.value);
+});
 
 const fetchData = () => {
   request.post(`/glassOptimize/projectInfo/${projectNo.value}`).then((res) => {
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/RectRenderer.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
similarity index 75%
rename from north-glass-erp/northglass-erp/src/views/pp/glassOptimize/RectRenderer.vue
rename to north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
index 11e262d..55c3067 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/RectRenderer.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
@@ -1,18 +1,14 @@
 <template>
   <div ref="layoutPanel" :class="panelClass" :style="panelStyle">
-    <div v-for="(layout, layoutIndex) in layouts" :key="layoutIndex" 
-         class="layout-wrapper">
-      
+    <div v-for="(layout, layoutIndex) in layouts" :key="layoutIndex" class="layout-wrapper">
       <!-- 甯冨眬淇℃伅鏍囩 -->
       <div class="layout-info" :style="layoutInfoStyle(layoutIndex)">
-        甯冨眬{{ layoutIndex + 1 }}
+         {{ getCurrentRectInfo(layoutIndex) }}
       </div>
 
       <!-- 甯冨眬瀹瑰櫒 -->
-      <div class="layout-container"
-           :style="layoutContainerStyle(layoutIndex)">
-        
-        <div v-for="(rect, rectIndex) in layout.rects" :key="rectIndex" 
+      <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
+        <div v-for="(rect, rectIndex) in layout.rects" :key="rectIndex"
              :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
              :class="rectClass"
              :style="rectStyle(rect, layoutIndex)"
@@ -31,41 +27,26 @@
 import { ref, reactive, onMounted, onUnmounted } from 'vue';
 
 const props = defineProps({
-  layoutData: {
-    type: Object,
-    required: true
-  },
-  gw: {
-    type: Number,
-    default: 1000
-  },
-  gh: {
-    type: Number,
-    default: 1000
-  },
-  style: {
-    type: String,
-    default: 'width:1000px;height:600px;display:block;background:gray'
-  }
+  layoutData: { type: Object, required: true },
+  gw: { type: Number, default: 1000 },
+  gh: { type: Number, default: 1000 },
+  style: { type: String, default: 'width:1000px;height:600px;display:block;background:gray' }
 });
 
 const emit = defineEmits(['rectClicked']);
-
 const layoutPanel = ref(null);
 const rectsElements = ref({});
 const focusIndex = ref(null);
 const layouts = ref([]);
-
 const panelClass = ref('');
 const panelStyle = ref(props.style);
-
 const rectClass = ref('layout-rect');
 
 const layoutContainerStyle = (layoutIndex) => {
-  const containerWidth = (props.gw - 210) / 2; // 涓ゅ垪锛屾瘡鍒楀搴︿负gw鐨勪竴鍗婏紝鍑忓幓鍙宠竟璺�
-  const containerHeight = (props.gh - 100) / 3; // 涓夎锛屾瘡琛岄珮搴︿负gh鐨勪笁鍒嗕箣涓�锛屽噺鍘讳笅杈硅窛
-  const x = (layoutIndex % 2) * (containerWidth + 50); // 妯悜鎺掑垪锛屽姞涓�50px闂磋窛
-  const y = Math.floor(layoutIndex / 2) * (containerHeight + 50); // 绾靛悜鎺掑垪锛屽姞涓�50px闂磋窛
+  const containerWidth = (props.gw - 210) / 2;
+  const containerHeight = (props.gh - 100) / 3;
+  const x = (layoutIndex % 2) * (containerWidth + 50);
+  const y = Math.floor(layoutIndex / 2) * (containerHeight + 50);
   return {
     position: 'absolute',
     left: `${x}px`,
@@ -86,7 +67,7 @@
   return {
     position: 'absolute',
     left: `${x}px`,
-    top: `${y - 45}px`, // 灏嗘爣绛炬斁鍦ㄧ増鍥惧鍣ㄧ殑涓婃柟
+    top: `${y - 45}px`,
     background: 'none',
     textAlign: 'center',
     zIndex: 1000
@@ -101,7 +82,6 @@
     containerWidth / layout.width,
     containerHeight / layout.height
   );
-  
   return {
     position: 'absolute',
     left: `${rect.x * scale}px`,
@@ -119,25 +99,38 @@
   emit('rectClicked', 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 percentage = ((rect.w / layout.width) * 100).toFixed(1) + '%';
+  return `${currentRectIndex}/${totalRects} ${width}脳${height} 脳1 ${percentage}`;
+};
+
 const updateLayout = () => {
   if (!layoutPanel.value) return;
-
-  layouts.value = props.layoutData.data.Layouts;
+  layouts.value = props.layoutData.Layouts;
 };
 
 onMounted(() => {
-  updateLayout();
+  setTimeout(updateLayout, 500);
 });
 
 onUnmounted(() => {
   rectsElements.value = {};
 });
+
+
 </script>
 
 <style scoped>
 .layout-wrapper {
   position: relative;
-  margin-top:50px;
+  margin-top: 50px;
 }
 
 .layout-container {
@@ -153,7 +146,6 @@
   border-radius: 3px;
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
   font-weight: bold;
-
 }
 
 .rect-content {
diff --git a/north-glass-erp/src/main/java/com/example/erp/config/AppConfig.java b/north-glass-erp/src/main/java/com/example/erp/config/AppConfig.java
new file mode 100644
index 0000000..5369bd7
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/config/AppConfig.java
@@ -0,0 +1,13 @@
+package com.example.erp.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class AppConfig {
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java b/north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java
index b7aa8ec..6d839ca 100644
--- a/north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java
+++ b/north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java
@@ -3,14 +3,23 @@
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import com.example.erp.common.Constants;
 import com.example.erp.common.Result;
+import com.example.erp.entity.pp.LayoutsData;
 import com.example.erp.entity.pp.OptimizeProjectMange;
 import com.example.erp.exception.ServiceException;
 import com.example.erp.service.pp.GlassOptimizeService;
+import com.example.erp.service.pp.JsonToOptConverter;
+import com.example.erp.service.userInfo.UserService;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.IOException;
 import java.sql.Date;
 import java.util.Map;
 
@@ -20,7 +29,8 @@
 public class GlassOptimizeController {
     @Autowired
     GlassOptimizeService glassOptimizeService;
-
+    @Autowired
+    private UserService userService;
     //宸ョ▼淇℃伅
     @ApiOperation("宸ョ▼淇℃伅鎺ュ彛")
     @PostMapping  ("/projectInfo/{projectNo}")
@@ -134,6 +144,22 @@
         }
     }
 
+    @ApiOperation("浼樺寲璁剧疆淇濆瓨")
+    @PostMapping("/optimizeParms")
+    public Result optimizeParmsSave(@RequestBody Map<String, Object> object) {
+        try {
+            return Result.seccess(glassOptimizeService.optimizeParmsSave(object));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error();
+        }
+    }
+
+
+    @PostMapping("/selectOptimizeParms/{username}")
+    public Result getOptimizeParms(@PathVariable String username) {
+        return Result.seccess(userService.getOptimizeParms(username));
+    }
 
 
 
@@ -147,6 +173,8 @@
             return Result.error();
         }
     }
+
+
 
 
 
@@ -179,4 +207,51 @@
             @RequestBody Map<String,Object> object){
         return  Result.seccess(glassOptimizeService.addProjectSv(optionVal,projectId,projectNmae,object));
     }
+
+
+    @ApiOperation("淇濆瓨浼樺寲缁撴灉鎺ュ彛")
+    @PostMapping("/saveOptimizeResult")
+    public Result saveOptimizeResult(
+            @RequestBody Map<String,Object> object){
+        return  Result.seccess(glassOptimizeService.saveOptimizeResult(object));
+    }
+
+
+    @ApiOperation("鏌ヨ浼樺寲缁撴灉鎺ュ彛")
+    @PostMapping("/selectOptimizeResult/{processId}")
+    public Result selectOptimizeResult(
+            @PathVariable String processId){
+        return  Result.seccess(glassOptimizeService.selectOptimizeResult(processId));
+    }
+
+    @ApiOperation("鏇存柊浼樺寲缁撴灉鎺ュ彛")
+    @PostMapping("/updateOptimizeResult/{processId}")
+    public Result updateOptimizeResult(
+            @PathVariable String processId,@RequestBody Map<String,Object> object){
+
+        return  Result.seccess(glassOptimizeService.updateOptimizeResult(object,processId));
+    }
+    @ApiOperation("OPT鏂囦欢涓嬭浇鎺ュ彛")
+    @PostMapping("/generateOpt")
+    public ResponseEntity<byte[]> generateOptFile(@RequestBody LayoutsData layoutsData) throws IOException {
+        // 纭繚 layoutsData 鍖呭惈 Layouts 鏁扮粍
+        if (layoutsData == null || layoutsData.getLayouts() == null) {
+            throw new IllegalArgumentException("Layouts 鏁版嵁涓嶈兘涓虹┖");
+        }
+
+        // 鐢熸垚 OPT 鏂囦欢鍐呭
+        String optContent = JsonToOptConverter.generateOptContent(layoutsData);
+
+        // 鍒涘缓鍝嶅簲澶�
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(org.springframework.http.MediaType.TEXT_PLAIN);
+        headers.setContentDispositionFormData("attachment", "output.opt");
+
+        // 杩斿洖鏂囦欢鍐呭
+        return new ResponseEntity<>(optContent.getBytes(), headers, HttpStatus.OK);
+    }
+
+
+
+
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportingWorkController.java b/north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportingWorkController.java
index 3be1e02..d27b7fe 100644
--- a/north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportingWorkController.java
+++ b/north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportingWorkController.java
@@ -157,4 +157,10 @@
         return  Result.seccess(reportingWorkService.SaveReportingWorkSv(reportingWork));
     }
 
+    @ApiOperation("鎶ュ伐杞Щ")
+    @PostMapping  ("/reportingWorkTransfer")
+    public Result reportingWorkTransfer(@RequestBody Map<String,String> reportingWork)  {
+        return  Result.seccess(reportingWorkService.reportingWorkTransferSv(reportingWork));
+    }
+
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/controller/sd/OrderController.java b/north-glass-erp/src/main/java/com/example/erp/controller/sd/OrderController.java
index 99cdc19..f048d79 100644
--- a/north-glass-erp/src/main/java/com/example/erp/controller/sd/OrderController.java
+++ b/north-glass-erp/src/main/java/com/example/erp/controller/sd/OrderController.java
@@ -255,8 +255,15 @@
     @ApiOperation("鎵嬫満鎵爜鐜荤拑淇℃伅")
     @PostMapping("/scannerGlassInfo/{projectNo}")
     public Result scannerGlassInfo(@PathVariable String projectNo)  {
+        System.out.println("123123");
         return  Result.seccess(orderService.scannerGlassInfo(projectNo));
     }
 
+    @PostMapping("/test")
+    public Result scannerGlassInfo()  {
+        System.out.println("123123");
+        return  Result.seccess(null);
+    }
+
 
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/controller/userInfo/UserController.java b/north-glass-erp/src/main/java/com/example/erp/controller/userInfo/UserController.java
index 9878300..3f0c820 100644
--- a/north-glass-erp/src/main/java/com/example/erp/controller/userInfo/UserController.java
+++ b/north-glass-erp/src/main/java/com/example/erp/controller/userInfo/UserController.java
@@ -67,4 +67,5 @@
     public Result updateUserName(@RequestBody Map<String,Object> object){
         return Result.seccess( userService.updateUserName(object));
     }
+
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/dto/pp/OrderNumberTransferDTO.java b/north-glass-erp/src/main/java/com/example/erp/dto/pp/OrderNumberTransferDTO.java
new file mode 100644
index 0000000..0dc2533
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/dto/pp/OrderNumberTransferDTO.java
@@ -0,0 +1,45 @@
+package com.example.erp.dto.pp;
+
+import lombok.Data;
+
+/**
+ * 璁㈠崟搴忓彿鎶ュ伐杞崲鍙樻洿浼犺緭绫�
+ */
+
+@Data
+public class OrderNumberTransferDTO {
+    /**
+     * 鏃ф祦绋嬪崱鍙�
+     */
+    private String oldProcessId;
+
+    /**
+     * 鏃у簭鍙�
+     */
+    private String oldOrderNumber;
+
+    /**
+     * 鏃у眰鍙�
+     */
+    private Integer oldTechnologyNumber;
+
+    /**
+     * 淇℃祦绋嬪崱鍙�
+     */
+    private String newProcessId;
+
+    /**
+     * 鏂板簭鍙�
+     */
+    private String newOrderNumber;
+
+    /**
+     * 鏂板眰鍙�
+     */
+    private Integer newTechnologyNumber;
+
+    /**
+     * 鍙樻洿鏁伴噺
+     */
+    private Integer changeNumber;
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/pp/FlowCard.java b/north-glass-erp/src/main/java/com/example/erp/entity/pp/FlowCard.java
index a23d832..48ffb43 100644
--- a/north-glass-erp/src/main/java/com/example/erp/entity/pp/FlowCard.java
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/pp/FlowCard.java
@@ -62,6 +62,10 @@
     private Integer sort;
     //鏋跺彿
     private String rack;
+    //璁㈠崟杞Щ瀵煎叆鏁伴噺
+    private Integer importNumber;
+    //璁㈠崟杞Щ瀵煎嚭鏁伴噺
+    private Integer exportNumber;
     //寤虹珛鏃堕棿
     private LocalDate createTime;
     //淇敼鏃堕棿
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/pp/LayoutsData.java b/north-glass-erp/src/main/java/com/example/erp/entity/pp/LayoutsData.java
new file mode 100644
index 0000000..f9a2d9c
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/pp/LayoutsData.java
@@ -0,0 +1,113 @@
+package com.example.erp.entity.pp;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public class LayoutsData {
+    @JsonProperty("Layouts")
+    private List<Layout> layouts;
+
+    public List<Layout> getLayouts() {
+        return layouts;
+    }
+
+
+public static  class Layout  {
+    @JsonProperty("mnumber")
+    private int mNumber;
+    @JsonProperty("width")
+    private int width;
+    @JsonProperty("rects")
+    private List<Rect> rects;
+    @JsonProperty("wuliao")
+    private String material;
+    @JsonProperty("SameCount")
+    private int sameCount;
+    @JsonProperty("height")
+    private int height;
+
+    public int getWidth() {
+        return width;
+    }
+    public int getSameCount() {
+        return sameCount;
+    }
+    public String getWuliao() {
+        return material;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public List<Rect> getRects() {
+        return rects;
+    }
+}
+
+public static  class Rect {
+    @JsonProperty("isRemain")
+    private boolean isRemain;
+    @JsonProperty("h")
+    private int h;
+    @JsonProperty("DM2")
+    private int dm2;
+    @JsonProperty("xuhao")
+    private String serialNumber;
+    @JsonProperty("DM1")
+    private int dm1;
+    @JsonProperty("liuchengka")
+    private String processCard;
+    @JsonProperty("JiaHao")
+    private String jiaHao;
+    @JsonProperty("LM2")
+    private int lm2;
+    @JsonProperty("LM1")
+    private int lm1;
+    @JsonProperty("w")
+    private int W;
+    @JsonProperty("x")
+    private int x;
+    @JsonProperty("y")
+    private int y;
+    @JsonProperty("rownumber")
+    private int rowNumber;
+
+    public int getWidth() {
+        return W;
+    }
+
+    public int getHeight() {
+        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;
+    }
+}
+}
\ No newline at end of file
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/pp/ReportingWorkTransfer.java b/north-glass-erp/src/main/java/com/example/erp/entity/pp/ReportingWorkTransfer.java
new file mode 100644
index 0000000..42a82a6
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/pp/ReportingWorkTransfer.java
@@ -0,0 +1,28 @@
+package com.example.erp.entity.pp;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+public class ReportingWorkTransfer {
+    @TableId(type = IdType.AUTO)
+    private Long  id;
+    //琚浆绉昏鍗曞彿
+    private String  oldOrder;
+    //琚浆绉诲簭鍙�
+    private Integer  oldOrderNumber;
+    //琚浆绉诲唴瀹癸紙sd鎶ュ伐娴佺▼琛級
+    private String  oldReportContent;
+
+    //鏂拌鍗�
+    private String  newOrder;
+    //鏂拌鍗曞簭鍙�
+    private Integer  newOrderNumber;
+    //鏂拌浆绉诲唴瀹�
+    private String  newReportContent;
+    //寤虹珛鏃堕棿
+    private LocalDate createTime;
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/sd/OrderDetail.java b/north-glass-erp/src/main/java/com/example/erp/entity/sd/OrderDetail.java
index 74a2b5b..38fbe40 100644
--- a/north-glass-erp/src/main/java/com/example/erp/entity/sd/OrderDetail.java
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/sd/OrderDetail.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.example.erp.entity.mm.FinishedGoodsInventory;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -13,6 +14,7 @@
 import java.util.List;
 
 @Data
+@TableName("sd.`order_detail`")
 public class OrderDetail {
     @TableId(type = IdType.AUTO)
     private Long id;
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/userInfo/User.java b/north-glass-erp/src/main/java/com/example/erp/entity/userInfo/User.java
index a300841..0b49d07 100644
--- a/north-glass-erp/src/main/java/com/example/erp/entity/userInfo/User.java
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/userInfo/User.java
@@ -20,6 +20,7 @@
     private  String createTime;
     private  String updateTime;
     private  Integer state;
+    private  String optimizeParms;
     @TableField(select = false,exist = false)
     private  List<UserRole> userRoleList;
 
diff --git a/north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java b/north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java
index 8f66d57..31bd51d 100644
--- a/north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java
+++ b/north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java
@@ -50,7 +50,15 @@
     void addratioResult(Map<String, Object> object);
     //妯℃嫙璁$畻淇濆瓨 宸ョ▼淇℃伅
     void addratioProjectResult(Map<String, Object> object);
+    //浼樺寲璁剧疆淇濆瓨
+    void optimizeParmsSave(String jsonString);
 
+    //浼樺寲缁撴灉淇濆瓨
+    void optimizeResultSave(String jsonString);
+    //浼樺寲缁撴灉鏌ヨ
+    List<Map<String, Object>> selectOptimizeResult(String processId);
+    //浼樺寲缁撴灉璋冩暣
+    void updateOptimizeResult(String jsonString,String processId);
 
     List<Map<String, Object>> getProcessCardDetailmMp(String processId, Integer technologyNumber);
 
diff --git a/north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportingWorkTransferMapper.java b/north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportingWorkTransferMapper.java
new file mode 100644
index 0000000..d5923e7
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportingWorkTransferMapper.java
@@ -0,0 +1,9 @@
+package com.example.erp.mapper.pp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.erp.entity.pp.ReportingWorkTransfer;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportingWorkTransferMapper extends BaseMapper<ReportingWorkTransfer> {
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/mapper/userInfo/UserMapper.java b/north-glass-erp/src/main/java/com/example/erp/mapper/userInfo/UserMapper.java
index 1ee4995..ac9a6a0 100644
--- a/north-glass-erp/src/main/java/com/example/erp/mapper/userInfo/UserMapper.java
+++ b/north-glass-erp/src/main/java/com/example/erp/mapper/userInfo/UserMapper.java
@@ -39,4 +39,6 @@
     Boolean updateProcessMp(Integer id, String process);
 
     List<User> findByAddress(String userName);
+
+    String selectOptimizeParmsById(@Param("username") String username);
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java b/north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java
index 3d5c1f1..9b4db66 100644
--- a/north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java
+++ b/north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java
@@ -72,6 +72,57 @@
             return false;
         }
     }
+
+
+    //浼樺寲璁剧疆淇濆瓨
+    public Boolean optimizeParmsSave(Map<String, Object> object) {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            String jsonString = mapper.writeValueAsString(object);
+
+            glassOptimizeMapper.optimizeParmsSave(jsonString);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+
+    //浼樺寲璋冩暣缁撴灉淇濆瓨
+    public Boolean saveOptimizeResult(Map<String, Object> object) {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            String jsonString = mapper.writeValueAsString(object);
+            glassOptimizeMapper.optimizeResultSave(jsonString);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+    public Boolean updateOptimizeResult(Map<String, Object> object,String processId){
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            String jsonString = mapper.writeValueAsString(object);
+            glassOptimizeMapper.updateOptimizeResult(jsonString,processId);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+   //浼樺寲璋冩暣缁撴灉鏌ヨ
+    public Map<String, Object> selectOptimizeResult(String processId) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", glassOptimizeMapper.selectOptimizeResult(processId));
+        return map;
+    }
+
     //宸ョ▼淇℃伅
     public Map<String, Object> projectInfoSv(String projectNo) {
         Map<String, Object> map = new HashMap<>();
diff --git a/north-glass-erp/src/main/java/com/example/erp/service/pp/JsonToOptConverter.java b/north-glass-erp/src/main/java/com/example/erp/service/pp/JsonToOptConverter.java
new file mode 100644
index 0000000..c600248
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/service/pp/JsonToOptConverter.java
@@ -0,0 +1,137 @@
+package com.example.erp.service.pp;
+
+import com.example.erp.entity.pp.LayoutsData;
+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 {
+        ObjectMapper objectMapper = new ObjectMapper();
+        return objectMapper.writeValueAsString(layoutsData);
+    }
+
+    public static String generateOptContent(LayoutsData layoutsData) {
+        StringBuilder optContent = new StringBuilder();
+        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=5.0\n");
+        optContent.append("Dimension=mm\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) {
+        optContent.append("[OPT_Signature]\n");
+        optContent.append("Creator=OPTIMA S.r.l.\n\n");
+    }
+
+    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()) {
+            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 infoId = 1;
+        for (Layout layout : layoutsData.getLayouts()) {
+            for (Rect rect : layout.getRects()) {
+                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++;
+                }
+            }
+        }
+    }
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/service/pp/ReportingWorkService.java b/north-glass-erp/src/main/java/com/example/erp/service/pp/ReportingWorkService.java
index 829693b..1ab73e9 100644
--- a/north-glass-erp/src/main/java/com/example/erp/service/pp/ReportingWorkService.java
+++ b/north-glass-erp/src/main/java/com/example/erp/service/pp/ReportingWorkService.java
@@ -4,19 +4,22 @@
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.example.erp.common.Constants;
-import com.example.erp.entity.pp.DamageDetails;
-import com.example.erp.entity.pp.FlowCard;
-import com.example.erp.entity.pp.ReportingWork;
-import com.example.erp.entity.pp.ReportingWorkDetail;
+import com.example.erp.dto.pp.OrderNumberTransferDTO;
+import com.example.erp.entity.pp.*;
 import com.example.erp.entity.sd.Order;
+import com.example.erp.entity.sd.OrderDetail;
 import com.example.erp.entity.sd.OrderProcessDetail;
 import com.example.erp.entity.userInfo.Log;
 import com.example.erp.entity.userInfo.SysError;
 import com.example.erp.exception.ServiceException;
+import com.example.erp.mapper.mm.FinishedOperateLogMapper;
 import com.example.erp.mapper.pp.*;
 import com.baomidou.dynamic.datasource.annotation.DS;
+import com.example.erp.mapper.sd.OrderDetailMapper;
 import com.example.erp.mapper.sd.OrderGlassDetailMapper;
 import com.example.erp.mapper.sd.OrderMapper;
 import com.example.erp.mapper.sd.OrderProcessDetailMapper;
@@ -25,9 +28,15 @@
 import com.example.erp.service.userInfo.LogService;
 import com.example.erp.service.userInfo.SysErrorService;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.web.client.RestTemplate;
 
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
@@ -36,36 +45,31 @@
 
 @Service
 @DS("pp")
+@RequiredArgsConstructor
 public class ReportingWorkService {
-    final
-    ReportingWorkMapper reportingWorkMapper;
-    final
-    BasicDateProduceMapper basicDateProduceMapper;
-    final
-    DamageDetailsMapper damageDetailsMapper;
-    final
-    OrderProcessDetailMapper orderProcessDetailMapper;
-    final
-    ReportingWorkDetailMapper
-            reportingWorkDetailMapper;
-    final OrderMapper
-            orderMapper;
+    private final ReportingWorkTransferMapper reportingWorkTransferMapper;
+    private final ReportingWorkMapper reportingWorkMapper;
+    private final BasicDateProduceMapper basicDateProduceMapper;
+    private final DamageDetailsMapper damageDetailsMapper;
+    private final OrderProcessDetailMapper orderProcessDetailMapper;
+    private final ReportingWorkDetailMapper reportingWorkDetailMapper;
+    private final OrderMapper  orderMapper;
+    private final OrderDetailMapper orderDetailMapper;
 
-    final
-    FlowCardMapper flowCardMapper;
+    private final FlowCardMapper flowCardMapper;
 
-    final
-    OrderProcessDetailService orderProcessDetailService;
+    private final OrderProcessDetailService orderProcessDetailService;
 
-    final
-    LogService logService;
+    private final LogService logService;
 
-    final LogMapper logMapper;
+    private final LogMapper logMapper;
     private final OrderGlassDetailMapper orderGlassDetailMapper;
     private final SysErrorService sysErrorService;
+    private final FinishedOperateLogMapper finishedOperateLogMapper;
+    private final RestTemplate restTemplate;
 
 
-    public ReportingWorkService(ReportingWorkMapper reportingWorkMapper, BasicDateProduceMapper basicDateProduceMapper, DamageDetailsMapper damageDetailsMapper, ReportingWorkDetailMapper reportingWorkDetailMapper, OrderProcessDetailMapper orderProcessDetailMapper, OrderProcessDetailService orderProcessDetailService, OrderMapper orderMapper, FlowCardMapper flowCardMapper, LogService logService, LogMapper logMapper, OrderGlassDetailMapper orderGlassDetailMapper, SysErrorService sysErrorService) {
+    /*public ReportingWorkService(ReportingWorkMapper reportingWorkMapper, BasicDateProduceMapper basicDateProduceMapper, DamageDetailsMapper damageDetailsMapper, ReportingWorkDetailMapper reportingWorkDetailMapper, OrderProcessDetailMapper orderProcessDetailMapper, OrderProcessDetailService orderProcessDetailService, OrderMapper orderMapper, FlowCardMapper flowCardMapper, LogService logService, LogMapper logMapper, OrderGlassDetailMapper orderGlassDetailMapper, SysErrorService sysErrorService, OrderDetailMapper orderDetailMapper, FinishedOperateLogMapper finishedOperateLogMapper, ReportingWorkTransferMapper reportingWorkTransferMapper) {
         this.reportingWorkMapper = reportingWorkMapper;
         this.basicDateProduceMapper = basicDateProduceMapper;
         this.damageDetailsMapper = damageDetailsMapper;
@@ -78,7 +82,10 @@
         this.logMapper = logMapper;
         this.orderGlassDetailMapper = orderGlassDetailMapper;
         this.sysErrorService = sysErrorService;
-    }
+        this.orderDetailMapper = orderDetailMapper;
+        this.finishedOperateLogMapper = finishedOperateLogMapper;
+        this.reportingWorkTransferMapper = reportingWorkTransferMapper;
+    }*/
 
     public Map<String, Object> AddSelectLastWorkSv(String processIdStr, String technologyStr, String process, String reportType) {
         Map<String, Object> map = new HashMap<>();
@@ -819,4 +826,188 @@
 
         }
     }
+
+    @Transactional(rollbackFor = Exception.class)
+    public Object reportingWorkTransferSv(Map<String, String> reportingWork) {
+        Order oldOrder = orderMapper.selectOrderId(reportingWork.get("oldOrderId"));
+        OrderDetail oldOrderDetail = orderDetailMapper.selectOne(
+                new QueryWrapper<OrderDetail>()
+                        .eq("order_id", reportingWork.get("oldOrderId"))
+                        .eq("order_number", reportingWork.get("oldOrderNumber"))
+        );
+
+        Order newOrder = orderMapper.selectOrderId(reportingWork.get("newOrderId"));
+        OrderDetail newOrderDetail = orderDetailMapper.selectOne(
+                new QueryWrapper<OrderDetail>()
+                        .eq("order_id", reportingWork.get("newOrderId"))
+                        .eq("order_number", reportingWork.get("newOrderNumber"))
+        );
+        if(!Objects.equals(oldOrder.getCustomerId(), newOrder.getCustomerId())){
+            return "鏂版棫璁㈠崟瀹㈡埛涓嶄竴鑷�";
+        }
+        if(!Objects.equals(oldOrderDetail.getProductId(), newOrderDetail.getProductId())){
+            return "鏂版棫璁㈠崟浜у搧涓嶄竴鑷�";
+        }
+        if (!Objects.equals(oldOrderDetail.getWidth(), newOrderDetail.getWidth())
+                || !Objects.equals(oldOrderDetail.getHeight(), newOrderDetail.getHeight())){
+            return "鏂版棫璁㈠崟灏哄涓嶄竴鑷�";
+        }
+
+
+        //鑾峰彇鏃ц鍗曟槸鍚︽祦绋嬪崱鏄惁瀛樺湪
+        List<OrderProcessDetail> oldOrderProcessDetailList = orderProcessDetailMapper
+                .selectList(new QueryWrapper<OrderProcessDetail>()
+                        .eq("order_id", reportingWork.get("oldOrderId"))
+                        .eq("order_number", reportingWork.get("oldOrderNumber"))
+                );
+        if(oldOrderProcessDetailList.isEmpty()){
+            return "鏃ц鍗曟湭鍒嗘祦绋嬪崱";
+        }
+        //鑾峰彇鏂拌鍗曟槸鍚︽祦绋嬪崱鏄惁瀛樺湪
+        List<OrderProcessDetail> newOrderProcessDetailList = orderProcessDetailMapper
+                .selectList(new QueryWrapper<OrderProcessDetail>()
+                        .eq("order_id", reportingWork.get("newOrderId"))
+                        .eq("order_number", reportingWork.get("newOrderNumber"))
+                );
+        if(newOrderProcessDetailList.isEmpty()){
+            return "鏂拌鍗曟湭鍒嗘祦绋嬪崱";
+        }
+        //鏂拌鍗曟槸鍚﹀瓨鍦ㄥ凡缁忔帓鐗堝簭鍙�
+        List<FlowCard> newFlowCardLayoutStatus = flowCardMapper.selectList(new QueryWrapper<FlowCard>()
+                .eq("order_id", reportingWork.get("newOrderId"))
+                .eq("order_number", reportingWork.get("newOrderNumber"))
+                .gt("layout_status",0)
+        );
+        if(!newFlowCardLayoutStatus.isEmpty()){
+            return "鏂拌鍗曟搴忓彿瀛樺湪鎺掔増";
+        }
+        //鑾峰彇鏃ц鍗曟姤宸ユ暟鎹眹鎬�
+        List<OrderProcessDetail> oldOrderProcessDetailForReport = orderProcessDetailMapper
+                .selectList(new QueryWrapper<OrderProcessDetail>()
+                        .eq( "order_id", reportingWork.get("oldOrderId"))
+                        .eq("order_number", reportingWork.get("oldOrderNumber"))
+                        .gt("reporting_work_num",0)
+        );
+
+        Map<String,Object> log = new HashMap<>();
+        log.put("oldOrderBeforeChange",oldOrderProcessDetailForReport);
+
+        Map<String,Object> newOrderLog = new HashMap<>();
+        newOrderLog.put("newOrderBeforeChange",newOrderProcessDetailList);
+
+        //浼犵粰mes娴佺▼鍗℃暟閲忛泦鍚�
+        List<OrderNumberTransferDTO> orderNumberTransferList = new ArrayList<>();
+
+        oldOrderProcessDetailForReport.forEach(oldOrderProcessDetail -> {
+            int maxNum = 0;
+            for(OrderProcessDetail newOrderProcessDetail : newOrderProcessDetailList){
+                if(oldOrderProcessDetail.getReportingWorkNum() == 0){
+                    break;
+                }
+                //鍒ゆ柇灏忕墖鏄惁涓�鑷达紝宸ュ簭鏄惁涓�鑷�
+                if(newOrderProcessDetail.getProcess().equals(oldOrderProcessDetail.getProcess()) &&
+                        Objects.equals(newOrderProcessDetail.getTechnologyNumber(), oldOrderProcessDetail.getTechnologyNumber())){
+                    //鍒ゆ柇鏄惁涓虹涓�閬撳伐搴忥紝缁欏彲杞Щ鏈�澶у�艰祴鍊�
+                    if(oldOrderProcessDetail.getProcess().equals("鍒囧壊")){
+                        FlowCard  thisFlowCard = flowCardMapper.selectOne(new QueryWrapper<FlowCard>()
+                                .eq("process_id", newOrderProcessDetail.getProcessId())
+                                .eq("order_number", newOrderProcessDetail.getOrderNumber())
+                                .eq("technology_number",newOrderProcessDetail.getTechnologyNumber())
+                        );
+                        maxNum = thisFlowCard.getQuantity();
+                    }else{
+                        //褰撲笉鏄涓�閬撳伐搴忓垯锛屾嬁涓婁竴閬撳伐搴忎綔涓烘渶澶у��
+                        maxNum = orderProcessDetailMapper.selectById(newOrderProcessDetail.getId()-1).getReportingWorkNum();
+                    }
+                    //鍒ゆ柇琚浆绉荤殑鏁伴噺鏄惁澶т簬鍙浆绉荤殑鏁伴噺鏈�澶у��
+                    int transferNum = 0;
+                    if(oldOrderProcessDetail.getReportingWorkNum() > maxNum){
+                        transferNum = maxNum;
+                        oldOrderProcessDetail.setReportingWorkNum(oldOrderProcessDetail.getReportingWorkNum()-maxNum);
+                        oldOrderProcessDetail.setReportingWorkNumCount(oldOrderProcessDetail.getReportingWorkNumCount()-maxNum);
+                    }else{
+                        transferNum = oldOrderProcessDetail.getReportingWorkNum();
+                        oldOrderProcessDetail.setReportingWorkNum(0);
+                        oldOrderProcessDetail.setReportingWorkNumCount(0);
+                    }
+                    //鏇存柊鏃ц鍗曞皬鐗囨祦绋嬭〃鐨勬姤宸ユ暟閲�
+                    orderProcessDetailMapper.update(null,new UpdateWrapper<OrderProcessDetail>()
+                            .set("reporting_work_num",oldOrderProcessDetail.getReportingWorkNum())
+                            .set("reporting_work_num_count",oldOrderProcessDetail.getReportingWorkNumCount())
+                            .eq("id",oldOrderProcessDetail.getId())
+                    );
+                    //鏇存柊鏂拌鍗曞皬鐗囨祦绋嬭〃鐨勬姤宸ユ暟閲�
+                    orderProcessDetailMapper.update(null,new UpdateWrapper<OrderProcessDetail>()
+                            .set("reporting_work_num",transferNum)
+                            .set("reporting_work_num_count",transferNum)
+                            .eq("id",newOrderProcessDetail.getId())
+                    );
+                    if(oldOrderProcessDetail.getProcess().equals("鍒囧壊")){
+                        //鏇存柊鏃ц鍗曟祦绋嬪崱杞嚭鏁伴噺
+                        flowCardMapper.update(null,new UpdateWrapper<FlowCard>()
+                                .setSql("export_number = export_number + "+transferNum)
+                                .eq("process_id", oldOrderProcessDetail.getProcessId())
+                                .eq("order_number", oldOrderProcessDetail.getOrderNumber())
+                                .eq("technology_number",oldOrderProcessDetail.getTechnologyNumber())
+                        );
+                        //鏇存柊鏂拌鍗曟祦绋嬪崱杞嚭鏁伴噺
+                        flowCardMapper.update(null,new UpdateWrapper<FlowCard>()
+                                .setSql("import_number = import_number + "+transferNum)
+                                .eq("process_id", newOrderProcessDetail.getProcessId())
+                                .eq("order_number", newOrderProcessDetail.getOrderNumber())
+                                .eq("technology_number",newOrderProcessDetail.getTechnologyNumber())
+                        );
+
+                        //浼犵粰mes鏁版嵁璧嬪��
+                        OrderNumberTransferDTO orderNumberTransfer = new OrderNumberTransferDTO();
+                        orderNumberTransfer.setChangeNumber(transferNum);
+                        orderNumberTransfer.setOldProcessId(oldOrderProcessDetail.getProcessId());
+                        orderNumberTransfer.setNewProcessId(newOrderProcessDetail.getProcessId());
+                        orderNumberTransfer.setOldOrderNumber(oldOrderProcessDetail.getOrderNumber());
+                        orderNumberTransfer.setNewOrderNumber(newOrderProcessDetail.getOrderNumber());
+                        orderNumberTransfer.setOldTechnologyNumber(oldOrderProcessDetail.getTechnologyNumber());
+                        orderNumberTransfer.setNewTechnologyNumber(newOrderProcessDetail.getTechnologyNumber());
+                        orderNumberTransferList.add(orderNumberTransfer);
+
+                    }
+
+                }
+            }
+        });
+
+
+        //鎶婃棫璁㈠崟鏁版嵁鍜屾柊璁㈠崟鏁版嵁浼犲埌鏃ュ織琛ㄥ綋涓�
+        log.put("oldOrderChange",JSON.toJSONString(oldOrderProcessDetailForReport));
+
+        newOrderLog.put("newOrderChange",orderProcessDetailMapper
+                .selectList(new QueryWrapper<OrderProcessDetail>()
+                        .eq("order_id", reportingWork.get("newOrderId"))
+                        .eq("order_number", reportingWork.get("newOrderNumber"))
+                ));
+        //鏃ц鍗曚俊鎭紶鍏ユ棩蹇�
+        ReportingWorkTransfer reportingWorkTransfer = new ReportingWorkTransfer();
+        reportingWorkTransfer.setOldOrder(reportingWork.get("oldOrderId"));
+        reportingWorkTransfer.setOldOrderNumber(Integer.valueOf(reportingWork.get("oldOrderNumber")));
+        reportingWorkTransfer.setOldReportContent(JSON.toJSONString(log));
+
+        //鏂拌鍗曚俊鎭紶鍏ユ棩蹇�
+        reportingWorkTransfer.setNewOrder(reportingWork.get("newOrderId"));
+        reportingWorkTransfer.setNewOrderNumber(Integer.valueOf(reportingWork.get("newOrderNumber")));
+        reportingWorkTransfer.setNewReportContent(JSON.toJSONString(newOrderLog));
+        reportingWorkTransferMapper.insert(reportingWorkTransfer);
+        //restTemplate.postForObject("http://localhost:8086/order/test",orderNumberTransferList,String.class);
+
+        //鍚憁es鍙戦�乭ttp璇锋眰
+        ResponseEntity<String> response =restTemplate.exchange(
+                "http://localhost:88/api/loadGlass/order/order/orderChange",
+                HttpMethod.POST,
+                new HttpEntity<>(orderNumberTransferList),
+                String.class);
+
+        if(response.getStatusCode() == HttpStatus.OK){
+            return true;
+        }else{
+            return "mes鍝嶅簲瓒呮椂";
+        }
+    }
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/service/userInfo/UserService.java b/north-glass-erp/src/main/java/com/example/erp/service/userInfo/UserService.java
index 1127965..3b0510c 100644
--- a/north-glass-erp/src/main/java/com/example/erp/service/userInfo/UserService.java
+++ b/north-glass-erp/src/main/java/com/example/erp/service/userInfo/UserService.java
@@ -207,5 +207,15 @@
         map.put("users", Collections.singletonList(userList));
         return map;
     }
+
+
+//鏌ヨ鐢ㄦ埛浼樺寲鍙傛暟
+public String getOptimizeParms(String username) {
+    // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+
+        return userMapper.selectOptimizeParmsById(username);
+    }
+
 }
 
+
diff --git a/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml b/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
index 7a8eb21..c08f739 100644
--- a/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
+++ b/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
@@ -407,6 +407,7 @@
                 LEFT JOIN pp.damage_details dal ON  dal.order_number = g.order_number AND dal.technology_number = g.technology_number and f.process_id=dal.process_id
                 LEFT JOIN pp.flow_card fl ON fl.order_id = g.order_id AND fl.order_number = g.order_number AND fl.technology_number = g.technology_number
         WHERE
+            p.state IN (1, 2) and
           f.process_id = #{processId}
     </select>
 
@@ -528,7 +529,7 @@
             );
         </foreach>
     </insert>
-
+    <!--妯℃嫙璁$畻缁撴灉淇濆瓨-->
     <insert id="addratioResult" parameterType="map">
         <foreach collection="projectdetail.data[0].ratioResult" item="glass">
             INSERT INTO pp.optimize_heat_layout (
@@ -555,7 +556,7 @@
         </foreach>
     </insert>
 
-
+    <!--妯℃嫙璁$畻宸ョ▼鏇存柊-->
     <update id="addratioProjectResult" parameterType="map">
         UPDATE pp.optimize_project
         SET
@@ -573,6 +574,23 @@
             project_no = #{inputValues.project_no}
 
     </update>
+<!--浼樺寲璁剧疆淇濆瓨-->
+    <update id="optimizeParmsSave">
+        update erp_user_info.user as u
+        set u.optimize_parms = #{jsonString}
+    </update>
+
+    <update id="updateOptimizeResult">
+        update pp.optimize_project_file as u
+        set u.content = #{jsonString}
+        where  u.project_no=#{processId} and type='浼樺寲缁撴灉'
+    </update>
 
 
+
+    <select id="selectOptimizeResult">
+        SELECT content as Layouts
+                        FROM pp.optimize_project_file
+                        WHERE  project_no=#{processId} and type='浼樺寲缁撴灉';
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/north-glass-erp/src/main/resources/mapper/pp/ReportingWork.xml b/north-glass-erp/src/main/resources/mapper/pp/ReportingWork.xml
index 89fc012..02f61ac 100644
--- a/north-glass-erp/src/main/resources/mapper/pp/ReportingWork.xml
+++ b/north-glass-erp/src/main/resources/mapper/pp/ReportingWork.xml
@@ -137,8 +137,8 @@
             ogd.child_width,
             ogd.child_height,
             if(od.shape=1,'鏅舰',if(od.shape=2,'寮傚舰','')) as shape,
-            fc.quantity + ifnull(patch.patch_num,0) -odpd.reporting_work_num -odpd.broken_num   as quantity,
-            fc.quantity + ifnull(patch.patch_num,0) -odpd.reporting_work_num -odpd.broken_num   as completedQuantity,
+            fc.quantity -fc.export_number + ifnull(patch.patch_num,0) -odpd.reporting_work_num -odpd.broken_num   as quantity,
+            fc.quantity -fc.export_number + ifnull(patch.patch_num,0) -odpd.reporting_work_num -odpd.broken_num   as completedQuantity,
             odpd.reporting_work_num as completed,
             odpd.broken_num as onceBroken,
             if(fc.quantity -odpd.reporting_work_num = 0 ,true,false) as saveFlag, -- 鍒ゆ柇鏄惁宸茬粡瀹屾垚锛屽凡缁忓畬鎴愪笉搴忓彿鍜屽悓搴忓彿鏁伴噺鐩稿悓鎵嶈兘鎻愪氦
diff --git a/north-glass-erp/src/main/resources/mapper/userInfo/User.xml b/north-glass-erp/src/main/resources/mapper/userInfo/User.xml
index 62f4a3d..6629db6 100644
--- a/north-glass-erp/src/main/resources/mapper/userInfo/User.xml
+++ b/north-glass-erp/src/main/resources/mapper/userInfo/User.xml
@@ -104,4 +104,11 @@
         set address=#{process},update_time=now()
         where id=#{id}
     </update>
+
+
+        <select id="selectOptimizeParmsById" resultType="String">
+            SELECT optimize_parms FROM erp_user_info.user WHERE user_name = #{username}
+        </select>
+
+
 </mapper>
\ No newline at end of file

--
Gitblit v1.8.0