1
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# 网页端首页模块内容同步移动端首页 2026-04-30
|
||||
|
||||
## 背景
|
||||
|
||||
平台首页移动端已经收口为 `推荐 / 今日游戏 / 游戏分类` 三个频道。网页端首页保留宽屏布局,但模块文案和数据语义仍残留 `趋势关注`、`最新发布`、`作品广场` 等旧入口口径,导致双端首页内容不一致。
|
||||
|
||||
## 落地规则
|
||||
|
||||
1. 网页端首页只调整模块内容和文案,不改变现有宽屏栅格、面板数量与卡片布局。
|
||||
2. `推荐` 使用移动端推荐频道同源数据:精选作品优先,并与最新公开作品去重合并。
|
||||
3. `趋势关注` 改为 `今日游戏`,数据只取今天首次发布的公开作品,不把今天更新的旧作品计入今日游戏。
|
||||
4. `最新发布` 改为 `作品分类`,数据使用当前分类组内按综合指标排序后的作品。
|
||||
5. 首页首屏和快捷区域不再展示 `作品广场` 文案。
|
||||
6. 删除首页中的 `公开作品` 兜底模块;快捷区域只在存在最近作品或最近浏览时显示,不再用空模块占位。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 网页端首页仍保持原有 hero、右侧列表、中部双栏与底部网格布局。
|
||||
2. 网页端可见模块包含推荐、今日游戏、作品分类。
|
||||
3. 网页端首页不再出现 `趋势关注`、`最新发布`、`作品广场`。
|
||||
4. 无最近作品和最近浏览时,网页端首页不再展示 `公开作品` 快捷模块。
|
||||
5. 今日游戏与移动端 `今日游戏` 频道使用同一发布时间过滤规则。
|
||||
@@ -0,0 +1,95 @@
|
||||
# 拼图失败续时与存档投影设计 2026-05-01
|
||||
|
||||
## 背景
|
||||
|
||||
拼图运行时已经有倒计时失败态、道具确认扣费、下一关推荐和个人存档页,但失败后的玩家选择与拼图作品存档投影还没有闭环:
|
||||
|
||||
1. 倒计时结束后只能返回,不能重新开始或付费继续。
|
||||
2. 进入拼图作品后,存档页没有稳定出现一条可恢复的拼图游戏存档。
|
||||
3. 每通过一关后,存档应该更新到下一关入口,而不是停留在旧关卡。
|
||||
|
||||
本轮只补齐拼图运行态与存档投影,不迁移旧 `server-node`,不新增平行存档页。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 限定时间内未完成时弹出失败面板。
|
||||
2. 失败面板提供两个选择:
|
||||
- `重新开始`:重新开启当前拼图关卡,不扣陶泥币。
|
||||
- `继续1分钟`:先弹出确认窗口,确认后消耗 `1` 陶泥币,并把当前失败关卡恢复为 `playing`,剩余时间固定为 `60000ms`。
|
||||
3. 进入拼图作品后立即写入 `profile_save_archive`,存档页显示拼图存档。
|
||||
4. 每次进入下一关后更新同一条拼图存档,使存档恢复时指向最新可继续的关卡。
|
||||
|
||||
## 运行态规则
|
||||
|
||||
### 失败续时
|
||||
|
||||
`PuzzleRuntimePropKind` 增加 `extendTime`,沿用现有道具确认与扣费接口:
|
||||
|
||||
1. 前端只在 `runtimeStatus = failed` 时开放 `继续1分钟`。
|
||||
2. 点击后打开独立确认弹窗,文案只显示短标题和 `消耗 1 陶泥币`。
|
||||
3. 正式 run 继续走 `POST /api/runtime/puzzle/runs/:runId/props`。
|
||||
4. `api-server` 将 `extendTime` 映射为账单 `asset_kind = puzzle_prop_extend_time`。
|
||||
5. SpacetimeDB 侧只允许失败关卡续时;续时成功后:
|
||||
- `status = playing`
|
||||
- `remaining_ms = 60000`
|
||||
- `elapsed_ms = None`
|
||||
- `cleared_at_ms = None`
|
||||
- 清空暂停与冻结生效点
|
||||
- 调整 `paused_accumulated_ms`,保证从确认成功那一刻开始完整倒计时 `60` 秒
|
||||
|
||||
本地调试 run 没有真实钱包,沿用本地道具兜底:仍弹确认窗,但不扣真实陶泥币。
|
||||
|
||||
### 重新开始
|
||||
|
||||
重新开始不复用旧失败棋盘,而是重新创建当前关卡的 run:
|
||||
|
||||
1. 前端从当前 `currentLevel.profileId` 和 `currentLevel.levelId` 调用 `startPuzzleRun`。
|
||||
2. 新 run 的棋盘重新打乱、倒计时重置。
|
||||
3. 如果当前关卡来自作品内部第 N 关,必须携带 `levelId`,避免重开误回作品第 1 关。
|
||||
4. 旧失败 run 保留为历史运行记录,不在前端继续使用。
|
||||
|
||||
为支持第 3 点,`PuzzleRuntimeLevelSnapshot` 增加 `levelId: string | null`。
|
||||
|
||||
## 存档投影规则
|
||||
|
||||
复用现有 `profile_save_archive` 表,不新增拼图专属存档表。拼图存档固定规则:
|
||||
|
||||
1. `world_key = puzzle:{entry_profile_id}`。
|
||||
2. `world_type = PUZZLE`。
|
||||
3. `profile_id = entry_profile_id`,保证同一个作品链只覆盖一条存档。
|
||||
4. `world_name` 使用当前关卡名。
|
||||
5. `subtitle` 使用 `第 N 关`。
|
||||
6. `summary_text` 使用当前状态:
|
||||
- playing:`拼图进行中`
|
||||
- failed:`关卡失败`
|
||||
- cleared:`关卡已完成`
|
||||
7. `cover_image_src` 使用当前关卡正式图。
|
||||
8. `game_state_json` 保存最小拼图恢复载荷:
|
||||
- `runtimeKind = "puzzle"`
|
||||
- `runId`
|
||||
- `entryProfileId`
|
||||
- `currentProfileId`
|
||||
- `currentLevelIndex`
|
||||
- `currentLevelId`
|
||||
- `status`
|
||||
|
||||
## 写入时机
|
||||
|
||||
SpacetimeDB 拼图运行态每次持久化 run 时同步刷新存档:
|
||||
|
||||
1. `start_puzzle_run`:创建 run 后立即写入拼图存档。
|
||||
2. `advance_puzzle_next_level`:进入下一关后更新同一条存档。
|
||||
3. `use_puzzle_runtime_prop(extendTime)`:续时成功后更新状态。
|
||||
4. `get_puzzle_run` 导致失败态落库时,也同步更新为失败存档。
|
||||
|
||||
排行榜提交只负责成绩与通关态,不新增存档规则;如果它把 run 状态更新为通关,也跟随 run 持久化刷新存档。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 倒计时归零后失败弹窗有 `重新开始` 和 `继续1分钟`。
|
||||
2. 点击 `继续1分钟` 后先出现扣费确认,确认成功后失败弹窗关闭并恢复 `60` 秒倒计时。
|
||||
3. 陶泥币余额不足时确认弹窗保留,并展示错误。
|
||||
4. 点击 `重新开始` 后当前关卡重新打乱并重置倒计时。
|
||||
5. 进入拼图作品后,存档页出现 `worldType = PUZZLE` 的拼图存档。
|
||||
6. 通过一关进入下一关后,同一条存档更新到新关卡。
|
||||
7. 定向前端测试、Rust 拼图模块测试与编码检查通过。
|
||||
@@ -10,10 +10,13 @@
|
||||
|
||||
1. 玩家在创作页点击“拼图”入口时,前端必须立即创建一个新的拼图 Agent session,并同步生成一条 `publicationStatus = draft` 的拼图作品卡;此时不触发 `compile_puzzle_draft`,不生成图片,不进入生成进度页。
|
||||
2. 新 session 的 `seedText` 允许为空;SpacetimeDB 侧用空锚点和空表单草稿初始化,不得把默认题材文案写入玩家草稿字段。
|
||||
3. 初始表单输入自动保存到 session 的 `draft_json` 与 `puzzle_work_profile` 投影。保存字段只包含 `workTitle`、`workDescription`、`pictureDescription`、可推断标签和一个 `generationStatus = idle` 的默认关卡;参考图只保存在当前前端会话内,不落入 SpacetimeDB。
|
||||
3. 初始表单输入自动保存到 session 的 `draft_json` 与 `puzzle_work_profile` 投影。保存字段只包含 `workTitle`、`workDescription`、`pictureDescription`、可推断标签和一个 `generationStatus = idle` 的默认关卡;草稿设置阶段默认关卡名称必须为空,不得写入“第一关”“第1关”或作品名称作为默认值。参考图只保存在当前前端会话内,不落入 SpacetimeDB。
|
||||
4. 玩家在生成草稿前退出,再次从创作中心点击这条拼图草稿时,必须恢复到填表页,并回填之前自动保存的作品名称、作品描述和画面描述;只有执行 `compile_puzzle_draft` 且生成结果页草稿后,草稿入口才进入结果页。
|
||||
5. 表单自动保存走 `save_puzzle_form_draft` action,不消耗陶泥币,不生成图片,不改变 `stage = collecting_anchors`;生成草稿按钮仍单独触发 `compile_puzzle_draft` 并进入进度页。
|
||||
6. 点击拼图入口始终创建新草稿,不复用上一次未完成 session;恢复旧草稿只通过“我的创作”中的草稿卡进入。
|
||||
7. 若 Maincloud 仍运行旧 wasm,缺少 `save_puzzle_form_draft` procedure,前端提交生成或生成失败页重试时不得继续复用空 `seedText` 的表单 session,必须用当前表单 payload 新建带真实 seed 的 session 再执行 `compile_puzzle_draft`。
|
||||
8. api-server 也要兼容旧 wasm:`save_puzzle_form_draft` 缺失时,自动保存 action 降级返回当前 session;`compile_puzzle_draft` 前置保存缺失且当前 session 为空 seed 时,创建一条带表单 seed 的替代 session 后继续编译,避免再次暴露 `No such procedure`。
|
||||
9. 正式修复仍是发布最新 SpacetimeDB wasm。当前 Maincloud `xushi-p4wfr` 的迁移操作员表为空,但旧库引导密钥来自旧 wasm,本次临时生成的新引导密钥无法授权导出迁移,需使用已有迁移操作员 token 或数据库 owner 重新授权后发布;禁止为绕过冲突直接清库,除非明确接受数据丢失。
|
||||
|
||||
1. 作品名称为必填字段,保存到 `workTitle`,兼容写入旧 `seedText`,同时作为作品级 `workTitle` 的真相源。
|
||||
2. 作品描述为必填字段,保存到 `workDescription`,作为作品详情页、作品列表和发布资料中的 `summary` 真相源。
|
||||
@@ -51,7 +54,7 @@
|
||||
2. `PuzzleResultDraft.workDescription`:作品描述,旧 `summary` 只作为兼容字段同步为作品描述。
|
||||
3. `PuzzleResultDraft.themeTags`:作品标签,仍限制 3 到 6 个。
|
||||
4. `PuzzleResultDraft.levels[]`:关卡列表。每个关卡包含 `levelId`、`levelName`、`pictureDescription`、`candidates`、`selectedCandidateId`、`coverImageSrc`、`coverAssetId`、`generationStatus`。
|
||||
5. 首次草稿生成时必须创建一个默认关卡,`levelId = puzzle-level-1`,`pictureDescription = 表单画面描述`,首图生成后直接写入该关卡。
|
||||
5. 首次草稿生成时必须创建一个默认关卡,`levelId = puzzle-level-1`,`pictureDescription = 表单画面描述`,草稿设置阶段 `levelName` 为空;首图生成后可由后端根据画面描述和图片语义生成关卡名称并写入该关卡。
|
||||
6. 关卡名称由后端基于画面描述和图片语义输入生成;无可用语义时按题材标签与序号兜底,禁止继续直接使用作品名称作为关卡名称。
|
||||
7. 旧草稿或旧作品缺少 `levels` 时,读取层必须由旧 `levelName`、`summary`、`coverImageSrc`、`candidates` 补出一个兼容关卡,避免历史草稿无法打开。
|
||||
|
||||
@@ -69,14 +72,31 @@
|
||||
10. `ExecutePuzzleAgentActionRequest` 必须保留 `pictureDescription` 字段。表单直达生成时,`compile_puzzle_draft` 优先用 `pictureDescription` 作为首图 prompt,再回退到旧 `promptText`;避免生成页展示的是玩家画面描述,但后端实际用作品名称或旧摘要出图。
|
||||
11. `compile_puzzle_draft` 中的图片上游失败不得映射成 `400 BAD_REQUEST`。DashScope 返回 `InvalidParameter` 或任务失败时,api-server 统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留“拼图图片生成失败:...”的业务原因,避免生成页只显示“请求参数不合法”。
|
||||
12. `compile_puzzle_draft` 前置陶泥币预扣失败不得映射成 `400 BAD_REQUEST`。余额不足返回 `409 CONFLICT`,SpacetimeDB procedure 不可用、绑定不匹配、钱包服务异常等统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留真实钱包错误。
|
||||
13. 生成拼图作品草稿动作涉及的表单 seed prompt 与首图 prompt 来源选择统一收口在 `server-rs/crates/api-server/src/prompt/puzzle/draft.rs`;`puzzle.rs` 只负责调用 SpacetimeDB、计费、图片服务和持久化,不再直接拼草稿 prompt 文本。
|
||||
|
||||
## 结果页
|
||||
|
||||
拼图草稿结果页分为两个 Tab:
|
||||
|
||||
1. 拼图关卡列表:默认展示草稿生成出的第一关。列表项参考 RPG 草稿卡片样式,显示画面图、关卡名称和轻量状态。支持新增关卡、删除关卡。点击列表项进入独立关卡详情页,不在列表项下方展开。关卡详情页可编辑关卡名称、画面描述、重新生成画面,并支持单独体验该关卡。
|
||||
1. 拼图关卡列表:默认展示草稿生成出的第一关。列表项参考 RPG 草稿卡片样式,显示画面图、关卡名称和轻量状态。支持新增关卡、删除关卡。点击列表项进入独立关卡详情页,不在列表项下方展开。关卡详情页可编辑关卡名称、画面描述、生成或重新生成画面,并在已有正式图后支持关卡测试。
|
||||
2. 作品信息:展示并编辑作品名称、作品描述、作品标签。
|
||||
|
||||
### 2026-04-30 关卡列表卡片交互补充
|
||||
|
||||
1. 关卡列表卡片的删除按钮与关卡名称放在同一信息行,按钮固定在卡片右下角;不得再单独占用一整条底部分隔栏。
|
||||
2. 关卡图片、序号与名称区域仍作为打开关卡详情的主点击区;删除按钮只触发删除,不进入详情。
|
||||
|
||||
### 2026-04-30 关卡详情面板交互补充
|
||||
|
||||
1. 关卡详情面板内容区按移动端优先的单列顺序展示:`关卡名称 -> 画面图 -> 画面描述`。其中画面图只在该关卡已有正式图时出现;新建关卡或画面为空的关卡不展示空图占位模块。
|
||||
2. 画面生成主按钮固定吸底,始终位于关卡详情面板底部操作区。若当前关卡还没有正式图,按钮文案为“生成画面”;已有正式图后,按钮文案为“重新生成画面”。
|
||||
3. 关卡已有正式图后,底部操作区在生成按钮上方新增单独的关卡测试入口,原“体验该关”文案收口为“关卡测试”。无正式图时不展示该入口。
|
||||
4. 底部吸底操作区只承载动作按钮,不默认写玩法说明或规则解释,避免压缩移动端编辑空间。
|
||||
5. 关卡详情面板内触发生成画面时,前端必须把当前编辑态完整 `levelsJson` 随 `generate_puzzle_images` action 一起提交。这样新建关卡在自动保存完成前立即生成,也能由后端写回目标关卡。
|
||||
6. api-server 处理 `generate_puzzle_images` 时,若 action 带有 `levelsJson`,必须用这份关卡快照覆盖本次生成的草稿关卡视图后再定位 `levelId`。若请求明确传入 `levelId` 但关卡列表中不存在该关卡,必须返回错误,不得静默回退第一关。
|
||||
7. 历史拼图素材入口只在已有正式图的 `画面图` 区域右下角展示,不再放在 `画面描述` 输入区;本地上传参考图入口仍保留在画面描述输入区右下角。
|
||||
8. 历史拼图素材列表必须由服务端按当前登录账号过滤,只返回 `asset_kind = puzzle_cover_image` 且 `owner_user_id = 当前账号` 的资产;不得依赖前端过滤,也不得展示其他账号素材。
|
||||
|
||||
画面描述区域不再展示候选图实际 prompt 或“请生成一张适合……”之类内部提示词模块。参考图入口保留在画面描述编辑区域内,便于重新生成时继续带入。结果页编辑关卡画面描述时只同步该关卡 `pictureDescription`;作品描述只在作品信息 Tab 编辑,作品详情页不得再回退使用画面描述。
|
||||
|
||||
## 验收
|
||||
@@ -85,5 +105,5 @@
|
||||
2. 点击确认后进入拼图草稿生成进度页,并自动完成草稿编译、首图生成、正式图选择。
|
||||
3. 首图生成请求使用玩家画面描述作为 prompt;上传参考图时走图生图;作品详情页展示玩家作品描述。
|
||||
4. 结果页包含“拼图关卡”和“作品信息”两个 Tab;关卡列表默认至少一关,支持新增、删除和进入关卡详情。
|
||||
5. 关卡详情页支持重新生成画面和单独体验该关卡。
|
||||
5. 关卡详情页支持生成或重新生成画面;已有正式图后显示吸底“关卡测试”入口。
|
||||
6. 发布、作品测试、自动保存作品名称、作品描述、作品标签和关卡列表仍可用。
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# 拼图下一关与相似作品接续设计 2026-04-30
|
||||
|
||||
## 背景
|
||||
|
||||
拼图通关结算弹窗已有“下一关”按钮,但当前按钮依赖 `recommendedNextProfileId`。这会带来两个问题:
|
||||
|
||||
1. 当前作品还有未玩的内部关卡时,按钮可能因为没有跨作品推荐而被禁用。
|
||||
2. 当前作品全部关卡玩完后,只返回单个推荐作品,无法满足“三个相似作品由用户选择”的交互。
|
||||
|
||||
本轮只修复拼图运行态接续链路,不迁移旧 `server-node`,不在前端计算正式相似度。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 通关后默认点击“下一关”,优先加载当前拼图作品的下一关。
|
||||
2. 当前作品没有下一关时,后端按标签语义相似度选出相似度最高的三个已发布作品。
|
||||
3. 用户在通关弹窗里点击候选作品后,进入该作品并从第 1 关重新开始。
|
||||
4. 移动端优先,候选卡片要紧凑,不写玩法说明类文案。
|
||||
|
||||
## 数据契约
|
||||
|
||||
`PuzzleRunSnapshot` 增加:
|
||||
|
||||
1. `nextLevelMode: "sameWork" | "similarWorks" | "none"`。
|
||||
2. `nextLevelProfileId: string | null`:同作品下一关或跨作品推荐的默认目标。
|
||||
3. `nextLevelId: string | null`:同作品下一关的 `levelId`;跨作品时为 `null`。
|
||||
4. `recommendedNextWorks: PuzzleRecommendedNextWork[]`:跨作品候选,最多 3 个。
|
||||
|
||||
`PuzzleRecommendedNextWork` 字段:
|
||||
|
||||
1. `profileId`
|
||||
2. `levelName`
|
||||
3. `authorDisplayName`
|
||||
4. `themeTags`
|
||||
5. `coverImageSrc`
|
||||
6. `similarityScore`
|
||||
|
||||
保留 `recommendedNextProfileId` 作为旧字段兼容,但前端新逻辑不再只依赖它。
|
||||
|
||||
## 后端规则
|
||||
|
||||
1. SpacetimeDB 侧在 `start / get / swap / drag / leaderboard / advance` 后刷新下一关状态。
|
||||
2. 当前作品存在未玩的下一张关卡图时:
|
||||
- `nextLevelMode = "sameWork"`
|
||||
- `nextLevelProfileId = 当前作品 profileId`
|
||||
- `nextLevelId = 下一关 levelId`
|
||||
- `recommendedNextWorks = []`
|
||||
3. 当前作品没有内部下一关时:
|
||||
- 使用拼图现有 `recommendation_score = tagSimilarity * 0.7 + sameAuthor * 0.3`
|
||||
- `tagSimilarity` 优先复用 RPG/build 标签语义亲和度模型;两侧标签未命中该语义模型时,回退到规范化标签 Jaccard
|
||||
- 排除当前 run 已玩过的作品;若池子为空,允许回收但不连续重复上一关作品
|
||||
- 返回最高的 3 个候选
|
||||
4. `advance_puzzle_next_level`:
|
||||
- `nextLevelMode = sameWork` 时加载当前作品的下一关,并继续当前 run。
|
||||
- `nextLevelMode = similarWorks` 时默认加载候选第一项,并从该作品第 1 关重新开始。
|
||||
5. `local-next-level` 兼容接口同样优先找同作品下一关;没有时才返回相似作品候选或旧草稿兜底。
|
||||
|
||||
## 前端规则
|
||||
|
||||
1. 结算弹窗:
|
||||
- `sameWork`:主按钮显示“下一关”,直接触发默认推进。
|
||||
- `similarWorks`:展示最多 3 个作品候选卡;用户点击卡片进入候选作品。
|
||||
- `none`:禁用下一关入口。
|
||||
2. 底部通关后入口:
|
||||
- `sameWork` 保留“下一关”。
|
||||
- `similarWorks` 显示“换个作品”,点击后打开结算弹窗供选择。
|
||||
3. 所有正式相似度计算只信任后端返回,不在 UI 里重新算。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 当前作品有下一关时,点击“下一关”进入当前作品下一关。
|
||||
2. 当前作品没有下一关时,通关弹窗显示最多 3 个相似作品。
|
||||
3. 点击相似作品后进入该作品第 1 关。
|
||||
4. 旧 `recommendedNextProfileId` 为空时,只要 `nextLevelMode = sameWork`,按钮仍可用。
|
||||
5. 拼图 runtime 单测、Rust 拼图模块测试和编码检查通过。
|
||||
@@ -41,6 +41,15 @@
|
||||
2. 单块交换、拖到合并块后拆分、合并块整体重排,继续沿用当前本地运行态规则。
|
||||
3. 不新增前端本地裁决,不把玩法真相从既有运行态实现中分叉出去。
|
||||
|
||||
### 3.4 点击触觉反馈
|
||||
|
||||
移动端用户每次按下可交互拼图片时,需要触发一次短促手机震动:
|
||||
|
||||
1. 震动触发点放在 `pointerdown`,让点击选中、按住准备拖动与拖起都有一致手感。
|
||||
2. 同一次按下会话只触发一次震动,后续连续移动不重复震动。
|
||||
3. 使用浏览器标准 `navigator.vibrate([12])`,不支持震动能力的设备静默跳过。
|
||||
4. 该反馈只属于前端表现层,不影响拖拽落点、交换、合并、拆分与通关判定。
|
||||
|
||||
## 4. 验收标准
|
||||
|
||||
1. 单块拖动时拼块视觉位置应紧跟手指或鼠标,不再出现明显缓动拖尾。
|
||||
@@ -48,3 +57,4 @@
|
||||
3. 点击选中与拖动阈值判定仍保持原语义,不因为优化误触发交换。
|
||||
4. 运行时现有结算弹窗、排行榜和下一关入口不受影响。
|
||||
5. 定向测试覆盖拖动提交坐标的行为,并运行编码检查确保中文文档未被写坏。
|
||||
6. 移动端点击拼图片时立即触发一次短震,同一次按下后的连续移动不重复触发。
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
## 文档列表
|
||||
|
||||
- [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md):冻结 SpacetimeDB 表结构变更约束、自动迁移可接受范围、冲突后的系统行为,以及保留旧数据的增量迁移流程;凡涉及 `spacetime publish`、表字段调整或 `migration.rs` 对齐时优先参考。
|
||||
- [SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md](./SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md):记录本地 standalone 启动时报 `mismatched database identity` 的 root-dir/replica 数据残留根因、备份重建步骤和脚本诊断口径。
|
||||
- [LLM_MODEL_ROUTING_RPG_AND_CREATION_2026-04-30.md](./LLM_MODEL_ROUTING_RPG_AND_CREATION_2026-04-30.md):冻结 RPG 运行时剧情推理使用 `doubao-seed-character-251128` 的 `/chat/completions`,以及所有模板创作大模型推理使用 `deepseek-v3-2-251201` 的 `/responses`。
|
||||
- [PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md](./PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md):记录平台首页底部 dock 在手机浏览器地址栏展开时脱离可见区域的根因,以及 `100dvh`、固定底部锚点和安全区占位的修复口径。
|
||||
- [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md):记录 SpacetimeDB private 表迁移 JSON 导出/导入 procedure、迁移操作员授权、HTTP 413 分片导入、Jenkins 自动迁移回灌和导入脚本参数。
|
||||
@@ -19,6 +20,8 @@
|
||||
- [PUZZLE_IMAGE_AND_FRONTEND_RULES_ALIGNMENT_2026-04-29.md](./PUZZLE_IMAGE_AND_FRONTEND_RULES_ALIGNMENT_2026-04-29.md):记录拼图生成图片回到 1:1,运行时拖动、交换、合并与拆分由前端即时裁决,以及移动端棋盘贴近屏幕边缘的落地边界。
|
||||
- [PUZZLE_FORM_CREATION_FLOW_2026-04-29.md](./PUZZLE_FORM_CREATION_FLOW_2026-04-29.md):冻结拼图填表式创作入口、初始表单自动保存草稿、生成前退出后的表单恢复,以及草稿编译/首图生成的前后端边界。
|
||||
- [PUZZLE_LEADERBOARD_FRONTEND_LEVEL_AND_RPG_COMING_SOON_2026-04-30.md](./PUZZLE_LEADERBOARD_FRONTEND_LEVEL_AND_RPG_COMING_SOON_2026-04-30.md):记录拼图第二关排行榜提交以前端当前关卡为准、不被 SpacetimeDB 旧 run 快照误杀,以及 RPG 创作入口改为敬请期待的落地边界。
|
||||
- [PUZZLE_NEXT_LEVEL_AND_SIMILAR_WORK_HANDOFF_2026-04-30.md](./PUZZLE_NEXT_LEVEL_AND_SIMILAR_WORK_HANDOFF_2026-04-30.md):记录拼图通关后优先同作品下一关、无下一关时按 RPG/build 标签语义相似度返回三个候选作品并从第 1 关接续的落地规则。
|
||||
- [PUZZLE_FAILURE_EXTENSION_AND_SAVE_ARCHIVE_2026-05-01.md](./PUZZLE_FAILURE_EXTENSION_AND_SAVE_ARCHIVE_2026-05-01.md):记录拼图失败后重新开始/付费续时,以及进入作品与过关后同步存档页投影的落地规则。
|
||||
- [RPG_SCENE_ACT_PREVIEW_BOOTSTRAP_FIX_2026-04-30.md](./RPG_SCENE_ACT_PREVIEW_BOOTSTRAP_FIX_2026-04-30.md):记录编辑器幕预览卡在“正在载入这一幕”时的启动态根因,收口预览本地运行态装配与禁持久化首段 story 注入。
|
||||
- [PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md](./PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md):记录拼图结果页名称与标签编辑自动保存、发布门槛统一到 `3~6` 标签,以及前端发布校验不再被旧 session blocker 卡死的修复口径。
|
||||
- [WORK_AUTHOR_ID_RESOLUTION_2026-04-30.md](./WORK_AUTHOR_ID_RESOLUTION_2026-04-30.md):记录作品作者以 `owner_user_id` 为真相源,API 按用户 ID 解析最新昵称与公开用户码,历史 `author_display_name` 仅作为兼容回退。
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
## 体验规则
|
||||
|
||||
- 等待态继续复用 `RouteLoadingScreen`,只显示简短加载文案,不在 UI 中追加规则说明。
|
||||
- `RouteLoadingScreen` 必须读取 `tavernrealms.settings.v1` 中的 `platformTheme`,并复用 `platform-theme--light / platform-theme--dark` 与 `platform-body-fill / platform-text-*` token,不能硬编码独立深色背景。
|
||||
- 页面主体隐藏时使用 `visibility: hidden`,不能用 `display: none`,否则浏览器可能不触发布局与图片加载。
|
||||
- 图片加载失败不直接改写业务 UI;后续仍由原页面的兜底图、占位图或错误态处理。
|
||||
|
||||
## 涉及文件
|
||||
|
||||
- `src/routing/RouteImageReadyGate.tsx`
|
||||
- `src/routing/RouteLoadingScreen.tsx`
|
||||
- `src/routing/RouteImageReadyGate.test.ts`
|
||||
- `src/main.tsx`
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
|
||||
1. 拼图提示词参考 RPG 的目录组织,统一迁入 `server-rs/crates/api-server/src/prompt/puzzle/`。
|
||||
2. `prompt/puzzle/agent_chat.rs` 承接拼图共创 Agent 的 system prompt、单轮 JSON 输出契约、用户提示词与 anchor pack / 聊天记录提示词组装。
|
||||
3. `prompt/puzzle/image.rs` 承接拼图图片生成正式提示词与默认反向提示词。
|
||||
4. `puzzle_agent_turn.rs` 只保留 LLM 调用、结果解析、阶段判断和 SpacetimeDB 写回输入构造,不再内联拼图聊天提示词正文。
|
||||
5. `puzzle.rs` 只保留拼图路由、计费、DashScope、OSS、候选图持久化和运行态编排,不再内联拼图图片提示词正文。
|
||||
6. 后续调整拼图共创问法、输出契约、图片画面约束或反向提示词时,优先修改 `prompt/puzzle/`,不要在 `puzzle.rs` 或 `puzzle_agent_turn.rs` 中新增提示词正文。
|
||||
3. `prompt/puzzle/draft.rs` 承接生成拼图作品草稿动作里的表单 seed prompt、草稿首图 prompt 来源选择、单关图片再生成 prompt 来源选择。
|
||||
4. `prompt/puzzle/image.rs` 承接拼图图片生成正式提示词与默认反向提示词。
|
||||
5. `puzzle_agent_turn.rs` 只保留 LLM 调用、结果解析、阶段判断和 SpacetimeDB 写回输入构造,不再内联拼图聊天提示词正文。
|
||||
6. `puzzle.rs` 只保留拼图路由、计费、DashScope、OSS、候选图持久化和运行态编排,不再内联拼图草稿或图片提示词正文。
|
||||
7. 后续调整拼图共创问法、输出契约、生成草稿 prompt 来源、图片画面约束或反向提示词时,优先修改 `prompt/puzzle/`,不要在 `puzzle.rs` 或 `puzzle_agent_turn.rs` 中新增提示词正文。
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# SpacetimeDB 本地 replica identity 不一致处理方案
|
||||
|
||||
日期:`2026-04-30`
|
||||
|
||||
## 1. 问题
|
||||
|
||||
本地启动 SpacetimeDB standalone 时出现:
|
||||
|
||||
```text
|
||||
error starting database: failed to init replica 1 for <new-database-identity>: mismatched database identity: <old-database-identity> != <new-database-identity>
|
||||
```
|
||||
|
||||
本次现场日志中,`server-rs/.spacetimedb/local/data/logs/spacetime-standalone.log` 显示:
|
||||
|
||||
1. `2026-04-30T12:17:26Z` 开始按 `c2006f3d846a8259512006a556b1bc3f751a9aef6608fc0ee75788deea6d9331` 启动数据库。
|
||||
2. `replica 1` 的持久化数据仍带有旧库 `c20037fcfaac4e5c4b1f492f026a4f6119a98f56319b77f21ef021ededf8b7ae`。
|
||||
3. SpacetimeDB 因同一个副本目录中 identity 不一致而拒绝继续启动。
|
||||
|
||||
这不是 Rust 编译错误,也不是 `api-server:maincloud` 的 token 错误。只要错误来自 `server-rs/.spacetimedb/local/.../spacetime-standalone.log`,优先按本地 root-dir 数据目录污染处理。
|
||||
|
||||
## 2. 根因
|
||||
|
||||
`spacetime start --edition standalone` 会在同一个 `--root-dir` 下保存控制库、程序字节、WAL 与 replica 数据。当前仓库默认本地 root-dir 是:
|
||||
|
||||
```text
|
||||
server-rs/.spacetimedb/local
|
||||
```
|
||||
|
||||
当这个目录曾经启动并发布过旧 database identity,之后又用同一个 root-dir 初始化或发布到另一个 database identity 时,可能出现:
|
||||
|
||||
1. `control-db` 记录的是新库。
|
||||
2. `data/replicas/1` 里仍残留旧库 WAL 或快照。
|
||||
3. 启动时 SpacetimeDB 尝试把旧 replica 当作新库加载,触发 `mismatched database identity`。
|
||||
|
||||
## 3. 处理原则
|
||||
|
||||
1. 不在脚本里默认删除 `.spacetimedb` 数据,避免误删本地开发数据。
|
||||
2. 如果只是本地开发库且数据可丢弃,优先备份后重建 `data` 目录。
|
||||
3. 如果数据必须保留,不要清理目录;应改回创建旧库时使用的 database/root-dir,或先导出迁移数据。
|
||||
4. Maincloud 发布与本地 standalone root-dir 是两条链路;不要通过切回 `server-node` 或 PostgreSQL 绕过。
|
||||
|
||||
## 4. 本地可丢弃数据时的修复
|
||||
|
||||
PowerShell:
|
||||
|
||||
```powershell
|
||||
$root = "C:\Genarrative\server-rs\.spacetimedb\local"
|
||||
Get-CimInstance Win32_Process |
|
||||
Where-Object { $_.Name -match "spacetime" -and $_.CommandLine -and $_.CommandLine.Replace("/", "\") -like "*$($root.Replace("/", "\"))*" } |
|
||||
Select-Object ProcessId, Name, CommandLine
|
||||
```
|
||||
|
||||
确认占用进程后停止:
|
||||
|
||||
```powershell
|
||||
Stop-Process -Id <pid> -Force
|
||||
```
|
||||
|
||||
备份运行态数据目录:
|
||||
|
||||
```powershell
|
||||
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
Move-Item -LiteralPath "C:\Genarrative\server-rs\.spacetimedb\local\data" -Destination "C:\Genarrative\server-rs\.spacetimedb\local\data.identity-mismatch-backup.$stamp"
|
||||
```
|
||||
|
||||
重新启动本地链路:
|
||||
|
||||
```powershell
|
||||
npm run dev:rust
|
||||
```
|
||||
|
||||
`npm run dev:rust` 会重新启动 standalone、发布 `spacetime-module`,并生成新的本地数据库运行态。
|
||||
|
||||
## 5. 需要保留数据时的处理
|
||||
|
||||
不要移动或删除 `server-rs/.spacetimedb/local/data`。先确认旧库 identity 对应的数据库名、root-dir 与发布命令,然后选择:
|
||||
|
||||
1. 用旧库对应的 database/root-dir 重新启动。
|
||||
2. 使用迁移导出脚本导出旧数据,再清理本地 root-dir 并导入到新库。
|
||||
3. 如目标其实是 Maincloud,改用 `npm run api-server:maincloud` 连接云端,避免误启动本地 standalone。
|
||||
|
||||
## 6. 脚本诊断
|
||||
|
||||
`scripts/dev-rust-stack.sh` 已补充本地启动失败诊断:
|
||||
|
||||
1. SpacetimeDB 进程在就绪前退出时,会打印 `spacetime-standalone.log` 尾部。
|
||||
2. 若日志包含 `mismatched database identity`,会提示本地 `data/replicas/1` 与当前 control-db identity 不一致。
|
||||
3. 诊断只输出建议,不自动清理数据。
|
||||
Reference in New Issue
Block a user