fix: db.get_or_404 -> query.get_or_404 + rename to Palladium Monitor
- 修复删除快照时 AttributeError: SQLAlchemy.get_or_404 (低版本兼容) - UI/标题/邮件主题从 'Palladium Z1 Monitor' 改为 'Palladium Monitor'
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Palladium Z1 Monitor
|
# Palladium Monitor
|
||||||
|
|
||||||
LD 逻辑板使用监控系统 — 解析 `test_server -short` 输出,可视化展示 Palladium Z1 仿真器的逻辑板状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
LD 逻辑板使用监控系统 — 解析 `test_server -short` 输出,可视化展示 Palladium 仿真器的逻辑板状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ python3 app.py
|
|||||||
|
|
||||||
### 方式二:API 推送 (collect.py + 一键安装)
|
### 方式二:API 推送 (collect.py + 一键安装)
|
||||||
|
|
||||||
在 Palladium Z1 主机上部署采集 agent,**推荐**用一键脚本(处理 env 加载、crontab、依赖):
|
在 Palladium 主机上部署采集 agent,**推荐**用一键脚本(处理 env 加载、crontab、依赖):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 把 palladium-monitor/ 整个目录 scp 到 Z1 主机, 然后:
|
# 把 palladium-monitor/ 整个目录 scp 到 Z1 主机, 然后:
|
||||||
@@ -194,7 +194,7 @@ gunicorn --workers 2 --bind 0.0.0.0:5100 app:app
|
|||||||
| `SMTP_USE_TLS` | ❌ | `true` | 是否用 STARTTLS (端口 587 时设为 `true`) |
|
| `SMTP_USE_TLS` | ❌ | `true` | 是否用 STARTTLS (端口 587 时设为 `true`) |
|
||||||
| `SMTP_USE_SSL` | ❌ | `false` | 是否用隐式 SSL (端口 465 时设为 `true`) |
|
| `SMTP_USE_SSL` | ❌ | `false` | 是否用隐式 SSL (端口 465 时设为 `true`) |
|
||||||
| `MAIL_FROM` | 启用时必填 | — | 发件人邮箱 |
|
| `MAIL_FROM` | 启用时必填 | — | 发件人邮箱 |
|
||||||
| `MAIL_FROM_NAME` | ❌ | `Palladium Z1 Monitor` | 发件人显示名 |
|
| `MAIL_FROM_NAME` | ❌ | `Palladium Monitor` | 发件人显示名 |
|
||||||
| `MAIL_TO` | 启用时必填 | — | 收件人列表, 英文逗号分隔 (如 `alice@x.com,bob@y.com`) |
|
| `MAIL_TO` | 启用时必填 | — | 收件人列表, 英文逗号分隔 (如 `alice@x.com,bob@y.com`) |
|
||||||
| `MAIL_SEND_HOUR` | ❌ | `9` | 每天发送时间-小时 (0-23) |
|
| `MAIL_SEND_HOUR` | ❌ | `9` | 每天发送时间-小时 (0-23) |
|
||||||
| `MAIL_SEND_MINUTE` | ❌ | `0` | 每天发送时间-分钟 (0-59) |
|
| `MAIL_SEND_MINUTE` | ❌ | `0` | 每天发送时间-分钟 (0-59) |
|
||||||
@@ -251,7 +251,7 @@ ExecStart=/usr/bin/gunicorn --workers 2 --bind 0.0.0.0:5100 app:app
|
|||||||
#### 邮件内容示例
|
#### 邮件内容示例
|
||||||
|
|
||||||
每日报告包含:
|
每日报告包含:
|
||||||
- **主题**: `[Palladium Z1] 每日报告 YYYY-MM-DD — 利用率 X.X%`
|
- **主题**: `[Palladium] 每日报告 YYYY-MM-DD — 利用率 X.X%`
|
||||||
- **正文 (HTML + 纯文本)**: 系统信息 / 当前指标卡片 / 近 24h 趋势统计 + 样本柱状图 / 离线板列表 / 活跃作业列表
|
- **正文 (HTML + 纯文本)**: 系统信息 / 当前指标卡片 / 近 24h 趋势统计 + 样本柱状图 / 离线板列表 / 活跃作业列表
|
||||||
- **多部分**: 同时发 HTML 和纯文本, 邮件客户端自动选最合适的渲染
|
- **多部分**: 同时发 HTML 和纯文本, 邮件客户端自动选最合适的渲染
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Palladium Z1 Monitor — LD逻辑板使用监控系统
|
Palladium Monitor — LD逻辑板使用监控系统
|
||||||
|
|
||||||
解析 `test_server -short` 输出,展示 Palladium Z1 仿真器的
|
解析 `test_server -short` 输出,展示 Palladium 仿真器的
|
||||||
逻辑板 (LD) 状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
逻辑板 (LD) 状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
||||||
|
|
||||||
支持两种数据来源:
|
支持两种数据来源:
|
||||||
@@ -520,7 +520,7 @@ def history():
|
|||||||
@app.route("/snapshot/<int:sid>")
|
@app.route("/snapshot/<int:sid>")
|
||||||
def snapshot_detail(sid):
|
def snapshot_detail(sid):
|
||||||
"""单条快照详情。"""
|
"""单条快照详情。"""
|
||||||
snapshot = db.get_or_404(ScanSnapshot, sid)
|
snapshot = ScanSnapshot.query.get_or_404(sid)
|
||||||
stats = {
|
stats = {
|
||||||
"total_boards": snapshot.total_boards,
|
"total_boards": snapshot.total_boards,
|
||||||
"online_boards": snapshot.online_boards,
|
"online_boards": snapshot.online_boards,
|
||||||
@@ -681,7 +681,7 @@ def api_history():
|
|||||||
@app.route("/api/snapshot/<int:sid>/delete", methods=["POST"])
|
@app.route("/api/snapshot/<int:sid>/delete", methods=["POST"])
|
||||||
def delete_snapshot(sid):
|
def delete_snapshot(sid):
|
||||||
"""删除指定快照。"""
|
"""删除指定快照。"""
|
||||||
snapshot = db.get_or_404(ScanSnapshot, sid)
|
snapshot = ScanSnapshot.query.get_or_404(sid)
|
||||||
db.session.delete(snapshot)
|
db.session.delete(snapshot)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for("history"))
|
return redirect(url_for("history"))
|
||||||
@@ -1270,7 +1270,7 @@ if __name__ == "__main__":
|
|||||||
seed_sample_data()
|
seed_sample_data()
|
||||||
start_email_scheduler()
|
start_email_scheduler()
|
||||||
print("════════════════════════════════════════════════════════")
|
print("════════════════════════════════════════════════════════")
|
||||||
print(" Palladium Z1 Monitor")
|
print(" Palladium Monitor")
|
||||||
print(" http://0.0.0.0:5100")
|
print(" http://0.0.0.0:5100")
|
||||||
print("════════════════════════════════════════════════════════")
|
print("════════════════════════════════════════════════════════")
|
||||||
app.run(host="0.0.0.0", port=5100, debug=True)
|
app.run(host="0.0.0.0", port=5100, debug=True)
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
collect.py — Palladium Z1 远程数据采集推送脚本
|
collect.py — Palladium 远程数据采集推送脚本
|
||||||
|
|
||||||
在 Palladium Z1 主机上运行,执行 test_server -short 并将结果推送到监控服务器。
|
在 Palladium 主机上运行,执行 test_server -short 并将结果推送到监控服务器。
|
||||||
|
|
||||||
用法:
|
用法:
|
||||||
python3 collect.py # 默认配置
|
python3 collect.py # 默认配置
|
||||||
@@ -153,7 +153,7 @@ def push_to_monitor(url: str, raw_output: str, source: str,
|
|||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Palladium Z1 数据采集推送 (cron 友好, 带重试和日志)",
|
description="Palladium 数据采集推送 (cron 友好, 带重试和日志)",
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
)
|
)
|
||||||
parser.add_argument("--url", default=DEFAULT_URL,
|
parser.add_argument("--url", default=DEFAULT_URL,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
from typing import List, Dict, Tuple, Set, Any, Optional, Union
|
||||||
"""
|
"""
|
||||||
mailer.py — Palladium Z1 每日报告邮件发送
|
mailer.py — Palladium 每日报告邮件发送
|
||||||
|
|
||||||
通过 SMTP 把"今日快照 + 24h 趋势"汇总发送到指定邮箱。
|
通过 SMTP 把"今日快照 + 24h 趋势"汇总发送到指定邮箱。
|
||||||
所有配置都从环境变量读 (生产建议用 systemd EnvironmentFile 或 .env)。
|
所有配置都从环境变量读 (生产建议用 systemd EnvironmentFile 或 .env)。
|
||||||
@@ -79,7 +79,7 @@ def _build_config_from_env() -> dict:
|
|||||||
"smtp_use_tls": _bool("SMTP_USE_TLS", True),
|
"smtp_use_tls": _bool("SMTP_USE_TLS", True),
|
||||||
"smtp_use_ssl": _bool("SMTP_USE_SSL", False),
|
"smtp_use_ssl": _bool("SMTP_USE_SSL", False),
|
||||||
"from_addr": os.environ.get("MAIL_FROM", "").strip(),
|
"from_addr": os.environ.get("MAIL_FROM", "").strip(),
|
||||||
"from_name": os.environ.get("MAIL_FROM_NAME", "Palladium Z1 Monitor").strip(),
|
"from_name": os.environ.get("MAIL_FROM_NAME", "Palladium Monitor").strip(),
|
||||||
"to_addrs": [a.strip() for a in os.environ.get("MAIL_TO", "").split(",") if a.strip()],
|
"to_addrs": [a.strip() for a in os.environ.get("MAIL_TO", "").split(",") if a.strip()],
|
||||||
"send_hour": _int_env("MAIL_SEND_HOUR", 9),
|
"send_hour": _int_env("MAIL_SEND_HOUR", 9),
|
||||||
"send_minute": _int_env("MAIL_SEND_MINUTE", 0),
|
"send_minute": _int_env("MAIL_SEND_MINUTE", 0),
|
||||||
@@ -109,7 +109,7 @@ def _build_config_from_dict(raw: Dict[str, str]) -> dict:
|
|||||||
"smtp_use_tls": _b("smtp_use_tls", True),
|
"smtp_use_tls": _b("smtp_use_tls", True),
|
||||||
"smtp_use_ssl": _b("smtp_use_ssl", False),
|
"smtp_use_ssl": _b("smtp_use_ssl", False),
|
||||||
"from_addr": _s("from_addr"),
|
"from_addr": _s("from_addr"),
|
||||||
"from_name": _s("from_name") or "Palladium Z1 Monitor",
|
"from_name": _s("from_name") or "Palladium Monitor",
|
||||||
"to_addrs": [a.strip() for a in _s("to_addrs").split(",") if a.strip()],
|
"to_addrs": [a.strip() for a in _s("to_addrs").split(",") if a.strip()],
|
||||||
"send_hour": _i("send_hour", 9),
|
"send_hour": _i("send_hour", 9),
|
||||||
"send_minute": _i("send_minute", 0),
|
"send_minute": _i("send_minute", 0),
|
||||||
@@ -138,7 +138,7 @@ def save_config(data: dict) -> int:
|
|||||||
"smtp_use_tls": str(data.get("smtp_use_tls", True)).lower(),
|
"smtp_use_tls": str(data.get("smtp_use_tls", True)).lower(),
|
||||||
"smtp_use_ssl": str(data.get("smtp_use_ssl", False)).lower(),
|
"smtp_use_ssl": str(data.get("smtp_use_ssl", False)).lower(),
|
||||||
"from_addr": str(data.get("from_addr", "")).strip(),
|
"from_addr": str(data.get("from_addr", "")).strip(),
|
||||||
"from_name": str(data.get("from_name", "Palladium Z1 Monitor")).strip(),
|
"from_name": str(data.get("from_name", "Palladium Monitor")).strip(),
|
||||||
"to_addrs": to_addrs_str.strip(),
|
"to_addrs": to_addrs_str.strip(),
|
||||||
"send_hour": str(data.get("send_hour", 9)),
|
"send_hour": str(data.get("send_hour", 9)),
|
||||||
"send_minute": str(data.get("send_minute", 0)),
|
"send_minute": str(data.get("send_minute", 0)),
|
||||||
@@ -310,11 +310,11 @@ def _render_text(data: dict, base_url: str) -> str:
|
|||||||
"""纯文本版本 (HTML 不支持时回退)。"""
|
"""纯文本版本 (HTML 不支持时回退)。"""
|
||||||
latest = data["latest"]
|
latest = data["latest"]
|
||||||
if not latest:
|
if not latest:
|
||||||
return "Palladium Z1 Monitor — 当前无快照数据, 无法生成报告。\n"
|
return "Palladium Monitor — 当前无快照数据, 无法生成报告。\n"
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
title_date = _fmt_ts(latest.timestamp, "%Y-%m-%d")
|
title_date = _fmt_ts(latest.timestamp, "%Y-%m-%d")
|
||||||
lines.append(f"Palladium Z1 每日报告 — {title_date}")
|
lines.append(f"Palladium 每日报告 — {title_date}")
|
||||||
lines.append("=" * 60)
|
lines.append("=" * 60)
|
||||||
lines.append(f"生成时间: {_fmt_ts(data['now_utc'])} UTC")
|
lines.append(f"生成时间: {_fmt_ts(data['now_utc'])} UTC")
|
||||||
lines.append(f"快照时间: {_fmt_ts(latest.timestamp)}")
|
lines.append(f"快照时间: {_fmt_ts(latest.timestamp)}")
|
||||||
@@ -381,7 +381,7 @@ def _render_html(data: dict, base_url: str) -> str:
|
|||||||
if not latest:
|
if not latest:
|
||||||
return (
|
return (
|
||||||
'<html><body style="font-family:sans-serif;padding:20px">'
|
'<html><body style="font-family:sans-serif;padding:20px">'
|
||||||
'<h2>Palladium Z1 Monitor</h2>'
|
'<h2>Palladium Monitor</h2>'
|
||||||
'<p>当前无快照数据, 无法生成报告。</p>'
|
'<p>当前无快照数据, 无法生成报告。</p>'
|
||||||
'</body></html>'
|
'</body></html>'
|
||||||
)
|
)
|
||||||
@@ -475,7 +475,7 @@ def _render_html(data: dict, base_url: str) -> str:
|
|||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div style="background:linear-gradient(135deg,#007bff,#0056b3);color:#fff;padding:24px 28px">
|
<div style="background:linear-gradient(135deg,#007bff,#0056b3);color:#fff;padding:24px 28px">
|
||||||
<h1 style="margin:0;font-size:22px">⚡ Palladium Z1 每日报告</h1>
|
<h1 style="margin:0;font-size:22px">⚡ Palladium 每日报告</h1>
|
||||||
<div style="margin-top:6px;opacity:0.9;font-size:14px">{title_date}</div>
|
<div style="margin-top:6px;opacity:0.9;font-size:14px">{title_date}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ def _render_html(data: dict, base_url: str) -> str:
|
|||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<div style="background:#f8f9fa;padding:16px 28px;border-top:1px solid #e0e0e0;
|
<div style="background:#f8f9fa;padding:16px 28px;border-top:1px solid #e0e0e0;
|
||||||
font-size:12px;color:#888;text-align:center">
|
font-size:12px;color:#888;text-align:center">
|
||||||
由 <a href="{base_url}/" style="color:#007bff;text-decoration:none">Palladium Z1 Monitor</a> 自动生成 ·
|
由 <a href="{base_url}/" style="color:#007bff;text-decoration:none">Palladium Monitor</a> 自动生成 ·
|
||||||
{_fmt_ts(data['now_utc'], '%Y-%m-%d %H:%M:%S')} UTC
|
{_fmt_ts(data['now_utc'], '%Y-%m-%d %H:%M:%S')} UTC
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ def render_report(data: dict, cfg: dict) -> Tuple[str, str, str]:
|
|||||||
else:
|
else:
|
||||||
title_date = _fmt_ts(data["now_utc"], "%Y-%m-%d")
|
title_date = _fmt_ts(data["now_utc"], "%Y-%m-%d")
|
||||||
util = f"{latest.utilization:.1f}%" if latest else "—"
|
util = f"{latest.utilization:.1f}%" if latest else "—"
|
||||||
subject = f"[Palladium Z1] 每日报告 {title_date} — 利用率 {util}"
|
subject = f"[Palladium] 每日报告 {title_date} — 利用率 {util}"
|
||||||
html = _render_html(data, cfg["monitor_base_url"])
|
html = _render_html(data, cfg["monitor_base_url"])
|
||||||
text = _render_text(data, cfg["monitor_base_url"])
|
text = _render_text(data, cfg["monitor_base_url"])
|
||||||
return subject, html, text
|
return subject, html, text
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Palladium Z1 Monitor
|
# Palladium Monitor
|
||||||
|
|
||||||
LD 逻辑板使用监控系统 — 解析 `test_server -short` 输出,可视化展示 Palladium Z1 仿真器的逻辑板状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
LD 逻辑板使用监控系统 — 解析 `test_server -short` 输出,可视化展示 Palladium 仿真器的逻辑板状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Palladium Z1 Monitor — LD逻辑板使用监控系统
|
Palladium Monitor — LD逻辑板使用监控系统
|
||||||
|
|
||||||
解析 `test_server -short` 输出,展示 Palladium Z1 仿真器的
|
解析 `test_server -short` 输出,展示 Palladium 仿真器的
|
||||||
逻辑板 (LD) 状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
逻辑板 (LD) 状态、逻辑板利用率、作业信息和 T-Pod 可用性。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ def history():
|
|||||||
|
|
||||||
@app.route("/snapshot/<int:sid>")
|
@app.route("/snapshot/<int:sid>")
|
||||||
def snapshot_detail(sid):
|
def snapshot_detail(sid):
|
||||||
snapshot = db.get_or_404(ScanSnapshot, sid)
|
snapshot = ScanSnapshot.query.get_or_404(sid)
|
||||||
stats = _snapshot_stats(snapshot)
|
stats = _snapshot_stats(snapshot)
|
||||||
racks_data = _build_racks(sid)
|
racks_data = _build_racks(sid)
|
||||||
jobs_data = JobInfo.query.filter_by(snapshot_id=sid).all()
|
jobs_data = JobInfo.query.filter_by(snapshot_id=sid).all()
|
||||||
@@ -434,7 +434,7 @@ def api_history():
|
|||||||
|
|
||||||
@app.route("/api/snapshot/<int:sid>/delete", methods=["POST"])
|
@app.route("/api/snapshot/<int:sid>/delete", methods=["POST"])
|
||||||
def delete_snapshot(sid):
|
def delete_snapshot(sid):
|
||||||
snapshot = db.get_or_404(ScanSnapshot, sid)
|
snapshot = ScanSnapshot.query.get_or_404(sid)
|
||||||
db.session.delete(snapshot)
|
db.session.delete(snapshot)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for("history"))
|
return redirect(url_for("history"))
|
||||||
@@ -627,7 +627,7 @@ if __name__ == "__main__":
|
|||||||
db.create_all()
|
db.create_all()
|
||||||
seed_sample_data()
|
seed_sample_data()
|
||||||
print("════════════════════════════════════════════════════════")
|
print("════════════════════════════════════════════════════════")
|
||||||
print(" Palladium Z1 Monitor")
|
print(" Palladium Monitor")
|
||||||
print(" http://0.0.0.0:5100")
|
print(" http://0.0.0.0:5100")
|
||||||
print("════════════════════════════════════════════════════════")
|
print("════════════════════════════════════════════════════════")
|
||||||
app.run(host="0.0.0.0", port=5100, debug=True)
|
app.run(host="0.0.0.0", port=5100, debug=True)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
# collect.sh — Palladium Z1 数据采集脚本 (Shell 版, 无需 Python)
|
# collect.sh — Palladium 数据采集脚本 (Shell 版, 无需 Python)
|
||||||
#
|
#
|
||||||
# 在 Palladium 主机上运行, 执行 test_server -short 并推送到监控服务器
|
# 在 Palladium 主机上运行, 执行 test_server -short 并推送到监控服务器
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% block title %}Palladium Z1 Monitor{% endblock %}</title>
|
<title>{% block title %}Palladium Monitor{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<nav class="topnav">
|
<nav class="topnav">
|
||||||
<div class="nav-brand">
|
<div class="nav-brand">
|
||||||
<span class="nav-logo">⚡</span>
|
<span class="nav-logo">⚡</span>
|
||||||
<span class="nav-title">Palladium Z1 Monitor</span>
|
<span class="nav-title">Palladium Monitor</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="{{ url_for('dashboard') }}" class="{% if request.endpoint == 'dashboard' %}active{% endif %}">仪表板</a>
|
<a href="{{ url_for('dashboard') }}" class="{% if request.endpoint == 'dashboard' %}active{% endif %}">仪表板</a>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p class="modal-hint">在 Palladium 主机执行 <code>test_server -short</code>,将输出粘贴到下方:</p>
|
<p class="modal-hint">在 Palladium 主机执行 <code>test_server -short</code>,将输出粘贴到下方:</p>
|
||||||
<textarea name="raw_output" rows="20" class="paste-textarea"
|
<textarea name="raw_output" rows="20" class="paste-textarea"
|
||||||
placeholder="Emulator: sc01_emu Hardware: Palladium Z1 ..."></textarea>
|
placeholder="Emulator: sc01_emu Hardware: Palladium ..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closePasteModal()">取消</button>
|
<button type="button" class="btn btn-secondary" onclick="closePasteModal()">取消</button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}仪表板 — Palladium Z1 Monitor{% endblock %}
|
{% block title %}仪表板 — Palladium Monitor{% endblock %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}历史记录 — Palladium Z1 Monitor{% endblock %}
|
{% block title %}历史记录 — Palladium Monitor{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>📅 历史快照</h2>
|
<h2>📅 历史快照</h2>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}快照 #{{ snapshot.id }} — Palladium Z1 Monitor{% endblock %}
|
{% block title %}快照 #{{ snapshot.id }} — Palladium Monitor{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="snapshot-header">
|
<div class="snapshot-header">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/* ═══════════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
Palladium Z1 Monitor — Dark Theme Dashboard
|
Palladium Monitor — Dark Theme Dashboard
|
||||||
═══════════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════════ */
|
||||||
:root {
|
:root {
|
||||||
--bg-primary: #0d1117;
|
--bg-primary: #0d1117;
|
||||||
|
|||||||
+3
-3
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% block title %}Palladium Z1 Monitor{% endblock %}</title>
|
<title>{% block title %}Palladium Monitor{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<nav class="topnav">
|
<nav class="topnav">
|
||||||
<div class="nav-brand">
|
<div class="nav-brand">
|
||||||
<span class="nav-logo">⚡</span>
|
<span class="nav-logo">⚡</span>
|
||||||
<span class="nav-title">Palladium Z1 Monitor</span>
|
<span class="nav-title">Palladium Monitor</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="{{ url_for('dashboard') }}" class="{% if request.endpoint == 'dashboard' %}active{% endif %}">仪表板</a>
|
<a href="{{ url_for('dashboard') }}" class="{% if request.endpoint == 'dashboard' %}active{% endif %}">仪表板</a>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p class="modal-hint">在 Palladium 主机执行 <code>test_server -short</code>,将输出粘贴到下方:</p>
|
<p class="modal-hint">在 Palladium 主机执行 <code>test_server -short</code>,将输出粘贴到下方:</p>
|
||||||
<textarea name="raw_output" rows="20" class="paste-textarea"
|
<textarea name="raw_output" rows="20" class="paste-textarea"
|
||||||
placeholder="Emulator: sc01_emu Hardware: Palladium Z1 ..."></textarea>
|
placeholder="Emulator: sc01_emu Hardware: Palladium ..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" onclick="closePasteModal()">取消</button>
|
<button type="button" class="btn btn-secondary" onclick="closePasteModal()">取消</button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}仪表板 — Palladium Z1 Monitor{% endblock %}
|
{% block title %}仪表板 — Palladium Monitor{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}邮件配置 — Palladium Z1 Monitor{% endblock %}
|
{% block title %}邮件配置 — Palladium Monitor{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cfg_from_name">发件人名称</label>
|
<label for="cfg_from_name">发件人名称</label>
|
||||||
<input type="text" id="cfg_from_name" placeholder="Palladium Z1 Monitor">
|
<input type="text" id="cfg_from_name" placeholder="Palladium Monitor">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}历史记录 — Palladium Z1 Monitor{% endblock %}
|
{% block title %}历史记录 — Palladium Monitor{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}快照 #{{ snapshot.id }} — Palladium Z1 Monitor{% endblock %}
|
{% block title %}快照 #{{ snapshot.id }} — Palladium Monitor{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="snapshot-header">
|
<div class="snapshot-header">
|
||||||
|
|||||||
Reference in New Issue
Block a user