dsh-plugin-image-workbench 1.1.11 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server/pool.py +10 -7
- package/server/static/index.html +17 -13
package/package.json
CHANGED
package/server/pool.py
CHANGED
|
@@ -603,13 +603,16 @@ class PoolManager:
|
|
|
603
603
|
|
|
604
604
|
# ---------- 并行数(用户可调) ----------
|
|
605
605
|
def valid_accounts(self) -> int:
|
|
606
|
-
"""有效账号数 =
|
|
606
|
+
"""有效账号数 = 能出图的号(可用 + 正在出图中)。
|
|
607
607
|
|
|
608
|
-
|
|
608
|
+
「正在出图」也是有效账号,不能因为它在忙就从上限里扣掉:否则一边出图
|
|
609
|
+
一边上限往下掉,用户刚设好的并行数会被自己压回去。
|
|
610
|
+
限流 / 已下线 / 未绑定 / 待验证 / 异常这些才算无效。
|
|
609
611
|
"""
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
612
|
+
if self.accounts:
|
|
613
|
+
return sum(1 for a in self.accounts
|
|
614
|
+
if a.get("status") in ("ready", "busy"))
|
|
615
|
+
# 账号明细拿不到时退回号池自报的可用数
|
|
613
616
|
try:
|
|
614
617
|
return int(self.pool_stat.get("active") or 0)
|
|
615
618
|
except Exception:
|
|
@@ -650,10 +653,10 @@ class PoolManager:
|
|
|
650
653
|
save_config({"workers": target})
|
|
651
654
|
if target != old:
|
|
652
655
|
log(f"并行数 {old} → {target}"
|
|
653
|
-
+ (f"(请求 {want}
|
|
656
|
+
+ (f"(请求 {want},按有效账号 {cap} 收紧)" if target != want else ""))
|
|
654
657
|
msg = f"并行上限已设为 {target}"
|
|
655
658
|
if want > cap:
|
|
656
|
-
msg = f"最多 {cap}
|
|
659
|
+
msg = f"最多 {cap} 个:并行数不能超过有效账号数,已按 {cap} 执行"
|
|
657
660
|
return {"ok": True, "workers": target, "max": cap, "requested": want,
|
|
658
661
|
"prev": old, "clamped": want > cap, "message": msg}
|
|
659
662
|
|
package/server/static/index.html
CHANGED
|
@@ -1003,7 +1003,7 @@
|
|
|
1003
1003
|
<button class="btn ghost mini" id="monClose" type="button">关闭</button>
|
|
1004
1004
|
</div>
|
|
1005
1005
|
<div class="mon-sum" id="monSum"></div>
|
|
1006
|
-
<!-- 并行上限:默认 3
|
|
1006
|
+
<!-- 并行上限:默认 3,可自行加减。上限跟着有效账号数走(在出图的号也算),超了自动压回来 -->
|
|
1007
1007
|
<div class="mon-wbar">
|
|
1008
1008
|
<span class="wlbl">并行上限</span>
|
|
1009
1009
|
<div class="wctl">
|
|
@@ -1011,7 +1011,7 @@
|
|
|
1011
1011
|
<input id="monW" type="number" min="1" step="1" inputmode="numeric" aria-label="并行上限">
|
|
1012
1012
|
<button type="button" class="wbtn" id="monWUp" title="加 1" aria-label="并行上限加 1">+</button>
|
|
1013
1013
|
</div>
|
|
1014
|
-
<span class="whint" id="monWHint">默认 3
|
|
1014
|
+
<span class="whint" id="monWHint">默认 3,最多不超过有效账号数</span>
|
|
1015
1015
|
</div>
|
|
1016
1016
|
<div class="mon-sec"><b>账号状态</b><span id="monAccHint"></span><span class="spacer"></span><span id="monCheckHint"></span></div>
|
|
1017
1017
|
<div class="mon-box">
|
|
@@ -3944,7 +3944,7 @@ async function stopAllJobs(){
|
|
|
3944
3944
|
const ST_LABEL = {ready:'可用', busy:'出图中', limited:'限流', unhealthy:'已下线', unbound:'未绑定', pending:'待验证', error:'异常'};
|
|
3945
3945
|
let monTimer = null;
|
|
3946
3946
|
|
|
3947
|
-
/* ---------- 并行上限:默认 3,用户可调,封顶 =
|
|
3947
|
+
/* ---------- 并行上限:默认 3,用户可调,封顶 = 有效账号数(在出图的号也算有效) ---------- */
|
|
3948
3948
|
let _wBusy = false, _wLast = null, _wHintTimer = null;
|
|
3949
3949
|
|
|
3950
3950
|
function syncWorkersCtl(d){
|
|
@@ -3966,8 +3966,8 @@ function syncWorkersCtl(d){
|
|
|
3966
3966
|
const over = cur > cap;
|
|
3967
3967
|
hint.className = 'whint' + (over ? ' warn' : '');
|
|
3968
3968
|
hint.textContent = over
|
|
3969
|
-
? `当前 ${cur}
|
|
3970
|
-
: `默认 3,最多 ${cap} 个${valid ?
|
|
3969
|
+
? `当前 ${cur} 个,已超过有效账号 ${cap} 个,建议调低`
|
|
3970
|
+
: `默认 3,最多 ${cap} 个${valid ? `(有效账号 ${valid} 个)` : ''}`;
|
|
3971
3971
|
}
|
|
3972
3972
|
|
|
3973
3973
|
function flashWorkersHint(ms){
|
|
@@ -4058,7 +4058,7 @@ function renderMonitor(d){
|
|
|
4058
4058
|
$('#monSum').innerHTML =
|
|
4059
4059
|
kpi('账号可用', `${kReady}/${kTotal}`, kReady ? 'ok' : 'err')
|
|
4060
4060
|
+ kpi('并行任务', `${run.length}/${d.workers || 1}`, run.length ? 'warn' : '',
|
|
4061
|
-
'并行上限可调:改下面那条「并行上限」的 − / +
|
|
4061
|
+
'并行上限可调:改下面那条「并行上限」的 − / + 或直接填数字,最多不超过有效账号数')
|
|
4062
4062
|
+ kpi('排队', d.queued || 0, d.queued ? 'warn' : '')
|
|
4063
4063
|
+ kpi('今日成功', hist.today_done || 0, 'ok')
|
|
4064
4064
|
+ kpi('今日失败', hist.today_error || 0, hist.today_error ? 'err' : '')
|
|
@@ -4597,12 +4597,16 @@ async function openDrafts(){
|
|
|
4597
4597
|
d.items.forEach(it=>{
|
|
4598
4598
|
const row = document.createElement('div');
|
|
4599
4599
|
row.className = 'draft-row';
|
|
4600
|
-
/*
|
|
4601
|
-
|
|
4602
|
-
const
|
|
4600
|
+
/* 名字优先用标题:标题才是这篇东西叫什么,选题只是「想写什么」的一句话,
|
|
4601
|
+
以前选题优先,标题写好了却看到草稿叫「33333」 */
|
|
4602
|
+
const draftLabel = () => safeText(it.name || it.title || it.topic || '(无标题)');
|
|
4603
|
+
/* 小字只留「N 条分镜 · 跟主名不同的那条信息」:主名已经是标题了,
|
|
4604
|
+
再拼一遍标题等于占地方;选题也跟主名一样就跳过,试下第一条分镜标题 */
|
|
4605
|
+
const brief = [safeText(it.topic),
|
|
4606
|
+
safeText((it.titles || []).find(Boolean) || '')]
|
|
4607
|
+
.find(t => t && t !== draftLabel()) || '';
|
|
4603
4608
|
const sub = clipText([it.count ? it.count + ' 条分镜' : '无分镜',
|
|
4604
4609
|
brief ? clipText(brief, 12) : ''].filter(Boolean).join(' · '), 30);
|
|
4605
|
-
const draftLabel = () => safeText(it.name || it.topic || it.title || '(无选题)');
|
|
4606
4610
|
row.innerHTML = `<span class="dc"><b data-role="label">${esc(draftLabel())}</b>`
|
|
4607
4611
|
+ `<input class="rn-input" data-role="rn" type="text" maxlength="60" placeholder="输入草稿名称,留空恢复默认" style="display:none">`
|
|
4608
4612
|
+ `<span class="ds">${esc(fmtTime(it.updated))} · ${esc(sub)}</span></span>`
|
|
@@ -4615,8 +4619,8 @@ async function openDrafts(){
|
|
|
4615
4619
|
const labelEl = row.querySelector('[data-role="label"]');
|
|
4616
4620
|
const rnEl = row.querySelector('[data-role="rn"]');
|
|
4617
4621
|
/* 回显「当前这个名字」:自定义名优先,没有自定义名就回显它现在显示的默认名
|
|
4618
|
-
|
|
4619
|
-
const defaultName = () => safeText(it.
|
|
4622
|
+
(标题 / 选题),用户在现有名字上改,而不是对着一个空框重想 */
|
|
4623
|
+
const defaultName = () => safeText(it.title || it.topic || '');
|
|
4620
4624
|
const currentName = () => safeText(it.name || '') || defaultName();
|
|
4621
4625
|
rnEl.value = currentName();
|
|
4622
4626
|
row.querySelector('[data-act="rename"]').onclick = ()=>{
|
|
@@ -4634,7 +4638,7 @@ async function openDrafts(){
|
|
|
4634
4638
|
labelEl.style.display = 'block';
|
|
4635
4639
|
if (!save) { rnEl.value = currentName(); return; }
|
|
4636
4640
|
const val = Array.from(safeText(rnEl.value.trim())).slice(0, 60).join('');
|
|
4637
|
-
/*
|
|
4641
|
+
/* 改完正好等于默认名(标题 / 选题)就存空串,让名字继续跟着标题走,
|
|
4638
4642
|
免得把它写死成一份静态名称 */
|
|
4639
4643
|
const nextName = val === defaultName() ? '' : val;
|
|
4640
4644
|
if (nextName === (it.name || '')) { rnEl.value = currentName(); return; }
|