From 027970de29a47e74432baaf4089be2932e46469c Mon Sep 17 00:00:00 2001 From: aaron <> Date: Mon, 18 May 2026 20:07:05 +0800 Subject: [PATCH] 1 --- .env.example | 1 + app/config.py | 2 ++ app/server.py | 43 ++++++++++++++++++++++++++++++++++------ docker-compose.yml | 4 ++-- tests/test_dispatcher.py | 8 ++++++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index 5fc0d9e..e8d8222 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,7 @@ APP_HOST=0.0.0.0 APP_PORT=8030 DATABASE_PATH=data/dispatcher.db +TZ=Asia/Shanghai ADMIN_USERNAME=admin ADMIN_PASSWORD=12345678 diff --git a/app/config.py b/app/config.py index ac3b2af..d8f685d 100644 --- a/app/config.py +++ b/app/config.py @@ -18,6 +18,7 @@ class Settings: max_delivery_attempts: int = 3 retry_backoff_seconds: int = 60 feishu_timeout_seconds: int = 10 + timezone: str = "" def get_settings() -> Settings: @@ -33,4 +34,5 @@ def get_settings() -> Settings: max_delivery_attempts=int(os.getenv("MAX_DELIVERY_ATTEMPTS", "3")), retry_backoff_seconds=int(os.getenv("RETRY_BACKOFF_SECONDS", "60")), feishu_timeout_seconds=int(os.getenv("FEISHU_TIMEOUT_SECONDS", "10")), + timezone=os.getenv("APP_TIMEZONE") or os.getenv("TZ", ""), ) diff --git a/app/server.py b/app/server.py index 4bee7a0..4cbcfdd 100644 --- a/app/server.py +++ b/app/server.py @@ -6,11 +6,13 @@ import mimetypes import os import urllib.error import urllib.request +from datetime import datetime, timezone from http import HTTPStatus from http.cookies import SimpleCookie from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from typing import Any from urllib.parse import parse_qs, urlparse +from zoneinfo import ZoneInfo, ZoneInfoNotFoundError from app.auth import COOKIE_NAME, check_credentials, hash_password, is_valid_session, make_session_cookie from app.config import Settings, get_settings @@ -148,6 +150,33 @@ def render_pagination(base_path: str, active_tab: str, page: int, total: int, pa ) +def display_timezone(settings: Settings) -> timezone: + if settings.timezone: + try: + return ZoneInfo(settings.timezone) + except ZoneInfoNotFoundError: + return datetime.now().astimezone().tzinfo or timezone.utc + return datetime.now().astimezone().tzinfo or timezone.utc + + +def display_timezone_label(settings: Settings) -> str: + if settings.timezone: + return settings.timezone + return str(display_timezone(settings)) + + +def format_display_time(settings: Settings, value: str | None) -> str: + if not value: + return "" + try: + parsed = datetime.fromisoformat(value) + except ValueError: + return value + if parsed.tzinfo is None: + parsed = parsed.replace(tzinfo=timezone.utc) + return parsed.astimezone(display_timezone(settings)).strftime("%Y-%m-%d %H:%M:%S") + + class Handler(BaseHTTPRequestHandler): context: AppContext @@ -452,7 +481,7 @@ class Handler(BaseHTTPRequestHandler): ("Pending", counts["pending"]), ]) rows = "".join( - f"
结构化 alert 分发、飞书转发和重试状态。
| ID | 品种 | 周期 | 策略 | 状态 | 时间 |
|---|
{html.escape(raw_payload)}| ID | 品种 | 周期 | 策略 | 状态 | 错误 | 时间 | 原始 Alert |
|---|
| ID | Alert | 目标 | 状态 | 次数 | HTTP | 错误 | 下次重试 |
|---|
| ID | Alert | 目标 | 状态 | 次数 | HTTP | 发送时间 | 错误 | 下次重试 |
|---|
按类型查看 Alert 和分发记录,每页 {LOG_PAGE_SIZE} 条。
按类型查看 Alert 和分发记录,每页 {LOG_PAGE_SIZE} 条。当前显示时区:{timezone_label}。