fix: restore analysis chart rendering
This commit is contained in:
@@ -91,6 +91,18 @@
|
||||
: v.toLocaleString();
|
||||
}
|
||||
|
||||
function formatMetric(v, label = '') {
|
||||
if (typeof v !== 'number' || !Number.isFinite(v)) return v;
|
||||
const name = String(label || '').toLowerCase();
|
||||
if (name.includes('%') || name.includes('率') || name.includes('yoy') || name.includes('mom')) {
|
||||
return `${v >= 0 ? '+' : ''}${v.toFixed(1)}%`;
|
||||
}
|
||||
if (name.includes('$') || name.includes('金額') || name.includes('營收') || name.includes('業績') || name.includes('毛利') || name.includes('客單') || name.includes('單價')) {
|
||||
return `$${Math.round(v).toLocaleString()}`;
|
||||
}
|
||||
return formatNumber(v);
|
||||
}
|
||||
|
||||
function tuneDataset(ds, idx, type) {
|
||||
if (!ds || typeof ds !== 'object') return;
|
||||
const palette = readPalette();
|
||||
@@ -118,6 +130,8 @@
|
||||
ds.pointBackgroundColor = ds.pointBackgroundColor || color;
|
||||
ds.pointBorderColor = ds.pointBorderColor || theme.elevated;
|
||||
ds.tension = ds.tension ?? (t === 'line' ? 0.32 : undefined);
|
||||
ds.hoverBorderWidth = ds.hoverBorderWidth || (t === 'line' ? 3 : 1);
|
||||
ds.maxBarThickness = ds.maxBarThickness || (t === 'bar' ? 34 : undefined);
|
||||
}
|
||||
|
||||
function tuneChartConfig(config) {
|
||||
@@ -136,6 +150,8 @@
|
||||
const plugins = (config.options.plugins = config.options.plugins || {});
|
||||
plugins.legend = {
|
||||
...(plugins.legend || {}),
|
||||
position: (plugins.legend || {}).position || (isCompact() ? 'bottom' : 'top'),
|
||||
align: (plugins.legend || {}).align || 'start',
|
||||
labels: {
|
||||
color: theme.muted,
|
||||
boxWidth: 10,
|
||||
@@ -165,7 +181,7 @@
|
||||
typeof ctx.parsed === 'object'
|
||||
? ctx.parsed.y ?? ctx.parsed.x ?? ctx.raw
|
||||
: ctx.parsed;
|
||||
return `${lbl}${formatNumber(v)}`;
|
||||
return `${lbl}${formatMetric(v, ctx.dataset && ctx.dataset.label)}`;
|
||||
},
|
||||
...((plugins.tooltip || {}).callbacks || {})
|
||||
}
|
||||
@@ -185,6 +201,7 @@
|
||||
color: theme.muted,
|
||||
maxRotation: isCompact() ? 0 : 30,
|
||||
autoSkip: isCompact(),
|
||||
maxTicksLimit: isCompact() ? 5 : 8,
|
||||
font: {
|
||||
family: theme.mono,
|
||||
size: isCompact() ? 10 : 11,
|
||||
@@ -252,6 +269,28 @@
|
||||
if (!window.echarts || window.echarts.__ewooocThemed) return;
|
||||
const ec = window.echarts;
|
||||
const nativeInit = ec.init.bind(ec);
|
||||
const tuneAxis = axis => {
|
||||
if (!axis || typeof axis !== 'object') return axis;
|
||||
return {
|
||||
axisLine: { lineStyle: { color: theme.faint }, ...(axis.axisLine || {}) },
|
||||
axisTick: { lineStyle: { color: theme.faint }, ...(axis.axisTick || {}) },
|
||||
axisLabel: {
|
||||
color: theme.muted,
|
||||
fontFamily: theme.mono,
|
||||
fontSize: isCompact() ? 10 : 11,
|
||||
...(axis.axisLabel || {})
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: { color: theme.faint, type: 'dashed' },
|
||||
...(axis.splitLine || {})
|
||||
},
|
||||
...axis
|
||||
};
|
||||
};
|
||||
const tuneAxisList = axes => {
|
||||
if (Array.isArray(axes)) return axes.map(tuneAxis);
|
||||
return tuneAxis(axes);
|
||||
};
|
||||
ec.init = function (dom, themeName, opts) {
|
||||
const chart = nativeInit(dom, themeName || null, opts);
|
||||
const setOpt = chart.setOption.bind(chart);
|
||||
@@ -261,7 +300,33 @@
|
||||
...opt,
|
||||
color: palette,
|
||||
backgroundColor: 'transparent',
|
||||
textStyle: { color: theme.ink, fontFamily: theme.font }
|
||||
textStyle: { color: theme.ink, fontFamily: theme.font, ...(opt.textStyle || {}) },
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
confine: true,
|
||||
backgroundColor: theme.elevated,
|
||||
borderColor: theme.faint,
|
||||
borderWidth: 1,
|
||||
textStyle: { color: theme.ink, fontFamily: theme.font },
|
||||
axisPointer: { type: 'cross', label: { backgroundColor: '#6f6256' } },
|
||||
...(opt.tooltip || {})
|
||||
},
|
||||
legend: {
|
||||
bottom: 0,
|
||||
type: 'scroll',
|
||||
textStyle: { color: theme.muted, fontFamily: theme.mono, fontSize: 11 },
|
||||
...(opt.legend || {})
|
||||
},
|
||||
grid: {
|
||||
containLabel: true,
|
||||
left: isCompact() ? 12 : 28,
|
||||
right: isCompact() ? 12 : 24,
|
||||
top: isCompact() ? 24 : 36,
|
||||
bottom: isCompact() ? 34 : 40,
|
||||
...(opt.grid || {})
|
||||
},
|
||||
xAxis: tuneAxisList(opt.xAxis),
|
||||
yAxis: tuneAxisList(opt.yAxis)
|
||||
};
|
||||
return setOpt(tuned, notMerge, lazy);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user