From 545ffa4b2cb8c6ede809091af9f459b4694278bf Mon Sep 17 00:00:00 2001 From: kdletters Date: Wed, 3 Jun 2026 12:09:03 +0800 Subject: [PATCH] fix: hide public card account identifiers --- .codex/environments/environment.toml | 2 +- .hermes/shared-memory/pitfalls.md | 8 +++++ ...玩法创作】平å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md | 2 ++ .../PlatformWorkDetailView.test.tsx | 7 ++-- .../RpgEntryHomeView.recharge.test.tsx | 28 ++++++++++++++++ .../rpgEntryWorldPresentation.test.ts | 32 ++++++++++++++++++- .../rpg-entry/rpgEntryWorldPresentation.ts | 27 +++++++++++++--- 7 files changed, 96 insertions(+), 10 deletions(-) diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml index fd735e29..c12cc7b1 100644 --- a/.codex/environments/environment.toml +++ b/.codex/environments/environment.toml @@ -4,7 +4,7 @@ name = "Genarrative" [setup] script = ''' -cp "$CODEX_SOURCE_TREE_PATH\.env.secrets.local" "$CODEX_WORKTREE_PATH\.env.secrets.local" +cp "$CODEX_SOURCE_TREE_PATH/.env.secrets.local" "$CODEX_WORKTREE_PATH/.env.secrets.local" npm install npm run codegraph:init npm run codegraph:index diff --git a/.hermes/shared-memory/pitfalls.md b/.hermes/shared-memory/pitfalls.md index 8fb8aacb..4aff3fc0 100644 --- a/.hermes/shared-memory/pitfalls.md +++ b/.hermes/shared-memory/pitfalls.md @@ -1572,6 +1572,14 @@ - 验è¯ï¼š`npm run test -- src/components/rpg-entry/rpgEntryWorldPresentation.test.ts src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`ã€`npm run typecheck`ã€`npm run check:encoding`。 - å…³è”:`src/index.css`ã€`src/components/rpg-entry/RpgEntryHomeView.tsx`ã€`src/components/rpg-entry/rpgEntryWorldPresentation.ts`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 +## 公开作å“å¡ä½œè€…行ä¸è¦æ‹¼æ‰‹æœºå·æˆ–é™¶æ³¥å· + +- 现象:å‘现页 / 推è页公开作å“å¡ä½œè€…行显示 `158****3533 · SY-00000003` è¿™ç±»æ‰‹æœºå·æŽ©ç å’Œé™¶æ³¥å·ç»„åˆï¼Œåˆ—表å¡ç‰‡çœ‹èµ·æ¥åƒæš´éœ²è´¦å·æ ‡è¯†ã€‚ +- 原因:`resolvePlatformWorkAuthorDisplayName(...)` 曾把公开昵称和 `publicUserCode` 拼接为 `昵称 · SY-*`,并在无法解æžå…¬å¼€æ˜µç§°æ—¶ç›´æŽ¥å›žé€€åŽç«¯å¡ç‰‡é‡Œçš„ `authorDisplayName`;当åŽç«¯æˆ–æ—§æŠ•å½±æŠŠæ‰‹æœºå·æŽ©ç å†™è¿›å±•ç¤ºåæ—¶ï¼Œå¡ç‰‡ä¼šåŽŸæ ·å¤–éœ²ã€‚ +- 处ç†ï¼šå…¬å¼€å¡ç‰‡ä½œè€…ååªå–å¯è¯»å…¬å¼€æ˜µç§°ï¼›è¯†åˆ«æ‰‹æœºå·æŽ©ç ã€å•独 `SY-*` 或 `æ‰‹æœºå·æŽ©ç  Â· SY-*` 时回退为 `玩家`。作å“å·å¤åˆ¶ã€é™¶æ³¥å·æœç´¢å’Œå®Œæ•´èº«ä»½å±•ç¤ºåªæ”¾åœ¨è¯¦æƒ…é¡µã€æœç´¢æˆ–明确å¤åˆ¶å…¥å£ï¼Œä¸å¡žè¿›å¡ç‰‡ä½œè€…行。 +- 验è¯ï¼š`npm run test -- src/components/rpg-entry/rpgEntryWorldPresentation.test.ts src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/platform-entry/PlatformWorkDetailView.test.tsx`。 +- å…³è”:`src/components/rpg-entry/rpgEntryWorldPresentation.ts`ã€`src/components/rpg-entry/RpgEntryHomeView.tsx`ã€`src/components/platform-entry/PlatformWorkDetailView.tsx`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 + ## 生æˆä¸­è‰ç¨¿æ¢å¤è¦æŒ‰åŽç«¯æ—¶é—´æˆ³è®¡æ—¶ - 现象:拼图或抓大鹅è‰ç¨¿ç”Ÿæˆä¸­åˆ·æ–°ç½‘页åŽï¼Œè¿›å…¥ç”Ÿæˆé¡µçš„“已耗时â€ä»Ž `0 ç§’` 釿–°å¼€å§‹ï¼›å¦ä¸€ç±»æ—§é—®é¢˜æ˜¯åŽç«¯ `progressPercent=88` 时总进度首帧直接跳到 `88%`。 diff --git a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md index b5d29797..479c91c2 100644 --- a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md +++ b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md @@ -54,6 +54,8 @@ 10. æ•²æœ¨é±¼ä½œå“æž¶è¯»å–当å‰ç”¨æˆ·ä½œå“列表时走 `GET /api/creation/wooden-fish/works`ï¼›å‘布æˆåŠŸåŽå¹³å°å£³å¿…é¡»åŒæ—¶åˆ·æ–°ä½œå“架与公开广场,é¿å…作å“刚å‘布时ä»åœç•™åœ¨æ—§åˆ—表。 11. 移动端è‰ç¨¿é¡µæ•´ä½“ç¦æ­¢é•¿æŒ‰é€‰æ‹©æ–‡å­—,é¿å…è¯¯è§¦ç³»ç»Ÿé€‰åŒºï¼›è¾“å…¥æ¡†ã€æ–‡æœ¬åŸŸå’Œå¯ç¼–辑区域ä»å¿…é¡»ä¿ç•™æ–‡æœ¬é€‰æ‹©èƒ½åŠ›ã€‚ +å‘现页 / 推è页公开作å“å¡çš„ä½œè€…è¡Œåªæ˜¾ç¤ºå¯è¯»å…¬å¼€æ˜µç§°ï¼›ä¸å¾—æŠŠæ‰‹æœºå·æŽ©ç ã€`SY-*` é™¶æ³¥å·æˆ–作å“å·æ‹¼æŽ¥è¿›å¡ç‰‡ä½œè€…åã€‚é™¶æ³¥å·æœç´¢ã€ä½œå“å·å¤åˆ¶å’Œå®Œæ•´ä½œå“身份åªåœ¨æœç´¢ã€è¯¦æƒ…页或明确的å¤åˆ¶å…¥å£å±•示,é¿å…å¡ç‰‡åˆ—è¡¨æš´éœ²è´¦å·æ ‡è¯†ã€‚ + å‘现 Tabã€åˆ›ä½œ Tab 与è‰ç¨¿ Tab çš„é¡µé¢æ ¹å†…容区ä¸å†å¥— `platform-page-stage` 外层全局å¡ç‰‡å£³ï¼Œè®©åˆ—表ã€ç­›é€‰å’ŒçŽ©æ³•å¡èŽ·å¾—æ›´å®½çš„æ¨ªå‘空间;推èé¡µå’Œæˆ‘çš„é¡µä»æŒ‰å„自页é¢è®¾è®¡ä¿ç•™åŽŸæœ‰å…¨å±€å¡ç‰‡å£å¾„。移动端“我的â€é¡µä»æŒ‰é¡¶éƒ¨å¤´åƒ / 昵称 / é™¶æ³¥å·ã€ä¼šå‘˜æ¨ªå¹…ã€ä¸‰å¼ ç»Ÿè®¡å¡ã€æ¯æ—¥ä»»åŠ¡ã€äº”项常用功能宫格ã€è®¾ç½®å…¥å£å’Œæ³•律信æ¯ç»„织,ä¸ä¿ç•™æ—§çš„底部“填邀请ç â€æ¬¡çº§å…¥å£ï¼›å¸¸ç”¨åŠŸèƒ½å½“å‰åªå±•ç¤ºå››é¡¹å¸¸é©»å…¥å£æ—¶å¿…须按四列铺满整行,ä¸ä¿ç•™äº”列网格导致左对é½ç©ºä½ï¼›æ¯æ—¥ä»»åŠ¡å¡å¿…é¡»è¯»å– `/api/profile/tasks` 的当å‰ä»»åŠ¡æ‘˜è¦å¹¶åœ¨é¢†å–åŽåŒæ­¥åˆ·æ–°å¡ç‰‡è¿›åº¦ã€‚å­—å·å¿…须维æŒå¹³å°æ™®é€š UI æ¡£ä½ï¼Œä¸èƒ½å› ä¸ºçª„å±æŠŠå¡ç‰‡æ ‡é¢˜ã€åŠŸèƒ½ label æˆ–æ³•å¾‹ä¿¡æ¯æ’‘æˆå±•示级字å·ï¼›æœ€åŽä¸€å±å†…容必须能在底部 dock 上方完整滚动露出,ä¸å¾—è¢«å›ºå®šåº•éƒ¨å¯¼èˆªé®æŒ¡ã€‚ ## RPG / 自定义世界 diff --git a/src/components/platform-entry/PlatformWorkDetailView.test.tsx b/src/components/platform-entry/PlatformWorkDetailView.test.tsx index 5275c565..4d23684e 100644 --- a/src/components/platform-entry/PlatformWorkDetailView.test.tsx +++ b/src/components/platform-entry/PlatformWorkDetailView.test.tsx @@ -163,7 +163,7 @@ test('PlatformWorkDetailView prefers resolved public user display name', () => { expect(screen.queryByText('137****6613')).toBeNull(); }); -test('PlatformWorkDetailView prefers display name then public user code for wooden fish works', () => { +test('PlatformWorkDetailView prefers display name without appending public user code', () => { render( , ); - expect(screen.getByText('公开昵称 · SY-00000004')).toBeTruthy(); + expect(screen.getByText('公开昵称')).toBeTruthy(); + expect(screen.queryByText('公开昵称 · SY-00000004')).toBeNull(); + expect(screen.queryByText('SY-00000004')).toBeNull(); expect(screen.queryByText('phone_00000004')).toBeNull(); expect(screen.queryByText('敲木鱼玩家')).toBeNull(); - expect(screen.queryByText('公开昵称')).toBeNull(); }); test('PlatformWorkDetailView calls like handler', () => { diff --git a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx index f0e2a7eb..989b581e 100644 --- a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx +++ b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx @@ -3434,6 +3434,34 @@ test('public gallery cards hide work code until detail is opened', async () => { expect(onOpenGalleryDetail).toHaveBeenCalledWith(puzzlePublicEntry); }); +test('public gallery cards hide phone masked author and public user code', async () => { + mockDesktopLayout(); + const user = userEvent.setup(); + const maskedAuthorEntry = { + ...puzzlePublicEntry, + workId: 'puzzle-work-masked-author', + profileId: 'puzzle-profile-masked-author', + publicWorkCode: 'PZ-MASKED1', + authorDisplayName: '158****3533 · SY-00000003', + worldName: '喜气洋洋', + } satisfies PlatformPublicGalleryCard; + + renderStatefulLoggedOutHomeView( + { + latestEntries: [maskedAuthorEntry], + }, + true, + ); + await user.click(screen.getByRole('button', { name: 'å‘现' })); + + const card = screen.getByRole('button', { name: /喜气洋洋/u }); + expect(card).toBeTruthy(); + expect(within(card).getByText('公开作者')).toBeTruthy(); + expect(within(card).queryByText('158****3533 · SY-00000003')).toBeNull(); + expect(within(card).queryByText('158****3533')).toBeNull(); + expect(within(card).queryByText('SY-00000003')).toBeNull(); +}); + test('logged out mobile shell defaults to discover tab', () => { const { container } = renderStatefulLoggedOutHomeView({ latestEntries: [puzzlePublicEntry], diff --git a/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts b/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts index 33918436..765d4436 100644 --- a/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts +++ b/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts @@ -224,7 +224,7 @@ test('resolves public work author from display name and public user code before displayName: '公开昵称', avatarUrl: null, }), - ).toBe('公开昵称 · SY-00000004'); + ).toBe('公开昵称'); expect( resolvePlatformWorkAuthorDisplayName(card, { id: 'user_00000004', @@ -237,6 +237,36 @@ test('resolves public work author from display name and public user code before expect(resolvePlatformWorkAuthorDisplayName(card, null)).toBe('敲木鱼玩家'); }); +test('public work author display hides phone masks and public user codes on cards', () => { + const card = mapWoodenFishWorkToPlatformGalleryCard({ + publicWorkCode: 'WF-AUTHOR2', + workId: 'wooden-fish-work-author-mask', + profileId: 'wooden-fish-profile-author-mask', + ownerUserId: 'user-author-mask', + authorDisplayName: '158****3533 · SY-00000003', + workTitle: '喜气洋洋', + workDescription: '喜庆主题敲木鱼。', + coverImageSrc: null, + themeTags: ['敲木鱼'], + publicationStatus: 'published', + playCount: 0, + updatedAt: '2026-05-20T00:00:00.000Z', + publishedAt: '2026-05-20T00:00:00.000Z', + generationStatus: 'ready', + }); + + expect( + resolvePlatformWorkAuthorDisplayName(card, { + id: 'user_00000003', + publicUserCode: 'SY-00000003', + username: '158****3533', + displayName: '158****3533', + avatarUrl: null, + }), + ).toBe('玩家'); + expect(resolvePlatformWorkAuthorDisplayName(card, null)).toBe('玩家'); +}); + test('keeps baby object match public card code and template label intact', () => { const card: PlatformEdutainmentGalleryCard = { sourceType: 'edutainment', diff --git a/src/components/rpg-entry/rpgEntryWorldPresentation.ts b/src/components/rpg-entry/rpgEntryWorldPresentation.ts index e4ee3ecd..ff4b511e 100644 --- a/src/components/rpg-entry/rpgEntryWorldPresentation.ts +++ b/src/components/rpg-entry/rpgEntryWorldPresentation.ts @@ -867,14 +867,31 @@ export function resolvePlatformWorkAuthorDisplayName( entry: PlatformPublicGalleryCard, authorSummary?: PublicUserSummary | null, ) { - const displayName = authorSummary?.displayName?.trim(); - const publicUserCode = authorSummary?.publicUserCode?.trim(); + const displayName = normalizePlatformPublicAuthorName( + authorSummary?.displayName, + ); + const entryAuthorName = normalizePlatformPublicAuthorName( + entry.authorDisplayName, + ); - if (displayName && publicUserCode) { - return `${displayName} · ${publicUserCode}`; + return displayName || entryAuthorName || '玩家'; +} + +function normalizePlatformPublicAuthorName(value: string | null | undefined) { + const normalized = value?.trim() ?? ''; + if (!normalized || normalized === 'null' || normalized === 'undefined') { + return ''; } - return displayName || publicUserCode || entry.authorDisplayName.trim() || '玩家'; + const compact = normalized.replace(/\s+/gu, ''); + if (/^\d+\*+\d+(?:[·.-]?SY-\d+)?$/iu.test(compact)) { + return ''; + } + if (/^SY-\d+$/iu.test(compact)) { + return ''; + } + + return normalized; } export function buildPlatformWorldDisplayTags(