From d648ebc69905befd409cac296dc4b6c7e8bd1d7b Mon Sep 17 00:00:00 2001
From: 廖井涛 <2265517004@qq.com>
Date: 星期一, 28 四月 2025 14:02:23 +0800
Subject: [PATCH] 添加第三方优化对接模块

---
 north-glass-erp/northglass-erp/src/router/index.js                                             |   47 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeCard.vue       |  185 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeProject.vue        |   96 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectMange.vue           |  702 +++++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue        |   93 
 north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeDetail.java                    |   29 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCardDetail.vue |  149 +
 north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java               |   30 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue                     |    8 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizationRect.vue  | 1122 ++++++++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeMove.vue           |   23 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/Compute.vue           |  426 +++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimization.vue           |   52 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCard.vue       |  374 ++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetAmount.vue         |  217 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectDetail.vue     |  611 ++++
 north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java             |  106 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizationRectPrint.vue  |  103 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizeCompute.vue   |  144 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/CheckInventory.vue    |   97 
 north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml                                 |  140 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimize.vue               |   72 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectCreate.vue          |  391 +++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/GlassInventory.vue    |  322 ++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/GlassComputed.vue          |  328 ++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizePrint.vue          |   80 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue                    |    8 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectList.vue       |  281 ++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/RectRenderer.vue      |  341 ++
 north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java       |   71 
 north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeHeatDetail.java                |   28 
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeParms.vue          |  522 ++++
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetTrimming.vue       |  205 +
 north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeDetail.vue     |  134 +
 34 files changed, 7,519 insertions(+), 18 deletions(-)

diff --git a/north-glass-erp/northglass-erp/src/router/index.js b/north-glass-erp/northglass-erp/src/router/index.js
index f85f0b3..d538582 100644
--- a/north-glass-erp/northglass-erp/src/router/index.js
+++ b/north-glass-erp/northglass-erp/src/router/index.js
@@ -1232,6 +1232,53 @@
           ]
         },
         {
+          //绗笁鏂圭幓鐠冧紭鍖�
+          path: 'glassOptimizeThirdParty',
+          name: 'glassOptimizeThirdParty',
+          component: () => import('../views/pp/glassOptimizeThirdParty/Optimize.vue'),
+          children:[
+            {
+              path: 'optimizeProject',
+              name: 'optimizeProject',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizeProject.vue'),
+            },
+            {
+              path: 'optimizePrint',
+              name: 'optimizePrint',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizePrint.vue'),
+            },
+            {
+              path: 'OptimizationRectPrint',
+              name: 'OptimizationRectPrint',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizationRectPrint.vue'),
+            },
+            {
+              path: 'OptimizeControl',
+              name: 'OptimizeControl',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizeControl.vue'),
+            },
+            {
+              path: 'Optimization',
+              name: 'Optimization',
+              component: () => import('../views/pp/glassOptimizeThirdParty/Optimization.vue'),
+            },
+            {
+              path: 'optimizeparms',
+              name: 'optimizeparms',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizeParms.vue'),
+            },
+            {
+              path: '/optimizeProject/:projectNo/:thickNess/:model',
+              name: 'optimizeInfo',
+              component: () => import('../views/pp/glassOptimizeThirdParty/OptimizeProject.vue')
+            },
+            {
+              path: '',
+              redirect:'/main/glassOptimizeThirdParty/optimizeProject'
+            }
+          ]
+        },
+        {
           path: '',
           redirect:'/main/order'
         }
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue
index 1d87d33..f80568c 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue
@@ -256,8 +256,8 @@
               "order_number": 33,
               "process_id": "NG24120028A005",
               "technology_number": 2,
-              "tempering_feed_sequence": 14,
-              "tempering_layout_id": 15,
+              "tempering_feed_sequence": 1,
+              "tempering_layout_id": 1,
               "width": 814,
               "x_coordinate": 1582.0,
               "y_coordinate": 3768.0
@@ -270,8 +270,8 @@
               "order_number": 33,
               "process_id": "NG24120028A005",
               "technology_number": 2,
