Fix timestamps missing after restart + align detail modal
Docker Build and Push / check-secrets (push) Successful in 6s
Docker Build and Push / build-and-push (cpu, latest) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 11.8) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 12.6) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 12.8) (push) Has been skipped
Docker Build and Push / build-and-push (directml, latest) (push) Has been skipped
Build Windows CPU / build (push) Has been cancelled
Build Windows CUDA 11.8 / build (push) Has been cancelled
Build Windows CUDA 12.6 / build (push) Has been cancelled
Build Windows CUDA 12.8 / build (push) Has been cancelled
Build Windows DirectML / build (push) Has been cancelled
Docker Build and Push / check-secrets (push) Successful in 6s
Docker Build and Push / build-and-push (cpu, latest) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 11.8) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 12.6) (push) Has been skipped
Docker Build and Push / build-and-push (cuda, 12.8) (push) Has been skipped
Docker Build and Push / build-and-push (directml, latest) (push) Has been skipped
Build Windows CPU / build (push) Has been cancelled
Build Windows CUDA 11.8 / build (push) Has been cancelled
Build Windows CUDA 12.6 / build (push) Has been cancelled
Build Windows CUDA 12.8 / build (push) Has been cancelled
Build Windows DirectML / build (push) Has been cancelled
- Add started_at / completed_at columns to tasks table (were missing) - Migration adds columns to existing DB without data loss - _save_task_to_db now persists created_at / started_at / completed_at - _load_tasks_from_db restores all three timestamp fields on startup - Detail modal shows same created/started/elapsed layout as table row with identical fmtTime / fmtDur helpers, live elapsed for in-progress tasks Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
d5468ec958
commit
76f5d1c857
+25
-10
@@ -1007,9 +1007,18 @@ function openDetail(id) {
|
||||
el.className = `badge ${cls}`;
|
||||
el.innerHTML = `<span class="bdot"></span>${label}`;
|
||||
|
||||
const dur = (t.started_at && t.completed_at)
|
||||
? `${Math.round(t.completed_at - t.started_at)}s`
|
||||
: (t.started_at ? '进行中…' : '-');
|
||||
// 与列表完全一致的格式函数
|
||||
const fmtTime = ts => ts ? new Date(ts*1000).toLocaleTimeString('zh-CN', {hour:'2-digit',minute:'2-digit',second:'2-digit'}) : '-';
|
||||
const fmtDur = () => {
|
||||
if (!t.started_at) return '-';
|
||||
const end = t.completed_at || (Date.now()/1000);
|
||||
const s = Math.round(end - t.started_at);
|
||||
const m = Math.floor(s/60), sec = s%60;
|
||||
const str = m > 0 ? `${m}m ${sec}s` : `${sec}s`;
|
||||
return t.completed_at ? str : `<span style="color:var(--warn)">${str}…</span>`;
|
||||
};
|
||||
|
||||
const modeLabel = { 'sttn-auto':'STTN 自动','sttn-det':'STTN','lama':'LaMa','propainter':'ProPainter','opencv':'OpenCV' };
|
||||
|
||||
const body = document.getElementById('detailBody');
|
||||
body.innerHTML = `
|
||||
@@ -1017,23 +1026,29 @@ function openDetail(id) {
|
||||
<div class="item-row">
|
||||
<span class="item-title" style="word-break:break-all">${esc(t.url)}</span>
|
||||
</div>
|
||||
<div class="subtle mono">${esc(t.id)}</div>
|
||||
<div class="subtle">算法: ${t.inpaint_mode} · 检测: ${t.detect_mode} · 耗时: ${dur}</div>
|
||||
${t.error ? `<div class="badge bad" style="align-self:start;word-break:break-all">${esc(t.error)}</div>` : ''}
|
||||
<div class="subtle mono" style="margin-top:2px">${esc(t.id)}</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(3,auto);gap:4px 20px;margin-top:8px;width:fit-content">
|
||||
<span class="subtle">创建时间</span><span class="subtle">开始处理</span><span class="subtle">耗时</span>
|
||||
<span style="font-size:13px">${fmtTime(t.created_at)}</span>
|
||||
<span style="font-size:13px">${fmtTime(t.started_at)}</span>
|
||||
<span style="font-size:13px">${fmtDur()}</span>
|
||||
</div>
|
||||
<div class="subtle" style="margin-top:6px">算法: ${modeLabel[t.inpaint_mode]||t.inpaint_mode} · 检测: ${t.detect_mode==='smart'?'水印模式':'文字 OCR'}</div>
|
||||
${t.error ? `<div class="badge bad" style="align-self:start;word-break:break-all;margin-top:4px">${esc(t.error)}</div>` : ''}
|
||||
${t.status==='downloading' ? `
|
||||
<div style="margin-top:4px">
|
||||
<div style="margin-top:8px">
|
||||
<div style="font-size:11px;color:var(--muted);margin-bottom:4px">下载进度 ${t.download_progress||0}%</div>
|
||||
<div class="prog-track"><div class="prog-fill dl" style="width:${t.download_progress||0}%"></div></div>
|
||||
</div>
|
||||
` : ''}
|
||||
${t.status==='processing' ? `
|
||||
<div style="margin-top:4px;display:grid;gap:5px">
|
||||
<div style="margin-top:8px;display:grid;gap:5px">
|
||||
<div class="phase-row"><span class="phase-label">检测</span><div class="phase-track"><div class="phase-fill detect" style="width:${t.detect_pct||0}%"></div></div><span class="phase-pct">${t.detect_pct||0}%</span></div>
|
||||
<div class="phase-row"><span class="phase-label">处理</span><div class="phase-track"><div class="phase-fill process" style="width:${t.process_pct||0}%"></div></div><span class="phase-pct">${t.process_pct||0}%</span></div>
|
||||
<div class="phase-row"><span class="phase-label">合并</span><div class="phase-track"><div class="phase-fill merge" style="width:${t.merge_pct||0}%"></div></div><span class="phase-pct">${t.merge_pct||0}%</span></div>
|
||||
</div>
|
||||
` : ''}
|
||||
<div style="display:flex;gap:8px;margin-top:4px;flex-wrap:wrap">
|
||||
<div style="display:flex;gap:8px;margin-top:10px;flex-wrap:wrap">
|
||||
${t.cache_path ? `
|
||||
<button class="button secondary" style="min-height:32px;padding:0 14px;font-size:13px"
|
||||
onclick="playVideo('${t.id}', 'source')">▶ 原视频</button>
|
||||
@@ -1052,7 +1067,7 @@ function openDetail(id) {
|
||||
background:#f7f9fc;border:1px solid var(--line);border-radius:var(--radius-sm);
|
||||
padding:12px 14px;max-height:240px;overflow-y:auto;
|
||||
font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.7;
|
||||
">${(t.logs||[]).map(l => `<div>${esc(l)}</div>`).join('') || '<div style="color:var(--muted)">暂无日志</div>'}</div>
|
||||
">${(t.logs||[]).map(l => `<div>${esc(l)}</div>`).join('') || '<div style="color:var(--muted)">暂无日志(点「日志」按钮从数据库加载完整记录)</div>'}</div>
|
||||
</div>
|
||||
`;
|
||||
openModal('modal-detail');
|
||||
|
||||
+17
-5
@@ -167,7 +167,9 @@ def init_db():
|
||||
output_path TEXT,
|
||||
error TEXT,
|
||||
platform_task_id INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at REAL,
|
||||
started_at REAL,
|
||||
completed_at REAL,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
@@ -186,9 +188,15 @@ def init_db():
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_task_logs_task_id ON task_logs(task_id)")
|
||||
for col in ("preview_mode", "detect_mode", "platform_task_id"):
|
||||
for col, default in [
|
||||
("preview_mode", "BOOLEAN DEFAULT 0"),
|
||||
("detect_mode", "TEXT DEFAULT 'text'"),
|
||||
("platform_task_id", "INTEGER"),
|
||||
("started_at", "REAL"),
|
||||
("completed_at", "REAL"),
|
||||
]:
|
||||
try:
|
||||
conn.execute(f"ALTER TABLE tasks ADD COLUMN {col} {'BOOLEAN DEFAULT 0' if col == 'preview_mode' else ('TEXT DEFAULT ' + repr('text') if col == 'detect_mode' else 'INTEGER')}")
|
||||
conn.execute(f"ALTER TABLE tasks ADD COLUMN {col} {default}")
|
||||
except Exception:
|
||||
pass
|
||||
conn.commit()
|
||||
@@ -281,8 +289,9 @@ def _save_task_to_db(task: dict):
|
||||
INSERT OR REPLACE INTO tasks
|
||||
(id, url, is_cache_file, cache_path, inpaint_mode, subtitle_areas,
|
||||
preview_mode, detect_mode, status, progress, download_progress,
|
||||
cached, output_path, error, platform_task_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
cached, output_path, error, platform_task_id,
|
||||
created_at, started_at, completed_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
task["id"], task["url"], task.get("is_cache_file", False),
|
||||
task.get("cache_path", ""), task["inpaint_mode"],
|
||||
@@ -290,6 +299,7 @@ def _save_task_to_db(task: dict):
|
||||
task.get("detect_mode", "text"), task["status"], task["progress"],
|
||||
task["download_progress"], task["cached"], task["output_path"],
|
||||
task["error"], task.get("platform_task_id"),
|
||||
task.get("created_at"), task.get("started_at"), task.get("completed_at"),
|
||||
))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
@@ -317,6 +327,8 @@ def _load_tasks_from_db():
|
||||
"download_progress": r["download_progress"],
|
||||
"cached": r["cached"], "output_path": r["output_path"],
|
||||
"error": r["error"], "platform_task_id": r.get("platform_task_id"),
|
||||
"created_at": r.get("created_at"), "started_at": r.get("started_at"),
|
||||
"completed_at": r.get("completed_at"),
|
||||
"logs": [],
|
||||
}
|
||||
with task_lock:
|
||||
|
||||
Reference in New Issue
Block a user