From d219712567683f32b4059d088ce1098bab3d5c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Tue, 17 Mar 2026 16:49:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(batch):=20=E6=89=B9=E6=AC=A1=E9=A1=B5?= =?UTF-8?q?=E6=B2=BB=E7=90=86=E5=85=A5=E5=8F=A3=E5=A2=9E=E5=8A=A0=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E9=93=BE=E6=8E=A5=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/admin.js | 72 ++++++++++++++----- .../admin/platform_batches/show.blade.php | 2 + ...GovernanceLinksButtonsShouldRenderTest.php | 38 ++++++++++ 3 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 tests/Feature/AdminPlatformBatchShowPageCopyGovernanceLinksButtonsShouldRenderTest.php diff --git a/public/js/admin.js b/public/js/admin.js index 7da6f4a..9642fac 100644 --- a/public/js/admin.js +++ b/public/js/admin.js @@ -546,6 +546,36 @@ }); } + function toastSuccess(text) { + try { + var container = qs('[data-role="toast-container"]'); + if (!container) { + return false; + } + + var t = document.createElement('div'); + t.className = 'toast toast-success'; + t.setAttribute('role', 'status'); + + var c = document.createElement('div'); + c.className = 'toast-content'; + c.textContent = String(text || ''); + + t.appendChild(c); + container.appendChild(t); + + setTimeout(function () { + try { + container.removeChild(t); + } catch (e) {} + }, 2500); + + return true; + } catch (e) { + return false; + } + } + // 批次页:一键复制 run_id(渐进增强) (function(){ var btn = qs('[data-action="copy-run-id"][data-run-id]'); @@ -554,25 +584,9 @@ btn.addEventListener('click', function(){ var runId = btn.getAttribute('data-run-id') || ''; copyToClipboard(runId).then(function(){ - // 复用 toast 容器(若不存在则降级 alert) - try { - var container = qs('[data-role="toast-container"]'); - if(container){ - var t = document.createElement('div'); - t.className = 'toast toast-success'; - t.setAttribute('role','status'); - var c = document.createElement('div'); - c.className = 'toast-content'; - c.textContent = '已复制 run_id:' + runId; - t.appendChild(c); - container.appendChild(t); - setTimeout(function(){ - try{ container.removeChild(t);}catch(e){} - }, 2500); - return; - } - } catch(e) {} - + if (toastSuccess('已复制 run_id:' + runId)) { + return; + } try { window.alert('已复制 run_id:' + runId); } catch (e) {} }).catch(function(){ try { window.alert('复制失败,请手动复制 run_id:' + runId); } catch (e) {} @@ -580,6 +594,26 @@ }); })(); + // 批次页:一键复制治理集合链接(例如:本批次失败 / 按Top原因) + (function(){ + var btns = document.querySelectorAll('[data-action="copy-link"][data-href]'); + if(!btns || btns.length === 0){return;} + + btns.forEach(function(btn){ + btn.addEventListener('click', function(){ + var href = btn.getAttribute('data-href') || ''; + copyToClipboard(href).then(function(){ + if (toastSuccess('已复制链接')) { + return; + } + try { window.alert('已复制链接'); } catch (e) {} + }).catch(function(){ + try { window.alert('复制失败,请手动复制链接'); } catch (e) {} + }); + }); + }); + })(); + // 续费缺订阅治理:订单详情页“绑定订阅ID”输入框,小交互增强: // - 输入后按 Enter 直接提交 // - 自动聚焦,减少点击 diff --git a/resources/views/admin/platform_batches/show.blade.php b/resources/views/admin/platform_batches/show.blade.php index 773806f..4ba2e6d 100644 --- a/resources/views/admin/platform_batches/show.blade.php +++ b/resources/views/admin/platform_batches/show.blade.php @@ -124,10 +124,12 @@ @if(($governanceLinks['failed'] ?? '') !== '') 本批次失败 + @endif @if(($governanceLinks['top_reason'] ?? '') !== '') 按Top原因 + @endif @if(($governanceLinks['retry_syncable'] ?? '') !== '') diff --git a/tests/Feature/AdminPlatformBatchShowPageCopyGovernanceLinksButtonsShouldRenderTest.php b/tests/Feature/AdminPlatformBatchShowPageCopyGovernanceLinksButtonsShouldRenderTest.php new file mode 100644 index 0000000..077eb1b --- /dev/null +++ b/tests/Feature/AdminPlatformBatchShowPageCopyGovernanceLinksButtonsShouldRenderTest.php @@ -0,0 +1,38 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_batch_show_page_should_render_copy_buttons_for_governance_links_when_present(): void + { + $this->loginAsPlatformAdmin(); + + // 不依赖 DB:该页面即使 summary 缺失也会渲染治理入口(本批次失败/按Top原因)是否存在取决于 controller summary。 + // 这里用 BAS + 任意 run_id,只校验按钮结构存在;治理链接内容在其它测试已覆盖。 + $runId = 'BAS_COPY_LINKS_0001'; + + // 该 run_id 在空库下 summary 为空,controller 仍会生成 failed/all/retry 链接,因此“本批次失败”应存在。 + $html = $this->get('/admin/platform-batches/show?type=bas&run_id=' . $runId) + ->assertOk() + ->getContent(); + + $this->assertStringContainsString('data-action="copy-link"', $html); + $this->assertStringContainsString('data-role="copy-failed-link"', $html); + } +}