143 lines
4.0 KiB
JavaScript
143 lines
4.0 KiB
JavaScript
/**
|
||
* 微信环境检测 Hook
|
||
* 用于判断当前运行环境,选择合适的小程序跳转方式
|
||
*/
|
||
import { useMemo } from 'react';
|
||
|
||
/**
|
||
* 跳转方式枚举
|
||
*/
|
||
export const LAUNCH_METHOD = {
|
||
OPEN_TAG: 'openTag', // 微信内使用开放标签
|
||
URL_SCHEME: 'urlScheme', // 外部浏览器使用 URL Scheme
|
||
QR_CODE: 'qrCode', // PC 端显示小程序码
|
||
};
|
||
|
||
/**
|
||
* 检测是否在微信浏览器内
|
||
*/
|
||
export const isWeChatBrowser = () => {
|
||
if (typeof window === 'undefined') return false;
|
||
const ua = navigator.userAgent.toLowerCase();
|
||
return ua.includes('micromessenger');
|
||
};
|
||
|
||
/**
|
||
* 检测是否为移动端设备
|
||
* 使用多种检测方式,确保 Safari 兼容性
|
||
*/
|
||
export const isMobileDevice = () => {
|
||
if (typeof window === 'undefined') return false;
|
||
|
||
const ua = navigator.userAgent;
|
||
|
||
// 方式1:User Agent 检测
|
||
const uaCheck = /iPhone|iPad|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i.test(ua);
|
||
|
||
// 方式2:触摸屏检测(Safari 兼容)
|
||
const touchCheck = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
||
|
||
// 方式3:屏幕宽度检测(作为备用)
|
||
const screenCheck = window.innerWidth <= 768;
|
||
|
||
// 方式4:Safari 特定检测(iOS Safari 不会在 UA 中包含 "Mobile" 但会有 "Safari")
|
||
const isSafariMobile = /Safari/i.test(ua) && /Apple/i.test(navigator.vendor) && touchCheck;
|
||
|
||
const result = uaCheck || (touchCheck && screenCheck) || isSafariMobile;
|
||
|
||
// 调试日志(仅在开发环境)
|
||
if (process.env.NODE_ENV === 'development') {
|
||
console.log('[isMobileDevice] UA:', ua);
|
||
console.log('[isMobileDevice] uaCheck:', uaCheck, 'touchCheck:', touchCheck, 'screenCheck:', screenCheck, 'isSafariMobile:', isSafariMobile);
|
||
console.log('[isMobileDevice] result:', result);
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
/**
|
||
* 检测是否为 iOS 设备
|
||
*/
|
||
export const isIOSDevice = () => {
|
||
if (typeof window === 'undefined') return false;
|
||
const ua = navigator.userAgent;
|
||
return /iPhone|iPad|iPod/i.test(ua);
|
||
};
|
||
|
||
/**
|
||
* 检测是否为 Android 设备
|
||
*/
|
||
export const isAndroidDevice = () => {
|
||
if (typeof window === 'undefined') return false;
|
||
const ua = navigator.userAgent;
|
||
return /Android/i.test(ua);
|
||
};
|
||
|
||
/**
|
||
* 获取微信版本号
|
||
* @returns {string|null} 版本号字符串,如 "7.0.12"
|
||
*/
|
||
export const getWeChatVersion = () => {
|
||
if (typeof window === 'undefined') return null;
|
||
const ua = navigator.userAgent.toLowerCase();
|
||
const match = ua.match(/micromessenger\/(\d+\.\d+\.\d+)/i);
|
||
return match ? match[1] : null;
|
||
};
|
||
|
||
/**
|
||
* 检测微信版本是否支持开放标签
|
||
* 开放标签需要微信 7.0.12 及以上版本
|
||
*/
|
||
export const isOpenTagSupported = () => {
|
||
const version = getWeChatVersion();
|
||
if (!version) return false;
|
||
|
||
const [major, minor, patch] = version.split('.').map(Number);
|
||
// 7.0.12 及以上支持
|
||
if (major > 7) return true;
|
||
if (major === 7) {
|
||
if (minor > 0) return true;
|
||
if (minor === 0 && patch >= 12) return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* 微信环境检测 Hook
|
||
* @returns {Object} 环境信息对象
|
||
*/
|
||
export const useWechatEnvironment = () => {
|
||
const environment = useMemo(() => {
|
||
const isWechat = isWeChatBrowser();
|
||
const isMobile = isMobileDevice();
|
||
const isIOS = isIOSDevice();
|
||
const isAndroid = isAndroidDevice();
|
||
const wechatVersion = getWeChatVersion();
|
||
const openTagSupported = isOpenTagSupported();
|
||
|
||
// 确定跳转方式
|
||
let launchMethod;
|
||
if (isWechat && openTagSupported) {
|
||
launchMethod = LAUNCH_METHOD.OPEN_TAG;
|
||
} else if (isMobile) {
|
||
launchMethod = LAUNCH_METHOD.URL_SCHEME;
|
||
} else {
|
||
launchMethod = LAUNCH_METHOD.QR_CODE;
|
||
}
|
||
|
||
return {
|
||
isWechat, // 是否在微信内
|
||
isMobile, // 是否移动端
|
||
isIOS, // 是否 iOS
|
||
isAndroid, // 是否 Android
|
||
wechatVersion, // 微信版本
|
||
openTagSupported, // 是否支持开放标签
|
||
launchMethod, // 推荐的跳转方式
|
||
};
|
||
}, []);
|
||
|
||
return environment;
|
||
};
|
||
|
||
export default useWechatEnvironment;
|