import { renderChart } from "../chartService/index.js"; import { colorSchemes } from "../colors.js"; export const generateTwoDMarkersChart1 = async ( data, bucketName, objectName, ) => { try { // ✅ 1. 数据拆分(修复 enginName 拼写问题🔥) const scatterData = data.data.find( (item) => item.engineName !== "合同功率曲线", ); const lineData = data.data.find( (item) => item.engineName === "合同功率曲线" || item.enginName === "合同功率曲线", ); if (!scatterData) { throw new Error("scatterData 不存在"); } // ✅ 2. 颜色数据源 const rawColorData = scatterData.colorbar?.length === scatterData.xData.length ? scatterData.colorbar : scatterData.color; const uniqueLabels = [...new Set(rawColorData)]; const tickvals = uniqueLabels.map((_, i) => i + 1); const ticktext = uniqueLabels.map((dateStr) => { const date = new Date(dateStr); if (isNaN(date)) return dateStr; // 防止非法时间🔥 const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, "0"); return `${y}-${m}`; }); const mapping = uniqueLabels.reduce((acc, cur, i) => { acc[cur] = i + 1; return acc; }, {}); // ✅ 3. 颜色渐变(安全版) const colors = colorSchemes?.[0]?.colors || []; const safePick = (i) => colors[i] || colors[0] || "#1B2973"; const colorStops = [safePick(0), safePick(4), safePick(8), safePick(12)]; const colorscale = colorStops.map((c, i) => [ i / (colorStops.length - 1), c, ]); if (colorscale.length < 2) { colorscale.push([1, safePick(0)]); } // ✅ 4. 映射颜色 const colorValues = rawColorData.map((v) => mapping[v]); // ⚠️ 性能优化 const pointCount = scatterData.xData.length; const markerSize = pointCount > 5000 ? 3 : 6; // ✅ 5. scatter trace const scatterTrace = { x: scatterData.xData, y: scatterData.yData, type: "scattergl", mode: "markers", name: scatterData.engineName, marker: { color: colorValues, colorscale, size: markerSize, colorbar: { title: { text: scatterData.colorbartitle || "时间" }, tickvals, ticktext, }, line: { color: "#fff", width: 0.3, }, }, customdata: rawColorData, hovertemplate: `${data.xaixs}: %{x}
` + `${data.yaixs}: %{y}
` + `时间: %{customdata}`, }; // ✅ 6. 合同曲线(优化:避免空对象加入🔥) const traces = [scatterTrace]; if (lineData?.xData?.length && lineData?.yData?.length) { traces.push({ x: lineData.xData, y: lineData.yData, type: "scatter", mode: "lines+markers", name: "合同功率曲线", line: { color: "red" }, marker: { color: "red", size: 4 }, }); } // ✅ 7. layout const layout = { title: { text: scatterData.title || "散点图", font: { size: 16 }, }, xaxis: { title: data.xaixs, gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", showbackground: true, showline: true, // ✅ 显示 X 轴轴线 zeroline: false, linecolor: "#ffffff", // ✅ X 轴轴线颜色设为白色 }, yaxis: { title: data.yaixs, gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#e5ecf6", showbackground: true, showline: true, // ✅ 显示 X 轴轴线 zeroline: false, linecolor: "#ffffff", // ✅ X 轴轴线颜色设为白色 }, showlegend: false, plot_bgcolor: "#e5ecf6", paper_bgcolor: "#e5ecf6", }; // ✅ 8. 渲染 const url = await renderChart({ traces, layout, bucketName, objectName, }); return url; } catch (error) { console.error("❌ 生成2D散点图失败:", error); throw error; } };