feat(batch): 批次页增加一键复制run_id(轻量JS)
This commit is contained in:
@@ -489,6 +489,70 @@
|
||||
}, 9000);
|
||||
})();
|
||||
|
||||
// 通用:复制到剪贴板(有权限限制/兼容降级)
|
||||
function copyToClipboard(text) {
|
||||
var t = String(text || '');
|
||||
if (!t) {
|
||||
return Promise.reject(new Error('empty'));
|
||||
}
|
||||
|
||||
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return navigator.clipboard.writeText(t);
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = t;
|
||||
ta.setAttribute('readonly', 'readonly');
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.top = '-1000px';
|
||||
ta.style.left = '-1000px';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
var ok = document.execCommand('copy');
|
||||
document.body.removeChild(ta);
|
||||
ok ? resolve() : reject(new Error('copy_failed'));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 批次页:一键复制 run_id(渐进增强)
|
||||
(function(){
|
||||
var btn = qs('[data-action="copy-run-id"][data-run-id]');
|
||||
if(!btn){return;}
|
||||
|
||||
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) {}
|
||||
|
||||
try { window.alert('已复制 run_id:' + runId); } catch (e) {}
|
||||
}).catch(function(){
|
||||
try { window.alert('复制失败,请手动复制 run_id:' + runId); } catch (e) {}
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
// 续费缺订阅治理:订单详情页“绑定订阅ID”输入框,小交互增强:
|
||||
// - 输入后按 Enter 直接提交
|
||||
// - 自动聚焦,减少点击
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
</div>
|
||||
<div class="actions gap-10">
|
||||
<a class="btn btn-secondary btn-sm" href="{{ $backToListUrl }}">返回上一页</a>
|
||||
@if($runId !== '')
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-action="copy-run-id" data-run-id="{{ $runId }}">复制 run_id</button>
|
||||
@endif
|
||||
<a class="btn btn-secondary btn-sm" href="/admin/platform-batches/show?type={{ $type }}&run_id={{ urlencode($runId) }}&back={{ urlencode($selfWithoutBack) }}">刷新</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AdminPlatformBatchShowPageCopyRunIdButtonShouldRenderTest 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_batch_show_page_should_render_copy_run_id_button(): void
|
||||
{
|
||||
$this->loginAsPlatformAdmin();
|
||||
|
||||
$runId = 'BAS_COPY_BTN_0001';
|
||||
|
||||
$html = $this->get('/admin/platform-batches/show?type=bas&run_id=' . $runId)
|
||||
->assertOk()
|
||||
->getContent();
|
||||
|
||||
$this->assertStringContainsString('data-action="copy-run-id"', $html);
|
||||
$this->assertStringContainsString('data-run-id="' . $runId . '"', $html);
|
||||
$this->assertStringContainsString('复制 run_id', $html);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user