import puppeteer from "puppeteer"; import fs from "fs-extra"; import path from "path"; import axios from "axios"; import FormData from "form-data"; import { colorSchemes } from "../colors.js"; /** * 生成折线图并上传 * @param {Object} options - 配置选项 * @param {string} options.fileAddr - 数据文件地址 * @param {string[]} options.color1 - 颜色数组1 * @param {string[]} options.colors - 颜色数组2 * @param {Object[]} options.setUpImgData - 图表设置数据 * @returns {Promise} - 返回图片URL */ export const generateLineAndChildLine = async (options) => { const { fileAddr } = options; try { console.log("开始生成折线图..."); // 获取数据 const resultChartsData = await axios.get(fileAddr); const chartData = resultChartsData.data; // 准备图表数据 const data = []; chartData.data && chartData.data.forEach((turbine, index) => { const chartConfig = { x: turbine.xData, y: turbine.yData, name: turbine.engineName, mode: "lines", line: { color: colorSchemes[index % colorSchemes.length], }, marker: { color: colorSchemes[index % colorSchemes.length], }, hovertemplate: `${chartData.xaixs}:` + ` %{x}
` + `${chartData.yaixs}:` + "%{y}
", }; if (chartData.yaixs === "概率密度函数") { chartConfig.line.color = colorSchemes[0][12]; } data.push(chartConfig); }); // 准备布局配置 const layout = { title: { text: chartData.title, font: { size: 16, weight: "bold", }, }, xaxis: { title: chartData.xaixs || "X轴", gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", }, yaxis: { title: chartData.yaixs || "Y轴", gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", }, margin: { l: 50, r: 50, t: 50, b: 50, }, plot_bgcolor: "#e5ecf6", gridcolor: "#fff", bgcolor: "#e5ecf6", autosize: true, barmode: "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, }, marker: { color: "red", size: 4 }, }); } // 创建临时目录 const tempDir = path.join(process.cwd(), "temp"); await fs.ensureDir(tempDir); const tempFilePath = path.join( tempDir, `temp_line_chart_${Date.now()}.png` ); // 获取 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", args: ["--no-sandbox", "--disable-setuid-sandbox"], }); try { const page = await browser.newPage(); // 创建HTML内容 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: "png", }); // 上传图片到服务器 const formData = new FormData(); formData.append("file", fs.createReadStream(tempFilePath)); formData.append("type", "chart"); // 这里假设需要从 chartData 中获取 engineCode 和 analysisTypeCode,根据实际情况调整 formData.append("engineCode", chartData.engineCode || ""); formData.append("analysisTypeCode", chartData.analysisTypeCode || ""); // const uploadResponse = await axios.post( // "http://localhost:6900/upload", // formData, // { // headers: { // ...formData.getHeaders(), // }, // } // ); // 删除临时文件 await fs.remove(tempFilePath); // console.log("折线图生成并上传成功:", uploadResponse.data.url); // return uploadResponse.data.url; return formData; } finally { await browser.close(); } } catch (error) { console.error("生成折线图失败:", error); throw error; } };