fix: 活跃作业从 DomainDetail 回退统计 + 修复 Gmail 嵌套 div 进度条
1. Z1 详细输出把作业存在 DomainDetail 而非 JobInfo, 增加回退逻辑 按 (owner, pid, design) 去重统计活跃作业数 2. 移除利用率进度条的嵌套 div (Gmail 会过滤导致后续内容丢失) 改为单元素蓝色进度条 3. 活跃作业卡片显示实际统计数而非 Snapshot 缓存值
This commit is contained in:
@@ -254,6 +254,35 @@ def collect_report_data() -> dict:
|
||||
# ── 活跃作业 ──
|
||||
jobs_active = JobInfo.query.filter_by(snapshot_id=latest.id).order_by(JobInfo.job_index).all()
|
||||
|
||||
# Z1 详细输出把作业信息存在 DomainDetail 里, 若 JobInfo 为空则从 DomainDetail 回退
|
||||
if not jobs_active:
|
||||
try:
|
||||
from app import DomainDetail
|
||||
domain_rows = DomainDetail.query.filter_by(snapshot_id=latest.id).all()
|
||||
if domain_rows:
|
||||
# 按 (owner, pid, design) 去重统计活跃作业数
|
||||
active_set = set()
|
||||
for dr in domain_rows:
|
||||
owner = dr.owner or ""
|
||||
pid = dr.pid or ""
|
||||
if owner and owner not in ("NONE", "") and pid and pid not in ("0", ""):
|
||||
active_set.add((owner, pid, dr.design or "—", dr.t_pod or "—"))
|
||||
if active_set:
|
||||
# 构造虚拟 job 对象供渲染 (兼容 jobs_active 格式)
|
||||
class _VJob:
|
||||
pass
|
||||
for idx, (o, p, design, tpod) in enumerate(sorted(active_set), 1):
|
||||
j = _VJob()
|
||||
j.job_index = idx
|
||||
j.owner = o
|
||||
j.pid = p
|
||||
j.t_pod = tpod
|
||||
j.design = design
|
||||
j.elap_time = ""
|
||||
jobs_active.append(j)
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
# ── 24h 统计 ──
|
||||
snaps_24h = ScanSnapshot.query.filter(
|
||||
ScanSnapshot.timestamp >= cutoff_24h
|
||||
@@ -543,10 +572,8 @@ def _render_html(data: dict, base_url: str) -> str:
|
||||
f'<tr><td style="padding:4px 12px;font-family:monospace">{_fmt_ts(smp.timestamp, "%m-%d %H:%M")}</td>'
|
||||
f'<td style="padding:4px 12px;text-align:right;font-weight:bold">{smp.utilization:.1f}%</td>'
|
||||
f'<td style="padding:4px 12px">'
|
||||
f'<div style="background:#e0e0e0;height:14px;width:200px;border-radius:2px">'
|
||||
f'<div style="background:{DOMAIN_COLORS.get("downloaded", "#007bff")};'
|
||||
f'height:14px;width:{min(smp.utilization, 100):.1f}%;border-radius:2px"></div>'
|
||||
f'</div></td></tr>'
|
||||
f'<span style="background:#007bff;color:#fff;padding:2px 6px;border-radius:2px;font-size:11px;font-weight:bold">{smp.utilization:.1f}%</span>'
|
||||
f'</td></tr>'
|
||||
for smp in data["samples_24h"]
|
||||
)
|
||||
trend_html = f"""
|
||||
@@ -607,14 +634,12 @@ def _render_html(data: dict, base_url: str) -> str:
|
||||
<div style="flex:1;min-width:200px;background:#f8f9fa;padding:14px;border-radius:6px;border-left:4px solid {DOMAIN_COLORS.get('downloaded')}">
|
||||
<div style="color:#888;font-size:12px">逻辑板利用率</div>
|
||||
<div style="font-size:24px;font-weight:bold;margin-top:4px;color:#007bff">{latest.utilization:.1f}%</div>
|
||||
<div style="background:#e0e0e0;height:8px;border-radius:4px;margin-top:6px">
|
||||
<div style="background:{DOMAIN_COLORS.get('downloaded')};height:8px;width:{util_bar_width};border-radius:4px"></div>
|
||||
</div>
|
||||
<div style="background:#007bff;height:8px;border-radius:4px;margin-top:6px;width:{util_bar_width}"></div>
|
||||
<div style="font-size:12px;margin-top:4px">使用 {latest.used_boards} / 空闲 {latest.online_boards - latest.used_boards}</div>
|
||||
</div>
|
||||
<div style="flex:1;min-width:140px;background:#f8f9fa;padding:14px;border-radius:6px;border-left:4px solid #28a745">
|
||||
<div style="color:#888;font-size:12px">活跃作业</div>
|
||||
<div style="font-size:24px;font-weight:bold;margin-top:4px">{latest.active_jobs}</div>
|
||||
<div style="font-size:24px;font-weight:bold;margin-top:4px">{len(data.get('jobs_active', []))}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user