feat(web): include removed in visible stats; cover bang badge
站内展示/统计统一 VISIBLE(含 removed):热度、UP 列表、总览 active_ups/初导入计数、说明页粉丝覆盖、黑名单视频数。采集队列仍 只 active/unfaved。失效片封面右上角感叹号徽标,点击/tap 提示 「该视频已失效」;手动/候选入库仍可复活 removed→active。
This commit is contained in:
1 parent
6c73904b25
commit
0c660c6474
7 files changed
+122
-17
No files matched your search
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""失效封面徽标静态落地检查: uv run python tests/test_removed_cover_mark.py"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
STATIC = ROOT / "reaction_board" / "web" / "static"
|
||||
|
||||
|
||||
def test_removed_cover_mark_markup():
|
||||
components = (STATIC / "components.js").read_text(encoding="utf-8")
|
||||
assert "export function removedCoverMark" in components
|
||||
assert 'data-removed-tip' in components
|
||||
assert "该视频已失效" in components
|
||||
assert "${removedCoverMark(item)}" in components
|
||||
|
||||
app = (STATIC / "app.js").read_text(encoding="utf-8")
|
||||
assert 'closest("[data-removed-tip]")' in app
|
||||
assert 'toast("该视频已失效")' in app
|
||||
|
||||
css = (STATIC / "style.css").read_text(encoding="utf-8")
|
||||
assert ".cover-removed-mark" in css
|
||||
|
||||
video = (STATIC / "views" / "video.js").read_text(encoding="utf-8")
|
||||
assert "removedCoverMark(detail)" in video
|
||||
|
||||
|
||||
def main():
|
||||
test_removed_cover_mark_markup()
|
||||
print("OK: 失效封面徽标静态落地检查通过")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -38,11 +38,11 @@ def test_overview():
|
||||
assert overview["data_date"] == DATES[-1]
|
||||
assert overview["snapshot_days"] == 3
|
||||
assert overview["is_first_day"] is False
|
||||
assert overview["initial_import_count"] == 2
|
||||
assert overview["initial_import_count"] == 3 # 含 removed 104
|
||||
assert overview["counts"]["active"] == 2
|
||||
assert overview["counts"]["unfaved"] == 1
|
||||
assert overview["counts"]["removed"] == 1
|
||||
assert overview["counts"]["active_ups"] == 2
|
||||
assert overview["counts"]["active_ups"] == 3 # 含 UP C(仅 removed)
|
||||
assert overview["counts"]["candidates_pending"] == 1
|
||||
assert overview["totals"]["view"] == 1200 + 5200 + 120
|
||||
assert overview["interactions"] > 0
|
||||
@@ -68,7 +68,7 @@ def test_video_listing_filters_and_sorting():
|
||||
|
||||
heat = q.list_videos(sort="heat")
|
||||
aids = [item["aid"] for item in heat["items"]]
|
||||
# 热度榜仍按门槛过滤;104 removed 无成功快照,不进热度
|
||||
# 热度门槛榜口径含 removed;104 无成功快照仍不进热度
|
||||
assert 104 not in aids
|
||||
# 综合热度榜应用最小播放门槛 2000:101(1200)与 103(120)被排除
|
||||
assert aids == [102], aids
|
||||
@@ -111,6 +111,27 @@ def test_video_listing_filters_and_sorting():
|
||||
db.close()
|
||||
|
||||
|
||||
|
||||
def test_heat_ranking_includes_removed_with_metrics():
|
||||
"""removed 进入热度门槛榜口径;有成功快照且过门槛时可见。"""
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, q = setup(tmp)
|
||||
try:
|
||||
db.write(lambda conn: conn.execute(
|
||||
"UPDATE snapshot SET ok = 1, view = 5000, like = 10, coin = 1, "
|
||||
"favorite = 1, share = 0, reply = 0, danmaku = 0, err = NULL "
|
||||
"WHERE aid = 104 AND stat_date = ?",
|
||||
(DATES[1],),
|
||||
))
|
||||
DASHBOARD_CACHE.clear()
|
||||
heat = q.list_videos(sort="heat")
|
||||
aids = [item["aid"] for item in heat["items"]]
|
||||
assert 104 in aids
|
||||
assert next(item for item in heat["items"] if item["aid"] == 104)["status"] == "removed"
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_growth_and_cold_start():
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, q = setup(tmp)
|
||||
@@ -191,13 +212,14 @@ def test_up_queries():
|
||||
try:
|
||||
ups = q.list_ups()
|
||||
assert ups["sort"] == "avg_views"
|
||||
assert ups["total"] == 2
|
||||
assert ups["total"] == 3 # 含仅有 removed 视频的 UP C
|
||||
assert ups["items"][0]["up_mid"] == 1
|
||||
assert ups["items"][0]["video_count"] == 2
|
||||
assert ups["items"][0]["total_views"] == 6400
|
||||
assert ups["items"][0]["avg_views"] == 3200.0
|
||||
assert ups["items"][0]["up_face"] == "https://i0.hdslb.com/bfs/face/a.jpg"
|
||||
assert ups["items"][0]["follower_latest"] == 12345
|
||||
assert {item["up_mid"] for item in ups["items"]} == {1, 2, 3}
|
||||
|
||||
one = q.list_ups(min_videos=2)
|
||||
assert one["total"] == 1
|
||||
@@ -228,8 +250,8 @@ def test_up_queries():
|
||||
# 大小写不敏感
|
||||
lower = q.list_ups(q="up b")
|
||||
assert lower["total"] == 1 and lower["items"][0]["up_mid"] == 2
|
||||
# 命中多个 UP
|
||||
assert q.list_ups(q="UP")["total"] == 2
|
||||
# 命中多个 UP(含 UP C)
|
||||
assert q.list_ups(q="UP")["total"] == 3
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -479,7 +501,7 @@ def test_year_filter_and_published_sort():
|
||||
assert added["total"] == 4 # 含 removed
|
||||
|
||||
ups = q.list_ups(sort="efficiency", year=2026)
|
||||
assert ups["year"] == 2026 and ups["total"] == 2
|
||||
assert ups["year"] == 2026 and ups["total"] == 3
|
||||
ups_none = q.list_ups(sort="views", year=2025)
|
||||
assert ups_none["total"] == 0
|
||||
finally:
|
||||
@@ -506,9 +528,9 @@ def test_about_payload():
|
||||
"growth_rate_prior": 1000,
|
||||
}
|
||||
assert about["heat_weights"]["view"] == 0.30
|
||||
assert about["followers"]["videos_total"] == 3
|
||||
assert about["followers"]["videos_total"] == 4 # 含 removed
|
||||
assert about["followers"]["videos_covered"] == 3
|
||||
assert about["followers"]["videos_missing"] == 0
|
||||
assert about["followers"]["videos_missing"] == 1
|
||||
assert about["folders"][0]["media_id"] == 3700023351
|
||||
assert about["preview"] is False
|
||||
finally:
|
||||
|
||||
Reference in new issue
Block a user