From f7a2fcdda7f1120498c5c5f75c5a99955fc54b43 Mon Sep 17 00:00:00 2001
From: 廖井涛 <2265517004@qq.com>
Date: 星期二, 16 十二月 2025 16:54:09 +0800
Subject: [PATCH] Merge branch 'master' of http://10.153.19.25:10105/r/ERP_override

---
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue |  411 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 340 insertions(+), 71 deletions(-)

diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
index 5aa0ca4..6b19094 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
@@ -1,45 +1,54 @@
 <template>
   <div>
-    <el-button id="button" type="primary" @click="printReports" style="background: #409eff; position: fixed; top: 90px; right: 90px; padding: 20px; color: white; border: none; cursor: pointer; margin-right: 10px;">
-      棰勮
-    </el-button>
-    <el-button id="button" type="primary" @click="handlePrint" style="position: fixed; top: 90px; right: 20px; padding: 20px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;">
-      鎵撳嵃
+<!--    <el-button id="button" type="primary" @click="printReports" style="position: fixed; top: 90px; right: 20px; padding: 20px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;">-->
+<!--      鎵撳嵃-->
+<!--    </el-button>-->
+    <el-button
+        id="button"
+        type="primary"
+        @click="previewReport"
+        :loading="loading"      style="position: fixed; top: 90px; right: 40px; padding: 20px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;"
+        :disabled="loading">
+      {{ loading ? '鐢熸垚涓�...' : '棰勮' }}
     </el-button>
 
     <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 20px;">
       <span>宸ョ▼缂栧彿锛�</span>
       <el-input readonly placeholder="" style="width: 150px" v-model="processId"></el-input>&nbsp;
-      <el-checkbox v-model="config.printLayouts">
-        鎵撳嵃鐗堝浘
-      </el-checkbox>
-      <el-checkbox v-model="config.printReport">
-        鎵撳嵃鎶ュ憡
-      </el-checkbox>
-      <div style="margin-right: 30px;"></div>
-      <span>甯冨眬閫夋嫨锛�</span>
-      <el-select v-model="config.columnTypes"  style="width: 120px;">
-        <el-option v-for="type in columnTypes" :key="type" :value="type" />
-      </el-select>
-      <el-select v-model="config.rowTypes"  style="width: 120px;">
-        <el-option v-for="type in rowTypes" :key="type" :value="type" />
-      </el-select>
     </div>
-    <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 20px;">
-      <span>鏄剧ず灏忕墖淇℃伅锛�</span>
-      <el-select v-model="config.glassInfo"  style="width: 120px;">
-        <el-option v-for="type in glassInfo" :key="type" :value="type" />
-      </el-select>
-      <span>鏄剧ず鍒囧壊淇℃伅锛�</span>
-      <el-select v-model="config.cutInfo"  style="width: 120px;">
-        <el-option v-for="type in cutInfo" :key="type" :value="type" />
-      </el-select>
+
+    <div v-if="pdfUrl || pdfLoading" style="margin-top: 20px;">
+      <!-- PDF鍔犺浇鏃舵樉绀虹編鍖栧悗鐨勫姞杞藉姩鐢� -->
+      <div v-if="pdfLoading" style="display: flex; justify-content: center; align-items: center; height: 800px; border: 1px solid #ddd; background-color: #f5f5f5;">
+        <div style="text-align: center;">
+          <div class="loading-animation">
+            <div class="dot-flashing"></div>
+          </div>
+          <p style="margin-top: 20px; font-size: 18px; color: #666;">PDF鏂囨。鍔犺浇涓�...</p>
+          <p style="font-size: 14px; color: #999; margin-top: 10px;">姝e湪涓烘偍鍑嗗棰勮鍐呭</p>
+        </div>
+      </div>
+      <!-- PDF鍔犺浇瀹屾垚鏃舵樉绀篜DF -->
+      <iframe
+          v-else
+          :src="pdfUrl"          style="width: 100%; height: 780px; border: 1px solid #ddd;"
+          title="PDF棰勮">
+      </iframe>
+    </div>
+
+    <div v-else style="margin-top: 20px;">
+      <div style="display: flex; justify-content: center; align-items: center; height: 780px; border: 1px solid #ddd; background-color: white;">
+        <div style="text-align: center; color: #999;">
+          <p style="font-size: 20px; margin-bottom: 10px;">浼樺寲鎶ュ憡棰勮鍖�</p>
+          <p style="font-size: 14px;">鐐瑰嚮涓婃柟"棰勮"鎸夐挳鐢熸垚骞舵煡鐪嬩紭鍖栨姤鍛�</p>
+        </div>
+      </div>
     </div>
 
     <div ref="printContainer" style="position: relative;">
