123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- import puppeteer from "puppeteer";
- import fs from "fs-extra";
- import path from "path";
- import FormData from "form-data";
- import axios from "axios"; // 导入 axios
- import { colorSchemes } from "../colors.js";
- export const getFaultAllCharts = async (
- data,
- bucketName,
- objectName,
- analysisTypeCode
- ) => {
- // 获取 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");
- // console.log(data, "全场故障数据");
- try {
- // 提取故障类型、故障次数和故障时长
- const faultTypes = data.map((item) => item.fault_detail);
- const faultCounts = data.map((item) => item.count);
- const faultDurations = data.map((item) => item.fault_time_sum);
- // 故障次数的柱状图数据(左侧 Y 轴)
- const barTrace = {
- x: faultTypes.slice(0, 10),
- y: faultCounts.slice(0, 10),
- type: "bar",
- marker: { color: "#64ADC2" }, // 蓝色柱状图
- name: "故障次数",
- hovertemplate: `故障类型: %{x} <br> 故障次数: %{y} 次<br>`,
- };
- // 故障时长的折线图数据(右侧 Y 轴)
- const lineTrace = {
- x: faultTypes.slice(0, 10),
- y: faultDurations.slice(0, 10),
- type: "scatter",
- mode: "lines+markers", // 线性图 + 点标记
- line: { color: "#1A295D" }, // 红色折线
- name: "故障时长",
- yaxis: "y2", // 使用第二个 Y 轴(右侧)
- hovertemplate: `故障类型: %{x} <br> 故障时长: %{y} 小时 <br>`,
- };
- // 布局配置,设置双 Y 轴
- const layout = {
- title: {
- text: "全场故障次数与时长分析Top10",
- font: {
- size: 16, // 设置标题字体大小(默认 16)
- weight: "bold",
- },
- },
- xaxis: {
- title: {
- text: "故障类型",
- },
- tickangle: 30,
- tickmode: "array",
- tickvals: faultTypes.slice(0, 10),
- tickfont: { size: 12 },
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- yaxis: {
- title: {
- text: "故障次数",
- },
- titlefont: { color: "#64ADC2" },
- tickfont: { color: "#64ADC2" },
- side: "left", // 左侧的 Y 轴
- showline: true,
- linecolor: "#64ADC2",
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- yaxis2: {
- title: {
- text: "故障时长 (小时)",
- },
- titlefont: { color: "#1A295D" },
- tickfont: { color: "#1A295D" },
- overlaying: "y", // 在第一个 Y 轴上方绘制
- side: "right", // 右侧的 Y 轴
- position: 1, // 调整右侧轴的位置
- showline: true,
- linecolor: "#1A295D", // 设置右侧轴线颜色
- },
- barmode: "group", // 柱状图分组
- plot_bgcolor: "#e5ecf6",
- gridcolor: "#fff",
- bgcolor: "#e5ecf6", // 设置背景颜色
- showlegend: false,
- margin: {
- t: 80, // 上边距
- b: 150, // 下边距,给 X 轴标签更多空间
- },
- };
- // 创建临时目录
- const tempDir = path.join(process.cwd(), "images");
- await fs.ensureDir(tempDir);
- const tempFilePath = path.join(
- tempDir,
- `temp_fault_all_chart_${Date.now()}.jpeg`
- );
- // 使用 Puppeteer 生成图表的截图
- 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 htmlContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>全场故障</title>
- <script>${plotlyContent}</script>
- <style>
- body { margin: 0; }
- #chart { width: 800px; height: 600px; }
- </style>
- </head>
- <body>
- <div id="chart"></div>
- <script>
- window.onload = function() {
- Plotly.newPlot('chart', [${JSON.stringify(
- barTrace
- )}, ${JSON.stringify(lineTrace)}], ${JSON.stringify(
- layout
- )}).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));
- const response = await axios.post(
- `${process.env.API_BASE_URL}/examples/upload`,
- {
- filePath: tempFilePath,
- bucketName,
- objectName,
- }
- );
- return response?.data?.url;
- } catch (error) {
- console.error("生成图表失败:", error);
- } finally {
- await browser.close();
- }
- } catch (error) {
- console.error("发生错误:", error);
- }
- };
|