press-plus
Version:
215 lines (174 loc) • 6.08 kB
text/typescript
import { consoleInfo } from 't-comm/es/log/log';
/**
* 获取相对路径,即项目内 vue-router 可以识别的路径
*
* @example
* ```ts
* const corePath = '/pvpesport.next.user'
*
* getRelativePath(corePath, '/pvpesport.next.user/views/index/index-home');
*
* // /views/index/index-home
* ```
*/
function getRelativePath(corePath: string, target = '') {
const innerTarget = target ? (new URL(target)).pathname : location.pathname ;
let innerPath = corePath;
if (!corePath.startsWith('/')) {
innerPath = `/${innerPath}`;
}
return innerTarget.replace(new RegExp(`^${innerPath}`), '');
}
/**
* 获取 url 前缀
* @example
* ```ts
* const corePath = '/pvpesport.next.user'
*
* getPrefixPath(corePath);
*
* // https://h5.nes.smoba.qq.com/pvpesport.next.user/view
* ```
*/
function getPrefixPath(corePath: string) {
let innerPath = corePath;
if (!innerPath.startsWith('/')) {
innerPath = `/${innerPath}`;
}
if (!location.pathname.startsWith(innerPath)) {
return location.origin;
}
return location.origin + innerPath;
}
function pureInitEnv() {
const ua = navigator.userAgent.toLowerCase();
const isPc = !ua.match(/(phone|pad|pod|iphone|ipod|ios|ipad|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|webos|symbian|windows phone)/i);
const isPCWeixin = ua.includes('windowswechat')
|| ua.includes('macwechat');
return {
isPc,
isPCWeixin,
};
}
const checkIsCrossOrigin = () => {
let result = false;
try {
const { href } = window.parent.location;
console.log('[checkIsCrossOrigin] href', href);
} catch (err) {
result = true;
}
return result;
};
export function redirectToWebContainerInPC({
pathWhiteList,
disableWebContainerList,
corePath,
shouldRedirect,
router,
webContainerRoute = '/views/web-container/index',
log: shouldLog = false,
tag = '',
extraCheckRedirectFunc,
extraCheckNoRedirectFunc,
}: {
pathWhiteList?: string[],
disableWebContainerList?: string[],
corePath: string,
shouldRedirect?: boolean | Function,
router?: any
webContainerRoute?: string;
log?: boolean;
tag?: string;
extraCheckRedirectFunc?: Function;
extraCheckNoRedirectFunc?: Function;
}) {
if (checkIsCrossOrigin()) {
return;
}
const isWhite = !!pathWhiteList?.find(item => window.location.href?.includes(item));
// const isDebug = process.env.NODE_ENV.startsWith('development');
const env = pureInitEnv();
let temp = true;
if (typeof shouldRedirect === 'undefined') {
temp = true;
} else if (typeof shouldRedirect === 'function') {
temp = shouldRedirect();
} else if (typeof shouldRedirect === 'boolean') {
temp = shouldRedirect;
}
consoleInfo(shouldLog, '[redirectToWebContainerInPC]', window.self === window.parent ? '[主应用]' : '[子应用]', tag || '');
const realShouldRedirect = temp
&& env.isPc
&& !env.isPCWeixin
&& !isWhite
&& window.self === window.parent
&& !window.location.href.includes(webContainerRoute)
&& (!extraCheckRedirectFunc || (typeof extraCheckRedirectFunc === 'function' && extraCheckRedirectFunc()))
&& !window.location.href.includes('noredirect=true');
consoleInfo(shouldLog, '[isWhite]', isWhite);
consoleInfo(shouldLog, '[realShouldRedirect]', realShouldRedirect);
const shouldHideWebContainer = (
!!disableWebContainerList?.find(item => window.location.href.includes(item))
|| (!env.isPc || env.isPCWeixin)
|| (typeof extraCheckNoRedirectFunc === 'function' && extraCheckNoRedirectFunc())
)
&& window.location.href.includes('views/web-container/index?path=');
consoleInfo(shouldLog, '[shouldHideWebContainer]', shouldHideWebContainer);
const newParentUrl = window.parent?.location?.href?.replace(/path=[^&?]+/, `path=${encodeURIComponent(window.location.href)}`);
const shouldReplaceParentState = window.parent
&& window.self !== window.parent
&& newParentUrl !== window.parent.location.href;
consoleInfo(shouldLog, '[shouldReplaceParentState]', shouldReplaceParentState);
if (shouldHideWebContainer) {
// 主应用隐藏 container
const path = /[?|&]path=(.*?)$|&/;
const match = window.location.href.match(path);
if (match?.[1]) {
const target = decodeURIComponent(match[1]);
const relativePath = getRelativePath(corePath, target);
consoleInfo(shouldLog, '[hideWebContainer target]', target);
const list = target.split('?');
const queryObj = (list[1] || '').split('&').reduce((acc: Record<string, string>, str) => {
const innerList = str.split('=');
acc[innerList[0]] = innerList[1];
return acc;
}, {});
if (router) {
consoleInfo(shouldLog, '[router.replace] path: ', relativePath);
consoleInfo(shouldLog, '[router.replace] query:', queryObj);
router.replace({
path: relativePath,
query: queryObj,
});
} else {
window.location.href = target;
}
}
} else if (realShouldRedirect) {
// 主应用,跳转 container
const prefixPath = getPrefixPath(corePath);
const pathQuery = encodeURIComponent(window.location.href);
const postfix = `${webContainerRoute}?path=${pathQuery}`;
const target = `${prefixPath}${postfix}`;
consoleInfo(shouldLog, '[redirect target]', target);
if (router) {
consoleInfo(shouldLog, '[router.replace] path: ', webContainerRoute);
consoleInfo(shouldLog, '[router.replace] query: ', pathQuery);
router.replace({
path: webContainerRoute,
query: {
path: pathQuery,
},
});
} else {
window.location.href = target;
}
} else if (shouldReplaceParentState) {
// 子应用,操作主应用 history
consoleInfo(shouldLog, '[newCurUrl]', window.location.href);
consoleInfo(shouldLog, '[newParentUrl]', newParentUrl);
consoleInfo(shouldLog, '[oldParentUrl]', window.parent.location.href);
window.parent.history.replaceState('', '', newParentUrl);
}
}