feat: 优化页面信息展示

This commit is contained in:
meijiali
2026-07-03 18:20:20 +08:00
parent 9244f360be
commit 2dc8ca1b5b
9 changed files with 163 additions and 18 deletions
+5
View File
@@ -34,6 +34,11 @@ class TaskResponse(BaseModel):
current_stage: str | None = None
current_stage_label: str | None = None
last_progress_at: datetime | None = None
display_number: int = 0
display_id: str = ""
created_at_label: str = ""
scale_label: str = ""
error_summary: str | None = None
running_seconds: int = 0
seconds_since_last_progress: int | None = None
running_duration_label: str = "刚刚"
+36
View File
@@ -34,6 +34,10 @@ STAGE_LABELS = {
"success": "已完成",
"failed": "失败",
}
PLATFORM_LABELS = {
"xiaohongshu": "小红书",
"douyin": "抖音",
}
def has_running_task(session: Session) -> bool:
@@ -150,6 +154,15 @@ def get_task(session: Session, task_id: str) -> Task | None:
def hydrate_task_progress(session: Session, task: Task) -> Task:
display_number = calculate_task_display_number(session, task)
task.display_number = display_number
task.display_id = f"#{display_number}"
task.created_at_label = format_datetime_minute(task.created_at)
task.scale_label = (
f"{PLATFORM_LABELS.get(task.platform, task.platform)} · "
f"{task.hotspot_limit}热点 × {task.item_limit_per_hotspot}内容 × {task.comment_limit_per_item}评论"
)
task.error_summary = build_task_error_summary(task)
task.hotspots_count = session.scalar(select(func.count(Hotspot.id)).where(Hotspot.task_id == task.id)) or 0
task.comments_count = session.scalar(select(func.count(Comment.id)).where(Comment.task_id == task.id)) or 0
task.reports_count = session.scalar(select(func.count(Report.id)).where(Report.task_id == task.id)) or 0
@@ -182,6 +195,29 @@ def hydrate_task_progress(session: Session, task: Task) -> Task:
return task
def calculate_task_display_number(session: Session, task: Task) -> int:
task_ids = list(session.scalars(select(Task.id).order_by(Task.created_at, Task.id)))
try:
return task_ids.index(task.id) + 1
except ValueError:
return len(task_ids) + 1
def format_datetime_minute(value: datetime | None) -> str:
value = ensure_utc_datetime(value)
return value.strftime("%Y-%m-%d %H:%M") if value else ""
def build_task_error_summary(task: Task) -> str | None:
if task.error_message:
return task.error_message
if task.error_stage == "system" and task.error_type == "unexpected_restart":
return RESTART_ERROR_MESSAGE
if task.error_stage or task.error_type:
return "任务失败,请查看后端日志"
return None
def format_duration_zh(total_seconds: int | None) -> str:
if total_seconds is None:
return "暂无记录"
-3
View File
@@ -28,8 +28,5 @@
{% endblock %}
{% block content %}{% endblock %}
</main>
<footer class="border-top py-3">
<div class="container text-muted small">内部演示工具 | 仅供学习参考</div>
</footer>
</body>
</html>
+1 -1
View File
@@ -3,7 +3,7 @@
{% block breadcrumbs %}
<nav aria-label="breadcrumb"><ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">首页</a></li>
<li class="breadcrumb-item"><a href="/tasks/{{ task.id }}">任务 #{{ task.id }}</a></li>
<li class="breadcrumb-item"><a href="/tasks/{{ task.id }}">任务 {{ task.display_id }}</a></li>
<li class="breadcrumb-item active">汇总报告</li>
</ol></nav>
{% endblock %}
+1 -1
View File
@@ -3,7 +3,7 @@
{% block breadcrumbs %}
<nav aria-label="breadcrumb"><ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">首页</a></li>
<li class="breadcrumb-item"><a href="/tasks/{{ task.id }}">任务 #{{ task.id }}</a></li>
<li class="breadcrumb-item"><a href="/tasks/{{ task.id }}">任务 {{ task.display_id }}</a></li>
<li class="breadcrumb-item"><a href="/hotspots/{{ hotspot.id }}/report">热点 #{{ hotspot.rank }}{{ hotspot.title }}</a></li>
<li class="breadcrumb-item active">{{ item.title or item.source_item_id }}</li>
</ol></nav>
+5 -8
View File
@@ -4,14 +4,14 @@
{% set ai_percent = rate_percent(task.analysis_success_rate) %}
<tr>
<td>
<code>{{ task.id }}</code>
<strong>{{ task.display_id or ("#" ~ loop.index) }}</strong>
{% if task.is_demo %}
<br><span class="badge text-bg-info">Demo 数据</span>
{% endif %}
</td>
<td>{{ task.platform | platform_label }}</td>
<td>{{ task.created_at }}</td>
<td><small class="text-muted">热点 {{ task.hotspot_limit }} / 内容 {{ task.item_limit_per_hotspot }} / 评论 {{ task.comment_limit_per_item }}</small></td>
<td>{{ task.created_at_label }}</td>
<td><small class="text-muted">{{ task.scale_label }}</small></td>
<td class="task-progress-cell">
<div class="d-flex justify-content-between align-items-center gap-2">
<span class="small">已处理 {{ task.processed_items_count }} / 共 {{ task.total_items_count }} 条内容</span>
@@ -32,11 +32,8 @@
</td>
<td>
<span class="badge {{ status_class }}">{{ status_label }}</span>
{% if task.error_stage or task.error_type %}
<br><small class="text-muted">{{ task.error_stage }} / {{ task.error_type }}</small>
{% endif %}
{% if task.error_message %}
<br><small class="text-danger">{{ task.error_message }}</small>
{% if task.error_summary %}
<br><small class="text-danger">{{ task.error_summary }}</small>
{% endif %}
</td>
<td><a class="btn btn-sm btn-outline-primary" href="/tasks/{{ task.id }}">查看</a></td>
+5 -4
View File
@@ -1,14 +1,14 @@
{% extends "base.html" %}
{% block title %}任务 #{{ task.id }} - 热榜评论分析工具{% endblock %}
{% block title %}任务 {{ task.display_id }} - 热榜评论分析工具{% endblock %}
{% block breadcrumbs %}
<nav aria-label="breadcrumb"><ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">首页</a></li>
<li class="breadcrumb-item active">任务 #{{ task.id }}</li>
<li class="breadcrumb-item active">任务 {{ task.display_id }}</li>
</ol></nav>
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h3 mb-0">任务 #{{ task.id }}</h1>
<h1 class="h3 mb-0">任务 {{ task.display_id }}</h1>
<button class="btn btn-outline-secondary btn-sm" onclick="window.location.reload()">手动刷新</button>
</div>
<section class="card mb-4" {% if task.status == "running" %}data-task-id="{{ task.id }}" data-auto-poll="true"{% endif %}><div class="card-body">
@@ -20,6 +20,7 @@
<p class="mb-0">平台:{{ task.platform | platform_label }} <span class="badge {{ cls }}">{{ label }}</span>{% if task.is_demo %}<span class="badge text-bg-info ms-1">Demo 数据</span>{% endif %}</p>
<p class="mb-0 text-muted">阶段:{{ task.current_stage_label or "等待启动" }}</p>
</div>
<div class="small text-muted mb-3">创建时间 {{ task.created_at_label }} · 完整 ID {{ task.id }}</div>
<div class="mb-3">
<div class="d-flex justify-content-between align-items-center gap-2">
<span>已处理 {{ task.processed_items_count }} / 共 {{ task.total_items_count }} 条内容</span>
@@ -72,7 +73,7 @@
<span class="badge text-bg-warning ms-1">AI 样本不足</span>
{% endif %}
</div>
{% if task.error_message %}<div class="alert alert-danger">{{ task.error_stage }} / {{ task.error_type }}{{ task.error_message }}</div>{% endif %}
{% if task.error_summary %}<div class="alert alert-danger">{{ task.error_summary }}</div>{% endif %}
</div></section>
{% if task.status == "running" and not hotspots %}
<div class="text-center text-muted py-5"><div class="spinner-border text-warning mb-3"></div><p>正在抓取热点数据,请稍候...</p></div>