From 67837b407edf83d2428129e4b806209567e1699a Mon Sep 17 00:00:00 2001 From: butubb <1422726308@qq.com> Date: Sat, 10 Oct 2026 15:41:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(comments):=20=E8=AF=84=E8=AE=BA=E6=A0=8F?= =?UTF-8?q?=E6=89=80=E6=9C=89=E5=8D=9A=E4=B8=BB=E9=83=BD=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=88=90=E3=80=8C=E6=9C=AA=E7=9F=A5=E5=8D=9A=E4=B8=BB=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:小红书的和抖音的评论栏,最外层分组全是「未知博主」,分不出谁是谁。 根因是分组接口漏了两个字段。api/routers/monitor.py 里按作品构造桶时只放了 note_id/note_title/note_cover/note_url/comments,而前端 groupByCreator 是用 bucket.creator_hash / bucket.creator_name 分组的 —— 两个都是 undefined,于是所有 博主塌成同一个 key,标签取空串回退成「未知博主」。 数据一直都在:每条评论上都带着 note_creator_hash / note_creator_name (service.py:540-541),只是没往桶上搬。TS 的 CommentBucket 里也声明了这两个字段, 所以是后端没兑现自己的契约,不是前端写错。 修:构造桶时把作品的创作者一并放上去(同一个桶里的评论必然同属一个作品,取哪条都一样)。 测试:种子数据改成「两个作品属于不同博主」(原来是同一个 hash,测不出这个 bug), 新增一条断言每个桶带上自己那个博主、且两个博主的 hash 确实不同。 --- api/routers/monitor.py | 6 ++++++ tests/test_monitor_comments.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/api/routers/monitor.py b/api/routers/monitor.py index 26c9e51..fb40058 100644 --- a/api/routers/monitor.py +++ b/api/routers/monitor.py @@ -172,6 +172,12 @@ async def list_comments( "note_title": comment["note_title"], "note_cover": comment["note_cover"], "note_url": comment["note_url"], + # 作品所属的创作者。评论流按 博主 → 作品 → 评论 三级展开时,最外层 + # 就是按这两个字段分组的 —— 少了它们,前端拿到的是 undefined, + # 于是所有博主塌成同一个分组、标签回退成「未知博主」。 + # 同一个桶里的评论必然同属一个作品,所以取哪一条都一样。 + "creator_hash": comment["note_creator_hash"], + "creator_name": comment["note_creator_name"], "comments": [], }, ) diff --git a/tests/test_monitor_comments.py b/tests/test_monitor_comments.py index 6ca7152..60cbd89 100644 --- a/tests/test_monitor_comments.py +++ b/tests/test_monitor_comments.py @@ -49,12 +49,17 @@ async def _seed(): session.add(task) await session.flush() - for note_id, title in (("note-a", "作品甲"), ("note-b", "作品乙")): + # 两个作品**属于不同的博主** —— 评论流最外层按创作者分组,同一个人就没得测了。 + for note_id, title, creator_hash, creator_name in ( + ("note-a", "作品甲", "hash-a", "博主甲"), + ("note-b", "作品乙", "hash-b", "博主乙"), + ): session.add( MonitorNote( task_id=task.id, note_id=note_id, title=title, note_url=f"https://www.xiaohongshu.com/explore/{note_id}", - cover=f"https://img/{note_id}.jpg", creator_hash="h", + cover=f"https://img/{note_id}.jpg", creator_hash=creator_hash, + creator_name=creator_name, source_kind="video", published_at=None, first_seen_run_id=1, first_seen_at=1_700_000_000_000, last_seen_run_id=1, last_seen_at=1_700_000_000_000, @@ -139,6 +144,27 @@ class TestGroupByNote: # note-b's only comment is the most recent overall. assert groups[0]["note_id"] == "note-b" + @pytest.mark.asyncio + async def test_each_bucket_carries_its_creator(self, client): + """桶上必须带作品的创作者 —— 评论流最外层就是按它分组的。 + + 少了这两个字段,前端拿到的 creator_hash / creator_name 都是 undefined, + 于是所有博主塌成同一个分组、标签回退成「未知博主」:一个人都分不出来。 + """ + groups = { + group["note_id"]: group + for group in ( + await client.get("/api/monitor/comments", params={"group_by": "note"}) + ).json()["groups"] + } + + assert groups["note-a"]["creator_hash"] == "hash-a" + assert groups["note-a"]["creator_name"] == "博主甲" + assert groups["note-b"]["creator_hash"] == "hash-b" + assert groups["note-b"]["creator_name"] == "博主乙" + # 两个作品的创作者必须真的不同,否则界面上照样分不出来。 + assert groups["note-a"]["creator_hash"] != groups["note-b"]["creator_hash"] + @pytest.mark.asyncio async def test_flat_shape_is_unchanged_without_the_flag(self, client): body = (await client.get("/api/monitor/comments")).json()