-      <RectRenderer 
+      <RectRenderer
         ref="rectRenderer"
-        :layoutData="layoutData" 
+        :layoutData="layoutData"
         :gw="currentGw"
         :gh="currentGh"
         :printLayout="printLayout"
@@ -62,6 +71,9 @@
 import request from "@/utils/request";
 import {ElMessage, ElMessageBox} from "element-plus";
 import requestOptimize from "@/utils/requestOptimize";
+import useUserInfoStore from "@/stores/userInfo";
+
+const userStore = useUserInfoStore();
 
 const props = defineProps({
   project : null,
@@ -74,17 +86,24 @@
 const layoutData = ref();
 const optimizeUse = ref();
 const reportData = ref();
-const layoutSet = ref();
 const materialList = ref();
 const productList = ref();
 const dataLoaded = ref(false);
 const materialDetails = ref();
 const injectedProjectNo = inject('projectNo', null);
 const state = ref();
-const columnTypes = ['涓�鍒�', '涓ゅ垪', '涓夊垪', '鍥涘垪']
-const rowTypes = ['涓�琛�', '涓よ']
-const glassInfo = ['涓嶆樉绀�', '鏄剧ず鍦ㄥ彸渚�', '鏄剧ず鍦ㄤ笅渚�']
-const cutInfo = ['涓嶆樉绀�', '鏄剧ず']
+const filePath = ref('');
+const loading = ref(false);
+const pdfLoading = ref(false);
+const printLayouts = ref();
+const printReport = ref();
+const layoutRows = ref();
+const layoutColumns = ref();
+const glassInfoShow = ref();
+const cutInfoShow = ref();
+const username = userStore.user.userName;
+
+const pdfUrl = ref('');
 
 // 瀹氫箟涓嶅悓甯冨眬瀵瑰簲鐨勫昂瀵�
 const layoutDimensions = {
@@ -141,6 +160,30 @@
       });
 };
 
+const fetchSettings = async (username) => {
+  try {
+    const response = await request.post(`/glassOptimize/selectOptimizeParms/${username}`);
+    if (response.code == 200) {
+      if (!response.data) {
+        console.error('鍝嶅簲鏁版嵁涓虹┖');
+        return;
+      }
+      const parsedData = JSON.parse(response.data);
+      console.log('璁剧疆鍐呭:', parsedData);
+      printLayouts.value = parsedData.server.printLayouts;
+      printReport.value = parsedData.server.printReport;
+      layoutRows.value = parsedData.server.layoutRows;
+      layoutColumns.value = parsedData.server.layoutColumns;
+      glassInfoShow.value = parsedData.server.glassInfoShow;
+      cutInfoShow.value = parsedData.server.cutInfoShow;
+    } else {
+      console.error('璇锋眰澶辫触锛岀姸鎬佺爜:', response.code);
+    }
+  } catch (error) {
+    console.error('璇锋眰鍙戠敓閿欒:', error);
+  }
+};
+
 
 const selectMaterialData= () => {
   request.post(`/glassOptimize/materialInfo/${processId.value}`)
@@ -180,40 +223,13 @@
       });
 };
 
