补充创作者主页与关注粉丝工程文档
明确主页入口、公开关系列表及用户主页跳转行为 补充关注关系表、接口契约、权限和前端状态设计 拆分后端查询与页面交互里程碑及验收标准 记录游戏列表沿用现有上限、不增加分页改造的边界 同步文档索引与团队决策记录
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
- [当前产品与工程约束](./【项目基线】当前产品与工程约束-2026-05-15.md):现役入口、账号钱包、UI 和后端分层。
|
||||
- [平台入口与玩法链路](./【玩法创作】平台入口与玩法链路-2026-05-15.md):平台壳、图片画布、游戏分发与在线游玩合同;网站游戏评分与评价已实现并通过本地验证,待用户验收,未部署。
|
||||
- [网站游戏评分与评价里程碑](./project-memory/plans/【里程碑】网站游戏评分与评价-2026-09-30.md):唯一评价、编辑预填、4000 字符、公共分页与平均分/人数的验收边界与本地证据。
|
||||
- [创作者主页与关注粉丝合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#创作者主页与关注粉丝合同)、[关系与公开查询里程碑](./project-memory/plans/【里程碑】创作者关系与公开查询-2026-10-05.md)和[主页与交互里程碑](./project-memory/plans/【里程碑】创作者主页与关系交互-2026-10-05.md):规划草案,未实现;第四项默认进入自己主页,关注/粉丝列表公开可查看。
|
||||
- [创作者主页与关注粉丝工程设计](./technical/【技术方案】创作者主页与关注粉丝工程设计-2026-10-05.md):待实现的分层落点、关系表/DTO、授权、关系列表分页、组件状态、深链与验证边界;游戏列表沿用最多 48 项限制,不做额外分页改造。
|
||||
- [后台游戏评价管理合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#后台游戏评价管理合同):查找、分页、隐藏/恢复/删除、必填原因、统计与个人状态联动;已实现并通过本地验证,待用户验收,未部署。
|
||||
- [后台游戏评价管理里程碑](./project-memory/plans/【里程碑】后台游戏评价管理-2026-10-01.md)与[实施计划](./project-memory/plans/【实施计划】后台游戏评价管理-2026-10-01.md):单里程碑范围、接口/schema 边界及验收要求;本地证据已回写主规范。
|
||||
- [游戏广场评分展示合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏广场评分展示合同)、[里程碑](./project-memory/plans/【里程碑】游戏广场评分展示-2026-10-01.md)与[实施计划](./project-memory/plans/【实施计划】游戏广场评分展示-2026-10-01.md):已实现并通过本地定向验证,待用户验收,未部署;公开列表/详情携带真实摘要,卡片显示一位小数均分与人数,复用有效评价统计。
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# 创作者主页与关系交互
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 0.1 |
|
||||
| Status | proposed |
|
||||
| Date | 2026-10-05 |
|
||||
| Parent Spec | [创作者主页与关注粉丝合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#创作者主页与关注粉丝合同) |
|
||||
|
||||
## 目标与范围
|
||||
|
||||
在既有主站接入第四项创作者主页、游戏详情作者链接和关注按钮、公开主页与游戏列表、关注和粉丝列表及本人管理操作。
|
||||
|
||||
复用公共游戏卡、账号资料、登录能力、确认弹窗与页面导航;通用关注表现和用户行抽到共享组件,后端副作用与正式关系由业务层持有。不包含主页装修、资料编辑新系统和关注消息通知。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- [创作者关系与公开查询](./【里程碑】创作者关系与公开查询-2026-10-05.md)已验收。
|
||||
- 主规范和本里程碑完成评审;开始编码前单独落地本阶段实施计划。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 桌面第四项进入自己主页,第五项为“我的”;移动入口按评审口径接入。
|
||||
- [ ] 游戏详情可进入自己或他人主页,关注按钮与作者链接互不误触。
|
||||
- [ ] 主页显示真实计数和公开游戏,点击进入现有详情;本人无自关注按钮。
|
||||
- [ ] 公开关注/粉丝列表支持分页;只有本人有移除粉丝动作。
|
||||
- [ ] 自己/他人的关注/粉丝四类列表,游客和登录用户均可点击列表用户头像或昵称进入其创作者主页,覆盖本人及无公开游戏用户;返回恢复来源列表和分页/滚动位置,关系操作按钮不误触跳转。
|
||||
- [ ] 取消关注后可在当前行重新关注;刷新后的正式列表正确。
|
||||
- [ ] 粉丝列表回关/取消回关和移除粉丝分别改变正确方向。
|
||||
- [ ] 登录、退出、账号切换、请求迟到和网络失败不污染关系状态。
|
||||
- [ ] 主页/详情/列表往返状态一致,深链刷新和返回位置正确。
|
||||
- [ ] 375px 移动和桌面布局、长昵称、空态/错误态、键盘和触摸操作可用。
|
||||
|
||||
## 证据与停止点
|
||||
|
||||
前端定向 Vitest、`npm run typecheck`、`npm run check:encoding`、`npm run check:doc-index` 和 `git diff --check`;真实浏览器配合三个测试账号完成关系闭环,验证公开与私有游戏隔离。
|
||||
|
||||
提交最终逐条证据,等待验收;通过后将持久结论更新到主规范和相关共享记忆,删除已完成临时计划。本里程碑不授权自动生产部署。当前无实现或浏览器证据。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 创作者关系与公开查询
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 0.1 |
|
||||
| Status | proposed |
|
||||
| Date | 2026-10-05 |
|
||||
| Parent Spec | [创作者主页与关注粉丝合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#创作者主页与关注粉丝合同) |
|
||||
|
||||
## 目标与范围
|
||||
|
||||
为公开创作者主页提供真实用户资料、关注/粉丝计数、分页关系列表、访问者关系和作者公开游戏筛选,并支持认证用户关注、取消关注和移除自己粉丝。
|
||||
|
||||
不包含页面接入、消息通知、推荐、拉黑、既有游戏列表分页改造和生产部署。不新增独立创作者身份,公开游戏沿用现有可见性口径及最多 48 项限制。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 主规范与本里程碑完成评审,明确账号不可公开状态的现有判断依据。
|
||||
- 开始实现前另建仅覆盖本里程碑的实施计划,明确 schema、DTO、事务、API、测试及回滚边界。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 用户对唯一、不能自关注、重复写入与删除幂等。
|
||||
- [ ] 关注和粉丝方向正确,移除粉丝不取消本人对对方的关注。
|
||||
- [ ] 第三方不能代替他人写出边或删除入边。
|
||||
- [ ] 游客可读公开资料和列表,认证关系不混入共享公共缓存。
|
||||
- [ ] 分页、计数、失效账号过滤一致,响应不泄露私有账号字段。
|
||||
- [ ] 作者游戏筛选发生在最多 48 项截取前,过滤未公开、下架和删除作品;不增加游戏分页,未传作者的广场请求保持原有行为。
|
||||
- [ ] schema、迁移、表目录、生成绑定与共享 DTO 同步。
|
||||
- [ ] 正常、重复、并发和权限负向用例通过真实 API/SpacetimeDB 验证。
|
||||
|
||||
## 证据与停止点
|
||||
|
||||
领域/契约定向测试、schema 与 DDD 边界检查、编码/文档检查;通过 `npm run dev:api-server` 启动并验证 `/healthz` 后,以三个测试账号验证本人/对方/第三方关系。新增测试数据仅写隔离开发环境。
|
||||
|
||||
提供主规范逐条证据矩阵及未验证项;通过验收后才进入页面里程碑。当前只有规划草案,无实现或运行时证据。
|
||||
@@ -1,5 +1,12 @@
|
||||
# 决策记录
|
||||
|
||||
## 2026-10-05 创作者主页与关注粉丝的产品边界
|
||||
|
||||
- 已确认但未实现:桌面第四项“创作者主页”默认进入当前账号主页,“我的”移到第五项;他人的关注/粉丝列表公开可查看,自己或他人的两类列表均可点击用户进入其创作者主页。
|
||||
- 关注为单向关系,取消回关与移除粉丝分别影响不同方向;只有本人可移除自己的粉丝,自己不能关注自己。
|
||||
- 用户明确本次不额外改造游戏目录分页:既有游戏广场和“我的游戏”保持现状,作者主页按作者过滤后沿用最多 48 项限制。新关注/粉丝列表的分页仍按主规范设计。
|
||||
- 行为真相见[创作者主页与关注粉丝合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#创作者主页与关注粉丝合同),工程落点见[工程设计](../../technical/【技术方案】创作者主页与关注粉丝工程设计-2026-10-05.md)。当前仅完成文档,不代表功能上线。
|
||||
|
||||
## 2026-10-03 AGC 发布版本标签改为由工程内部版本派生,取代「用户可编辑标签」口径
|
||||
|
||||
- 背景:用户实机验收指出发布面板「项目版本」显示 v6,而 AGC 工程内部只有 4 条正式版本记录(资源总览「项目版本」栏目 4 张卡,顶栏「智能体修订」下拉同样只有这 4 条)。核实:面板值来自本地清单 `manifest.projectVersion` 这个可编辑标量,它被三条链路反复钉到**平台** `game_distribution_version.version_number` 上——发布成功回写(`apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs:1531-1535`)、打开面板回读绑定回填(`:536-541`)、用户手改(`:944-965`);而 `manifest.versions` 从头到尾不参与该值。`publicationRevision` 只做 CAS,与任何版本号都无推导关系(`module-game-distribution/src/domain.rs:27-40` 的版本号解析只比 `max_existing` 与 `requested`)。
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# 创作者主页与关注粉丝工程设计
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 0.1 |
|
||||
| Status | proposed(文档已形成,业务未实现、未部署) |
|
||||
| Date | 2026-10-05 |
|
||||
| Parent Spec | [创作者主页与关注粉丝合同](../【玩法创作】平台入口与玩法链路-2026-05-15.md#创作者主页与关注粉丝合同) |
|
||||
|
||||
本文明确主站创作者主页、关注关系和列表操作的工程边界,供后续按里程碑实施。产品行为以父规范为准;本次只提交文档,不改业务代码或数据库。
|
||||
|
||||
## 当前实现与修改边界
|
||||
|
||||
| 层 | 现有入口与拟修改范围 |
|
||||
| --- | --- |
|
||||
| 主站导航 | `src/components/platform-entry/PlatformEntryActiveFlowShell.tsx`、`platformEntryActiveTypes.ts`、`src/routing/activeAppPageRoutes.ts`;增加创作者主页与关系列表 stage,保持既有创作/项目/游戏/我的入口 |
|
||||
| 详情与公共 UI | `src/components/game-distribution/GameDetailPage.tsx`、`packages/shared/src/components/GameDetailDisplay/`;扩展作者区域插槽,公共关注按钮和用户行放共享组件 |
|
||||
| 新页面与访问层 | 在 `src/components/creator/`、`src/services/creatorClient.ts` 增加主页、关系列表和 HTTP 访问;复用现有认证、响应解包、错误处理和游戏卡表现 |
|
||||
| DTO | `server-rs/crates/shared-contracts/src/creator.rs`、`packages/shared/src/contracts/creator.ts`(拟新增);分别在现有导出入口注册 |
|
||||
| 领域 | `module-auth` 内新增纯关系规则子模块;不新增账号系统,不把 HTTP、数据库和 UI 状态放入领域规则 |
|
||||
| 持久化 | `spacetime-module` 新增关系模块,复用 `auth/tables.rs` 中的用户身份;同步模块注册、`migration.rs`、表目录和生成绑定 |
|
||||
| Facade | `spacetime-client` 新增 creator typed facade 与 mapper,复用现有连接和受信服务身份 |
|
||||
| HTTP | `api-server/src/modules/creator.rs` 与 `modules`/`app.rs` 注册;认证由现有 access token 校验链提供 |
|
||||
| 作者游戏 | 扩展现有 game-distribution 列表 query、共享内部输入及 facade/procedure,增加可选 `authorId` 精确过滤 |
|
||||
| 深链部署 | 按新增稳定路由同步 nginx SPA 路由及 Pingora 路由对照,覆盖直接访问、刷新与未知路径回退 |
|
||||
|
||||
以上新增文件是拟定落点,实施时可按相邻模块组织拆分,但不得建立第二套身份、作品或数据访问系统。不涉及 AGC 桌面客户端、外部 OpenAPI、后台管理页或游戏运行态。
|
||||
|
||||
源码已确认:公开游戏列表和“我的游戏”一次最多取 48 项,公开列表 `nextCursor` 固定为 null,前端 `listGames` 只返回数组;游戏广场的设备过滤发生在这份数组上。用户明确本次不额外改造这些现状。创作者主页只增加服务端作者过滤,沿用最多 48 项和原排序,不增加游戏分页、加载更多或新的筛选控件。
|
||||
|
||||
## 关系模型和授权
|
||||
|
||||
拟新增私有表 `user_follow`:
|
||||
|
||||
| 字段 | 类型与约束 |
|
||||
| --- | --- |
|
||||
| `relationship_id` | String 主键;编码为关注方 ID 的 UTF-8 字节长度、冒号、关注方 ID、被关注方 ID,保证有向用户对无歧义唯一 |
|
||||
| `follower_user_id` | String,关注发起方;建立对应索引 |
|
||||
| `followee_user_id` | String,被关注方;建立对应索引 |
|
||||
| `created_at` | Timestamp,只在关系首次建立时取事务时间;重复关注不改时间 |
|
||||
|
||||
同一用户对最多一行,双方不得相同。删除后重新关注视为新的建立时间。不另存关系计数、昵称、头像或互关布尔值;读时按对应方向索引计算,并以 `user_account` 当前存在性过滤对端。当前账号表和公开查询没有独立的封禁/公开状态,不能凭空增加状态字段。
|
||||
|
||||
写入沿用项目受信 API 服务身份调用 procedure 的模式:HTTP 从已验证 access token 派生操作者 ID,procedure 先校验调用服务身份,再在事务内检查操作者、目标和方向。普通客户端不能直接传入任意操作者绕过认证。新表不进入认证全量快照替换流程,登录或刷新账号资料不能清空关系。
|
||||
|
||||
关注只插入 `actor → target`;取消只删除同一方向;移除粉丝只删除 `follower → actor`。事务回执返回 actor 相对目标的最新关系,不把移除粉丝误报为 actor 已取消关注。用户不再存在时不暴露其资料,计数和列表同步排除;本次不增加账号注销或清理任务。
|
||||
|
||||
## HTTP 与 DTO
|
||||
|
||||
接口路径、方法和错误状态见父规范,统一复用现有成功/错误响应信封。以下形状是信封内的数据字段,Rust 使用 camelCase 序列化,TS 同名。
|
||||
|
||||
```ts
|
||||
type CreatorUser = {
|
||||
id: string;
|
||||
publicUserCode: string;
|
||||
displayName: string;
|
||||
avatarUrl: string | null;
|
||||
};
|
||||
type CreatorRelationship = {
|
||||
isSelf: boolean;
|
||||
isFollowing: boolean;
|
||||
isFollowedBy: boolean;
|
||||
};
|
||||
type CreatorProfile = {
|
||||
user: CreatorUser;
|
||||
followingCount: number;
|
||||
followerCount: number;
|
||||
};
|
||||
type CreatorConnection = {
|
||||
user: CreatorUser;
|
||||
followedAt: string; // 当前列表所表示方向的建立时间,RFC 3339
|
||||
relationship: CreatorRelationship | null; // 游客为 null
|
||||
};
|
||||
type CreatorConnections = {
|
||||
items: CreatorConnection[];
|
||||
nextCursor: string | null;
|
||||
total: number;
|
||||
};
|
||||
type CreatorRelationshipResponse = {
|
||||
userId: string; // 相对当前访问者的目标;移除粉丝时为 followerId
|
||||
relationship: CreatorRelationship;
|
||||
};
|
||||
```
|
||||
|
||||
`CreatorUser` 从现有公开资料投影所需字段,不返回手机号、登录名、钱包或认证数据。主页返回 `CreatorProfile`;关系列表返回 `CreatorConnections`;关系 GET 与三种写操作返回 `CreatorRelationshipResponse`。写请求无需 body,身份只来自认证,路径 ID 按统一规则 trim、校验并安全编码。
|
||||
|
||||
关系写操作成功返回 200,目标存在时重复关注/删除仍成功;对自己操作返回 400,未认证为 401,非受信或越权调用为 403,不存在的用户为 404。有效目标但不存在关系的删除与“目标不存在”明确区分。前端不自动重试结果未知的写请求,先回读关系。
|
||||
|
||||
主页摘要一次事务内完成用户和双向计数读取;关系列表一次事务内读取 `items/total` 和当前访问者相对各行的关系。不同 HTTP 请求不承诺共享同一事务快照,跨页变化通过写后失效与回读收敛,不能要求两次独立请求永远返回相同计数。
|
||||
|
||||
公开主页不携带访问者状态;`relationship` 端点必须认证。列表无 Authorization 时按游客读取,有 Authorization 时校验后批量返回关系;无效凭据返回 401,前端经现有认证处理后可回到游客读取。关系端点和带认证列表响应使用 `Cache-Control: private, no-store`,不得进入跨用户缓存。
|
||||
|
||||
## 关系列表分页与作者游戏读取
|
||||
|
||||
关注/粉丝列表的查询参数为 `limit`、`cursor`;默认 20,上限 50,非整数或超范围返回 400。按 `(created_at DESC, relationship_id DESC)` 排序,游标包含版本、列表主人、following/followers 类型与末项排序键;使用有长度上限的 base64url JSON 编码并严格解析,时间戳用十进制字符串避免 JS 精度损失。游标只是分页定位,不作为授权证明。
|
||||
|
||||
先排除不存在的对端,再计算 total 和分页;读取 limit+1 判断是否还有下一页。同时间多行不漏读,游标主人或类型不匹配返回 400。并发增删不保证多页构成冻结快照,按 userId 去重,刷新从首批开始;不引入跨请求数据库快照或游标持久化表。
|
||||
|
||||
作者游戏只扩展现有 `GET /api/game-distribution/games` 的 `authorId`:未传保持原行为,显式空值返回 400;先按稳定 owner ID 和既有公开条件过滤,再排序、截取最多 48 项。现有条件包含 published、未删除及有效公开版本。前端 `GameListQuery` 增加可选 authorId,仍返回现有游戏数组;不修改游戏表结构或引入新的游戏列表系统。
|
||||
|
||||
## 前端状态与组件责任
|
||||
|
||||
- 主页 `/creators` 解析当前账号,`/creators?id=...` 读取指定公开用户;关系列表用 `/creators/connections?id=...&tab=following|followers`,缺主人或非法 tab 展示明确无效链接状态。显式他人 ID 不因登录切换改成自己的主页。
|
||||
- 关系状态按访问者 ID、目标 ID 隔离。业务 hook/client 负责请求、写入单飞、失败回读和失效;共享关注按钮、用户行只接收数据、pending 和回调,不直接持有认证或网络副作用。
|
||||
- 自己/他人的关注列表、粉丝列表四种组合均支持头像/昵称进入任意用户主页;用独立链接和按钮避免嵌套交互。列表用户为自己时隐藏关注按钮,主页仍可访问。
|
||||
- 取消关注后的行保留集合只属于当前列表生命周期,与服务端成员和 total 分离;成功重新关注后清除暂留标记。刷新、离开列表或账号变化清除暂留集合;正常失效回读时不可把可重新关注的行立即抹掉。
|
||||
- 移除粉丝成功从粉丝列表去行,回关/取消回关不去行。确认弹窗复用公共组件;两个方向的按钮在同一目标写入期间一起禁用,写后刷新摘要和相关列表。
|
||||
- 进入页面、返回和重新聚焦时回读;旧请求通过请求序号/取消机制隔离。认证变化清除私有关系缓存和旧页请求,不让上个账号响应覆盖新账号。
|
||||
- 新主页路由接入页面标题、导航高亮、返回兜底和滚动位置恢复。移动点击区域至少 44px;加载、错误、空态分别呈现,不因关系失败阻断公开游戏阅读。
|
||||
|
||||
## 兼容、验证和交付
|
||||
|
||||
新关系表从空数据开始;同步迁移登记、后端表目录和 Rust 生成绑定。新增 procedure 与 facade 同步发布,不手改生成文件;游戏查询新增的 authorId 是可选能力,旧 HTTP 请求继续有效。后端部署先于新前端,回滚前端不删除关系数据;回滚后端必须保留新表的兼容 schema,禁止删库回退。
|
||||
|
||||
实施顺序和验收边界分别见[关系与公开查询里程碑](../project-memory/plans/【里程碑】创作者关系与公开查询-2026-10-05.md)、[主页与关系交互里程碑](../project-memory/plans/【里程碑】创作者主页与关系交互-2026-10-05.md)。每阶段评审后再创建单里程碑实施计划;前阶段验收通过才进入下一阶段。
|
||||
|
||||
实施时按范围执行以下命令;本次文档提交只执行最后三项:
|
||||
|
||||
```bash
|
||||
cargo test --locked --manifest-path server-rs/Cargo.toml -p module-auth creator
|
||||
cargo test --locked --manifest-path server-rs/Cargo.toml -p api-server creator
|
||||
cargo test --locked --manifest-path server-rs/Cargo.toml -p api-server game_distribution
|
||||
cargo test --locked --manifest-path server-rs/Cargo.toml -p spacetime-module creator
|
||||
npm run spacetime:generate
|
||||
npm run check:server-rs-ddd
|
||||
npm run test -- src/components/creator src/routing/activeAppPageRoutes.test.ts src/components/platform-entry/PlatformEntryActiveFlowShell.test.tsx src/components/game-distribution/GameDistributionPages.test.tsx
|
||||
npm run typecheck
|
||||
npm run check:nginx-spa-routes
|
||||
npm run check:pingora-route-parity
|
||||
npm run check:encoding
|
||||
npm run check:doc-index
|
||||
git diff --check
|
||||
```
|
||||
|
||||
`creator` 测试组为实施时新增的定向分组,届时核对实际匹配数量,零匹配不算通过;补充共享 DTO/UI 和 facade 的对应测试。host 单测不替代 SpacetimeDB 事务验证,运行时通过 `npm run dev:api-server` 启动并验证实际开发地址 `/healthz`,使用隔离开发库的 A/B/C 三账号完成权限、重复写入、双向关系与未知结果回读。
|
||||
|
||||
浏览器覆盖桌面与 375px 移动,四类列表跳转、返回位置、自己的空游戏主页、互关后移除粉丝和登录切换。游戏边界夹具应包含超过 48 项及其他作者作品,证明作者过滤在截取前,广场原有上限保持不变;关系列表用超过 50 项和同时间关系验证分页。所有执行结果回填里程碑证据,本次不宣称实现或运行时验收完成。
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
交付“AGC 一键提交游戏 / 网页上传游戏 ZIP → 后端收取真实发行包 → 校验与人工审核 → 主站发现、详情、游客在线游玩 → 更新与下架”的完整闭环。验收必须使用真实上传、真实存储、真实审核状态和隔离发行域名;静态演示卡片、metadata-only 请求或前端本地发布状态不能作为完成证据。
|
||||
|
||||
首版支持可以离线运行的静态 Web 游戏:HTML、JavaScript、CSS、JSON 与图片、字体、音视频。AGC 首先支持现有 npm/Vite Web 工程;网页入口允许上传符合相同包合同的 ZIP,不以游戏引擎名称限制普通静态产物。Godot/Cocos 工程源码、原生可执行文件、Wasm、服务端进程、外部 API、多人联机、云存档和跨版本存档迁移不在首版内。本发行合同 Version 0.2 不包含用户评分与评论,其扩展范围见下文“网站游戏评分与评价合同”;关注、榜单、推荐算法、交易和创作者收入仍不在范围内。
|
||||
首版支持可以离线运行的静态 Web 游戏:HTML、JavaScript、CSS、JSON 与图片、字体、音视频。AGC 首先支持现有 npm/Vite Web 工程;网页入口允许上传符合相同包合同的 ZIP,不以游戏引擎名称限制普通静态产物。Godot/Cocos 工程源码、原生可执行文件、Wasm、服务端进程、外部 API、多人联机、云存档和跨版本存档迁移不在首版内。本发行合同 Version 0.2 不包含用户评分与评论,其扩展范围见下文“网站游戏评分与评价合同”;关注扩展见下文“创作者主页与关注粉丝合同”提案,榜单、推荐算法、交易和创作者收入仍不在范围内。
|
||||
|
||||
### 入口与产品体验
|
||||
|
||||
@@ -550,3 +550,113 @@
|
||||
|
||||
- 管理员权限继续复用现有游戏审核权限映射,还是单独增加 `game-review-preview` 动作权限;第一里程碑默认复用现有审核权限,不扩大权限模型。
|
||||
- 预览 Token 的单次 HTML 读取与同包静态资源多次读取需要统一 TTL 和失效规则;第一里程碑使用短 TTL 的版本绑定会话。
|
||||
|
||||
## 创作者主页与关注粉丝合同
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 0.2 |
|
||||
| Status | proposed(工程设计待实现;已确认产品决策见本节末尾) |
|
||||
| Date | 2026-10-05 |
|
||||
| 范围 | 主站导航、公开创作者主页、游戏详情作者入口、关注关系与列表管理 |
|
||||
|
||||
### 目标与当前基线
|
||||
|
||||
让用户从游戏详情进入任意作者主页、查看作者公开游戏、关注或取消关注,并在自己的列表管理关注和粉丝。验收以真实账号关系、计数、公开游戏过滤及跨页回读一致为准。
|
||||
|
||||
2026-10-05 源码核验:`PlatformEntryActiveFlowShell` 的桌面导航实际为“创作 / 项目 / 游戏 / 我的”,移动端为“游戏 / 我的”;`activeAppPageRoutes` 已包含游戏列表、详情、游玩与作者管理路由。本文前部旧三入口说明不作为本提案的导航基线。现有 `GameDetailPage` 使用共享 `GameDetailDisplay`,作者身份已有稳定 `author.id`,昵称缺失时经公开用户接口查询;现有 schema 尚无关注关系表。
|
||||
|
||||
必须项为入口、主页、双向列表查看、关注/取消关注/重新关注、本人移除粉丝、公开游戏列表及详情跳转。风险项为关系方向、越权、公开/私有游戏隔离、并发请求与关系列表分页回读。私信、关注动态、通知、拉黑、推荐榜单、主页装修、关系隐私设置和既有游戏目录分页改造不纳入首版。
|
||||
|
||||
### 页面与导航
|
||||
|
||||
- 桌面导航保留前三项顺序,新增第四项“创作者主页”,“我的”变为第五项。第四项默认进入当前登录账号自己的主页(用户已确认)。
|
||||
- 移动端建议为“游戏 / 创作者主页 / 我的”,保留创作、项目的现有桌面限制,不把五项桌面入口强行塞入底部导航。
|
||||
- 建议主页路由 `/creators?id=<userId>`;裸 `/creators` 表示自己的主页,登录后解析当前账号。显式 ID 深链可刷新、分享及直接访问,自己的主页与他人的主页共用页面。
|
||||
- 建议列表路由 `/creators/connections?id=<userId>&tab=following|followers`,关注数和粉丝数分别进入对应列表;返回恢复来源页及分页/滚动位置,直接访问的返回兜底为所属主页。
|
||||
- 主页展示头像、昵称、陶泥号、关注按钮、`关注数 | 粉丝数` 和公开游戏列表。没有游戏或关系时显示真实空态,接口失败展示重试,不以 0 或空列表冒充成功。
|
||||
- 他人主页按钮为“关注”或“已关注”,点击“已关注”执行取消关注;自己的主页隐藏该按钮,不允许关注自己。按钮的可访问名称明确表达“取消关注”。
|
||||
- 游戏详情的作者头像/名称可点击进入主页,包括本人;作者旁增加同一套关注按钮。作者链接和关注按钮是独立点击目标,不因关注同时触发跳转;自己的游戏隐藏关注按钮。
|
||||
- 主页游戏卡复用现有公开卡片和详情路由,只列该用户仍然公开、未删除且有有效公开版本的游戏。自己的主页也遵循公开口径;未公开、审核中、下架游戏继续在 `/games/mine` 管理。
|
||||
- 游戏列表沿用现有读取限制:服务端先按作者和公开可见性筛选,再按创建时间倒序、游戏 ID 升序排序,最多返回 48 项;`nextCursor` 仍为空,不增加游戏分页或加载更多。不能下载广场前 48 项后在前端过滤作者。游戏广场和“我的游戏”保持原状;用户已明确本次不做额外改造。
|
||||
|
||||
### 关系方向与列表操作
|
||||
|
||||
关系 `A → B` 表示 A 关注 B,同时 B 获得粉丝 A;反方向独立存在。“关注数”统计出边,“粉丝数”统计入边,互相关注不是第三种持久化状态。
|
||||
|
||||
| 场景 | 可用操作 | 正式关系变化 |
|
||||
| --- | --- | --- |
|
||||
| A 查看 B 主页或 B 的游戏详情 | 关注/取消关注 | 添加/删除 `A → B` |
|
||||
| A 查看自己的关注列表中的 B | 取消关注;取消后重新关注 | 删除/恢复 `A → B` |
|
||||
| A 查看自己的粉丝列表中的 B | 回关/取消关注;移除粉丝 | 前两项只改变 `A → B`;移除只删除 `B → A` |
|
||||
| A 查看他人的关系列表 | 查看主页;对列表用户关注/取消关注 | 只改变 A 自己的出边,不代替列表主人操作 |
|
||||
| 游客查看主页或列表 | 浏览;点击关注唤起登录 | 未认证不写关系 |
|
||||
|
||||
关注/粉丝列表公开可查看(用户已确认),包括无已发布游戏用户的主页。仅允许本人移除自己的粉丝,任何客户端传入的主人 ID 都不能替代服务端认证身份。
|
||||
|
||||
列表行包含公开头像、昵称、陶泥号和当前访问者相对该用户的关注状态。无论查看自己的还是他人的关注列表、粉丝列表,点击任意用户的头像或昵称都进入该用户的创作者主页(用户已确认);游客同样可以跳转,列表中的用户即使是自己或尚未发布游戏,也使用同一主页入口。关注、取消关注与移除粉丝按钮是独立操作,不同时触发主页跳转;从用户主页返回时恢复来源列表及分页/滚动位置。
|
||||
|
||||
自己的关注列表取消后,当前已加载行暂留并显示“重新关注”,计数以服务端结果更新;重新进入或刷新后该行不再属于正式列表。这是临时 UI 行保留,不是第二份关系。粉丝列表取消回关不移除粉丝行,因为入边没有改变。
|
||||
|
||||
“移除粉丝”使用现有共享确认弹窗,确认后删除入边并移除当前行,保留自己对对方的关注。移除不是拉黑,对方仍可再次主动关注;本人无法代替对方恢复这条入边。取消关注默认不二次确认,支持在当前行重新关注。
|
||||
|
||||
### 登录、失败与一致性
|
||||
|
||||
- 主页和列表公开部分允许游客读取;登录后才查询访问者关系。裸主页入口未登录时展示登录入口,不猜测账号;登录成功进入自己的主页。游客在他人页面点击关注,登录后返回原目标并回读关系,再由用户执行关注。
|
||||
- 账号切换、退出、目标作者变化时清除访问者关系和列表临时保留行,失效旧请求;旧账号或旧页面的迟到响应不能覆盖当前页面。
|
||||
- 同一目标写操作进行中禁用重复点击。服务端接口表达“设为已关注/未关注”,不使用 toggle;重复相同请求不重复插行、不重复计数、不刷新既有关注时间。相反方向的并发操作按服务端事务提交顺序生效,回到页面或重新聚焦时回读。
|
||||
- 写入成功后回读当前主页摘要和受影响列表;游戏详情、主页和列表使用按访问者与目标区分的共享状态失效机制,防止各维护一份长期布尔值。
|
||||
- 超时或断网后不能断言写入失败:提示“状态未确认”,先查询正式关系,再允许重试当前意图;不得自动反转或重放陈旧的相反操作。确定失败保留已确认状态并显示错误。
|
||||
- 公共资料与访问者关系分开读取或使用正确的私有缓存策略,不能把某个用户的 `isFollowing` 放入匿名公共缓存。分页响应中的关系查询批量完成,避免逐行网络查询。
|
||||
- 不存在或不可公开的账号返回不可访问状态;资料只投影公开用户字段,不包含手机、会话、钱包或第三方身份凭据。计数与列表对不可公开账号使用相同过滤条件。
|
||||
|
||||
### 数据与接口提案
|
||||
|
||||
关注属于账号关系,复用现有账号身份,不新建创作者账号系统。建议在现有 `module-auth` 内划分关系子模块承载纯规则,SpacetimeDB 保存事实和事务,`spacetime-client` 提供 facade,`api-server` 提供 HTTP/BFF,Rust/TypeScript 共享 DTO 同步更新。
|
||||
|
||||
建议新增私有关注关系表:无歧义的有向用户对主键、`follower_user_id`、`followee_user_id`、`created_at`,分别支持关注方和被关注方索引。用户对唯一且不得相同;不保存昵称/头像副本。首版从关系索引计算准确计数,每次摘要或列表请求内部使用一致事务快照,不同 HTTP 请求通过回读收敛;如量级要求额外计数投影,须先补充事务一致性方案。
|
||||
|
||||
| 建议接口 | 用途与权限 |
|
||||
| --- | --- |
|
||||
| `GET /api/creators/{userId}` | 公开资料、关注数、粉丝数;游客可读 |
|
||||
| `GET /api/creators/{userId}/following` | 公开关注列表,游标分页 |
|
||||
| `GET /api/creators/{userId}/followers` | 公开粉丝列表,游标分页 |
|
||||
| `GET /api/creators/{userId}/relationship` | 登录访问者与目标的 `isSelf/isFollowing/isFollowedBy` |
|
||||
| `PUT /api/creators/{userId}/follow` | 当前登录用户关注目标,幂等 |
|
||||
| `DELETE /api/creators/{userId}/follow` | 当前登录用户取消关注目标,幂等 |
|
||||
| `DELETE /api/creators/me/followers/{followerId}` | 当前登录用户移除自己的粉丝,幂等 |
|
||||
| 扩展 `GET /api/game-distribution/games?authorId=<userId>` | 服务端精确作者过滤,复用公开游戏可见性与卡片契约 |
|
||||
|
||||
以上为拟新增合同,尚不是可调用 API。关注/粉丝列表建议默认 20、上限 50,按关系建立时间与稳定身份倒序,返回 `items/nextCursor/total`;游标绑定主人和列表类型,非法/错域游标返回 400。增删期间重新加载可能改变页内成员,前端按用户 ID 去重,重新关注产生新的建立时间。此分页规则仅用于新关系列表;游戏列表继续最多读取 48 项,不实现分页。
|
||||
|
||||
关系写入成功返回 200 与当前访问者关系;重复删除不存在的关系仍成功。不合法输入或关注自己返回 400,未认证 401,越权 403,目标不存在或不可公开 404。公开读取可携带有效认证以批量附带各行访问者关系,游客该字段为 null;带关系的响应禁用共享缓存,认证失效时清除访问者关系并按游客重新读取。
|
||||
|
||||
此次只新增关系表和站内接口,不改现有账号/游戏主键,不迁移出虚构的历史关注,也不扩充 external v1。实施时同步 `migration.rs`、表目录、生成绑定和 schema 检查;若后续需要破坏性修改已有表,须另行确认迁移计划。
|
||||
|
||||
### 分阶段交付与验收
|
||||
|
||||
1. 关系与公开查询:先交付真实持久化、权限、幂等、双向查询、准确计数、公开资料和作者游戏筛选;通过 API 与数据库运行时验收后进入页面接入。
|
||||
2. 页面与交互:接入导航、主页、列表、详情作者链接、共享关注控件和移除弹窗,完成真实账号桌面/移动端闭环验收。
|
||||
|
||||
每阶段先评审里程碑,再编写该阶段的单独实施计划;本次只交付规划,不进入业务实现。每阶段完成后给出证据并等待验收,不以单元测试替代真实运行时验证。
|
||||
|
||||
| 验收条款 | 证据要求 |
|
||||
| --- | --- |
|
||||
| 桌面第四/第五项与移动三入口;自己/他人深链、刷新、返回 | 路由测试与桌面、375px 移动浏览器操作 |
|
||||
| A 关注 B、取消、重新关注;A/B 各自正确计数 | 两个真实账号的 API 与数据库回读 |
|
||||
| 互关后 A 移除 B 粉丝,`A → B` 保留、`B → A` 消失 | 定向事务测试与真实 API;重复移除不重复扣数 |
|
||||
| 取消关注后当前行可重新关注;刷新后正式列表正确 | UI 定向测试与浏览器操作 |
|
||||
| 自己/他人的关注/粉丝四类列表均可点击用户进入主页,操作按钮不误跳转 | 游客和登录态浏览器验证,覆盖本人、他人、无公开游戏用户及返回位置恢复 |
|
||||
| 游客只读;禁止自关注和第三方移除他人粉丝 | 权限负向测试;第三账号越权调用 |
|
||||
| 主页只含作者公开游戏,自己的主页也不泄露私有版本 | 混合公开/未公开/下架/删除作品夹具与 HTTP 验证 |
|
||||
| 超时后回读、重复请求、并发、快速换作者/账号 | 后端幂等及前端迟到响应测试 |
|
||||
| 分页、空态、错误态、长昵称、触摸与键盘操作 | 超过一页数据及移动/桌面 UI 验证 |
|
||||
|
||||
### 决策与待评审项
|
||||
|
||||
- 已确认:第四项默认进入自己主页;他人关注和粉丝列表公开可查看;自己或他人的关注/粉丝列表均可点击任意用户进入其创作者主页;本次不额外改造游戏目录分页,保持既有广场和“我的游戏”行为。
|
||||
- 建议待评审:移动三入口、自己的主页只列公开游戏、取消后暂留行、移除粉丝二次确认,以及本节接口命名和分页默认值。
|
||||
- 源码核验:现有公开用户查询按账号存在性返回资料,`user_account` 没有独立封禁/公开状态字段。首版复用该存在性口径,关系计数和列表一致排除不存在的账号,不在本功能内增加账号状态体系。
|
||||
- 本次证据只覆盖源码调研和规划文档检查;业务、数据库迁移与浏览器验收均未执行。
|
||||
|
||||
工程落点、DTO、事务与验证命令见[创作者主页与关注粉丝工程设计](./technical/【技术方案】创作者主页与关注粉丝工程设计-2026-10-05.md)。本节是行为主规范,工程设计不另立产品规则。
|
||||
|
||||
Reference in New Issue
Block a user