feat(admin): 仪表盘占比卡接入套餐订单占比(Top5)
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Models\Admin;
|
||||
use App\Models\Order;
|
||||
use App\Models\Product;
|
||||
use App\Models\Merchant;
|
||||
use App\Models\Plan;
|
||||
use App\Models\PlatformOrder;
|
||||
use App\Models\User;
|
||||
use App\Support\CacheKeys;
|
||||
@@ -59,10 +60,31 @@ class DashboardController extends Controller
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
// 占比卡(最小可用):按套餐统计平台订单数量 TopN
|
||||
$planOrderShare = PlatformOrder::query()
|
||||
->selectRaw('plan_id, COUNT(*) as cnt')
|
||||
->whereNotNull('plan_id')
|
||||
->groupBy('plan_id')
|
||||
->orderByDesc('cnt')
|
||||
->limit(5)
|
||||
->get()
|
||||
->map(function ($row) {
|
||||
return [
|
||||
'plan_id' => (int) $row->plan_id,
|
||||
'count' => (int) $row->cnt,
|
||||
];
|
||||
})
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$planIdToName = Plan::query()->pluck('name', 'id')->all();
|
||||
|
||||
return view('admin.dashboard', [
|
||||
'adminName' => $admin->name,
|
||||
'stats' => $stats,
|
||||
'recentPlatformOrders' => $recentPlatformOrders,
|
||||
'planOrderShare' => $planOrderShare,
|
||||
'planIdToName' => $planIdToName,
|
||||
'platformAdmin' => $admin,
|
||||
'cacheMeta' => [
|
||||
'store' => config('cache.default'),
|
||||
|
||||
@@ -151,9 +151,49 @@
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="mt-0">占比(占位)</h3>
|
||||
<div class="muted">后续接入:套餐销量占比 / 渠道占比 / 支付方式占比(支持时间范围切换)。</div>
|
||||
<div class="muted muted-xs mt-10">说明:后续会补占比卡的 legend 与颜色体系(对齐 AntD Pro)。</div>
|
||||
<div class="flex-between">
|
||||
<h3 class="mt-0">套餐订单占比(Top5)</h3>
|
||||
<a class="muted" href="/admin/plans">查看套餐</a>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$shareRows = (array) ($planOrderShare ?? []);
|
||||
$totalOrders = 0;
|
||||
foreach ($shareRows as $r) {
|
||||
$totalOrders += (int) ($r['count'] ?? 0);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>套餐</th>
|
||||
<th>订单数</th>
|
||||
<th>占比</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($shareRows as $row)
|
||||
@php
|
||||
$planId = (int) ($row['plan_id'] ?? 0);
|
||||
$count = (int) ($row['count'] ?? 0);
|
||||
$pct = $totalOrders > 0 ? round(($count / $totalOrders) * 100, 1) : 0;
|
||||
$planName = (string) (($planIdToName[$planId] ?? '') ?: ('#' . $planId));
|
||||
@endphp
|
||||
<tr>
|
||||
<td>{{ $planName }}</td>
|
||||
<td>{{ $count }}</td>
|
||||
<td>{{ $pct }}%</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="3" class="muted">暂无数据</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="muted muted-xs mt-10">说明:当前口径为“平台订单按 plan_id 的数量占比(Top5)”;后续扩展到金额占比、渠道占比与时间范围切换。</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AdminDashboardPlanOrderShareCardShouldRenderTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function loginAsPlatformAdmin(): void
|
||||
{
|
||||
$this->seed();
|
||||
|
||||
$this->post('/admin/login', [
|
||||
'email' => 'platform.admin@demo.local',
|
||||
'password' => 'Platform@123456',
|
||||
])->assertRedirect('/admin');
|
||||
}
|
||||
|
||||
public function test_dashboard_plan_order_share_card_should_render(): void
|
||||
{
|
||||
$this->loginAsPlatformAdmin();
|
||||
|
||||
$res = $this->get('/admin');
|
||||
$res->assertOk();
|
||||
|
||||
$res->assertSee('套餐订单占比', false);
|
||||
$res->assertSee('Top5', false);
|
||||
$res->assertSee('查看套餐', false);
|
||||
|
||||
// 有数据时至少应包含百分号展示
|
||||
$res->assertSee('%', false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user