/* * @Author: your name * @Date: 2025-05-14 10:49:00 * @LastEditTime: 2025-05-26 11:02:41 * @LastEditors: bogon * @Description: In User Settings Edit * @FilePath: /downLoadServer/src/server/utils/chartsCom/yawErrorLine.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"; export const generateYawErrorLine = async ( chartData, bucketName, objectName ) => { try { const data = []; const colors = [...colorSchemes[0].colors]; // 生成颜色 // 获取 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"); chartData && chartData.data && chartData.data.forEach((turbine, index) => { // 判断图表类型,根据类型调整绘制方式 const chartConfig = { x: turbine.xData, // X 数据 y: turbine.yData, // Y 数据 name: turbine.legend, // 使用机组名称 line: { color: colors[index % colors.length], // 为每个机组分配不同的颜色 }, marker: { color: colors[index % colors.length], // 为每个机组分配不同的颜色 }, hovertemplate: `${chartData.xaixs}:` + ` %{x}
` + `${chartData.yaixs}:` + "%{y}
", }; if (chartData.chartType === "line") { chartConfig.mode = "lines+markers"; // 如果是折线图 chartConfig.fill = "none"; } else if (chartData.chartType === "bar") { chartConfig.fill = "tonexty"; } data.push(chartConfig); }); const layout = { title: { text: chartData.data[0].title, font: { size: 16, // 设置标题字体大小(默认 16) weight: "bold", }, }, xaxis: { gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", title: chartData.xaixs || "X轴", // 横坐标标题 }, yaxis: { gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", title: chartData.yaixs || "Y轴", // 纵坐标标题 }, // margin: { // l: 50, // r: 50, // t: 50, // b: 50, // }, plot_bgcolor: "#e5ecf6", gridcolor: "#fff", bgcolor: "#e5ecf6", // 设置背景颜色 autosize: true, // 开启自适应 barmode: chartData.chartType === "bar" ? "stack" : "group", // 如果是柱状图则启用堆叠 }; if ( chartData.contract_Cp_curve_yData && chartData.contract_Cp_curve_yData.length > 0 ) { data.push({ x: chartData.contract_Cp_curve_xData, y: chartData.contract_Cp_curve_yData, mode: "lines+markers", name: "合同功率曲线", line: { color: "red", width: 1, // 设置线条的宽度为1 }, marker: { color: "red", size: 4 }, }); } // 使用 Puppeteer 生成图表的截图 const browser = await puppeteer.launch({ headless: "new", args: ["--no-sandbox", "--disable-setuid-sandbox"], }); const tempDir = path.join(process.cwd(), "images"); await fs.ensureDir(tempDir); const tempFilePath = path.join( tempDir, `temp_yaw_error_chart_${Date.now()}.jpeg` ); try { const page = await browser.newPage(); const htmlContent = ` 静态偏航折线分图
`; 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)); const response = await axios.post( `${process.env.API_BASE_URL}/examples/upload`, { filePath: tempFilePath, bucketName, objectName, } ); console.log("上传成功:", response.data); return response?.data?.url; } catch (error) { console.error("生成折线图失败:", error); throw error; } finally { await browser.close(); } } catch (error) { console.error("生成折线图失败:", error); throw error; } };