diff --git a/app/services/task_service.py b/app/services/task_service.py index ad12a18..42809ad 100644 --- a/app/services/task_service.py +++ b/app/services/task_service.py @@ -3,6 +3,7 @@ import json from concurrent.futures import ThreadPoolExecutor from collections.abc import Callable from datetime import UTC, datetime +from zoneinfo import ZoneInfo from sqlalchemy import func, select from sqlalchemy.orm import Session, sessionmaker @@ -22,6 +23,7 @@ RUNNING_TASK_MESSAGE = "当前有正在运行的任务,请稍后再试" RESTART_ERROR_MESSAGE = "系统重启,任务被中断" STALE_PROGRESS_THRESHOLD_SECONDS = 10 * 60 STALE_PROGRESS_ERROR_TYPE = "stale_progress_timeout" +DISPLAY_TIMEZONE = ZoneInfo("Asia/Shanghai") task_executor = ThreadPoolExecutor(max_workers=1) @@ -227,7 +229,7 @@ def calculate_task_display_number(session: Session, task: Task) -> int: def format_datetime_minute(value: datetime | None) -> str: value = ensure_utc_datetime(value) - return value.strftime("%Y-%m-%d %H:%M") if value else "" + return value.astimezone(DISPLAY_TIMEZONE).strftime("%Y-%m-%d %H:%M") if value else "" def build_task_error_summary(task: Task) -> str | None: diff --git a/app/templates/index.html b/app/templates/index.html index 1d7ac51..481fdf3 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -56,7 +56,7 @@

任务历史

-

最近任务与 Demo 数据

+

最近任务

{% if has_running_tasks %}自动更新中{% endif %}
diff --git a/app/templates/partials/task_rows.html b/app/templates/partials/task_rows.html index 6fe1cb6..efd1832 100644 --- a/app/templates/partials/task_rows.html +++ b/app/templates/partials/task_rows.html @@ -5,9 +5,6 @@ {{ task.display_id or loop.index }} - {% if task.is_demo %} -
Demo 数据 - {% endif %} {{ task.platform | platform_label }} {{ task.created_at_label }} diff --git a/app/templates/tasks/detail.html b/app/templates/tasks/detail.html index 09bbe2a..2744221 100644 --- a/app/templates/tasks/detail.html +++ b/app/templates/tasks/detail.html @@ -20,7 +20,7 @@ {% set ai_percent = rate_percent(task.analysis_success_rate) %} {% set target_comments = task.hotspot_limit * task.item_limit_per_hotspot * task.comment_limit_per_item %}
-

平台:{{ task.platform | platform_label }}{% if task.is_demo %}Demo 数据{% endif %}

+

平台:{{ task.platform | platform_label }}

创建时间 {{ task.created_at_label }} · 阶段 {{ task.current_stage_label or "等待启动" }}

diff --git a/tests/integration/test_routes.py b/tests/integration/test_routes.py index 76f44a2..6bc3e7b 100644 --- a/tests/integration/test_routes.py +++ b/tests/integration/test_routes.py @@ -107,8 +107,9 @@ def test_index_page_uses_short_task_numbers_compact_fields_and_friendly_error_co assert "#" not in visible_text assert first_id not in visible_text assert second_id not in visible_text - assert "2026-07-03 10:30" in visible_text - assert "2026-07-03 10:35" in visible_text + assert "2026-07-03 18:30" in visible_text + assert "2026-07-03 18:35" in visible_text + assert "Demo 数据" not in visible_text assert "5热点 × 5内容 × 50评论" in visible_text assert "1热点 × 1内容 × 10评论" in visible_text assert "小红书 · 5热点" not in visible_text @@ -207,7 +208,38 @@ def test_task_detail_uses_short_number_title_and_hides_full_uuid(): assert task_id not in visible_text assert "任务 #33333333-3333-4333-8333-333333333333" not in visible_text assert "#" not in visible_text - assert "创建时间 2026-07-03 10:30" in visible_text + assert "创建时间 2026-07-03 18:30" in visible_text + assert "Demo 数据" not in visible_text + + +def test_demo_task_flag_is_kept_but_demo_copy_is_hidden_from_pages(): + with make_test_client() as (client, engine): + from sqlalchemy.orm import Session + + with Session(engine) as session: + session.add( + Task( + id="demo-task-hidden-copy", + platform="xiaohongshu", + status="success", + created_at=datetime(2026, 7, 3, 10, 30, tzinfo=UTC), + hotspot_limit=1, + item_limit_per_hotspot=1, + comment_limit_per_item=10, + ) + ) + session.commit() + + index_response = client.get("/") + detail_response = client.get("/tasks/demo-task-hidden-copy") + api_response = client.get("/api/tasks/demo-task-hidden-copy") + + assert index_response.status_code == 200 + assert detail_response.status_code == 200 + assert api_response.status_code == 200 + assert api_response.json()["is_demo"] is True + assert "Demo 数据" not in BeautifulSoup(index_response.text, "html.parser").get_text(" ") + assert "Demo 数据" not in BeautifulSoup(detail_response.text, "html.parser").get_text(" ") def test_running_task_detail_page_keeps_polling_after_hotspots_exist():