Files
hot_comment_radar/app/templates/tasks/detail.html
T

108 lines
5.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}任务 #{{ task.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>
</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>
<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">
{% set label, cls = status_badge_config(task.status) %}
{% set percent = progress_percent(task.processed_items_count, task.total_items_count) %}
{% 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 %}
<div class="d-flex flex-wrap justify-content-between gap-3 mb-3">
<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="mb-3">
<div class="d-flex justify-content-between align-items-center gap-2">
<span>已处理 {{ task.processed_items_count }} / 共 {{ task.total_items_count }} 条内容</span>
<span class="text-muted">{{ percent }}%</span>
</div>
<div class="progress task-progress mt-2" role="progressbar" aria-label="任务进度" aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar" style="width: {{ percent }}%"></div>
</div>
<div class="small text-muted mt-2">成功 {{ task.successful_items_count }} / 失败 {{ task.failed_items_count }}</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-4">
<div class="metric-box">
<div class="text-muted small">目标上限</div>
<strong>{{ task.hotspot_limit }} 热点 × {{ task.item_limit_per_hotspot }} 内容 × {{ task.comment_limit_per_item }} 评论</strong>
<div class="text-muted small">最多 {{ target_comments }} 条评论</div>
</div>
</div>
<div class="col-md-4">
<div class="metric-box">
<div class="text-muted small">实际结果</div>
<strong>实际评论 {{ task.comments_count or 0 }}</strong>
<div class="text-muted small">已获取热点 {{ task.hotspots_count or 0 }} / 目标 {{ task.hotspot_limit }} · 报告 {{ task.reports_count or 0 }}</div>
</div>
</div>
<div class="col-md-4">
<div class="metric-box">
<div class="text-muted small">最近进度</div>
<strong>{{ task.last_progress_ago_label or "暂无记录" }}</strong>
<div class="text-muted small">运行时长 {{ task.running_duration_label or "刚刚" }} · 评论 {{ task.comments_count or 0 }}</div>
</div>
</div>
</div>
{% if task.status == "running" %}
<div class="alert alert-secondary">
小规模通常较快,默认规模可能需要数分钟,取决于 TikHub 与 AI 响应速度。
</div>
{% endif %}
{% if task.is_progress_stale %}
<div class="alert alert-warning">
超过 {{ task.stale_threshold_minutes }} 分钟没有进度更新,可能仍在等待外部接口或 AI 响应;如果长时间不恢复,请刷新状态或查看后端日志。
</div>
{% endif %}
{% if task.status == "success" and (task.comments_count or 0) < target_comments %}
<div class="alert alert-info">少于理论上限通常是内容本身评论不足或平台返回不足,不直接代表任务失败。若失败内容数大于 0,请结合失败原因判断。</div>
{% endif %}
<div class="mb-2">
<span class="{% if task.analysis_status == 'insufficient' %}text-warning{% else %}text-muted{% endif %}">AI 成功率 {{ ai_percent }}%</span>
{% if task.analysis_status == "insufficient" %}
<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 %}
</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>
{% endif %}
<div class="accordion" id="hotspot-list">
{% for hotspot in hotspots %}
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button {% if not loop.first %}collapsed{% endif %}" type="button" data-bs-toggle="collapse" data-bs-target="#hotspot-{{ hotspot.id }}">
热点 #{{ hotspot.rank }}{{ hotspot.title }}
</button>
</h2>
<div id="hotspot-{{ hotspot.id }}" class="accordion-collapse collapse {% if loop.first %}show{% endif %}" data-bs-parent="#hotspot-list">
<div class="accordion-body">
<a class="btn btn-sm btn-outline-primary mb-2" href="/hotspots/{{ hotspot.id }}/report">查看热点级汇总报告</a>
<ul class="list-group">
{% for item in hotspot.content_items %}
<li class="list-group-item d-flex justify-content-between">
<span>{{ item.title or item.summary or item.source_item_id }} <small class="text-muted">{{ item.status }}</small></span>
<a class="btn btn-sm btn-outline-secondary" href="/items/{{ item.id }}">查看详情</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
{% if task.status == "running" %}
<script>document.addEventListener("DOMContentLoaded", () => pollTaskDetailStatus("{{ task.id }}"));</script>
{% endif %}
{% endblock %}