实现网站游戏评分与评价 (#561)
Project CI / AI game creator shell Rust crates (push) Successful in 1m43s
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 2m7s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m55s
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 3m23s
Project CI / Frontend tests (push) Successful in 3m3s
Project CI / Repository checks (push) Successful in 3m42s
Project CI / AI game creator shell web tests (push) Successful in 2m3s
Project CI / Backend tests (push) Successful in 6m19s
Project CI / Native shell tests (push) Successful in 8m7s

公开游戏详情页新增评分与评价:登录用户可提交并修改自己对每款游戏的唯一一条 1–10 分评价,评论可空且最多 4000 个 Unicode 码点;游客可分页浏览评价并查看平均分与评分人数。

- 新增私有评价表及共享 DTO/API,事务内校验游戏公开可见性、保证唯一性,并计算分页与全量评分统计;下架或封禁后关闭读写,重新公开及更新版本保留评价。
- 详情页支持编辑预填、取消、提交期间冻结输入、失败保留草稿,以及保存、翻页和账号/游戏切换时的旧响应隔离;复用现有认证与公共组件。
- 同步主规范、里程碑、实施计划、生成绑定、表目录和验收脚本。不扩展 AGC、外部 API、评论审核或评分缓存。

验证:
- 本轮审查复跑前端定向测试 40 项、评价领域测试 2 项,均通过。
- 网站 typecheck、Rust/TypeScript DTO 对齐、SpacetimeDB schema、文档索引、编码与 diff 检查通过。
- 实施文档另记录本地隔离数据库/API 49 项及桌面/移动视口浏览器 smoke 通过;本轮审查未重跑这些运行时验收,也未运行完整测试套件。

发布说明:新增 SpacetimeDB 表,部署时需同步 module 与 API。尚未部署 dev/production,待用户验收。

Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/561
Co-authored-by: Linghong <ink29535@proton.me>
Co-committed-by: Linghong <ink29535@proton.me>
This commit was merged in pull request #561.
This commit is contained in:
2026-10-01 19:19:58 +08:00
committed by 孔令弘
parent 44f415d057
commit b60aea4e71
81 changed files with 8594 additions and 60 deletions
@@ -0,0 +1,48 @@
# 【实施计划】后台游戏评价管理
| 字段 | 值 |
| --- | --- |
| Milestone | [后台游戏评价管理](./【里程碑】后台游戏评价管理-2026-10-01.md) |
| Status | implemented(本地验证通过,待用户验收;未部署) |
| Owner | Codex |
## 修改边界
- 主规范:[后台游戏评价管理合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#后台游戏评价管理合同);不扩大其四类筛选与单条管理范围。
- 领域:`server-rs/crates/module-game-distribution/src/reviews.rs` 的管理动作/原因校验与有效评价统计规则。
- 数据:`spacetime-module/src/game_distribution.rs` 追加隐藏字段、用户索引、新私有管理记录及读写事务;同步 migration、表目录与生成绑定。
- 后端:`spacetime-client` facade/mapper、`shared-contracts`、`api-server/src/modules/game_distribution.rs` 路由与 handler,`admin.rs` 页面权限映射;不得使用新直接数据库访问路径。
- 前端:admin-web 的路由/导航/账号权限/DTO/client/评价管理页及游戏管理跳转;网站评价 DTO、个人提示、摘要/列表读取。复用共享列表、表单、弹窗和后台写确认。
- 文档:主规范、后端数据契约、决策记录和索引;不改 AGC、游戏发行审核或外部 OpenAPI。
## 实现顺序
1. 技术评审后将方案转为 ready;冻结原因校验、四类筛选、DTO及错误码。
2. 追加默认 false 字段与索引、新管理记录表;事务实现隐藏/恢复/删除、创建时间目标核对及操作 key 重放,公共所有统计统一过滤,个人写保留隐藏状态。
3. 同步迁移/绑定和 facade;新增后台列表、游戏选择、详情与管理 POST,接入独立 game-reviews 权限;普通用户投影不包含原因。
4. 接入后台页、游戏入口、分页筛选、原因确认和详情内记录;网站个人状态加精确提示。请求重试复用同 key,不用旧响应覆盖新目标。
5. 定向测试及真实运行时验证,包括旧 schema 带评价升级、删除后主键复用和后台/网站联动;回写证据和限制,交付验收。
## 验证命令与操作
- `cargo test --manifest-path server-rs/Cargo.toml --locked -p module-game-distribution`
- `cargo test --manifest-path server-rs/Cargo.toml --locked -p api-server game_distribution`,另运行 admin 权限映射相关定向测试。
- `cargo check --manifest-path server-rs/Cargo.toml --locked -p spacetime-module`
- `npm run spacetime:generate`、`npm run check:spacetime-schema`、`npm run check:game-distribution-dto-parity`
- Vitest 定向运行后台新评价页、路由/权限/client与网站 `GameReviews` 测试;以仓库 include 配置核对实际执行名单。
- `npm run admin-web:typecheck`、`npm run typecheck`,受影响文件 ESLint/Prettier。
- `npm run check:doc-index`、`npm run check:encoding`、`git diff --check`
- 通过项目 dev 脚本启动隔离数据库及 `npm run dev:api-server` 并检查 `/healthz`;端口按运行状态核实,不使用人工 `spacetime --root-dir`。
- 在隔离数据库先发布旧 schema 并写入评价,再兼容升级;核对旧评价全部公开且内容/时间不变。真实 HTTP 验证跨页过滤、隐藏/统计/恢复/删除、重新评价、旧 key 重试和权限。
- 桌面与移动视口真实浏览器验证游戏管理跳转、长评论弹窗、原因必填/取消/失败,以及网站回读。缺失证据如实标记未验证。
## 风险与回滚点
- 删除是不可恢复操作;复用确认交互,事务校验原创建时间和幂等操作 key,禁止旧请求作用于新评价。
- schema 只兼容追加和新增私有表,不删字段/表或清空数据。发布冲突时停止,不通过 delete-data 绕过迁移。
- 隐藏后的旧后端会重新暴露评价;产生隐藏记录后只能回滚到仍过滤隐藏状态的兼容实现,保留全部数据和操作记录。
- 不引入前端内容版本锁、搜索服务或统计缓存;当前规模采用完整筛选后分页,不在有限首批数据上筛选造成漏查。
## 当前状态
已按上述边界完成实现;定向自动化、旧 schema 带 21 条评价无损升级、真实 HTTP 管理链路和桌面/375×812 移动视口验证通过。完整证据及未验证项见主规范“迁移与验收”。保留计划供用户验收;未部署。
@@ -0,0 +1,66 @@
# 【实施计划】游戏广场评分展示
| 字段 | 值 |
| --- | --- |
| Milestone | [游戏广场评分展示](./【里程碑】游戏广场评分展示-2026-10-01.md) |
| Status | implemented(本地验证通过,待用户验收;未部署) |
| Date | 2026-10-01 |
| Owner | Codex |
## 修改边界
- 主规范:[游戏广场评分展示合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏广场评分展示合同);仅实施本里程碑。
- 数据读取:`server-rs/crates/spacetime-module/src/game_distribution.rs` 的公开快照、列表/详情读取及 procedure 返回类型;复用已有评分 helper。现有持久化表、索引、评价写入与 migration 登记不变。
- 后端:`spacetime-client/src/active/mapper/game_distribution.rs` 公开 record 和 mapper、`shared-contracts/src/game_distribution.rs`、`api-server/src/modules/game_distribution.rs` 公开响应与 no-store;通过既有 facade,不新增数据库访问通道。
- 前端:`packages/shared/src/contracts/gameDistribution.ts`、共享评分文本组件及导出,网站 `GameGalleryPage.tsx`、`GameReviews.tsx` 和对应 CSS/定向测试;API client 只按必要调整类型,不新增逐卡读取。
- 契约检查:`scripts/check-game-distribution-dto-parity.mjs` 与生成绑定;运行时复用现有隔离数据,不新增 E2E 脚本或扩大评分/后台管理回归矩阵。
- 文档:主规范、本文、里程碑、文档索引及稳定决策。后台 UI、AGC、外部 OpenAPI、发行包链路不在修改范围。
## 实现顺序
1. 扩展 `GameDistributionPublicGameSnapshot` 返回类型,追加 `average_score:Option<f64>` 与 `rating_count:u64`;复用 `game_distribution_user_rating_summary` 及领域 `visible_review_summary` 的隐藏过滤、一位小数和空态。列表先核对公开可见性与有效版本、按原规则排序并限量,再只为返回项构建含摘要的快照;不能让无效版本占用限量名额。详情共用该公开快照。
2. 同步生成绑定与公开 record/mapper,将摘要映射为既有 `GameDistributionRatingSummaryRecord`。浮点数进入公开快照/record 后,移除其及引用结果类型中不适用的 `Eq`,保留 `PartialEq`;record 嵌入摘要时按现有序列化用途补齐必要 derives。
3. Rust/TS 共用游戏 DTO 追加可选 `ratingSummary`,Rust 允许旧字段缺失;公开 `public_game_payload` 必须输出摘要对象,复用既有摘要转换。同步列表/详情 no-store、DTO parity 的公开构建器 `mustEmit` 和必要嵌套约束;作者 `game_payload` 可省略摘要,不造零值。
4. 将纯评分文本展示抽到 `packages/shared`,只接收摘要数据,复用一位小数及人数表现。现有 `GameRatingSummary` 保留详情评价的加载/错误/重试职责,已加载文本使用共享组件;广场卡片使用列表摘要,无额外评价请求,缺字段显示“评分暂不可用”。卡片简介下增摘要行,采用现有视觉变量并允许移动换行。
5. 在现有广场页面测试中补有评分、零评价、缺摘要三种展示断言;复用现有公开响应/DTO 测试核对新增字段。有效评价统计、管理动作、筛选、滚动恢复和迟到响应沿用已有测试,不另加重复用例;纯文本共享组件由页面测试覆盖即可。
6. 执行定向工程检查,以现有隔离数据做一次公开 API smoke 和桌面/移动页面检查,按主规范回写证据和限制,交付用户验收;验收通过后融合持久结论并清理临时计划。
## 必要测试范围
- 前端:在已有页面测试中覆盖正常评分、一位小数/人数、无人评分与缺字段提示;运行受影响的广场及详情评价测试。
- 后端:复用已有响应/契约测试验证摘要字段,沿用有效评价统计测试确认隐藏过滤。相同映射不在 mapper、handler、DTO 每层重复添加一套测试。
- 联调:复用现有两款游戏及少量评价,一次核对列表/详情/评价接口摘要一致、隐藏记录不计入且游戏间统计不串联;浏览器检查布局与详情返回后的更新。
- 不新增测试框架、专用 E2E 脚本、大批量账号/分页 fixture、故障注入或完整管理动作矩阵。仅在实现确实改动已有行为且现有测试未覆盖时补相应回归。
## 验证命令与操作
- 运行 `module-game-distribution` 已有有效评价统计定向测试;领域逻辑未改时不新增同类测试。
- `cargo test --manifest-path server-rs/Cargo.toml --locked -p shared-contracts game_distribution`
- `cargo test --manifest-path server-rs/Cargo.toml --locked -p api-server game_distribution`
- `cargo check --manifest-path server-rs/Cargo.toml --locked -p spacetime-module -p spacetime-client`
- `npm run spacetime:generate`、`npm run check:generated-bindings`、`npm run check:spacetime-schema`、`npm run check:game-distribution-dto-parity`
- `npm run test -- src/components/game-distribution/GameDistributionPages.test.tsx src/components/game-distribution/GameReviews.test.tsx`;只有 API client 实现发生变化时追加其已有测试,不单独新增纯文本共享组件测试。
- `npm run typecheck`,对受影响代码运行仓库现有格式/静态检查。
- `npm run check:doc-index`、`npm run check:encoding`、`git diff --check`。
- 按现有 dev 脚本启动显式隔离数据库和 `npm run dev:api-server`,读取 `.app/dev-stack.json` 核对目标/端口,检查 `/healthz`;复用现有隔离数据做一次列表/详情/评价摘要对照,不为本增量重建整套 ratings/moderation E2E 流程。
- 真实浏览器桌面与 375px 移动视口检查评分行、换行及详情改分后返回;确认摘要随列表返回。筛选/滚动恢复、错误/重试及迟到响应沿用已有定向测试,不重复建立浏览器矩阵。
## 风险与回滚点
- 公开 procedure 返回类型属于配套运行时合同;module、生成绑定和后端先在隔离环境一起验证,再按现有运维流程发布,网站随后更新。无需持久化迁移或数据回填,不能用删除数据处理类型不匹配。
- 评分聚合仅作用于返回项,并使用既有按游戏索引;保留有效版本过滤与排序,避免额外扫描全部匹配游戏的评价。当前规模不增加缓存、统计表或预计算任务。
- 缺字段只表示不可用,不能默认成 `null/0`;详情评价状态继续由现有读取/保存驱动,避免公开投影摘要覆盖提交后的最新值。
- 回滚网站展示可保留新增公开字段;回滚 module/后端必须恢复互相匹配的绑定,并继续过滤隐藏评价。不得退回不识别管理隐藏状态的基础评价旧实现。
## 执行结果
- 已完成上述代码与绑定接入;公开列表先过滤有效版本、排序并限量,只为返回游戏聚合评分。持久化表与评价写入规则未变。
- 前端两文件 36 项、API game_distribution 34 项、shared-contracts 4 项、领域 summary 2 项通过;module/client 编译、typecheck、受影响代码静态/格式检查通过。
- `spacetime:generate` 使用固定 2.8.3 完成;保留新增快照字段,清除无关生成格式 diff。生成绑定、schema(87 表)、DTO parity(31 类型/4 构建器)、编码、文档索引和 diff 检查通过。
- `dev:api-server` 启动后 `/healthz` 通过;本机显式隔离库没有既有评分 fixture,复用现有 helper 创建两个账号、两款游戏、两条评价。游客/登录公开列表摘要一致,列表/详情/评价摘要 `8/2`,隐藏一条后 `7/1`,另一游戏始终 `null/0`;列表/详情 no-store 通过。临时联调代码与数据仅留在 ignored 本地产物,未新增专用仓库 E2E 脚本。
- 1280px/375px 浏览器评分行无横向溢出,卡片可进入详情;详情期间通过 API 将可见评分从 7 改为 6,返回广场显示 `6.0/10 · 1 人评分`。
- 前端实现与后端只读审查由两个 `gpt-6.1-sol` subagent 协助,后端审查未发现可执行问题。
## 未验证与待验收
用户最终验收与生产部署待完成,保留本计划。未跑完整仓库测试、完整评价/后台管理 E2E、真实手机、长标题/极大人数浏览器矩阵、浏览器登录改分和实际发行包游玩。返回刷新通过 API 改分验证,登录公开读取通过 HTTP smoke 验证;未增加复杂测试矩阵。
@@ -0,0 +1,43 @@
# 【实施计划】网站游戏评分与评价
| 字段 | 值 |
| --- | --- |
| Milestone | [网站游戏评分与评价](./【里程碑】网站游戏评分与评价-2026-09-30.md) |
| Status | implemented(本地验证通过,待用户验收) |
| Owner | Codex |
## 修改边界
- 按用户确认的最新主规范实施网站详情评价、评分统计、公共分页与个人编辑。
- 后端限定现有 game-distribution 领域、私有评价表、spacetime-client、共享 DTO 与 API 路由;新增表不破坏现有表。
- 前端限定网站详情、评价组件与 API client,复用现有登录、按钮和状态组件。
- 不扩展 AGC、广场、外部 API,不新增删除、审核、回复、点赞、排行榜或统计缓存。
## 实现顺序
1. 补齐评分、码点长度、归一化、排序统计领域规则与 Rust/TS DTO。
2. 新增 game_distribution_review 私有表,以游戏/用户组合为唯一主键,按游戏建立索引;同步 migration、表目录、生成绑定。在事务内检查公开可玩状态并保存,读取分页与统计使用一致快照。
3. facade 和 HTTP 接入公共分页、个人读取、唯一 PUT,身份由认证主体取得,响应 no-store。
4. 网站实现个人表单/记录/编辑、公共分页与平均分人数,输入冻结及读取请求序号隔离;补定向交互测试。
5. 定向 Rust/Vitest、typecheck、DTO/schema/编码/索引检查及真实数据库/API/桌面移动浏览器 smoke;记录逐条证据和限制。
## 验证命令
- `cargo test --manifest-path server-rs/Cargo.toml -p module-game-distribution`
- `cargo test --manifest-path server-rs/Cargo.toml -p api-server game_distribution`
- `cargo test --manifest-path server-rs/Cargo.toml -p spacetime-module game_distribution`
- `npm run spacetime:generate`、`npm run check:spacetime-schema`、`npm run check:game-distribution-dto-parity`
- `npx vitest run src/components/game-distribution src/services/gameDistributionClient.test.ts`
- `npm run typecheck`、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check`
- `npm run dev:api-server` 检查 `/healthz`,真实本地 SpacetimeDB/API 验证两账号、唯一并发与至少 21 条评价;浏览器验证桌面、移动、编辑取消与键盘评分。
## 风险与回滚点
- 当前是新增私有表,无旧数据回填。回滚页面/API 时保留评价数据,不删除数据库记录。
- 中文/emoji 统一按换行归一化后的 Unicode 码点计数,不依赖 textarea 原生 UTF-16 maxLength。
- 保存成功与账号/游戏切换使旧读取失效,旧成功、失败、finally 均不得覆盖当前状态。
- 若环境不支持真实 smoke,明确记录已通过的自动化证据和未验证项,不标记已上线或已验收。
## 验证结果
本计划步骤已实施;各条行为和验证证据已回写[主规范](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#网站游戏评分与评价合同)。真实数据库/API 49 项及桌面/移动视口浏览器 smoke 通过,未部署。用户验收后与里程碑一起清理。
@@ -0,0 +1,53 @@
# 【里程碑】后台游戏评价管理
| 字段 | 值 |
| --- | --- |
| Version | 1.0 |
| Status | implemented(本地验证通过,待用户验收;未部署) |
| Date | 2026-10-01 |
| Parent Spec | [后台游戏评价管理合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#后台游戏评价管理合同) Version 1.0 |
## 目标
交付后台查找评价、隐藏/恢复/删除、原因与操作记录,并同步网站公共分页/统计和个人隐藏状态,保持每账号每游戏唯一评价。
## 范围
- 独立“游戏评价”后台页及页面权限;从游戏管理带游戏 ID 进入,完整正文和评分只读。
- 游戏名称搜索选择/ID定位、评价用户 ID、正文关键词和公开/隐藏状态组合筛选;完整数据过滤后分页。
- 隐藏/删除必填原因,恢复无须原因;管理操作原子保存,失败与取消不产生部分写入。
- 隐藏排除整条评价及评分,个人固定提示“已被管理员隐藏”;用户编辑保持隐藏,恢复重新参与统计。
- 删除不可恢复,允许用户重新评价;旧管理目标和重复请求不能误处理重新创建的记录。
- 存量无损升级、管理员权限、私有原因隔离、真实数据库/API和桌面/移动后台及网站联动。
## 不在范围内
- 管理员修改正文/分数、删除恢复、再次评价封禁、批量、导出、举报、自动审核、申诉、通知/轮询/推送。
- 评分/时间范围等额外筛选、独立操作日志页、AGC 评价、外部 API、统计缓存或清理任务。
## 依赖与前置条件
- 用户已确认主规范与本里程碑按方案实施;实施计划进入执行,范围仍限本里程碑。
- 基础网站评价已实现且本地验证通过,其用户验收/生产发布状态独立;本次不推定该功能已验收。
- 现有后台认证/账号授权、游戏/账号读取、评价唯一写入、受信服务身份及 SpacetimeDB 2.8.3 可用。
- 有隔离数据库可验证带真实存量评价的旧 schema 升级,以及超过 20 条评价的筛选/分页。
## 验收标准
- [ ] 游戏管理入口按权限显示,ID 参数首次及切换生效;四条件组合查询、重置、刷新、跨页匹配、空态正确。
- [ ] 列表与详情显示游戏/用户/评分/完整纯文本;仅评分记录可管理,管理员没有编辑内容/分数入口。
- [ ] 原因 1–4000 码点,隐藏/删除空原因被拒,恢复不要求;取消无写入,失败保留草稿,删除明确不可恢复。
- [ ] 隐藏后公共列表/人数/均分排除,全部隐藏为空态;个人提示精确、仍可编辑且不解除隐藏。
- [ ] 恢复后参与公共统计,创建和用户修改时间不变;游戏恢复公开不自动解除隐藏。
- [ ] 删除后个人读取为空并可重新评价,记录仍唯一;删除后总数减少、越界页正确回退。
- [ ] 原因和管理员身份仅后台可见;匿名 401、无权限 403、伪造身份/隐藏状态无效,下架游戏后台可管理。
- [ ] 管理变更与记录原子保存;同 key 重试不重复动作或日志,不同请求 409;旧页面/旧 key 不删除重新提交的新评价。
- [ ] 旧 schema 有数据升级后内容/时间/唯一性不变,默认公开;schema/绑定/DTO 和定向检查通过。
- [ ] 真实数据库/API及桌面/移动浏览器覆盖后台操作、前台回读、分页、长评论和失败;证据与未验证项逐条记录。
## 证据要求
- 自动化:领域原因校验/统计过滤,API鉴权/错误/DTO,后台筛选及操作交互、网站隐藏个人状态。
- 运行时:存量 schema 升级,21 条以上评价的筛选分页、隐藏/恢复/删除、重新提交与重试;浏览器后台和网站联动。
- 边界:401/403、管理原因泄漏、原子失败、状态并发、删除后主键复用、全部隐藏和页码越界。
- 本里程碑的自动化、存量升级、真实 HTTP 及桌面/移动视口证据已回写[主规范](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#迁移与验收);上方复选框保留供用户验收,不以既有评价功能证据替代。
@@ -36,7 +36,7 @@
- 正式状态来自后端,素材仍复用平台上传与归属能力;前端和 AGC 不另建公开游戏状态、owner 事实或审核结果。
- 真实发行包具有不可变版本和 SHA-256,AGC dist 归一化为发行根 `index.html`;网页 ZIP 与 AGC 共用一条服务管道。
- 不恢复退役玩法 API、公开作品表或专属 runtime;不把私有项目源码镜像公开。
- 首版不包含原生/Wasm 游戏、任意外网依赖、服务端进程、多人联机、云存档、评论/评分/关注、排行榜、推荐算法和收益结算。
- 本发行里程碑不包含原生/Wasm 游戏、任意外网依赖、服务端进程、多人联机、云存档、评论/评分/关注、排行榜、推荐算法和收益结算。网站评分与评价作为[独立里程碑](./【里程碑】网站游戏评分与评价-2026-09-30.md)推进,不借用本文件的发行验收结论。
- 本文件只协调本业务;不顺带改造图片编辑器、Agent Runtime 执行模型或无关项目数据。
## 阶段 A:真实包、身份与可恢复发行
@@ -0,0 +1,66 @@
# 【里程碑】游戏广场评分展示
| 字段 | 值 |
| --- | --- |
| Version | 1.0 |
| Status | implemented(本地验证通过,待用户验收;未部署) |
| Date | 2026-10-01 |
| Parent Spec | [游戏广场评分展示合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏广场评分展示合同) Version 1.0 |
## 目标
在网站游戏广场交付真实评分摘要展示,保持与详情评价及后台隐藏/恢复/删除后的统计一致,并保留原有目录交互。
## 范围
- 游客与登录用户均可在卡片查看 10 分制一位小数均分和评分人数,无有效评价显示“暂无评分”。
- 公开列表和详情返回同形状摘要,统计来自后端全部有效评价,与公开游戏资料采用一致读取快照。
- 空评论计人数,编辑不增加人数;隐藏/删除不计入,恢复重新参与,新版本保留评分。
- 列表一次取得摘要,详情返回广场重新读取,并保留既有筛选与滚动位置。
- 缺少摘要与无人评分明确区分,列表故障沿用重试;桌面和移动卡片均可正常展示和操作。
- 共享契约、生成绑定和配套运行时验证,不改变持久化表或既有数据。
## 不在范围内
- 卡片输入评分、评论预览、评分排序、排行、推荐、AGC 或作者管理页评分展示。
- 统计持久化/缓存/重算任务、推送/轮询、评价写入和管理规则变更、外部 API。
- 原网站评价与后台管理的用户验收、生产部署或游戏发行包验收。
## 依赖与前置条件
- 用户已确认方案、提交文档,并后续授权工程实现;本里程碑代码与本地定向验证已完成。
- 当前基础评价、后台管理与有效评价统计已实现并通过本地验证,其用户验收和生产发布状态独立。
- 现有公开游戏目录、详情、平台认证、数据库服务身份与后端访问链路可用。
- 可复用现有隔离测试游戏和少量评价,完成统计对照及桌面/移动视口检查;不要求新建大批量账号或分页数据。
## 验收标准
- [ ] 游客和登录用户均显示真实 `8.2/10 · 26 人评分` 形状,均分固定一位小数。
- [ ] 无评价及全部隐藏/删除为 `null/0` 和“暂无评分”,缺摘要为“评分暂不可用”,不显示虚构分数。
- [ ] 公开列表、公开详情、评价接口在稳定数据集上的统计一致;多游戏不串数据,统计覆盖全部有效评价而非当前评价页。
- [ ] 空评论计人数,改分只改均分,改文字不改均分;隐藏/恢复/删除后下一次读取正确变化。
- [ ] 下架/封禁或没有有效公开版本的游戏不进入目录;摘要不泄漏评论、管理原因、管理员或个人状态。
- [ ] 广场不逐卡请求评价;列表失败显示原错误/重试,旧响应不覆盖新筛选结果。
- [ ] 详情修改评分后返回广场读取最新值;筛选、封面、卡片点击和滚动恢复行为保留。
- [ ] 桌面和 375px 移动视口下长标题、大人数及评分换行不溢出、不阻挡操作。
- [ ] 新公开响应保证带摘要,作者/旧响应可省略;DTO/绑定/schema 与定向检查通过,持久化数据保持。
- [ ] 以现有数据完成一次隔离 API 摘要对照和桌面/移动页面检查,缺失验证如实标明;无需重跑完整评价/后台管理 E2E。
## 证据要求
- 新增自动化仅覆盖:已有广场页面测试中的正常/零评价/缺摘要展示,以及已有公开响应/契约测试中的新增摘要字段。
- 复用已有测试:有效评价统计、隐藏/恢复/删除、改分、可见性及目录/详情交互,不为每层映射或本增量再复制完整矩阵。
- 运行时:现有两款游戏和少量评价的一次列表/详情/评价摘要对照,确认隐藏过滤与统计不串联;桌面/移动检查评分布局及详情返回后的更新。
- 不新增测试框架、专用 E2E 脚本或大批量分页 fixture;纯文本共享组件由页面测试覆盖。只有新增行为或实际改动的旧行为缺少覆盖时补测试。
## 实现与验证证据
- 公开列表/详情快照同事务携带摘要,限量后聚合;共享 DTO、mapper、2.8.3 生成绑定与公开 no-store 已接入。网站卡片与详情复用纯文本组件,缺字段不会造零值。
- 前端受影响两文件 36 项、API game_distribution 34 项、shared-contracts 4 项、领域 summary 2 项通过。仅补评分文案参数化断言并扩展已有响应测试,未新增测试基础设施。
- module/client 编译、TypeScript typecheck、受影响文件静态/格式检查、DTO parity、生成绑定/schema、编码、文档索引与 diff 检查通过。
- 本机隔离库没有既有评分数据,复用既有 helper 建两个账号、两款游戏和两条空评论评价;三接口摘要 `8/2` 一致,隐藏一条后为 `7/1`,另一游戏 `null/0`。游客/登录列表一致,公开列表/详情 no-store、健康检查通过。
- 1280px 桌面及 375px 移动浏览器显示正常且评分行无横向溢出;详情期间经真实 API 改分,返回广场更新为 `6.0/10 · 1 人评分`。
## 未验证与待验收
验收勾选保留给用户最终确认,临时计划尚未清理。未执行完整仓库测试、完整评价/后台管理 E2E、真实手机、长标题/极大人数浏览器矩阵、浏览器登录改分、实际发行包游玩或生产部署;本次没有重建管理动作/分页矩阵。
@@ -0,0 +1,64 @@
# 【里程碑】网站游戏评分与评价
| 字段 | 值 |
| --- | --- |
| Version | 1.0 |
| Status | implemented(本地验证通过,待用户验收;未部署) |
| Date | 2026-09-30 |
| Parent Spec | [平台入口与玩法链路](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#网站游戏评分与评价合同)中的“网站游戏评分与评价合同”Version 1.0 |
## 目标
在网站公开游戏详情页交付“一用户一游戏一条评分与可选评论 → 查看个人评价 → 编辑与取消/提交 → 公共分页浏览 → 平均分与评分人数更新”的完整行为闭环。
## 范围
- 复用现有平台登录态,游客可浏览公开评价与统计,登录后可保存和修改自己的唯一评价。
- 评分为 1–10 整数且必选,评论可空、最多 4000 Unicode 码点;实时显示字数与上限。
- 已评价默认显示个人记录和编辑按钮,编辑时预填;取消不保存修改,成功提交收起输入模块。
- 公共列表默认每页 20 条,按首次提交时间倒序;包含当前用户和空评论评价,不因编辑改变位置。
- 详情显示平均分与评分人数,无人评分为“暂无评分”;人数不因修改增加,均分覆盖全部评价。
- 评价随游戏身份保留,新版本发布不清空;下架与封禁关闭评价读写,重新公开恢复读取。
- 覆盖并发唯一性、账号切换、失败与重试、移动端和键盘可操作性。
## 不在范围内
- AGC 客户端评价、独立评价页面、游戏广场评分卡片、评论回复/点赞/附件/Markdown。
- 评价删除、评价审核、评分排行/推荐、必须游玩或消费才能评价的门槛。
- 通用评论框架、统计缓存、评分任务或外部 API;不补做游戏发行原里程碑的生产上线验收。
## 依赖与前置条件
- 主规范与本里程碑评审通过,整数评分、分页与取消行为等默认规则已确认;均分/人数已由用户确认纳入范围。
- 当前游戏详情、公开可见性、平台认证、账号公开资料读取与受信服务身份链路在验收环境可用。
- 能建立独立测试账号及公开游戏,运行真实 SpacetimeDB/API 和网站浏览器验收;不得把本地通过当成生产上线。
- 新增评价 schema、共享 DTO 与既有绑定变更在实现前写入本里程碑的单独实施计划,不对现有表进行破坏性修改。
## 验收标准
下列条款已完成本地验证,证据与限制见主规范;保留勾选供用户验收确认。
- [ ] 游客可读公开游戏评价与摘要;未登录不能保存或读取个人评价。
- [ ] 1/10 分和空评论成功,未选/越界/非整数分数与超长评论均被拒。
- [ ] 中文、英文、emoji、空格及换行计数一致,4000/4001 边界、粘贴和中文输入法符合主规范。
- [ ] 已评价先显示自己的记录,编辑预填;取消恢复旧记录,提交中禁用评分选择、评论输入及取消/提交,成功隐藏表单,失败恢复编辑并保留草稿。
- [ ] 首次取消不落库;同一账号/游戏的重复与并发保存只有一条;不能指定他人身份写入。
- [ ] 至少 21 条真实记录验证分页、顺序和总数,自己的评价允许在个人区与公共区各出现一次。
- [ ] 空评论也展示分数并计人数;编辑不增加人数、不改变创建时间或排序位置。
- [ ] 无评价显示“暂无评分”;改分正确更新全部评价均分,改评论不改变均分,分页不影响统计。
- [ ] 切换账号或游戏不残留个人草稿、不接受旧响应覆盖;读取失败不伪装为未评价。
- [ ] 保存成功后此前的个人评价与公共列表读取失效,不覆盖新记录、摘要或列表;快速翻页/重复刷新只接受各区域最新请求的结果,旧请求不改写错误及加载状态。
- [ ] 游戏下架/封禁后读写不可见,恢复公开后仍能读取已有评价,新版本不清空评价。
- [ ] 评价读取或保存故障不阻断既有游戏资料与游玩;桌面/移动/键盘操作均可用。
- [ ] 定向测试、网站类型、DTO、schema/生成绑定、真实 API/SpacetimeDB/browser smoke 及编码/文档索引/diff 检查有可复核结果。
## 证据要求
- 自动化:评分/字数/唯一性与修改规则、统计、分页、页面交互及账号切换定向测试。
- 运行时:真实 SpacetimeDB/API 上的两账号写入、并发首次保存与分页统计;真实浏览器编辑/取消/提交、移动端字数提示与键盘评分。
- 边界:未登录、伪造身份、不可见游戏、4000/4001 字符、0/11/非整数分数、响应丢失与迟到响应。
- 证据按主规范条款逐项记录环境、操作、结果与未验证原因,原游戏发行证据不自动代替本次验收。
## 实施与验证状态
实现与本地验收已完成,详细证据已回写主规范:前端 77 项、领域 18 项、API 31 项、DTO 4 项、真实数据库/API 49 项(21 条评价)与桌面/移动视口浏览器操作通过。网站类型、定向严格类型/ESLint、DTO/schema/绑定、DDD/runtime access、编码/索引/diff 检查通过。未部署,未验证物理手机/真实系统输入法或发行资源游玩;用户验收后清理本里程碑和实施计划。
@@ -1,11 +1,38 @@
# 决策记录
## 2026-10-01 游戏广场评分展示边界
- 用户确认广场卡片增加一位小数的 10 分制平均分与评分人数,无有效评价显示“暂无评分”;保留现有排序、筛选、卡片打开详情及返回上下文。
- 公开游戏列表和详情共用投影,随现有请求返回 ratingSummary;复用后端有效评价统计并排除隐藏记录,不逐卡请求评价,不增加统计表、缓存或重算任务。
- 共用 DTO 可选字段兼容作者及旧响应,当前公开列表/详情保证返回;缺字段显示“评分暂不可用”,不能伪装为无人评分。读取与后台管理后的下一次刷新一致,不增加推送/轮询。
- 本增量不改变持久化表或评价写入,仅同步读取投影、DTO 与生成绑定;不扩展评分排序、推荐、AGC 或外部 API。
- 用户要求测试保持简单:仅补卡片正常/零评价/缺摘要及公开摘要契约断言,复用已有统计/管理/目录测试和少量隔离数据 smoke;不新增专用 E2E、分页 fixture 或逐层重复测试。
- 权威入口:[游戏广场评分展示合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏广场评分展示合同)。已完成工程实现及本地定向验证,待用户验收,未部署;持久化表未变,公开 procedure 返回类型与后端绑定需配套发布。
## 2026-10-01 后台游戏评价管理规则
- 用户确认新增管理员隐藏/删除评价,后台不能修改分数或正文;隐藏整条评价并从公共列表、平均分、人数和公共分页总数排除,恢复后重新参与。个人区域固定提示“已被管理员隐藏”,用户仍可编辑但不能自动恢复公开。
- 隐藏和删除必须填写原因,恢复不要求;原因仅后台展示。删除物理移除,不能恢复,用户可重新评价,唯一规则继续成立。
- 当前方案范围为游戏名称选择/ID定位、评价用户 ID、评论关键词、状态四类组合筛选,以及分页、详情、单条操作和持久操作记录。不增加批量、导出、举报、自动审核或评分/时间范围筛选。
- 实现边界:评价表末尾追加默认 false 的 is_hidden;新增私有管理记录,事务保存操作人/原因/时间,以创建时间区分删除后重建记录,同 key 重试不得再次操作新评价。不增加统计缓存;用户编辑保持隐藏状态,管理操作不改变用户内容时间。
- 状态:用户确认按方案实施;后台与网站联动已实现并通过本地存量升级、真实 HTTP 和浏览器验证,证据见主规范。待用户验收,未部署。产生隐藏记录后不得直接回退到未过滤隐藏状态的旧后端。
- 权威入口:[后台游戏评价管理合同](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#后台游戏评价管理合同);活动[里程碑](../plans/【里程碑】后台游戏评价管理-2026-10-01.md)与[实施计划](../plans/【实施计划】后台游戏评价管理-2026-10-01.md)。
## 2026-09-30 网站游戏评价范围与状态边界
- 已确认需求:网站游戏详情支持每账号每游戏唯一一条 1–10 分评分和可空的评论(最多 4000 字符),可修改自己的评价;个人区默认展示已有评价并提供编辑预填,公共列表分页且不排除自己。
- 已确认扩展:详情显示真实平均分与评分人数,空评论计人数,修改不增加人数;当前先由后端评价记录计算,不增加统计缓存。
- 状态:用户已确认按最新方案实现;整数评分、默认每页 20 条、创建时间排序、取消行为与游戏维度保留作为现行合同。网站与后端实现已落地,本地验收证据见主规范;用户验收与生产发布单独确认。原发行 Version 0.2 的排除项不再被解释为永久禁止新增用户评价。
- 实现边界:新增私有 `game_distribution_review` 表和三条评价 API,游戏/账号组合主键保证唯一;可见性与写入同事务,分页与均分来自一致快照,作者资料读时关联账号。网站用游戏/账号上下文隔离草稿,以读取序号隔离旧成功、错误和加载结束,保存期间冻结输入。
- 权威入口:[平台入口与玩法链路](../../【玩法创作】平台入口与玩法链路-2026-05-15.md#网站游戏评分与评价合同);执行验收使用[独立里程碑](../plans/【里程碑】网站游戏评分与评价-2026-09-30.md),不得把既有发行或本次文档检查当作评价功能上线证据。
## 2026-10-01 生产 Nginx 以模板为唯一来源:host-only 块独立成 snippet、退役路由不做显式 404
- 背景:线上主站 `genarrative.conf` 长期手工维护,`profile` 未进 SPA allowlist 导致 `/profile` 刷新 404,`client_max_body_size` 也停在 `64m`;同时线上存在 4 处仓库模板没有的 host-only 块(画廊读取限流、`/finance-forecast/`、`/medical-science/`、`/home/` 官网首页入口),直接用 `Genarrative-Server-Provision` 覆盖会静默删除它们。
- 决策:生产 vhost 以 `deploy/nginx/genarrative.conf` 为唯一来源;生产机专属路径收进 `deploy/nginx/snippets/genarrative-host-extras.conf`,由主模板 include、由 Server-Provision 安装,新增平台路由仍必须在主模板内声明并同步 `deploy/pingora/nginx-route-parity.matrix.json` 与 Pingora 网关。snippet 内的 location 有意不在矩阵覆盖范围,Pingora 接公网 443 前必须单独确认这些路径的处理方式。
- 边界:退役路由(`/match3d`、`/puzzle`、`/runtime/*`、`/gallery/*/detail`、`/works/detail`、`/worlds/detail`、`/bark-battle` 等)不再进 SPA allowlist,也不配置显式 404,统一落 `location /` 的 `error_page 404 /404.html`。`/home/` 是 2026-08-11 官网拆分前的历史入口,是否退役需与官网侧一起决定。
- 验证方式:`node scripts/check-nginx-spa-routes.mjs`、`node scripts/check-pingora-route-parity.mjs`、`npm run check:production-ops`、`npm run check:encoding`、`git diff --check`、`bash -n scripts/jenkins-server-provision.sh`;线上改后按生效配置烟测 `/profile`、模板 12 条 SPA 路由、`/admin/`、`/home/`、`/finance-forecast/`、`/medical-science/`、画廊 API 与 `/games/game_<id>/…` 发行网关。
## 2026-10-01 DirectProject 审批拒绝原因留痕
- 决策:宿主拒绝 app-server 的审批 / 交互请求时,原因必须落 AppData `RUST` 日志。稳定键 `agent.direct_codex.approval.denied`,字段为 `thread_id` / `method` / `reason` / `distinct_reasons`;未绑定宿主执行器时另记 `agent.direct_codex.interaction.no_adapter`(`method` / `outcome`,`outcome` 区分 `decline` / `empty-permissions` / `unsupported-method`);回包未送达另记 `agent.direct_codex.approval.response_delivery_failed`,`cause` 区分 `response-write-failed` 与 `turn-bind-mismatch`。