跟上主题详情契约变更:memberCount 为真实可见数 + rootsTruncated 截断信号
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled

- 客户端:GameDistributionThemeDetail 增加必填 rootsTruncated;getTheme 的响应类型与返回值透传该键(缺键按 false,空成员时服务端也是 false 而不是缺键)
- 主题页:新增「共 N 棵作品树」,总数一律用 memberCount(真实可见成员数,不受 50 上限截断),不再用 roots.length;rootsTruncated 为 true 时给出明确提示「这里只显示前 A 个,共 B 个」,与族谱页的 truncated 同一约定
- 顺带确认:全仓没有别处按 memberCount === roots.length 做不变式(此前只有主题列表页展示 memberCount,主题页未展示计数)
- 测试:新增一条——rootsTruncated=true 且 memberCount=120 / roots 只有 1 个时,截断提示出现且总数展示 120,不得出现用 roots.length 算出的「共 1 棵作品树」
This commit is contained in:
2026-10-06 04:30:41 +08:00
parent 0d0166c2d9
commit d6d3913320
4 changed files with 62 additions and 0 deletions
+10
View File
@@ -400,6 +400,13 @@ export type GameDistributionThemeSummary = {
/** 主题详情:摘要 + 成员根清单(逐条是公开目录同一份投影)。 */
export type GameDistributionThemeDetail = GameDistributionThemeSummary & {
roots: GameDistributionGame[];
/**
* `roots` 是否被服务端的响应体积上限截断(与族谱响应的 `truncated` 同一种约定)。
*
* **`memberCount` 与 `roots.length` 不再保证相等**:`memberCount` 是真实可见成员数(不截断),
* `roots` 可能只含前 50 个。展示总数一律用 `memberCount`,这个布尔只负责决定要不要提示。
*/
rootsTruncated: boolean;
};
function normalizeThemeList(value: unknown): GameDistributionThemeSummary[] {
@@ -464,6 +471,8 @@ export async function getTheme(
summary?: string;
badge?: string;
memberCount?: number;
/** `roots` 被响应体积上限截断:与 `roots` 同层,空成员时也是 `false`(不是缺键)。 */
rootsTruncated?: boolean;
roots?: unknown;
}>(
`/themes/${encodeURIComponent(normalizedThemeId)}`,
@@ -477,6 +486,7 @@ export async function getTheme(
summary: payload.summary ?? '',
badge: payload.badge ?? '',
memberCount: payload.memberCount ?? 0,
rootsTruncated: payload.rootsTruncated === true,
roots: normalizeGameList(payload.roots),
};
}