移动端欢迎界面和说明

新增移动端首页欢迎弹窗,提示移动端仅支持作品展示。

替换欢迎弹窗 IP 图标并调整正文换行与标点。

关闭弹窗后本次页面生命周期内切换底部页签不再重复弹出,刷新后重新显示。

补充弹窗展示规则测试并同步玩法入口文档。
This commit is contained in:
2026-06-23 15:02:26 +08:00
parent 47bdc73b93
commit c8aa1775f3
7 changed files with 286 additions and 1 deletions
@@ -129,6 +129,7 @@ Tab
- 桌面端从 `/creation` 切换到 `/project` 后,“项目”页签进入选中态,“创作”页签必须恢复为普通默认态,不保留创作主页的主按钮强调表现。
- `/project` 项目页头部必须提供 `返回主站` 按钮,点击后切回平台首页 `/`,行为与桌面侧栏切回推荐页保持一致。
- 移动端导航列表不展示“创作”和“项目”。
- 移动端首次进入或刷新 `/` 平台首页时显示欢迎弹窗,文案提示移动端仅支持作品展示,体验创作工具请使用电脑端访问;点击 `好` 关闭后,本次页面生命周期内切换下方页签再回到首页不再弹出。
- 移动端直接访问 `/creation` 时显示桌面端打开引导,不加载创作工具主页;`/creation/<play>` 继续直达对应玩法工作台。`/project` 暂不新增移动端拦截。
## 实施拆分
@@ -195,6 +196,7 @@ git diff --check
- 桌面导航显示“项目”,不显示“草稿”。
- `/project` 头部点击“返回主站”回到 `/`,并退出项目页主内容。
- 移动视口底部不显示“创作”和“项目”。
- 移动端进入 `/` 首页时显示 `欢迎` 弹窗,正文包含移动端仅支持作品展示和电脑端访问提示,按钮为 `好`
- 移动端直达 `/creation` 显示“请在桌面端打开创作主页”,点击“返回首页”回到 `/`
- “我的”页没有项目快捷入口。
- 陶泥儿精选素材瀑布流不出现账号级非项目素材、公开作品补充、上传素材、mock 素材、假作者或假泥点成本。
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

