feat: show data labels on channel-compare and spend-share charts

This commit is contained in:
王源
2026-09-10 14:46:58 +08:00
parent a5107fccf7
commit 86ae56259f
+24 -3
View File
@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moboost 广告投放报告</title> <title>Moboost 广告投放报告</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0/dist/chartjs-plugin-datalabels.min.js"></script>
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } * { margin: 0; padding: 0; box-sizing: border-box; }
body { body {
@@ -363,6 +364,8 @@
} }
/* ---------- Tab 1: 投放数据 ---------- */ /* ---------- Tab 1: 投放数据 ---------- */
// datalabels 默认全局注册,先取消,只在需要的图表按需启用
if (window.ChartDataLabels) { try { Chart.unregister(ChartDataLabels); } catch(e){} }
const CH_COLORS = { Mintegral:'#3b82f6', MediaGo:'#10b981', Bigo:'#f59e0b' }; const CH_COLORS = { Mintegral:'#3b82f6', MediaGo:'#10b981', Bigo:'#f59e0b' };
const PALETTE = ['#3b82f6','#10b981','#f59e0b','#ef4444','#8b5cf6','#06b6d4','#ec4899','#84cc16','#f97316','#6366f1']; const PALETTE = ['#3b82f6','#10b981','#f59e0b','#ef4444','#8b5cf6','#06b6d4','#ec4899','#84cc16','#f97316','#6366f1'];
let perfCharts = {}; let perfCharts = {};
@@ -471,15 +474,33 @@
{ label:'转化', data:chConv, backgroundColor:'#ef4444', borderRadius:4, yAxisID:'y1' }, { label:'转化', data:chConv, backgroundColor:'#ef4444', borderRadius:4, yAxisID:'y1' },
]}, ]},
options:{ responsive:true, maintainAspectRatio:false, options:{ responsive:true, maintainAspectRatio:false,
plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}}}, layout:{padding:{top:24}},
plugins:{
legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},
datalabels:{
anchor:'end', align:'end', color:'#374151', font:{size:11,weight:'600'},
formatter:(v,ctx)=> ctx.datasetIndex===0 ? '$'+Math.round(v).toLocaleString() : Math.round(v).toLocaleString()
}
},
scales:{ x:{grid:{display:false},ticks:{color:'#9ca3af'}}, scales:{ x:{grid:{display:false},ticks:{color:'#9ca3af'}},
y:{position:'left',ticks:{color:'#9ca3af'},grid:{color:'#f3f4f6'}}, y:{position:'left',ticks:{color:'#9ca3af'},grid:{color:'#f3f4f6'}},
y1:{position:'right',ticks:{color:'#9ca3af'},grid:{display:false}} } } y1:{position:'right',ticks:{color:'#9ca3af'},grid:{display:false}} } },
plugins:[ChartDataLabels]
}); });
const totalSpend = chSpend.reduce((a,b)=>a+b,0) || 1;
drawChart('chartSpendShare', { drawChart('chartSpendShare', {
type:'doughnut', type:'doughnut',
data:{ labels:chans, datasets:[{ data:chSpend, backgroundColor:chans.map(c=>CH_COLORS[c]||'#999') }] }, data:{ labels:chans, datasets:[{ data:chSpend, backgroundColor:chans.map(c=>CH_COLORS[c]||'#999') }] },
options:{ responsive:true, maintainAspectRatio:false, plugins:{legend:{position:'right',labels:{boxWidth:12,font:{size:11}}}} } options:{ responsive:true, maintainAspectRatio:false,
plugins:{
legend:{position:'right',labels:{boxWidth:12,font:{size:11}}},
datalabels:{
color:'#fff', font:{size:12,weight:'700'},
formatter:(v)=> (v/totalSpend*100)>=5 ? '$'+Math.round(v).toLocaleString()+'\n'+(v/totalSpend*100).toFixed(0)+'%' : '',
textAlign:'center'
}
} },
plugins:[ChartDataLabels]
}); });
// ---- 模块4:渠道效率对比(按 产品_国家 分组,展开各渠道)---- // ---- 模块4:渠道效率对比(按 产品_国家 分组,展开各渠道)----