diff --git a/admin/dashboard/blueprints/plugin_schedules.py b/admin/dashboard/blueprints/plugin_schedules.py index 8e20734..aed8c00 100644 --- a/admin/dashboard/blueprints/plugin_schedules.py +++ b/admin/dashboard/blueprints/plugin_schedules.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from datetime import datetime from flask import Blueprint, current_app, jsonify, render_template, request from .auth import login_required @@ -7,6 +8,25 @@ from .auth import login_required plugin_schedules_bp = Blueprint("plugin_schedules", __name__, url_prefix="/plugin_schedules") +def _normalize_datetime_text(value): + """统一时间文本格式为 `YYYY-MM-DD HH:MM:SS`。 + + 兼容场景: + 1. 数据库返回 datetime 对象; + 2. 已经是 ISO 字符串(包含 T); + 3. 兜底保留原值字符串,避免因为解析失败把数据抹掉。 + """ + if value is None: + return value + if isinstance(value, datetime): + return value.strftime("%Y-%m-%d %H:%M:%S") + text = str(value) + # 先处理常见 ISO 格式,直接去掉 T 并截到秒,避免前端显示异常。 + if "T" in text: + return text.replace("T", " ")[:19] + return text + + @plugin_schedules_bp.route("/") @login_required def page_plugin_schedules(): @@ -18,6 +38,11 @@ def page_plugin_schedules(): def api_list_schedules(): server = current_app.dashboard_server data = server.plugin_schedule_manager.list_schedules_with_runtime() + # 后端统一格式化时间字段,避免前端出现 Fri, 17 Apr 2026 ... 这类 RFC 时间串。 + for row in data: + for key in ("next_run_at", "last_run_at", "created_at", "updated_at"): + if key in row: + row[key] = _normalize_datetime_text(row.get(key)) return jsonify({"success": True, "data": data}) @@ -74,6 +99,10 @@ def api_schedule_logs(schedule_id: int): server = current_app.dashboard_server limit = int(request.args.get("limit", 100)) logs = server.plugin_schedule_manager.get_logs(schedule_id, limit=limit) + # 日志时间统一成固定格式,避免被 Flask JSON 序列化成 RFC 字符串。 + for row in logs: + if "triggered_at" in row: + row["triggered_at"] = _normalize_datetime_text(row.get("triggered_at")) return jsonify({"success": True, "data": logs})