63 lines
2.7 KiB
JavaScript
63 lines
2.7 KiB
JavaScript
import { compactMoneyAxis, formatCoin } from "../../utils/format.js";
|
|
|
|
export function createMetricTrendOption(item) {
|
|
const lines = Array.isArray(item?.trend) ? item.trend.filter((line) => Array.isArray(line.data) && line.data.length) : [];
|
|
const labels = lines[0]?.data.map((point) => point.label) || [];
|
|
const values = lines.flatMap((line) => line.data.map((point) => Number(point.value) || 0));
|
|
const axis = niceAxis(values);
|
|
return {
|
|
animationDuration: 650,
|
|
color: ["#27e4f5", "#24d79f", "#4f8cff"],
|
|
grid: { bottom: 32, left: 58, right: 24, top: 42 },
|
|
legend: { icon: "roundRect", itemGap: 18, itemHeight: 8, itemWidth: 14, textStyle: { color: "#a8bdd8", fontSize: 12 }, top: 0 },
|
|
tooltip: {
|
|
backgroundColor: "#08243a",
|
|
borderColor: "#1a5f82",
|
|
formatter: (params) => {
|
|
const rows = Array.isArray(params) ? params : [params];
|
|
return rows.map((row, index) => `${index === 0 ? `${row.axisValue}<br/>` : ""}${row.marker}${row.seriesName}: ${formatTrendValue(row.data, item.trendFormat)}`).join("<br/>");
|
|
},
|
|
textStyle: { color: "#e9f6ff" },
|
|
trigger: "axis"
|
|
},
|
|
xAxis: { axisLabel: { color: "#90a8c4", margin: 10 }, axisLine: { lineStyle: { color: "#1a3a56" } }, axisTick: { show: false }, boundaryGap: false, data: labels, type: "category" },
|
|
yAxis: { axisLabel: { color: "#90a8c4", formatter: (value) => formatTrendValue(value, item.trendFormat, true) }, axisTick: { show: false }, interval: axis.interval, max: axis.max, min: 0, splitLine: { lineStyle: { color: "rgba(111, 166, 212, 0.16)", type: "dashed" } }, type: "value" },
|
|
series: lines.map((line) => ({
|
|
areaStyle: { color: "rgba(39, 228, 245, 0.08)" },
|
|
data: line.data.map((point) => point.value),
|
|
lineStyle: { width: 3 },
|
|
name: line.name,
|
|
smooth: 0.38,
|
|
symbol: "circle",
|
|
symbolSize: 7,
|
|
type: "line"
|
|
}))
|
|
};
|
|
}
|
|
|
|
export function niceAxis(values) {
|
|
const maxValue = Math.max(...values, 0);
|
|
if (maxValue <= 0) {
|
|
return { interval: 1, max: 4 };
|
|
}
|
|
const rawStep = maxValue / 4;
|
|
const magnitude = 10 ** Math.floor(Math.log10(rawStep));
|
|
const normalized = rawStep / magnitude;
|
|
const step = (normalized <= 1 ? 1 : normalized <= 2 ? 2 : normalized <= 5 ? 5 : 10) * magnitude;
|
|
return {
|
|
interval: step,
|
|
max: step * Math.ceil(maxValue / step)
|
|
};
|
|
}
|
|
|
|
function formatTrendValue(value, format, axis = false) {
|
|
const numeric = Number(value) || 0;
|
|
if (format === "money") {
|
|
return axis ? compactMoneyAxis(numeric) : `$${numeric.toLocaleString("en-US", { maximumFractionDigits: 2 })}`;
|
|
}
|
|
if (format === "coin") {
|
|
return axis ? compactMoneyAxis(numeric) : formatCoin(numeric);
|
|
}
|
|
return axis ? compactMoneyAxis(numeric) : numeric.toLocaleString("en-US");
|
|
}
|