diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md index 12c85716..b4b810f9 100644 --- a/.hermes/shared-memory/decision-log.md +++ b/.hermes/shared-memory/decision-log.md @@ -1249,6 +1249,14 @@ - 验证方式:`npm run test -- src/components/rpg-entry/rpgEntryPublicGalleryViewModel.test.ts`、`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "recommend|edutainment"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "logged out home recommendation next starts the next puzzle work"`、针对变更文件执行 ESLint、`npm run typecheck`、`npm run check:encoding`。 - 关联文档:`docs/technical/【前端架构】RecommendFeedViewModel收口计划-2026-06-03.md`。 +## 2026-06-03 Ranking ViewModel 收口 + +- 背景:排行 tab 的文案、metric label 与空态文案在 `RpgEntryHomeView.tsx`,排序和 metric value 在 `rpgEntryPublicGalleryViewModel.ts`,同一 `PlatformRankingTab` 的 Interface 分散且页面需要类型断言取 active config。 +- 决策:在 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts` 收口 `DEFAULT_PLATFORM_RANKING_TAB`、`PLATFORM_RANKING_TABS`、`getPlatformRankingTabConfig` 与 `getPlatformRankingMetric`;页面仅保留 active tab 状态和渲染。 +- 影响范围:发现页排行频道 tab 顺序、tab 文案、空态文案、排行项指标 label/value。 +- 验证方式:`npm run test -- src/components/rpg-entry/rpgEntryPublicGalleryViewModel.test.ts`、`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "bottom category tab becomes ranking and switches ranking metrics|ranking"`、针对变更文件执行 ESLint、`npm run typecheck`、`npm run check:encoding`。 +- 关联文档:`docs/technical/【前端架构】RankingViewModel收口计划-2026-06-03.md`。 + ## 2026-06-03 Public Work Presentation 收口 - 背景:作品卡、推荐 runtime meta、排行项、分类项、搜索结果和桌面 hero 共用玩法类型 label 与紧凑计数格式,但规则仍在 `RpgEntryHomeView.tsx` 页面 Implementation 内。 diff --git a/docs/README.md b/docs/README.md index 92dbefdd..b286166d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -51,6 +51,8 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_ 推荐 feed 的公开作品去重、普通内容过滤、active 窗口与上一条 / 下一条回环选择也收口到 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts`,规则见 [【前端架构】RecommendFeedViewModel收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RecommendFeedViewModel%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。 +排行频道的默认 tab、tab 文案、空态文案、排序字段与指标 label/value 收口到 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts`,规则见 [【前端架构】RankingViewModel收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RankingViewModel%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。 + 每日任务卡片与任务中心弹窗的任务选择、进度、状态标签和按钮文案收口到 `src/components/rpg-entry/rpgEntryProfileTaskViewModel.ts`,规则见 [【前端架构】ProfileTaskViewModel收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91ProfileTaskViewModel%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。 个人数据卡、钱包 chip 与“玩过”弹窗的计数、时长、作品类型和作品号展示收口到 `src/components/rpg-entry/rpgEntryProfileDashboardPresentation.ts`,规则见 [【前端架构】ProfileDashboardPresentation收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91ProfileDashboardPresentation%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。 diff --git a/docs/technical/【前端架构】RankingViewModel收口计划-2026-06-03.md b/docs/technical/【前端架构】RankingViewModel收口计划-2026-06-03.md new file mode 100644 index 00000000..049faea6 --- /dev/null +++ b/docs/technical/【前端架构】RankingViewModel收口计划-2026-06-03.md @@ -0,0 +1,32 @@ +# 【前端架构】Ranking ViewModel 收口计划 + +## 背景 + +平台发现页排行频道以 `PlatformRankingTab` 决定 tab 文案、空态文案、排序字段和指标展示。原先排序与指标取值在 `rpgEntryPublicGalleryViewModel.ts`,而 tab label、metric label 与 empty text 留在 `RpgEntryHomeView.tsx`,页面还用类型断言寻找 active config,导致同一个排行语义的 **Interface** 分散。 + +## 决策 + +在 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts` 收口排行 **Interface**: + +- `DEFAULT_PLATFORM_RANKING_TAB` 与 `PLATFORM_RANKING_TABS`:统一 tab 顺序、tab label、metric label 与空态文案。 +- `getPlatformRankingTabConfig(tab)`:统一 active tab 配置兜底。 +- `getPlatformRankingMetric(entry, tab)`:统一 metric label 与 value,避免 label/value 漂移。 +- `buildPlatformRankingEntries(entries, tab)` 继续承载排序规则。 + +`RpgEntryHomeView.tsx` 只保留 active tab 状态、点击与渲染,不再理解“热门榜=游玩值”“新品榜=近 7 日值”等映射。排行规则的 **Locality** 收口到 PublicGallery ViewModel。 + +## 约定 + +- 默认排行 tab 保持 `hot`。 +- tab 顺序保持“热门榜 / 改造榜 / 新品榜 / 点赞榜”。 +- 排序口径保持:`hot=playCount`、`remix=remixCount`、`new=recentPlayCount7d`、`like=likeCount`。 +- “新品榜”仍按近 7 日游玩数排序,不改为发布时间排序。 +- 页面层继续保留最多显示 30 条的展示限制。 + +## 验证 + +- `npm run test -- src/components/rpg-entry/rpgEntryPublicGalleryViewModel.test.ts` +- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "bottom category tab becomes ranking and switches ranking metrics|ranking"` +- 针对变更文件执行 ESLint +- `npm run typecheck` +- `npm run check:encoding` diff --git a/src/components/rpg-entry/RpgEntryHomeView.tsx b/src/components/rpg-entry/RpgEntryHomeView.tsx index c273bf00..3bb1eb3d 100644 --- a/src/components/rpg-entry/RpgEntryHomeView.tsx +++ b/src/components/rpg-entry/RpgEntryHomeView.tsx @@ -160,20 +160,24 @@ import { buildPublicCategoryGroups, buildPublicGalleryCardKey, dedupePlatformPublicGalleryEntries, + DEFAULT_PLATFORM_RANKING_TAB, filterPlatformWorkSearchResults, filterTodayPublishedEntries, getAllPlatformPublicEntries, getPlatformCategoryPrimaryMetric, getPlatformPublicEntries, - getPlatformRankingMetricValue, + getPlatformRankingMetric, + getPlatformRankingTabConfig, getPlatformSearchableWorkIds, getPlatformWorldLikeCount, getPlatformWorldPlayCount, getPlatformWorldRemixCount, isExactPublicWorkCodeSearch, matchesPlatformCategoryKindFilter, + PLATFORM_RANKING_TABS, type PlatformCategoryKindFilter, type PlatformCategorySortMode, + type PlatformRankingMetric, type PlatformRankingTab, selectPlatformRecommendFeedWindow, sortPlatformCategoryEntries, @@ -405,37 +409,6 @@ const CHILD_MOTION_DEMO_DEFAULT_CARD = { summary: '站位、招手和左右手活动。', }; -const PLATFORM_RANKING_TABS: Array<{ - id: PlatformRankingTab; - label: string; - metricLabel: string; - emptyText: string; -}> = [ - { - id: 'hot', - label: '热门榜', - metricLabel: '游玩', - emptyText: '公开广场暂时还没有热门作品。', - }, - { - id: 'remix', - label: '改造榜', - metricLabel: '改造', - emptyText: '公开广场暂时还没有改造作品。', - }, - { - id: 'new', - label: '新品榜', - metricLabel: '近7日', - emptyText: '近 7 日暂时还没有新品。', - }, - { - id: 'like', - label: '点赞榜', - metricLabel: '点赞', - emptyText: '公开广场暂时还没有点赞作品。', - }, -]; function ResolvedAssetBackdrop({ src, fallbackSrc, @@ -1362,14 +1335,12 @@ function DesktopTrendingItem({ function PlatformRankingItem({ entry, rank, - metricLabel, - metricValue, + metric, onClick, }: { entry: PlatformPublicGalleryCard; rank: number; - metricLabel: string; - metricValue: number; + metric: PlatformRankingMetric; onClick: () => void; }) { const coverImage = resolvePlatformWorldCoverImage(entry); @@ -1405,9 +1376,9 @@ function PlatformRankingItem({