Преглед изворни кода

feat: 数据分析中指标趋势和指标聚合增加打印功能

yanglzh пре 9 месеци
родитељ
комит
66936c5898

+ 1 - 0
package.json

@@ -32,6 +32,7 @@
     "echarts-wordcloud": "2.0.0",
     "element-plus": "2.2.28",
     "event-source-polyfill": "1.0.31",
+    "html2canvas": "^1.4.1",
     "js-cookie": "3.0.5",
     "jsplumb": "2.15.6",
     "jsrsasign": "10.8.6",

+ 39 - 0
pnpm-lock.yaml

@@ -53,6 +53,9 @@ importers:
       event-source-polyfill:
         specifier: 1.0.31
         version: 1.0.31
+      html2canvas:
+        specifier: ^1.4.1
+        version: 1.4.1
       js-cookie:
         specifier: 3.0.5
         version: 3.0.5
@@ -741,6 +744,10 @@ packages:
   balanced-match@1.0.2:
     resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
 
+  base64-arraybuffer@1.0.2:
+    resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
+    engines: {node: '>= 0.6.0'}
+
   batch-processor@1.0.0:
     resolution: {integrity: sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==}
 
@@ -866,6 +873,9 @@ packages:
     resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
     engines: {node: '>= 8'}
 
+  css-line-break@2.1.0:
+    resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
+
   css-tree@2.3.1:
     resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
     engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
@@ -1394,6 +1404,10 @@ packages:
     resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==}
     engines: {node: '>=12.0.0'}
 
+  html2canvas@1.4.1:
+    resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
+    engines: {node: '>=8.0.0'}
+
   ignore@5.3.2:
     resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
     engines: {node: '>= 4'}
@@ -1951,6 +1965,9 @@ packages:
     resolution: {integrity: sha512-KCuXjYxCZ3ru40dmND+oCLsXyuA8hoseu2SS404Px5ouyS0A99v8X/mdiLqsR5MTAyamMBN7PRwt2Dv3+xGIxw==}
     hasBin: true
 
+  text-segmentation@1.0.3:
+    resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
+
   text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
 
@@ -2033,6 +2050,9 @@ packages:
   uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
 
+  utrie@1.0.2:
+    resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
+
   uuid@9.0.0:
     resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
     hasBin: true
@@ -2951,6 +2971,8 @@ snapshots:
 
   balanced-match@1.0.2: {}
 
+  base64-arraybuffer@1.0.2: {}
+
   batch-processor@1.0.0: {}
 
   binary-extensions@2.3.0: {}
@@ -3089,6 +3111,10 @@ snapshots:
       shebang-command: 2.0.0
       which: 2.0.2
 
+  css-line-break@2.1.0:
+    dependencies:
+      utrie: 1.0.2
+
   css-tree@2.3.1:
     dependencies:
       mdn-data: 2.0.30
@@ -3665,6 +3691,11 @@ snapshots:
 
   highlight.js@11.10.0: {}
 
+  html2canvas@1.4.1:
+    dependencies:
+      css-line-break: 2.1.0
+      text-segmentation: 1.0.3
+
   ignore@5.3.2: {}
 
   immutable@4.3.7: {}
@@ -4168,6 +4199,10 @@ snapshots:
       resolve: 1.22.8
       string.prototype.trim: 1.2.9
 
+  text-segmentation@1.0.3:
+    dependencies:
+      utrie: 1.0.2
+
   text-table@0.2.0: {}
 
   tiny-emitter@2.1.0: {}
@@ -4256,6 +4291,10 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
+  utrie@1.0.2:
+    dependencies:
+      base64-arraybuffer: 1.0.2
+
   uuid@9.0.0: {}
 
   v8-compile-cache@2.4.0: {}

+ 55 - 0
src/utils/print.ts

@@ -0,0 +1,55 @@
+import html2canvas from 'html2canvas';
+import { ElMessage } from 'element-plus';
+
+/**
+ * 打印图表
+ * @param chartElement 图表DOM元素
+ */
+export const printChart = async (chartElement: HTMLElement) => {
+  if (!chartElement) {
+    ElMessage.warning('图表未加载');
+    return;
+  }
+  
+  try {
+    const canvas = await html2canvas(chartElement);
+    const dataUrl = canvas.toDataURL('image/png');
+    
+    // 创建打印窗口
+    const printWindow = window.open('', '_blank');
+    if (!printWindow) {
+      ElMessage.error('请允许打开新窗口');
+      return;
+    }
+    
+    printWindow.document.write(`
+      <html>
+        <head>
+          <title>图表打印</title>
+          <style>
+            body { margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; }
+            img { max-width: 100%; height: auto; }
+          </style>
+        </head>
+        <body>
+          <img src="${dataUrl}" />
+        </body>
+      </html>
+    `);
+    printWindow.document.close();
+    
+    // 等待图片加载完成后打印
+    const img = printWindow.document.querySelector('img');
+    if (img) {
+      img.onload = () => {
+        setTimeout(() => {
+          printWindow.print();
+          printWindow.close();
+        }, 100);
+      };
+    }
+  } catch (error) {
+    console.error('打印失败:', error);
+    ElMessage.error('打印失败,请稍后重试');
+  }
+};

+ 15 - 0
src/views/iot/dataAnalysis/IndicatorAggregation/index.vue

@@ -46,6 +46,12 @@
             </el-icon>
             查询
           </el-button>
+          <el-button type="primary" @click="handlePrintChart">
+            <el-icon>
+              <ele-Printer />
+            </el-icon>
+            打印图表
+          </el-button>
         </el-form-item>
       </el-form>
       <div class="title">
@@ -66,6 +72,7 @@ import api from '/@/api/device';
 import dayjs from 'dayjs';
 import Chart from '/@/components/chart/index.vue'
 import { getLineOption } from '/@/components/chart/options'
+import { printChart } from '/@/utils/print';
 
 const productList = ref<any[]>([])
 const deviceList = ref<any[]>([])
@@ -147,6 +154,14 @@ function propertyChange(property: string) {
   propertyName.value = propertyList.value.find(item => item.key === property)?.name
 }
 
+// 打印图表
+const handlePrintChart = async () => {
+  if (!chart.value) {
+    ElMessage.warning('图表未加载');
+    return;
+  }
+  await printChart(chart.value.$el);
+};
 </script>
 <style scoped>
 .title {

+ 15 - 0
src/views/iot/dataAnalysis/exponentialTrend/index.vue

@@ -44,6 +44,12 @@
             </el-icon>
             查询
           </el-button>
+          <el-button type="primary" @click="handlePrintChart">
+            <el-icon>
+              <ele-Printer />
+            </el-icon>
+            打印图表
+          </el-button>
         </el-form-item>
       </el-form>
       <div class="title">
@@ -64,6 +70,7 @@ import api from '/@/api/device';
 import dayjs from 'dayjs';
 import Chart from '/@/components/chart/index.vue'
 import { getLineOption } from '/@/components/chart/options'
+import { printChart } from '/@/utils/print';
 
 const productList = ref<any[]>([])
 const deviceList = ref<any[]>([])
@@ -150,6 +157,14 @@ function propertyChange(property: string) {
   propertyName.value = propertyList.value.find(item => item.key === property)?.name
 }
 
+// 打印图表
+const handlePrintChart = async () => {
+  if (!chart.value) {
+    ElMessage.warning('图表未加载');
+    return;
+  }
+  await printChart(chart.value.$el);
+};
 </script>
 <style scoped>
 .title {