-const printReports = async() => {
+const generateReport = async() => {
   try {
     // 纭繚鏈夋暟鎹彲浠ユ彁浜�
     if (!processId) {
       ElMessage.warning('娌℃湁鍙墦鍗扮殑鏁版嵁');
       return;
     }
-
-    // 鏄犲皠 rowTypes 鍒� layoutRows
-    const layoutRowsMap = {
-      '涓�琛�': 1,
-      '涓よ': 2
-    };
-
-    // 鏄犲皠 columnTypes 鍒� layoutColumns
-    const layoutColumnsMap = {
-      '涓�鍒�': 1,
-      '涓ゅ垪': 2,
-      '涓夊垪': 3,
-      '鍥涘垪': 4
-    };
-
-    // 鏄犲皠 glassInfo 鍒� glassInfoShow
-    const glassInfoMap = {
-      '涓嶆樉绀�': 0,
-      '鏄剧ず鍦ㄥ彸渚�': 1,
-      '鏄剧ず鍦ㄤ笅渚�': 2
-    };
-
-    // 鏄犲皠 cutInfo 鍒� cutInfoShow
-    const cutInfoMap = {
-      '涓嶆樉绀�': 0,
-      '鏄剧ず': 1
-    };
 
     const response = await requestOptimize.post('/api/reports', {
       fileName: processId.value,
@@ -222,8 +238,8 @@
       glassThickness : optimizeUse.value.thickness,
       glassType : optimizeUse.value.model,
       quantity : String(optimizeUse.value.processingQuantity),
-      printLayouts : config.printLayouts ? '1' : '0',
-      printReport : config.printReport ? '1' : '0',
+      printLayouts : printLayouts.value || '0',
+      printReport : printReport.value || '0',
       layouts : layoutData.value,
       reportData:{
         rectangleQuantity: reportData.value.rectangleQuantity,
@@ -236,10 +252,10 @@
         productList: productList.value,
       },
       layoutSet: {
-        layoutRows: layoutRowsMap[config.rowTypes] || 1,
-        layoutColumns: layoutColumnsMap[config.columnTypes] || 1,
-        glassInfoShow: glassInfoMap[config.glassInfo] || 0,
-        cutInfoShow: cutInfoMap[config.cutInfo] || 0
+        layoutRows: parseInt(layoutRows.value) || 2,
+        layoutColumns: parseInt(layoutColumns.value) || 2,
+        glassInfoShow: parseInt(glassInfoShow.value) || 0,
+        cutInfoShow: parseInt(cutInfoShow.value) || 0
       }
 
     }, {
@@ -248,13 +264,211 @@
       }
     });
 
+    if (response.code == 200) {
+      ElMessage.success('淇濆瓨鎴愬姛');
+      filePath.value = response.data[0];
+      console.log('filePath:', filePath.value);
+    } else {
+      ElMessage.error('淇濆瓨澶辫触锛岃绋嶅悗鍐嶈瘯');
+    }
+
   } catch (error) {
     console.error('淇濆瓨澶辫触:', error);
     ElMessage.error('淇濆瓨澶辫触锛岃绋嶅悗鍐嶈瘯');
   }
 };
 
