Files
Genarrative/apps/mobile-shell/src/shell/loadFailure.ts
T
kdletters 6ba22b214c 收口移动壳加载失败兜底信息
移动壳加载失败兜底层只保留脱敏页面路径

移动壳加载失败详情改为稳定文案不直出系统描述

扩展移动壳配置门禁锁定加载失败脱敏边界

补充宿主壳方案和共享决策中的加载失败边界
2026-06-21 00:26:31 +08:00

119 lines
2.6 KiB
TypeScript

import { shouldOpenInMobileShellWebView } from './navigation';
export type MobileShellLoadFailureInput =
| {
type: 'native';
url: string;
code?: number | null;
description?: string | null;
}
| {
type: 'http';
url: string;
statusCode?: number | null;
description?: string | null;
}
| {
type: 'process';
url: string;
description?: string | null;
};
export type MobileShellLoadFailure = {
type: 'native' | 'http' | 'process';
url: string;
title: string;
detail: string;
retryLabel: string;
};
function sameDocumentUrl(
left: URL,
right: string | null | undefined,
allowedOrigin: string,
) {
if (!right) {
return true;
}
try {
const current = new URL(right, allowedOrigin);
return (
left.origin === current.origin &&
left.pathname === current.pathname &&
left.search === current.search
);
} catch {
return false;
}
}
function shouldShowLoadFailure(
rawUrl: string,
allowedOrigin: string,
currentPageUrl?: string | null,
) {
if (!shouldOpenInMobileShellWebView(rawUrl, allowedOrigin)) {
return false;
}
try {
const url = new URL(rawUrl, allowedOrigin);
return (
url.origin === allowedOrigin &&
url.pathname !== '/favicon.ico' &&
sameDocumentUrl(url, currentPageUrl, allowedOrigin)
);
} catch {
return false;
}
}
function sanitizeLoadFailureUrl(rawUrl: string, allowedOrigin: string) {
const url = new URL(rawUrl, allowedOrigin);
return `${url.origin}${url.pathname}`;
}
export function normalizeMobileShellLoadFailure(
input: MobileShellLoadFailureInput,
allowedOrigin: string,
currentPageUrl?: string | null,
): MobileShellLoadFailure | null {
if (!shouldShowLoadFailure(input.url, allowedOrigin, currentPageUrl)) {
return null;
}
const url = sanitizeLoadFailureUrl(input.url, allowedOrigin);
if (input.type === 'http') {
const statusCode =
Number.isInteger(input.statusCode) && input.statusCode
? input.statusCode
: null;
return {
type: 'http',
url,
title: statusCode ? `加载失败 ${statusCode}` : '加载失败',
detail: '服务器暂时没有返回可用页面',
retryLabel: '重试',
};
}
if (input.type === 'process') {
return {
type: 'process',
url,
title: '页面已停止',
detail: '当前页面连续恢复失败',
retryLabel: '重试',
};
}
return {
type: 'native',
url,
title: '网络不可用',
detail: '当前页面没有加载成功',
retryLabel: '重试',
};
}