-              "tempering_feed_sequence": 14,
-              "tempering_layout_id": 15,
+              "tempering_feed_sequence": 2,
+              "tempering_layout_id": 1,
               "width": 814,
               "x_coordinate": 1582.0,
               "y_coordinate": 3768.0
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue
index 0502060..1164c45 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue
@@ -237,10 +237,14 @@
 const handleSave = () => {
   
   if (props.data) {
- 
+    console.log(props.data)
 
     let projectData = ref({
-      projectdetail: props.data,
+      projectdetail: props.data.data[0].glass_details,
+      ratioResult: props.data.data[0].ratioResult,
+      rackinfos: props.data.data[0].rackinfos,
+      resultSum: props.data.data[0].resultSum,
+      guidance: props.data.data[0].guidance,
       userName : username,
       inputValues:inputValues
     })
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/GlassComputed.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/GlassComputed.vue
new file mode 100644
index 0000000..8373b04
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/GlassComputed.vue
@@ -0,0 +1,328 @@
+<script setup>
+import ComputeCard from "@/views/pp/glassOptimizeThirdParty/page/ComputeCard.vue";
+import ComputeDetail from "@/views/pp/glassOptimizeThirdParty/page/ComputeDetail.vue";
+import Compute from "@/views/pp/glassOptimizeThirdParty/page/Compute.vue";
+import {onMounted, ref} from 'vue';
+import {ElMessage, ElLoading} from "element-plus";
+import request from "@/utils/request";
+
+const props = defineProps({
+  project : null
+});
+
+const computed = ref(null);
+const computedCard = ref(null);
+const computedData = ref({
+  // 瑕佷紶閫掔粰瀛愮粍浠剁殑鏁版嵁
+});
+
+// 鐩戝惉瀛愮粍浠禖omputeCard鐨勬暟鎹�
+
+
+const  computeCardRef=ref(null)
+
+
+const handleCardData = (data) => {
+
+  computedCard.value = data;
+  // 灏� computed.value 鍚堝苟鍒� computedCard.value 鐨勬渶澶栧眰
+  computedCard.value = {
+    ...computed.value,
+    ...computedCard.value
+  };
+};
+
+// 鐩戝惉瀛愮粍浠禖omputeDetail鐨勬暟鎹�
+const handleData = (data) => {
+  computed.value = data;
+};
+
+onMounted(() => {
+  if (props.project) {
+    console.log(props.project)
+    handleFetchData(props.project.projectNumber);
+    //handleTableData(data);
+    //handleDataReceive(data);
+  }
+});
+
+// 鍦ㄧ埗缁勪欢涓畾涔夊鐞嗘帴鏀舵暟鎹殑鍑芥暟
+const handleDataReceive= async (data) => {
+  console.log('鎺ユ敹鍒板瓙缁勪欢鐨勬暟鎹�2:', data);
+  // 澶勭悊鏁版嵁锛屼緥濡傛洿鏂扮埗缁勪欢鐨勭姸鎬佹垨璋冪敤鍚庣API
+ 
+}
+
+
+// 鐢ㄤ簬瀛樺偍浠庡悗绔幏鍙栧埌鐨勬暟鎹紝鍒濆鍖栦负绌烘暟缁�
+const receivedData = ref([]);
+
+
+console.log(receivedData)
+const handleFetchData = async (projectNumber) => {
+  try {
+    const res = await request.post(`/glassOptimize/selectProjectComputeMpThirdParty/${projectNumber}`);
+    if (Number(res.code) === 200 && res.data && res.data.data) {
+      receivedData.value = res.data.data;
+    } else {
+      console.error('璇锋眰鍑虹幇闂锛岀姸鎬佺爜锛�', res.code, '锛岄敊璇俊鎭細', res.msg);
+      if (res.code === 404) {
+        ElMessage.error('鏈壘鍒板搴斿伐绋嬪彿鐨勬暟鎹紝璇锋鏌ヨ緭鍏ユ槸鍚︽纭�');
+      } else if (res.code === 500) {
+        ElMessage.error('鏈嶅姟鍣ㄥ唴閮ㄥ嚭鐜伴敊璇紝璇风◢鍚庡啀璇�');
+      } else {
+        ElMessage.warning(res.msg);
+      }
+    }
+  } catch (error) {
+    console.error('璇锋眰鍑洪敊', error);
+    ElMessage.error('璇疯緭鍏ュ伐绋嬪彿锛�');
+  }
+};
+
+const  handleTableData= async (data) => {
+  // 澶勭悊鎺ユ敹鍒扮殑琛ㄦ牸鏁版嵁
+  console.log('鐖剁粍浠舵帴鏀跺埌鐨勬暟鎹�1:', data);
+}
+
+const handleSimulation = async () => {
+  const data=computeCardRef.value.selectFullData();
+  if(props.project!=null){
+    computed.value.glass_thickness=props.project.glass_thickness
+    computed.value.glass_type=props.project.glass_type
+  }
+  data.forEach(item=>{
+    const processCard = {
+      process_no: item.processId,
+      layers: item.technologyNumber,
+      total_layers: item.total_layers,
+      total_num: item.total_num,
+      total_area: item.total_area,
+      is_must: true,
+      allow_rotate: item.allow_rotate,
+      priority_level: 0,
+      tempering: item.tempering,
+      curtain_wall: item.curtain_wall,
+      glass_details: []
+    };
+
+    request.post(`/glassOptimize/selectComputeDetailThirdParty/${item.processId}/${item.technologyNumber}`).then((res) => {
+      if(Number(res.code) === 200){
+        res.data.data.forEach(items=>{
+          const detail={
+            process_id:null,
+            technology_number:null,
+            order_number:null,
+            layers_number:null,
+            max_width:null,
+            max_height:null,
+            child_width:null,
+            child_height:null,
+            quantity:null,
+            patch_state:null
+          }
+          detail.process_id=items.process_id
+          detail.technology_number=items.technology_number
+          detail.order_number=items.order_number
+          detail.layers_number=item.total_layers
+          detail.max_width=items.maxwidth
+          detail.max_height=items.maxheight
+          detail.child_width=items.width
+          detail.child_height=items.height
+          detail.quantity=items.quantity
+          detail.patch_state=item.patch_state
+
+          processCard.glass_details.push(detail)
+        })
+
+
+      }else{
+        ElMessage.warning(res.msg)
+      }
+    })
+    computed.value.process_cards.push(processCard)
+  })
+  console.log(computed.value)
+
+
+
+
+  const loading = ElLoading.service({
+      lock: true,
+      text: '姝e湪璁$畻涓紝璇风◢鍊�...',
+      background: 'rgba(0, 0, 0, 0.7)'
+    });
+   console.log('鍙戦�佸埌鍚庣鐨勬暟鎹�',computedCard.value)
+  const mockData = {
+      code: 200,
+      data: [
+        {
+          "glass_details": [
+            {
+              "angle": 0.0,
+              "glass_type": 3,
+              "height": 862,
+              "layers_number": 2,
+              "order_number": 33,
+              "process_id": "NG24120028A005",
+              "technology_number": 2,
+              "tempering_feed_sequence": 1,
+              "tempering_layout_id": 1,
+              "width": 814,
+              "x_coordinate": 1582.0,
+              "y_coordinate": 3768.0
+            },
+            {
+              "angle": 0.1,
+              "glass_type": 4,
+              "height": 862,
+              "layers_number": 2,
+              "order_number": 33,
+              "process_id": "NG24120028A005",
+              "technology_number": 2,
+              "tempering_feed_sequence": 2,
+              "tempering_layout_id": 1,
+              "width": 814,
+              "x_coordinate": 1582.0,
+              "y_coordinate": 3768.0
+            }
+          ],
+          "guidance": 15,
+          "rackinfos": [
+            "NG24120026A003-2",
+            "NG24120027A003-2",
+            "NG24120028A005-2"
+          ],
+          "ratioResult": [
+            {
+              "area": 10.53,
+              "glass_total": 15,
+              "ratio": 0.74,
+              "tempering_layout_id": "13"
+            },
+            {
+              "area": 10.53,
+              "glass_total": 15,
+              "ratio": 0.74,
+              "tempering_layout_id": "14"
+            },
+            {
+              "area": 9.82,
+              "glass_total": 14,
+              "ratio": 0.69,
+              "tempering_layout_id": "15"
+            }
+          ],
+          "resultSum": [15.0, 0.74]
+        }
+      ]
+    };
+    if (mockData.code === 200) {
+    loading.close();
+    ElMessage.success('妯℃嫙璁$畻鎴愬姛!');
+    }
+    // 鏇存柊computedData
+    computedData.value = mockData;
+  // try {
+  //   if (!computed.value ) {
+  //     ElMessage.warning('璇峰厛鍔犺浇鏁版嵁鍐嶈繘琛屾ā鎷熻绠�');
+  //     return;
+  //   }
+
+  //   // 鏄剧ず鍔犺浇鎻愮ず
+  //   const loading = ElLoading.service({
+  //     lock: true,
+  //     text: '姝e湪璁$畻涓紝璇风◢鍊�...',
+  //     background: 'rgba(0, 0, 0, 0.7)'
+  //   });
+
+  //   try {
+  //     // 灏嗘暟鎹彁浜ゅ埌鍚庣
+  //     const response = await request.post('/glassOptimize/simulationCalculate', {
+        
+  //       data: computedCard.value
+
+  //     });
+
+  //     if (response.code === 200) {
+  //       ElMessage.success('妯℃嫙璁$畻鎴愬姛!');
+  //     } else {
+  //       ElMessage.error(response.msg || '妯℃嫙璁$畻澶辫触');
+  //     }
+  //   } catch (error) {
+  //     console.error('璇锋眰澶辫触:', error);
+  //     ElMessage.error('缃戠粶寮傚父锛岃绋嶅悗鍐嶈瘯');
+  //   } finally {
+  //     // 鍏抽棴鍔犺浇鎻愮ず
+  //     loading.close();
+  //   }
+  // } catch (error) {
+  //   console.error('璇锋眰澶辫触:', error);
+  //   ElMessage.error('缃戠粶寮傚父锛岃绋嶅悗鍐嶈瘯');
+  // }
+};
+
+
+
+//鎺ュ彈瀛愮粍浠禖omputeCard鐨勬祦绋嬪崱鍙�
+let projectRow = ref({
+  processId:null,
+  patchState:null,
+  technologyNumber:null
+})
+const handleUpdateProcessId = (processId,technologyNumber) => {
+  projectRow.value.processId = processId;
+};
+
+const handleTechnologyNumberUpdate = (processId,technologyNumber) => {
+  projectRow.value.technologyNumber = technologyNumber;
+};
+
+
+
+</script>
+
+<template>
+  <div style="width: 100%; height: 100%;">
+   
+    <div id="compute">
+      <compute  :data="computedData"  @fetch-data="handleFetchData" :project="props.project"  @sendData="handleData"  @simulate-click="handleSimulation" />
+    </div>
+
+    <div id="computeCard">
+      <compute-card ref="computeCardRef" :table-data="receivedData"
+                    :process-id="projectRow.processId===null?null:projectRow.processId"
+                    :technology-number="projectRow.technologyNumber===null?null:projectRow.technologyNumber"
+                    @upProcessId="handleUpdateProcessId"  @updateTechnologyNumber="handleTechnologyNumberUpdate" @sendData="handleCardData"
+      />
+    </div>
+
+    <div id="computeDetail">
+      <compute-detail :process-id="projectRow.processId===null?null:projectRow.processId"
+                      :technology-number="projectRow.technologyNumber===null?null:projectRow.technologyNumber"
+                      :patch-state="projectRow.patchState===null?null:projectRow.patchState"/>
+    </div>
+   
+  </div>
+</template>
+
+<style scoped>
+#compute{
+  float: left;
+  margin-top: -30px;
+  margin-bottom: 2%;
+  width: 100%;
+  height: 37%;
+}
+#computeCard{
+  width: 64%;
+  height: 55%;
+  float: left;
+}
+#computeDetail{
+  margin-left: 1%;
+  float: left;
+  width: 35%;
+  height: 55%;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimization.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimization.vue
new file mode 100644
index 0000000..eb356bb
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimization.vue
@@ -0,0 +1,52 @@
+<template>
+  <div>
+    <RectRenderer 
+      v-if="dataLoaded"
+      :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 savedProjectNo = localStorage.getItem('projectNo');
+const processId = savedProjectNo;
+const layoutData = ref(null);
+const dataLoaded = ref(false);
+
+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;
+          dataLoaded.value = true;
+          ElMessage.success("鎵撳紑鐗堝浘鎴愬姛");
+        } catch (error) {
+          ElMessage.error("瑙f瀽鏁版嵁鏃跺嚭閿�:", error);
+        }
+      } else {
+        ElMessage.error(t('basicData.msg.requestFailed'));
+      }
+    })
+    .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/glassOptimizeThirdParty/OptimizationRectPrint.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizationRectPrint.vue
new file mode 100644
index 0000000..4174687
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizationRectPrint.vue
@@ -0,0 +1,103 @@
+<template>
+  <div>
+    <el-button id="button" type="primary" @click="handlePrint">鎵撳嵃鐗堝浘</el-button>
+    <el-select 
+      v-model="printLayout" 
+      placeholder="閫夋嫨鎵撳嵃甯冨眬" 
+      @change="handleLayoutChange" 
+      style="width: 150px; margin-bottom: 10px;">
+      <el-option label="鍥涜涓ゅ垪" value="4rows-2cols"></el-option>
+      <el-option label="涓夎涓ゅ垪" value="3rows-2cols"></el-option>
+      <el-option label="涓夎涓�鍒�" value="3rows-1col"></el-option>
+      <el-option label="涓よ涓ゅ垪" value="2rows-2cols"></el-option>
+    </el-select>
+    
+    <div ref="printContainer" style="position: relative;">
+      <RectRenderer 
+        ref="rectRenderer"
+        :layoutData="layoutData" 
+        :gw="currentGw"
+        :gh="currentGh"
+        :printLayout="printLayout"
+        :printWidth="currentPrintWidth"
+        :printHeight="currentPrintHeight"
+        style="position: absolute;"
+        v-if="dataLoaded"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, watch } from 'vue';
+import RectRenderer from './page/RectRenderer.vue';
+import request from "@/utils/request";
+
+const printLayout = ref('2rows-2cols');
+const rectRenderer = ref(null);
+const savedProjectNo = localStorage.getItem('projectNo');
+const processId = savedProjectNo;
+const layoutData = ref(null);
+const dataLoaded = ref(false);
+// 瀹氫箟涓嶅悓甯冨眬瀵瑰簲鐨勫昂瀵�
+const layoutDimensions = {
+  '4rows-2cols': { width: 1000, height: 1000 },
+  '3rows-2cols': { width: 1000, height: 1000 },
+  '3rows-1col': { width: 1000, height: 1000 },
+  '2rows-2cols': { width: 1200, height: 1200 }
+};
+
+// 褰撳墠甯冨眬鐨勫昂瀵�
+const currentGw = ref(layoutDimensions[printLayout.value].width);
+const currentGh = ref(layoutDimensions[printLayout.value].height);
+const currentPrintWidth = ref(layoutDimensions[printLayout.value].width);
+const currentPrintHeight = ref(layoutDimensions[printLayout.value].height);
+
+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;
+          dataLoaded.value = true;
+        } catch (error) {
+          console.error("瑙f瀽甯冨眬鏁版嵁澶辫触:", error);
+        }
+      } else {
+        console.error("璇锋眰澶辫触锛岀姸鎬佺爜:", res.code);
+      }
+    })
+    .catch((error) => {
+      console.error("璇锋眰澶辫触:", error);
+    });
+};
+
+onMounted(() => {
+  selectLayout();
+});
+
+const handlePrint = () => {
+  if (rectRenderer.value) {
+    rectRenderer.value.print();
+  }
+};
+
+const handleLayoutChange = () => {
+  // 鏇存柊甯冨眬灏哄
+  const dimensions = layoutDimensions[printLayout.value];
+  currentGw.value = dimensions.width;
+  currentGh.value = dimensions.height;
+  currentPrintWidth.value = dimensions.width;
+  currentPrintHeight.value = dimensions.height;
+  
+  if (rectRenderer.value) {
+    rectRenderer.value.updateLayout();
+  }
+};
+
+// 鐩戝惉甯冨眬鍙樺寲
+watch(printLayout, (newVal) => {
+  handleLayoutChange();
+});
+</script>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimize.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimize.vue
new file mode 100644
index 0000000..53031ff
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/Optimize.vue
@@ -0,0 +1,72 @@
+<script setup>
+import {ArrowDown, ArrowLeftBold, ArrowRight, Search} from "@element-plus/icons-vue"
+import {useRouter,useRoute,onBeforeRouteUpdate} from "vue-router"
+import {useI18n} from "vue-i18n"
+const { t } = useI18n()
+const router = useRouter()
+const route = useRoute()
+let indexFlag=$ref(1)
+function changeRouter(index){
+  indexFlag=index
+
+}
+
+</script>
+
+<template>
+  <div id="main-div">
+    <div id="div-title">
+      <el-breadcrumb :separator-icon="ArrowRight">
+        <el-breadcrumb-item @click="changeRouter(1)" :class="indexFlag===1?'indexTag':''" :to="{ path: '/main/glassOptimizeThirdParty/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(5)" :class="indexFlag===5?'indexTag':''" :to="{ path: '/main/glassOptimizeThirdParty/OptimizeControl' }">鏁版帶
+        </el-breadcrumb-item>
+        <el-breadcrumb-item @click="changeRouter(6)" :class="indexFlag===6?'indexTag':''" :to="{ path: '/main/glassOptimizeThirdParty/optimizeparms' }">璁剧疆
+        </el-breadcrumb-item>
+        <el-breadcrumb-item></el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+
+    <div id="main-body">
+      <router-view :key="route.fullPath" />
+    </div>
+  </div>
+</template>
+
+<style scoped>
+#main-div{
+  width: 99%;
+  height: 100%;
+}
+#div-title{
+  height: 2%;
+  width: 100%;
+}
+#searchButton{
+  margin-top: -5px;
+  margin-left: 1rem;
+}
+#searchButton1{
+//margin-left: 10rem;
+}
+/*main-body鏍峰紡*/
+#main-body{
+  width: 100%;
+  height: 95%;
+  margin-top: 1%;
+}
+#select{
+  margin-left:0.5rem;
+}
+:deep(.indexTag .el-breadcrumb__inner){
+  color: #5CADFE !important;
+}
+
+.example-showcase .el-dropdown-link {
+  cursor: pointer;
+  color: var(--el-color-primary);
+  display: flex;
+  align-items: center;
+}
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue
new file mode 100644
index 0000000..fa030f7
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue
@@ -0,0 +1,93 @@
+<template>
+    <div >
+      <RectRenderer 
+    :layoutData="layoutData" 
+    :gw="1400" 
+    :gh="1100" 
+    style="width: 1500px; height: 800px; position: relative;"
+    v-if="dataLoaded"
+  />
+  
+  
+    </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 dataLoaded = ref(false);
+
+
+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;
+      dataLoaded.value = true;
+    } 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/glassOptimizeThirdParty/OptimizeMove.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeMove.vue
new file mode 100644
index 0000000..0135d34
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeMove.vue
@@ -0,0 +1,23 @@
+<template>
+    <div >
+      <RectRenderer 
+    :layoutData="layoutData" 
+    :gw="1400" 
+    :gh="1100" 
+    style="width: 1500px; height: 800px; position: relative;"
+  />
+  
+  
+    </div>
+  </template>
+  
+  <script setup>
+  import { ref } from 'vue';
+  import RectRenderer from './page/RectRenderer.vue';
+  import mockLayoutData from '../../../components/pp/MockData';
+  
+  const layoutData = ref(mockLayoutData);
+  
+  
+  </script>
+  
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeParms.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeParms.vue
new file mode 100644
index 0000000..67cd4b0
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/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>闀胯酱榛樿闂撮殧(mm)</label>
+            <input type="number" v-model="settings.tempering.xAxisInterval" step="1" />
+          </div>
+          <div class="form-group">
+            <label>瀹借酱榛樿闂撮殧(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/glassOptimizeThirdParty/OptimizePrint.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizePrint.vue
new file mode 100644
index 0000000..e6fd0ff
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizePrint.vue
@@ -0,0 +1,80 @@
+<script setup>
+ import {ref} from "vue";
+
+ const layout=ref([
+   {"x":0,"y":0,"w":50,"h":50,"i":"0"},
+   /*{"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":3,"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"}*/
+ ])
+
+ const layoutUpdated = (newLayout) => {
+   //checkLayoutBounds(newLayout)
+ }
+ const checkLayoutBounds = (layout1) => {
+   layout1.forEach(item => {
+     // 妫�鏌ヨ竟鐣岋紝渚嬪纭繚x鍜寉涓嶅皬浜�0锛屽苟涓攚鍜宧涓嶈秴鍑烘渶澶у�肩瓑銆�
+     if (item.x < 0) item.x = 0;
+     if (item.y < 0) item.y = 0;
+     if (item.w > 12) item.w = 12; // 鍋囪鏈�澶у垪鏁颁负12
+     if (item.h > 10) item.h = 10; // 鍋囪鏈�澶ц涓�10锛堟牴鎹渶瑕佽皟鏁达級
+   });
+   layout.value = layout1; // 搴旂敤杈圭晫妫�鏌ュ悗鐨勫竷灞�
+   console.log(layout1)
+ }
+ const moveEvent = (i, newX, newY) => {
+   console.log(`绉诲姩鍏冪礌 ${i} 鍒� (${newX}, ${newY})`)
+ }
+
+</script>
+
+<template>
+  <grid-layout
+      style="border:1px solid black;height: 244px;width: 366px;overflow: hidden;grid-template-columns: 1px"
+      :layout.sync="layout"
+      :col-num="366"
+      :row-height="1"
+      :is-draggable="true"
+      :is-resizable="false"
+      :is-mirrored="false"
+      :vertical-compact="true"
+      :margin="[0, 0]"
+      :use-css-transforms="true"
+      :autoSize="false"
+      @layout-updated="layoutUpdated"
+  >
+
+    <grid-item v-for="item in layout"
+               :x="item.x"
+               :y="item.y"
+               :w="item.w"
+               :h="item.h"
+               :i="item.i"
+               :key="item.i"
+               @move="moveEvent"
+               style="background-color: white"
+    >
+      {{item.i}}
+    </grid-item>
+  </grid-layout>
+</template>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeProject.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeProject.vue
new file mode 100644
index 0000000..45a11bb
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeProject.vue
@@ -0,0 +1,96 @@
+<script setup>
+import GlassInventory from "@/views/pp/glassOptimizeThirdParty/page/GlassInventory.vue"
+import ProjectDetail from "@/views/pp/glassOptimizeThirdParty/page/ProjectDetail.vue"
+import GlassComputed from "@/views/pp/glassOptimizeThirdParty/GlassComputed.vue";
+import ProjectMange from "@/views/pp/glassOptimizeThirdParty/ProjectMange.vue";
+
+import {ref} from "vue";
+let dialogVisible = ref(false)
+let detailPage = ref(0)
+const changeDialog = (value) => {
+  dialogVisible.value = true
+  detailPage.value = value
+}
+
+//浠庡伐绋嬬鐞嗚幏鍙栧伐绋嬪彿锛屽苟璺宠浆
+const projectNumber = ref();
+const switchDialog = (number) => {
+  projectNumber.value = number;
+  detailPage.value = 3;
+};
+
+//宸ョ▼绠$悊鍏抽棴寮圭獥
+const handlePopupClose = () => {
+  dialogVisible.value = false;
+};
+
+//鑾峰彇SetTrimming鐨勫��
+const dataForGlassInventory = ref();
+const handleProjectDetailData = (data) => {
+  dataForGlassInventory.value = data;
+};
+
+//鑾峰彇GlassInventory鐨勫��(鏌ヨ搴撳瓨)
+const sendDataGlassInventory = ref()
+const handleInventoyData = (selectedLabel1,selectedLabel2,type) => {
+  sendDataGlassInventory.value = {
+    selectedLabel1, selectedLabel2,type
+  };
+};
+
+//鍙抽敭鑿滃崟鎵撳紑淇竟
+const isTrimmingDialogVisible = ref(false);
+const sendTrimming = (value) => {
+    isTrimmingDialogVisible.value = value;
+  };
+
+</script>
+
+<template >
+ <div style="width: 100%;height: 100%">
+   <div id="main-body">
+     <project-detail @changeDialog="changeDialog"
+                     @forward-data-to-grandparent="handleProjectDetailData"
+                     @send-inventory-to-op="handleInventoyData"
+                     :TrimmingDialogVisible="isTrimmingDialogVisible" />
+   </div>
+   <div id="main-footer">
+     <glass-inventory :receivedData="dataForGlassInventory"
+                      :InventoryData="sendDataGlassInventory"
+                      @select-trimming="sendTrimming"/>
+   </div>
+
+
+   <el-dialog
+       v-model="dialogVisible"
+       :title=" detailPage ===2? '宸ョ▼绠$悊' : detailPage ===3? '妯℃嫙璁$畻':''"
+       destroy-on-close
+       style="width: 90%;height:90%;margin-top: 3vh"
+       z-index="100"
+   >
+     <project-mange  v-if="detailPage===2" @switch-dialog="switchDialog" @closeDetailPage="handlePopupClose"/>
+     <glass-computed v-if="detailPage===3" :project="projectNumber"/>
+     <div v-else></div>
+   </el-dialog>
+
+ </div>
+</template>
+
+<style scoped>
+#main-body{
+  width: 100%;
+  height: 60%;
+}
+#main-footer{
+  margin-top: 10px;
+  width: 100%;
+  height: calc(40% - 10px);
+}
+:deep( .el-dialog__body){
+  height: calc(100% - 55px);
+  width: 100%;
+  margin-top: 30px;
+  //padding: 0;
+}
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectCreate.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectCreate.vue
new file mode 100644
index 0000000..68ced28
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectCreate.vue
@@ -0,0 +1,391 @@
+<script setup>
+import ProcessCard from "@/views/pp/glassOptimize/page/ProcessCard.vue";
+import ProcessCardDetail from "@/views/pp/glassOptimize/page/ProcessCardDetail.vue";
+import ProjectList from "@/views/pp/glassOptimize/page/ProjectList.vue";
+
+import {defineEmits, nextTick, onMounted, reactive, ref} from "vue";
+import {useI18n} from "vue-i18n";
+import GlassComputed from "@/views/pp/glassOptimize/GlassComputed.vue";
+import ProjectMange from "@/views/pp/glassOptimize/ProjectMange.vue";
+import request from "@/utils/request";
+import {ElMessage, ElMessageBox} from "element-plus";
+import deepClone from "@/utils/deepClone";
+import {useRouter} from "vue-router";
+import {changeFilterEvent, filterChanged} from "@/hook";
+
+const router = useRouter();
+let projectRow = ref({
+  processId:null,
+  technologyNumber:null
+})
+
+const  processCardRef=ref(null)
+
+const handleProcessIdUpdate = newProcessId => {
+  projectRow.value.processId = newProcessId;
+
+};
+
+const handleTechnologyNumberUpdate = newTechnologyNumber => {
+  projectRow.value.technologyNumber = newTechnologyNumber;
+};
+
+const updateState = state => {
+  getProject();
+
+};
+
+
+const { t } = useI18n()
+
+const xGrid = ref()
+
+
+const gridOptions = reactive({
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProjectList',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    //remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+  columns:[
+    {field: 'id',width: 150, title: 'ID'},
+    {field: 'projectNumber',width: 150, title: '宸ョ▼鍙�',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'project_name',width: 150, title: '椤圭洰鍚嶇О',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'glass_type',width: 150, title: '鑶滅郴',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'glass_thickness',width: 150, title: '鍘氬害',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'type',width: 150, title: '绫诲瀷',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'state',width: 150, title: '鐘舵��',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'quantity',width: 150, title: t('order.quantity')},
+    {field: 'glass_total_area',width: 150, title: t('order.grossArea'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'process_qty',width: 150, title: '娴佺▼鏁伴噺',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'process_cards',width: 150, title: '娴佺▼鍗″彿',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [
+    ],
+    import: false,
+    // export: true,
+    // print: true,
+    zoom: true,
+    custom: true
+  },
+  //鍙抽敭鑿滃崟閫夐」
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {code: 'openProject', name: '鎵撳紑宸ョ▼', prefixIcon: 'vxe-icon-folder-open'},
+          {code: 'updateProject', name: '淇敼宸ョ▼', prefixIcon: 'vxe-icon-folder-open'},
+          {code: 'compute', name: '妯℃嫙璁$畻', prefixIcon: 'vxe-icon-subtable'},
+          {code: 'delProject', name: '鍒犻櫎宸ョ▼', prefixIcon: 'vxe-icon-delete'},
+        ],
+        []
+      ]
+    }
+  }
+
+})
+
+// 瀹氫箟鎿嶄綔閰嶇疆瀵硅薄鏁扮粍锛岄泦涓鐞嗕笉鍚屾搷浣滈�夐」瀵瑰簲鐨勫弬鏁�
+const operationConfigs = [
+  {
+    code: 'openProject', // 鎵撳紑宸ョ▼
+    initialState: ['1'], //
+    targetState: null,
+    successMsg: '宸叉墦寮�锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    openFile: async ({row}) => {
+      const projectNumber = row.projectNumber;
+      const thickness = row.glass_thickness;
+      const glassType = row.glass_type;
+      await router.push({
+        name: 'optimizeInfo',
+        params: {
+          projectNo: projectNumber,
+          thickNess: thickness,
+          model: glassType
+        }
+      });
+    }
+  },
+  {
+    code: 'compute', // 鎵撳紑妯℃嫙璁$畻鎿嶄綔
+    initialState: ['1'], //
+    targetState: null,
+    successMsg: '妯℃嫙璁$畻宸插惎鍔紒',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎妯℃嫙璁$畻鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    actionFunction: async ({row}) => {
+      const projectNo = row.projectNumber;
+      emit('switch-dialog', row);
+    }
+  },
+  {
+    code: 'delProject',
+    initialState: ['1'],
+    targetState: null,
+    successMsg: '宸ョ▼鍒犻櫎鎴愬姛锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鍒犻櫎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+  },
+  {
+    code: 'updateProject',
+        initialState: ['1'],
+      targetState: null,
+      successMsg: '',
+      checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鍒犻櫎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+  }
+
+];
+
+//瀹氫箟鍒囨崲妯℃嫙璁$畻寮圭獥
+const emit = defineEmits(['switch-dialog']);
+
+onMounted(async () => {
+  getProject();
+})
+
+// 瀹氫箟鏁版嵁杩斿洖缁撴灉锛屼娇鐢╮ef鍒涘缓鍝嶅簲寮忔暟鎹紝鍒濆鍖栦负绌烘暟缁�
+let produceList = ref([])
+
+const getProject = ()=>{
+  request.post(`/glassOptimize/getProjectList`).then((res) => {
+    if(res.code==200){
+      produceList.value = deepClone(res.data.data);
+      xGrid.value.loadData(produceList.value)
+    }else{
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+
+// 鍏叡澶勭悊鍑芥暟锛屽鐞嗙浉鍚屾暟鎹椂鐨勬搷浣滐紝骞惰繑鍥瀟argetRoute瀵硅薄锛堝彸閿彍鍗曞拰鍙屽嚮鎵撳紑锛�
+const handleSameDataOperation = async ({projectNumber, thickness, glassType}) => {
+  const targetRoute = {
+    name: 'optimizeInfo',
+    params: {
+      projectNo: projectNumber,
+      thickNess: String(thickness),
+      model: glassType
+    }
+  };
+  const currentRoute = router.currentRoute.value;
+  const isRoutesEqual = currentRoute.name === targetRoute.name &&
+      currentRoute.params.projectNo === targetRoute.params.projectNo &&
+      currentRoute.params.thickNess === targetRoute.params.thickNess &&
+      currentRoute.params.model === targetRoute.params.model;
+  if (isRoutesEqual) {
+    handleConfirm();
+  }
+  return {isRoutesEqual};
+};
+
+//閫変腑鐩稿悓鏁版嵁鏃跺脊绐楁彁绀�
+const handleConfirm = () => {
+  const currentRoute = router.currentRoute.value;
+  const projectNumber = currentRoute.params.projectNo;
+  ElMessageBox.confirm(`褰撳墠宸ョ▼锛堝伐绋嬪彿锛�${projectNumber}锛夊凡鎵撳紑锛屾槸鍚﹂噸鏂版墦寮�锛焋, '纭鎿嶄綔', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  })
+      .then(() => {
+        emit('close-detail-page');
+        ElMessage.success('宸叉墦寮�锛�');
+      })
+      .catch(() => {
+        ElMessage.info('宸插彇娑堟搷浣�');
+      });
+};
+
+const gridEvents = {
+  menuClick({menu, row}) {
+    const $grid = xGrid.value;
+    if ($grid) {
+      const config = operationConfigs.find(c => c.code === menu.code);
+      if (config) {
+        if (config.requiresRow && !row) {
+          ElMessage.warning('鏈�変腑宸ョ▼锛岃閫変腑宸ョ▼鍚庡啀杩涜褰撳墠鎿嶄綔锛�');
+          return;
+        }
+        if (config.code === 'compute') {
+          config.actionFunction({row});
+          return;
+        }
+        if (config.code === 'updateProject') {
+          if (!row) {
+            ElMessage.warning(config.checkMessage);
+            return;
+          }
+          processCardRef.value.getUpdateFlowCardList(row.projectNumber,row.glass_type,row.glass_thickness);
+          return;
+        }
+        if (config.code === 'openProject') {
+          handleSameDataOperation(row).then(({isRoutesEqual}) => {
+            if (!isRoutesEqual) {
+              config.openFile({row});
+              ElMessage.success(config.successMsg);
+            }
+          });
+        }
+        // 娣诲姞纭鎻愮ず寮圭獥锛岃闂敤鎴锋槸鍚﹁繘琛屽綋鍓嶆搷浣�
+        ElMessageBox.confirm('鏄惁杩涜褰撳墠鎿嶄綔锛�', '纭鎿嶄綔', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          if (config.code === 'delProject') {
+            if (!row) {
+              ElMessage.warning(config.checkMessage);
+              return;
+            }
+            const isInitialStateMatched = config.initialState.includes(String(row.state));
+            if (!isInitialStateMatched) {
+              ElMessage.warning(config.checkMessage);
+              return;
+            }
+            deleteProject(row.projectNumber, config);
+          }
+        }).catch(() => {
+          // 鐢ㄦ埛鐐瑰嚮鍙栨秷鍚庢墽琛岀殑閫昏緫
+          ElMessage.info('宸插彇娑堟搷浣�');
+        });
+      } else {
+        console.error(`鏈壘鍒版搷浣滈�夐」 ${menu.code} 瀵瑰簲鐨勯厤缃紝璇锋鏌ラ厤缃」`);
+      }
+    }
+  }
+};
+
+
+function deleteProject(projectNumber, config) {
+  request.post(`/glassOptimize/deleteProject/${projectNumber}`, {
+    headers: {
+      'Content-Type': 'application/json'
+    }
+  }).then((res) => {
+    if (res.code==200 && res.data===true) {
+      ElMessage.success(config.successMsg);
+      // 浠庡垪琛ㄤ腑绉婚櫎宸插垹闄ょ殑宸ョ▼鏁版嵁
+      const index = produceList.value.findIndex(item => item.projectNumber === projectNumber);
+      if (index !== -1) {
+        produceList.value.splice(index, 1);
+        xGrid.value.reloadData(produceList.value);
+      }
+      //鍒锋柊宸ョ▼鍙�
+      processCardRef.value.getProjectId();
+      processCardRef.value.selectGlassType();
+      processCardRef.value.selectFlowCardList();
+    } else {
+      console.log('res.code 鐨勫��:', res.code, ', 绫诲瀷:', typeof res.code);
+      console.log('res.msg 鐨勫��:', res.msg, ', 绫诲瀷:', typeof res.msg);
+      const errorMsg = res.data ? res.data.errorMessage : config.failureMsg;
+      ElMessage.error(`鎿嶄綔澶辫触锛屽師鍥�: ${errorMsg}`);
+    }
+  }).catch((error) => {
+    console.error('璇锋眰鍑洪敊锛屽伐绋嬪垹闄ゆ湭瀹屾垚锛岃缁嗛敊璇俊鎭�:', error);
+    ElMessage.error(`璇锋眰鍑洪敊锛屽伐绋嬪垹闄ゆ湭瀹屾垚锛屽師鍥�: ${errorMsg}`);
+  });
+}
+
+</script>
+
+<template>
+  <div style="width: 100%; height: 100%;">
+
+    <div id="processCard">
+      <process-card ref="processCardRef" :process-id="projectRow.processId===null?null:projectRow.processId"
+                    :technology-number="projectRow.technologyNumber===null?null:projectRow.technologyNumber"
+                    @updateProcessId="handleProcessIdUpdate"
+                    @updateTechnologyNumber="handleTechnologyNumberUpdate"
+                    @updateState="updateState"
+      />
+    </div>
+
+    <div id="processCard-detail" >
+      <process-card-detail :process-id="projectRow.processId===null?null:projectRow.processId"
+                           :technology-number="projectRow.technologyNumber===null?null:projectRow.technologyNumber"/>
+    </div>
+
+    <div id="project-list">
+      <div style="width: 100%;height: 100%">
+        <h1>宸ョ▼鍒楄〃</h1>
+        <vxe-grid
+            size="small"
+            height="100%"
+            class="mytable-scrollbar"
+            ref="xGrid"
+            v-bind="gridOptions"
+            v-on="gridEvents"
+        >
+
+          <template #num2_filter="{ column, $panel }">
+            <div>
+              <div v-for="(option, index) in column.filters" :key="index">
+                <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+                  <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+                  <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+                </vxe-select>
+              </div>
+            </div>
+          </template>
+
+          <template #num1_filter="{ column, $panel }">
+            <div>
+              <div v-for="(option, index) in column.filters" :key="index">
+                <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
+              </div>
+            </div>
+          </template>
+        </vxe-grid>
+      </div>
+    </div>
+
+
+
+  </div>
+</template>
+
+
+<style scoped>
+#processCard{
+  width: 64%;
+  height: 55%;
+  float: left;
+}
+#processCard-detail{
+  margin-left: 1%;
+  float: left;
+  width: 35%;
+  height: 55%;
+}
+#project-list{
+  float: left;
+  margin-top: 2%;
+  width: 100%;
+  height: 30%;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectMange.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectMange.vue
new file mode 100644
index 0000000..ed096b1
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/ProjectMange.vue
@@ -0,0 +1,702 @@
+<script setup>
+import {computed, nextTick, reactive, ref} from "vue";
+import {useI18n} from "vue-i18n";
+import deepClone from "@/utils/deepClone"
+import {Search} from "@element-plus/icons-vue";
+import request from "@/utils/request";
+import {ElDatePicker, ElMessage, ElMessageBox} from "element-plus";
+import useOrderInfoStore from "@/stores/sd/order/orderInfo";
+import useUserInfoStore from "@/stores/userInfo";
+import userInfo from "@/stores/userInfo";
+import {useRouter} from 'vue-router';
+import {defineEmits} from 'vue';
+import {changeFilterEvent, filterChanged} from "@/hook";
+
+
+const {t} = useI18n()
+const userStore = useUserInfoStore()
+const user = userInfo()
+const orderInfo = useOrderInfoStore()
+
+const router = useRouter();
+
+const xGrid = ref()
+const gridOptions = reactive({
+  height: '100%',
+  loading: false,
+  border: "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe: true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true, height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProjectMange',
+  scrollX: {enabled: true},
+  scrollY: {enabled: true, gt: 0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow: true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    //remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+
+  columns: [
+    {type: 'seq', title: t('basicData.Number'), width: 80},
+    {field: 'projectNumber', width: 100, title: '宸ョ▼鍙�',sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'projectName', width: 50, title: '鍚嶇О',},
+    {field: 'glassType', width: 50, title: '鑶滅郴',},
+    {field: 'thickness', width: 50, title: '鍘氬害',},
+    {field: 'type', width: 50, title: '绫诲瀷',},
+    {field: 'state', width: 50, title: '鐘舵��',},
+    {field: 'quantity', width: 50, title: '鏁伴噺',},
+    {field: 'area', width: 50, title: '闈㈢Н',},
+    {field: 'processCardQuantity', width: 100, title: '娴佺▼鍗℃暟閲�',},
+    {field: 'usingQuantity', width: 100, title: '鍘熺墖浣跨敤鏁�',},
+    {field: 'processCardCollection', width: 70, title: '娴佺▼鍗�',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged},
+    {field: 'temperedLoadingRate', width: 100, title: '閽㈠寲瑁呰浇鐜�',},
+    {field: 'numberOfTemperingFurnaces', width: 100, title: '閽㈠寲鐐夋暟',},
+    {field: 'averageCuttingRate', width: 100, title: '骞冲潎鍒囪鐜�',},
+    {field: 'effectiveCuttingRate', width: 100, title: '鏈夋晥鍒囪鐜�',},
+    {field: 'residueGlassCuttingRate', width: 100, title: '灏剧墖鍒囪鐜�',},
+    {field: 'amountOfOriginalGlassUsage1', width: 100, title: '鍘熸枡浣跨敤鏁�',},
+    {field: 'averageCuttingRate1', width: 100, title: '骞冲潎鍒囪鐜�',},
+    {field: 'notes', width: 50, title: '澶囨敞',},
+    {field: 'creator', width: 100, title: '鍒涘缓浜�',},
+    {field: 'createTime', width: 100, title: '鍒涘缓鏃堕棿',},
+    {field: 'modifyTime', width: 100, title: '淇敼鏃堕棿',},
+  ],//琛ㄥご鍙傛暟
+  data: null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [
+    ],
+    import: false,
+    // export: true,
+    // print: true,
+    zoom: true,
+    custom: true
+  },
+  //鍙抽敭鑿滃崟閫夐」
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {code: 'openProject', name: '鎵撳紑宸ョ▼', prefixIcon: 'vxe-icon-folder-open'},
+          {code: 'compute', name: '妯℃嫙璁$畻', prefixIcon: 'vxe-icon-subtable'},
+          {code: 'production', name: '鍏佽鐢熶骇', prefixIcon: 'vxe-icon-square-checked'},
+          {code: 'novisible', name: '鐢熶骇涓嶅彲瑙�', prefixIcon: 'vxe-icon-eye-fill-close'},
+          {code: 'undoCompute', name: '鎾ら攢妯℃嫙璁$畻', prefixIcon: 'vxe-icon-error-circle-fill'},
+          {code: 'delProject', name: '鍒犻櫎宸ョ▼', prefixIcon: 'vxe-icon-delete'},
+          {code: 'viewTempered', name: '鏌ョ湅閽㈠寲鐗堝浘', prefixIcon: 'vxe-icon-custom-column'},
+          {code: 'Export', name: '鏁版嵁瀵煎嚭', prefixIcon: 'vxe-icon-download', visible: true, disabled: false},
+
+        ],
+        []
+      ]
+    },
+  },
+})
+// 瀹氫箟鎿嶄綔閰嶇疆瀵硅薄鏁扮粍锛岄泦涓鐞嗕笉鍚屾搷浣滈�夐」瀵瑰簲鐨勫弬鏁�
+const operationConfigs = [
+  {
+    code: 'openProject', // 鎵撳紑宸ョ▼
+    initialState: ['2','10', '100', '200'], //
+    targetState: null,
+    successMsg: '宸叉墦寮�锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    openFile: async ({row}) => {
+      const projectNumber = row.projectNumber;
+      const thickness = row.thickness;
+      const glassType = row.glassType;
+      await router.push({
+        name: 'optimizeInfo',
+        params: {
+          projectNo: projectNumber,
+          thickNess: thickness,
+          model: glassType
+        }
+      });
+    }
+  },
+  {
+    code: 'compute', // 鎵撳紑妯℃嫙璁$畻鎿嶄綔
+    initialState: '2',
+    targetState: null,
+    successMsg: '妯℃嫙璁$畻宸插惎鍔紒',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎妯℃嫙璁$畻鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    actionFunction: async ({row}) => {
+      const projectNo = row.projectNumber;
+      emit('switch-dialog', row);
+    }
+  },
+  {
+    code: 'undoCompute',
+    initialState: '10',
+    targetState: 2,
+    successMsg: '鎾ら攢妯℃嫙璁$畻鎴愬姛锛屾暟鎹凡鏇存柊锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鎾ら攢妯℃嫙璁$畻鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+  },
+  {
+    code: 'production',
+    initialState: '10',
+    targetState: 100,
+    successMsg: '璁剧疆鎴愬姛锛屽厑璁哥敓浜э紒',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鍏佽鐢熶骇鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+  },
+  {
+    code: 'novisible',
+    initialState: '100',
+    targetState: 10,
+    successMsg: '璁剧疆鎴愬姛锛岀敓浜т笉鍙锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鐢熶骇涓嶅彲瑙佹潯浠讹紝璇风‘璁ゅ伐绋嬬姸鎬佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+  },
+  {
+    code: 'delProject',
+    initialState: ['2', '10'],
+    targetState: null,
+    successMsg: '宸ョ▼鍒犻櫎鎴愬姛锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鍒犻櫎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+  },
+  {
+    code: 'Export', // 瀵煎嚭鏂囦欢鎿嶄綔鐨勯厤缃�
+    initialState: [],
+    targetState: null,
+    successMsg: '鏂囦欢瀵煎嚭鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+  },
+  {
+    code: 'viewTempered',
+    initialState: [],
+    targetState: null,
+    successMsg: '閽㈠寲鐗堝浘宸叉墦寮�锛�',
+    failureMsg: '宸ョ▼鍒犻櫎澶辫触锛岃鑱旂郴绠$悊鍛橈紒',
+  }
+];
+
+function getOriginalState(targetState) {
+  // 鏍规嵁宸ョ▼鐘舵�佽繑鍥炲搴旂殑鍘熷鐘舵��
+  const stateMapping = {
+    2: '10',
+    10: '100',
+    100: '200',
+    200: '100'
+  };
+  return stateMapping[targetState] || targetState;
+}
+
+//鍙抽敭鑿滃崟鏉′欢鍒ゆ柇
+function checkOperationCondition(config, row) {
+  if (!config.requiresRow || !row) {
+    return false;
+  }
+  if (Array.isArray(config.initialState)) {
+    return config.initialState.includes(String(row.state));
+  }
+  return config.initialState === String(row.state);
+}
+
+// 鍙抽敭鑿滃崟鐐瑰嚮浜嬩欢
+const gridEvents = {
+  menuClick({menu, row}) {
+    const $grid = xGrid.value;
+    if ($grid) {
+      const config = operationConfigs.find(c => c.code === menu.code);
+      if (config) {
+        if (config.requiresRow && !row) {
+          ElMessage.warning('鏈�変腑宸ョ▼锛岃閫変腑宸ョ▼鍚庡啀杩涜褰撳墠鎿嶄綔锛�');
+          return;
+        }
+        if (!checkOperationCondition(config, row)) {
+          ElMessage.warning(config.checkMessage);
+          return;
+        }
+        if (config.code === 'Export') {
+          config.gridRef.value.exportData();
+          ElMessage.success(config.successMsg);
+          return;
+        }
+        if (config.code === 'compute') {
+          config.actionFunction({row});
+          return;
+        }
+        // 娣诲姞纭鎻愮ず寮圭獥锛岃闂敤鎴锋槸鍚﹁繘琛屽綋鍓嶆搷浣�
+        ElMessageBox.confirm('鏄惁杩涜褰撳墠鎿嶄綔锛�', '纭鎿嶄綔', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          if (config.code === 'viewTempered') {
+            ElMessageBox.alert('褰撳墠鐐瑰嚮鐨勬槸鏌ョ湅閽㈠寲鐗堝浘鍔熻兘锛岀洰鍓嶆殏鏃朵粎鍋氭彁绀猴紝鏆傛棤瀹為檯鏌ョ湅鎿嶄綔!', '鍔熻兘鎻愮ず', {
+              confirmButtonText: '鎴戠煡閬撲簡'
+            });
+            return;
+          }
+          if (config.code === 'viewOptimize') {
+            ElMessageBox.alert('褰撳墠鐐瑰嚮鐨勬槸鏌ョ湅閽㈠寲鐗堝浘鍔熻兘锛岀洰鍓嶆殏鏃朵粎鍋氭彁绀猴紝鏆傛棤瀹為檯鏌ョ湅鎿嶄綔!', '鍔熻兘鎻愮ず', {
+              confirmButtonText: '鎴戠煡閬撲簡'
+            });
+            return;
+          }
+          if (config.code === 'delProject') {
+            if (!row) {
+              ElMessage.warning(config.checkMessage);
+              return;
+            }
+            deleteProject(row.projectNumber, config);
+          } else {
+            if (config.code === 'openProject') {
+              handleSameDataOperation(row).then(({isRoutesEqual}) => {
+                if (!isRoutesEqual) {
+                  config.openFile({row});
+                  ElMessage.success(config.successMsg);
+                }
+              });
+            } else if (config.code === 'compute') {
+              config.actionFunction({row});
+            } else  if (config.code === 'optimizeTypography') {
+              handleSameDataOperation(row).then(({isRoutesEqual}) => {
+                if (!isRoutesEqual) {
+                  config.Typography({row});
+                  ElMessage.success(config.successMsg);
+                }
+              });
+            }
+            else {
+              row.state = config.targetState;
+              let code=0
+              const index = produceList.value.findIndex(item => item === row);
+              if (index !== -1) {
+                produceList.value.splice(index, 1, {...row});
+                xGrid.value.reloadData(produceList.value);
+              }
+              if(config.code === 'undoCompute'){
+                code=1
+              }else if(config.code === 'undoOptimize'){
+                code=2
+              }
+              else if(config.code === 'production'){
+                code=3
+              }
+              else if(config.code === 'novisible'){
+                code=4
+              }
+              else if(config.code === 'InitializeProject'){
+                code=5
+              }
+              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,code, config.successMsg);
+            }
+          }
+        }).catch(() => {
+          // 鐢ㄦ埛鐐瑰嚮鍙栨秷鍚庢墽琛岀殑閫昏緫
+          ElMessage.info('宸插彇娑堟搷浣�');
+        });
+      } else {
+        console.error(`鏈壘鍒版搷浣滈�夐」 ${menu.code} 瀵瑰簲鐨勯厤缃紝璇锋鏌ラ厤缃」`);
+      }
+    }
+  },
+  cellDblclick: ({row}) => {
+    const menu = {code: 'openProject'};
+    nextTick(() => {
+      handleSameDataOperation(row).then(({isRoutesEqual}) => {
+        if (!isRoutesEqual) {
+          gridEvents.menuClick({menu, row});
+        }
+      });
+    });
+  },
+};
+
+// 鍏叡澶勭悊鍑芥暟锛屽鐞嗙浉鍚屾暟鎹椂鐨勬搷浣滐紝骞惰繑鍥瀟argetRoute瀵硅薄锛堝彸閿彍鍗曞拰鍙屽嚮鎵撳紑锛�
+const handleSameDataOperation = async ({projectNumber, thickness, glassType}) => {
+  const targetRoute = {
+    name: 'optimizeInfo',
+    params: {
+      projectNo: projectNumber,
+      thickNess: String(thickness),
+      model: glassType
+    }
+  };
+  const currentRoute = router.currentRoute.value;
+  const isRoutesEqual = currentRoute.name === targetRoute.name &&
+      currentRoute.params.projectNo === targetRoute.params.projectNo &&
+      currentRoute.params.thickNess === targetRoute.params.thickNess &&
+      currentRoute.params.model === targetRoute.params.model;
+  if (isRoutesEqual) {
+    handleConfirm();
+  }
+  return {isRoutesEqual};
+};
+//閫変腑鐩稿悓鏁版嵁鏃跺脊绐楁彁绀�
+const handleConfirm = () => {
+  const currentRoute = router.currentRoute.value;
+  const projectNumber = currentRoute.params.projectNo;
+  ElMessageBox.confirm(`褰撳墠宸ョ▼锛堝伐绋嬪彿锛�${projectNumber}锛夊凡鎵撳紑锛屾槸鍚﹂噸鏂版墦寮�锛焋, '纭鎿嶄綔', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  })
+      .then(() => {
+        emit('close-detail-page');
+        ElMessage.success('宸叉墦寮�锛�');
+      })
+      .catch(() => {
+        ElMessage.info('宸插彇娑堟搷浣�');
+      });
+};
+
+
+// 灏佽鍙戦�佸彸閿彍鍗曡姹傘�佸鐞嗗搷搴斾互鍙婇敊璇洖婊氱瓑閫昏緫鐨勫嚱鏁�
+function rollbackStateAndReloadGrid(row, targetState) {
+  row.state = getOriginalState(targetState);
+  const rollbackIndex = produceList.value.findIndex(item => item === row);
+  if (rollbackIndex !== -1) {
+    produceList.value.splice(rollbackIndex, 1, {...row});
+    xGrid.value.reloadData(produceList.value);
+  }
+}
+
+function updateProjectStateAndHandleResponse(row, projectNumber, targetState,code, successMsg) {
+  const updateParams = {
+    projectNumber: projectNumber,
+    stateToUpdate: targetState
+  };
+  request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${code}`, updateParams, {
+    headers: {
+      'Content-Type': 'application/json'
+    }
+  }).then((res) => {
+    if (Number(res.code) === 200 && (res.msg === "" || res.msg === null)) {
+      ElMessage.success(successMsg);
+    } else {
+      console.log('res.code 鐨勫��:', res.code, ', 绫诲瀷:', typeof res.code);
+      console.log('res.msg 鐨勫��:', res.msg, ', 绫诲瀷:', typeof res.msg);
+      const errorMsg = res.data ? res.data.errorMessage : '鎿嶄綔澶辫触锛屾湭鑾峰彇鍒板叿浣撳師鍥狅紝璇疯仈绯荤鐞嗗憳';
+      ElMessage.error(`鎿嶄綔澶辫触锛屽師鍥�: ${errorMsg}`);
+      rollbackStateAndReloadGrid(row, targetState); // 璋冪敤鍥炴粴鍑芥暟
+    }
+  }).catch((error) => {
+    console.error('璇锋眰鍑洪敊锛屾搷浣滄湭瀹屾垚锛岃缁嗛敊璇俊鎭�:', error);
+    const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : '鎿嶄綔澶辫触锛屾湭鑾峰彇鍒板叿浣撳師鍥狅紝璇疯仈绯荤鐞嗗憳';
+    ElMessage.error(`璇锋眰鍑洪敊锛屾搷浣滄湭瀹屾垚锛屽師鍥�: ${errorMsg}`);
+    rollbackStateAndReloadGrid(row, targetState); // 璋冪敤鍥炴粴鍑芥暟
+  });
+}
+
+//鍒犻櫎宸ョ▼
+function deleteProject(projectNumber, config) {
+  request.post(`/glassOptimize/deleteProjectThirdParty/${projectNumber}`, {
+    headers: {
+      'Content-Type': 'application/json'
+    }
+  }).then((res) => {
+    if (res.code==200 && res.data===true) {
+      ElMessage.success(config.successMsg);
+      // 浠庡垪琛ㄤ腑绉婚櫎宸插垹闄ょ殑宸ョ▼鏁版嵁
+      const index = produceList.value.findIndex(item => item.projectNumber === projectNumber);
+      if (index !== -1) {
+        produceList.value.splice(index, 1);
+        xGrid.value.reloadData(produceList.value);
+      }
+    } else {
+      console.log('res.code 鐨勫��:', res.code, ', 绫诲瀷:', typeof res.code);
+      console.log('res.msg 鐨勫��:', res.msg, ', 绫诲瀷:', typeof res.msg);
+      const errorMsg = res.data ? res.data.errorMessage : config.failureMsg;
+      ElMessage.error(`鎿嶄綔澶辫触锛屽師鍥�: ${errorMsg}`);
+    }
+  }).catch((error) => {
+    console.error('璇锋眰鍑洪敊锛屽伐绋嬪垹闄ゆ湭瀹屾垚锛岃缁嗛敊璇俊鎭�:', error);
+    const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : config.failureMsg;
+    ElMessage.error(`璇锋眰鍑洪敊锛屽伐绋嬪垹闄ゆ湭瀹屾垚锛屽師鍥�: ${errorMsg}`);
+  });
+}
+
+//瀹氫箟鍒囨崲妯℃嫙璁$畻寮圭獥
+const emit = defineEmits(['switch-dialog', 'close-detail-page']);
+
+//瀹氫箟宸ョ▼鐘舵��
+const optionVal = ref('all')
+const options = [
+  {
+    value: 'all',
+    label: '鍏ㄩ儴',
+  },
+  {
+    value: '2',
+    label: '浼樺寲瀹屾垚锛�2',
+  },
+  {
+    value: '10',
+    label: '妯℃嫙璁$畻锛�10',
+  },
+  {
+    value: '100',
+    label: '鐢熶骇鍙锛�100',
+  },
+  {
+    value: '200',
+    label: '鐢熶骇棰嗗彇锛�200',
+  },
+]
+
+//宸ョ▼鐘舵�佸嚱鏁�
+function handleOptionChange() {
+  if (optionVal.value === 'all') {
+    // 娓呯┖宸ョ▼鐘舵�佺浉鍏崇殑宸叉湁绛涢�夋潯浠�
+    delete filterData.value['state'];
+  } else {
+    filterData.value['state'] = optionVal.value; // 鏄庣‘娣诲姞閫夋嫨鐨勫伐绋嬬姸鎬佸�煎埌绛涢�夋潯浠朵腑
+  }
+  getWorkOrder();
+}
+
+//鍏叡鍑芥暟
+function buildRequestParams() {
+  let startSelectTime = orderInfo.workOrderDate[0];
+  let endSelectTime = orderInfo.workOrderDate[1];
+
+  const params = {
+    startSelectTime,
+    endSelectTime,
+  };
+
+  return params;
+}
+
+//绛涢�夋潯浠�
+let filterData = ref({
+  projectNumber: '',
+})
+// 瀹氫箟鏁版嵁杩斿洖缁撴灉锛屼娇鐢╮ef鍒涘缓鍝嶅簲寮忔暟鎹紝鍒濆鍖栦负绌烘暟缁�
+let produceList = ref([])
+
+// 鑾峰彇15澶╁墠鍒板綋鍓嶆椂闂�
+function getNowTime() {
+  const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 70)
+      .toISOString()
+      .replace('T', ' ')
+      .slice(0, 10) //榛樿寮�濮嬫椂闂�15澶╁墠
+  const end = new Date(new Date().getTime())
+      .toISOString()
+      .replace('T', ' ')
+      .slice(0, 10)//榛樿缁撴潫鏃堕棿褰撳墠鏃堕棿
+  return [start, end]
+}
+
+// 鍒濆鍖栨椂闂磋寖鍥达紝鑻ヤ负绌哄垯璁句负杩�15澶╂椂闂�
+if (orderInfo.workOrderDate[0] === "" && orderInfo.workOrderDate[1] === "") {
+  orderInfo.workOrderDate = getNowTime();
+}
+//鑾峰彇閫変腑鏃堕棿
+let startSelectTime = orderInfo.workOrderDate[0]
+let endSelectTime = orderInfo.workOrderDate[1]
+// 棣栨鍔犺浇鏁版嵁
+request.post(`/glassOptimize/optimizeProjectMange/${startSelectTime}/${endSelectTime}`, filterData.value).then((res) => {
+  if (res.code == 200) {
+    produceList.value = produceList.value.concat(deepClone(res.data.data))
+    xGrid.value.reloadData(produceList.value);
+    gridOptions.loading = false;
+  } else {
+    ElMessage.warning(res.msg);
+  }
+})
+
+// 鐐瑰嚮鏌ヨ鎸夐挳瑙﹀彂鐨勫嚱鏁帮紝鏍规嵁褰撳墠绛涢�夋潯浠惰幏鍙栨暟鎹苟鍔犺浇鍒拌〃鏍�
+const getWorkOrder = () => {
+  const params = buildRequestParams();
+  request.post(`/glassOptimize/optimizeProjectMange/${params.startSelectTime}/${params.endSelectTime}`, filterData.value).then((res) => {
+    if (res.code == 200) {
+      produceList.value = deepClone(res.data.data);
+      gridOptions.data = produceList.value;
+      xGrid.value.loadData(produceList.value);
+      gridOptions.loading = false;
+    } else {
+      ElMessage.warning(res.msg);
+    }
+  });
+};
+// 璁$畻灏忕墖鏁伴噺
+const smallPieceQuantityInput = computed(() => {
+  return produceList.value.reduce((acc, item) => acc + item.quantity, 0);
+});
+// 璁$畻灏忕墖闈㈢Н
+const smallPieceAreaInput = computed(() => {
+  const sum = produceList.value.reduce((acc, item) => acc + item.area, 0);
+  return Number(sum.toFixed(2)); // 鍏堜娇鐢╰oFixed淇濈暀涓や綅灏忔暟锛屽啀杞崲鍥炴暟鍊肩被鍨嬶紙鍥犱负toFixed杩斿洖瀛楃涓诧級
+});
+
+// 璁$畻鍘熺墖鏁伴噺
+const originalPieceQuantityInput = computed(() => {
+  return produceList.value.reduce((acc, item) => acc + item.usingQuantity, 0);
+});
+
+// 鍘熺墖闈㈢Н鍥哄畾涓�0锛岀洿鎺ヨ繑鍥�0
+const originalPieceAreaInput = 0;
+
+//鏃ユ湡宸︿晶鏍忓揩鎹烽�夐」
+const shortcuts = [
+  {
+    text: '褰撴棩',
+    value: () => {
+      const end = new Date()
+      const start = new Date(end)
+      start.setHours(0, 0, 0, 0) // 璁剧疆涓哄綋澶╃殑鍑屾櫒 00:00:00
+      return [start, end]
+    }
+  },
+  {
+    text: '杩�1鍛�',
+    value: () => {
+      const end = new Date()
+      const start = new Date()
+      start.setDate(start.getDate() - 7)
+      return [start, end]
+    }
+  },
+
+  {
+    text: '杩�1涓湀',
+    value: () => {
+      const end = new Date()
+      const start = new Date()
+      start.setMonth(start.getMonth() - 1)
+      return [start, end]
+    }
+  },
+  {
+    text: '杩�2涓湀',
+    value: () => {
+      const end = new Date()
+      const start = new Date()
+      start.setMonth(start.getMonth() - 2)
+      return [start, end]
+    }
+  },
+  {
+    text: '杩�3涓湀',
+    value: () => {
+      const end = new Date()
+      const start = new Date()
+      start.setMonth(start.getMonth() - 3)
+      return [start, end]
+    }
+  }
+]
+
+</script>
+
+<template>
+  <div id="mange">
+    <div id="select" style="">
+      <span>浼樺寲鏃ユ湡</span>
+      <el-date-picker
+          style="margin-left:10px; margin-top: -10px; "
+          v-model="orderInfo.workOrderDate"
+          :default-time="defaultTime"
+          :start-placeholder="$t('basicData.startDate')"
+          :end-placeholder="$t('basicData.endDate')"
+          type="daterange"
+          :shortcuts="shortcuts"
+          showToday
+          format="YYYY/MM/DD"
+          value-format="YYYY-MM-DD"
+      />
+      <span class="input">宸ョ▼鐘舵��</span>
+      <el-select
+          style="margin-left:10px; margin-top: -5px; width: 150px"
+          :default-first-option="true"
+          ref="getSelect"
+          v-model="optionVal"
+          clearable
+          class="m-2"
+          @change="handleOptionChange"
+      >
+        <el-option
+            v-for="item in options"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+        />
+      </el-select>
+      <!--鏌ヨ-->
+      <el-button
+          style="margin-left:10px;margin-top: -5px"
+          :icon="Search"
+          type="primary"
+          @click="getWorkOrder">{{ $t('basicData.search') }}
+      </el-button>
+    </div>
+
+    <vxe-grid
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+      <template #select_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+    </vxe-grid>
+    <div id="last">
+      灏忕墖鏁伴噺
+      <el-input class="input" disabled v-model="smallPieceQuantityInput"></el-input>
+      灏忕墖闈㈢Н
+      <el-input class="input" disabled v-model="smallPieceAreaInput"></el-input>
+      鍘熺墖鏁伴噺
+      <el-input class="input" disabled v-model="originalPieceQuantityInput"></el-input>
+      鍘熺墖闈㈢Н
+      <el-input class="input" disabled v-model="originalPieceAreaInput"></el-input>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+#mange {
+  width: 100%;
+  height: 85%;
+}
+
+:deep(.vxe-button.type--button.is--circle) {
+  margin-top: -20px;
+}
+
+#last {
+  margin-top: 10px;
+}
+
+.input {
+  width: 80px;
+  margin-left: 10px;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/CheckInventory.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/CheckInventory.vue
new file mode 100644
index 0000000..855da7a
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/CheckInventory.vue
@@ -0,0 +1,97 @@
+<script setup>
+import {defineEmits, ref} from "vue";
+
+
+const value1 = ref('')
+const value2 = ref('')
+
+const options1 = [
+  {
+    value: 'Option1',
+    label: '5',
+  },
+  {
+    value: 'Option2',
+    label: '6',
+  },
+  {
+    value: 'Option3',
+    label: '8',
+  },
+  {
+    value: 'Option4',
+    label: '10',
+  },
+  {
+    value: 'Option5',
+    label: '12',
+  },
+]
+const options2 = [
+  {
+    value: 'Option1',
+    label: '鐧界幓',
+  },
+  {
+    value: 'Option2',
+    label: '鐏伴暅',
+  },
+  {
+    value: 'Option3',
+    label: 'Low-e',
+  },
+]
+
+const emit = defineEmits(['send-data-inventory',]);
+const props = defineProps({
+  closeDialog: Function,
+  thickNess:null,
+  model:null
+});
+
+value1.value=props.thickNess
+value2.value=props.model
+
+const CheckInventory = () => {
+  const selectedLabel1 = value1.value;
+  const selectedLabel2 = value2.value;
+  // 鍒ゆ柇涓や釜鍊兼槸鍚﹂兘琚�夋嫨浜嗭紝濡傛灉鏈変竴涓负绌哄瓧绗︿覆锛屽垯鎻愮ず骞惰繑鍥烇紝涓嶆墽琛屽悗缁搷浣�
+  if (selectedLabel1==="" || selectedLabel2==="") {
+    window.alert('璇疯緭鍏�');
+    return;
+  }
+  props.closeDialog(1);
+  emit('send-data-inventory', selectedLabel1,selectedLabel2);
+};
+
+</script>
+
+<template>
+  <div id="box">
+    <div>
+      <span>鍘氬害(mm)锛�</span>
+      <el-input v-model="value1"  style="width: 140px"></el-input>
+    </div>
+
+    <div style="margin-top: 30px">
+    <span>鐜荤拑绫诲瀷  锛�</span>
+      <el-input v-model="value2" style="width: 140px">
+
+      </el-input>
+    </div>
+
+    <div style="float: right; margin:-55px 35px 0 0;">
+      <el-button type="primary" @click="CheckInventory">鏌ヨ</el-button>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+#box {
+  width: 100%;
+  height: 100%;
+  padding: 10px;
+  margin-top: -20px;
+  border-radius: 5px;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/Compute.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/Compute.vue
new file mode 100644
index 0000000..1164c45
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/Compute.vue
@@ -0,0 +1,426 @@
+<script setup>
+import {onMounted, reactive, ref, watch} from "vue";
+import {useI18n} from "vue-i18n";
+import {Platform, Search, SuccessFilled} from "@element-plus/icons-vue";
+import useUserInfoStore from "@/stores/userInfo";
+import request from "@/utils/request";
+import {ElMessage} from "element-plus";
+
+
+const userStore = useUserInfoStore()
+const username = userStore.user.userName
+
+const {t} = useI18n()
+
+const xGrid = ref()
+//鑾峰彇宸ョ▼鍙�
+const props = defineProps({
+  projectNo : String,
+  project: null,
+  data: {
+    type: Array,
+    default: () => []
+  }
+});
+
+
+const selectOptions = [
+  {
+    value: '0',
+    label: '榛樿'
+  },
+  {
+    value: '1',
+    label: '浼樺厛绔栨帓'
+  },
+  {
+    value: '2',
+    label: '浼樺厛妯帓'
+  }
+]
+
+
+// 瀹氫箟娣锋帓绛夌骇
+const optionVal = ref(50)
+
+// 瀹氫箟瑁呰浇鐜�
+const percentage1 = ref(80)
+const percentage2 = ref(50)
+
+// 瀹氫箟鍏朵粬琛ㄥ崟鏁版嵁
+const furnaceWidth = ref('') // 鐐夊
+const furnaceLength = ref('') // 鐐夐暱
+const heatingTime = ref('') // 閽㈠寲鍔犵儹鏃堕棿
+const rotateMode = ref({value: '0', label: '榛樿'}) // 閽㈠寲鏃嬭浆妯″紡
+const spacingLong = ref('') // 闀胯酱闂撮殧
+const spacingWidth = ref('') // 瀹借酱闂撮殧
+const quantity = ref('') // 宸ョ▼鐗囨暟
+
+// 瀹氫箟鍝嶅簲寮忔暟鎹紝鐢ㄤ簬缁戝畾宸ョ▼鍙疯緭鍏ユ鐨勫��
+let inputValue=ref(null)
+if(props.project!==undefined){
+  inputValue= ref(props.project.projectNumber);
+  quantity.value=props.project.quantity
+}
+
+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);
+      if (parsedData.tempering) {
+        furnaceLength.value = parsedData.tempering.furnaceLength;
+        furnaceWidth.value = parsedData.tempering.furnaceWidth;
+        spacingWidth.value=parsedData.tempering.xAxisInterval;
+        spacingLong.value=parsedData.tempering.yAxisInterval;
+        heatingTime.value=parsedData.tempering.temperingTime;
+      }
+      
+     
+    } else {
+      console.error('璇锋眰澶辫触锛岀姸鎬佺爜:', response.code);
+    }
+  } catch (error) {
+    console.error('璇锋眰鍙戠敓閿欒:', error);
+  }
+};
+
+fetchSettings(username);
+
+const gridOptions = reactive({
+  height: '100%',
+  loading: false,
+  border: "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe: true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true, height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'Compute',
+  scrollX: {enabled: true},
+  scrollY: {enabled: true, gt: 0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow: true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+
+  columns: [
+    {field: 'id', width: 70, title: '搴忓彿'},
+    {field: 'layoutsNumber', width: 100, title: '鐗堝浘鏁�'},
+    {field: 'loadingRate', width: 100, title: '瑁呰浇鐜�'},
+    {field: 'processCards', width: 100, title: '娴佺▼鍗℃暟'},
+    {field: 'simulatedPieces', width: 100, title: '妯℃嫙鐗囨暟'},
+    {
+      field: 'processId',
+      width: 350,
+      title: t('processCard.processId'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+  ],//琛ㄥご鍙傛暟
+  data: null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+
+  },
+})
+
+onMounted(async() => {
+  await firstLoading()
+})
+
+const firstLoading = async() => {
+    request.post(`/glassOptimize/selectOptimizeParms/${username}`).then((res) => {
+      if (res.code == "200") {
+        const parsedData = JSON.parse(res.data);
+          furnaceWidth.value=parsedData.tempering.furnaceWidth
+          furnaceLength.value=parsedData.tempering.furnaceLength
+          spacingLong.value=parsedData.tempering.xAxisInterval
+          spacingWidth.value=parsedData.tempering.yAxisInterval
+      } else {
+        ElMessage.warning(res.msg)
+      }
+    })
+
+}
+
+// 鐩戝惉鐖剁粍浠朵紶閫掔殑鏁版嵁鍙樺寲
+watch(() => props.data, (newValue) => {
+  if (newValue) {
+    // 澶勭悊鏁版嵁骞舵洿鏂拌〃鏍�
+    const processData = newValue.data[0];
+    const processedData = [
+      {
+        id: "1",
+        layoutsNumber: processData.resultSum[0],
+        loadingRate: processData.resultSum[1],
+        processCards: processData.rackinfos.length,
+        simulatedPieces: processData.glass_details.length,
+        processId:processData.rackinfos
+      }
+    ];
+    gridOptions.data = processedData;
+  } else {
+    console.error("鏁版嵁鏍煎紡涓嶆纭垨涓虹┖");
+    gridOptions.data = [];
+  }
+})
+
+const inputValues = {
+  project_no:inputValue.value,
+  glass_thickness:"",
+  glass_type:"",
+  chaos_pct: optionVal.value*0.01,//娣锋帓绛夌骇
+  cage_free:percentage2.value*0.01,//鐞嗙墖榫欑┖闂插害
+  tempering_time:heatingTime.value,//閽㈠寲鍔犵儹鏃堕棿
+  heat_mode: 0,//妯″紡閫夋嫨
+  max_load_pct: percentage1.value*0.01,//鏈�澶ц杞界巼
+  max_area: 0,//鏈�澶ч潰绉�
+  max_qty:0,//鏈�澶х墖鏁�
+  load_width:null,
+  load_length: null,
+  x_space: null,
+  y_space: null,
+  load_rate: null,
+  furnaces_qty:"",
+  rotate_mode:0,
+  polys_allow_rotate: 0,
+  process_cards:[]
+};
+
+
+// let emit = defineEmits(['fetch-data']);
+let emit = defineEmits(['fetch-data', 'sendData'])
+
+const handleSearchClick = () => {
+  // 閫氳繃 $emit 瑙﹀彂鑷畾涔変簨浠讹紝灏嗗伐绋嬪彿浼犻�掔粰鐖剁粍浠讹紝鐢辩埗缁勪欢鍘昏皟鐢ㄦ帴鍙h幏鍙栨暟鎹�
+  emit('fetch-data', inputValue.value);
+ 
+ 
+};
+const handleSimulationClick = () => {
+
+      inputValues.load_width = furnaceWidth.value
+      inputValues.load_length = furnaceLength.value
+      inputValues.x_space = spacingWidth.value
+      inputValues.y_space = spacingLong.value
+      inputValues.polys_allow_rotate = parseInt(rotateMode.value.value)
+
+  emit('sendData', {
+    ...inputValues
+  })
+  // 瑙﹀彂鐖剁粍浠剁殑 simulate-click 浜嬩欢
+  emit('simulate-click');
+
+ 
+};
+
+
+
+
+
+const handleSave = () => {
+  
+  if (props.data) {
+    console.log(props.data)
+
+    let projectData = ref({
+      projectdetail: props.data.data[0].glass_details,
+      ratioResult: props.data.data[0].ratioResult,
+      rackinfos: props.data.data[0].rackinfos,
+      resultSum: props.data.data[0].resultSum,
+      guidance: props.data.data[0].guidance,
+      userName : username,
+      inputValues:inputValues
+    })
+   
+    request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => {
+      if (res.code == 200 && res.data === true) {
+        ElMessage.success(t('basicData.msg.saveSuccess'))
+      
+      } else {
+        ElMessage.warning(res.msg)
+      }
+    })
+
+  }
+}
+
+</script>
+
+<template>
+<div style="width: 100%;height: 100%">
+    <!--妯℃嫙璁$畻琛ㄥご-->
+<div id="title" style="margin-top: -10px;height: 50%">
+  <div style="display: flex">
+    <div style="width: 850px">
+      宸ョ▼缂栧彿
+      <el-input style="width:150px;margin-left: 30px" clearable v-model="inputValue" placeholder="璇疯緭鍏ュ伐绋嬪彿"></el-input>
+      <el-button
+          type="primary"
+          :icon="Search"
+          style="margin-left: 20px"
+          @click="handleSearchClick"
+      >{{ $t('basicData.search') }}
+      </el-button>
+    </div>
+    <div style="display: flex ; width: 700px;align-items: center;">
+      <span>宸ョ▼娣锋帓绛夌骇</span>
+      <el-slider
+          style="max-width: 200px; flex: 1; margin-left: 10px"
+          v-model="optionVal"
+          :min="0"
+          :max="100"
+          :step="1"/>
+      <span style="margin-left: 20px ; width: 35px;">{{ optionVal }}%</span>
+
+      <el-button type="primary" style="margin-left: 10px" :icon="Platform"  @click="handleSimulationClick">妯℃嫙璁$畻</el-button>
+      <el-button type="primary" style="margin-left: 20px" :icon="SuccessFilled"  @click="handleSave">淇濆瓨</el-button>
+    </div>
+  </div><br>
+  <div style="display:flex">
+    <div class="demo-progress" style="margin-top: 5px;width: 50%">
+      <div style="display: flex; align-items: center">
+        <span>閽㈠寲鏈�澶ц杞�</span>
+        <!-- 杩涘害鏉¤缃� -->
+        <el-slider
+            style="max-width: 400px; flex: 1; margin-left: 10px"
+            v-model="percentage1"
+            :min="0"
+            :max="100"
+            :step="1"/>
+        <span style="margin-left: 20px ; width: 35px;">{{ percentage1 }}%</span>
+        <!--      <span style="float: right ; margin-left: 150px;">
+                    宸ョ▼鐗囨暟 <vxe-input size="small" disabled class="input"  v-model="quantity"></vxe-input>
+                    瀹借酱闂撮殧 <vxe-input size="small" class="input" clearable v-model="spacingWidth"></vxe-input>
+                    鐐夊(mm) <vxe-input size="small" class="input" clearable v-model="furnaceWidth"></vxe-input>
+              </span>-->
+      </div>
+      <div style="display: flex; align-items: center">
+        <span>鐞嗙墖绗肩┖闂插害</span>
+        <!-- 杩涘害鏉¤缃� -->
+        <el-slider
+            style="max-width: 400px; flex: 1; margin-left: 10px"
+            v-model="percentage2"
+            :min="0"
+            :max="100"
+            :step="1"/>
+        <span style="margin-left: 20px ; width: 35px;">{{ percentage2 }}%</span>
+      </div>
+    </div>
+
+    <div class="demo-progress" style="display: flex;font-size: 15px">
+      <div style="height: 35px;line-height: 35px">
+        <div>宸ョ▼鐗囨暟 <el-input size="small" disabled class="input"  v-model="quantity"></el-input></div>
+        <div>閽㈠寲鏃嬭浆鏂瑰紡
+          <el-select style="width: 100px;height: 30px" v-model="rotateMode">
+            <el-option
+                v-for="item in selectOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            />
+          </el-select>
+        </div>
+      </div>
+      <div style="margin-left: 15px;height: 35px;line-height: 35px">
+        <div>瀹借酱闂撮殧 <el-input size="small" class="input" clearable v-model="spacingWidth"></el-input></div>
+        <div>闀胯酱闂撮殧 <vxe-input size="small" class="input" clearable v-model="spacingLong"></vxe-input></div>
+
+
+      </div>
+      <div style="margin-left: 15px;height: 35px;line-height: 35px">
+        <div>鐐夊(mm) <el-input size="small" class="input" clearable v-model="furnaceWidth"></el-input></div>
+        <div>鐐夐暱(mm) <vxe-input size="small" class="input" clearable v-model="furnaceLength"></vxe-input></div>
+      </div>
+
+    </div>
+  </div>
+<!--  <div class="demo-progress" style="margin-top: -10px">
+    <div style="display: flex; align-items: center">
+      <span>鐞嗙墖绗肩┖闂插害</span>
+      &lt;!&ndash; 杩涘害鏉¤缃� &ndash;&gt;
+      <el-slider
+          style="max-width: 400px; flex: 1; margin-left: 10px"
+          v-model="percentage2"
+          :min="0"
+          :max="100"
+          :step="1"/>
+      <span style="margin-left: 20px ; width: 35px;">{{ percentage2 }}%</span>
+      <span style="float: right ; margin-left: 150px;">
+              鍔犵儹鏃堕棿(绉�)<el-select style="width: 50px;height: 30px" v-model="rotateMode">
+                            <el-option
+                                v-for="item in selectOptions"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            />
+                        </el-select>
+              闀胯酱闂撮殧 <vxe-input size="small" class="input" clearable v-model="spacingLong"></vxe-input>
+              鐐夐暱(mm) <vxe-input size="small" class="input" clearable v-model="furnaceLength"></vxe-input>
+      </span>
+    </div>
+  </div>-->
+</div>
+<div style="height: 50%">
+  <vxe-grid
+      size="small"
+      @filter-change="filterChanged"
+      height="50%"
+      class="mytable-scrollbar"
+      ref="xGrid"
+      v-bind="gridOptions"
+      v-on="gridEvents"
+  >
+    <template #num2_filter="{ column, $panel }">
+      <div>
+        <div v-for="(option, index) in column.filters" :key="index">
+          <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"
+                      @change="changeFilterEvent($event, option, $panel)">
+            <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+            <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+          </vxe-select>
+        </div>
+      </div>
+    </template>
+
+    <template #num1_filter="{ column, $panel }">
+      <div>
+        <div v-for="(option, index) in column.filters" :key="index">
+          <input
+              type="type"
+              v-model="option.data"
+              @keyup.enter.native="$panel.confirmFilter()"
+              @input="changeFilterEvent($event, option, $panel)"/>
+        </div>
+      </div>
+    </template>
+  </vxe-grid>
+</div>
+
+  </div>
+</template>
+
+<style scoped>
+
+.input {
+  width: 80px;
+  height: 30px;
+}
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeCard.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeCard.vue
new file mode 100644
index 0000000..bc2be90
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeCard.vue
@@ -0,0 +1,185 @@
+<script setup>
+import {nextTick, onMounted, reactive, ref, watch} from "vue";
+import request from "@/utils/request";
+import {useI18n} from "vue-i18n";
+import {ElMessage} from "element-plus";
+import deepClone from "@/utils/deepClone";
+const { t } = useI18n()
+
+const xGrid = ref()
+
+const checkboxCellRender = reactive({
+  name: 'VxeCheckboxGroup',
+  options: [
+    { label: '骞曞妯″紡', value: '1' },
+    { label: '鍏佽妯帓', value: '2' },
+    { label: '閽㈠寲', value: '3' },
+
+  ]
+})
+
+const gridOptions = reactive({
+
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ComputeCard',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+
+  columns:[
+    {type: 'seq', title: t('basicData.Number'), width: 80},
+    {field: 'curtain_wall',title: '骞曞妯″紡',width: 80, slots: { default: 'state1' }},
+    {field: "allow_rotate", title: '鍏佽妯帓', width: 80, slots: { default: 'state2' }},
+    {field: "tempering", title: '閽㈠寲', width: 80, slots: { default: 'state3' }},
+
+    {field: 'processId',width: 150, title: t('processCard.processId'), sortable: true},
+    {field: 'technologyNumber',width: 70, title: '灞�', sortable: true},
+    {field: 'total_layers',width: 150, title: '鎬诲眰鏁�', sortable: true},
+    {field: 'TotalNumber',width: 150, title: '瑙勬牸', sortable: true},
+    {field: 'total_num',width: 150, title: t('order.quantity'), sortable: true},
+    {field: 'glass_child',width: 150, title: t('order.product'), sortable: true},
+    {field: 'project', width:150, title: t('order.project'), showOverflow: "ellipsis"},
+    {field: 'total_area',width: 150, title: t('order.area'), sortable: true},
+
+
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+
+  toolbarConfig: {
+    buttons: [],
+    zoom: true,
+    custom: true
+  },
+
+})
+
+let emit = defineEmits([
+  'changeDialog','upProcessId', 'sendData'
+]);
+
+
+const selectFullData =  () => {
+  return xGrid.value.getTableData().fullData
+}
+
+
+const props = defineProps({
+  tableData: Array,
+  processId: null,
+  technologyNumber: null,
+  patchState: null,
+});
+
+
+
+
+watch(() => props.tableData, async (newData) => {
+  if (Array.isArray(newData)) {
+    console.log(newData)
+    xGrid.value.loadData(deepClone(newData))
+    const data = xGrid.value.getTableData().fullData
+    data.forEach(item => {
+      item.tempering = item.tempering === 1;
+      item.allow_rotate = item.allow_rotate === 1;
+      item.curtain_wall = item.curtain_wall === 1;
+    })
+  }
+});
+
+
+
+
+let process_id = ref()
+//鑾峰彇娴佺▼鍗″彿璇︽儏
+let rowClickIndex = ref(null)
+const gridEvents = {
+  cellClick({row}) {
+    rowClickIndex.value = row
+    // Emit 浜嬩欢灏嗘洿鏂板悗鐨勫�间紶閫掔粰鐖剁粍浠�
+    emit('upProcessId', rowClickIndex.value.processId,rowClickIndex.value.technologyNumber);
+    emit('updateTechnologyNumber', rowClickIndex.value.processId,rowClickIndex.value.technologyNumber);
+  }
+}
+
+defineExpose({selectFullData})
+</script>
+
+<template>
+  <div style="width: 100%;height: 100%">
+    <span>娴佺▼鍗�</span>
+    <vxe-grid
+        size="small"
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input
+
+                type="type"
+                v-model="option.data"
+                @keyup.enter.native="$panel.confirmFilter()"
+                @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+
+      <template #state1="{ row,column}">
+        <el-checkbox
+            v-model="row.curtain_wall"/>
+      </template>
+      <template #state2="{ row,column}">
+        <el-checkbox
+            v-model="row.allow_rotate"/>
+      </template>
+      <template #state3="{ row,column}">
+        <el-checkbox
+            v-model="row.tempering"/>
+      </template>
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+:deep(.vxe-tools--operate){
+  height: 20px;
+  margin-top: -20px;
+}
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeDetail.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeDetail.vue
new file mode 100644
index 0000000..a56cbb9
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ComputeDetail.vue
@@ -0,0 +1,134 @@
+<script setup>
+import {onMounted, reactive, ref, watch} from "vue";
+import {useI18n} from "vue-i18n";
+import request from "@/utils/request";
+import {ElMessage} from "element-plus";
+import {Minus, Plus, Search} from "@element-plus/icons-vue";
+import {changeFilterEvent, filterChanged} from "@/hook";
+const { t } = useI18n()
+
+// 鎺ユ敹鐖剁粍浠朵紶閫掕繃鏉ョ殑娴佺▼鍗″彿锛坧rocessId锛�
+let props = defineProps({
+  processId:null,
+  patchState:null,
+  technologyNumber:null
+});
+
+const xGrid = ref()
+
+const gridOptions = reactive({
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ComputeDetail',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    //remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+
+  columns:[
+    {type: 'seq',width: 70,  title: '搴忓彿',filters:[{ data: '' }],},
+    {field: 'width',width: 150,title: t('order.width'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'height',width: 150,title: t('order.height'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'quantity',width: 150, title: t('order.quantity'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'building_number',width: 150, title: t('order.buildingNumber'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'shape',width: 150, title: t('order.shape'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'area',width: 150, title: t('order.grossArea'),filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+    {field: 'icon',width: 150, title: '鍗版爣',filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [],
+    zoom: true,
+    custom: true
+  },
+})
+
+
+
+
+
+watch(
+    ()=> [props.processId,props.technologyNumber],
+    ([newValue, oldValue])=> {
+  if (props.processId!=null){
+    selectComputeDetail()
+
+  }
+});
+
+
+
+const selectComputeDetail =  () => {
+  if (props.processId!=null || props.processId!=""){
+    request.post(`/glassOptimize/selectComputeDetailThirdParty/${props.processId}/${props.technologyNumber}`).then((res) => {
+      if(Number(res.code) === 200){
+        xGrid.value.loadData(res.data.data)
+      }else{
+        ElMessage.warning(res.msg)
+      }
+    })
+  }
+}
+</script>
+
+<template>
+  <div style="width: 100%;height: 100%">
+    <span>娴佺▼鍗¤鎯�</span>
+    <vxe-grid
+        size="small"
+        @filter-change="filterChanged"
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+
+
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+:deep(.vxe-tools--operate){
+  height: 20px;
+  margin-top: -20px;
+}
+</style>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/GlassInventory.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/GlassInventory.vue
new file mode 100644
index 0000000..eb6ab49
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/GlassInventory.vue
@@ -0,0 +1,322 @@
+<script setup>
+import {nextTick, onMounted, reactive, ref, watch} from "vue";
+import {useI18n} from "vue-i18n";
+import request from "@/utils/request";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {useRoute} from "vue-router";
+import {addListener, toolbarButtonClickEvent} from "@/hook/mouseMove";
+const { t } = useI18n()
+
+const xGrid = ref()
+const gridOptions = reactive({
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'GlassInventory',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'dblclick',
+    mode: 'cell',
+    showStatus: true
+  },
+
+  columns:[
+    {type:'seq',fixed:"left", title:' ', width: 50},
+    {type: 'checkbox', fixed: "left", title: t('basicData.check'), width: 80},
+    {field: 'id', title: '鐗╂枡缂栫爜',},
+    {field:'width',editRender: { name: 'input',attrs: {disabled:true}}, title: t('order.width'),},
+    {field: 'height',editRender: { name: 'input',attrs: {disabled:true}},title: t('order.height')},
+    {field: 'thickness', title: t('order.totalThickness'),},
+    {field: 'model', title: t('warehouseBasicData.type'),},
+    {field: 'leftTrim',editRender: { name: 'input',attrs: {disabled:false}}, title: '宸︿慨杈�',},
+    {field: 'downTrim',editRender: { name: 'input',attrs: {disabled:false}}, title: '涓嬩慨杈�',},
+    {field: 'rightTrim',editRender: { name: 'input',attrs: {disabled:false}}, title: '鍙充慨杈�',},
+    {field: 'upTrim',editRender: { name: 'input',attrs: {disabled:false}}, title: '涓婁慨杈�',},
+    {field: 'available_quantity',editRender: { name: 'input',attrs: {disabled:false}}, title: '搴撳瓨鏁伴噺',},
+    {field: 'processingQuantity', title: '鍔犲伐鏁伴噺',},
+    {field: 'name', title: '鍚嶇О',},
+    {field: 'producer', title: '渚涘簲鍟�',}
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+  //鍙抽敭鑿滃崟
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {code: 'selectTrimming', name: '璁剧疆缁熶竴淇竟',},
+          {code: 'Exports', name: '鏁版嵁瀵煎嚭', prefixIcon: 'vxe-icon-download', visible: true, disabled: false},
+          {code: 'addRow', name: t('basicData.add'), prefixIcon: 'vxe-icon-square-plus', visible: true, disabled: true },
+        ],
+      ]
+    },
+  },
+  toolbarConfig: {
+    buttons: [],
+  },
+})
+
+const emit = defineEmits(['select-trimming']);
+// 鍙抽敭鑿滃崟
+const operationConfigs = [
+  {
+    code: 'selectTrimming', // 璁剧疆缁熶竴淇竟
+    successMsg: '宸叉墦寮�锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    openTrimming: async () => {
+     emit ( 'select-trimming', true)
+    }
+  },
+  {
+    code: 'Exports', // 瀵煎嚭鏂囦欢鎿嶄綔鐨勯厤缃�
+    successMsg: '鏂囦欢瀵煎嚭鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+  },
+  {
+    code: 'addRow', // 瀵煎嚭鏂囦欢鎿嶄綔鐨勯厤缃�
+    successMsg: '娣诲姞鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+  },
+]
+
+// 鍙抽敭鑿滃崟鐐瑰嚮閫昏緫
+const gridEvents = {
+  menuClick({menu}) {
+    const $grid = xGrid.value;
+    if ($grid) {
+      const config = operationConfigs.find(c => c.code === menu.code);
+      if (config) {
+        if (config.code === 'Exports') {
+          config.gridRef.value.exportData();
+          ElMessage.success(config.successMsg);
+          return;
+        }
+        if (config.code === 'addRow') {
+          if ($grid.getTableData().tableData.length >=100){
+            ElMessage.error(t('order.msg.tableLengthMax'))
+            return
+          }
+          if ($grid.getCheckedFilters().length!==0){
+            ElMessage.error(t('order.msg.pleaseCancelTheFilteringFirst'))
+            return
+          }
+          console.log($grid.getTableData().visibleData)
+          let result = toolbarButtonClickEvent()
+          let lengths = 0
+          if (result!=null){
+            lengths=result.start
+          }
+          if($grid.getTableData().fullData.length>lengths+1){
+            $grid.insertAt({}, lengths+1)
+          }else{
+            $grid.insertAt({}, -1)
+          }
+          return;
+        }
+        // 娣诲姞纭鎻愮ず寮圭獥锛岃闂敤鎴锋槸鍚﹁繘琛屽綋鍓嶆搷浣�
+        ElMessageBox.confirm('鏄惁杩涜褰撳墠鎿嶄綔锛�', '纭鎿嶄綔', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          if (config.code === 'selectTrimming') {
+            config.openTrimming();
+            ElMessage.success(config.successMsg);
+          }
+        }).catch(() => {
+          // 鐢ㄦ埛鐐瑰嚮鍙栨秷鍚庢墽琛岀殑閫昏緫
+          ElMessage.info('宸插彇娑堟搷浣�');
+        });
+      } else {
+        console.error(`鏈壘鍒版搷浣滈�夐」 ${menu.code} 瀵瑰簲鐨勯厤缃紝璇锋鏌ラ厤缃」`);
+      }
+    }
+  },
+};
+
+
+const route = useRoute();
+
+const thickness = ref(route.params.thickNess);
+const model = ref(route.params.model);
+let projectNo = ref(null);
+let type = ref(1);
+
+const selectMaterialStore = async () =>{
+  request.get(`/glassOptimize/materialStoreSvThirdParty/${projectNo}`).then((res) => {
+    if (Number(res.code) === 200) {
+      const rawData = res.data.data;
+      const edgeTrimming = res.data.edgeTrimming;
+      let state = res.data.state;
+      if (Array.isArray(rawData) && rawData.length > 0) {
+        const formattedData = rawData.map(item => {
+          const formattedItem = {};
+          for (const key in item) {
+            if (typeof item[key] === 'string') {
+              //鍘婚櫎瀛楃涓插睘鎬у�煎紑澶村拰缁撳熬鐨勫弻寮曞彿
+              formattedItem[key] = item[key].replace(/^\"|\"$/g, '');
+            } else {
+              formattedItem[key] = item[key];
+            }
+          }
+          return formattedItem;
+        });
+
+          gridOptions.columns[7].editRender.attrs.disabled=true
+          gridOptions.columns[8].editRender.attrs.disabled=true
+          gridOptions.columns[9].editRender.attrs.disabled=true
+          gridOptions.columns[10].editRender.attrs.disabled=true
+          gridOptions.columns[11].editRender.attrs.disabled=true
+
+        xGrid.value.loadData(formattedData);
+        gridOptions.data = formattedData;
+      } else {
+      }
+    } else {
+      ElMessage.warning(res.msg);
+      console.error('璇锋眰鑾峰彇搴撳瓨澶辫触锛岀姸鎬佺爜锛�', res.code, '锛岄敊璇俊鎭細', res.msg);
+    }
+  });
+};
+
+onMounted(() => {
+  addListener(xGrid.value,gridOptions)
+  if(route.params.projectNo!=null){
+    projectNo=route.params.projectNo
+    selectMaterialStore();
+  }
+
+});
+
+watch(() => props.receivedData, (newData) => {
+  if (newData) {
+    Trimming(newData);
+  }
+}, { immediate: true });
+
+watch(() => props.InventoryData, (newInventoryData) => {
+  if (newInventoryData) {
+    thickness.value = newInventoryData.selectedLabel1;
+    model.value = newInventoryData.selectedLabel2;
+    type.value=newInventoryData.type
+    // 鐢变簬 thickness 鍜� model 鐨勫�兼敼鍙樹簡锛屾洿鏂拌〃鏍硷紝璋冪敤 selectMaterialStore 閲嶆柊鑾峰彇鏁版嵁
+    selectMaterialStore();
+  }
+});
+
+const props = defineProps({
+  receivedData : {
+    type: Object,
+    required: false,
+    properties: {
+      quicksetLeft: { type: Number },
+      quicksetBottom: { type: Number },
+      quicksetRight: { type: Number },
+      quicksetTop: { type: Number }
+    }
+  },
+  InventoryData : {
+    type: Object,
+    required: false,
+    properties: {
+      selectedLabel1: { type: String },
+      selectedLabel2: { type: String },
+      type: { type: String }
+    }
+  }
+});
+
+//鎺ュ彈SetTrimming鐨勫�� 锛堜慨杈癸級
+const Trimming = (receivedData) => {
+  nextTick(() => {
+    const data = gridOptions.data;
+    if (data) {
+      try {
+        const updatedData = [];
+        for (let i = 0; i < data.length; i++) {
+          const item = data[i];
+          const updatedItem = {
+            ...item,
+            // 浠� receivedData 涓幏鍙栧搴旂殑鍊兼潵鏇存柊琛ㄦ牸鏁版嵁椤�
+            leftTrim: Number(receivedData.quicksetLeft),
+            downTrim: Number(receivedData.quicksetBottom),
+            rightTrim: Number(receivedData.quicksetRight),
+            upTrim: Number(receivedData.quicksetTop),
+          };
+          updatedData.push(updatedItem);
+        }
+        gridOptions.data = updatedData;
+        xGrid.value.loadData(updatedData);
+      } catch (error) {
+        console.error('鏇存柊琛ㄦ牸鏁版嵁鏃跺嚭閿�:', error);
+        ElMessage.error('鏇存柊琛ㄦ牸鏁版嵁鏃跺嚭鐜伴敊璇紝璇锋鏌ヨ緭鍏ユ垨鑱旂郴绠$悊鍛�');
+      }
+    } else {
+      console.warn('琛ㄦ牸鏁版嵁涓虹┖锛屾棤娉曟洿鏂扮(閲忓��');
+    }
+  });
+};
+
+
+</script>
+
+<template>
+  <div style="width: 100%;height: 100%">
+    <vxe-grid
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+
+
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input
+                type="type"
+                v-model="option.data"
+                @keyup.enter.native="$panel.confirmFilter()"
+                @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizationRect.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizationRect.vue
new file mode 100644
index 0000000..0b7e1f6
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizationRect.vue
@@ -0,0 +1,1122 @@
+<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"
+            @click="handleRectClick(layoutIndex, rectIndex)"
+          >
+            <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
+let clickEventListener = null;
+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);
+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);
+      if (parsedData.display && parsedData.frameNumber) {
+        showJiaHao.value = parsedData.display.frameNumber;
+      }
+      if (parsedData.display && parsedData.orderNumber) {
+        showProcessId.value = parsedData.display.orderNumber;
+      }
+      if (parsedData.display) {
+        themeColor.value = parsedData.display.themeColor;
+      }
+    } 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];
+  const bestFitPosition = findBestFitPosition(layoutIndex, newRect);
+  if (bestFitPosition) {
+    newRect.x = bestFitPosition.x;
+    newRect.y = bestFitPosition.y;
+    layout.rects.push(newRect);
+    adjustGrayRectangles(layoutIndex);
+  } else {
+    ElMessage.warning('鏃犳硶鏀剧疆锛屾病鏈夎冻澶熺殑绌洪棿');
+  }
+};
+
+const findBestFitPosition = (layoutIndex, newRect) => {
+  const layout = layouts.value[layoutIndex];
+  const obstacles = layout.rects.filter(r => !r.isRemain);
+  let bestFit = null;
+  let minAreaDifference = Infinity;
+
+  const remainingAreas = calculateRemainingAreas(layout.width, layout.height, obstacles);
+  remainingAreas.forEach(area => {
+    if (newRect.w <= area.w && newRect.h <= area.h) {
+      const areaDifference = Math.abs(area.w * area.h - newRect.w * newRect.h);
+      if (areaDifference < minAreaDifference) {
+        minAreaDifference = areaDifference;
+        bestFit = {
+          x: area.x,
+          y: area.y,
+          w: newRect.w,
+          h: newRect.h
+        };
+      }
+    }
+  });
+
+  return bestFit;
+};
+
+const layoutContainerStyle = (layoutIndex) => {
+  const 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);
+  });
+
+  const mirrorXItem = document.createElement('div');
+  mirrorXItem.textContent = 'X闀滃儚';
+  mirrorXItem.style.cursor = 'pointer';
+  mirrorXItem.addEventListener('click', () => {
+    mirrorLayoutX(layoutIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  const mirrorYItem = document.createElement('div');
+  mirrorYItem.textContent = 'Y闀滃儚';
+  mirrorYItem.style.cursor = 'pointer';
+  mirrorYItem.addEventListener('click', () => {
+    mirrorLayoutY(layoutIndex);
+    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);
+  contextMenu.appendChild(mirrorXItem);
+  contextMenu.appendChild(mirrorYItem);
+
+  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);
+  });
+
+  const mirrorXItem = document.createElement('div');
+  mirrorXItem.textContent = 'X闀滃儚';
+  mirrorXItem.style.cursor = 'pointer';
+  mirrorXItem.addEventListener('click', () => {
+    mirrorLayoutX(layoutIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  const mirrorYItem = document.createElement('div');
+  mirrorYItem.textContent = 'Y闀滃儚';
+  mirrorYItem.style.cursor = 'pointer';
+  mirrorYItem.addEventListener('click', () => {
+    mirrorLayoutY(layoutIndex);
+    document.body.removeChild(contextMenu);
+  });
+
+  contextMenu.appendChild(addItem);
+  contextMenu.appendChild(mirrorXItem);
+  contextMenu.appendChild(mirrorYItem);
+
+  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) {
+      rect.x = Math.round((otherRect.x + otherRect.w - rect.w));
+    }
+    // 鍨傜洿瀵归綈
+    if (Math.abs(rect.y - otherRect.y) < threshold) {
+      rect.y = Math.round((rect.y + otherRect.y) / 2);
+    }
+    // 鍨傜洿瀵归綈涓嬭竟缂�
+    if (Math.abs((rect.y + rect.h) - (otherRect.y + otherRect.h)) < threshold) {
+      rect.y = Math.round((otherRect.y + otherRect.h - rect.h));
+    }
+  });
+
+  // 纭繚鐭╁舰涓嶄細瓒呭嚭甯冨眬杈圭晫
+  rect.x = Math.max(0, rect.x);
+  rect.y = Math.max(0, rect.y);
+  rect.x = Math.min(rect.x, layout.width - rect.w);
+  rect.y = Math.min(rect.y, layout.height - rect.h);
+
+  // 璋冩暣鍚庨噸鏂拌绠楃伆鑹蹭綑鏂�
+  adjustGrayRectangles(layoutIndex);
+};
+
+const mergeAdjacentGrayRects = (rects) => {
+  const grayRects = rects.filter(r => r.isRemain);
+  let merged = [];
+
+  grayRects.sort((a, b) => {
+    if (a.x !== b.x) return a.x - b.x;
+    return a.y - b.y;
+  });
+
+  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 };
+
+  let maxStep = 0;
+  const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
+
+  switch (direction) {
+    case 'up':
+      maxStep = getAvailableSpaceUp(rect, layout, obstacles);
+      break;
+    case 'down':
+      maxStep = getAvailableSpaceDown(rect, layout, obstacles);
+      break;
+    case 'left':
+      maxStep = getAvailableSpaceLeft(rect, layout, obstacles);
+      break;
+    case 'right':
+      maxStep = getAvailableSpaceRight(rect, layout, obstacles);
+      break;
+  }
+
+  if (maxStep <= 0) {
+    ElMessage.warning('鏃犳硶绉诲姩锛屾病鏈夎冻澶熺殑绌洪棿');
+    return;
+  }
+
+  switch (direction) {
+    case 'up':
+      rect.y -= maxStep;
+      break;
+    case 'down':
+      rect.y += maxStep;
+      break;
+    case 'left':
+      rect.x -= maxStep;
+      break;
+    case 'right':
+      rect.x += maxStep;
+      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;
+};
+
+const getAvailableSpaceUp = (rect, layout, obstacles) => {
+  let maxSpace = rect.y;
+  obstacles.forEach(obstacle => {
+    if (obstacle.y + obstacle.h < rect.y &&
+        obstacle.x <= rect.x + rect.w &&
+        obstacle.x + obstacle.w >= rect.x) {
+      maxSpace = Math.min(maxSpace, rect.y - (obstacle.y + obstacle.h));
+    }
+  });
+  return maxSpace;
+};
+
+const getAvailableSpaceDown = (rect, layout, obstacles) => {
+  let maxSpace = layout.height - (rect.y + rect.h);
+  obstacles.forEach(obstacle => {
+    if (obstacle.y > rect.y + rect.h &&
+        obstacle.x <= rect.x + rect.w &&
+        obstacle.x + obstacle.w >= rect.x) {
+      maxSpace = Math.min(maxSpace, obstacle.y - (rect.y + rect.h));
+    }
+  });
+  return maxSpace;
+};
+
+const getAvailableSpaceLeft = (rect, layout, obstacles) => {
+  let maxSpace = rect.x;
+  obstacles.forEach(obstacle => {
+    if (obstacle.x + obstacle.w < rect.x &&
+        obstacle.y <= rect.y + rect.h &&
+        obstacle.y + obstacle.h >= rect.y) {
+      maxSpace = Math.min(maxSpace, rect.x - (obstacle.x + obstacle.w));
+    }
+  });
+  return maxSpace;
+};
+
+const getAvailableSpaceRight = (rect, layout, obstacles) => {
+  let maxSpace = layout.width - (rect.x + rect.w);
+  obstacles.forEach(obstacle => {
+    if (obstacle.x > rect.x + rect.w &&
+        obstacle.y <= rect.y + rect.h &&
+        obstacle.y + obstacle.h >= rect.y) {
+      maxSpace = Math.min(maxSpace, obstacle.x - (rect.x + rect.w));
+    }
+  });
+  return maxSpace;
+};
+
+let moveInterval = null;
+
+const handleKeyDown = (event) => {
+  if (!focusIndex.value) return;
+
+  const { layoutIndex, rectIndex } = focusIndex.value;
+  const layout = layouts.value[layoutIndex];
+  const rect = layout.rects[rectIndex];
+  const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
+
+  switch (event.key) {
+    case 'ArrowUp':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'up');
+        }, 50);
+      }
+      break;
+    case 'ArrowDown':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'down');
+        }, 50);
+      }
+      break;
+    case 'ArrowLeft':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'left');
+        }, 50);
+      }
+      break;
+    case 'ArrowRight':
+      event.preventDefault();
+      if (!moveInterval) {
+        moveInterval = setInterval(() => {
+          moveRect(layoutIndex, rectIndex, 'right');
+        }, 50);
+      }
+      break;
+  }
+};
+
+const handleKeyUp = (event) => {
+  if (event.key === 'ArrowUp' || event.key === 'ArrowDown' ||
+      event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
+    if (moveInterval) {
+      clearInterval(moveInterval);
+      moveInterval = null;
+    }
+  }
+};
+
+const mirrorLayoutX = (layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const width = layout.width;
+  const rects = [...layout.rects]; // 鍒涘缓鍓湰閬垮厤鐩存帴淇敼
+
+  rects.forEach(rect => {
+    // 璁$畻X闀滃儚鍚庣殑鍧愭爣
+    const newX = width - rect.x - rect.w;
+    const newY = rect.y;
+
+    // 鏇存柊鐭╁舰浣嶇疆
+    rect.x = newX;
+    rect.y = newY;
+  });
+
+  // 鏇存柊甯冨眬
+  layout.rects = rects;
+  adjustGrayRectangles(layoutIndex);
+};
+
+const mirrorLayoutY = (layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const height = layout.height;
+  const rects = [...layout.rects]; // 鍒涘缓鍓湰閬垮厤鐩存帴淇敼
+
+  rects.forEach(rect => {
+    // 璁$畻Y闀滃儚鍚庣殑鍧愭爣
+    const newX = rect.x;
+    const newY = height - rect.y - rect.h;
+
+    // 鏇存柊鐭╁舰浣嶇疆
+    rect.y = newY;
+  });
+
+  // 鏇存柊甯冨眬
+  layout.rects = rects;
+  adjustGrayRectangles(layoutIndex);
+};
+
+onMounted(() => {
+  fetchSettings(username);
+ updateLayout();
+
+  selectedLayoutIndex.value = 0;
+
+  clickEventListener = (event) => {
+    const contextMenus = document.querySelectorAll('.context-menu');
+    if (contextMenus.length > 0) {
+      contextMenus.forEach(menu => menu.remove());
+    }
+  };
+  document.addEventListener('click', clickEventListener);
+
+  document.addEventListener('keydown', handleKeyDown);
+  document.addEventListener('keyup', handleKeyUp);
+});
+
+onUnmounted(() => {
+  rectsElements.value = {};
+  if (clickEventListener) {
+    document.removeEventListener('click', clickEventListener);
+    clickEventListener = null;
+  }
+  document.removeEventListener('keydown', handleKeyDown);
+  document.removeEventListener('keyup', handleKeyUp);
+});
+</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: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  padding: 5px;
+  min-width: 60px;
+  min-height: 20px;
+  white-space: normal;
+  overflow-wrap: break-word;
+}
+
+.size {
+  font-size: 12px;
+  color: #444;
+  white-space: normal;
+  word-wrap: break-word;
+}
+
+.jia-hao, .liuchengka {
+  font-size: 14px;
+  font-weight: bold;
+  white-space: normal;
+  word-wrap: break-word;
+}
+
+.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/glassOptimizeThirdParty/page/OptimizeCompute.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizeCompute.vue
new file mode 100644
index 0000000..1e040bd
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/OptimizeCompute.vue
@@ -0,0 +1,144 @@
+<script setup>
+import {ref, computed} from "vue";
+import {Connection} from "@element-plus/icons-vue";
+
+//璁℃椂鍣�
+let seconds = ref(0);
+let isRunning = ref(false);
+let intervalId;
+
+//浼樺寲杩涘害鏉�
+let progress = ref(0);
+
+//浼樺寲娆℃暟锛涙椂闀匡紱鏁堢巼
+let progressValue1 = ref(10);
+let progressValue2 = ref(1000);
+let progressValue3 = ref(50);
+
+const formattedTime = computed(() => {
+  const minutes = Math.floor(seconds.value / 60);
+  const remainingSeconds = seconds.value % 60;
+  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+});
+const startTimer = () => {
+  if (!isRunning.value) {
+    intervalId = setInterval(() => {
+      seconds.value++;
+      progress.value += 10;
+      if (progress.value >= 100) {
+        progress.value = 100;
+        clearInterval(intervalId);
+      }
+    }, 1000);
+    isRunning.value = true;
+  }
+};
+const pauseTimer = () => {
+  if (isRunning.value) {
+    clearInterval(intervalId);
+    isRunning.value = false;
+  }
+};
+const resetTimer = () => {
+  clearInterval(intervalId);
+  isRunning.value = false;
+  seconds.value = 0;
+  progress.value = 0;
+};
+
+</script>
+
+<template>
+  <div class="header">
+    <el-header>
+      <div class="header-content">
+        <span style="margin-left: -20px;">闇�鍒囨垚鍝�</span><br>
+        <div>
+          <span>鎬婚潰绉�(m2)锛�</span>
+          <vxe-input class="input" disabled placeholder=""></vxe-input>
+          <span>鎬绘暟閲�(鐗�)锛�</span>
+          <vxe-input class="input" disabled placeholder=""></vxe-input>
+          <span>浼樺寲鏃堕暱(绉�)锛�</span>
+          <span class="time-display">{{ formattedTime }}</span>
+          <el-button type="primary" style="margin-left: 20px" @click="startTimer">寮�濮嬩紭鍖�</el-button>
+          <el-button class="buttons" type="primary" @click="pauseTimer">鏆傚仠</el-button>
+          <el-button class="buttons" type="primary" @click="resetTimer">瀹屾垚</el-button>
+        </div>
+        <br>
+        <div style="display: flex;margin-top: -10px">
+          <span>鏂规姹� 浼樺寲娆℃暟锛�</span>
+          <el-slider v-model="progressValue1" :min="2" :max="20" size="small" style="max-width: 200px;"></el-slider>
+          <span>鍗曟浼樺寲鏃堕暱锛�</span>
+          <el-slider v-model="progressValue2" :min="50" :max="2000" size="small" style="max-width: 200px;"></el-slider>
+          <span>閽㈠寲鏁堢巼浼樺厛锛�</span>
+          <el-slider v-model="progressValue3" :show-tooltip="false" size="small" style="max-width: 200px;"></el-slider>
+          <span>鍒囪鐜囦紭鍏�</span>
+        </div>
+      </div>
+    </el-header>
+  </div>
+
+  <div id="box">
+    <span style="font-size: 20px">浼樺寲杩涘害</span>
+    <div class="progress-bar">
+      <el-progress :percentage="progress"
+                   :text-inside="true"
+                   :stroke-width="20"
+                   status="success"
+                   striped
+                   striped-flow
+                   duration="45"/>
+    </div>
+    <div style="height: 100px; margin-top: 20px; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
+      <span style="font-weight: bold">鑰楃敤鍘熺墖</span>
+    </div>
+    <div style="height: 130px; margin-top: 20px;  display: flex; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
+      <span style="font-weight: bold">褰撳墠缁撴灉</span>
+      <div style="margin-top: 5%">
+        <span>浜х敓鏃堕棿锛歿{ formattedTime }}</span>
+        <span style="margin-left: 20px">鎬诲埄鐢ㄧ巼锛�0.0%</span>
+        <span style="margin-left: 20px">灏剧墖锛�</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+
+.header {
+  height: 120px;
+  background-color: #d5eaff;
+  margin-top: -30px;
+  padding: 10px;
+  border-radius: 5px;
+}
+
+div header span {
+  margin-left: 10px;
+  font-weight: bold;
+}
+
+.input {
+  border: none !important;
+  height: 25px;
+  width: 80px;
+}
+
+.time-display {
+  font-size: 18px;
+  color: #409eff;
+}
+
+.buttons {
+  float: right;
+}
+
+#box {
+  padding: 10px;
+  margin-top: 10px;
+  width: 100%;
+  height: 80%;
+}
+
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCard.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCard.vue
new file mode 100644
index 0000000..b87f6e7
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCard.vue
@@ -0,0 +1,374 @@
+<script setup>
+import {onMounted, reactive, ref} from "vue";
+import {useI18n} from "vue-i18n";
+import {Search} from "@element-plus/icons-vue";
+import request from "@/utils/request";
+import deepClone from "@/utils/deepClone";
+import {ElMessage} from "element-plus";
+import useUserInfoStore from "@/stores/userInfo";
+import {changeFilterEvent, filterChanged} from "@/hook";
+
+const {t} = useI18n()
+const userStore = useUserInfoStore()
+const username = userStore.user.userName
+let rowClickIndex = ref(null)
+
+let props = defineProps({
+  processId: null,
+  technologyNumber: null
+})
+
+//鑶滅郴
+const optionVal = ref()
+//鑶滅郴
+const projectNmae = ref()
+//宸ョ▼缂栧彿涓暟
+let projectId = ref()
+//宸ョ▼缂栧彿
+const Id = ref()
+let oddNumbers = ref()
+
+//瀹氫箟鎺ユ敹鍔犺浇琛ㄥご涓嬫媺鏁版嵁
+const titleSelectJson = ref({
+  processType: [],
+})
+
+const selectGlassType = () => {
+  //鏌ヨ鑶滅郴
+  request.post(`/glassOptimize/selectGlassType`).then((res) => {
+    if (res.code == 200) {
+      titleSelectJson.value.processType = res.data.data
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+//鏌ヨ鏈�鏂板伐绋嬪彿
+const getProjectId = () => {
+  request.post(`/glassOptimize/getProjectId`).then((res) => {
+    if (res.code == 200) {
+      projectId = res.data.data[0].project_no
+      // 鑾峰彇瀛楃涓茬殑鏈�鍚庝袱浣嶆暟瀛�
+      let maximum = projectId.slice(-2);
+      let lastTwoInteger = parseInt(maximum, 10);
+       // 璁剧疆涓や綅涓嶅琛�0
+      let formattedNumber = (lastTwoInteger + 1).toString().padStart(2, '0');
+      // 鏍煎紡鍖栧綋鍓嶆棩鏈熶负 "yyMMdd"
+      let currentDate = new Date();
+      let formattedDate = currentDate.getFullYear().toString().slice(-2) +
+          (currentDate.getMonth() + 1).toString().padStart(2, '0') +
+          currentDate.getDate().toString().padStart(2, '0');
+
+      // 鎷兼帴鎴愭渶缁堢殑瀛楃涓�
+      oddNumbers.value = 'P' + formattedDate + formattedNumber;
+
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+
+
+onMounted(() => {
+  getProjectId();
+  selectGlassType();
+
+})
+
+const xGrid = ref()
+const gridOptions = reactive({
+
+  height: '100%',
+  loading: false,
+  border: "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe: true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true, height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProcessCard',
+  scrollX: {enabled: true},
+  scrollY: {enabled: true, gt: 0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow: true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    //remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+  columns: [
+
+    {field: 'select',type:'checkbox',title: t('basicData.check'), width: 80,fixed:"left"},
+    {
+      field: 'process_id',
+      width: 150,
+      title: t('processCard.processId'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'technology_number',
+      width: 70,
+      title: '灞�',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'TotalFloors',
+      width: 150,
+      title: '鎬诲眰鏁�',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'TotalNumber',
+      width: 150,
+      title: '瑙勬牸',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'quantity',
+      width: 150,
+      title: t('order.quantity'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'shape',
+      width: 150,
+      title: t('order.shape'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {
+      field: 'glass_child',
+      width: 150,
+      title: t('order.product'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },
+    {field: 'project', width: 150, title: t('order.project'), showOverflow: "ellipsis",filterMethod:filterChanged},
+    {
+      field: 'area',
+      width: 150,
+      title: t('order.area'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true,
+      filterMethod:filterChanged
+    },{
+      field: 'patch_state',
+      width: 100,
+      title: '琛ョ墖鐘舵��'
+    },
+
+
+  ],//琛ㄥご鍙傛暟
+  data: null,//琛ㄦ牸鏁版嵁
+
+  toolbarConfig: {
+    buttons: [],
+    slots: {
+      buttons: "toolbar_buttons"
+    },
+  },
+
+
+})
+
+const gridEvents = {
+  cellClick({row}) {
+    rowClickIndex.value = row
+    // Emit 浜嬩欢灏嗘洿鏂板悗鐨勫�间紶閫掔粰鐖剁粍浠�
+    emit('updateProcessId', rowClickIndex.value.process_id);
+    emit('updateTechnologyNumber', rowClickIndex.value.technology_number);
+  }
+}
+const emit = defineEmits(['updateProcessId', 'updateTechnologyNumber', 'updateState']);
+
+
+//灏忓渾鐐瑰崟閫夋
+let radio = ref(1);
+let isButtonDisabledAdd = ref(false);
+let isButtonDisabledUpdate = ref(true);
+
+const selectFlowCardList = async () => {
+  request.post(`/glassOptimize/getFlowCardList/${optionVal.value}/${radio.value}`).then((res) => {
+    if (res.code == 200) {
+      getProjectId()
+      isButtonDisabledAdd.value=false
+      isButtonDisabledUpdate.value = true
+      xGrid.value.loadData(res.data.data)
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+
+const getUpdateFlowCardList = async (projectNumber,type,thickness) => {
+  radio.value=1
+  request.post(`/glassOptimize/getUpdateFlowCardList/${type}/${thickness}/${radio.value}/${projectNumber}`).then((res) => {
+    if (res.code == 200) {
+      oddNumbers.value=projectNumber
+      optionVal.value=thickness+"mm"+type
+      isButtonDisabledAdd.value=true
+      isButtonDisabledUpdate.value=false
+      xGrid.value.loadData(deepClone(res.data.data))
+      xGrid.value.getTableData().fullData.forEach(item => {
+        if(item.occupyState===0){
+          xGrid.value.setCheckboxRow(item, true);
+        }
+      })
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+
+//鍒涘缓宸ョ▼
+const addProject = (type) => {
+  const $table = xGrid.value
+  if ($table) {
+    const selectRecords = $table.getCheckboxRecords()
+    if($table.getCheckedFilters().length!==0){
+      ElMessage.error(t('order.msg.pleaseCancelTheFilteringFirst'))
+      return
+    }
+    if (selectRecords.length == 0) {
+      ElMessage.warning(t('reportingWorks.selectProcessCardData'))
+      return;
+    }
+
+    let projectData = ref({
+      projectdetail: selectRecords,
+      userName : username,
+      projectType: type
+    })
+    let inputProject = projectNmae.value
+    if (inputProject == undefined) {
+      inputProject = null
+    }
+    request.post(`/glassOptimize/addProject/${optionVal.value}/${oddNumbers.value}/${inputProject}`, projectData.value).then((res) => {
+      if (res.code == 200 && res.data === "true") {
+        emit('updateState', 1);
+        ElMessage.success(t('basicData.msg.saveSuccess'))
+        selectFlowCardList()
+        getProjectId();
+      }else if(res.data === "false1") {
+        ElMessage.warning("宸ョ▼鍙峰凡瀛樺湪璇烽噸鏂板埛鏂扮晫闈�")
+      } else {
+        ElMessage.warning(res.msg)
+      }
+    })
+
+  }
+}
+const handleRowClassName = ({ row, rowIndex }) => {
+  if (row.patch_state === 1) {
+    return 'high-score';
+  }
+  if (row.occupyState === 0) {
+    return 'high-score2';
+  }
+}
+
+//鎶涘嚭鏂规硶鍒扮埗鐣岄潰
+defineExpose({getProjectId,selectFlowCardList,selectGlassType,getUpdateFlowCardList})
+</script>
+
+<template>
+  <div style="width: 100%;height: 110%; margin-top: -36px">
+    <div>
+      娴佺▼鍗″垪琛�
+      <span style="margin-left: 140px;font-size: 14px">宸ョ▼缂栧彿锛�</span>
+<!--      <span>{{oddNumbers}}</span>-->
+      <el-input disabled v-model="oddNumbers" style="width: 100px"></el-input>
+<!--      <vxe-input :disabled="isDisabled" placeholder="" v-model="oddNumbers" size="small" style="color:black;"></vxe-input>&nbsp;-->
+      <span style="font-size: 14px">宸ョ▼鍚嶇О锛�</span>
+      <el-input style="width: 150px" placeholder="" v-model="projectNmae" size="small"></el-input>
+      <el-button style="margin-left: 20px" type="primary" :disabled="isButtonDisabledAdd" @click="addProject(1)">鍒涘缓</el-button>
+      <el-button style="margin-left: 20px;" type="primary"  :disabled="isButtonDisabledUpdate"  @click="addProject(2)">淇敼</el-button>
+    </div>
+    <vxe-grid
+        ref="xGrid"
+        class="mytable-scrollbar"
+        height="100%"
+        size="small"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+        :row-class-name="handleRowClassName"
+    >
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"
+                        @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option :label="$t('basicData.unchecked')" value="0"></vxe-option>
+              <vxe-option :label="$t('basicData.selected')" value="1"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+
+      <template #toolbar_buttons>
+        <h1>鑶滅郴绛涢�夛細</h1>
+        <el-select v-model="optionVal" clearable default-value="default_city" placeholder="閫夋嫨鑶滅郴"
+                   style="width: 120px">
+          <el-option
+              v-for="item in titleSelectJson['processType']"
+              :key="item.id"
+              :label="item.glassType"
+              :value="item.glassType"
+          />
+        </el-select>
+        <el-button :icon="Search" style="margin-left: 20px" type="primary" @click="selectFlowCardList">鏌ヨ</el-button>
+        <vxe-radio-group v-model="radio" style="margin-left: 20px">
+          <vxe-radio content="鍏ㄩ儴" label="1"></vxe-radio>
+          <vxe-radio content="姝e崟" label="2"></vxe-radio>
+          <vxe-radio content="琛ュ崟" label="3"></vxe-radio>
+        </vxe-radio-group>
+      </template>
+
+    </vxe-grid>
+  </div>
+</template>
+
+<style lang="css">
+.high-score {
+  background-color: #d4baba !important;
+}
+.high-score2 {
+  background-color: #a5aec9 !important;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCardDetail.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCardDetail.vue
new file mode 100644
index 0000000..21d790a
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProcessCardDetail.vue
@@ -0,0 +1,149 @@
+<script setup>
+import {onMounted, reactive, ref, watch} from "vue";
+import {useI18n} from "vue-i18n";
+import request from "@/utils/request";
+import {ElMessage} from "element-plus";
+import {changeFilterEvent, filterChanged} from "@/hook";
+const { t } = useI18n()
+
+let props = defineProps({
+  processId:null,
+  technologyNumber:null
+})
+const xGrid = ref()
+
+const gridOptions = reactive({
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProcessCardDetail',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    //remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+  /*formConfig: {
+    data: {
+      width: '',
+      height: '',
+      quantity: ''
+    },
+    items: [
+      { field: 'width', title: t('order.width')+':', itemRender: { name: 'VxeInput' } },
+      { field: 'height', title: t('order.height')+':', itemRender: { name: 'VxeInput' } },
+      { field: 'quantity', title: t('order.quantity')+':', itemRender: { name: 'VxeInput' } },
+      {
+        itemRender: {
+          name: 'VxeButtonGroup',
+          options: [
+            { type: 'submit', content: t('craft.sure'), status: 'primary' },
+            { type: 'reset', content: t('product.msg.reset') }
+          ]
+        }
+      }
+    ]
+  },*/
+  columns:[
+    {field: 'order_number',width: 70,  title: '搴忓彿',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field:'child_width',width: 150,title: t('order.width'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'child_height',width: 150,title: t('order.height'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'quantity',width: 150, title: t('order.quantity'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'building_number',width: 150, title: t('order.buildingNumber'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'shape',width: 150, title: t('order.shape'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'grossArea',width: 150, title: t('order.grossArea'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+    {field: 'separation',width: 150, title: t('craft.TrademarkAttribute'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true,filterMethod:filterChanged},
+
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [],
+    slots:{
+    },
+  },
+
+})
+
+
+onMounted(()=>{
+
+})
+
+watch(
+
+    () => props.processId,
+    (newValue, oldValue) => {
+if (props.processId!=null){
+  getWorkOrder()
+}
+
+    }
+);
+
+const getWorkOrder = () => {
+  if (props.processId!=null || props.processId!=""){
+    request.post(`/glassOptimize/getProcessCardDetail/${props.processId}/${props.technologyNumber}`).then((res) => {
+      if(res.code==200){
+        xGrid.value.loadData(res.data.data)
+      }else{
+        ElMessage.warning(res.msg)
+      }
+    })
+  }
+
+}
+</script>
+
+<template>
+  <div style="width: 100%;height: 100%">
+    <h1>娴佺▼鍗¤鎯�</h1>
+    <vxe-grid
+        size="small"
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectDetail.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectDetail.vue
new file mode 100644
index 0000000..e85a929
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectDetail.vue
@@ -0,0 +1,611 @@
+<script setup>
+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";
+import SetAmount from "@/views/pp/glassOptimize/page/SetAmount.vue";
+import SetTrimming from "@/views/pp/glassOptimize/page/SetTrimming.vue";
+import CheckInventory from "@/views/pp/glassOptimize/page/CheckInventory.vue";
+import request from "@/utils/request";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {useRoute} from 'vue-router';
+
+
+const {t} = useI18n()
+
+const xGrid = ref()
+const gridOptions = reactive({
+  height: '100%',
+  loading: false,
+  border: "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe: true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true, height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProjectDetail',
+  scrollX: {enabled: true},
+  scrollY: {enabled: true, gt: 0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow: true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+
+  columns: [
+    {type: 'seq', title: t('basicData.Number'), width: 80},
+    {field: 'order_number', title: '璁㈠簭', width: 70},
+    {field: 'width',
+      width: 100,
+      title: t('order.width'),
+      sortable: true
+    },
+    {
+      field: 'height',
+      width: 100,
+      title: t('order.height'),
+      sortable: true
+    },
+    {
+      field: 'quantity',
+      width: 150,
+      title: t('order.quantity'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'longGrind1',
+      width: 150,
+      title: '闀跨(1',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'longGrind2',
+      width: 150,
+      title: '闀跨(2',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'shortGrind1',
+      width: 150,
+      title: '鐭(1',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'shortGrind2',
+      width: 150,
+      title: '鐭(2',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'shape',
+      width: 150,
+      title: t('order.shape'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'process_id',
+      width: 150,
+      title: '娴佺▼鍗″彿',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'product_name',
+      width: 150,
+      title: t('order.product'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'price',
+      width: 150,
+      title: t('鍗曚环'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'remark',
+      width: 150,
+      title: t('basicData.remarks'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'building_number',
+      width: 150,
+      title: '妤煎眰鍙�',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'perimeter',
+      width: 150,
+      title: t('order.perimeter'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'area',
+      width: 150,
+      title: t('order.grossArea'),
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+
+    {
+      field: 'layout_id',
+      width: 150,
+      title: '鏋跺彿',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'technology_number',
+      width: 150,
+      title: '灞�',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'glass_child',
+      width: 150,
+      title: '鍗曠墖鍚嶇О',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+    {
+      field: 'icon',
+      width: 150,
+      title: '鍗版爣绫诲瀷',
+      filters: [{data: ''}],
+      slots: {filter: 'num1_filter'},
+      sortable: true
+    },
+  ],//琛ㄥご鍙傛暟
+  data: null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [
+    ],
+    import: false,
+    // export: true,
+    // print: true,
+    zoom: true,
+    custom: true
+  },
+  //鍙抽敭鑿滃崟
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {code: 'displayProcessCard', name: '鏄剧ず娴佺▼鍗�',},
+          {code: 'hideProcessCard', name: '闅愯棌娴佺▼鍗�',},
+          {code: 'setShape', name: '璁剧疆鍥惧舰',},
+          {code: 'Export', name: '鏁版嵁瀵煎嚭', prefixIcon: 'vxe-icon-download', visible: true, disabled: false},
+          {code: 'safeDXF', name: '鍥惧舰鍙﹀瓨涓篋XF',},
+        ],
+        []
+      ]
+    },
+  },
+})
+const processCardColumns = reactive({
+  columns:[
+  {field: 'process_id', title: '娴佺▼鍗�', width: 200, align: 'center'},
+  {field: 'project', title: '椤圭洰鍚�', width: 150, align: 'center'},
+  {field: 'order_number', title: '璁㈠簭', width: 100, align: 'center'},
+  {field: 'sizes', title: '灏哄', width: 200, align: 'center'},
+  {field: 'layer', title: '灞�', width: 100, align: 'center'},
+  {field: 'quantity', title: '鏁伴噺', width: 100, align: 'center'}
+],
+  toolbarConfig: {
+    buttons: [
+    ],
+    import: false,
+    // export: true,
+    // print: true,
+
+  },
+});
+
+// 鍙抽敭鑿滃崟
+const operationConfigs = [
+  {
+    code: 'setAmount', // 璁剧疆缁熶竴纾ㄩ噺
+    successMsg: '宸叉墦寮�锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    openAmount: async () => {
+      dialogVisible.value[2] = true;
+    }
+  },
+  {
+    code: 'displayProcessCard',
+    successMsg: '鎿嶄綔鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    displayProcess: () => {
+      getProcessCard();
+      // 鏄剧ず娴佺▼鍗℃椂锛屽皢 left-table 瀹藉害鏀逛负 50%
+      leftTableWidth.value = 60;
+      showProcessCardTable.value = true;
+    }
+  },
+  {
+    code: 'hideProcessCard',
+    successMsg: '鎿嶄綔鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    hideProcess: () => {
+      leftTableWidth.value = 100;
+      showProcessCardTable.value = false;
+    }
+  },
+  {
+    code: 'setShape',
+    successMsg: '鎿嶄綔鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    showMessage: () => {
+      ElMessage.info('姝ゅ姛鑳芥殏鏈畬鍠勶紝鏆傛椂鏃犳硶鎵ц璁剧疆鍥惧舰鎿嶄綔銆�');
+    }
+  },
+  {
+    code: 'Export', // 瀵煎嚭鏂囦欢鎿嶄綔鐨勯厤缃�
+    successMsg: '鏂囦欢瀵煎嚭鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+  },
+  {
+    code: 'safeDXF',
+    successMsg: '鎿嶄綔鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    showMessage: () => {
+      ElMessage.info('姝ゅ姛鑳芥殏鏈畬鍠勶紝鏆傛椂鏃犳硶鎵ц鍥惧舰鍙﹀瓨涓篋XF鎿嶄綔銆�');
+    }
+  },
+  {
+    code: 'exportOPTIMA',
+    successMsg: '鎿嶄綔鎴愬姛锛�',
+    gridRef: xGrid,
+    requiresRow: false,
+    showMessage: () => {
+      ElMessage.info('姝ゅ姛鑳芥殏鏈畬鍠勶紝鏆傛椂鏃犳硶鎵ц瀵煎嚭鏁版嵁鍒癘PTIMA鎿嶄綔銆�');
+    }
+  },
+]
+
+// 鍙抽敭鑿滃崟鐐瑰嚮閫昏緫
+const gridEvents = {
+  menuClick({menu}) {
+    const $grid = xGrid.value;
+    if ($grid) {
+      const config = operationConfigs.find(c => c.code === menu.code);
+      if (config) {
+        if (config.code === 'Export') {
+          config.gridRef.value.exportData();
+          ElMessage.success(config.successMsg);
+          return;
+        }
+        // 娣诲姞纭鎻愮ず寮圭獥锛岃闂敤鎴锋槸鍚﹁繘琛屽綋鍓嶆搷浣�
+        ElMessageBox.confirm('鏄惁杩涜褰撳墠鎿嶄綔锛�', '纭鎿嶄綔', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          if (config.code === 'setAmount') {
+            config.openAmount();
+            ElMessage.success(config.successMsg);
+          } else if (config.code === 'displayProcessCard') {
+            config.displayProcess();
+            ElMessage.success(config.successMsg);
+          } else if (config.code === 'hideProcessCard') {
+            config.hideProcess();
+            ElMessage.success(config.successMsg);
+          } else if (['setShape', 'safeDXF', 'exportOPTIMA'].includes(config.code)) {
+            config.showMessage();
+          }
+        }).catch(() => {
+          // 鐢ㄦ埛鐐瑰嚮鍙栨秷鍚庢墽琛岀殑閫昏緫
+          ElMessage.info('宸插彇娑堟搷浣�');
+        });
+      } else {
+        console.error(`鏈壘鍒版搷浣滈�夐」 ${menu.code} 瀵瑰簲鐨勯厤缃紝璇锋鏌ラ厤缃」`);
+      }
+    }
+  },
+};
+
+const handleCommand = async (command) => {
+  await emit('changeDialog', command)
+}
+
+let originalFilm=ref(true)
+let surplusMaterial=ref(false)
+
+//浼樺寲璁$畻
+const dialogVisible = ref({});
+const openDialog = (index) => {
+  dialogVisible.value[index] = true;
+};
+//鍏抽棴寮圭獥
+const closeDialog = (index) => {
+  dialogVisible.value[index] = false;
+};
+
+//鍙抽敭鑿滃崟缁熶竴淇竟
+const props = defineProps({
+  TrimmingDialogVisible: Boolean
+});
+watch(() => props.TrimmingDialogVisible, (newValue) => {
+  if (newValue === true) {
+    dialogVisible.value[3] = newValue;
+  }
+});
+
+const route = useRoute();
+//宸ョ▼鍙�
+const projectNo = ref(route.params.projectNo);
+const projectName = ref('');
+const thickNess = ref(route.params.thickNess);
+const model = ref(route.params.model);
+onBeforeUnmount(() => {
+  localStorage.setItem('projectNo', projectNo.value);
+});
+
+const fetchData = () => {
+  request.post(`/glassOptimize/projectInfoThirdParty/${projectNo.value}`).then((res) => {
+    if ((Number(res.code) === 200)) {
+      const data = res.data.data;
+      const grindingTrimming = res.data.grindingTrimming;
+      if(grindingTrimming!==null){
+        const formattedData = grindingTrimming.map(item => {
+          const formattedItem = {};
+          for (const key in item) {
+            if (typeof item[key] === 'string') {
+              //鍘婚櫎瀛楃涓插睘鎬у�煎紑澶村拰缁撳熬鐨勫弻寮曞彿
+              formattedItem[key] = item[key].replace(/^\"|\"$/g, '');
+            } else {
+              formattedItem[key] = item[key];
+            }
+          }
+          return formattedItem;
+        });
+
+      }
+      xGrid.value.loadData(data);
+      gridOptions.data = data;
+      projectName.value = data[0].project_name;
+    } else {
+      ElMessage.warning(res.msg);
+    }
+  }).catch((error) => {
+    console.error("鑾峰彇鏁版嵁鍑洪敊:", error);
+  });
+};
+onMounted(() => {
+  if (projectNo.value) {
+    fetchData();
+  }
+});
+
+// 娴佺▼鍗� 瀹藉害
+const leftTableWidth = ref(100);
+const showProcessCardTable = ref(false);
+// 鐢ㄤ簬瀛樺偍娴佺▼鍗℃暟鎹�
+const processCardData = ref(null);
+//娴佺▼鍗�
+const getProcessCard = () => {
+  request.post(`/glassOptimize/getProcessCardMpThirdParty/${projectNo.value}`).then((res) => {
+    if (Number(res.code) === 200) {
+      processCardData.value = res.data.data;
+    } else {
+      ElMessage.warning(res.msg);
+    }
+  });
+};
+
+
+// 浠庡瓙缁勪欢SetAmount鑾峰彇纾ㄩ噺鍊硷紝骞舵洿鏂拌〃鏍兼暟鎹�
+const Amount = (amountData) => {
+  fetchData()
+  /*nextTick(() => {
+    const data = gridOptions.data;
+    if (data) {
+      try {
+        const updatedData = [];
+        for (let i = 0; i < data.length; i++) {
+          const item = data[i];
+          const updatedItem = {
+            ...item,
+            longGrind1: Number(amountData.quicksetTop),
+            longGrind2: Number(amountData.quicksetRight),
+            shortGrind1: Number(amountData.quicksetBottom),
+            shortGrind2: Number(amountData.quicksetLeft)
+          };
+          updatedData.push(updatedItem);
+        }
+        gridOptions.data = updatedData;
+        xGrid.value.loadData(updatedData);
+      } catch (error) {
+        console.error('鏇存柊琛ㄦ牸鏁版嵁鏃跺嚭閿�:', error);
+        // 杩欓噷鍙互鏍规嵁瀹為檯闇�姹傛坊鍔犱竴浜涘洖婊氭搷浣滄垨鑰呮彁绀虹敤鎴风殑閫昏緫锛屾瘮濡傛樉绀轰竴涓敊璇彁绀烘绛�
+        ElMessage.error('鏇存柊纾ㄩ噺鏁版嵁鏃跺嚭鐜伴敊璇紝璇锋鏌ヨ緭鍏ユ垨鑱旂郴绠$悊鍛�');
+      }
+    } else {
+      console.warn('琛ㄦ牸鏁版嵁涓虹┖锛屾棤娉曟洿鏂扮(閲忓��');
+    }
+  });*/
+};
+
+//涓浆绔欐帴鍙桽etTrimming鐨勫�硷紙璁剧疆淇竟锛�
+const emit = defineEmits([
+  'changeDialog',
+  'forward-data-to-grandparent',
+  'send-inventory-to-op'
+]);
+
+const handleTrimmingData = (data) => {
+  emit('forward-data-to-grandparent', data);
+};
+
+//涓浆绔欐帴鍙桟heckInventory鐨勫�硷紙鏌ヨ搴撳瓨锛�
+const handleInventory = (selectedLabel1, selectedLabel2) => {
+  let type=0;
+  if(originalFilm.value===true&&surplusMaterial.value===true){
+    type=3
+  }else if(originalFilm.value===true&&surplusMaterial.value===false){
+    type=1
+  }else if(originalFilm.value===false&&surplusMaterial.value===true){
+    type=2
+  }else{
+    type=1
+  }
+  emit('send-inventory-to-op', selectedLabel1, selectedLabel2,type);
+}
+
+</script>
+
+<template>
+  <div style="width: 100%;height: 85%;">
+    <!-- 澶撮儴 -->
+    <div id="header" >
+      <!--宸ョ▼鏂囦欢鑿滃崟-->
+      <el-dropdown @command="handleCommand">
+        <el-button type="primary" :icon="Folder" style="margin-top: 8px; margin-left: 5px">
+          宸ョ▼鏂囦欢
+        </el-button>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <el-dropdown-item :command="2" :icon="Setting">宸ョ▼绠$悊</el-dropdown-item>
+            <el-dropdown-item :command="3" :icon="Operation">妯℃嫙璁$畻</el-dropdown-item>
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
+
+      <div id="title">
+        <span>宸ョ▼缂栧彿锛�</span>
+        <el-input readonly placeholder="" style="width: 150px" v-model="projectNo"></el-input>&nbsp;
+        <span>宸ョ▼鍚嶇О锛�</span>
+        <el-input readonly placeholder="" style="width: 150px; margin-right: 140px;" v-model="projectName" ></el-input>
+      </div>
+    </div>
+
+    <!-- 琛ㄦ牸瀹瑰櫒 -->
+    <div class="table-container">
+      <vxe-grid
+          class="left-table"
+          @filter-change="filterChanged"
+          height="100%"
+          ref="xGrid"
+          v-bind="gridOptions"
+          v-on="gridEvents"
+          v-bind:style="{ width: leftTableWidth + '%' }"
+      >
+        <template #num2_filter="{ column, $panel }">
+          <div>
+            <div v-for="(option, index) in column.filters" :key="index">
+              <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"
+                          @change="changeFilterEvent($event, option, $panel)">
+                <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+                <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+              </vxe-select>
+            </div>
+          </div>
+        </template>
+        <template #num1_filter="{ column, $panel }">
+          <div>
+            <div v-for="(option, index) in column.filters" :key="index">
+              <input
+                  type="type"
+                  v-model="option.data"
+                  @keyup.enter.native="$panel.confirmFilter()"
+                  @input="changeFilterEvent($event, option, $panel)"/>
+            </div>
+          </div>
+        </template>
+      </vxe-grid>
+
+      <!-- 娴佺▼鍗¤〃鏍� -->
+      <vxe-grid
+          height="100%"
+          class="right-table"
+          :data="processCardData"
+          v-bind="processCardColumns"
+          v-if="showProcessCardTable"
+          :header-cell-style="{'height': '51.9px'}"
+      >
+      </vxe-grid>
+
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.table-container {
+  width: 100%;
+  height: 100%;
+  flex: 1;
+  display: flex;
+}
+
+.left-table {
+  float: left;
+}
+
+.right-table {
+  width: 40%;
+}
+
+:deep(.vxe-toolbar){
+  height: 40px;
+}
+
+#header {
+  height: 50px;
+  display: flex;
+
+}
+
+#title {
+  margin: 8px 5px;
+  width: 1240px;
+}
+
+#button {
+  margin-left: 10px;
+}
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectList.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectList.vue
new file mode 100644
index 0000000..15c125a
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/ProjectList.vue
@@ -0,0 +1,281 @@
+<script setup>
+import {nextTick, onMounted, reactive, ref, watch} from "vue";
+import {useI18n} from "vue-i18n";
+import request from "@/utils/request";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {defineEmits} from 'vue';
+const { t } = useI18n()
+
+const xGrid = ref()
+
+
+const gridOptions = reactive({
+  height:'100%',
+  loading: false,
+  border:  "full",//琛ㄦ牸鍔犺竟妗�
+  keepSource: true,//淇濇寔婧愭暟鎹�
+  align: 'center',//鏂囧瓧灞呬腑
+  stripe:true,//鏂戦┈绾�
+  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//榧犳爣绉诲姩鎴栭�夋嫨楂樹寒
+  id: 'ProjectList',
+  scrollX:{enabled: true},
+  scrollY:{ enabled: true ,gt:0},//寮�鍚櫄鎷熸粴鍔�
+  showOverflow:true,
+  columnConfig: {
+    resizable: true,
+    useKey: true
+  },
+  filterConfig: {   //绛涢�夐厤缃」
+    remote: true
+  },
+  customConfig: {
+    storage: true
+  },
+  editConfig: {
+    trigger: 'click',
+    mode: 'row',
+    showStatus: true
+  },
+  columns:[
+    {field: 'id',width: 150, title: 'ID',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'project_no',width: 150, title: '宸ョ▼鍙�',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'project_name',width: 150, title: '椤圭洰鍚嶇О',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'glass_type',width: 150, title: '鑶滅郴',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'glass_thickness',width: 150, title: '鍘氬害',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'type',width: 150, title: '绫诲瀷',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'state',width: 150, title: '鐘舵��',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'glass_total',width: 150, title: t('order.quantity'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'glass_total_area',width: 150, title: t('order.grossArea'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'process_qty',width: 150, title: '娴佺▼鏁伴噺',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+    {field: 'process_cards',width: 150, title: '娴佺▼鍗″彿',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
+
+  ],//琛ㄥご鍙傛暟
+  data:null,//琛ㄦ牸鏁版嵁
+  toolbarConfig: {
+    buttons: [
+    ],
+    import: false,
+    // export: true,
+    // print: true,
+    zoom: true,
+    custom: true
+  },
+  //鍙抽敭鑿滃崟閫夐」
+  menuConfig: {
+    body: {
+      options: [
+        [
+          {code: 'openProject', name: '鎵撳紑宸ョ▼', prefixIcon: 'vxe-icon-folder-open'},
+          {code: 'compute', name: '妯℃嫙璁$畻', prefixIcon: 'vxe-icon-subtable'},
+          {code: 'delProject', name: '鍒犻櫎宸ョ▼', prefixIcon: 'vxe-icon-delete'},
+        ],
+        []
+      ]
+    }
+  }
+
+})
+
+// 瀹氫箟鎿嶄綔閰嶇疆瀵硅薄鏁扮粍锛岄泦涓鐞嗕笉鍚屾搷浣滈�夐」瀵瑰簲鐨勫弬鏁�
+const operationConfigs = [
+  {
+    code: 'openProject', // 鎵撳紑宸ョ▼
+    initialState: ['10', '20', '100', '200'], //
+    targetState: null,
+    successMsg: '宸叉墦寮�锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    openFile: async ({row}) => {
+      const projectNumber = row.projectNumber;
+      const thickness = row.thickness;
+      const glassType = row.glassType;
+      await router.push({
+        name: 'optimizeInfo',
+        params: {
+          projectNo: projectNumber,
+          thickNess: thickness,
+          model: glassType
+        }
+      });
+    }
+  },
+  {
+    code: 'compute', // 鎵撳紑妯℃嫙璁$畻鎿嶄綔
+    initialState: ['1', '2'], //
+    targetState: null,
+    successMsg: '妯℃嫙璁$畻宸插惎鍔紒',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎妯℃嫙璁$畻鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+    requiresRow: true,
+    actionFunction: async ({row}) => {
+      const projectNo = row.projectNumber;
+      emit('switch-dialog', row);
+    }
+  },
+  {
+    code: 'delProject',
+    initialState: ['1', '2', '10', '20', '100'],
+    targetState: null,
+    successMsg: '宸ョ▼鍒犻櫎鎴愬姛锛�',
+    checkMessage: '褰撳墠宸ョ▼鐘舵�佷笉绗﹀悎鍒犻櫎鏉′欢锛岃纭宸ョ▼鐘舵�佸悗鍐嶆搷浣滐紒',
+  }
+
+];
+
+//瀹氫箟鍒囨崲妯℃嫙璁$畻寮圭獥
+const emit = defineEmits(['switch-dialog']);
+
+onMounted(async () => {
+  getProject();
+})
+
+
+
+const getProject = ()=>{
+  request.post(`/glassOptimize/getProjectList`).then((res) => {
+    if(res.code==200){
+      xGrid.value.loadData(res.data.data)
+    }else{
+      ElMessage.warning(res.msg)
+    }
+  })
+}
+
+const gridEvents = {
+  menuClick({menu, row}) {
+    const $grid = xGrid.value;
+    if ($grid) {
+      const config = operationConfigs.find(c => c.code === menu.code);
+      if (config) {
+        if (config.requiresRow && !row) {
+          ElMessage.warning('鏈�変腑宸ョ▼锛岃閫変腑宸ョ▼鍚庡啀杩涜褰撳墠鎿嶄綔锛�');
+          return;
+        }
+        if (config.code === 'compute') {
+          config.actionFunction({row});
+          return;
+        }
+        // 娣诲姞纭鎻愮ず寮圭獥锛岃闂敤鎴锋槸鍚﹁繘琛屽綋鍓嶆搷浣�
+        ElMessageBox.confirm('鏄惁杩涜褰撳墠鎿嶄綔锛�', '纭鎿嶄綔', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          if (config.code === 'viewTempered') {
+            ElMessageBox.alert('褰撳墠鐐瑰嚮鐨勬槸鏌ョ湅閽㈠寲鐗堝浘鍔熻兘锛岀洰鍓嶆殏鏃朵粎鍋氭彁绀猴紝鏆傛棤瀹為檯鏌ョ湅鎿嶄綔!', '鍔熻兘鎻愮ず', {
+              confirmButtonText: '鎴戠煡閬撲簡'
+            });
+            return;
+          }
+          if (config.code === 'viewOptimize') {
+            ElMessageBox.alert('褰撳墠鐐瑰嚮鐨勬槸鏌ョ湅閽㈠寲鐗堝浘鍔熻兘锛岀洰鍓嶆殏鏃朵粎鍋氭彁绀猴紝鏆傛棤瀹為檯鏌ョ湅鎿嶄綔!', '鍔熻兘鎻愮ず', {
+              confirmButtonText: '鎴戠煡閬撲簡'
+            });
+            return;
+          }
+          if (config.code === 'delProject') {
+            if (!row) {
+              ElMessage.warning(config.checkMessage);
+              return;
+            }
+            const isInitialStateMatched = config.initialState.includes(String(row.state));
+            if (!isInitialStateMatched) {
+              ElMessage.warning(config.checkMessage);
+              return;
+            }
+            deleteProject(row.projectNumber, config);
+          } else if (!checkOperationCondition(config, row)) {
+            ElMessage.warning(config.checkMessage);
+            return;
+          } else {
+            if (config.code === 'openProject') {
+              handleSameDataOperation(row).then(({isRoutesEqual}) => {
+                if (!isRoutesEqual) {
+                  config.openFile({row});
+                  ElMessage.success(config.successMsg);
+                }
+              });
+            } else if (config.code === 'compute') {
+              config.actionFunction({row});
+            } else  if (config.code === 'optimizeTypography') {
+              handleSameDataOperation(row).then(({isRoutesEqual}) => {
+                if (!isRoutesEqual) {
+                  config.Typography({row});
+                  ElMessage.success(config.successMsg);
+                }
+              });
+            }
+            else {
+              row.state = config.targetState;
+              const index = produceList.value.findIndex(item => item === row);
+              if (index !== -1) {
+                produceList.value.splice(index, 1, {...row});
+                xGrid.value.reloadData(produceList.value);
+              }
+              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState, config.successMsg);
+            }
+          }
+        }).catch(() => {
+          // 鐢ㄦ埛鐐瑰嚮鍙栨秷鍚庢墽琛岀殑閫昏緫
+          ElMessage.info('宸插彇娑堟搷浣�');
+        });
+      } else {
+        console.error(`鏈壘鍒版搷浣滈�夐」 ${menu.code} 瀵瑰簲鐨勯厤缃紝璇锋鏌ラ厤缃」`);
+      }
+    }
+  },
+  cellDblclick: ({row}) => {
+    const menu = {code: 'openProject'};
+    nextTick(() => {
+      handleSameDataOperation(row).then(({isRoutesEqual}) => {
+        if (!isRoutesEqual) {
+          gridEvents.menuClick({menu, row});
+        }
+      });
+    });
+  },
+};
+</script>
+
+<template>
+  <div style="width: 100%;height: 100%">
+    <h1>宸ョ▼鍒楄〃</h1>
+    <vxe-grid
+        size="small"
+        @filter-change="filterChanged"
+        height="100%"
+        class="mytable-scrollbar"
+        ref="xGrid"
+        v-bind="gridOptions"
+        v-on="gridEvents"
+    >
+
+      <template #num2_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
+              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
+              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
+            </vxe-select>
+          </div>
+        </div>
+      </template>
+
+      <template #num1_filter="{ column, $panel }">
+        <div>
+          <div v-for="(option, index) in column.filters" :key="index">
+            <input
+
+                type="type"
+                v-model="option.data"
+                @keyup.enter.native="$panel.confirmFilter()"
+                @input="changeFilterEvent($event, option, $panel)"/>
+          </div>
+        </div>
+      </template>
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/RectRenderer.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/RectRenderer.vue
new file mode 100644
index 0000000..faea382
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/RectRenderer.vue
@@ -0,0 +1,341 @@
+<template>
+  <div ref="layoutPanel" :class="panelClass" :style="panelStyle">
+    <div id="printFlowCard">
+      <div v-for="(layout, layoutIndex) in layouts" :key="layoutIndex" class="layout-wrapper">
+        <div class="header" :style="headerStyle(layoutIndex)">
+          宸ョ▼鍙穥{ processId }}
+          {{ getCurrentRectInfo(layoutIndex) }}
+        </div>
+        <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
+          <div class="grid-container" :class="`cols-${printColumns}`">
+            <div
+              v-for="(rect, rectIndex) in layout.rects"
+              :key="rectIndex"
+              :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
+              :class="rectClass"
+              :style="rectStyle(rect, layoutIndex)"
+              @click="handleRectClick(layoutIndex, rectIndex)"
+            >
+              <div v-if="!rect.isRemain" class="rect-content">
+                <div class="size">{{ rect.w }}脳{{ rect.h }}</div>
+                <div class="jia-hao">{{ rect.JiaHao }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted, watch, nextTick } from 'vue';
+import request from "@/utils/request";
+
+const props = defineProps({
+  layoutData: { type: Object, required: true },
+  gw: { type: Number, default: 1400 },
+  gh: { type: Number, default: 1100 },
+  style: { type: String, default: 'width:100%;height:800px;display:block;background:gray' },
+  printLayout: { type: String, default: '2rows-2cols' }, // 鍙�夊�硷細4rows-2cols, 3rows-2cols, 3rows-1col, 2rows-2cols
+  fixedPageHeight: { type: Number, default: 1100 } // 鍥哄畾椤甸潰楂樺害
+});
+
+const 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 processId = localStorage.getItem('projectNo');
+const printColumns = ref(2); // 鍒濆鍖栦负2鍒�
+const layoutsPerPage = ref(4); // 榛樿姣忛〉鏄剧ず4涓竷灞�锛�2琛屆�2鍒楋級
+
+// 瀹氫箟涓嶅悓甯冨眬鐨勬斁澶ф瘮渚�
+const layoutScales = {
+  '4rows-2cols': 0.8, // 鍥涜涓ゅ垪锛岃緝灏忕殑鏀惧ぇ姣斾緥
+  '3rows-2cols': 0.9, // 涓夎涓ゅ垪锛岄�備腑鐨勬斁澶ф瘮渚�
+  '3rows-1col': 1.0,  // 涓夎涓�鍒楋紝杈冨ぇ鐨勬斁澶ф瘮渚�
+  '2rows-2cols': 1   // 涓よ涓ゅ垪锛岃緝澶х殑鏀惧ぇ姣斾緥
+};
+
+// 鐩戝惉printLayout鍙樺寲
+watch(() => props.printLayout, (newVal) => {
+  adjustPrintLayout();
+  updateLayout();
+});
+
+const layoutContainerStyle = (layoutIndex) => {
+  const containerWidth = (props.gw - 20) / printColumns.value; // 鍑忓皯杈硅窛
+  const containerHeight = (props.gh - 20) / Math.ceil(layoutsPerPage.value / printColumns.value);
+  const x = (layoutIndex % printColumns.value) * containerWidth;
+  const y = Math.floor(layoutIndex / printColumns.value) * containerHeight;
+  return {
+    position: 'absolute',
+    left: `${x}px`,
+    top: `${y}px`,
+    width: `${containerWidth}px`,
+    height: `${containerHeight}px`,
+    overflow: 'visible',
+    padding: '10px' // 娣诲姞鍐呰竟璺�
+  };
+};
+
+const headerStyle = (layoutIndex) => {
+  const containerWidth = (props.gw - 20) / printColumns.value;
+  const containerHeight = (props.gh - 20) / Math.ceil(layoutsPerPage.value / printColumns.value);
+  const x = (layoutIndex % printColumns.value) * containerWidth;
+  const y = Math.floor(layoutIndex / printColumns.value) * containerHeight;
+  const scale = Math.min(
+    containerWidth,
+    containerHeight
+  ) * 1.2; // 鏀惧ぇ1.2鍊�
+  return {
+    position: 'absolute',
+    left: `${x}px`,
+    top: `${y - 45}px`,
+    width: `${scale}px`,
+    textAlign: 'center',
+    zIndex: 1000,
+    background: '#ffffff',
+    padding: '5px',
+    fontSize: '12px'
+  };
+};
+
+const rectStyle = (rect, layoutIndex) => {
+  const layout = layouts.value[layoutIndex];
+  const containerWidth = (props.gw - 100) / printColumns.value;
+  const containerHeight = (props.gh - 100) / Math.ceil(layoutsPerPage.value / printColumns.value);
+  
+  // 鏍规嵁褰撳墠鎵撳嵃甯冨眬鑾峰彇鏀惧ぇ姣斾緥
+  const currentScale = layoutScales[props.printLayout] || 1.0;
+  
+  const scale = Math.min(
+    containerWidth / layout.width,
+    containerHeight / layout.height
+  ) * currentScale; // 搴旂敤褰撳墠甯冨眬鐨勬斁澶ф瘮渚�
+  
+  return {
+    position: 'absolute',
+    left: `${rect.x * scale}px`,
+    top: `${rect.y * scale}px`,
+    width: `${rect.w * scale}px`,
+    height: `${rect.h * scale}px`,
+    backgroundColor: rect.isRemain ? '#f0f0f0' : '#a0d8ef',
+    border: '1px solid #000',
+    cursor: 'pointer'
+  };
+};
+
+const handleRectClick = (layoutIndex, rectIndex) => {
+  focusIndex.value = { layoutIndex, rectIndex };
+  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 sum = layout.rects.reduce((sum, r) => sum + (r.w * r.h), 0);
+  const areaUtilization = ((sum / (width * height)) * 100).toFixed(2);
+  return `${currentRectIndex}/${totalRects} ${height}X${width}X1 ${areaUtilization}%`;
+};
+
+const adjustPrintLayout = () => {
+  switch (props.printLayout) {
+    case '4rows-2cols':
+      printColumns.value = 2;
+      layoutsPerPage.value = 8; // 4琛屆�2鍒�
+      break;
+    case '3rows-2cols':
+      printColumns.value = 2;
+      layoutsPerPage.value = 6; // 3琛屆�2鍒�
+      break;
+    case '3rows-1col':
+      printColumns.value = 1;
+      layoutsPerPage.value = 3; // 3琛屆�1鍒�
+      break;
+    case '2rows-2cols':
+      printColumns.value = 2;
+      layoutsPerPage.value = 4; // 2琛屆�2鍒�
+      break;
+    default:
+      printColumns.value = 2;
+      layoutsPerPage.value = 4;
+  }
+};
+
+const updateLayout = () => {
+  if (!layoutPanel.value) return;
+  layouts.value = props.layoutData.Layouts;
+  adjustPrintLayout();
+  // 寮哄埗閲嶆柊娓叉煋
+  layoutPanel.value.offsetHeight; // 瑙﹀彂甯冨眬鏇存柊
+};
+
+onMounted(() => {
+updateLayout();
+});
+
+onUnmounted(() => {
+  rectsElements.value = {};
+});
+
+const print = () => {
+  const el = document.getElementById('printFlowCard');
+  const doc = document;
+  const body = doc.body || doc.getElementsByTagName("body")[0];
+  const printId = "print-" + Date.now();
+
+  // 鍒涘缓涓�涓厠闅嗙殑鑺傜偣
+  const content = document.createElement("div");
+  content.id = printId;
+  content.appendChild(el.cloneNode(true)); // 鍏嬮殕鑺傜偣骞朵繚鐣欐墍鏈夊睘鎬у拰瀛愯妭鐐�
+
+  const style = document.createElement("style");
+  style.innerHTML =
+    "body>#" +
+    printId +
+    "{display:none}@media print{" +
+    "@page {" +
+    "    size: auto; " +
+    "    margin: 13mm 4mm 0mm 4mm; " +
+    "  }body>:not(#" +
+    printId +
+    "){display:none !important}body>#" +
+    printId +
+    "{display:block;padding-top:1px}}";
+
+  body.appendChild(style);
+  body.appendChild(content);
+
+  // 浼樺寲鍒嗛〉閫昏緫
+  const layoutWrappers = content.querySelectorAll('.layout-wrapper');
+  let currentPageHeight = 0;
+  let currentWrapperIndex = 0;
+
+  layoutWrappers.forEach((wrapper, index) => {
+    const wrapperHeight = wrapper.offsetHeight;
+    if (currentPageHeight + wrapperHeight > props.fixedPageHeight) {
+      const pageBreak = document.createElement('div');
+      pageBreak.className = 'element-to-break-after';
+      layoutWrappers[currentWrapperIndex - 1].appendChild(pageBreak);
+      currentPageHeight = wrapperHeight;
+    } else {
+      currentPageHeight += wrapperHeight;
+    }
+    currentWrapperIndex = index + 1;
+  });
+
+  setTimeout(() => {
+    window.print();
+    body.removeChild(content);
+    body.removeChild(style);
+  }, 200);
+};
+
+defineExpose({
+  print,
+  updateLayout
+});
+</script>
+
+<style scoped>
+@media print {
+  .layout-wrapper {
+    page-break-inside: avoid;
+    margin-bottom: 20px;
+  }
+
+  .element-to-break-after {
+    page-break-after: always;
+  }
+
+  .header {
+    position: static;
+    width: 100%;
+  }
+
+  .layout-container {
+    position: static;
+    width: 100%;
+    height: auto;
+  }
+
+  .grid-container {
+    display: grid;
+    gap: 10px; /* 鍑忓皯鎵撳嵃鏃剁殑缃戞牸闂磋窛 */
+  }
+
+  .cols-1 {
+    grid-template-columns: 1fr;
+  }
+
+  .cols-2 {
+    grid-template-columns: repeat(2, 1fr);
+  }
+
+  .cols-3 {
+    grid-template-columns: repeat(3, 1fr);
+  }
+
+  .cols-4 {
+    grid-template-columns: repeat(4, 1fr);
+  }
+}
+
+.element-to-break-after {
+  page-break-after: always;
+}
+
+.layout-wrapper {
+  position: relative;
+  margin-top: 50px;
+}
+
+.header {
+  position: absolute;
+  top: -45px;
+  left: 0;
+  width: 100%;
+  text-align: center;
+  z-index: 1000;
+  background-color: #ffffff;
+  padding: 5px;
+  font-size: 12px;
+}
+
+.layout-container {
+  position: relative;
+  overflow: visible;
+}
+
+.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 {
+  grid-row: 2;
+  grid-column: 1;
+  margin: auto;
+  font-size: 14px;
+  font-weight: bold;
+}
+</style>
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetAmount.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetAmount.vue
new file mode 100644
index 0000000..10fccb5
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetAmount.vue
@@ -0,0 +1,217 @@
+<script setup>
+import {onMounted, ref} from "vue";
+import {defineEmits} from 'vue';
+import request from "@/utils/request";
+import {ElMessage} from "element-plus";
+
+onMounted(async() => {
+  await firstLoading()
+})
+
+const firstLoading = async() => {
+  request.post(`/glassOptimize/getConfiguration/纾ㄩ噺`).then((res) => {
+    if (res.code == "200") {
+      const rawData = res.data.data;
+      if (Array.isArray(rawData) && rawData.length > 0) {
+        const formattedData = rawData.map(item => {
+          const formattedItem = {};
+          for (const key in item) {
+            if (typeof item[key] === 'string') {
+              //鍘婚櫎瀛楃涓插睘鎬у�煎紑澶村拰缁撳熬鐨勫弻寮曞彿
+              formattedItem[key] = item[key].replace(/^\"|\"$/g, '');
+            } else {
+              formattedItem[key] = item[key];
+            }
+          }
+          return formattedItem;
+        });
+        quicksetLeft.value=formattedData[0].leftEdge
+        quicksetTop.value=formattedData[0].upEdge
+        quicksetRight.value=formattedData[0].rightEdge
+        quicksetBottom.value=formattedData[0].downEdge
+        controlValue.value=formattedData[0].quickEdge
+        if(formattedData[0].autoFillEdge=="true"){
+          check.value=true
+        }else{
+          check.value=false
+        }
+        minAutoLenght.value=formattedData[0].minAutoLenght
+
+      }
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  });
+};
+function setupComponent() {
+  // 鍚勪釜杈撳叆妗嗙粦瀹氱殑鍊硷紝鍒濆鍖栦负0
+  const quicksetTop = ref('0');
+  const quicksetRight = ref('0');
+  const quicksetBottom = ref('0');
+  const quicksetLeft = ref('0');
+  // 鐢ㄤ簬鎺у埗鐨勮緭鍏ュ�硷紝鍒濆鍖栦负1
+  const controlValue = ref('1');
+  const minAutoLenght = ref('0');
+
+  const syncValues = () => {
+    // 灏嗘帶鍒跺�艰祴缁欏叾浠栧洓涓粍浠�
+    quicksetTop.value = controlValue.value;
+    quicksetRight.value = controlValue.value;
+    quicksetBottom.value = controlValue.value;
+    quicksetLeft.value = controlValue.value;
+  };
+  return {
+    quicksetTop,
+    quicksetRight,
+    quicksetBottom,
+    quicksetLeft,
+    controlValue,
+    minAutoLenght,
+    syncValues
+  };
+}
+const {
+  quicksetTop,
+  quicksetRight,
+  quicksetBottom,
+  quicksetLeft,
+  controlValue,
+  minAutoLenght,
+  syncValues
+} = setupComponent();
+
+const check = ref()
+
+const emit = defineEmits(['set-amount']);
+const props = defineProps({
+  closeDialog: Function
+});
+
+const setAmount = () => {
+  let json = "{"
+  json+='"left_edge":"'+quicksetLeft.value+'",'
+  json+='"up_edge":"'+quicksetTop.value+'",'
+  json+='"right_edge":"'+quicksetRight.value+'",'
+  json+='"down_edge":"'+quicksetBottom.value+'",'
+  json+='"auto_fill_edge":"'+check.value+'",'
+  json+='"quick_edge":"'+controlValue.value+'",'
+  json+='"min_auto_lenght":"'+minAutoLenght.value+'"'
+  json+="}"
+
+  let configuration={
+    json:json,
+  }
+
+  request.post(`/glassOptimize/saveConfiguration/纾ㄩ噺`,configuration).then((res) => {
+    if(res.code==200 && res.data===true){
+      const amountData = {
+        quicksetTop: quicksetTop.value,
+        quicksetRight: quicksetRight.value,
+        quicksetBottom: quicksetBottom.value,
+        quicksetLeft: quicksetLeft.value,
+        controlValue:controlValue.value,
+        minAutoLenght:minAutoLenght.value,
+      };
+      emit('set-amount', amountData);
+      props.closeDialog(2);
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  });
+};
+
+</script>
+
+<template>
+  <div id="box1">
+     <div style="display: flex; justify-content: center">
+      <div class="square-container">
+        <div class="square" @click="syncValues"></div>
+        <el-input-number v-model="quicksetTop" class="top" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetRight" class="right" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetBottom" class="bottom" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetLeft" class="left" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+      </div>
+      <el-button type="primary" style="float: right; margin: -75px 0;" @click="setAmount">搴旂敤</el-button>
+    </div>
+
+    <div style="margin-top: 20px">
+      <span>榧犳爣鐐瑰嚮钃濊壊鍥惧舰鍖哄煙鍙揩閫熻缃(閲�</span>
+      <el-input-number v-model="controlValue" class="quickset" placeholder="0"
+                       controls-position="right" :step="0.1" :min="0"></el-input-number>
+      <br>
+      <div style="margin-top: 30px">
+      <span>鎴愬搧杈归暱澶т簬绛変簬澶氬皯鏃惰嚜鍔ㄥ~鍏�(鍗曚綅: mm)</span>
+      <el-checkbox v-model="check" style="margin: 5px 0 0 12px;"/>
+      <vxe-input style="width: 100px; height: 40px; margin-left: 5px" v-model="minAutoLenght" placeholder=""/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+#box1 {
+  width: 100%;
+  height: 100%;
+  padding: 10px;
+  border-radius: 5px;
+}
+
+.square-container {
+  width: 300px;
+  height: 250px;
+  display: flex;
+  position: relative;
+  justify-content: center;
+  align-items: center;
+}
+
+.square {
+  width: 100px;
+  height: 100px;
+  background-color: #5cadfe;
+}
+
+.top,
+.right,
+.bottom,
+.left {
+  width: 100px;
+  height: 50px;
+  position: absolute;
+}
+
+.top {
+  top: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.right {
+  top: 50%;
+  right: -5px;
+  transform: translateY(-50%);
+}
+
+.bottom {
+  bottom: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.left {
+  top: 50%;
+  left: -5px;
+  transform: translateY(-50%);
+}
+
+.quickset {
+  margin-left: 60px;
+  width: 100px;
+  height: 40px;
+}
+</style>
\ No newline at end of file
diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetTrimming.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetTrimming.vue
new file mode 100644
index 0000000..f12748d
--- /dev/null
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/page/SetTrimming.vue
@@ -0,0 +1,205 @@
+<script setup>
+import {onMounted, ref} from "vue";
+import {defineEmits} from 'vue';
+import request from "@/utils/request";
+import {ElMessage} from "element-plus";
+
+
+onMounted(async() => {
+  await firstLoading()
+})
+
+const firstLoading = async() => {
+  request.post(`/glassOptimize/getConfiguration/淇竟`).then((res) => {
+    if (res.code == "200") {
+      const rawData = res.data.data;
+      if (Array.isArray(rawData) && rawData.length > 0) {
+        const formattedData = rawData.map(item => {
+          const formattedItem = {};
+          for (const key in item) {
+            if (typeof item[key] === 'string') {
+              //鍘婚櫎瀛楃涓插睘鎬у�煎紑澶村拰缁撳熬鐨勫弻寮曞彿
+              formattedItem[key] = item[key].replace(/^\"|\"$/g, '');
+            } else {
+              formattedItem[key] = item[key];
+            }
+          }
+          return formattedItem;
+        });
+        quicksetLeft.value=formattedData[0].leftTrim
+        quicksetTop.value=formattedData[0].upTrim
+        quicksetRight.value=formattedData[0].rightTrim
+        quicksetBottom.value=formattedData[0].downTrim
+
+      }
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  });
+};
+
+function setupComponent() {
+  // 鍚勪釜杈撳叆妗嗙粦瀹氱殑鍊硷紝鍒濆鍖栦负0
+  const quicksetTop = ref('0');
+  const quicksetRight = ref('0');
+  const quicksetBottom = ref('0');
+  const quicksetLeft = ref('0');
+  // 鐢ㄤ簬鎺у埗鐨勮緭鍏ュ�硷紝鍒濆鍖栦负1
+  const controlValue = ref('1');
+
+  const syncValues = () => {
+    // 灏嗘帶鍒跺�艰祴缁欏叾浠栧洓涓粍浠�
+    quicksetTop.value = controlValue.value;
+    quicksetRight.value = controlValue.value;
+    quicksetBottom.value = controlValue.value;
+    quicksetLeft.value = controlValue.value;
+  };
+  return {
+    quicksetTop,
+    quicksetRight,
+    quicksetBottom,
+    quicksetLeft,
+    controlValue,
+    syncValues
+  };
+}
+const {
+  quicksetTop,
+  quicksetRight,
+  quicksetBottom,
+  quicksetLeft,
+  controlValue,
+  syncValues
+} = setupComponent();
+
+const check = ref(true)
+
+
+const emit = defineEmits(['send-data-event',]);
+const props = defineProps({
+  closeDialog: Function
+});
+
+const setTrimming = () => {
+  let json = "{"
+  json+='"left_trim":"'+quicksetLeft.value+'",'
+  json+='"up_trim":"'+quicksetTop.value+'",'
+  json+='"right_trim":"'+quicksetRight.value+'",'
+  json+='"down_trim":"'+quicksetBottom.value+'",'
+  json+='"auto_fill_trim":"'+true+'",'
+  json+='"quick_trim":"'+15+'"'
+  json+="}"
+
+  let configuration={
+      json:json,
+    }
+
+  request.post(`/glassOptimize/saveConfiguration/淇竟`,configuration).then((res) => {
+    if(res.code==200 && res.data===true){
+      const dataToSend = {
+        quicksetTop: quicksetTop.value,
+        quicksetRight: quicksetRight.value,
+        quicksetBottom: quicksetBottom.value,
+        quicksetLeft: quicksetLeft.value
+      };
+      emit('send-data-event', dataToSend);
+      props.closeDialog(3);
+    } else {
+      ElMessage.warning(res.msg)
+    }
+  });
+
+};
+
+</script>
+
+<template>
+  <div id="box1">
+    <div style="display: flex; margin-top: -20px; justify-content: center">
+      <div class="square-container">
+        <div class="square" @click="syncValues"></div>
+        <el-input-number v-model="quicksetTop" class="top" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetRight" class="right" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetBottom" class="bottom" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+        <el-input-number v-model="quicksetLeft" class="left" placeholder="0"
+                         controls-position="right" :step="0.1" :min="0"></el-input-number>
+      </div>
+      <el-button type="primary" style="float: right; margin: -55px 0;" @click="setTrimming">搴旂敤</el-button>
+    </div>
+
+    <div>
+      <span>榧犳爣鐐瑰嚮钃濊壊鍥惧舰鍖哄煙鍙揩閫熻缃慨杈归噺</span>
+      <el-input-number v-model="controlValue" class="quickset" placeholder="0"
+                       controls-position="right" :step="0.1" :min="0"></el-input-number>
+      <br>
+      <span>鏌ヨ鍘熺墖鏃惰嚜鍔ㄥ~鍏�(鍗曚綅: mm)</span>
+      <el-checkbox v-model="check" style="margin: 20px 0 0 117px;"/>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+#box1 {
+  width: 100%;
+  height: 100%;
+  padding: 10px;
+  border-radius: 5px;
+}
+
+.square-container {
+  width: 300px;
+  height: 300px;
+  display: flex;
+  position: relative;
+  justify-content: center;
+  align-items: center;
+}
+
+.square {
+  width: 100px;
+  height: 100px;
+  background-color: #5cadfe;
+}
+
+.top,
+.right,
+.bottom,
+.left {
+  width: 100px;
+  height: 50px;
+  position: absolute;
+}
+
+.top {
+  top: 45px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.right {
+  top: 50%;
+  right: -5px;
+  transform: translateY(-50%);
+}
+
+.bottom {
+  bottom: 45px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.left {
+  top: 50%;
+  left: -5px;
+  transform: translateY(-50%);
+}
+
+.quickset {
+  margin-left: 60px;
+  width: 100px;
+  height: 45px;
+}
+</style>
\ No newline at end of file
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 226d24a..467aeb9 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
@@ -289,4 +289,75 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+    //妯℃嫙璁$畻宸ョ▼鍙锋煡璇㈢涓夋柟
+    @ApiOperation("妯℃嫙璁$畻宸ョ▼鍙锋煡璇�")
+    @PostMapping  ("/selectProjectComputeMpThirdParty/{projectNumber}")
+    public Result selectProjectComputeMpThirdParty( @PathVariable String projectNumber){
+        return Result.seccess(glassOptimizeService.selectProjectComputeMpThirdParty(projectNumber));
+    }
+
+    //妯℃嫙璁$畻娴佺▼鍗¤鎯呯涓夋柟
+    @ApiOperation("妯℃嫙璁$畻娴佺▼鍗¤鎯�")
+    @PostMapping  ("/selectComputeDetailThirdParty/{processId}/{technologyNumber}")
+    public Result selectComputeDetailThirdParty(
+            @PathVariable String processId, @PathVariable Integer technologyNumber){
+        return Result.seccess(glassOptimizeService.selectComputeDetailThirdParty(processId,technologyNumber));
+    }
+
+    @ApiOperation("妯℃嫙璁$畻淇濆瓨")
+    @PostMapping("/simulationSaveThirdParty")
+    public Result simulationSaveThirdParty(@RequestBody Map<String, Object> object) {
+        try {
+            return Result.seccess(glassOptimizeService.simulationSaveThirdParty(object));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error();
+        }
+    }
+
+    //鍒犻櫎宸ョ▼
+    @ApiOperation("宸ョ▼绠$悊鍒犻櫎鎺ュ彛")
+    @PostMapping("/deleteProjectThirdParty/{projectNumber}")
+    public Result deleteProjectThirdParty(
+            @PathVariable String projectNumber){
+        return Result.seccess(glassOptimizeService.deleteProjectThirdParty(projectNumber));
+    }
+
+    @ApiOperation("宸ョ▼淇℃伅鎺ュ彛")
+    @PostMapping  ("/projectInfoThirdParty/{projectNo}")
+    public Result projectInfoThirdParty(
+            @PathVariable String projectNo){
+        return Result.seccess(glassOptimizeService.projectInfoThirdParty(projectNo));
+    }
+
+    //搴撳瓨淇℃伅
+    @ApiOperation("搴撳瓨淇℃伅鎺ュ彛")
+    @GetMapping  ("/materialStoreSvThirdParty/{projectNumber}")
+    public Result materialStoreSvThirdParty(@PathVariable  String projectNumber ){
+        return Result.seccess(glassOptimizeService.materialStoreSvThirdParty(projectNumber));
+    }
+
+    //宸ョ▼淇℃伅娴佺▼鍗�
+    @ApiOperation("宸ョ▼淇℃伅娴佺▼鍗℃帴鍙�")
+    @PostMapping  ("/getProcessCardMpThirdParty/{projectNo}")
+    public Result getProcessCardMpThirdParty(
+            @PathVariable String projectNo){
+        return Result.seccess(glassOptimizeService.getProcessCardMpThirdParty(projectNo));
+    }
+
+
+
+
+
+
 }
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeDetail.java b/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeDetail.java
new file mode 100644
index 0000000..94f9aba
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeDetail.java
@@ -0,0 +1,29 @@
+package com.example.erp.entity.pp;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+@TableName("pp.`optimize_detail`")
+public class OptimizeDetail {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String projectNo;
+    private String processId;
+    private Integer total_layer;
+    private Integer layer;
+    private Integer orderSort;
+    private Integer stock_id;
+    private Integer stock_number;
+    private String glass_id;
+    private Double pWidth;
+    private Double pHeight;
+    private Integer heatLayoutId;
+    private Integer heatLayoutSort;
+
+
+}
diff --git a/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeHeatDetail.java b/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeHeatDetail.java
new file mode 100644
index 0000000..65cb714
--- /dev/null
+++ b/north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeHeatDetail.java
@@ -0,0 +1,28 @@
+package com.example.erp.entity.pp;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+@TableName("pp.`optimize_heat_detail`")
+public class OptimizeHeatDetail {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String projectNo;
+    private String processId;
+    private Integer patchState;
+    private Integer layer;
+    private Integer orderSort;
+    private Integer layoutId;
+    private Integer sort;
+    private Integer glass_id;
+    private Double width;
+    private Double height;
+    private LocalDate createTime;
+
+
+}
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 b997236..3b7e96b 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
@@ -1,10 +1,7 @@
 package com.example.erp.mapper.pp;
 
 
-import com.example.erp.entity.pp.FlowCard;
-import com.example.erp.entity.pp.OptimizeProjectMange;
-import com.example.erp.entity.pp.OptimizeUse;
-import com.example.erp.entity.pp.PatchLog;
+import com.example.erp.entity.pp.*;
 import com.example.erp.entity.sd.OrderGlassDetail;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -67,6 +64,10 @@
 
     int deleteOptimizeDetail(String projectNumber);
 
+    List<OptimizeHeatDetail> selectOptimizeHeatDetail(String projectNumber);
+
+    OptimizeDetail selectOptimizeDetailById(String projectNumber,String processId,Integer orderSort,Integer layer);
+
     //妯℃嫙璁$畻宸ョ▼鍙锋煡璇�
     List<Map<String, Object>> selectProjectComputeMp(@Param("projectNo")String projectNumber);
 
@@ -93,6 +94,8 @@
     List<Map<String, Object>> selectOptimizeResult(String processId);
     //浼樺寲缁撴灉璋冩暣
     void updateOptimizeResult(String jsonString,String processId);
+
+    void updateOptimizeDetail(Long id,Integer layoutId,Integer sort);
 
     List<Map<String, Object>> getProcessCardDetailmMp(String processId, Integer technologyNumber);
 
@@ -125,4 +128,23 @@
     List<Map<String, Object>> getEdgeTrimming();
 
     Boolean updateOptimizeConfig(String json,Integer type);
+
+
+
+
+    //妯℃嫙璁$畻宸ョ▼鍙锋煡璇�
+    List<Map<String, Object>> selectProjectComputeMpThirdParty(@Param("projectNo")String projectNumber);
+
+    //妯℃嫙璁$畻娴佺▼鍗¤鎯�
+    List<Map<String, Object>> selectComputeDetailMpThirdParty(String processId,Integer technologyNumber);
+
+    int deleteOptimizeDetailThirdParty(String projectNumber);
+
+    List<Map<String, Object>> firstOptimizationThirdParty(String projectNo);
+
+    List<Map<String, Object>> analogComputationOptimizationThirdParty(String projectNo);
+
+    //宸ョ▼淇℃伅娴佺▼鍗�
+    List<Map<String, Object>> getProcessCardMpThirdParty(String projectNo);
+
 }
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 52a2b9e..621c55d 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
@@ -5,9 +5,9 @@
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.example.erp.common.RabbitMQUtil;
-import com.example.erp.entity.pp.FlowCard;
-import com.example.erp.entity.pp.OptimizeProjectMange;
-import com.example.erp.entity.pp.PatchLog;
+import com.example.erp.entity.pp.*;
+import com.example.erp.entity.sd.Delivery;
+import com.example.erp.entity.sd.OrderDetail;
 import com.example.erp.entity.userInfo.Log;
 import com.example.erp.entity.userInfo.SysError;
 import com.example.erp.mapper.pp.GlassOptimizeMapper;
@@ -71,6 +71,9 @@
 //妯℃嫙璁$畻淇濆瓨
     public Boolean addSimulation(Map<String, Object> object) {
         try {
+            Map<String, Object> objectMap = (Map<String, Object>) object.get("inputValues");
+            String projectNo = objectMap.get("project_no").toString();
+            Map<String, Object> optimizeProjectMap = glassOptimizeMapper.selectProjectCount(projectNo);
             glassOptimizeMapper.addSimulation(object);
             glassOptimizeMapper.addratioResult(object);
             glassOptimizeMapper.addratioProjectResult(object);
@@ -610,4 +613,101 @@
     }
 
 
+
+
+
+
+
+
+
+
+    //妯℃嫙璁$畻宸ョ▼鍙锋煡璇�
+    public Map<String, Object>selectProjectComputeMpThirdParty(String projectNumber) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", glassOptimizeMapper.selectProjectComputeMpThirdParty(projectNumber));
+        return map;
+    }
+
+    //妯℃嫙璁$畻娴佺▼鍗¤鎯�
+    public Map<String, Object>selectComputeDetailThirdParty(String processId,Integer technologyNumber) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", glassOptimizeMapper.selectComputeDetailMpThirdParty(processId,technologyNumber));
+        return map;
+    }
+
+    public Boolean simulationSaveThirdParty(Map<String, Object> object) {
+        try {
+            Map<String, Object> objectMap = (Map<String, Object>) object.get("inputValues");
+            String projectNo = objectMap.get("project_no").toString();
+            Map<String, Object> optimizeProjectMap = glassOptimizeMapper.selectProjectCount(projectNo);
+            glassOptimizeMapper.addSimulation(object);
+            glassOptimizeMapper.addratioResult(object);
+            glassOptimizeMapper.addratioProjectResult(object);
+
+            List<OptimizeHeatDetail> optimizeHeatDetail = glassOptimizeMapper.selectOptimizeHeatDetail(projectNo);
+            for (OptimizeHeatDetail projectdetail:optimizeHeatDetail){
+                OptimizeDetail optimizeDetail=glassOptimizeMapper.selectOptimizeDetailById(projectNo,projectdetail.getProcessId(),
+                        projectdetail.getOrderSort(),projectdetail.getLayer());
+                glassOptimizeMapper.updateOptimizeDetail(optimizeDetail.getId(),projectdetail.getLayoutId(),projectdetail.getSort());
+            }
+
+
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    //鍒犻櫎宸ョ▼
+    public boolean deleteProjectThirdParty(String projectNumber) {
+        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber);
+        if(stringObjectMap.get("state").equals(2)){
+            glassOptimizeMapper.deleteOptimizeDetailThirdParty(projectNumber);
+            glassOptimizeMapper.deleteOptimizeDetail(projectNumber);
+        }else if(stringObjectMap.get("state").equals(10)){
+            glassOptimizeMapper.deleteOptimizeDetailThirdParty(projectNumber);
+            glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
+            glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber);
+        }
+        glassOptimizeMapper.deleteProjectMp(projectNumber);
+
+        return true;
+    }
+
+    //宸ョ▼淇℃伅
+    public Map<String, Object> projectInfoThirdParty(String projectNo) {
+        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNo);
+        Map<String, Object> map = new HashMap<>();
+        if(stringObjectMap.get("state").equals(2)){
+            map.put("data", glassOptimizeMapper.firstOptimizationThirdParty(projectNo));
+            map.put("grindingTrimming", null);
+        }else{
+            map.put("data", glassOptimizeMapper.firstOptimizationThirdParty(projectNo));
+            map.put("grindingTrimming", null);
+        }
+        return map;
+    }
+
+    //搴撳瓨淇℃伅
+    public Map<String, Object> materialStoreSvThirdParty(String projectNumber) {
+        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber);
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", glassOptimizeMapper.materialStoreOptimizeUse(projectNumber));
+        map.put("edgeTrimming", null);
+        map.put("state", Integer.parseInt(stringObjectMap.get("state").toString()));
+        return map;
+    }
+
+    //宸ョ▼淇℃伅娴佺▼鍗�
+    public Map<String, Object> getProcessCardMpThirdParty(String projectNo) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("data", glassOptimizeMapper.getProcessCardMpThirdParty(projectNo));
+        return map;
+    }
+
+
+
+
+
 }
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 020e27f..f6f616d 100644
--- a/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
+++ b/north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
@@ -223,7 +223,7 @@
             fc.process_id,
             fc.order_number,
             fc.quantity,
-            CONCAT(fc.technology_number, '/', COUNT(fc.technology_number)) AS layer,
+            CONCAT(fc.technology_number, '/', COUNT(fc.layers_number)) AS layer,
             so.project,
             CONCAT(sd.child_width, ' 脳 ', sd.child_height) AS sizes
         FROM
@@ -587,6 +587,17 @@
         where project_no = #{projectNumber}
     </delete>
 
+    <select id="selectOptimizeDetailById">
+        select * from pp.optimize_detail
+        where project_no = #{projectNumber} and process_id= #{processId} and layer= #{layer} and order_sort= #{orderSort}
+          and heat_layout_id is null limit 0,1;
+    </select>
+
+    <select id="selectOptimizeHeatDetail">
+        select * from pp.optimize_heat_detail
+        where project_no = #{projectNumber}
+    </select>
+
     <select id="getProjectListMp">
         SELECT
             p.id,
@@ -847,7 +858,7 @@
 
 
     <insert id="addSimulation" parameterType="map">
-        <foreach collection="projectdetail.data[0].glass_details" item="glass">
+        <foreach collection="projectdetail" item="glass">
             INSERT INTO pp.optimize_heat_detail (
             project_no,
             process_id,
@@ -895,7 +906,7 @@
     </insert>
     <!--妯℃嫙璁$畻缁撴灉淇濆瓨-->
     <insert id="addratioResult" parameterType="map">
-        <foreach collection="projectdetail.data[0].ratioResult" item="glass">
+        <foreach collection="ratioResult" item="glass">
             INSERT INTO pp.optimize_heat_layout (
             project_no,
             layout_id,
@@ -925,6 +936,8 @@
         UPDATE pp.optimize_project
         SET
             state = 10,
+            furnaces_qty=#{resultSum[0]},
+            load_rate=#{resultSum[1]},
             chaos_pct = #{inputValues.chaos_pct},
             max_load_pct = #{inputValues.max_load_pct},
             max_area=#{inputValues.max_area},
@@ -932,8 +945,7 @@
             load_width=#{inputValues.load_width},
             load_length=#{inputValues.load_length},
             x_space=#{inputValues.x_space},
-            y_space=#{inputValues.y_space},
-            load_rate=#{inputValues.load_rate}
+            y_space=#{inputValues.y_space}
         WHERE
             project_no = #{inputValues.project_no}
 
@@ -948,6 +960,12 @@
         update pp.optimize_project_file as u
         set u.content = #{jsonString}
         where  u.project_no=#{processId} and type='浼樺寲缁撴灉'
+    </update>
+
+    <update id="updateOptimizeDetail">
+        update pp.optimize_detail
+        set heat_layout_id=#{layoutId},heat_layout_sort=#{sort},glass_id=concat(process_id,'|',#{layoutId},'|',#{sort})
+        where id=#{id};
     </update>
 
 
@@ -1035,4 +1053,116 @@
               c.process_id,
               c.order_number
     </select>
+
+
+
+
+
+
+
+    <!--妯℃嫙璁$畻鏌ヨ娴佺▼鍗$涓夋柟-->
+    <select id="selectProjectComputeMpThirdParty">
+        select
+            process_id as processId,
+            layer as technologyNumber,
+            total_layer as total_layers,
+            filmsid as TotalNumber,
+            sum(glass_total) as total_num,
+            product_name as glass_child,
+            0 as tempering,
+            0 as allow_rotate,
+            0 as curtain_wall,
+            0 as priority_level,
+            1 as is_must
+        from pp.other_flow_card where project_no = #{projectNo} group by process_id,layer
+    </select>
+
+    <!--妯℃嫙璁$畻娴佺▼鍗¤鎯呯涓夋柟-->
+    <select id="selectComputeDetailMpThirdParty">
+        select
+            process_id as process_id,
+            width as width,
+            height as height,
+            width as maxwidth,
+            height as maxheight,
+            order_number as order_number,
+            glass_total as quantity,
+            layer as technology_number,
+            0 as patch_state
+        from pp.other_flow_card where process_id = #{processId} and layer=#{technologyNumber}
+    </select>
+
+    <!--绗竴娆′紭鍖栨煡璇�-->
+    <select id="firstOptimizationThirdParty">
+        select
+            project_no,
+            concat( process_id, '-', layer ) AS process_id,
+            width,
+            height,
+            layer,
+            glass_total as quantity,
+            product_name,
+            order_number
+        from pp.other_flow_card where project_no = #{projectNo}
+    </select>
+
+    <select id="analogComputationOptimizationThirdParty">
+        SELECT
+            h.project_no,
+            h.layout_id,
+            h.width AS width,
+            h.height AS height,
+            count( 1 ) AS quantity,
+            concat( h.process_id, '-', h.layer ) AS 'process_id',
+            h.layer,
+            c.order_number
+        from
+            pp.`optimize_heat_detail` h
+                LEFT JOIN pp.other_flow_card c ON h.process_id = c.process_id
+                AND h.layer = c.technology_number
+                AND h.order_sort = c.order_number
+        WHERE
+            h.project_no = #{projectNo}
+        GROUP BY
+            h.project_no,
+            h.layout_id,
+            h.width,
+            h.height,
+            h.process_id,
+            h.layer,
+            c.quantity,
+            c.order_number
+        ORDER BY
+            LENGTH( h.layout_id ),
+            h.layout_id;
+    </select>
+
+    <!--宸ョ▼淇℃伅娴佺▼鍗�-->
+    <select id="getProcessCardMpThirdParty">
+        SELECT
+            fc.process_id,
+            fc.order_number,
+            fc.glass_total as quantity,
+            CONCAT(fc.layer, '/', COUNT(fc.total_layer)) AS layer,
+            CONCAT(fc.width, ' 脳 ', fc.height) AS sizes
+        FROM
+            pp.other_flow_card AS fc
+        WHERE
+            fc.project_no = #{projectNo}
+        GROUP BY
+            fc.layer,
+            fc.order_number
+    </select>
+
+    <delete id="deleteOptimizeDetailThirdParty">
+        delete from pp.other_flow_card
+        where project_no = #{projectNumber}
+    </delete>
+
+
+
+
+
+
+
 </mapper>
\ No newline at end of file

--
Gitblit v1.8.0