统一界面上的ip形象标识

新增陶泥儿产品 IP 公共图片资产
左上角品牌标识和绑定页品牌块统一展示该形象
更新产品基线、创作主页方案和共享决策记录
This commit is contained in:
2026-06-23 15:48:03 +08:00
parent c8aa1775f3
commit dab879e0c4
14 changed files with 118 additions and 27 deletions
@@ -50,6 +50,11 @@ test('绑定手机号表单复用平台输入和字段标题', async () => {
expect(screen.getByText('当前登录身份:微信旅人').className).toContain(
'platform-subpanel',
);
expect(
document
.querySelector('.selection-hero-brand__image')
?.getAttribute('src'),
).toBe('/branding/taonier-product-ip.png');
await user.type(phoneInput, '13800000000');
await user.type(codeInput, '123456');
+11 -1
View File
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import type { PlatformTheme } from '../../../packages/shared/src/contracts/runtime';
import type { AuthCaptchaChallenge, AuthUser } from '../../services/authService';
import { BRAND_ASSETS } from '../../uiAssets';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
@@ -67,7 +68,16 @@ export function BindPhoneScreen({
<div className="platform-auth-card grid w-full max-w-4xl overflow-hidden rounded-[28px] md:grid-cols-[1.05fr_0.95fr]">
<div className="border-b border-[var(--platform-subpanel-border)] bg-[linear-gradient(135deg,rgba(204,117,76,0.18),rgba(240,203,169,0.16))] px-6 py-8 md:border-b-0 md:border-r md:px-10 md:py-12">
<div className="selection-hero-brand selection-hero-brand--left">
<div className="selection-hero-brand__title"></div>
<div className="selection-hero-brand__lockup">
<img
src={BRAND_ASSETS.taonierProductIp}
alt=""
aria-hidden="true"
draggable={false}
className="selection-hero-brand__image"
/>
<div className="selection-hero-brand__title"></div>
</div>
<div className="selection-hero-brand__subtitle"> RPG</div>
</div>
<p className="mt-8 text-[11px] font-semibold tracking-[0.32em] text-[var(--platform-cool-text)]">
@@ -0,0 +1,25 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import { expect, test } from 'vitest';
import { RpgEntryBrandLogo } from './RpgEntryBrandLogo';
test('陶泥儿品牌标识展示统一产品形象', () => {
const { container } = render(<RpgEntryBrandLogo />);
expect(
screen.getByRole('img', { name: '陶泥儿 GENARRATIVE' }),
).toBeTruthy();
expect(
container
.querySelector('.platform-brand-logo__image')
?.getAttribute('src'),
).toBe('/branding/taonier-product-ip.png');
});
test('装饰模式不暴露额外品牌朗读入口', () => {
render(<RpgEntryBrandLogo decorative />);
expect(screen.queryByRole('img')).toBeNull();
});
+14 -3
View File
@@ -1,3 +1,5 @@
import { BRAND_ASSETS } from '../../uiAssets';
export interface RpgEntryBrandLogoProps {
className?: string;
decorative?: boolean;
@@ -18,10 +20,19 @@ export function RpgEntryBrandLogo({
aria-hidden={decorative || undefined}
aria-label={decorative ? undefined : '陶泥儿 GENARRATIVE'}
>
<span className="platform-brand-logo__title">
<span className="platform-brand-logo__title-suffix"></span>
<img
src={BRAND_ASSETS.taonierProductIp}
alt=""
aria-hidden="true"
draggable={false}
className="platform-brand-logo__image"
/>
<span className="platform-brand-logo__copy">
<span className="platform-brand-logo__title">
<span className="platform-brand-logo__title-suffix"></span>
</span>
<span className="platform-brand-logo__subtitle">GENARRATIVE</span>
</span>
<span className="platform-brand-logo__subtitle">GENARRATIVE</span>
</span>
);
}
@@ -3834,6 +3834,11 @@ test('desktop recommend page reuses compact workbench chrome', () => {
expect(leftbar).toBeTruthy();
expect(topbar).toBeTruthy();
expect(leftbar?.querySelector('.creation-home-brand-lockup')).toBeTruthy();
expect(
leftbar
?.querySelector('.platform-brand-logo__image')
?.getAttribute('src'),
).toBe('/branding/taonier-product-ip.png');
expect(topbar?.querySelector('.creation-home-brand-lockup')).toBeNull();
expect(
within(leftbar as HTMLElement).getByRole('button', { name: '推荐' }),
@@ -331,7 +331,6 @@ const CREATION_HOME_NAV_ICON_SRC: Record<PlatformNavTab, string> = {
profile: '/creation-home/nav-profile.png',
};
const CREATION_HOME_TOPBAR_ASSETS = {
brandMascot: '/creation-home/brand-mascot.png',
search: '/creation-home/topbar-search.png',
wallet: '/creation-home/topbar-wallet.png',
} as const;
@@ -4926,13 +4925,6 @@ export function RpgEntryHomeView({
) : null;
const desktopBrandLockup: ReactNode = (
<span className="creation-home-brand-lockup shrink-0">
<img
src={CREATION_HOME_TOPBAR_ASSETS.brandMascot}
alt=""
aria-hidden="true"
draggable={false}
className="creation-home-brand-lockup__art"
/>
<RpgEntryBrandLogo className="shrink-0" decorative />
</span>
);
+42 -11
View File
@@ -888,6 +888,20 @@ html[data-mobile-keyboard-open='true'] #root {
text-align: left;
}
.selection-hero-brand__lockup {
display: inline-flex;
align-items: center;
gap: 0.82rem;
}
.selection-hero-brand__image {
width: clamp(3rem, 10vw, 4.4rem);
height: clamp(3rem, 10vw, 4.4rem);
flex: 0 0 auto;
object-fit: contain;
filter: drop-shadow(0 0.55rem 0.58rem rgba(0, 0, 0, 0.28));
}
.selection-hero-brand__title {
font-family: 'Noto Serif SC', 'Georgia', serif !important;
font-size: clamp(3rem, 10vw, 4.6rem);
@@ -1485,10 +1499,25 @@ html[data-mobile-keyboard-open='true'] #root {
.platform-brand-logo {
display: inline-flex;
flex: none;
align-items: center;
gap: 0.5rem;
line-height: 1;
}
.platform-brand-logo__image {
width: clamp(2.1rem, 6vw, 2.95rem);
height: clamp(2.1rem, 6vw, 2.95rem);
flex: 0 0 auto;
object-fit: contain;
filter: drop-shadow(0 0.24rem 0.28rem rgba(112, 62, 32, 0.18));
}
.platform-brand-logo__copy {
display: inline-flex;
min-width: 0;
flex-direction: column;
align-items: flex-start;
gap: 0.18rem;
line-height: 1;
}
.platform-brand-logo__title,
@@ -11700,7 +11729,6 @@ button.image-canvas-editor__reference-chip:disabled {
gap: 0.7rem;
}
.creation-home-brand-lockup__art,
.creation-home-nav-art,
.creation-home-topbar-art {
display: none;
@@ -11774,21 +11802,15 @@ button.image-canvas-editor__reference-chip:disabled {
.platform-desktop-shell--workbench .creation-home-brand-lockup {
align-self: flex-start;
gap: 0.42rem;
min-height: 3.28rem;
padding-left: 0.28rem;
}
.platform-desktop-shell--workbench .creation-home-brand-lockup__art {
display: block;
width: 2.58rem;
height: 2.58rem;
.platform-desktop-shell--workbench .platform-brand-logo__image {
width: 2.82rem;
height: 2.82rem;
flex: 0 0 auto;
border-radius: 999px;
object-fit: cover;
object-position: center;
filter: drop-shadow(0 0.36rem 0.34rem rgba(112, 62, 32, 0.18));
mix-blend-mode: multiply;
}
.platform-desktop-shell--workbench .platform-brand-logo__title {
@@ -14204,6 +14226,15 @@ button {
gap: 0.6rem;
}
.selection-hero-brand__lockup {
gap: 0.58rem;
}
.selection-hero-brand__image {
width: 2.85rem;
height: 2.85rem;
}
.selection-hero-brand__title {
letter-spacing: 0.16em;
}
+1
View File
@@ -53,6 +53,7 @@ export const CUSTOM_WORLD_THEME_ICONS = {
export const BRAND_ASSETS = {
kuranGamesLogo: '/branding/kuran-games-logo.svg',
taonierProductIp: '/branding/taonier-product-ip.png',
} as const;
export const UI_CHROME = {