feat(admin-dashboard): add mini trend chart for 7d paid sum

This commit is contained in:
萝卜
2026-03-16 10:17:13 +08:00
parent e0b1a707fb
commit 3c4612b339
4 changed files with 110 additions and 0 deletions

View File

@@ -308,6 +308,52 @@
} }
/* 可复用KPI 卡片栅格(参考 Ant Design Pro Analysis第一行 4 个等宽卡片) */ /* 可复用KPI 卡片栅格(参考 Ant Design Pro Analysis第一行 4 个等宽卡片) */
/* 可复用:迷你图表(渐进增强:由 admin.js 渲染,页面无 JS 时为空但不影响表格) */
.adm-mini-chart{
margin-top:10px;
height:86px;
width:100%;
display:flex;
align-items:flex-end;
gap:8px;
padding:10px 10px;
border:1px solid var(--adm-border-color, #e5e7eb);
border-radius:var(--adm-radius, 12px);
background:var(--adm-surface-tint, rgba(15, 23, 42, .02));
box-shadow:var(--adm-shadow-sm);
}
.adm-mini-chart.is-empty{
align-items:center;
justify-content:center;
color:var(--adm-text-muted, #94a3b8);
font-size:12px;
}
.adm-mini-chart-bar{
flex:1;
min-width:0;
height:10px;
border-radius:10px 10px 4px 4px;
border:1px solid var(--adm-primary-border-35, rgba(22, 119, 255, .35));
background:var(--adm-primary-tint-08, rgba(22, 119, 255, .08));
position:relative;
overflow:hidden;
}
.adm-mini-chart-bar::after{
content:"";
position:absolute;
inset:0;
background:linear-gradient(180deg, rgba(22, 119, 255, .22), rgba(22, 119, 255, .04));
}
.adm-mini-chart-bar:hover{
border-color:var(--adm-primary-border-45, rgba(22, 119, 255, .45));
background:var(--adm-primary-tint-06, rgba(22, 119, 255, .06));
}
.kpi-grid{ .kpi-grid{
display:grid; display:grid;
grid-template-columns:repeat(4,minmax(0,1fr)); grid-template-columns:repeat(4,minmax(0,1fr));

View File

@@ -74,6 +74,58 @@
}); });
})(); })();
// 仪表盘:迷你图表(趋势图渐进增强)
// 说明:不引入图表库,避免构建链;用 div bar 方式渲染。
(function () {
var el = qs('[data-role="platform-order-trend-7d-chart"][data-points]');
if (!el) {
return;
}
var raw = el.getAttribute('data-points') || '[]';
var points = [];
try {
points = JSON.parse(raw) || [];
} catch (e) {
points = [];
}
if (!points || points.length === 0) {
el.classList.add('is-empty');
el.textContent = '暂无趋势数据';
return;
}
var max = 0;
points.forEach(function (p) {
var v = Number(p && p.paid_sum ? p.paid_sum : 0);
if (v > max) {
max = v;
}
});
if (!max || max <= 0) {
max = 1;
}
// 清空(避免 SSR/重复执行污染)
el.innerHTML = '';
points.forEach(function (p) {
var paid = Number(p && p.paid_sum ? p.paid_sum : 0);
var h = Math.round(Math.max(6, (paid / max) * 72));
var bar = document.createElement('div');
bar.className = 'adm-mini-chart-bar';
bar.style.height = h + 'px';
var date = (p && p.date) ? String(p.date) : '';
var count = (p && p.count != null) ? String(p.count) : '0';
bar.title = date + '' + count + ' 单,已付 ¥' + paid.toFixed(2);
el.appendChild(bar);
});
})();
// 通用:将后端 flash 信息同步到 toast更像 Ant Design Pro 的反馈方式) // 通用:将后端 flash 信息同步到 toast更像 Ant Design Pro 的反馈方式)
// 说明:渐进增强。页面仍保留原本的提示块,不依赖 JS。 // 说明:渐进增强。页面仍保留原本的提示块,不依赖 JS。
(function () { (function () {

View File

@@ -84,8 +84,19 @@
@php @php
$trendRows = (array) ($platformOrderTrend7d ?? []); $trendRows = (array) ($platformOrderTrend7d ?? []);
// 用于前端渐进增强渲染迷你图表JS 读取 data-points
$trendPoints = [];
foreach ($trendRows as $r) {
$trendPoints[] = [
'date' => (string) ($r['date'] ?? ''),
'count' => (int) ($r['count'] ?? 0),
'paid_sum' => (float) ($r['paid_sum'] ?? 0),
];
}
@endphp @endphp
<div class="adm-mini-chart" data-role="platform-order-trend-7d-chart" data-points='@json($trendPoints)'></div>
<table class="mt-10" data-role="platform-order-trend-7d"> <table class="mt-10" data-role="platform-order-trend-7d">
<thead> <thead>
<tr> <tr>

View File

@@ -78,6 +78,7 @@ class AdminDashboardPlatformOrderTrend7dShouldRenderTest extends TestCase
$res->assertOk(); $res->assertOk();
$res->assertSee('data-role="platform-order-trend-7d"', false); $res->assertSee('data-role="platform-order-trend-7d"', false);
$res->assertSee('data-role="platform-order-trend-7d-chart"', false);
$res->assertSee('近7天平台订单按天'); $res->assertSee('近7天平台订单按天');
// 断言日期行出现(只验证两个代表点) // 断言日期行出现(只验证两个代表点)