feat: 邮件报告增加用户-LD 板使用统计

- 在 _collect_report_data 中聚合 DomainDetail 按用户统计 LD 板使用
- 纯文本版新增【用户-LD 板统计】版块 (用户/LD板/Rack/T-Pod/设计)
- HTML 版新增紫色标题表格, 紫色徽章显示 LD 数
- 自动过滤 NONE/UNOWNED/FREE/AVAILABLE 等无主域
- 过滤 T-Pod 占位符 '--' (包括 '24 --' 含 -- 的值)
This commit is contained in:
Your Name
2026-07-17 12:39:38 +08:00
parent b5205d0543
commit 07867eaefc
+94
View File
@@ -286,12 +286,63 @@ def collect_report_data() -> dict:
stats_24h = None
samples_24h = []
# ── 按用户聚合 LD 板使用 ──
user_board_agg = []
try:
from app import DomainDetail
domain_rows = DomainDetail.query.filter_by(
snapshot_id=latest.id
).all()
if domain_rows:
# 按用户聚合: 统计每用户用了多少块不同 LD
user_boards: dict[str, dict] = {}
for dr in domain_rows:
owner = dr.owner or ""
if not owner or owner.upper() in ("NONE", "UNOWNED", "FREE", "AVAILABLE"):
continue
board_key = (dr.rack, dr.cluster, dr.ld_index)
if owner not in user_boards:
user_boards[owner] = {
"user": owner,
"boards": set(),
"racks": set(),
"pods": set(),
"designs": set(),
}
entry = user_boards[owner]
entry["boards"].add(board_key)
if dr.rack is not None:
entry["racks"].add(dr.rack)
t_pod = dr.t_pod or ""
# 过滤占位符 "--" (包括 "24 --" 这种含 -- 的)
if t_pod and "--" not in t_pod and t_pod.strip() != "":
entry["pods"].add(t_pod)
design = dr.design or ""
if design:
entry["designs"].add(design)
# 转为列表并排序 (按 LD 数降序)
for owner, info in user_boards.items():
boards_sorted = sorted(info["boards"], key=lambda x: (x[0], x[1], x[2]))
user_board_agg.append({
"user": owner,
"ld_count": len(boards_sorted),
"boards": ", ".join(f"R{b[0]}C{b[1]}LD{b[2]}" for b in boards_sorted),
"racks": ", ".join(str(r) for r in sorted(info["racks"])) if info["racks"] else "",
"pods": ", ".join(sorted(info["pods"])) if info["pods"] else "",
"designs": "; ".join(sorted(info["designs"])) if info["designs"] else "",
})
user_board_agg.sort(key=lambda x: (-x["ld_count"], x["user"]))
except (ImportError, AttributeError):
pass
return {
"latest": latest,
"boards_offline": boards_offline,
"jobs_active": jobs_active,
"stats_24h": stats_24h,
"samples_24h": samples_24h,
"user_board_agg": user_board_agg,
"now_utc": now,
"now_local": datetime.now(),
}
@@ -349,6 +400,20 @@ def _render_text(data: dict, base_url: str) -> str:
lines.append(f" 活跃作业: {latest.active_jobs}")
lines.append("")
# 用户-LD 板统计
if data.get("user_board_agg"):
lines.append("【用户-LD 板统计】")
for ub in data["user_board_agg"]:
lines.append(f" {ub['user']}: {ub['ld_count']} 块 LD")
lines.append(f" LD 板: {ub['boards']}")
if ub["racks"] != "":
lines.append(f" Rack: {ub['racks']}")
if ub["pods"] != "":
lines.append(f" T-Pod: {ub['pods']}")
if ub["designs"] != "":
lines.append(f" 设计: {ub['designs']}")
lines.append("")
# 24h 趋势
if data["stats_24h"]:
s = data["stats_24h"]
@@ -443,6 +508,32 @@ def _render_html(data: dict, base_url: str) -> str:
else:
jobs_html = '<p style="color:#888;margin:6px 0">无活跃作业</p>'
# 用户-LD 板统计 HTML
user_board_html = ""
if data.get("user_board_agg"):
ub_rows = "".join(
f'<tr style="border-bottom:1px solid #e9ecef">'
f'<td style="padding:6px 12px;font-family:monospace;font-weight:bold;color:#6f42c1">{ub["user"]}</td>'
f'<td style="padding:6px 12px;text-align:center"><span style="background:#6f42c1;color:#fff;padding:2px 8px;border-radius:10px;font-size:12px;font-weight:bold">{ub["ld_count"]}</span></td>'
f'<td style="padding:6px 12px;font-family:monospace;font-size:13px">{ub["racks"]}</td>'
f'<td style="padding:6px 12px;font-family:monospace;font-size:13px">{ub["pods"]}</td>'
f'<td style="padding:6px 12px;font-size:13px;color:#555">{ub["designs"]}</td>'
f'</tr>'
for ub in data["user_board_agg"]
)
user_board_html = f"""
<h2 style="font-size:16px;margin:20px 0 10px;color:#555">👤 用户-LD 板统计</h2>
<table style="border-collapse:collapse;width:100%;margin-top:6px">
<thead><tr style="background:#6f42c1;color:#fff">
<th style="padding:6px 12px;text-align:left">用户</th>
<th style="padding:6px 12px;text-align:center">LD 数</th>
<th style="padding:6px 12px;text-align:left">Rack</th>
<th style="padding:6px 12px;text-align:left">T-Pod</th>
<th style="padding:6px 12px;text-align:left">设计</th>
</tr></thead>
<tbody>{ub_rows}</tbody>
</table>"""
# 24h 趋势 HTML
if data["stats_24h"]:
s = data["stats_24h"]
@@ -526,6 +617,9 @@ def _render_html(data: dict, base_url: str) -> str:
</div>
</div>
<!-- 用户-LD 板统计 -->
{user_board_html}
<!-- 24h 趋势 -->
<h2 style="font-size:16px;margin:20px 0 10px;color:#555">📈 近 24 小时趋势</h2>
{trend_html}