liujiejie 1 ヶ月 前
コミット
f2b7ae0c08

+ 20 - 4
downLoadServer/src/server/controllers/chartController.js

@@ -3,6 +3,7 @@ import { generateBarChart } from "../utils/chartsCom/BarChart.js";
 import { generateLineChart } from "../utils/chartsCom/lineChartsFen.js";
 import { generateLineAndChildLine } from "../utils/chartsCom/lineAndChildLine.js";
 import { generateHeatmapChart } from "../utils/chartsCom/HeatmapCharts.js";
+import { generate3DDrawingChart } from "../utils/chartsCom/3DDrawingChart.js";
 import axios from "axios";
 
 // 提取公共逻辑到辅助函数
@@ -15,15 +16,27 @@ const handleChartGeneration = async (
 ) => {
   try {
     const { fileAddr } = req.body;
-
     if (!fileAddr) {
       return errorResponse(res, "缺少数据URL", 400);
     }
-
     // 从URL获取数据
     const response = await axios.get(fileAddr);
-    const data = response.data;
-
+    let data = [];
+    console.log("获取到的数据:", data);
+    if (typeof response.data === "string") {
+      let dataString = response.data;
+      dataString = dataString.trim(); // 去除前后空格
+      dataString = dataString.replace(/Infinity/g, '"Infinity"'); // 替换 Infinity 为 "Infinity"
+      try {
+        const parsedData = JSON.parse(dataString);
+        data = parsedData;
+      } catch (error) {
+        console.error("JSON 解析失败:", error);
+      }
+    } else {
+      data = response.data;
+    }
+    console.log(data, "  data");
     // 验证数据格式
     if (
       !data ||
@@ -89,3 +102,6 @@ export const createLineAndChildLine = async (req, res) => {
 export const createHeatmapCharts = async (req, res) => {
   await handleChartGeneration(req, res, generateHeatmapChart, "热力图生成成功");
 };
+export const create3DDrawingChart = async (req, res) => {
+  await handleChartGeneration(req, res, generate3DDrawingChart, "3D图生成成功");
+};

+ 2 - 0
downLoadServer/src/server/routes/chartRoutes.js

@@ -4,6 +4,7 @@ import {
   createLineChart,
   createLineAndChildLine,
   createHeatmapCharts,
+  create3DDrawingChart,
 } from "../controllers/chartController.js";
 
 const router = express.Router();
@@ -12,4 +13,5 @@ router.post("/bar", createBarChart);
 router.post("/line", createLineChart);
 router.post("/lineAndChildLine", createLineAndChildLine);
 router.post("/heatmap", createHeatmapCharts);
+router.post("/3DDrawingChart", create3DDrawingChart);
 export default router;

+ 218 - 0
downLoadServer/src/server/utils/chartsCom/3DDrawingChart.js

@@ -0,0 +1,218 @@
+/*
+ * @Author: your name
+ * @Date: 2025-04-14 16:09:13
+ * @LastEditTime: 2025-04-15 09:40:22
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /downLoadServer/src/server/utils/chartsCom/3DDrawingChart.js
+ */
+import puppeteer from "puppeteer";
+import fs from "fs-extra";
+import path from "path";
+import FormData from "form-data";
+import { colorSchemes } from "../colors.js";
+export const generate3DDrawingChart = async (data) => {
+  try {
+    console.log("开始生成热力图...");
+    console.log("数据:", data);
+    const colorSchemesItem = colorSchemes[0].colors;
+    // 创建临时目录
+    const tempDir = path.join(process.cwd(), "images");
+    await fs.ensureDir(tempDir);
+    const tempFilePath = path.join(
+      tempDir,
+      `temp_heatmap_chart_${Date.now()}.png`
+    );
+
+    // 获取 plotly.js 的绝对路径
+    const plotlyPath = path.join(
+      process.cwd(),
+      "src",
+      "public",
+      "js",
+      "plotly-3.0.1.min.js"
+    );
+    const plotlyContent = await fs.readFile(plotlyPath, "utf-8");
+
+    // 创建浏览器实例
+    const browser = await puppeteer.launch({
+      headless: "new",
+      args: ["--no-sandbox", "--disable-setuid-sandbox"],
+    });
+
+    try {
+      const page = await browser.newPage();
+
+      // 准备图表数据
+      const chartDataset = data.data[0]; // 修改为 data.chartData
+
+      const uniqueColors = [...new Set(chartDataset.color)];
+      const traces = uniqueColors.map((color, idx) => {
+        const colorData = chartDataset.color.map((c) => (c === color ? 1 : 0));
+
+        return {
+          x: chartDataset.xData.filter((_, i) => colorData[i] === 1),
+          y: chartDataset.yData.filter((_, i) => colorData[i] === 1),
+          z: chartDataset.zData.filter((_, i) => colorData[i] === 1),
+          mode: "markers", // 根据需要设置模式
+          type: "scatter3d",
+          marker: {
+            size: 1, // 使用动态点大小
+            color: colorSchemesItem[idx], // 使用配色方案
+            colorscale: "YlGnBu",
+          },
+          name: ` ${color}`,
+          // hovertemplate: `${data.xaixs}: %{x} <br> ${data.yaixs}: %{y} <br> ${data.zaixs}: %{z} <extra></extra>`,
+        };
+      });
+      // 准备布局配置
+      const layout = {
+        title: {
+          text: chartDataset.title,
+          font: {
+            size: 16,
+            weight: "bold",
+          },
+        },
+        scene: {
+          xaxis: {
+            gridcolor: "rgb(255,255,255)",
+            tickcolor: "rgb(255,255,255)",
+            backgroundcolor: "#CFD4DC",
+            showbackground: true,
+            linecolor: "black", // 轴线颜色
+            ticks: "outside", // 设置刻度线在轴线外
+            fixedrange: true, // 防止缩放
+            tickcolor: "black",
+            tickangle: -10,
+            title: {
+              text: data.xaixs,
+            },
+          },
+          yaxis: {
+            type: "category",
+            categoryorder: "array", // 自定义顺序,确保间隔均匀
+            categoryarray: [...new Set(chartDataset.yData)],
+            gridcolor: "rgb(255,255,255)",
+            linecolor: "black",
+            ticks: "outside",
+            gridcolor: "rgb(255,255,255)",
+            tickcolor: "rgb(255,255,255)",
+            backgroundcolor: "#CFD4DC",
+            showbackground: true,
+            tickcolor: "black",
+            tickangle: 25,
+            title: {
+              text: data.yaixs,
+            },
+          },
+          zaxis: {
+            gridcolor: "rgb(255,255,255)",
+            tickcolor: "rgb(255,255,255)",
+            backgroundcolor: "#CFD4DC",
+            showbackground: true,
+            fixedrange: true, // 防止缩放
+            linecolor: "black", // 轴线颜色
+            ticks: "outside", // 设置刻度线在轴线外
+            tickcolor: "black",
+            tickangle: -90,
+            title: {
+              text: data.zaixs,
+            },
+          },
+          aspectratio: {
+            x: 2.2,
+            y: 1.7,
+            z: 1,
+          },
+          plot_bgcolor: "#e5ecf6",
+          gridcolor: "#fff",
+          bgcolor: "#e5ecf6", // 设置背景颜色
+          camera: {
+            up: {
+              x: 0.200292643688136,
+              y: 0.2488259353493132,
+              z: 0.947612004346693,
+            },
+            center: {
+              x: -0.052807476121180814,
+              y: 0.02451796399554085,
+              z: -0.022911006648570736,
+            },
+            eye: {
+              x: -2.126379643342493,
+              y: -2.551422475965373,
+              z: 1.0917667684145647,
+            },
+            projection: {
+              type: "orthographic",
+            },
+          },
+        },
+        margin: { t: 50, b: 50, l: 50, r: 50 },
+        staticPlot: false,
+        showlegend: true,
+        legend: {
+          marker: {
+            size: 10, // 图例中点的大小
+          },
+        },
+      };
+
+      // 准备 HTML 内容
+      const htmlContent = `
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="UTF-8">
+  <title>热力图</title>
+  <script>${plotlyContent}</script>
+</head>
+<body>
+  <div id="chart" style="width: 100%; height: 450px"></div>
+  <script>
+    const traces = ${JSON.stringify(traces)};
+    const layout = ${JSON.stringify(layout)};
+    Plotly.newPlot('chart', traces, layout, { responsive: true }).then(() => {
+      window.chartRendered = true; // 确保在图表渲染完成后设置
+      console.log("图表渲染完成");
+    }).catch((error) => {
+      console.error("图表渲染错误:", error); // 捕获渲染错误
+    });
+  </script>
+</body>
+</html>
+`;
+      // ... existing code ...
+      // 设置页面内容
+      await page.setContent(htmlContent, {
+        waitUntil: "networkidle0",
+      });
+
+      // 等待图表渲染完成,延长超时时间
+      await page.waitForFunction(() => window.chartRendered === true, {
+        timeout: 150000, // 延长到 120 秒
+      });
+
+      // 截图并保存到临时文件
+      const chartElement = await page.$("#chart");
+      await chartElement.screenshot({
+        path: tempFilePath,
+        type: "png",
+      });
+
+      // 上传图片到服务器
+      const formData = new FormData();
+      formData.append("file", fs.createReadStream(tempFilePath));
+      return formData;
+    } catch (error) {
+      console.error("生成3D图失败:", error);
+      throw error;
+    } finally {
+      await browser.close();
+    }
+  } catch (error) {
+    console.error("生成3D图失败:", error);
+    throw error;
+  }
+};

+ 0 - 1
downLoadServer/src/server/utils/chartsCom/BarChart.js

@@ -1,7 +1,6 @@
 import puppeteer from "puppeteer";
 import fs from "fs-extra";
 import path from "path";
-import axios from "axios";
 import FormData from "form-data";
 
 /**

+ 8 - 0
downLoadServer/src/server/utils/chartsCom/Time3DChart.js

@@ -0,0 +1,8 @@
+/*
+ * @Author: your name
+ * @Date: 2025-04-14 17:49:33
+ * @LastEditTime: 2025-04-14 17:49:33
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/downLoadServer/src/server/utils/chartsCom/Time3DChart.js
+ */

+ 2 - 2
src/views/home/Index.vue

@@ -52,7 +52,7 @@ export default {
   data() {
     return {
       loading: false,
-      isShowHd: true, //true 则展示华电的菜单样式,false 则展示默认的左侧边栏菜单
+      isShowHd: false, //true 则展示华电的菜单样式,false 则展示默认的左侧边栏菜单
     };
   },
   methods: {
@@ -120,7 +120,7 @@ export default {
   opacity: 0;
 }
 
-.headerLeft{
+.headerLeft {
   width: 190px;
 }
 </style>

+ 8 - 5
src/views/performance/assetssMag.vue

@@ -524,14 +524,17 @@ export default {
   methods: {
     async handleDownLoadChart() {
       const res = await axios.post(
-        "/downLoadChart/chartServer/charts/heatmap",
+        "/downLoadChart/chartServer/charts/3DDrawingChart",
         {
           fieldEngineCode: "WOG00623", //lineChartFen
           fileAddr:
-            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/wind_speed_frequency/manual/wind_Speed_Frequency%2302.json", //barChart
-            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/cp/manual/%2320.json", //lineChartFen
-            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/cp/manual/WEM00013.json", //lineAndChartLine
-            "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/data_integrity_second/manual/Data_Integrity_Of_Second_Analyst.json", //heatmap
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/wind_speed_frequency/manual/wind_Speed_Frequency%2302.json", //barChart  url:bar
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/cp/manual/%2320.json", //lineChartFen  url:line
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/cp/manual/WEM00013.json", //lineAndChartLine  url:lineAndChildLine
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/data_integrity_second/manual/Data_Integrity_Of_Second_Analyst.json", //HeatmapCharts  url:heatmap
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/speed_torque/manual/total_3D_WEM00012.json", //3DDrawingChart  url:3DDrawingChart
+            // "http://192.168.50.233:6900/wof039800012/WOF039800012-WOB000001/speed_power/manual/total_3D_WEM00012.json",//3DDrawingChart  url:3DDrawingChart
+            "",
         }
       );
       console.log(res, "res linechart");

+ 0 - 8
src/views/performance/components/chartsCom/Time3DChart.vue

@@ -154,7 +154,6 @@ export default {
       const month = ("0" + (date.getMonth() + 1)).slice(-2); // 获取月份并确保两位数
       return `${year}-${month}`;
     },
-
     renderChart() {
       // 提取 Y 轴数据中的月份,并去重
       const uniqueMonths = Array.from(
@@ -435,11 +434,4 @@ export default {
 ::v-deep canvas {
   /* height: 400px !important; */
 }
-/* .js-plotly-plot .plotly,
-.js-plotly-plot .plotly div {
-  background: #e5ecf6 !important;
-}
-#scene {
-  background: #e5ecf6 !important;
-} */
 </style>