Files
shanxia2.0/web-admin/src/utils/mp-webview.ts
T
2026-09-17 09:10:10 +08:00

142 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export const MP_WEBVIEW_PATH_PREFIX = '/m/'
export const MP_PLAN_LIST_PATH = '/m/pl/plan'
export const MINI_WORKBENCH_PATH = '/pages/workbench/workbench'
/** H5 iframe / uni 壳页约定:内嵌页请求返回工作台 */
export const MP_WEBVIEW_GO_WORKBENCH = 'MP_WEBVIEW_GO_WORKBENCH'
/** H5 iframe:内嵌页 Clipboard API 被拦截时,请壳页代为写入剪贴板 */
export const MP_WEBVIEW_COPY_TEXT = 'MP_WEBVIEW_COPY_TEXT'
const MP_RETURN_ORIGIN_KEY = 'mp_webview_return_origin'
/** MpWebviewShell 换票 / 就绪引导中:业务请求若 401 不得触发登出(与换票竞态) */
let mpWebviewAuthBootDepth = 0
export function beginMpWebviewAuthBoot(): void {
mpWebviewAuthBootDepth += 1
}
export function endMpWebviewAuthBoot(): void {
mpWebviewAuthBootDepth = Math.max(0, mpWebviewAuthBootDepth - 1)
}
export function isMpWebviewAuthBooting(): boolean {
return mpWebviewAuthBootDepth > 0
}
export function isMpWebviewPath(path: string): boolean {
return (path || '').startsWith(MP_WEBVIEW_PATH_PREFIX)
}
type WxMiniProgramApi = {
reLaunch?: (opt: { url: string; fail?: () => void }) => void
navigateBack?: (opt?: { delta?: number; fail?: () => void }) => void
getEnv?: (cb: (res: { miniprogram?: boolean }) => void) => void
}
export function getWxMiniProgram(): WxMiniProgramApi | null {
if (typeof window === 'undefined') return null
const wxObj = (window as unknown as { wx?: { miniProgram?: unknown } }).wx
const mini = wxObj?.miniProgram as WxMiniProgramApi | undefined
return mini || null
}
/** 真机 web-view 内才为 true;勿信任 jweixin 在普通浏览器里挂上的空壳 API */
export function isInMiniProgramWebView(): boolean {
if (typeof window === 'undefined') return false
const w = window as unknown as { __wxjs_environment?: string }
if (w.__wxjs_environment === 'miniprogram') return true
const ua = typeof navigator !== 'undefined' ? navigator.userAgent || '' : ''
return /miniProgram/i.test(ua) && /MicroMessenger/i.test(ua)
}
/** 记住小程序壳 origin,供 H5 iframe 顶栏返回工作台(跨域无法读 parent.location) */
export function rememberMpReturnOrigin(origin?: string): void {
if (typeof sessionStorage === 'undefined') return
const value = String(origin || '').trim().replace(/\/$/, '')
if (!value || !/^https?:\/\//i.test(value)) return
try {
sessionStorage.setItem(MP_RETURN_ORIGIN_KEY, value)
} catch {
/* ignore quota */
}
}
function readMpReturnOrigin(): string {
if (typeof sessionStorage === 'undefined') return ''
try {
return String(sessionStorage.getItem(MP_RETURN_ORIGIN_KEY) || '').trim()
} catch {
return ''
}
}
function postGoWorkbenchToHost(): boolean {
if (typeof window === 'undefined') return false
const payload = { type: MP_WEBVIEW_GO_WORKBENCH }
let posted = false
try {
if (window.parent && window.parent !== window) {
window.parent.postMessage(payload, '*')
posted = true
}
} catch {
/* ignore */
}
try {
if (window.top && window.top !== window && window.top !== window.parent) {
window.top.postMessage(payload, '*')
posted = true
}
} catch {
/* ignore */
}
return posted
}
function navigateTopToMiniWorkbench(): boolean {
const origin = readMpReturnOrigin()
if (!origin || typeof window === 'undefined') return false
try {
const target = `${origin}${MINI_WORKBENCH_PATH}`
if (window.top && window.top !== window) {
window.top.location.href = target
return true
}
window.location.href = target
return true
} catch {
return false
}
}
/** 列表顶栏「返回」:回到小程序工作台(web-view 多用 redirectTo 打开,须 reLaunch) */
export function goToMiniWorkbench(): void {
const mini = getWxMiniProgram()
if (isInMiniProgramWebView() && mini?.reLaunch) {
mini.reLaunch({ url: MINI_WORKBENCH_PATH })
return
}
// uni-app H5:web-view 多为 iframe,由壳页监听 postMessage;再兜底顶层跳转
postGoWorkbenchToHost()
navigateTopToMiniWorkbench()
}
export function redirectToMiniLogin(): void {
const mini = getWxMiniProgram()
if (isInMiniProgramWebView() && mini?.reLaunch) {
mini.reLaunch({ url: '/pages/login/login' })
return
}
postGoWorkbenchToHost()
// 非小程序:只展示空态,禁止跳管理端登录
}
export function stripMpTicketFromUrl(
_path: string,
query: Record<string, unknown>
): Record<string, unknown> {
const next = { ...query }
delete next.mpTicket
delete next.mpReturnOrigin
return next
}