diff --git a/app/server.py b/app/server.py
index d98a2ec..73c471b 100644
--- a/app/server.py
+++ b/app/server.py
@@ -565,17 +565,29 @@ class Handler(BaseHTTPRequestHandler):
def render_logs(self) -> None:
logs = self.list_logs()
- alert_rows = "".join(
- f"
| {row['id']} | {html.escape(row['symbol'])} | {html.escape(row['timeframe'])} | {html.escape(row['strategy'])} | {html.escape(row['status'])} | {html.escape(row['error'] or '')} | {row['created_at']} |
"
- for row in logs["alerts"]
- )
+ alert_rows = ""
+ for row in logs["alerts"]:
+ try:
+ raw_payload = json.dumps(json.loads(row["payload"]), ensure_ascii=False, indent=2)
+ except Exception:
+ raw_payload = row["payload"] or ""
+ alert_rows += f"""
+| {row['id']} |
+{html.escape(row['symbol'])} |
+{html.escape(row['timeframe'])} |
+{html.escape(row['strategy'])} |
+{html.escape(row['status'])} |
+{html.escape(row['error'] or '')} |
+{row['created_at']} |
+查看{html.escape(raw_payload)} |
+
"""
delivery_rows = "".join(
f"| {row['id']} | {row['alert_id']} | {html.escape(row['target_name'])} | {html.escape(row['status'])} | {row['attempts']} | {html.escape(str(row['response_code'] or ''))} | {html.escape(row['error'] or '')} | {html.escape(row['next_attempt_at'] or '')} |
"
for row in logs["deliveries"]
)
body = f"""
-Alert 日志
| ID | 品种 | 周期 | 策略 | 状态 | 错误 | 时间 |
{alert_rows}
+Alert 日志
| ID | 品种 | 周期 | 策略 | 状态 | 错误 | 时间 | 原始 Alert |
{alert_rows}
Delivery 日志
| ID | Alert | 目标 | 状态 | 次数 | HTTP | 错误 | 下次重试 |
{delivery_rows}
"""
self.send_html("日志", body)
diff --git a/app/static/styles.css b/app/static/styles.css
index 958418e..68ae4f4 100644
--- a/app/static/styles.css
+++ b/app/static/styles.css
@@ -364,6 +364,18 @@ pre {
color: #f7f1e4;
}
+.payload-details summary {
+ cursor: pointer;
+ color: var(--accent);
+ font-weight: 800;
+}
+
+.payload-details pre {
+ width: min(620px, 70vw);
+ max-height: 360px;
+ margin: 10px 0 0;
+}
+
.inline {
display: inline;
}