Dashboard: add platform order funnel mini bars (unpaid→pending→syncable)
This commit is contained in:
@@ -283,6 +283,44 @@
|
|||||||
$poRenewalMissingPct = $poTotal > 0 ? min(100, max(0, round(($poRenewalMissing / $poTotal) * 100, 1))) : 0;
|
$poRenewalMissingPct = $poTotal > 0 ? min(100, max(0, round(($poRenewalMissing / $poTotal) * 100, 1))) : 0;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
@php
|
||||||
|
$poUnpaidPending = (int) ($stats['platform_orders_unpaid_pending'] ?? 0);
|
||||||
|
$poPaidPending = (int) ($stats['platform_orders_paid_pending'] ?? 0);
|
||||||
|
$poSyncable = (int) ($stats['platform_orders_syncable'] ?? 0);
|
||||||
|
|
||||||
|
$poUnpaidPendingPct = $poTotal > 0 ? min(100, max(0, round(($poUnpaidPending / $poTotal) * 100, 1))) : 0;
|
||||||
|
$poPaidPendingPct = $poTotal > 0 ? min(100, max(0, round(($poPaidPending / $poTotal) * 100, 1))) : 0;
|
||||||
|
$poSyncablePct = $poTotal > 0 ? min(100, max(0, round(($poSyncable / $poTotal) * 100, 1))) : 0;
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="mt-10" data-role="dashboard-po-funnel-bars">
|
||||||
|
<div class="muted muted-xs">收费主链漏斗(相对平台订单总量 {{ $poTotal }})</div>
|
||||||
|
|
||||||
|
<div class="adm-mini-bar-row mt-6" data-role="dashboard-po-unpaid-pending-row">
|
||||||
|
<div class="adm-mini-bar-label">待支付</div>
|
||||||
|
<div class="adm-mini-bar" data-role="dashboard-po-unpaid-pending-bar" title="{{ $poUnpaidPending }} / {{ $poTotal }}({{ $poUnpaidPendingPct }}%)">
|
||||||
|
<span class="adm-mini-bar-fill" style="width: {{ $poUnpaidPendingPct }}%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="adm-mini-bar-value">{{ $poUnpaidPendingPct }}%</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adm-mini-bar-row mt-6" data-role="dashboard-po-paid-pending-row">
|
||||||
|
<div class="adm-mini-bar-label">待生效</div>
|
||||||
|
<div class="adm-mini-bar" data-role="dashboard-po-paid-pending-bar" title="{{ $poPaidPending }} / {{ $poTotal }}({{ $poPaidPendingPct }}%)">
|
||||||
|
<span class="adm-mini-bar-fill" style="width: {{ $poPaidPendingPct }}%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="adm-mini-bar-value">{{ $poPaidPendingPct }}%</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adm-mini-bar-row mt-6" data-role="dashboard-po-syncable-row">
|
||||||
|
<div class="adm-mini-bar-label">可同步</div>
|
||||||
|
<div class="adm-mini-bar" data-role="dashboard-po-syncable-bar" title="{{ $poSyncable }} / {{ $poTotal }}({{ $poSyncablePct }}%)">
|
||||||
|
<span class="adm-mini-bar-fill" style="width: {{ $poSyncablePct }}%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="adm-mini-bar-value">{{ $poSyncablePct }}%</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-10" data-role="dashboard-po-governance-bars">
|
<div class="mt-10" data-role="dashboard-po-governance-bars">
|
||||||
<div class="muted muted-xs">治理风险占比(相对平台订单总量 {{ $poTotal }})</div>
|
<div class="muted muted-xs">治理风险占比(相对平台订单总量 {{ $poTotal }})</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class AdminDashboardPlatformOrderFunnelMiniBarsShouldRenderTest 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_should_render_platform_order_funnel_mini_bars(): void
|
||||||
|
{
|
||||||
|
$this->loginAsPlatformAdmin();
|
||||||
|
|
||||||
|
$res = $this->get('/admin');
|
||||||
|
$res->assertOk();
|
||||||
|
|
||||||
|
$html = (string) $res->getContent();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('data-role="dashboard-po-funnel-bars"', $html);
|
||||||
|
$this->assertStringContainsString('data-role="dashboard-po-unpaid-pending-bar"', $html);
|
||||||
|
$this->assertStringContainsString('data-role="dashboard-po-paid-pending-bar"', $html);
|
||||||
|
$this->assertStringContainsString('data-role="dashboard-po-syncable-bar"', $html);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user