|
@@ -259,7 +259,10 @@
|
|
|
<div class="modal-panel">
|
|
<div class="modal-panel">
|
|
|
<div class="modal-head">
|
|
<div class="modal-head">
|
|
|
<h3 id="partsTitle">拆件预览</h3>
|
|
<h3 id="partsTitle">拆件预览</h3>
|
|
|
- <button class="ghost" id="partsClose">关闭</button>
|
|
|
|
|
|
|
+ <div class="row">
|
|
|
|
|
+ <button class="ghost" id="partsRebuildAll">按主图重生全部拆件</button>
|
|
|
|
|
+ <button class="ghost" id="partsClose">关闭</button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="parts-grid">
|
|
<div class="parts-grid">
|
|
|
<div class="parts-box" style="grid-column:1/-1">
|
|
<div class="parts-box" style="grid-column:1/-1">
|
|
@@ -295,6 +298,7 @@ function markTasksRunning(items, running=true){
|
|
|
|
|
|
|
|
function openPartsModal(c, t){
|
|
function openPartsModal(c, t){
|
|
|
CURRENT_PARTS = {asset:c, task:t};
|
|
CURRENT_PARTS = {asset:c, task:t};
|
|
|
|
|
+ $('#partsRebuildAll').dataset.boss = c.id || t.id;
|
|
|
$('#partsTitle').textContent = `${t.chineseName} · 拆件检查`;
|
|
$('#partsTitle').textContent = `${t.chineseName} · 拆件检查`;
|
|
|
$('#partsAtlas').src = assetUrl(c.png);
|
|
$('#partsAtlas').src = assetUrl(c.png);
|
|
|
const parts = c.parts || [];
|
|
const parts = c.parts || [];
|
|
@@ -654,6 +658,41 @@ $('#view').addEventListener('click', async e=>{
|
|
|
});
|
|
});
|
|
|
$('#partsClose').onclick=()=>$('#partsModal').classList.remove('open');
|
|
$('#partsClose').onclick=()=>$('#partsModal').classList.remove('open');
|
|
|
$('#partsModal').onclick=e=>{ if(e.target.id==='partsModal') $('#partsModal').classList.remove('open'); };
|
|
$('#partsModal').onclick=e=>{ if(e.target.id==='partsModal') $('#partsModal').classList.remove('open'); };
|
|
|
|
|
+$('#partsRebuildAll').onclick=async()=>{
|
|
|
|
|
+ const game=$('#gameSel').value;
|
|
|
|
|
+ const bossId=$('#partsRebuildAll').dataset.boss;
|
|
|
|
|
+ if(!game||game==='(暂无)'||!bossId){ opMsg('没有可重生的关主拆件',false); return; }
|
|
|
|
|
+ const item={kind:'characters',id:bossId};
|
|
|
|
|
+ $('#partsRebuildAll').disabled=true;
|
|
|
|
|
+ $('#partsRebuildAll').textContent='重生中…';
|
|
|
|
|
+ markTasksRunning([item], true);
|
|
|
|
|
+ render();
|
|
|
|
|
+ opMsg(`正在按主图重生全部拆件 ${bossId}…`);
|
|
|
|
|
+ const log=$('#log'); log.style.display='block'; log.textContent=`按主图重生全部拆件 ${bossId} 任务创建中…`;
|
|
|
|
|
+ try{
|
|
|
|
|
+ const r=await fetch('/api/retry-boss-parts-from-preview',{method:'POST',headers:{'Content-Type':'application/json'},
|
|
|
|
|
+ body:JSON.stringify({
|
|
|
|
|
+ game, bossId,
|
|
|
|
|
+ provider:$('#provider').value, api_key:$('#apiKey').value,
|
|
|
|
|
+ base_url:$('#baseUrl').value, model:$('#model').value, size:$('#size').value })});
|
|
|
|
|
+ const d=await r.json();
|
|
|
|
|
+ if(!d.ok || !d.jobId){
|
|
|
|
|
+ log.textContent='❌ '+(d.error||'按主图重生拆件失败');
|
|
|
|
|
+ markTasksRunning([item], false); render();
|
|
|
|
|
+ $('#partsRebuildAll').disabled=false;
|
|
|
|
|
+ $('#partsRebuildAll').textContent='按主图重生全部拆件';
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ await pollJob(d.jobId, log, $('#partsRebuildAll'), [item]);
|
|
|
|
|
+ const row=tasksFor('characters').find(t=>t.id===bossId);
|
|
|
|
|
+ if(row && row.asset) openPartsModal(row.asset, row);
|
|
|
|
|
+ }catch(err){
|
|
|
|
|
+ log.textContent='请求失败: '+err;
|
|
|
|
|
+ markTasksRunning([item], false); render();
|
|
|
|
|
+ $('#partsRebuildAll').disabled=false;
|
|
|
|
|
+ $('#partsRebuildAll').textContent='按主图重生全部拆件';
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
$('#partsList').addEventListener('click', async e=>{
|
|
$('#partsList').addEventListener('click', async e=>{
|
|
|
const btn=e.target.closest('.part-retry-btn');
|
|
const btn=e.target.closest('.part-retry-btn');
|
|
|
if(!btn) return;
|
|
if(!btn) return;
|