From 838c74d8feaa72b3d21d350f59df251c56be5148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Sun, 24 May 2026 20:34:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=95=B2=E6=9C=A8?= =?UTF-8?q?=E9=B1=BC=E7=BB=93=E6=9E=9C=E9=A1=B5=E5=85=83=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E8=A1=A5=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hermes/shared-memory/decision-log.md | 10 +- .hermes/shared-memory/pitfalls.md | 10 +- ...€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md | 38 +-- ...玩法创作】平å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md | 7 +- .../crates/api-server/src/match3d/tests.rs | 9 +- .../crates/api-server/src/wooden_fish.rs | 6 +- .../common/CreativeImageInputPanel.tsx | 48 +-- .../PlatformEntryFlowShellImpl.tsx | 49 +++ .../WoodenFishWorkspace.test.tsx | 85 ++++- .../WoodenFishWorkspace.tsx | 187 +++++------ .../WoodenFishResultView.test.tsx | 41 ++- .../WoodenFishResultView.tsx | 317 ++++++++++++++++-- .../miniGameDraftGenerationProgress.test.ts | 34 +- .../miniGameDraftGenerationProgress.ts | 131 +++++--- 14 files changed, 757 insertions(+), 215 deletions(-) diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md index d4ca26f6..04d08a92 100644 --- a/.hermes/shared-memory/decision-log.md +++ b/.hermes/shared-memory/decision-log.md @@ -27,7 +27,7 @@ ## 2026-05-22 敲木鱼图片创作采用三图 image2 链路 - 背景:敲木鱼自定义题æåªç”Ÿæˆä¸å¤®æ•²å‡»ç‰©æ—¶ï¼Œè¿è¡Œæ€ç¼ºå°‘与新主题匹é…的竖å±èƒŒæ™¯å’Œä¸»é¢˜åŒ–返回按钮;若直接让背景 prompt è‡ªç”±å‘æŒ¥ï¼Œåˆå®¹æ˜“把敲击物或木槌画进背景里。 -- 决ç–:敲木鱼 `compile-draft` / `regenerate-hit-object` å›¾ç‰‡é“¾è·¯å›ºå®šä¸ºä¸‰æ¥ image2 edits。第一æ¥è°ƒç”¨ VectorEngine `/v1/images/edits` + `gpt-image-2`,以默认木鱼图作为结构和画风å‚è€ƒï¼Œç”¨æˆ·ä¸Šä¼ å‚考图åªä½œä¸ºåŒæ¬¡è¯·æ±‚的新主题å‚考,结åˆç”¨æˆ·é¢˜æå…³é”®è¯æˆ–å‚è€ƒå›¾ä¸»é¢˜ç”Ÿæˆ `1:1` 绿色背景主体图;`api-server` å…ˆå¯¹è¿™å¼ ç»¿å¹•å›¾æ‰§è¡ŒåŽ»ç»¿èƒŒæ™¯å¤„ç†å¹¶å†™å›ž `hitObjectAsset`。第二æ¥å¿…é¡»ä»¥ç¬¬ä¸€æ¥æŠ å›¾å®ŒæˆåŽçš„逿˜Žæ•²å‡»ç‰©å›¾ä½œä¸ºå‚考,结åˆç”¨æˆ·åŽŸå§‹é¢˜æç”Ÿæˆ `9:16` 背景环境图并写回 `backgroundAsset`,é¿å…背景图继承绿幕或纯绿色画布。第三æ¥å¿…须以去绿åŽçš„æ•²å‡»ç‰©ä¸»ä½“图和背景环境图为å‚è€ƒï¼Œç”Ÿæˆ `1:1` 绿色背景返回按钮图,æœåŠ¡ç«¯åŽ»ç»¿åŽå†™å›ž `backButtonAsset`ã€‚ä¸‰æ¥ prompt 使用 PRD ä¸å›ºå®šéšè—关键è¯ï¼Œä¸è¿½åŠ é¢å¤– negative prompt;返回按钮åªå…许å‚考图约æŸåœ†å½¢åº•色和ç®å¤´é…色,ä¸å…è®¸ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚形外框或装饰图案;背景图ä¸å¾—åŒ…å«æ•²å‡»ç‰©æœ¬ä½“或木槌互动物å“,返回按钮图ä¸å¾—åŒ…å«æ–‡å—ã€æ•°å—ã€æ°´å°æˆ–é¢å¤– UI 颿¿ã€‚ +- 决ç–:敲木鱼 `compile-draft` / `regenerate-hit-object` å›¾ç‰‡é“¾è·¯å›ºå®šä¸ºä¸‰æ¥ image2 edits。第一æ¥è°ƒç”¨ VectorEngine `/v1/images/edits` + `gpt-image-2`,以默认木鱼图作为结构和画风å‚è€ƒï¼Œç”¨æˆ·ä¸Šä¼ å‚考图åªä½œä¸ºåŒæ¬¡è¯·æ±‚的新主题å‚考,结åˆç”¨æˆ·é¢˜æå…³é”®è¯æˆ–å‚è€ƒå›¾ä¸»é¢˜ç”Ÿæˆ `1:1` 绿色背景主体图;`api-server` å…ˆå¯¹è¿™å¼ ç»¿å¹•å›¾æ‰§è¡ŒåŽ»ç»¿èƒŒæ™¯å¤„ç†å¹¶å†™å›ž `hitObjectAsset`。第二æ¥å¿…é¡»ä»¥ç¬¬ä¸€æ¥æŠ å›¾å®ŒæˆåŽçš„逿˜Žæ•²å‡»ç‰©å›¾ä½œä¸ºå‚考,结åˆç”¨æˆ·åŽŸå§‹é¢˜æç”Ÿæˆ `9:16` 背景环境图并写回 `backgroundAsset`,é¿å…背景图继承绿幕或纯绿色画布。第三æ¥å¿…须以去绿åŽçš„æ•²å‡»ç‰©ä¸»ä½“图和背景环境图为å‚è€ƒï¼Œç”Ÿæˆ `1:1` 绿色背景返回按钮图,æœåŠ¡ç«¯åŽ»ç»¿åŽå†™å›ž `backButtonAsset`ã€‚ä¸‰æ¥ prompt 使用 PRD ä¸å›ºå®šéšè—关键è¯ï¼Œä¸è¿½åŠ é¢å¤– negative prompt;返回按钮åªå…许å‚考图约æŸåœ†å½¢åº•色和ç®å¤´é…色,ä¸å…è®¸ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆï¼Œä¸»ä½“è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,并带主题色外æè¾¹ï¼›èƒŒæ™¯å›¾ä¸å¾—åŒ…å«æ•²å‡»ç‰©æœ¬ä½“或木槌互动物å“,返回按钮图ä¸å¾—åŒ…å«æ–‡å—ã€æ•°å—ã€æ°´å°æˆ–é¢å¤– UI 颿¿ã€‚ - å½±å“范围:`api-server` 木鱼图片生æˆç¼–排ã€`wooden_fish_work_profile.background_asset_json`ã€`wooden_fish_work_profile.back_button_asset_json`ã€shared contractsã€å‰ç«¯ç»“果页 / è¿è¡Œæ€èƒŒæ™¯ä¸Žè¿”å›žæŒ‰é’®å±•ç¤ºã€æ•²æœ¨é±¼ PRD 和平å°é“¾è·¯æ–‡æ¡£ã€‚ - éªŒè¯æ–¹å¼ï¼šæ‰§è¡Œ `cargo test -p api-server wooden_fish --manifest-path server-rs/Cargo.toml`ã€`cargo test -p spacetime-client wooden_fish --manifest-path server-rs/Cargo.toml`ã€`npm run spacetime:generate`ã€`npm run check:spacetime-schema`ã€`npm run typecheck`。 - å…³è”æ–‡æ¡£ï¼š`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 @@ -855,3 +855,11 @@ - 背景:结果页承载预览ã€ä¿®è¡¥å’Œå‘å¸ƒï¼Œè‹¥ç»§ç»æ”¾â€œä¸€æ¬¡ç”Ÿæˆâ€æŒ‰é’®ä¼šæŠŠåˆå§‹ç”Ÿæˆå’Œç»“果修补èŒè´£æ··åœ¨ä¸€èµ·ã€‚ - 决ç–:åˆå§‹ä¸‰å›¾ç”Ÿæˆæ”¹ç”± `bark-battle-generating` 独立生æˆé¡µè‡ªåŠ¨æ‰§è¡Œï¼Œç›®æ ‡æ§½ä½åªæœ‰çŽ©å®¶å½¢è±¡ã€å¯¹æ‰‹å½¢è±¡å’Œç«žæŠ€èƒŒæ™¯ï¼›è¡¨å•术è¯ç»Ÿä¸€ä¸º `themeDescription`ã€çŽ©å®¶å½¢è±¡æè¿°å’Œå¯¹æ‰‹å½¢è±¡æè¿°ï¼Œä¸å†å›žé€€ `themePreset`ã€ç‹—狗皮肤预设或“角色设定â€ã€‚部分失败也进入结果页。结果页ä¸å†æä¾›ä¸€æ¬¡ç”ŸæˆæŒ‰é’®ï¼ŒéŸ³é¢‘é…置和排åé…ç½®ä¸è¿›å…¥ v1 公开é—环;结果页åªä¿ç•™å•æ§½é‡è¯•ã€é‡æ–°ç”Ÿæˆå’Œä¸Šä¼ 。å‘布时 SpacetimeDB `bark_battle_published_config.config_json` 使用规范化åŽçš„æœ€ç»ˆ `publishedSnapshot`,`published_snapshot_json` åŒæ¥ä¿å˜åŒä¸€ä»½å¿«ç…§ã€‚ - éªŒè¯æ–¹å¼ï¼šè¡¨å•æäº¤åŽè¿›å…¥ `bark-battle-generating`;结果页ä¸ä¼šå‡ºçŽ°ä¸€æ¬¡ç”ŸæˆæŒ‰é’®ã€éŸ³é¢‘æ§½ã€çš®è‚¤é¢„è®¾å…¥å£æˆ–排åé…置;Bark Battle å‘å¸ƒåŽæ£å¼ runtime 应读å–ç»“æžœé¡µæœ€ç»ˆå›¾ç‰‡ç´ æè€Œä¸æ˜¯åˆå§‹è‰ç¨¿ç´ æã€‚ + +## 2026-05-24 敲木鱼结果页先补录作å“ä¿¡æ¯å†è¯•玩 / å‘布 + +- 背景:敲木鱼工作å°åªåº”ä¿ç•™ç”Ÿæˆæ‰€éœ€è¾“å…¥ï¼Œä½œå“æ ‡é¢˜ã€ç®€ä»‹å’Œä¸»é¢˜æ ‡ç¾é€‚åˆæ”¾åœ¨ç”Ÿæˆè‰ç¨¿åŽçš„补录阶段。 +- 决ç–:敲木鱼的 `workTitle`ã€`workDescription` å’Œ `themeTags` 从工作å°é¦–å±ç§»åˆ°ç»“果页;结果页编辑åŽåœ¨è¯•玩或å‘布å‰å…ˆè°ƒç”¨ `update-work-meta` 写回当å‰ä½œå“ä¿¡æ¯ã€‚ä¸»é¢˜æ ‡ç¾ç¼–è¾‘æ ·å¼å¯¹é½æ‹¼å›¾ç»“æžœé¡µçš„èƒ¶å›Šæ ‡ç¾ç¼–辑器。 +- å½±å“范围:`WoodenFishWorkspace`ã€`WoodenFishResultView`ã€`PlatformEntryFlowShellImpl`ã€æ•²æœ¨é±¼ PRD 和平å°å…¥å£é“¾è·¯æ–‡æ¡£ã€‚ +- éªŒè¯æ–¹å¼ï¼šå·¥ä½œå°é¦–å±ä¸å†å‡ºçŽ°æ ‡é¢˜ / 简介 / æ ‡ç¾è¾“入;结果页修改åŽç‚¹è¯•玩或å‘布会先写回当å‰ä½œå“ä¿¡æ¯ã€‚ +- å…³è”æ–‡æ¡£ï¼š`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 diff --git a/.hermes/shared-memory/pitfalls.md b/.hermes/shared-memory/pitfalls.md index abd649a6..ca486930 100644 --- a/.hermes/shared-memory/pitfalls.md +++ b/.hermes/shared-memory/pitfalls.md @@ -51,7 +51,7 @@ - 现象:返回按钮试玩图有时会被画æˆå¾½ç« ã€èŠ±ç›˜ã€æµ®é›•åœ†ç‰Œï¼Œç”šè‡³å‡ºçŽ°å¤æ‚外圈和装饰花纹,左ç®å¤´å而ä¸å¤Ÿçªå‡ºã€‚ - åŽŸå› ï¼šprompt åªè¯´â€œä¸»é¢˜åŒ–è¿”å›žæŒ‰é’®â€æ—¶ï¼Œimage2 会把å‚考图里的装饰è¯è¨€ä¸€èµ·å¦è¿›åŽ»ï¼›å¦‚æžœæ²¡æœ‰æŠŠå½¢çŠ¶æ”¶æŸåˆ°â€œæ ‡å‡†åœ†å½¢ + å•个居ä¸å·¦ç®å¤´â€ï¼Œæ¨¡åž‹ä¼šä¼˜å…ˆè¡¥é€ åž‹è€Œä¸æ˜¯è¡¥å›¾æ ‡ã€‚ -- 处ç†ï¼šè¿”å›žæŒ‰é’®ç”Ÿæˆ prompt å¿…é¡»åªå…许å‚考图约æŸåœ†å½¢åº•色与ç®å¤´é…è‰²ï¼Œæ˜Žç¡®ç¦æ¢å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†å’Œè£…é¥°å›¾æ¡ˆï¼ŒæŒ‰é’®æœ¬ä½“å›ºå®šä¸ºæ ‡å‡†åœ†å½¢ã€‚ +- 处ç†ï¼šè¿”å›žæŒ‰é’®ç”Ÿæˆ prompt å¿…é¡»åªå…许å‚考图约æŸåœ†å½¢åº•色与ç®å¤´é…è‰²ï¼Œæ˜Žç¡®ç¦æ¢å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†å’Œè£…é¥°å›¾æ¡ˆï¼ŒæŒ‰é’®æœ¬ä½“å›ºå®šä¸ºæ ‡å‡†åœ†å½¢ï¼Œè§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,圆形外沿需è¦ä¸€åœˆä¸Žä¸»é¢˜è‰²æé…的干净外æè¾¹ã€‚ - 验è¯ï¼š`cargo test -p api-server wooden_fish --manifest-path server-rs\Cargo.toml`ï¼Œå¹¶é‡æ–°è¯•玩确认返回按钮åªå‰©åœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´ã€‚ - å…³è”:`server-rs/crates/api-server/src/wooden_fish.rs`ã€`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`. @@ -63,6 +63,14 @@ - 验è¯ï¼š`npm run test -- src/services/wooden-fish/woodenFishClient.test.ts`,并在本地触å‘一次木鱼创作确认ä¸å†å‡ºçް 15 ç§’å‰ç«¯è¶…时。 - å…³è”:`src/services/wooden-fish/woodenFishClient.ts`ã€`src/services/creation-agent/creationAgentClientFactory.ts`ã€`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`。 +## 敲木鱼创作“å¡ä½â€å…ˆæŸ¥ 2xx 慢请求 + +- 现象:敲木鱼工作å°ç‚¹å‡»ç”ŸæˆåŽé•¿æ—¶é—´åœç•™åœ¨ç”Ÿæˆé¡µï¼Œçœ‹èµ·æ¥åƒå¡ä½ï¼›`api-server` 日志å¯èƒ½å‡ºçް `/api/creation/wooden-fish/sessions/{sessionId}/actions` çš„ `2xx` 慢请求,耗时å¯è¾¾æ•°åˆ†é’Ÿï¼Œä¾‹å¦‚ `latency_ms=525473`。 +- åŽŸå› ï¼šå½“å‰ `compile-draft` æ˜¯åŒæ¥ action,会串行ç‰å¾…敲击物ã€èƒŒæ™¯çŽ¯å¢ƒå›¾ã€è¿”回按钮图三次 image2 editsã€åŽ»ç»¿å¤„ç†ã€OSS 写入和 SpacetimeDB è‰ç¨¿å†™å›žï¼›æç¤ºè¯ç”ŸæˆéŸ³æ•ˆå·²å…³é—,ä¸åº”作为生æˆé˜¶æ®µã€‚ +- 处ç†ï¼šå…ˆç¡®è®¤æ—¥å¿—ä¸è¯¥ action æ˜¯ä¸æ˜¯æœ€ç»ˆ 200;若是 200 慢请求,ä¸è¦ä¼˜å…ˆæŽ’查 WebSocket 或 SpacetimeDB procedure。å‰ç«¯ç”Ÿæˆé¡µè¿›åº¦å¿…须按“整ç†è‰ç¨¿ -> ç”Ÿæˆæ•²å‡»ç‰© -> 生æˆèƒŒæ™¯çŽ¯å¢ƒå›¾ -> 生æˆè¿”回按钮图 -> 写入æ£å¼è‰ç¨¿â€å±•示,并在未收到 action 回包å‰ä¿æŒç‰å¾…æ€ï¼Œä¸å®£ç§°å®Œæˆã€‚ +- 验è¯ï¼š`npm run test -- src/services/miniGameDraftGenerationProgress.test.ts -t "wooden fish"`,并观察木鱼生æˆé¡µåœ¨ 5 分钟以上ç‰å¾…æ—¶ä»åœç•™åœ¨åˆç†é˜¶æ®µã€‚ +- å…³è”:`src/services/miniGameDraftGenerationProgress.ts`ã€`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 + ## 敲木鱼点击生æˆå‡ºçް SpacetimeDB procedure è¶…æ—¶å…ˆæŸ¥ç‰ˆæœ¬é”™é… - 现象:敲木鱼创作时点击“生æˆâ€ï¼Œå‰ç«¯æç¤º `SpacetimeDB procedure 调用超时`,但æœåŠ¡ç«¯æ—¥å¿—æ›´æ—©å‡ºçŽ° `Failed to BSATN deserialize procedure return value` 或类似ååºåˆ—化错误。 diff --git a/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md b/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md index 21eba04e..238a200b 100644 --- a/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md +++ b/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md @@ -113,31 +113,29 @@ WF-* å¿…å¡«å—æ®µï¼š 1. `templateId = "wooden-fish"`ï¼› -2. `workTitle`ï¼šä½œå“æ ‡é¢˜ï¼› -3. `hitObjectPrompt`ï¼šç”¨æˆ·æƒ³æ•²çš„å¯¹è±¡å…³é”®è¯æˆ–æè¿°ï¼Œé»˜è®¤â€œé»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯â€ï¼› -4. `floatingWords[]`:ç¥ç¦è¯ï¼Œæœ€å¤š 8 æ¡ï¼Œä¸å¡«æˆ–清空时使用默认ç¥ç¦è¯ã€‚ +2. `hitObjectPrompt`ï¼šç”¨æˆ·æƒ³æ•²çš„å¯¹è±¡å…³é”®è¯æˆ–æè¿°ï¼Œé»˜è®¤â€œé»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯â€ï¼› +3. `floatingWords[]`:ç¥ç¦è¯ï¼Œæœ€å¤š 8 æ¡ï¼Œä¸å¡«æˆ–清空时使用默认ç¥ç¦è¯ã€‚ å¯é€‰å—段: -1. `workDescription`:作å“简介; -2. `themeTags[]`:最多 6 ä¸ªæ ‡ç¾ï¼› -3. `hitObjectReferenceImageSrc`ï¼šä¸Šä¼ æˆ–åŽ†å²å›¾å¼•用,åªèƒ½ä½œä¸º image2 å‚考,ä¸å¯ç›´æŽ¥è¿›å…¥è¿è¡Œæ€ï¼› -4. `hitSoundPrompt`:历å²å…¼å®¹å—段,当å‰åˆ›ä½œæµç¨‹ä¸å†ä½¿ç”¨ï¼› -5. `hitSoundAsset`ï¼šç”¨æˆ·ä¸Šä¼ ã€å½•音或默认音频资产。 +1. `hitObjectReferenceImageSrc`ï¼šä¸Šä¼ æˆ–åŽ†å²å›¾å¼•用,åªèƒ½ä½œä¸º image2 å‚考,ä¸å¯ç›´æŽ¥è¿›å…¥è¿è¡Œæ€ï¼› +2. `hitSoundPrompt`:历å²å…¼å®¹å—段,当å‰åˆ›ä½œæµç¨‹ä¸å†ä½¿ç”¨ï¼› +3. `hitSoundAsset`ï¼šç”¨æˆ·ä¸Šä¼ ã€å½•音或默认音频资产。 -默认ç¥ç¦è¯ï¼š +ç»“æžœé¡µè¡¥å½•å—æ®µï¼š + +1. `workTitle`ï¼šä½œå“æ ‡é¢˜ï¼Œé»˜è®¤å€¼åœ¨ç»“果页å¯ç¼–辑; +2. `workDescription`:作å“简介; +3. `themeTags[]`:最多 6 ä¸ªæ ‡ç¾ï¼Œæ ·å¼å¯¹é½æ‹¼å›¾ç»“æžœé¡µæ ‡ç¾ç¼–辑器。 + +创作界é¢é»˜è®¤ç¥ç¦è¯ï¼š ```text å¹¸è¿ -å¥åº· -财富 -姻缘 -å¹¸ç¦ -事业 -æˆåŠŸ -功德 ``` +用户å¯é€šè¿‡åŠ å·ç»§ç»æ–°å¢ž 7 ä¸ªè¯æ¡ï¼Œæ€»æ•°æœ€å¤š 8 æ¡ã€‚æ–°å¢žè¯æ¡å³ä¾§æä¾›å‡å· / åˆ é™¤å°æŒ‰é’®ï¼›é»˜è®¤çš„ç¬¬ä¸€ä¸ªè¯æ¡ä¿ç•™ä¸ºæ™®é€šè¾“å…¥æ ¼ã€‚ + `floatingWords[]` ä¿å˜è¯æ¡å本身,ä¸ä¿å˜ `+1` åŽç¼€ï¼›è¿è¡Œæ€æ¯æ¬¡æ•²å‡»æ—¶å†æŠŠé£˜å—å±•ç¤ºä¸ºâ€œè¯æ¡+1â€ã€‚ ## 6. 生æˆè§„则 @@ -181,11 +179,11 @@ WF-* 1. 调用 VectorEngine `/v1/images/edits`,模型固定为 `gpt-image-2`ï¼› 2. multipart å‚考图固定包å«ç¬¬ä¸€æ¥åŽ»é™¤ç»¿è‰²èƒŒæ™¯åŽçš„æ•²å‡»ç‰©ä¸»ä½“图,以åŠç¬¬äºŒæ¥ç”Ÿæˆçš„背景环境图; 3. 尺寸固定 `1:1`,必须输出绿色背景主体图(纯绿色绿幕),åŽç«¯è½åº“剿‰§è¡ŒåŒä¸€å¥—去绿背景处ç†ï¼› -4. 按主题ã€ç”»é£Žã€æè´¨å’Œé…色生æˆå·¦ä¸Šè§’返回按钮图,但å‚考图åªç”¨äºŽçº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸å¾—å€Ÿé‰´å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆï¼›æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œä¸å¤®åªä¿ç•™å•个清晰左ç®å¤´æˆ–返回ç®å¤´ï¼Œä¸å¾—åŒ…å«æ–‡å—ã€æ•°å—ã€æ°´å°ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“å…·ï¼› +4. 按主题ã€ç”»é£Žã€æè´¨å’Œé…色生æˆå·¦ä¸Šè§’返回按钮图,但å‚考图åªç”¨äºŽçº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸å¾—å€Ÿé‰´å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆï¼›æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œä¸»ä½“è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,圆形外沿必须有与主题色æé…的干净外æè¾¹ï¼Œä¸å¤®åªä¿ç•™å•个清晰左ç®å¤´æˆ–返回ç®å¤´ï¼Œä¸å¾—åŒ…å«æ–‡å—ã€æ•°å—ã€æ°´å°ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“å…·ï¼› 5. æç¤ºè¯ä¸¥æ ¼ä½¿ç”¨ï¼š ```text -ç”Ÿæˆæ•²æœ¨é±¼å·¦ä¸Šè§’è¿”å›žæŒ‰é’®å›¾ã€‚è¦æ±‚以å‚考图-去除绿色背景åŽçš„æ•²å‡»ç‰©ä¸»ä½“和背景环境图为主题ã€ç”»é£Žã€æè´¨å’Œé…色å‚考,但å‚考图åªç”¨æ¥çº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸è¦ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆã€‚æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œæ•´ä½“åƒå•ä¸ªåœ†å½¢å›¾æ ‡ï¼Œåœ†å¿ƒå±…ä¸ï¼Œåœ†å½¢å†…部åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´ï¼Œä¸è¦å‡ºçŽ°æ–‡å—ã€æ•°å—ã€æ°´å°ã€æŒ‰é’®å¤–æ ‡ç¾ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“具。尺寸1:1,输出绿色背景主体图(纯绿色绿幕),背景必须是å•一纯绿色 #00FF00 ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— 阴影。按钮主体边缘干净,åŽç»ç”±æœåŠ¡ç«¯æ‰£é™¤ç»¿è‰²èƒŒæ™¯ï¼›æŒ‰é’®åº•è‰²ä¸è¦ä½¿ç”¨ä¸Žç»¿å¹•接近的纯绿色,若主题天然包å«ç»¿è‰²ï¼Œè¯·ä»…åœ¨åœ†å½¢åº•è‰²ä¸Šä½¿ç”¨åæ·±ã€å黄或åè“的主题绿色,并用更高对比的ç®å¤´é¢œè‰²åŒºåˆ†ã€‚ +ç”Ÿæˆæ•²æœ¨é±¼å·¦ä¸Šè§’è¿”å›žæŒ‰é’®å›¾ã€‚è¦æ±‚以å‚考图-去除绿色背景åŽçš„æ•²å‡»ç‰©ä¸»ä½“和背景环境图为主题ã€ç”»é£Žã€æè´¨å’Œé…色å‚考,但å‚考图åªç”¨æ¥çº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸è¦ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆã€‚æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œæ•´ä½“åƒå•ä¸ªåœ†å½¢å›¾æ ‡ï¼ŒæŒ‰é’®ä¸»ä½“åœ¨ç”»å¸ƒä¸çš„è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,圆心居ä¸ï¼Œåœ†å½¢å¤–æ²¿åŠ ä¸€åœˆå’Œä¸»é¢˜è‰²æé…的干净外æè¾¹ï¼Œè®©å®ƒæ›´åƒä¸€ä¸ªæŒ‰é’®ï¼Œä½†ä»ç„¶åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´ï¼Œä¸è¦å‡ºçŽ°æ–‡å—ã€æ•°å—ã€æ°´å°ã€æŒ‰é’®å¤–æ ‡ç¾ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“具。尺寸1:1,输出绿色背景主体图(纯绿色绿幕),背景必须是å•一纯绿色 #00FF00 ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— 阴影。按钮主体边缘干净,åŽç»ç”±æœåŠ¡ç«¯æ‰£é™¤ç»¿è‰²èƒŒæ™¯ï¼›æŒ‰é’®åº•è‰²ä¸è¦ä½¿ç”¨ä¸Žç»¿å¹•接近的纯绿色,若主题天然包å«ç»¿è‰²ï¼Œè¯·ä»…åœ¨åœ†å½¢åº•è‰²ä¸Šä½¿ç”¨åæ·±ã€å黄或åè“的主题绿色,并用更高对比的ç®å¤´é¢œè‰²åŒºåˆ†ã€‚ 主题为:(用户æä¾›å‚考图或用户输入关键è¯ï¼‰ ``` @@ -304,7 +302,7 @@ finish `compile-draft` 是长耗时动作。å‰ç«¯è¿›å…¥ç”Ÿæˆé¡µåŽåº”å±•ç¤ºå¯æ¢å¤è¿›åº¦ï¼›å¦‚æžœè¯·æ±‚å¤±è´¥ï¼Œæ ‡è®°å¤±è´¥å‰å¿…é¡»å¤è¯» session,确认åŽç«¯æ˜¯å¦å·²ç»ç”Ÿæˆå¹¶å†™å›žè‰ç¨¿ã€‚ -敲木鱼创作请求在å‰ç«¯å¿…须使用长ç‰å¾…窗å£ï¼Œé¿å… `createSession` 或 `executeAction` 仿²¿ç”¨å…±äº«åˆ›ä½œå·¥åŽ‚é»˜è®¤çš„ 15 ç§’è¶…æ—¶ã€‚å› ä¸º `compile-draft` 会串行ç‰å¾…敲击物ã€èƒŒæ™¯ã€è¿”回按钮和 OSS è½åº“,木鱼 client 需è¦å•独é…ç½®ä¸Žæ•´æ¡ image2 链路匹é…的超时。 +敲木鱼创作请求在å‰ç«¯å¿…须使用长ç‰å¾…窗å£ï¼Œé¿å… `createSession` 或 `executeAction` 仿²¿ç”¨å…±äº«åˆ›ä½œå·¥åŽ‚é»˜è®¤çš„ 15 ç§’è¶…æ—¶ã€‚å› ä¸º `compile-draft` 会串行ç‰å¾…敲击物ã€èƒŒæ™¯ã€è¿”回按钮三次 image2 å’Œ OSS è½åº“,木鱼 client 需è¦å•独é…ç½®ä¸Žæ•´æ¡ image2 链路匹é…的超时。本地测试ä¸è¯¥ action å¯èƒ½è¾¾åˆ°æ•°åˆ†é’Ÿçº§ï¼›ç”Ÿæˆé¡µè¿›åº¦å¿…须按“整ç†è‰ç¨¿ -> ç”Ÿæˆæ•²å‡»ç‰© -> 生æˆèƒŒæ™¯çŽ¯å¢ƒå›¾ -> 生æˆè¿”回按钮图 -> 写入æ£å¼è‰ç¨¿â€å±•示,ä¸å±•示“æç¤ºè¯ç”ŸæˆéŸ³æ•ˆâ€é˜¶æ®µï¼Œå› ä¸ºå½“å‰æœ¨é±¼éŸ³æ•ˆåªæ”¯æŒä¸Šä¼ ã€å½•音或默认音。 ## 9. SpacetimeDB 表和 view @@ -340,7 +338,7 @@ finish 1. é‡ç”Ÿæˆæ•²å‡»ç‰©å›¾æ¡ˆï¼› 2. ä¸Šä¼ ã€å½•åˆ¶æˆ–æ›¿æ¢æ•²å‡»éŸ³æ•ˆï¼›æœªæä¾›æ—¶ä½¿ç”¨é»˜è®¤æœ¨é±¼éŸ³ï¼› -3. ä¿®æ”¹æ ‡é¢˜ã€ç®€ä»‹å’Œæ ‡ç¾ï¼› +3. ä¿®æ”¹æ ‡é¢˜ã€ç®€ä»‹å’Œæ ‡ç¾ï¼Œå¹¶åœ¨è¯•玩或å‘布å‰å†™å›žå½“å‰ä½œå“ä¿¡æ¯ï¼› 4. 修改ç¥ç¦è¯ï¼Œæœ€å¤š 8 æ¡ã€‚ 图案é‡ç”Ÿæˆæ˜¯ç‹¬ç«‹å±€éƒ¨ç”Ÿæˆæ€ï¼Œä¸å¾—æŠŠå·²æœ‰å¯æŸ¥çœ‹ç»“æžœé‡æ–°å˜æˆä¸å¯æ‰“开的全局生æˆä¸ã€‚音效替æ¢åªæŽ¥å—ä¸Šä¼ æˆ–å½•éŸ³èµ„äº§ï¼Œä¸è§¦å‘æç¤ºè¯éŸ³æ•ˆç”Ÿæˆã€‚ diff --git a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md index 8e0ef674..0afe6e42 100644 --- a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md +++ b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md @@ -134,9 +134,12 @@ RPG / 拼图ç‰è¿è¡Œæ€å˜æ¡£é€‰æ‹©å…¥å£ç»Ÿä¸€åœ¨ä¸ªäººä¸å¿ƒ `常用功能 > 1. `敲什么`:敲击物å•图资产槽ä½ã€‚默认模æ¿ä½¿ç”¨å†…ç½®é€æ˜Ž PNG `/wooden-fish/default-hit-object.png` 作为 `bundled-default` 敲击物资产,é¿å…默认关键è¯è¢«é‡æ–°è¯ä¹‰åŒ–æ”¹å½¢ï¼›ç”¨æˆ·è¾“å…¥è‡ªå®šä¹‰å…³é”®è¯æˆ–ä¸Šä¼ å‚考图时,åŽç«¯å¿…须以默认木鱼图作为基础结构和画风å‚考,使用 image2 ç”Ÿæˆæœ€ç»ˆæ•²å‡»ç‰©å›¾æ¡ˆï¼Œä¸Šä¼ 图åªä½œä¸ºæ–°ä¸»é¢˜å‚考,ä¸ç›´æŽ¥è¿›å…¥è¿è¡Œæ€ã€‚自定义 `compile-draft` / `regenerate-hit-object` å¿…é¡»å®Œæˆ image2 -> OSS ç§æœ‰å¯¹è±¡ -> asset object 登记和绑定åŽï¼Œå†ç”± `api-server` 注入真实 `hitObjectAsset.imageSrc`,ä¸èƒ½åªå†™ `/generated-wooden-fish-assets/...` å ä½è·¯å¾„,也ä¸èƒ½æŽ¥å—å‰ç«¯è¯·æ±‚自带的 `hitObjectAsset` çŸè·¯ç”Ÿæˆã€‚ 2. `敲击音效`:音频资产槽ä½ï¼Œå½“å‰åˆ›ä½œé˜¶æ®µåªæ”¯æŒç”¨æˆ·ä¸Šä¼ 或麦克风录制;未æä¾›éŸ³é¢‘时统一写回内置默认木鱼音 `/wooden-fish/default-hit-sound.mp3`。æç¤ºè¯ç”ŸæˆéŸ³æ•ˆå…¥å£ä¸´æ—¶å…³é—,通用 `/api/creation/audio/sound-effect` 对木鱼 `hit_sound` ç›®æ ‡ä¹Ÿè¿”å›ž `410 Gone`ï¼›`hitSoundPrompt` åªä½œä¸ºåކå²å…¼å®¹å—段ä¿ç•™ï¼Œä¸å‚与当å‰åˆ›ä½œæµç¨‹ï¼Œä¹Ÿä¸å¾—ç”± `spacetime-client` åˆæˆå‡éŸ³é¢‘路径。 -3. `功德有什么`:最多 8 æ¡é£˜å—,默认 `幸è¿ã€å¥åº·ã€è´¢å¯Œã€å§»ç¼˜ã€å¹¸ç¦ã€äº‹ä¸šã€æˆåŠŸã€åŠŸå¾·`;创作æ€åªä¿å˜è¯æ¡å,è¿è¡Œæ€é£˜å—展示时å†è¿½åŠ `+1`。è¿è¡Œæ€é¡¶éƒ¨æ€»æ•°å¡é‡‡ç”¨å“ç‰ŒåŒ–å¾½æ ‡æ ·å¼ï¼Œå项计数器预置展示在å¯å±•开颿¿ä¸ï¼Œæœªå‡ºçŽ°è¯æ¡åˆå§‹å€¼ä¸º 0。 +3. `功德有什么`:最多 8 æ¡é£˜å—,创作æ€é¦–å±åªä¿ç•™ä¸€ä¸ªé»˜è®¤è¯æ¡ `幸è¿`,其下æä¾›åŠ å·æ ¼ç»§ç»è¿½åŠ è¯æ¡ï¼›åˆ›ä½œæ€åªä¿å˜è¯æ¡å,è¿è¡Œæ€é£˜å—展示时å†è¿½åŠ `+1`。è¿è¡Œæ€é¡¶éƒ¨æ€»æ•°å¡é‡‡ç”¨å“ç‰ŒåŒ–å¾½æ ‡æ ·å¼ï¼Œå项计数器预置展示在å¯å±•开颿¿ä¸ï¼Œæœªå‡ºçŽ°è¯æ¡åˆå§‹å€¼ä¸º 0。 +4. `ä½œå“æ ‡é¢˜ / 作å“简介 / ä¸»é¢˜æ ‡ç¾`:ä¸å†æ”¾åœ¨åˆ›ä½œå·¥ä½œå°é¦–å±ï¼Œæ”¹ä¸ºç”Ÿæˆè‰ç¨¿åŽçš„结果页补录区,æäº¤è¯•玩或å‘布å‰å¿…须先写回当å‰ä½œå“ä¿¡æ¯ã€‚ä¸»é¢˜æ ‡ç¾ç¼–è¾‘æ ·å¼å¯¹é½æ‹¼å›¾ç»“æžœé¡µçš„èƒ¶å›Šæ ‡ç¾ç¼–辑器。 -图片生æˆé“¾è·¯å›ºå®šä¸ºä¸‰å›¾ image2 æµç¨‹ï¼šç¬¬ä¸€æ¥ç”¨é»˜è®¤æœ¨é±¼å›¾ä½œä¸ºç»“构和画风å‚考,按用户题æå…³é”®è¯æˆ–å‚è€ƒå›¾ä¸»é¢˜ç”Ÿæˆ `1:1` 绿色背景主体图(纯绿色绿幕),prompt 必须显å¼è¦æ±‚背景为å•一纯绿色 `#00FF00` ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— é˜´å½±ã€æ— é“具,主体完整居ä¸ï¼Œä¸”ç¦æ¢é»‘底ã€ç™½åº•ã€æ£‹ç›˜æ ¼å’Œä»»ä½•实底背景;åŽç«¯åœ¨è½åº“å‰åªå¯¹è¿™å¼ 绿幕主体图执行去绿背景处ç†ï¼Œä¸åšæ³›æŠ å›¾ï¼Œé¿å…误伤玉米ç‰ä¸»ä½“åƒç´ 。第二æ¥å¿…é¡»ä½¿ç”¨ç¬¬ä¸€æ¥æŠ å›¾å®ŒæˆåŽçš„逿˜Žå›¾ä½œä¸ºå‚考图,å†ç”¨æ–°æ•²å‡»ç‰©ä½œä¸ºä¸»é¢˜å’Œç”»é£Žå‚è€ƒç”Ÿæˆ `9:16` 背景环境图,背景图åªé€‚é…主题和画风,ä¸èƒ½åŒ…嫿–°æ•²å‡»ç‰©æœ¬ä½“,也ä¸èƒ½å¢žåŠ æœ¨æ§Œäº’åŠ¨ç‰©å“;画é¢ä¸å¤®ä¸»ä½“预留区必须干净,ä¸å¤® 40% åŒºåŸŸç¦æ¢å‡ºçŽ°ä¸»é¢˜ä¸»ä½“ã€ä¸»ä½“局部特写ã€è½®å»“å½±åæˆ–é‡å¤å…ƒç´ ï¼Œä¸»é¢˜å…ƒç´ åªèƒ½ä½œä¸ºå¤–围氛围。第三æ¥å¿…须使用去绿åŽçš„æ•²å‡»ç‰©ä¸»ä½“图和背景环境图作为å‚è€ƒå›¾ç”Ÿæˆ `1:1` è¿”å›žæŒ‰é’®å›¾ï¼Œè¿”å›žæŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œä¸å¤®åªä¿ç•™å•个左ç®å¤´ï¼Œå‚考图åªçº¦æŸåœ†å½¢åº•色和ç®å¤´é…色,ä¸å¾—å»¶ä¼¸åˆ°å¤æ‚é€ åž‹å’ŒèŠ±çº¹ï¼›æŒ‰é’®ä¸å¾—出现文å—ã€æ•°å—ã€æ°´å°ã€é¢å¤– UI 颿¿æˆ–木槌物å“。三个资产分别写回 `hitObjectAsset`ã€`backgroundAsset` 与 `backButtonAsset`,并绑定到 `wooden_fish_work` çš„ `hit_object` / `background` / `back_button` æ§½ä½ã€‚è¿è¡Œæ€å’Œç»“果页消费 `backgroundAsset` åšç«–å±èƒŒæ™¯ï¼Œä¸å¤®å†å åŠ `hitObjectAsset`,左上角返回按钮消费 `backButtonAsset`。 +图片生æˆé“¾è·¯å›ºå®šä¸ºä¸‰å›¾ image2 æµç¨‹ï¼šç¬¬ä¸€æ¥ç”¨é»˜è®¤æœ¨é±¼å›¾ä½œä¸ºç»“构和画风å‚考,按用户题æå…³é”®è¯æˆ–å‚è€ƒå›¾ä¸»é¢˜ç”Ÿæˆ `1:1` 绿色背景主体图(纯绿色绿幕),prompt 必须显å¼è¦æ±‚背景为å•一纯绿色 `#00FF00` ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— é˜´å½±ã€æ— é“具,主体完整居ä¸ï¼Œä¸”ç¦æ¢é»‘底ã€ç™½åº•ã€æ£‹ç›˜æ ¼å’Œä»»ä½•实底背景;åŽç«¯åœ¨è½åº“å‰åªå¯¹è¿™å¼ 绿幕主体图执行去绿背景处ç†ï¼Œä¸åšæ³›æŠ å›¾ï¼Œé¿å…误伤玉米ç‰ä¸»ä½“åƒç´ 。第二æ¥å¿…é¡»ä½¿ç”¨ç¬¬ä¸€æ¥æŠ å›¾å®ŒæˆåŽçš„逿˜Žå›¾ä½œä¸ºå‚考图,å†ç”¨æ–°æ•²å‡»ç‰©ä½œä¸ºä¸»é¢˜å’Œç”»é£Žå‚è€ƒç”Ÿæˆ `9:16` 背景环境图,背景图åªé€‚é…主题和画风,ä¸èƒ½åŒ…嫿–°æ•²å‡»ç‰©æœ¬ä½“,也ä¸èƒ½å¢žåŠ æœ¨æ§Œäº’åŠ¨ç‰©å“;画é¢ä¸å¤®ä¸»ä½“预留区必须干净,ä¸å¤® 40% åŒºåŸŸç¦æ¢å‡ºçŽ°ä¸»é¢˜ä¸»ä½“ã€ä¸»ä½“局部特写ã€è½®å»“å½±åæˆ–é‡å¤å…ƒç´ ï¼Œä¸»é¢˜å…ƒç´ åªèƒ½ä½œä¸ºå¤–围氛围。第三æ¥å¿…须使用去绿åŽçš„æ•²å‡»ç‰©ä¸»ä½“图和背景环境图作为å‚è€ƒå›¾ç”Ÿæˆ `1:1` è¿”å›žæŒ‰é’®å›¾ï¼Œè¿”å›žæŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œä¸»ä½“è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,圆形外沿必须有与主题色æé…的干净外æè¾¹ï¼Œä¸å¤®åªä¿ç•™å•个左ç®å¤´ï¼Œå‚考图åªçº¦æŸåœ†å½¢åº•色和ç®å¤´é…色,ä¸å¾—å»¶ä¼¸åˆ°å¤æ‚é€ åž‹å’ŒèŠ±çº¹ï¼›æŒ‰é’®ä¸å¾—出现文å—ã€æ•°å—ã€æ°´å°ã€é¢å¤– UI 颿¿æˆ–木槌物å“。三个资产分别写回 `hitObjectAsset`ã€`backgroundAsset` 与 `backButtonAsset`,并绑定到 `wooden_fish_work` çš„ `hit_object` / `background` / `back_button` æ§½ä½ã€‚è¿è¡Œæ€å’Œç»“果页消费 `backgroundAsset` åšç«–å±èƒŒæ™¯ï¼Œä¸å¤®å†å åŠ `hitObjectAsset`,左上角返回按钮消费 `backButtonAsset`。 + +木鱼åˆå§‹ `compile-draft` æ˜¯é•¿è€—æ—¶åŒæ¥ action,生æˆé¡µå¿…须按上述三图 image2 链路展示进度:整ç†è‰ç¨¿ã€ç”Ÿæˆæ•²å‡»ç‰©ã€ç”ŸæˆèƒŒæ™¯çŽ¯å¢ƒå›¾ã€ç”Ÿæˆè¿”回按钮图ã€å†™å…¥æ£å¼è‰ç¨¿ã€‚本地或供应商慢时一次 action å¯èƒ½æŒç»æ•°åˆ†é’Ÿï¼›å‰ç«¯ä¸å¾—把已关é—çš„æç¤ºè¯ç”ŸæˆéŸ³æ•ˆå½“æˆè¿›åº¦é˜¶æ®µï¼Œä¹Ÿä¸å¾—在未收到 action 回包å‰å®£ç§°ç”Ÿæˆå®Œæˆã€‚ è¿è¡Œæ€è§„则真相以åŽç«¯ run 摘è¦ä¸ºå‡†ï¼Œå‰ç«¯åªåšç‚¹å‡»ä½Žå»¶è¿Ÿè¡¨çŽ°ã€æ•²å‡»åŠ¨ç”»ã€éŸ³é¢‘æ’æ”¾å’Œé£˜å—æ¸²æŸ“ã€‚æ¯æ¬¡éžåŠŸèƒ½åŒºç‚¹å‡»åœ¨å½“å‰ run 内累计 `totalTapCount` å’Œ `wordCounters`;计数ä¸è¿›å…¥è´¦å·é•¿æœŸè´¦æœ¬ï¼Œä¸åšæŽ’è¡Œæ¦œã€‚é¡¶éƒ¨æ€»æ•°å¡ç‚¹å‡»åŽå±•å¼€åé¡¹è®¡æ•°å™¨é¢æ¿ï¼Œåé¡¹è®¡æ•°åœ¨é¢æ¿ä¸æŒ‰è¯æ¡çºµåˆ—é¢„ç½®å±•ç¤ºï¼Œæœªå‡ºçŽ°è¯æ¡åˆå§‹å€¼ä¸º 0,åŽç»åŒè¯æ¡ç»§ç»ç´¯åŠ ï¼›è¿è¡Œæ€å·¦ä¸Šè§’ä½¿ç”¨ä¸»é¢˜åŒ–è¿”å›žæŒ‰é’®å›¾ï¼Œä¸æä¾›å³ä¸Šè§’é‡å¼€æŒ‰é’®ã€‚ diff --git a/server-rs/crates/api-server/src/match3d/tests.rs b/server-rs/crates/api-server/src/match3d/tests.rs index 905a1697..425fcb69 100644 --- a/server-rs/crates/api-server/src/match3d/tests.rs +++ b/server-rs/crates/api-server/src/match3d/tests.rs @@ -874,6 +874,7 @@ fn match3d_regenerated_asset_keeps_stable_identity_and_side_assets() { container_image_object_key: None, status: "image_ready".to_string(), error: None, + ..Default::default() }); let mut generated_asset = test_match3d_generated_item_asset(99, "æ–°è‰èŽ“"); generated_asset.image_src = @@ -1062,6 +1063,7 @@ fn match3d_background_asset_requires_background_and_container_images() { container_image_object_key: None, status: "image_ready".to_string(), error: None, + ..Default::default() }; let with_container = Match3DGeneratedBackgroundAsset { container_prompt: Some("æžœå›å®¹å™¨".to_string()), @@ -1108,6 +1110,7 @@ fn match3d_default_cover_prefers_generated_container_ui_image() { container_image_object_key: None, status: "image_ready".to_string(), error: None, + ..Default::default() }), status: "image_ready".to_string(), error: None, @@ -1169,7 +1172,7 @@ fn match3d_cover_reference_prompt_marks_reference_images() { #[test] fn match3d_cover_edit_prompt_preserves_uploaded_image() { - let prompt = build_match3d_cover_edit_prompt("æ°´æžœå°é¢"); + let prompt = build_match3d_cover_uploaded_reference_prompt("æ°´æžœå°é¢"); assert!(prompt.contains("ä¸Šä¼ çš„å°é¢å›¾ä½œä¸ºç¬¬ä¸€ä¼˜å…ˆçº§")); assert!(prompt.contains("ä¿ç•™ä¸»å›¾çš„ä¸»ä½“ã€æž„图ã€è§†è§’和主è¦é…色")); @@ -1212,6 +1215,7 @@ fn match3d_fallback_work_profile_keeps_generated_background_asset() { ), status: "image_ready".to_string(), error: None, + ..Default::default() }), status: "image_ready".to_string(), error: None, @@ -1349,6 +1353,7 @@ fn match3d_agent_session_response_hydrates_persisted_ui_assets() { ), status: "image_ready".to_string(), error: None, + ..Default::default() }), status: "image_ready".to_string(), error: None, @@ -1424,6 +1429,7 @@ fn match3d_agent_session_response_keeps_draft_ui_assets_without_work_detail_hydr ), status: "image_ready".to_string(), error: None, + ..Default::default() }), status: "image_ready".to_string(), error: None, @@ -1807,6 +1813,7 @@ fn match3d_work_summary_marks_complete_generated_assets_ready() { ), status: "image_ready".to_string(), error: None, + ..Default::default() }), ..test_match3d_generated_item_asset(1, "è‰èŽ“") }]; diff --git a/server-rs/crates/api-server/src/wooden_fish.rs b/server-rs/crates/api-server/src/wooden_fish.rs index b5e94452..e254f3aa 100644 --- a/server-rs/crates/api-server/src/wooden_fish.rs +++ b/server-rs/crates/api-server/src/wooden_fish.rs @@ -747,7 +747,7 @@ fn build_wooden_fish_background_prompt(prompt: &str) -> String { fn build_wooden_fish_back_button_prompt(prompt: &str) -> String { format!( - "ç”Ÿæˆæ•²æœ¨é±¼å·¦ä¸Šè§’è¿”å›žæŒ‰é’®å›¾ã€‚è¦æ±‚以å‚考图-去除绿色背景åŽçš„æ•²å‡»ç‰©ä¸»ä½“和背景环境图为主题ã€ç”»é£Žã€æè´¨å’Œé…色å‚考,但å‚考图åªç”¨æ¥çº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸è¦ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆã€‚æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œæ•´ä½“åƒå•ä¸ªåœ†å½¢å›¾æ ‡ï¼Œåœ†å¿ƒå±…ä¸ï¼Œåœ†å½¢å†…部åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´ï¼Œä¸è¦å‡ºçŽ°æ–‡å—ã€æ•°å—ã€æ°´å°ã€æŒ‰é’®å¤–æ ‡ç¾ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“具。尺寸1:1,输出绿色背景主体图(纯绿色绿幕),背景必须是å•一纯绿色 #00FF00 ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— 阴影。按钮主体边缘干净,åŽç»ç”±æœåŠ¡ç«¯æ‰£é™¤ç»¿è‰²èƒŒæ™¯ï¼›æŒ‰é’®åº•è‰²ä¸è¦ä½¿ç”¨ä¸Žç»¿å¹•接近的纯绿色,若主题天然包å«ç»¿è‰²ï¼Œè¯·ä»…åœ¨åœ†å½¢åº•è‰²ä¸Šä½¿ç”¨åæ·±ã€å黄或åè“的主题绿色,并用更高对比的ç®å¤´é¢œè‰²åŒºåˆ†ã€‚\n主题为:{}", + "ç”Ÿæˆæ•²æœ¨é±¼å·¦ä¸Šè§’è¿”å›žæŒ‰é’®å›¾ã€‚è¦æ±‚以å‚考图-去除绿色背景åŽçš„æ•²å‡»ç‰©ä¸»ä½“和背景环境图为主题ã€ç”»é£Žã€æè´¨å’Œé…色å‚考,但å‚考图åªç”¨æ¥çº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…,ä¸è¦ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚å½¢å¤–æ¡†æˆ–è£…é¥°å›¾æ¡ˆã€‚æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢ï¼Œæ•´ä½“åƒå•ä¸ªåœ†å½¢å›¾æ ‡ï¼ŒæŒ‰é’®ä¸»ä½“åœ¨ç”»å¸ƒä¸çš„è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%,圆心居ä¸ï¼Œåœ†å½¢å¤–æ²¿åŠ ä¸€åœˆå’Œä¸»é¢˜è‰²æé…的干净外æè¾¹ï¼Œè®©å®ƒæ›´åƒä¸€ä¸ªæŒ‰é’®ï¼Œä½†ä»ç„¶åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´ï¼Œä¸è¦å‡ºçŽ°æ–‡å—ã€æ•°å—ã€æ°´å°ã€æŒ‰é’®å¤–æ ‡ç¾ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“具。尺寸1:1,输出绿色背景主体图(纯绿色绿幕),背景必须是å•一纯绿色 #00FF00 ä¸”å¹³æ•´æ— çº¹ç†ã€æ— æ¸å˜ã€æ— 阴影。按钮主体边缘干净,åŽç»ç”±æœåŠ¡ç«¯æ‰£é™¤ç»¿è‰²èƒŒæ™¯ï¼›æŒ‰é’®åº•è‰²ä¸è¦ä½¿ç”¨ä¸Žç»¿å¹•接近的纯绿色,若主题天然包å«ç»¿è‰²ï¼Œè¯·ä»…åœ¨åœ†å½¢åº•è‰²ä¸Šä½¿ç”¨åæ·±ã€å黄或åè“的主题绿色,并用更高对比的ç®å¤´é¢œè‰²åŒºåˆ†ã€‚\n主题为:{}", clean_string(prompt, DEFAULT_HIT_OBJECT_PROMPT) ) } @@ -1230,7 +1230,9 @@ mod tests { assert!(prompt.contains("å‚考图åªç”¨æ¥çº¦æŸåœ†å½¢åº•色和ä¸å¤®å·¦ç®å¤´çš„颜色æé…")); assert!(prompt.contains("æŒ‰é’®å¿…é¡»å§‹ç»ˆæ˜¯æ ‡å‡†åœ†å½¢")); - assert!(prompt.contains("圆形内部åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´")); + assert!(prompt.contains("按钮主体在画布ä¸çš„è§†è§‰å°ºå¯¸æ¯”å½“å‰æ¨¡æ¿å†æ”¾å¤§çº¦ 50%")); + assert!(prompt.contains("åœ†å½¢å¤–æ²¿åŠ ä¸€åœˆå’Œä¸»é¢˜è‰²æé…的干净外æè¾¹")); + assert!(prompt.contains("åªä¿ç•™ä¸€ä¸ªæ¸…æ™°ã€ç®€æ´ã€å±…ä¸çš„å‘左返回ç®å¤´")); assert!(prompt.contains("ä¸è¦ç»§æ‰¿å¤æ‚é€ åž‹ã€èŠ±çº¹ã€æµ®é›•è¾¹ã€å¼‚形外框或装饰图案")); assert!(prompt.contains("ä¸è¦å‡ºçŽ°æ–‡å—ã€æ•°å—ã€æ°´å°ã€æŒ‰é’®å¤–æ ‡ç¾ã€é¢å¤– UI 颿¿ã€æœ¨æ§Œæˆ–敲击é“å…·")); assert!(prompt.contains("按钮底色ä¸è¦ä½¿ç”¨ä¸Žç»¿å¹•接近的纯绿色")); diff --git a/src/components/common/CreativeImageInputPanel.tsx b/src/components/common/CreativeImageInputPanel.tsx index 78448e9d..1c23c838 100644 --- a/src/components/common/CreativeImageInputPanel.tsx +++ b/src/components/common/CreativeImageInputPanel.tsx @@ -56,6 +56,7 @@ export type CreativeImageInputPanelProps = { imageModelPicker?: ReactNode; error?: string | null; inputError?: string | null; + showSubmitButton?: boolean; submitLabel: string; submitCostLabel?: string | null; submitDisabled: boolean; @@ -98,6 +99,7 @@ export function CreativeImageInputPanel({ imageModelPicker = null, error = null, inputError = null, + showSubmitButton = true, submitLabel, submitCostLabel = null, submitDisabled, @@ -382,27 +384,31 @@ export function CreativeImageInputPanel({ -