feat: 打磨报告页和内容详情页

This commit is contained in:
meijiali
2026-07-03 14:45:22 +08:00
parent 82d103757b
commit eedb1db4da
6 changed files with 211 additions and 15 deletions
+76 -5
View File
@@ -179,7 +179,14 @@ def seed_result_data(engine):
from sqlalchemy.orm import Session
with Session(engine) as session:
task = Task(id="task-result", platform="douyin", status="success", total_items_count=1, successful_items_count=1)
task = Task(
id="task-result",
platform="douyin",
status="success",
total_items_count=1,
successful_items_count=1,
analysis_success_rate=1.0,
)
session.add(task)
hotspot = Hotspot(id="hot-result", task_id=task.id, platform="douyin", title="热点标题", rank=1, raw_data="{}")
session.add(hotspot)
@@ -216,8 +223,8 @@ def seed_result_data(engine):
hotspot_id=hotspot.id,
report_type="hotspot",
title="热点标题",
metrics_json='{"sample_count":1,"sentiment":{"positive":{"count":1,"pct":100}},"top_labels":[{"name":"认可","count":1}]}',
typical_comments_json='{"positive":[{"content":"评论内容","like_count":3}]}',
metrics_json='{"sample_count":1,"item_count":1,"sentiment":{"positive":{"count":1,"pct":100},"neutral":{"count":0,"pct":0},"negative":{"count":0,"pct":0},"unknown":{"count":0,"pct":0}},"top_labels":[{"name":"认可","count":1}]}',
typical_comments_json='{"positive":[{"content":"评论内容","like_count":3}],"neutral":[],"negative":[]}',
summary="热点总结",
markdown_content="# 热点标题\n\n热点总结",
data="{}",
@@ -231,8 +238,8 @@ def seed_result_data(engine):
content_item_id=item.id,
report_type="item",
title="视频标题",
metrics_json='{"sample_count":1,"sentiment":{"positive":{"count":1,"pct":100}},"top_labels":[{"name":"认可","count":1}]}',
typical_comments_json='{"positive":[{"content":"评论内容","like_count":3}]}',
metrics_json='{"sample_count":1,"sentiment":{"positive":{"count":1,"pct":100},"neutral":{"count":0,"pct":0},"negative":{"count":0,"pct":0},"unknown":{"count":0,"pct":0}},"top_labels":[{"name":"认可","count":1}]}',
typical_comments_json='{"positive":[{"content":"评论内容","like_count":3}],"neutral":[],"negative":[]}',
summary="内容总结",
markdown_content="# 视频标题\n\n内容总结",
data="{}",
@@ -255,10 +262,74 @@ def test_result_pages_render_seeded_data():
assert 'onclick="window.location.reload()"' in task_response.text
assert hotspot_response.status_code == 200
assert "热点总结" in hotspot_response.text
assert "评论样本" in hotspot_response.text
assert "关联内容" in hotspot_response.text
assert "正向" in hotspot_response.text
assert "1 条(100%" in hotspot_response.text
assert "认可 (1)" in hotspot_response.text
assert "典型评论" in hotspot_response.text
assert "评论内容" in hotspot_response.text
assert "<pre" not in hotspot_response.text
assert item_response.status_code == 200
assert "内容总结" in item_response.text
assert "评论样本" in item_response.text
assert "Top 标签" in item_response.text
assert "评论内容" in item_response.text
def test_report_pages_render_empty_state_when_report_missing():
with make_test_client() as (client, engine):
from sqlalchemy.orm import Session
with Session(engine) as session:
task = Task(id="task-no-report", platform="xiaohongshu", status="running")
session.add(task)
hotspot = Hotspot(id="hot-no-report", task_id=task.id, platform="xiaohongshu", title="缺报告热点", rank=1, raw_data="{}")
session.add(hotspot)
session.add(
ContentItem(
id="item-no-report",
task_id=task.id,
hotspot_id=hotspot.id,
platform="xiaohongshu",
source_item_id="n1",
item_type="note",
title="缺报告内容",
status="pending",
raw_data="{}",
)
)
session.commit()
hotspot_response = client.get("/hotspots/hot-no-report/report")
item_response = client.get("/items/item-no-report")
assert hotspot_response.status_code == 200
assert "报告生成中,请稍候" in hotspot_response.text
assert item_response.status_code == 200
assert "报告生成中,请稍候" in item_response.text
def test_report_pages_warn_when_ai_sample_is_insufficient():
with make_test_client() as (client, engine):
seed_result_data(engine)
from sqlalchemy.orm import Session
with Session(engine) as session:
task = session.get(Task, "task-result")
task.analysis_status = "insufficient"
task.analysis_success_rate = 0.5
session.commit()
hotspot_response = client.get("/hotspots/hot-result/report")
item_response = client.get("/items/item-result")
assert hotspot_response.status_code == 200
assert "当前有效评论样本不足" in hotspot_response.text
assert item_response.status_code == 200
assert "当前有效评论样本不足" in item_response.text
def test_export_routes_return_csv_and_markdown():
with make_test_client() as (client, engine):
seed_result_data(engine)
+14 -1
View File
@@ -1,4 +1,4 @@
from app.templating import from_json_filter, progress_percent, rate_percent, status_badge_config
from app.templating import from_json_filter, from_json_object_filter, progress_percent, rate_percent, sentiment_label, status_badge_config
def test_status_badge_config_centralizes_task_status_copy():
@@ -13,6 +13,12 @@ def test_from_json_filter_returns_empty_list_for_invalid_json():
assert from_json_filter("bad-json") == []
def test_from_json_object_filter_returns_empty_dict_for_invalid_json():
assert from_json_object_filter('{"sample_count": 1}') == {"sample_count": 1}
assert from_json_object_filter("[]") == {}
assert from_json_object_filter("bad-json") == {}
def test_progress_percent_clamps_invalid_and_overflow_values():
assert progress_percent(0, 0) == 0
assert progress_percent(1, 2) == 50
@@ -23,3 +29,10 @@ def test_rate_percent_formats_ai_success_rate():
assert rate_percent(None) == 0
assert rate_percent(0.754) == 75
assert rate_percent(2.0) == 100
def test_sentiment_label_maps_report_copy():
assert sentiment_label("positive") == "正向"
assert sentiment_label("neutral") == "中性"
assert sentiment_label("negative") == "负向"
assert sentiment_label("unknown") == "未知"