/**
* URL Scheme 跳转组件
* 用于外部浏览器跳转小程序
*/
import React, { useState, useCallback } from 'react';
import {
Box,
Button,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
ModalCloseButton,
Text,
VStack,
useDisclosure,
useToast,
Icon,
} from '@chakra-ui/react';
import { ExternalLink, Copy, Check } from 'lucide-react';
import { isIOSDevice } from './hooks/useWechatEnvironment';
// 小程序 AppID
const MINIPROGRAM_APPID = 'wx0edeaab76d4fa414';
/**
* 生成明文 URL Scheme
* 格式:weixin://dl/business/?appid=APPID&path=PATH&query=QUERY
* 注意:path 不需要 URL encode,否则微信无法识别
*/
const generatePlainUrlScheme = (path, query) => {
let url = `weixin://dl/business/?appid=${MINIPROGRAM_APPID}&path=${path || ''}`;
if (query) {
url += `&query=${encodeURIComponent(query)}`;
}
return url;
};
/**
* URL Scheme 跳转组件
* @param {Object} props
* @param {string} [props.path] - 小程序页面路径
* @param {string} [props.query] - 页面参数
* @param {React.ReactNode} props.children - 按钮内容
* @param {Function} [props.onSuccess] - 跳转成功回调
* @param {Function} [props.onError] - 跳转失败回调
* @param {Object} [props.buttonProps] - 按钮属性
* @param {Object} [props.buttonStyle] - 按钮内联样式
*/
const UrlSchemeLauncher = ({
path = '',
query = '',
children,
onSuccess,
onError,
buttonProps = {},
buttonStyle = {},
}) => {
const [loading, setLoading] = useState(false);
const [openlink, setOpenlink] = useState(null);
const [copied, setCopied] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const toast = useToast();
const isIOS = isIOSDevice();
// 处理点击跳转
const handleLaunch = useCallback(async () => {
try {
setLoading(true);
// 生成明文 URL Scheme(不需要后端 API)
const scheme = generatePlainUrlScheme(path, query);
console.log('[UrlSchemeLauncher] 生成的 scheme:', scheme);
setOpenlink(scheme);
// 尝试直接跳转
window.location.href = scheme;
const success = true;
if (success) {
onSuccess?.();
// iOS 上可能会弹出确认框,显示引导弹窗
if (isIOS) {
setTimeout(() => {
onOpen();
}, 500);
}
} else {
// 跳转失败,显示引导弹窗
onOpen();
}
} catch (error) {
console.error('[UrlSchemeLauncher] error:', error);
toast({
title: '跳转失败',
description: error.message || '请稍后重试',
status: 'error',
duration: 3000,
});
onError?.(error);
} finally {
setLoading(false);
}
}, [path, query, onSuccess, onError, onOpen, toast, isIOS]);
// 复制链接
const handleCopy = useCallback(async () => {
if (!openlink) return;
try {
await navigator.clipboard.writeText(openlink);
setCopied(true);
toast({
title: '已复制',
description: '请在微信中打开',
status: 'success',
duration: 2000,
});
setTimeout(() => setCopied(false), 2000);
} catch (error) {
toast({
title: '复制失败',
description: '请手动复制',
status: 'error',
duration: 2000,
});
}
}, [openlink, toast]);
// 再次尝试跳转
const handleRetry = useCallback(() => {
if (openlink) {
window.location.href = openlink;
}
}, [openlink]);
return (
<>
}
style={buttonStyle}
{...buttonProps}
>
{children || '打开小程序'}
{/* 引导弹窗 */}
打开小程序
{isIOS
? '如果没有自动跳转,请点击下方按钮重试'
: '请在弹出的对话框中选择"打开微信"'}
提示:
1. 确保已安装微信
2. 点击"打开微信"按钮
3. 如果没有反应,请复制链接到微信打开
}
>
打开微信
}
>
{copied ? '已复制' : '复制链接'}
>
);
};
export default UrlSchemeLauncher;