This commit is contained in:
2026-05-01 01:30:02 +08:00
parent aabad6407f
commit 2e9d0f4640
92 changed files with 4548 additions and 248 deletions

View File

@@ -82,7 +82,7 @@
5. 玩家从广场进入某个作品时,第 1 关必须先显示当前作品本身。
6. 第 2 关及以后必须按照“标签相似度权重 `70%` + 同作者权重 `30%`”选择下一关。
7. 游戏运行时必须全屏展示拼图画布。
8. 新游戏进入时难度必须从 `3*3` 开始,完成 `3`后切为 `4*4`,后续持续为 `4*4`
8. 新游戏进入时难度必须从`1` 关的 `3*3` 开始,并按关卡配置推进到 `4*4``5*5``6*6``7*7`;第 `11`起每 `6` 关循环复用第 `5~10` 关配置
9. 拼图运行时必须支持:
- 点击选择两块并交换
- 正确相邻后自动合并
@@ -517,21 +517,35 @@ tagSimilarityScore =
本次建议同时显示:
1. 当前关卡序号
2. 当前网格规格,例如 `3x3``4x4`
2. 当前网格规格,例如 `3x3``5x5``7x7`
## 9.3 难度与关卡推进规则
每次新 run 都必须从最低难度开始:
每次新 run 都必须从`1` 关配置开始:
1.`1~3` 关固定为 `3x3`
2.`4` 关开始固定为 `4x4`
3. 后续全部关卡保持 `4x4`
| 关卡 | 切割规格 | 限时 |
| ---------- | -------- | -------------- |
| 第 `1` 关 | `3x3` | `5` 分钟 |
| 第 `2` 关 | `4x4` | `5` 分钟 |
| 第 `3` 关 | `5x5` | `5` 分钟 |
| 第 `4` 关 | `5x5` | `3``30` 秒 |
| 第 `5` 关 | `5x5` | `3``30` 秒 |
| 第 `6` 关 | `6x6` | `4` 分钟 |
| 第 `7` 关 | `5x5` | `3``30` 秒 |
| 第 `8` 关 | `7x7` | `4``30` 秒 |
| 第 `9` 关 | `5x5` | `4` 分钟 |
| 第 `10` 关 | `7x7` | `4``30` 秒 |
`11` 关开始,每 `6` 关循环复用第 `5~10` 关配置。
对应函数建议:
```ts
function resolvePuzzleGridSize(clearedLevelCount: number): 3 | 4 {
return clearedLevelCount >= 3 ? 4 : 3;
function resolvePuzzleLevelConfig(levelIndex: number): {
gridSize: 3 | 4 | 5 | 6 | 7;
timeLimitMs: number;
} {
// 统一从关卡序号解析切割规格和倒计时。
}
```
@@ -646,8 +660,8 @@ V1 规则如下:
`2026-04-29` 起,拼图运行时加入倒计时:
1. `3x3` 关卡限时 `180`
2. `4x4` 关卡限时 `300`
1. 倒计时必须使用第 `9.3` 节的关卡配置函数,不允许在 UI 或本地兜底里按网格规模另写一套时间表
2. `1~10` 关按配置表执行;第 `11` 关起每 `6` 关循环复用第 `5~10` 关配置
3. 规定时间内未完成拼图,关卡状态变为 `failed`
4. 弹窗、查看原图覆盖、冻结时间生效期间不消耗倒计时。
5. 通关成绩只统计有效消耗时间,不统计暂停与冻结时间。
@@ -693,7 +707,7 @@ interface PuzzleProfile {
interface PuzzleRuntimeLevelSnapshot {
runId: string;
levelIndex: number;
gridSize: 3 | 4;
gridSize: 3 | 4 | 5 | 6 | 7;
profileId: string;
levelName: string;
authorDisplayName: string;
@@ -738,7 +752,7 @@ interface PuzzleRunSnapshot {
entryProfileId: string;
clearedLevelCount: number;
currentLevelIndex: number;
currentGridSize: 3 | 4;
currentGridSize: 3 | 4 | 5 | 6 | 7;
playedProfileIds: string[];
previousLevelTags: string[];
currentLevel: PuzzleRuntimeLevelSnapshot | null;
@@ -1167,7 +1181,7 @@ interface PuzzleRunSnapshot {
先做:
1. `3x3 / 4x4` 切图
1. `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 切图
2. 点击两块交换
3. 正确连接自动合并
4. 合并块整体拖动
@@ -1202,7 +1216,7 @@ interface PuzzleRunSnapshot {
4. 发布后的拼图作品能进入平台广场。
5. 玩家从广场进入时,第 `1` 关必定是当前作品本身。
6.`2` 关及以后按照“标签相似度 `70%` + 同作者 `30%`”计算下一关。
7. 新 run `3` 关为 `3x3`,之后固定为 `4x4`
7. 新 run 的关卡切割和倒计时符合第 `9.3` 节配置,并且第 `11` 关起按第 `5~10` 关配置循环
8. 运行时支持点击两块交换。
9. 交换后正确相邻的块会自动合并。
10. 合并块可以整体拖动。

View File

@@ -93,8 +93,9 @@
1. 数字过大时做单位缩略展示
2. “游戏时长”卡固定以小时为单位展示,短时长不切换成分钟,长时长不切换成天
3. 进入页面先展示骨架屏
4. 数据请求失败时展示降级文案,不展示假数字
3. “玩过”卡展示值始终带 `个` 单位,例如 `0个``1个``1.2万个`
4. 进入页面先展示骨架屏
5. 数据请求失败时展示降级文案,不展示假数字
---

View File

@@ -16,7 +16,7 @@
1. 拼图生成图固定使用 `1024*1024`
2. 文生图和参考图生图共用同一个尺寸常量,禁止一条链路仍生成竖屏或横版图。
3. 拼图图片提示词明确写入 `1:1 正方形画布`,继续保留 `3x3 4x4 拼图切块`、主体清晰、层次明确、无文字水印等约束。
3. 拼图图片提示词明确写入 `1:1 正方形画布`,继续保留适配 `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 拼图切块、主体清晰、层次明确、无文字水印等约束。
4. 文生图正向 prompt 必须由后端压缩到 `500` 字符以内,优先保留玩家画面描述开头与固定拼图约束,避免 DashScope 旧 text2image 协议把超长 prompt 判为“请求参数不合法”。
5. DashScope 上游失败时api-server 必须在错误 details 中保留业务 message、`upstreamStatus` 和截断后的 `rawExcerpt`,日志也要记录同样的摘要,避免生成进度页只能看到通用 HTTP 文案。
6. 图片生成仍由 `api-server` 执行。SpacetimeDB reducer 不做网络 I/O。
@@ -47,7 +47,7 @@
1. 点击拼图草稿生成或重新生成画面时,后端请求 DashScope 的 `size``1024*1024`
2. 图片提示词包含 `1:1 正方形拼图关卡`
3. 图片提示词长度不超过 `500` 字符,超长画面描述会被截断,但 `3x3 4x4``避免文字、水印、边框和 UI 元素` 等玩法约束不能丢。
3. 图片提示词长度不超过 `500` 字符,超长画面描述会被截断,但适配 `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 拼图切块`避免文字、水印、边框和 UI 元素` 等玩法约束不能丢。
4. DashScope 返回参数错误、任务失败或非 2xx 时,前端错误优先展示后端 details.message后端日志能看到 `upstreamStatus``rawExcerpt`
5. 正式拼图 run 中拖动拼块后,前端立即更新棋盘、合并块和通关状态,不再等待 `/drag`
6. 移动端运行时棋盘为正方形,并尽量贴近屏幕两侧边缘。

View File

@@ -13,7 +13,7 @@
1. 通关后默认点击“下一关”,优先加载当前拼图作品的下一关。
2. 当前作品没有下一关时,后端按标签语义相似度选出相似度最高的三个已发布作品。
3. 用户在通关弹窗里点击候选作品后,进入该作品并从第 1 关重新开始。
3. 用户在通关弹窗里点击候选作品后,进入该作品并从第 `1` 关重新开始。
4. 移动端优先,候选卡片要紧凑,不写玩法说明类文案。
## 数据契约
@@ -51,8 +51,8 @@
- 返回最高的 3 个候选
4. `advance_puzzle_next_level`
- `nextLevelMode = sameWork` 时加载当前作品的下一关,并继续当前 run。
- `nextLevelMode = similarWorks` 时默认加载候选第一项,并从该作品第 1 关重新开始
5. `local-next-level` 兼容接口同样优先找同作品下一关;没有时返回相似作品候选或旧草稿兜底。
- `nextLevelMode = similarWorks` 时默认加载候选第一项,并`entryProfileId / clearedLevelCount / currentLevelIndex` 重置到目标作品第 `1`
5. `local-next-level` 兼容接口同样优先找同作品下一关;没有时返回 `similarWorks` 候选并保持当前通关 run只有候选池为空时才进入旧草稿兜底。
## 前端规则
@@ -64,11 +64,12 @@
- `sameWork` 保留“下一关”。
- `similarWorks` 显示“换个作品”,点击后打开结算弹窗供选择。
3. 所有正式相似度计算只信任后端返回,不在 UI 里重新算。
4. 本地/草稿 run 通关提交本地排行榜后,会异步调用 `local-next-level` 刷新 handoff若拿到 `similarWorks`,只合并候选字段,不把已通关弹窗改成新的 playing 关卡。
## 验收
1. 当前作品有下一关时,点击“下一关”进入当前作品下一关。
2. 当前作品没有下一关时,通关弹窗显示最多 3 个相似作品。
3. 点击相似作品后进入该作品第 1 关
3. 点击相似作品后进入该作品第 `1`HUD 关卡序号、切割规格和倒计时都按第 `1` 关显示
4.`recommendedNextProfileId` 为空时,只要 `nextLevelMode = sameWork`,按钮仍可用。
5. 拼图 runtime 单测、Rust 拼图模块测试和编码检查通过。

View File

@@ -24,12 +24,28 @@
## 难度限时
第一版按网格规模定义限时
拼图关卡切割规格和倒计时由统一关卡配置函数解析,不再按网格规模单独推导时间
1. `3x3``180000ms`
2. `4x4``300000ms`
| 关卡 | 切割规格 | 限时 |
| -------- | -------- | ---------- |
| 第 1 关 | `3x3` | `300000ms` |
| 第 2 关 | `4x4` | `300000ms` |
| 第 3 关 | `5x5` | `300000ms` |
| 第 4 关 | `5x5` | `210000ms` |
| 第 5 关 | `5x5` | `210000ms` |
| 第 6 关 | `6x6` | `240000ms` |
| 第 7 关 | `5x5` | `210000ms` |
| 第 8 关 | `7x7` | `270000ms` |
| 第 9 关 | `5x5` | `240000ms` |
| 第 10 关 | `7x7` | `270000ms` |
后续若扩展更多难度,只能通过同一个难度解析函数扩展,不允许在 UI 里写死另一套时间
第 11 关开始,每 6 关循环复用第 5 关到第 10 关的配置,即 `5x5/210000ms``6x6/240000ms``5x5/210000ms``7x7/270000ms``5x5/240000ms``7x7/270000ms`
同作品下一关必须使用同一个运行时关卡序号继续推进。跨作品相似推荐代表进入新作品,必须从目标作品第 `1` 关重新开始。
失败状态点击“重新开始”时,不进入作品第 `1` 关,而是重开当前失败关卡:前端需要传当前关 `levelId`,服务端按该 `levelId` 在作品内的位置恢复 `currentLevelIndex`、切割规格和倒计时。
后续若扩展更多难度,只能通过同一个关卡配置解析函数扩展,不允许在 UI 里写死另一套时间。
## 计时规则

View File

@@ -0,0 +1,59 @@
# 拼图作品积分激励链路设计
更新时间:`2026-05-01`
## 1. 目标
1. 拼图草稿页“新增关卡”按钮下方显示一行小字:“获得更多积分激励”。
2. 创作页的已发布拼图作品卡展示当前作品的积分激励总数、待领取积分数和领取按钮。
3. 用户在他人已发布拼图作品中消耗陶泥币时,作品作者获得消耗陶泥币数量的一半作为积分激励。
4. 作者领取时只能领取整数个陶泥币,待领取值向下取整;未满 1 个陶泥币的半数余额继续保留。
## 2. 数据模型
拼图作品激励归属到 `puzzle_work_profile`
1. `point_incentive_total_half_points: u64`
- 记录该作品累计获得的激励,单位为“半个陶泥币”。
- 每消耗 `N` 个陶泥币,增加 `N` 个 half points当前拼图道具每次消耗 1 个陶泥币,因此每次为作者增加 0.5。
2. `point_incentive_claimed_points: u64`
- 记录作者已领取的整数陶泥币数量。
3. 前端展示:
- 激励总数 = `pointIncentiveTotalHalfPoints / 2`,允许展示一位小数。
- 待领取积分 = `floor(pointIncentiveTotalHalfPoints / 2) - pointIncentiveClaimedPoints`
- 领取按钮仅在待领取积分大于 0 时可用。
## 3. 后端事务
1. 拼图运行道具扣费成功、道具效果成功落库后,后端根据 run 的当前作品 `profile_id` 查找作者。
2. 若使用者不是作品作者,则给该作品累积 `consumed_points` 个 half points。
3. 若使用者是作者本人,视为作者自测,不产生积分激励。
4. 若后续业务操作失败并触发扣费退款,不写入激励。
5. 领取接口:
- 只允许作品作者领取。
- 计算可领取整数 `claimable = total_half_points / 2 - claimed_points`
- `claimable <= 0` 时拒绝领取。
- 同一事务内更新作品 `claimed_points += claimable`,并向作者钱包增加 `claimable` 陶泥币,钱包流水来源使用 `puzzle_author_incentive_claim`
## 4. API 与前端
1. `PuzzleWorkSummary` / `PuzzleWorkProfile` 增加:
- `pointIncentiveTotalHalfPoints`
- `pointIncentiveClaimedPoints`
- `pointIncentiveTotalPoints`
- `pointIncentiveClaimablePoints`
2. 新增领取接口:
- `POST /api/runtime/puzzle/works/{profile_id}/point-incentive/claim`
- 返回更新后的 `PuzzleWorkProfile`
3. 创作页仅对已发布拼图作品显示积分激励块RPG、大鱼和草稿卡不显示。
4. 领取成功后刷新对应拼图作品列表状态,按钮立即禁用或显示新的待领取数。
5. `spacetime-client` 映射层继续兼容历史拼图运行快照:旧 `run_json` 若缺少 `started_at_ms`API 记录回填为非 0 值,避免前端计时器拿到无效开始时间。
## 5. 验收点
1. 拼图草稿页新增关卡按钮下方显示“获得更多积分激励”。
2. 已发布拼图作品卡展示“积分激励总数”和“待领取”两个数值。
3. 待领取积分为 0 时领取按钮禁用。
4. 非作者游玩他人拼图并使用付费道具后,该作品累计 half points 增加。
5. 作者领取后钱包增加向下取整后的整数陶泥币,作品待领取数归零或保留不足 1 的小数余额。
6. 修改后运行编码检查、SpacetimeDB 绑定生成、Rust 检查和必要前端测试。

View File

@@ -24,8 +24,9 @@
- [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_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):记录拼图失败后重新开始/付费续时,以及进入作品与过关后同步存档页投影的落地规则。
- [PUZZLE_RUNTIME_TIMER_AND_PROPS_2026-04-29.md](./PUZZLE_RUNTIME_TIMER_AND_PROPS_2026-04-29.md)记录拼图关卡切割、倒计时、失败态和三个运行时道具的统一规则2026-05-01 起关卡切割与限时按第 1-10 关配置,并从第 11 关按第 5-10 关六关循环。
- [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` 仅作为兼容回退。