diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3ec97d1..f0d3aca 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -535,7 +535,7 @@ P3 实现说明: | UP主(`/ups`) | 独立入口,不再与视频混排;卡片显示 UP 头像、视频数与总时长、最新粉丝数,以及当前排序的主/副指标(「总播放」排序时副指标为「平均播放」);排序下拉含内容效率、互动效率、内容量、总播放、视频数、平均播放、总互动、最近发布;不提供按视频数筛选。 | | 数据说明(`/about`) | 数据来源与更新、发布时间/入库时间/快照日期、指标公式、时长与成熟窗口筛选、粉丝快照覆盖与已知局限;数值由 `/api/about` 动态读取。 | | 视频详情 | 元数据、分 P 数、七项指标、内容/互动效率、入库时粉丝数、单指标趋势、快照表、同 UP 对比。 | -| UP 页 | 该 UP 的头像、全部视频、聚合趋势、单视频对比、总时长与播放·小时、入库时与当前粉丝数。 | +| UP 页 | 该 UP 的头像、mid、首RE时间、最近发布时间、全部视频、聚合趋势、单视频对比、总时长与播放·小时、入库时与当前粉丝数。 | | 粉丝页 | 粉丝总数、日增、7 日净增、累计增长(标注起始日期);支持预设和自选日期,范围超过一年时按每月峰值日期聚合;最近记录默认 14 天并显示“较上一成功日”增量;不叠加视频数据。 | | 候选池 | 待确认候选、规则命中、剩余保留时间;操作指向 Telegram/CLI。 | | 系统状态 | 最近扫描、同步、快照、下次运行、备份、鉴权和黑名单。 | @@ -754,6 +754,7 @@ uv run python tests/test_moves.py - `ViewStat` / `VideoDetail` 增加 UP `mid/name/face` 解析; - UP 列表卡片由视频封面改为 UP 头像(无头像时显示首字母占位)、常驻显示最新粉丝数;「总播放」排序时副指标显示「平均播放」,避免与主指标重复; - UP 详情页补充头像; +- UP 详情页移除已解耦的收藏夹徽标,改为显示「首RE时间」(该 UP 最早视频发布时间)与最近发布时间;`/api/ups/{mid}` 不再返回 `folders`; - `/api/ups` 返回 `up_face` 与 `follower_latest`,`/api/ups/{mid}` 返回 `up_face`; - 自动化测试更新:`test_migrations.py`、`test_database.py`、`test_web_queries.py`、`test_bilibili_client.py`、`test_library.py`、`test_snapshot.py`、`web_fixtures.py`。 diff --git a/reaction_board/web/queries.py b/reaction_board/web/queries.py index 5afbf07..dd6cfb0 100644 --- a/reaction_board/web/queries.py +++ b/reaction_board/web/queries.py @@ -1270,9 +1270,6 @@ class DashboardQueries: view_by_date = {str(row["stat_date"]): int(row["view"] or 0) for row in rows} dates = _date_range(min(view_by_date), latest) if view_by_date else [] items.sort(key=lambda item: ((item["metrics"] or {}).get("view", 0), item["pubdate"]), reverse=True) - folder_titles = sorted({ - str(item["folder_title"]) for item in items if item.get("folder_title") - }) return { "up_mid": mid, "up_name": items[0].get("up_name") or f"UP {mid}", @@ -1304,7 +1301,6 @@ class DashboardQueries: "follower_latest": None if profile is None else profile["follower_latest"], "first_pubdate": min(item["pubdate"] for item in items), "latest_pubdate": max(item["pubdate"] for item in items), - "folders": folder_titles, "blacklisted": bool(conn.execute( "SELECT 1 FROM up_blacklist WHERE mid = ?", (mid,) ).fetchone()), diff --git a/reaction_board/web/static/views/up.js b/reaction_board/web/static/views/up.js index dc5ef3a..f178002 100644 --- a/reaction_board/web/static/views/up.js +++ b/reaction_board/web/static/views/up.js @@ -49,10 +49,10 @@ export async function renderUp(root, { params, query }) {

${escapeHtml(up.up_name || `UP ${mid}`)}

mid ${up.up_mid} + 首RE时间 ${escapeHtml(formatDate(up.first_pubdate))} ${up.blacklisted ? badge("黑名单 · 仅影响发现", "warning") : ""} - ${(up.folders || []).map((title) => badge(title)).join("")}
-

首次发布 ${escapeHtml(formatDate(up.first_pubdate))} · 最近发布 ${escapeHtml(formatDate(up.latest_pubdate))}

+

最近发布 ${escapeHtml(formatDate(up.latest_pubdate))}

diff --git a/tests/test_web_queries.py b/tests/test_web_queries.py index dffc342..460cfb1 100644 --- a/tests/test_web_queries.py +++ b/tests/test_web_queries.py @@ -196,6 +196,8 @@ def test_up_queries(): assert detail["series"]["dates"] == list(DATES) assert detail["series"]["views"] == [6000, 6200, 6400] assert detail["space_url"].endswith("/1") + assert "folders" not in detail + assert detail["first_pubdate"] > 0 blacklisted = q.up_detail(2) assert blacklisted["blacklisted"] is True