123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- * @Author: your name
- * @Date: 2025-05-23 17:19:20
- * @LastEditTime: 2025-07-04 17:03:11
- * @LastEditors: bogon
- * @Description: In User Settings Edit
- * @FilePath: /downLoadServer/src/server/utils/chartsCom/PlotlyChartsFen.js
- */
- import puppeteer from "puppeteer";
- import fs from "fs-extra";
- import path from "path";
- import FormData from "form-data";
- import { colorSchemes } from "../colors.js";
- import axios from "axios";
- /**
- * 生成折线图并上传
- * @param {Object} data - 图表数据
- * @returns {Promise<String>} - 返回图片URL
- */
- export const generatePlotlyChartsFen = async (
- data,
- bucketName,
- objectName,
- fieldEngineCode
- ) => {
- try {
- // 创建临时目录
- const tempDir = path.join(process.cwd(), "images");
- await fs.ensureDir(tempDir);
- const tempFilePath = path.join(
- tempDir,
- `temp_heatmap_chart_${Date.now()}.jpeg`
- );
- // 获取 plotly.js 的绝对路径
- const plotlyPath = path.join(
- process.cwd(),
- "src",
- "public",
- "js",
- "plotly-latest.min.js"
- );
- const plotlyContent = await fs.readFile(plotlyPath, "utf-8");
- // 创建浏览器实例
- const browser = await puppeteer.launch({
- headless: "new",
- // 根据系统改路径
- executablePath: `${process.env.CHROME_PATH}`, // 根据系统改路径
- args: ["--no-sandbox", "--disable-setuid-sandbox"],
- });
- try {
- const page = await browser.newPage();
- // 准备图表数据
- const sortedData = data.data.sort((a, b) => {
- if (
- a.enginCode === fieldEngineCode &&
- b.enginCode !== fieldEngineCode
- ) {
- return 1;
- }
- if (
- a.enginCode !== fieldEngineCode &&
- b.enginCode === fieldEngineCode
- ) {
- return -1;
- }
- return 0;
- });
- const finalData = [];
- let enginName = "";
- console.log(fieldEngineCode, "fieldEngineCode");
- sortedData
- .filter((item) => item.enginName !== "合同功率曲线")
- .forEach((turbine) => {
- const color =
- turbine.enginCode === fieldEngineCode ? "#406DAB" : "#D3D3D3";
- enginName =
- turbine.enginCode === fieldEngineCode ? turbine.enginName : "";
- const chartConfig = {
- x: turbine.xData,
- y: turbine.yData,
- connectgaps: false,
- name: turbine.enginName,
- mode: "lines",
- fill: "none",
- line: { color },
- marker: { color },
- };
- finalData.push(chartConfig);
- });
- const filterData = data.data.filter(
- (item) => item.enginName === "合同功率曲线"
- );
- console.log(filterData, "合同功率曲线");
- // 添加合同功率曲线
- if (filterData && filterData[0].enginName === "合同功率曲线") {
- finalData.push({
- x: filterData[0].xData,
- y: filterData[0].yData,
- mode: "lines+markers",
- name: "合同功率曲线",
- line: {
- color: "red",
- width: 1,
- },
- marker: { color: "red", size: 4 },
- });
- }
- // 准备布局配置
- const layout = {
- title: {
- text: `机组 ${enginName}风速功率曲线分析`,
- font: {
- size: 16,
- weight: "bold",
- },
- },
- xaxis: {
- title: {
- text: "风速(m/s)" || "x轴",
- },
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- yaxis: {
- title: { text: "功率(kW)" || "Y轴" },
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- margin: {
- l: 50,
- r: 50,
- t: 50,
- b: 50,
- },
- autosize: true,
- plot_bgcolor: "#e5ecf6",
- gridcolor: "#fff",
- bgcolor: "#e5ecf6",
- legend: {
- orientation: "h",
- xanchor: "center",
- x: 0.5,
- y: -0.2,
- },
- };
- // 创建HTML内容
- const htmlContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <script>${plotlyContent}</script>
- <style>
- body { margin: 0; }
- #chart { width: 800px; height: 600px; }
- </style>
- </head>
- <body>
- <div id="chart"></div>
- <script>
- window.onload = function() {
- const data = ${JSON.stringify(finalData)};
- const layout = ${JSON.stringify(layout)};
- Plotly.newPlot('chart', data, layout, {
- responsive: true
- }).then(() => {
- window.chartRendered = true;
- });
- };
- </script>
- </body>
- </html>
- `;
- // 设置页面内容
- await page.setContent(htmlContent, {
- waitUntil: "networkidle0",
- });
- // 等待图表渲染完成
- await page.waitForFunction(() => window.chartRendered === true, {
- timeout: 60000,
- });
- // 截图并保存到临时文件
- // 截图并保存到临时文件
- const chartElement = await page.$("#chart");
- await chartElement.screenshot({
- path: tempFilePath,
- type: "jpeg",
- });
- // 上传图片到服务器
- const formData = new FormData();
- formData.append("file", fs.createReadStream(tempFilePath));
- // return formData;
- // 发送上传请求
- const response = await axios.post(
- `${process.env.API_BASE_URL}/examples/upload`,
- { filePath: tempFilePath, bucketName, objectName }
- );
- return response?.data?.url;
- } finally {
- await browser.close();
- }
- } catch (error) {
- console.error("生成折线图失败:", error);
- throw error;
- }
- };
|