+const printReports = async () => {
+  try {
+    await generateReport();
+    if (!filePath.value) {
+      ElMessage.error('鏈敹鍒版湁鏁堢殑PDF鏂囦欢璺緞');
+      return;
+    }
+    const encodedFilePath = encodeURIComponent(filePath.value);
 
+    const response = await request.get('/glassOptimize/reports/pdf', {
+      params: { filePath: encodedFilePath },
+      responseType: 'blob',
+      headers: {
+        'Accept': 'application/pdf'
+      }
+    });
+
+    // 妫�鏌ュ搷搴旀暟鎹槸鍚﹀瓨鍦ㄤ笖鏈夋晥
+    if (!response) {
+      ElMessage.error('鏈兘鑾峰彇鍒癙DF鏁版嵁');
+      return;
+    }
+
+    const blob = new Blob([response], { type: 'application/pdf' });
+
+    // 妫�鏌� blob 鏄惁鏈夋晥
+    if (blob.size === 0) {
+      ElMessage.error('鎺ユ敹鍒扮┖鐨凱DF鏂囦欢');
+      return;
+    }
+
+    const url = URL.createObjectURL(blob);
+
+    // 鍒涘缓闅愯棌鐨� iframe
+    const iframe = document.createElement('iframe');
+    iframe.style.position = 'fixed';
+    iframe.style.left = '0';
+    iframe.style.top = '0';
+    iframe.style.width = '0';
+    iframe.style.height = '0';
+    iframe.style.border = 'none';
+    iframe.src = url;
+
+    // 鏍囪鏄惁宸茬粡娓呯悊杩囪祫婧�
+    let isCleanedUp = false;
+    // 娓呯悊璧勬簮鍑芥暟
+    const cleanup = () => {
+      if (isCleanedUp) return;
+      isCleanedUp = true;
+      URL.revokeObjectURL(url);
+      if (iframe.parentNode) {
+        iframe.parentNode.removeChild(iframe);
+      }
+    };
+
+    iframe.onload = () => {
+      setTimeout(() => {
+        try {
+          // 纭繚 iframe 鍐呭宸插姞杞藉畬鎴�
+          if (iframe.contentWindow) {
+            iframe.contentWindow.focus();
+
+            // 鐩戝惉鎵撳嵃浜嬩欢锛堟煇浜涙祻瑙堝櫒鏀寔锛�
+            const handleAfterPrint = () => {
+              window.removeEventListener('afterprint', handleAfterPrint);
+              // 寤惰繜娓呯悊锛岀‘淇濇墦鍗板畬鎴�
+              setTimeout(cleanup, 3000);
+            };
+
+            window.addEventListener('afterprint', handleAfterPrint);
+
+            // 鎵ц鎵撳嵃
+            iframe.contentWindow.print();
+            ElMessage.success('鎶ュ憡鐢熸垚鎴愬姛锛屽凡鍚姩鎵撳嵃...');
+
+            // 濡傛灉娴忚鍣ㄤ笉鏀寔 afterprint 浜嬩欢锛岃缃秴鏃舵竻鐞�
+            setTimeout(cleanup, 10000);
+          }
+        } catch (printError) {
+          console.error('鎵撳嵃杩囩▼涓嚭閿�:', printError);
+          // 濡傛灉绋嬪簭鍖栨墦鍗板け璐ワ紝鑷冲皯鎵撳紑 PDF 渚涚敤鎴锋墜鍔ㄦ墦鍗�
+          window.open(url, '_blank');
+          ElMessage.info('宸叉墦寮�PDF鏂囦欢锛岃鎵嬪姩鎵撳嵃');
+          cleanup();
+        }
+      }, 1000); // 缁欐洿澶氭椂闂寸‘淇漃DF瀹屽叏娓叉煋
+    };
+
+    iframe.onerror = () => {
+      console.error('PDF 鍔犺浇澶辫触');
+      ElMessage.error('PDF 鏂囦欢鍔犺浇澶辫触锛岃閲嶈瘯');
+      cleanup();
+    };
+
+    document.body.appendChild(iframe);
+
+  } catch (error) {
+    console.error('鎵撳嵃娴佺▼寮傚父:', error);
+
+    if (error.response) {
+      const status = error.response.status;
+      if (status === 400) {
+        ElMessage.error('鏂囦欢璺緞鏃犳晥鎴栦笉鏄疨DF');
+      } else if (status === 404) {
+        ElMessage.error('PDF 鏂囦欢涓嶅瓨鍦�');
+      } else {
+        ElMessage.error(`鏈嶅姟鍣ㄩ敊璇� (${status})锛岃绋嶅悗鍐嶈瘯`);
+      }
+    } else if (error.request) {
+      ElMessage.error('缃戠粶閿欒锛岃妫�鏌ヨ繛鎺�');
+    } else {
+      ElMessage.error('鎵撳嵃澶辫触锛岃绋嶅悗鍐嶈瘯');
+    }
+  }
+};
+
+
+
+const previewReport = async () => {
+  try {
+    loading.value = true;
+    ElMessage.info('姝e湪鐢熸垚鎶ュ憡锛岃绋嶅��...')
+    await generateReport();
+    if (!filePath.value) {
+      ElMessage.error('鏈敹鍒版湁鏁堢殑PDF鏂囦欢璺緞');
+      loading.value = false;
+      return;
+    }
+    const encodedFilePath = encodeURIComponent(filePath.value);
+
+    // 璁剧疆PDF鍔犺浇鐘舵�佷负true
+    pdfLoading.value = true;
+
+    const response = await request.get('/glassOptimize/reports/pdf', {
+      params: { filePath: encodedFilePath },
+      responseType: 'blob',
+      headers: {
+        'Accept': 'application/pdf'
+      }
+    });
+
+    // 妫�鏌ュ搷搴旀暟鎹槸鍚﹀瓨鍦ㄤ笖鏈夋晥
+    if (!response) {
+      ElMessage.error('鏈兘鑾峰彇鍒癙DF鏁版嵁');
+      loading.value = false;
+      pdfLoading.value = false; // 璁剧疆PDF鍔犺浇鐘舵�佷负false
+      return;
+    }
+
+    const blob = new Blob([response], { type: 'application/pdf' });
+
+    // 妫�鏌� blob 鏄惁鏈夋晥
+    if (blob.size === 0) {
+      ElMessage.error('鎺ユ敹鍒扮┖鐨凱DF鏂囦欢');
+      loading.value = false;
+      pdfLoading.value = false; // 璁剧疆PDF鍔犺浇鐘舵�佷负false
+      return;
+    }
+
+    // 鍒涘缓PDF URL骞惰祴鍊肩粰pdfUrl鐢ㄤ簬鐣岄潰鏄剧ず
+    const url = URL.createObjectURL(blob);
+    pdfUrl.value = url;
+
+    ElMessage.success('鎶ュ憡鐢熸垚鎴愬姛锛屾鍦ㄩ瑙�...');
+    loading.value = false;
+
+    // 寤惰繜涓�灏忔鏃堕棿鍚庤缃甈DF鍔犺浇瀹屾垚锛岀‘淇濈敤鎴疯兘鐪嬪埌鍔犺浇鐘舵��
+    setTimeout(() => {
+      pdfLoading.value = false;
+    }, 500);
+
+  } catch (error) {
+    console.error('棰勮娴佺▼寮傚父:', error);
+    loading.value = false;
+    pdfLoading.value = false; // 璁剧疆PDF鍔犺浇鐘舵�佷负false
+    if (error.response) {
+      const status = error.response.status;
+      if (status === 400) {
+        ElMessage.error('鏂囦欢璺緞鏃犳晥鎴栦笉鏄疨DF');
+      } else if (status === 404) {
+        ElMessage.error('PDF 鏂囦欢涓嶅瓨鍦�');
+      } else {
+        ElMessage.error(`鏈嶅姟鍣ㄩ敊璇� (${status})锛岃绋嶅悗鍐嶈瘯`);
+      }
+    } else if (error.request) {
+      ElMessage.error('缃戠粶閿欒锛岃妫�鏌ヨ繛鎺�');
+    } else {
+      ElMessage.error('棰勮澶辫触锛岃绋嶅悗鍐嶈瘯');
+    }
+  }
+};
 
 const config = reactive({
   columnTypes: '涓ゅ垪',
@@ -262,7 +476,7 @@
   plain: true,
   printLayouts: true,
   printReport: true,
-  glassInfo: '涓嶆樉绀�',
+  glassInfo: '鏄剧ず鍦ㄤ笅渚�',
   cutInfo: '鏄剧ず'
 
 })
