Admin dashboard: add subscription expiry mini bars and generalize mini bar CSS
This commit is contained in:
@@ -589,8 +589,11 @@
|
|||||||
color:var(--adm-text-muted, #94a3b8);
|
color:var(--adm-text-muted, #94a3b8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 订阅到期治理:mini bar(纯 CSS,占比可视化,增强说服力) */
|
/* mini bar(纯 CSS,占比可视化,增强说服力)
|
||||||
[data-page="admin.site_subscriptions.index"] .adm-mini-bar{
|
* - 订阅列表页:订阅到期治理 Top10
|
||||||
|
* - 仪表盘:订阅到期治理占比
|
||||||
|
*/
|
||||||
|
.adm-mini-bar{
|
||||||
height:8px;
|
height:8px;
|
||||||
margin-top:6px;
|
margin-top:6px;
|
||||||
border-radius:999px;
|
border-radius:999px;
|
||||||
@@ -598,12 +601,34 @@
|
|||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-page="admin.site_subscriptions.index"] .adm-mini-bar-fill{
|
.adm-mini-bar-fill{
|
||||||
display:block;
|
display:block;
|
||||||
height:100%;
|
height:100%;
|
||||||
background:linear-gradient(90deg, var(--adm-color-primary, #1677ff), rgba(22, 119, 255, .35));
|
background:linear-gradient(90deg, var(--adm-color-primary, #1677ff), rgba(22, 119, 255, .35));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adm-mini-bar-row{
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns:88px 1fr 54px;
|
||||||
|
gap:10px;
|
||||||
|
align-items:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adm-mini-bar-label{
|
||||||
|
font-size:12px;
|
||||||
|
color:var(--adm-text-muted, #94a3b8);
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow:hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adm-mini-bar-value{
|
||||||
|
text-align:right;
|
||||||
|
font-size:12px;
|
||||||
|
color:var(--adm-text-muted, #94a3b8);
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.collapsible > summary{
|
.collapsible > summary{
|
||||||
list-style:none;
|
list-style:none;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
@@ -727,7 +752,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 平台订单列表:行内治理提示(精简视图主要入口) */
|
/* 平台订单列表:行内治理提示(精简视图主要入口) */
|
||||||
.platform-orders-table .row-warn,
|
.platform-orders-table .row-warn{
|
||||||
|
margin-top:4px;
|
||||||
|
padding:4px 6px;
|
||||||
|
border-left:3px solid var(--adm-error, #ef4444);
|
||||||
|
background:var(--adm-error-bg, #fef2f2);
|
||||||
|
border-radius:4px;
|
||||||
|
cursor:help;
|
||||||
|
}
|
||||||
|
|
||||||
[data-page="admin.dashboard"] .row-warn{
|
[data-page="admin.dashboard"] .row-warn{
|
||||||
margin-top:4px;
|
margin-top:4px;
|
||||||
padding:4px 6px;
|
padding:4px 6px;
|
||||||
@@ -741,6 +774,13 @@
|
|||||||
overflow-x:auto;
|
overflow-x:auto;
|
||||||
-webkit-overflow-scrolling:touch;
|
-webkit-overflow-scrolling:touch;
|
||||||
}
|
}
|
||||||
|
margin-top:4px;
|
||||||
|
padding:4px 6px;
|
||||||
|
border-left:3px solid var(--adm-error, #ef4444);
|
||||||
|
background:var(--adm-error-bg, #fef2f2);
|
||||||
|
border-radius:4px;
|
||||||
|
cursor:help;
|
||||||
|
}
|
||||||
|
|
||||||
[data-page="admin.dashboard"] .row-warn::-webkit-scrollbar{
|
[data-page="admin.dashboard"] .row-warn::-webkit-scrollbar{
|
||||||
height:6px;
|
height:6px;
|
||||||
@@ -762,7 +802,16 @@
|
|||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.platform-orders-table .row-warn-prefix,
|
.platform-orders-table .row-warn-prefix{
|
||||||
|
font-weight:600;
|
||||||
|
display:inline-block;
|
||||||
|
padding:1px 6px;
|
||||||
|
border-radius:10px;
|
||||||
|
background:var(--adm-error-tint, rgba(239, 68, 68, .12));
|
||||||
|
color:var(--adm-error, #ef4444);
|
||||||
|
margin-right:4px;
|
||||||
|
}
|
||||||
|
|
||||||
[data-page="admin.dashboard"] .row-warn-prefix{
|
[data-page="admin.dashboard"] .row-warn-prefix{
|
||||||
font-weight:600;
|
font-weight:600;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
@@ -838,7 +887,7 @@
|
|||||||
#refund-receipts:target,
|
#refund-receipts:target,
|
||||||
#add-refund-receipt:target{
|
#add-refund-receipt:target{
|
||||||
scroll-margin-top:90px;
|
scroll-margin-top:90px;
|
||||||
box-shadow:0 0 0 3px var(--adm-primary-focus-ring, rgba(22, 119, 255, .12)), var(--adm-shadow-sm, 0 1px 2px rgba(15, 23, 42, 0.06));
|
box-shadow:0 0 0 3px var(--adm-primary-focus-ring, rgba(22, 119, 255, .12)), var(--adm-shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 平台订单列表:精简视图也要可达的治理提示(对账/退款不一致) */
|
/* 平台订单列表:精简视图也要可达的治理提示(对账/退款不一致) */
|
||||||
|
|||||||
@@ -279,6 +279,35 @@
|
|||||||
<a class="btn btn-secondary btn-sm" href="{!! \App\Support\BackUrl::withBack('/admin/site-subscriptions?expiry=expiring_7d', $selfWithoutBack) !!}">7天内到期({{ (int) ($stats['site_subscriptions_expiring_7d'] ?? 0) }})</a>
|
<a class="btn btn-secondary btn-sm" href="{!! \App\Support\BackUrl::withBack('/admin/site-subscriptions?expiry=expiring_7d', $selfWithoutBack) !!}">7天内到期({{ (int) ($stats['site_subscriptions_expiring_7d'] ?? 0) }})</a>
|
||||||
<a class="btn btn-secondary btn-sm" href="{!! \App\Support\BackUrl::withBack('/admin/site-subscriptions?expiry=expired', $selfWithoutBack) !!}">已过期({{ (int) ($stats['site_subscriptions_expired'] ?? 0) }})</a>
|
<a class="btn btn-secondary btn-sm" href="{!! \App\Support\BackUrl::withBack('/admin/site-subscriptions?expiry=expired', $selfWithoutBack) !!}">已过期({{ (int) ($stats['site_subscriptions_expired'] ?? 0) }})</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@php
|
||||||
|
$subTotal = (int) ($stats['site_subscriptions'] ?? 0);
|
||||||
|
$subExpiring7d = (int) ($stats['site_subscriptions_expiring_7d'] ?? 0);
|
||||||
|
$subExpired = (int) ($stats['site_subscriptions_expired'] ?? 0);
|
||||||
|
|
||||||
|
$pctExpiring7d = $subTotal > 0 ? min(100, max(0, round(($subExpiring7d / $subTotal) * 100, 1))) : 0;
|
||||||
|
$pctExpired = $subTotal > 0 ? min(100, max(0, round(($subExpired / $subTotal) * 100, 1))) : 0;
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="mt-10" data-role="dashboard-sub-expiry-bars">
|
||||||
|
<div class="muted muted-xs">占比(相对订阅总量 {{ $subTotal }})</div>
|
||||||
|
|
||||||
|
<div class="adm-mini-bar-row mt-6" data-role="dashboard-sub-expiring-7d-row">
|
||||||
|
<div class="adm-mini-bar-label">7天内到期</div>
|
||||||
|
<div class="adm-mini-bar" data-role="dashboard-sub-expiring-7d-bar" title="{{ $subExpiring7d }} / {{ $subTotal }}({{ $pctExpiring7d }}%)">
|
||||||
|
<span class="adm-mini-bar-fill" style="width: {{ $pctExpiring7d }}%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="adm-mini-bar-value">{{ $pctExpiring7d }}%</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adm-mini-bar-row mt-6" data-role="dashboard-sub-expired-row">
|
||||||
|
<div class="adm-mini-bar-label">已过期</div>
|
||||||
|
<div class="adm-mini-bar" data-role="dashboard-sub-expired-bar" title="{{ $subExpired }} / {{ $subTotal }}({{ $pctExpired }}%)">
|
||||||
|
<span class="adm-mini-bar-fill" style="width: {{ $pctExpired }}%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="adm-mini-bar-value">{{ $pctExpired }}%</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="muted muted-xs mt-10">说明:这里先把收费主链的高频治理入口收敛到仪表盘;后续再补趋势/排行的真实聚合。</div>
|
<div class="muted muted-xs mt-10">说明:这里先把收费主链的高频治理入口收敛到仪表盘;后续再补趋势/排行的真实聚合。</div>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class AdminSiteSubscriptionIndexExpiring7dMiniBarsShouldRenderTest extends TestC
|
|||||||
$this->assertStringContainsString('class="adm-mini-bar-fill"', $html);
|
$this->assertStringContainsString('class="adm-mini-bar-fill"', $html);
|
||||||
|
|
||||||
$css = (string) file_get_contents(public_path('css/admin-components.css'));
|
$css = (string) file_get_contents(public_path('css/admin-components.css'));
|
||||||
$this->assertStringContainsString('[data-page="admin.site_subscriptions.index"] .adm-mini-bar', $css);
|
$this->assertStringContainsString('.adm-mini-bar{', $css);
|
||||||
$this->assertStringContainsString('[data-page="admin.site_subscriptions.index"] .adm-mini-bar-fill', $css);
|
$this->assertStringContainsString('.adm-mini-bar-fill{', $css);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user