网页端收藏:作品详情页收藏切换 + 我的收藏页签
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m50s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m38s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m38s
Project CI / Frontend tests (pull_request) Failing after 1m10s
Project CI / Backend tests (pull_request) Successful in 9m34s
Project CI / AI game creator shell web tests (pull_request) Successful in 4m3s
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled

- 客户端:新增 setGameCollection(PUT 带 Idempotency-Key;DELETE 不带)与 listMyCollections({games,nextCursor},条目形状与公开目录逐字一致,可复用同一套卡片);getGame 返回类型放宽为 GameDistributionGameWithCollection,collected 为可选
- 详情页:在动作区(「立即玩」旁,而不是共创信息卡——那张卡讲改编关系)新增收藏切换。三态严格区分:collected=true → 「已收藏」点击取消;collected=false → 「收藏」点击收藏;**缺字段(匿名 / 无效 token 被按匿名处理)绝不落成「未收藏」**,按钮 title 标注「登录后可收藏」,点击走既有登录门禁且不发请求
- 乐观更新 + 回滚:先切换本地态,失败回滚到服务端投影并用服务端 message 提示(role=status);成功以服务端返回的 collected 为准
- 广场卡片:卡片本身没有操作区,按「没有就别硬塞」不动
- 我的收藏:落在 /games/mine 的页签(「我的作品」/「我的收藏」)。理由:两者都是登录后的个人内容、该页已有登录门禁;且不需要新路由,避免牵动「路由表 + nginx×3 + Pingora allowlist」这组必须同批登记的清单。复用公开目录同一套卡片(shared 的 GameCard + GameCover),空态/失败重试/登录态照既有写法
- 分页按「将来会有 cursor」的形态写:读 nextCursor,非空才渲染「加载更多」并在点击时追加;服务端当前恒为 null,不伪造分页数据
- 文案统一「收藏 / 已收藏」(不用需求文档旧词「收录」)
- 测试:详情页收藏四例(已收藏→取消 / 未收藏→收藏 / 缺字段走门禁且零请求且不渲染已收藏 / 失败回滚+服务端文案);我的收藏两例(空态且默认页签不预取 / 列表渲染+卡片点击跳详情+无 cursor 不出现「加载更多」)
This commit is contained in:
2026-10-06 01:18:45 +08:00
parent 4b1f24a8fc
commit 785152f70b
6 changed files with 458 additions and 1 deletions
@@ -527,6 +527,34 @@
.game-detail-info-card .game-fork-compare-link:hover {
color: var(--platform-text-strong);
}
/* 收藏失败/状态提示:与动作行同一行内换行,不撑破容器。 */
.game-collection-notice {
color: var(--platform-text-soft);
font-size: 0.78rem;
overflow-wrap: anywhere;
}
/* 我的作品 / 我的收藏页签。 */
.game-tabs {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.game-tabs__button {
border: 1px solid var(--platform-surface-border);
border-radius: 999px;
padding: 0.25rem 0.9rem;
background: transparent;
color: var(--platform-text-base);
font: inherit;
font-size: 0.8rem;
font-weight: 700;
cursor: pointer;
}
.game-tabs__button[aria-selected='true'] {
border-color: var(--platform-accent-strong);
background: rgba(199, 101, 61, 0.12);
color: var(--platform-accent-strong);
}
.game-lineage-node__compare {
align-self: flex-start;
border: 1px solid var(--platform-surface-border);