修正画布路由与刷新加载

缺少项目 ID 的画布直达链接会回到创作页

路由级黑底加载只保留给移动端推荐页

补充画布直达和推荐加载开关回归测试
This commit is contained in:
2026-06-25 23:30:49 +08:00
parent 24f42061c5
commit 00b2720237
7 changed files with 176 additions and 14 deletions
+23
View File
@@ -5,9 +5,11 @@ import { describe, expect, it } from 'vitest';
import {
isAppHistoryState,
pushAppHistoryPath,
readEditorCanvasProjectIdFromLocationSearch,
replaceAppHistoryPath,
resolvePathForSelectionStage,
resolveSelectionStageFromPath,
shouldRedirectEditorCanvasWithoutProject,
} from './appPageRoutes';
describe('appPageRoutes', () => {
@@ -39,6 +41,27 @@ describe('appPageRoutes', () => {
expect(window.location.search).toBe('?projectid=project-from-route-test');
});
it('detects editor canvas routes that are missing project id', () => {
expect(readEditorCanvasProjectIdFromLocationSearch('?projectid=abc')).toBe(
'abc',
);
expect(shouldRedirectEditorCanvasWithoutProject('/editor/canvas', '')).toBe(
true,
);
expect(
shouldRedirectEditorCanvasWithoutProject('/EDITOR/CANVAS/', '?foo=bar'),
).toBe(true);
expect(
shouldRedirectEditorCanvasWithoutProject(
'/editor/canvas',
'?projectid=project-from-route-test',
),
).toBe(false);
expect(shouldRedirectEditorCanvasWithoutProject('/creation', '')).toBe(
false,
);
});
it('resolves the project route', () => {
expect(resolveSelectionStageFromPath('/project')).toBe('project');
expect(resolveSelectionStageFromPath('/PROJECT/')).toBe('project');
+16
View File
@@ -9,6 +9,7 @@ import {
export type RuntimePageRoute = 'rpg-character-select' | 'rpg-adventure';
export const PUBLIC_WORK_QUERY_PARAM = 'work';
export const EDITOR_CANVAS_PROJECT_ID_QUERY_PARAM = 'projectid';
const STAGE_ROUTE_ENTRIES = [
['platform', '/'],
@@ -122,6 +123,21 @@ export function readPublicWorkCodeFromLocationSearch(search: string) {
return params.get(PUBLIC_WORK_QUERY_PARAM)?.trim() || null;
}
export function readEditorCanvasProjectIdFromLocationSearch(search: string) {
const params = new URLSearchParams(search);
return params.get(EDITOR_CANVAS_PROJECT_ID_QUERY_PARAM)?.trim() || null;
}
export function shouldRedirectEditorCanvasWithoutProject(
pathname: string,
search: string,
) {
return (
normalizeAppPath(pathname) === APP_STAGE_ROUTES['image-editor'] &&
!readEditorCanvasProjectIdFromLocationSearch(search)
);
}
export function buildPublicWorkDetailPath(publicWorkCode: string) {
return buildPublicWorkStagePath('work-detail', publicWorkCode);
}
+13 -1
View File
@@ -1,6 +1,6 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { matchAppRoute } from './appRoutes';
import { matchAppRoute, shouldUseRecommendationRouteLoading } from './appRoutes';
afterEach(() => {
vi.unstubAllEnvs();
@@ -89,3 +89,15 @@ describe('matchAppRoute', () => {
});
});
});
describe('shouldUseRecommendationRouteLoading', () => {
it('only enables the dark recommendation loading screen for mobile root route', () => {
expect(shouldUseRecommendationRouteLoading('/', false)).toBe(true);
expect(shouldUseRecommendationRouteLoading('/', true)).toBe(false);
expect(shouldUseRecommendationRouteLoading('/creation', false)).toBe(false);
expect(shouldUseRecommendationRouteLoading('/project', false)).toBe(false);
expect(shouldUseRecommendationRouteLoading('/editor/canvas', false)).toBe(
false,
);
});
});
+7
View File
@@ -54,6 +54,13 @@ function normalizeRoutePath(pathname: string) {
return normalizeAppPath(pathname);
}
export function shouldUseRecommendationRouteLoading(
pathname: string,
isDesktopLayout: boolean,
) {
return normalizeRoutePath(pathname) === '/' && !isDesktopLayout;
}
export function matchAppRoute(pathname: string): AppRouteMatch {
const normalizedPath = normalizeRoutePath(pathname);