diff --git a/src/components/game-distribution/GameDistributionPages.test.tsx b/src/components/game-distribution/GameDistributionPages.test.tsx index fac14941b..2c5c86c11 100644 --- a/src/components/game-distribution/GameDistributionPages.test.tsx +++ b/src/components/game-distribution/GameDistributionPages.test.tsx @@ -3133,6 +3133,72 @@ describe('GameLineagePage 筛选器 / 主干线 / 信息面板(文档对齐) ); }); + it('热度排序判据 = 自身 playCount(子树合计更高的兄弟排后面)', async () => { + // self-hot:自身 100、无子代(合计 100)。deep-hot:自身 5、但子代 200(合计 205)。 + getGameLineageMock.mockResolvedValueOnce({ + rootGameId: 'game-root', + root: createLineageNode({ + gameId: 'game-root', + title: '母版', + generation: 0, + parentGameId: null, + playCount: 1, + }), + nodes: [ + createLineageNode({ + gameId: 'game-root', + title: '母版', + generation: 0, + parentGameId: null, + playCount: 1, + }), + createLineageNode({ + gameId: 'self-hot', + title: '自身热', + generation: 1, + parentGameId: 'game-root', + playCount: 100, + }), + createLineageNode({ + gameId: 'deep-hot', + title: '后代热', + generation: 1, + parentGameId: 'game-root', + playCount: 5, + }), + createLineageNode({ + gameId: 'deep-child', + title: '爆款孙代', + generation: 2, + parentGameId: 'deep-hot', + playCount: 200, + }), + ], + truncated: false, + }); + render( + , + ); + + await screen.findByText('自身热'); + fireEvent.click(screen.getByRole('checkbox', { name: '按热度排序' })); + // 判据是自身:自身热(100)排在 后代热(自身 5 / 合计 205)**前面**。 + expect(parseFloat((await cardOf('自身热')).style.left)).toBeLessThan( + parseFloat((await cardOf('后代热')).style.left), + ); + // 主干线同理,仍然选「自身热」。 + expect( + (await cardOf('自身热')).querySelector('.game-lineage-node__trunk'), + ).not.toBeNull(); + expect( + (await cardOf('后代热')).querySelector('.game-lineage-node__trunk'), + ).toBeNull(); + }); + it('主干线:每代热度最高的节点带「主干」角标,主干边单独标记', async () => { getGameLineageMock.mockResolvedValueOnce(tree); render( diff --git a/src/components/game-distribution/GameLineagePage.tsx b/src/components/game-distribution/GameLineagePage.tsx index 5d8a70890..295c4ffe8 100644 --- a/src/components/game-distribution/GameLineagePage.tsx +++ b/src/components/game-distribution/GameLineagePage.tsx @@ -347,6 +347,9 @@ export function GameLineagePage({ /** * 顶部筛选器:按世代筛选(保留该代及其祖先,树不断链)与按热度排序 * (同代内 `playCount` 倒序;关闭时保持服务端顺序 = 创建时间序)。 + * + * 注意排序判据是**自身** `playCount`(服务端字段原值),与主干线同裁定:热度表达的是 + * 「这一版自己有多热」,不是子树合计(显示口径见 §3.6.3)。别改成 `...Totals`。 */ const filteredNodes = useMemo(() => { const kept =