From 01a68bcf3dde8f8963adf4ba377a08c886c71551 Mon Sep 17 00:00:00 2001 From: kdletters Date: Wed, 3 Jun 2026 19:54:27 +0800 Subject: [PATCH] fix: route creation wallet chip to top-up entry --- .hermes/shared-memory/decision-log.md | 1 + ...玩法创作】平å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md | 2 ++ .../RpgEntryHomeView.recharge.test.tsx | 35 +++++++++++++++++++ src/components/rpg-entry/RpgEntryHomeView.tsx | 4 +-- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md index 2a616fff..6f798308 100644 --- a/.hermes/shared-memory/decision-log.md +++ b/.hermes/shared-memory/decision-log.md @@ -216,6 +216,7 @@ - 背景:创作页顶部ã€banner å¥–æ± å’ŒçŽ©æ³•å¡æ¶ˆè€—å£å¾„æ›¾ç»æ··åœ¨ä¸€èµ·ï¼Œå®¹æ˜“把活动奖池误认æˆè´¦å·ä½™é¢ï¼Œä¹Ÿè®©æ¨ªå‘空间被外部边框和过大的å¡ç‰‡é«˜åº¦æŒ¤å ã€‚ - 决策:移动端创作 Tab é¡¶æ ä¸Ž `陶泥儿` å“牌åŒä¸€è¡Œåªæ˜¾ç¤ºçœŸå®žè´¦æˆ·æ³¥ç‚¹æ•°ï¼Œæ•°æ®ç›´æŽ¥å– `profileDashboard.walletBalance`ï¼›banner 内åªå±•ç¤ºèµ›äº‹å¥–æ± ï¼Œæ–°å¢žæ‹¼å›¾ä¸»é¢˜åˆ›ä½œèµ›å’ŒæŠ“å¤§é¹…ä¸»é¢˜åˆ›ä½œèµ›ï¼Œä¸¤ä¸ªä¸»é¢˜å¥–æ± å„ `1000` 泥点数;玩法å¡å°é¢å³ä¸‹è§’固定展示 `10-20泥点数`ï¼Œåˆ—è¡¨å¤–æ¡†å–æ¶ˆï¼Œå¡ç‰‡é«˜åº¦å’Œæ¨ªå‘é—´è·ä¸€èµ·æ”¶ç´§ã€‚ +- 追加决策:创作页和è‰ç¨¿é¡µé¡¶æ å³ä¸Šæ³¥ç‚¹ä½™é¢èƒ¶å›Šæ˜¯è¡¥è¶³æ³¥ç‚¹å…¥å£ï¼›å½“å‰çŽ¯å¢ƒå¼€å¯å……值入壿—¶ç›´æŽ¥æ‰“开账户充值弹窗,å¦åˆ™æ‰“å¼€è¿è¥å…‘æ¢ç å¼¹çª—,ä¸å†è·³åˆ°è´¦æˆ·é¢æ¿æˆ–泥点账å•。 - å½±å“范围:`src/components/custom-world-home/CustomWorldCreationStartCard.tsx`ã€`src/components/rpg-entry/RpgEntryHomeView.tsx`ã€åˆ›ä½œé¡µç›¸å…³æµ‹è¯•和玩法链路文档。 - éªŒè¯æ–¹å¼ï¼šç§»åŠ¨ç«¯æµè§ˆå™¨æ£€æŸ¥åº”看到创作顶æ ä½™é¢ã€å¡å†…分页点ã€å†…åµŒæ¨ªå‘ banner 和更紧凑的玩法å¡ï¼›`CustomWorldCreationHub.test.tsx` 与 `RpgEntryHomeView.recharge.test.tsx` çš„å®šå‘æ–­è¨€åº”ä¿æŒé€šè¿‡ã€‚ - å…³è”æ–‡æ¡£ï¼š`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 diff --git a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md index 479c91c2..561b7133 100644 --- a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md +++ b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md @@ -8,6 +8,8 @@ 当å‰ç‚¹å‡»åº•部加å·è¿›å…¥çš„创作入å£é¡µæ‰¿è½½åŽå°å…¬å‘Šä½ã€åˆ›ä½œå…¥å£é¡µç­¾å’Œä¸¤åˆ—模æ¿å¡ï¼›é¡µç­¾ä¸­åªæœ‰çœŸå®žåŽç«¯ä½œå“架摘è¦å­˜åœ¨æ—¶æ‰å±•示“最近创作â€ï¼Œå…¶ä½™ä¸ºçŽ©æ³•æ¨¡æ¿åˆ†ç±»ã€‚点击模æ¿å¡åŽç›´æŽ¥è¿›å…¥å¯¹åº”玩法已有的入å£åˆ›ä½œè¡¨å• stage,ä¸å†ç»è¿‡ç©ºç™½å ä½é¡µï¼Œä¹Ÿä¸æŠŠæ—§è¡¨å•嵌进创作入å£é¡µã€‚移动端创作入å£é¡µé¡¶æ åœ¨ `陶泥儿` å“牌åŒä¸€è¡Œæ˜¾ç¤ºçœŸå®žè´¦æˆ·æ³¥ç‚¹æ•°ï¼Œæ•°æ®æ¥è‡ª `profileDashboard.walletBalance`,ä¸å¾—å†æŠŠå…¬å‘Šå†…å®¹æˆ–æ´»åŠ¨å¥–æ± å½“ä½œè´¦å·ä½™é¢å±•示。创作入å£é¡µå…¬å‘Šä½æ•°æ®ä¼˜å…ˆè¯»å– `GET /api/creation-entry/config` çš„ `eventBanners` 数组,多æ¡é…置时å‰ç«¯è‡ªåŠ¨è½®æ’­ï¼Œæ—§ `eventBanner` ä»…ä½œä¸ºå•æ¡å…¼å®¹å…œåº•。åŽå°å…¬å‘Šé…ç½®é¢å‘表å•ï¼šæ¯æ¡å…¬å‘ŠåŒ…嫿 ‡é¢˜å’Œ HTML 内容,åŽå°ä¿å­˜æ—¶åºåˆ—化为åŽç«¯ `eventBannersJson` 传输字段,由å‰ç«¯ç©ºæƒé™æ²™ç®± iframe 展示;旧结构化 banner 字段仅ä¿ç•™å›žæ˜¾å…¼å®¹ï¼Œä¸å†ä½œä¸ºåŽå°å…¬å‘Šé…置主格å¼ï¼›ä¸å¾—执行 JSX 或把åŽå°ä»£ç ç›´æŽ¥æ³¨å…¥ DOM。玩法列表ä¸å†å¥—外部边框å¡ç‰‡ï¼Œç§»åŠ¨ç«¯éœ€è¦åŽ‹ç¼©æ¨ªå‘è¾¹è·å’Œä¸¤åˆ—é—´è·ï¼›çŽ©æ³•å¡ç»Ÿä¸€æŒ‰â€œä¸Šå›¾ã€å·¦ä¸ŠçŠ¶æ€æ ‡ç­¾ï¼ˆä»…éžå¼€æ”¾æ€æ˜¾ç¤ºï¼‰ã€å°é¢å³ä¸‹ `10-20泥点数`ã€ä¸‹æ–¹ç™½åº•标题/æè¿°â€ç»“构展示,å¡ç‰‡é«˜åº¦ä¿æŒç´§å‡‘ä½†æ ‡é¢˜ã€æè¿°å’Œé¢„ä¼°æ¶ˆè€—ç‚¹æ•°éƒ½å¿…é¡»å¯è§ã€‚创作入å£é¡µæ ¹å®¹å™¨ä¸å†ä½¿ç”¨ `platform-page-stage` 这类全局内容å¡ç‰‡å£³ï¼Œä½†ç»§ç»­ä¿ç•™ `platform-remap-surface` 作为主题和输入框样å¼å‘½ä¸­é’©å­ã€‚创作入å£é¡µå­—å·éœ€è¦å¯¹é½å¹³å°æ™®é€š UI æ¡£ä½ï¼šé¡¶æ æ³¥ç‚¹ç»„ä»¶ã€å…¬å‘Šæ­£æ–‡ã€åˆ†ç±» Tab å’ŒçŽ©æ³•å¡æ ‡é¢˜ / 副标题 / 消耗说明优先使用 `11px` 到 `14px`,ä¸ä½¿ç”¨ `text-lg`ã€`text-xl` 或更大的展示级字å·ã€‚è‰ç¨¿ Tab ç»§ç»­æ‰¿æŽ¥ä½œå“æž¶ï¼›åº•部加å·å…¥å£é¡µçš„“最近创作â€åªç”¨ 7 天内的真实åŽç«¯ä½œå“架摘è¦åˆ¤æ–­æ˜¯å¦å±•示,并从摘è¦é‡ŒæŽ¨å¯¼æœ€è¿‘ä½¿ç”¨è¿‡çš„æ¨¡æ¿ ID,页é¢å¿…须展示“仅显示最近7天内使用过的模æ¿â€æç¤ºï¼Œåˆ—表内容必须å¤ç”¨å…¶å®ƒé¡µç­¾é‡Œçš„æ¨¡æ¿å¡æ ·å¼ã€æ–‡æ¡ˆå’Œç‚¹å‡»è¡Œä¸ºï¼Œä¸å±•示具体作å“åç§°ã€æ‘˜è¦æˆ–生æˆçжæ€ï¼Œä¹Ÿä¸æ–°å¢žç‹¬ç«‹æœ€è¿‘创作å¡ç»„件。RPGã€RPG 之外的å„玩法入å£åˆ†åˆ«è½åˆ°æ—¢æœ‰çš„ `agent-workspace`ã€`big-fish-agent-workspace`ã€`match3d-agent-workspace`ã€`square-hole-agent-workspace`ã€`jump-hop-workspace`ã€`wooden-fish-workspace`ã€`puzzle-agent-workspace`ã€`bark-battle-workspace`ã€`visual-novel-agent-workspace`ã€`baby-object-match-workspace`,这些入å£ç»§ç»­æ‰¿æŽ¥å„玩法自己的表å•ã€è‰ç¨¿æ¢å¤å’ŒåŽç»­ç¼–排,ä¸ä½œä¸ºåˆ›ä½œå…¥å£é¡µå†…容。 +创作页和è‰ç¨¿é¡µé¡¶æ å³ä¸Šè§’的泥点余é¢èƒ¶å›Šæ˜¯è¡¥è¶³æ³¥ç‚¹å…¥å£ï¼šå¦‚果当å‰è¿è¡ŒçŽ¯å¢ƒå¼€å¯å……值入å£ï¼Œç‚¹å‡»åŽç›´æŽ¥æ‰“开账户充值弹窗;å¦åˆ™ç›´æŽ¥æ‰“å¼€è¿è¥å…‘æ¢ç å¼¹çª—。该入å£ä¸å†è·³åˆ°è´¦æˆ·é¢æ¿æˆ–泥点账å•ï¼Œå¤´åƒ / 设置等账å·å…¥å£ç»§ç»­ä¿ç•™å„自语义。 + 创作æ¢å¤å‚æ•°åªä¿ç•™ `sessionId`ã€`profileId`ã€`draftId`ã€`workId` è¿™å››ä¸ªç§æœ‰ query。它们åªå…许在åŒä¸€æ¡åˆ›ä½œé“¾è·¯çš„结果页ã€ç”Ÿæˆé¡µã€å·¥ä½œå°ä¹‹é—´ä¿ç•™ï¼›åˆ‡åˆ°é¦–页ã€å…¬å¼€ä½œå“详情ã€runtime 或å¦ä¸€æ¡çŽ©æ³•é“¾è·¯æ—¶å¿…é¡»æ¸…æŽ‰ã€‚ç”Ÿæˆé¡µç­‰å¾…时间统一以生æˆçжæ€é‡Œçš„ `startedAtMs` ä¸ºå‡†ï¼›åˆ›å»ºè¯¥çŠ¶æ€æ—¶ä¼˜å…ˆä½¿ç”¨åŽç«¯ session 下å‘çš„æ—¶é—´æˆ³ï¼Œä½œå“æ‘˜è¦é‡Œçš„ `updatedAt` ä»åªç”¨äºŽæŽ’åºä¸Žæ‘˜è¦å±•示,ä¸ä½œä¸ºå‰ç«¯è‡ªè¡ŒæŽ¨å¯¼ä¸šåŠ¡çŠ¶æ€çš„真相。 统一创作入å£è¦†ç›–当å‰å¯è¿›å…¥åˆ›ä½œé“¾è·¯çš„已有模æ¿ï¼š`rpg`ã€`big-fish`ã€`puzzle`ã€`match3d`ã€`jump-hop`ã€`wooden-fish`ã€`square-hole`ã€`bark-battle`ã€`visual-novel`ã€`baby-object-match` å’Œ `creative-agent`ï¼›`airp` 仿˜¯æœªå¼€æ”¾å ä½ï¼Œä¸ä½œä¸ºå½“å‰ç»Ÿä¸€åˆ›ä½œé“¾è·¯ç›®æ ‡ã€‚æ‹¼å›¾ã€æŠ“å¤§é¹…ã€è·³ä¸€è·³å’Œæ•²æœ¨é±¼åœ¨å‰ç«¯ç»§ç»­ç»è¿‡ `UnifiedCreationWorkspace` å’Œ `UnifiedGenerationPage`:`UnifiedCreationWorkspace` 作为平å°å£³ä¾èµ–的统一创作编排层,å†å†…部调用 `src/components/unified-creation/workspaces/` 下的 `PuzzleCreationWorkspace`ã€`Match3DCreationWorkspace`ã€`JumpHopCreationWorkspace` å’Œ `WoodenFishCreationWorkspace`。其它已有模æ¿ç”±å¹³å°å£³ç”¨ `UnifiedCreationPage` åŒ…ä½æ—¢æœ‰å·¥ä½œå°ï¼Œå¤ç”¨ç»Ÿä¸€æ ‡é¢˜æ ã€è¿”回入å£ã€é¡µé¢çº§çºµå‘滚动和éšè—å­—æ®µå¥‘çº¦ï¼ŒåŒæ—¶ä¿ç•™å„玩法自己的表å•ã€è‰ç¨¿æ¢å¤å’ŒåŽç»­ç¼–排。创作页字段清å•ç”±åŽç«¯åœ¨ `GET /api/creation-entry/config` çš„ `creationTypes[].unifiedCreationSpec` 下å‘,å‰ç«¯ä»…在该扩展ä½ç¼ºå¤±æ—¶å›žé€€åˆ°æœ¬åœ°é»˜è®¤ spec;字段类型åªä¿ç•™ `text`ã€`select`ã€`image`ã€`audio`。`UnifiedCreationPage` ä¸åœ¨ UI 中é¢å¤–展示字段说明 chip,也ä¸åœ¨å³ä¸Šè§’显示内部 `playId`ã€æ¨¡æ¿ ID 或工作å°é˜¶æ®µå;竖å±ç§»åŠ¨ç«¯å¿…é¡»èƒ½ä»Žæ ‡é¢˜ã€è¡¨å•一路滑到æäº¤æŒ‰é’®ã€‚å„玩法工作å°è´Ÿè´£æ¸²æŸ“真实输入控件ã€ä¸Šä¼ ã€åކå²ç´ æã€æ ¡éªŒå’Œæäº¤ï¼Œä½†è¿”回按钮åªä¿ç•™åœ¨ç»Ÿä¸€é¡µå¤´ï¼Œå·¥ä½œå°å†…部ä¸å†é‡å¤æ¸²æŸ“。暗色创作进度å¡ç‰‡ä½äºŽ `platform-remap-surface` 内时,必须用组件专属 class 覆盖浅色主题 remap,确ä¿ç™½å­—ã€æµ…色边框和进度æ¡åº•色ä¸ä¼šè¢«å…¨å±€è§„åˆ™æ”¹æˆæ·±è‰²ï¼›ä¸è¦åªä¾èµ–通用 `text-white*` ç±»ã€‚æ•²æœ¨é±¼çš„éŸ³æ•ˆå’ŒåŠŸå¾·è¯æ¡é¢æ¿ä¸å¾—放进独立内部滚动容器,移动端应跟éšé¡µé¢è‡ªç„¶æ»šåŠ¨å±•å¼€ã€‚ç”Ÿæˆé¡µç»Ÿä¸€å±•示阶段ã€å½“剿­¥éª¤ã€æ€»è¿›åº¦ã€é”™è¯¯å’Œé‡è¯•动作。 diff --git a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx index 989b581e..07f39d36 100644 --- a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx +++ b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx @@ -3137,6 +3137,41 @@ test('logged in create tab shows real wallet balance beside the brand', () => { expect(topbar?.textContent).toContain('1,234泥点'); }); +test('create tab wallet chip opens reward code when recharge entry is hidden', async () => { + const user = userEvent.setup(); + mockNarrowMobileLayout(); + + render( + , + ); + + await user.click(screen.getByRole('button', { name: /^70泥点$/u })); + + expect(await screen.findByPlaceholderText('输入兑æ¢ç ')).toBeTruthy(); + expect(mockGetRpgProfileRechargeCenter).not.toHaveBeenCalled(); +}); + +test('create tab wallet chip opens recharge when recharge entry is enabled', async () => { + const user = userEvent.setup(); + mockWechatDesktopLayout(); + + render( + , + ); + + await user.click(screen.getByRole('button', { name: /^70泥点$/u })); + + expect(await screen.findByText('账户充值')).toBeTruthy(); + expect(mockGetRpgProfileRechargeCenter).toHaveBeenCalledTimes(1); + expect(screen.queryByPlaceholderText('输入兑æ¢ç ')).toBeNull(); +}); + test('mobile discover search submits public work code', async () => { const user = userEvent.setup(); const onSearchPublicCode = vi.fn(); diff --git a/src/components/rpg-entry/RpgEntryHomeView.tsx b/src/components/rpg-entry/RpgEntryHomeView.tsx index 6d5a5a8d..9d2a37d9 100644 --- a/src/components/rpg-entry/RpgEntryHomeView.tsx +++ b/src/components/rpg-entry/RpgEntryHomeView.tsx @@ -7063,7 +7063,7 @@ export function RpgEntryHomeView({ (activeTab === 'create' || activeTab === 'saves') ? (