@@ -283,7 +497,9 @@
     selectReportData();
     selectMaterialData();
     selectProductData();
+    fetchSettings(username);
   }
+
 });
 
 const handlePrint = () => {
@@ -299,7 +515,7 @@
   currentGh.value = dimensions.height;
   currentPrintWidth.value = dimensions.width;
   currentPrintHeight.value = dimensions.height;
-  
+
   if (rectRenderer.value) {
     rectRenderer.value.updateLayout();
   }
@@ -310,3 +526,56 @@
   handleLayoutChange();
 });
 </script>
+
+<style scoped>
+.loading-animation {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.dot-flashing {
+  position: relative;
+  width: 10px;
+  height: 10px;
+  border-radius: 5px;
+  background-color: #409eff;
+  color: #409eff;
+  animation: dotFlashing 1s infinite linear alternate;
+  animation-delay: .5s;
+}
+
+.dot-flashing::before, .dot-flashing::after {
+  content: '';
+  display: inline-block;
+  position: absolute;
+  top: 0;
+  width: 10px;
+  height: 10px;
+  border-radius: 5px;
+  background-color: #409eff;
+  color: #409eff;
+}
+
+.dot-flashing::before {
+  left: -15px;
+  animation: dotFlashing 1s infinite alternate;
+  animation-delay: 0s;
+}
+
+.dot-flashing::after {
+  left: 15px;
+  animation: dotFlashing 1s infinite alternate;
+  animation-delay: 1s;
+}
+
+@keyframes dotFlashing {
+  0% {
+    background-color: #409eff;
+  }
+  50%,
+  100% {
+    background-color: #c0d9f7;
+  }
+}
+</style>
\ No newline at end of file

--
Gitblit v1.8.0