@@ -536,6 +536,10 @@ import {
PlatformEntryHomeView,
type PlatformHomeTab,
} from './PlatformEntryHomeView';
import {
PlatformMobileHomeWelcomeDialog,
shouldOpenMobileHomeWelcomeDialog,
} from './PlatformMobileHomeWelcomeDialog';
import { PlatformProfileReferralModal } from './PlatformProfileReferralModal';
import { usePlatformDesktopLayout } from './platformEntryResponsive';
import {
@@ -1692,6 +1696,8 @@ export function PlatformEntryFlowShellImpl({
: 'platform-theme--light';
const isDesktopLayout = usePlatformDesktopLayout();
const [showCreationTypeModal, setShowCreationTypeModal] = useState(false);
const [isMobileHomeWelcomeDismissed, setIsMobileHomeWelcomeDismissed] =
useState(false);
const [isCreationCommunityOpen, setIsCreationCommunityOpen] =
useState(false);
const [draftGenerationPointNotice, setDraftGenerationPointNotice] =
@@ -15319,6 +15325,16 @@ export function PlatformEntryFlowShellImpl({
},
[platformBootstrap, selectionStage, setSelectionStage],
);
const shouldOpenMobileHomeWelcome = shouldOpenMobileHomeWelcomeDialog({
isDesktopLayout,
selectionStage,
platformTab: platformBootstrap.platformTab,
pathname:
typeof window === 'undefined'
? resolvePathForSelectionStage(selectionStage)
: window.location.pathname,
isDismissed: isMobileHomeWelcomeDismissed,
});
const platformHomeView = (
<PlatformEntryHomeView
activeTab={
@@ -17887,6 +17903,11 @@ export function PlatformEntryFlowShellImpl({
payload={publishSharePayload}
onClose={() => setPublishSharePayload(null)}
/>
<PlatformMobileHomeWelcomeDialog
open={shouldOpenMobileHomeWelcome}
platformThemeClass={platformThemeClass}
onClose={() => setIsMobileHomeWelcomeDismissed(true)}
/>
<PlatformErrorDialog
error={activePlatformErrorDialog}
onClose={closePlatformErrorDialog}
@@ -0,0 +1,115 @@
/* @vitest-environment jsdom */
import { fireEvent, render, screen } from '@testing-library/react';
import { expect, test, vi } from 'vitest';
import {
PlatformMobileHomeWelcomeDialog,
shouldOpenMobileHomeWelcomeDialog,
shouldShowMobileHomeWelcomeDialog,
} from './PlatformMobileHomeWelcomeDialog';
test('shows mobile home welcome only for the mobile platform home route', () => {
expect(
shouldShowMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'home',
pathname: '/',
}),
).toBe(true);
expect(
shouldShowMobileHomeWelcomeDialog({
isDesktopLayout: true,
selectionStage: 'platform',
platformTab: 'home',
pathname: '/',
}),
).toBe(false);
expect(
shouldShowMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'category',
pathname: '/',
}),
).toBe(false);
expect(
shouldShowMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'creation-home',
platformTab: 'home',
pathname: '/creation',
}),
).toBe(false);
});
test('keeps mobile home welcome dismissed across bottom tab switches until refresh', () => {
expect(
shouldOpenMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'home',
pathname: '/',
isDismissed: false,
}),
).toBe(true);
expect(
shouldOpenMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'category',
pathname: '/',
isDismissed: true,
}),
).toBe(false);
expect(
shouldOpenMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'home',
pathname: '/',
isDismissed: true,
}),
).toBe(false);
expect(
shouldOpenMobileHomeWelcomeDialog({
isDesktopLayout: false,
selectionStage: 'platform',
platformTab: 'home',
pathname: '/',
isDismissed: false,
}),
).toBe(true);
});
test('renders mobile home welcome copy and closes with the acknowledge button', () => {
const onClose = vi.fn();
const { container } = render(
<PlatformMobileHomeWelcomeDialog
open
platformThemeClass="platform-theme--light"
onClose={onClose}
/>,
);
expect(screen.getByRole('dialog', { name: '欢迎' })).toBeTruthy();
expect(screen.getByRole('heading', { name: '欢迎' })).toBeTruthy();
const copy = document.querySelector(
'.platform-mobile-home-welcome-dialog__copy',
);
expect(copy?.textContent).toBe(
'尼嚎,新陶泥er!移动端仅支持作品展示体验创作工具请使用电脑端访问该地址',
);
expect(copy?.querySelectorAll('br')).toHaveLength(2);
expect(
document
.querySelector('.platform-mobile-home-welcome-dialog__icon')
?.getAttribute('src'),
).toBe('/branding/mobile-home-welcome-taonier-ip.png');
fireEvent.click(screen.getByRole('button', { name: '好' }));
expect(onClose).toHaveBeenCalledTimes(1);
});
@@ -0,0 +1,90 @@
import { normalizeAppPath } from '../../routing/appPageRoutes';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { UnifiedModal } from '../common/UnifiedModal';
import type { SelectionStage } from './platformEntryTypes';
type MobileHomeWelcomeDecisionInput = {
isDesktopLayout: boolean;
selectionStage: SelectionStage;
platformTab: string;
pathname: string;
};
type MobileHomeWelcomeOpenInput = MobileHomeWelcomeDecisionInput & {
isDismissed: boolean;
};
type PlatformMobileHomeWelcomeDialogProps = {
open: boolean;
platformThemeClass: string;
onClose: () => void;
};
export function shouldShowMobileHomeWelcomeDialog({
isDesktopLayout,
selectionStage,
platformTab,
pathname,
}: MobileHomeWelcomeDecisionInput) {
return (
!isDesktopLayout &&
selectionStage === 'platform' &&
platformTab === 'home' &&
normalizeAppPath(pathname) === '/'
);
}
export function shouldOpenMobileHomeWelcomeDialog({
isDismissed,
...decisionInput
}: MobileHomeWelcomeOpenInput) {
return !isDismissed && shouldShowMobileHomeWelcomeDialog(decisionInput);
}
export function PlatformMobileHomeWelcomeDialog({
open,
platformThemeClass,
onClose,
}: PlatformMobileHomeWelcomeDialogProps) {
return (
<UnifiedModal
open={open}
title="欢迎"
onClose={onClose}
showHeader={false}
showCloseButton={false}
closeOnBackdrop={false}
closeOnEscape={false}
size="sm"
overlayClassName={`platform-theme ${platformThemeClass} platform-mobile-home-welcome-overlay !items-center !p-4`}
panelClassName="platform-remap-surface platform-mobile-home-welcome-dialog"
bodyClassName="platform-mobile-home-welcome-dialog__body"
footerClassName="platform-mobile-home-welcome-dialog__footer"
footer={
<PlatformActionButton
onClick={onClose}
size="md"
shape="pill"
fullWidth
className="min-h-11"
>
</PlatformActionButton>
}
>
<img
src="/branding/mobile-home-welcome-taonier-ip.png"
alt=""
className="platform-mobile-home-welcome-dialog__icon"
/>
<h1 className="platform-mobile-home-welcome-dialog__title"></h1>
<p className="platform-mobile-home-welcome-dialog__copy">
er
<br />
<br />
使访
</p>
</UnifiedModal>
);
}
+57
View File
@@ -8822,6 +8822,63 @@ button.image-canvas-editor__reference-chip:disabled {
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.16);
}
.platform-mobile-home-welcome-overlay {
background:
radial-gradient(circle at 50% 18%, rgba(255, 254, 252, 0.54), transparent 32%),
rgba(61, 31, 16, 0.24);
}
.platform-mobile-home-welcome-dialog {
width: min(100%, 21rem);
overflow: hidden;
border-radius: 1.65rem;
border: 1px solid rgba(255, 255, 255, 0.68);
background:
radial-gradient(circle at 18% 0%, rgba(240, 203, 169, 0.28), transparent 38%),
var(--platform-modal-fill);
box-shadow:
0 24px 58px rgba(112, 57, 30, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.82);
}
.platform-mobile-home-welcome-dialog__body {
display: flex;
flex-direction: column;
align-items: center;
padding: 1.5rem 1.35rem 0.85rem;
text-align: center;
}
.platform-mobile-home-welcome-dialog__footer {
justify-content: center;
border-top: 0;
padding: 0.35rem 1.35rem 1.35rem;
}
.platform-mobile-home-welcome-dialog__icon {
display: block;
width: 5.65rem;
height: 5.65rem;
object-fit: contain;
filter: drop-shadow(0 14px 20px rgba(182, 98, 63, 0.16));
}
.platform-mobile-home-welcome-dialog__title {
margin-top: 0.85rem;
color: var(--platform-text-strong);
font-size: 1.32rem;
font-weight: 900;
line-height: 1.18;
}
.platform-mobile-home-welcome-dialog__copy {
margin-top: 0.65rem;
color: var(--platform-text-base);
font-size: 0.9rem;
font-weight: 700;
line-height: 1.75;
}
.platform-modal-backdrop {
background: var(--platform-overlay-fill);
color: var(--platform-text-strong);