feat(admin-js): plan order share mini rows clickable via table plan links

This commit is contained in:
萝卜
2026-03-16 17:44:17 +08:00
parent 8971917bca
commit d6d8748ce6
4 changed files with 65 additions and 4 deletions

View File

@@ -418,6 +418,22 @@
text-decoration:none; text-decoration:none;
} }
/* 迷你占比整行可点击JS 渐进增强把 row 渲染为 <a> */
.adm-mini-share-row-link{
display:flex;
align-items:center;
gap:10px;
color:inherit;
text-decoration:none;
border-radius:10px;
padding:2px 4px;
}
.adm-mini-share-row-link:hover{
background:var(--adm-primary-tint-06, rgba(22, 119, 255, .06));
text-decoration:none;
}
.adm-mini-rank-name{ .adm-mini-rank-name{
width:72px; width:72px;
min-width:72px; min-width:72px;

View File

@@ -320,6 +320,22 @@
return; return;
} }
// 渐进增强:从下方表格复用“套餐→订单集合”链接口径(避免硬编码 URL 规则)。
var planIdToHref = {};
try {
var planLinks = document.querySelectorAll('[data-role="plan-order-share-top5"] a.link[href*="plan_id="]');
planLinks.forEach(function (a) {
var href = String(a.getAttribute('href') || '');
var m = href.match(/[?&]plan_id=(\d+)/);
if (!m) {
return;
}
planIdToHref[String(m[1])] = href;
});
} catch (e) {
planIdToHref = {};
}
// 视觉口径bar 宽度按 Top5 内最大值归一(更易读);百分比仍按 total 分母计算。 // 视觉口径bar 宽度按 Top5 内最大值归一(更易读);百分比仍按 total 分母计算。
var maxCnt = 0; var maxCnt = 0;
points.forEach(function (p) { points.forEach(function (p) {
@@ -339,8 +355,17 @@
var ratio = total > 0 ? Math.max(0, Math.min(1, cnt / total)) : 0; var ratio = total > 0 ? Math.max(0, Math.min(1, cnt / total)) : 0;
var barRatio = maxCnt > 0 ? Math.max(0, Math.min(1, cnt / maxCnt)) : 0; var barRatio = maxCnt > 0 ? Math.max(0, Math.min(1, cnt / maxCnt)) : 0;
var row = document.createElement('div'); var pid = Number(p && p.plan_id != null ? p.plan_id : 0);
row.className = 'adm-mini-share-row'; if (!isFinite(pid) || pid < 0) {
pid = 0;
}
var href = planIdToHref[String(pid)] ? String(planIdToHref[String(pid)]) : '';
var row = document.createElement(href ? 'a' : 'div');
row.className = 'adm-mini-share-row' + (href ? ' adm-mini-share-row-link' : '');
if (href) {
row.setAttribute('href', href);
}
var name = document.createElement('div'); var name = document.createElement('div');
name.className = 'adm-mini-share-name'; name.className = 'adm-mini-share-name';
@@ -371,7 +396,7 @@
// a 标签:避免默认下划线影响视觉(由 CSS 控制);并提升可访问性。 // a 标签:避免默认下划线影响视觉(由 CSS 控制);并提升可访问性。
if (href) { if (href) {
row.setAttribute('role', 'link'); row.setAttribute('role', 'link');
row.setAttribute('aria-label', '进入站点订单集合:' + mname); row.setAttribute('aria-label', '进入套餐订单集合:' + pname);
} }
el.appendChild(row); el.appendChild(row);

View File

@@ -589,7 +589,7 @@
<span class="adm-mini-meta-item">Top1占比<strong>{{ $shareTop1Pct }}%</strong></span> <span class="adm-mini-meta-item">Top1占比<strong>{{ $shareTop1Pct }}%</strong></span>
</div> </div>
<table> <table data-role="plan-order-share-top5">
<thead> <thead>
<tr> <tr>
<th>套餐</th> <th>套餐</th>

View File

@@ -0,0 +1,20 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
class AdminJsPlanOrderShareTop5ShouldReuseTablePlanLinksSelectorTest extends TestCase
{
public function test_admin_js_plan_order_share_top5_should_reuse_table_plan_links_selector(): void
{
$js = (string) file_get_contents(public_path('js/admin.js'));
// 护栏:占比条形图应从表格复用 plan_id 链接口径(避免 JS 里硬编码 created_from/to 规则)
$this->assertStringContainsString('[data-role="plan-order-share-top5"] a.link[href*="plan_id="]', $js);
// 且支持 a/div 二选一(可点击则 <a>
$this->assertStringContainsString("document.createElement(href ? 'a' : 'div')", $js);
$this->assertStringContainsString('adm-mini-share-row-link', $js);
}
}