完善官网 SEO 地基与精确路由

补充 robots、sitemap、SEO 元信息、结构化数据与首页语义内容
统一三套 Nginx 与 Pingora 的 62 条 SPA 路由和真实 404 行为
新增路由一致性检查、网关测试并同步技术文档与项目记忆
This commit is contained in:
2026-07-10 12:14:44 +08:00
parent e464e62697
commit 09fec601b1
26 changed files with 681 additions and 27 deletions
@@ -158,11 +158,11 @@ describe('CreationLandingView', () => {
expect(screen.getByRole('main', { name: '陶泥儿创作主页' })).toBeTruthy();
expect(
screen.getByRole('heading', {
name: '陶泥儿 - 开启全民精品游戏创作',
name: '游戏美术AI工作台,让个人创作者更快做出角色、场景与宣发素材',
}),
).toBeTruthy();
expect(
screen.getByText('登录即送100泥点,可以免费制作50个素材'),
screen.getByText(/陶泥儿 Genarrative 以美术 Agent 与无限画布/u),
).toBeTruthy();
expect(screen.getByRole('heading', { name: '创作工具' })).toBeTruthy();
expect(screen.getByText('游戏视觉规范')).toBeTruthy();
@@ -859,8 +859,13 @@ export function CreationLandingView({
<section className="creation-landing__hero">
<div className="creation-landing__hero-copy">
<span className="creation-landing__eyebrow">陶泥儿创作工具</span>
<h1>陶泥儿 - 开启全民精品游戏创作</h1>
<p>登录即送100泥点,可以免费制作50个素材</p>
<h1>
游戏美术AI工作台,让个人创作者更快做出角色、场景与宣发素材
</h1>
<p>
陶泥儿 Genarrative 以美术 Agent
与无限画布帮助个人创作者准备角色、场景与宣发素材;登录即送100泥点,可以免费制作50个素材。
</p>
<div className="creation-landing__hero-actions">
<PlatformActionButton
size="md"
@@ -95,7 +95,10 @@ test('renders mobile home welcome copy and closes with the acknowledge button',
);
expect(screen.getByRole('dialog', { name: '欢迎' })).toBeTruthy();
expect(screen.getByRole('heading', { name: '欢迎' })).toBeTruthy();
expect(
screen.getByRole('heading', { level: 2, name: '欢迎' }),
).toBeTruthy();
expect(screen.queryByRole('heading', { level: 1 })).toBeNull();
const copy = document.querySelector(
'.platform-mobile-home-welcome-dialog__copy',
);
@@ -68,7 +68,7 @@ export function PlatformMobileHomeWelcomeDialog({
alt=""
className="platform-mobile-home-welcome-dialog__icon"
/>
<h1 className="platform-mobile-home-welcome-dialog__title">欢迎</h1>
<h2 className="platform-mobile-home-welcome-dialog__title">欢迎</h2>
<p className="platform-mobile-home-welcome-dialog__copy">
尼嚎,新陶泥er!
<br />
@@ -378,6 +378,9 @@ const {
};
});
const HOME_SEO_HEADING =
'游戏美术AI工作台,让个人创作者更快做出角色、场景与宣发素材';
const {
mockGetPublicAuthUserByCode,
mockGetPublicAuthUserById,
@@ -4280,6 +4283,39 @@ test('desktop home shows empty states when public shelves are unavailable', () =
expect(screen.getByText('暂时还没有推荐作品。')).toBeTruthy();
});
test('desktop home exposes one product h1 and section h2 headings', () => {
renderLoggedOutHomeView(vi.fn(), {}, 'home', true);
const productHeading = screen.getByRole('heading', {
level: 1,
name: HOME_SEO_HEADING,
});
expect(screen.getAllByRole('heading', { level: 1 })).toHaveLength(1);
expect(productHeading.closest('button')).toBeNull();
expect(
screen.getByRole('heading', { level: 2, name: '今日游戏' }),
).toBeTruthy();
expect(
screen.getByRole('heading', { level: 2, name: '推荐' }),
).toBeTruthy();
expect(
screen.getByRole('heading', { level: 2, name: '作品分类' }),
).toBeTruthy();
});
test('mobile shell exposes one product h1 outside interactive content', () => {
renderLoggedOutHomeView(vi.fn(), {}, 'profile');
const productHeading = screen.getByRole('heading', {
level: 1,
name: HOME_SEO_HEADING,
});
expect(screen.getAllByRole('heading', { level: 1 })).toHaveLength(1);
expect(productHeading.closest('button')).toBeNull();
});
test('logged in create tab shows real wallet balance beside the brand', () => {
mockNarrowMobileLayout();
+20 -2
View File
@@ -1020,13 +1020,27 @@ function SectionHeader({ title, detail }: { title: string; detail: string }) {
<div className="text-[10px] font-semibold tracking-[0.26em] text-[var(--platform-text-soft)]">
{detail}
</div>
<div className="mt-1 text-base font-semibold text-[var(--platform-text-strong)]">
<h2 className="mt-1 text-base font-semibold text-[var(--platform-text-strong)]">
{title}
</div>
</h2>
</div>
);
}
function HomeSeoIntro() {
return (
<header className="mb-2 min-w-0 shrink-0 px-1">
<h1 className="text-sm font-semibold leading-5 text-[var(--platform-text-strong)]">
游戏美术AI工作台,让个人创作者更快做出角色、场景与宣发素材
</h1>
<p className="mt-0.5 text-xs leading-5 text-[var(--platform-text-soft)]">
在陶泥儿 Genarrative,用美术 Agent
快速生成与迭代素材,再在无限画布中整理角色、场景和宣发灵感。
</p>
</header>
);
}
function PublicCodeSearchBar({
value,
onChange,
@@ -4578,6 +4592,8 @@ export function RpgEntryHomeView({
const desktopHomeContent: ReactNode = (
<div className={DESKTOP_PAGE_STAGE_CLASS}>
<HomeSeoIntro />
{platformError ? (
<PlatformStatusMessage
tone="error"
@@ -5160,6 +5176,8 @@ export function RpgEntryHomeView({
</div>
) : null}
<HomeSeoIntro />
<div className="platform-tab-panel-stack min-w-0 flex-1">
{tabPanels}
</div>