/** * 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 ( <> {/* 引导弹窗 */} 打开小程序 {isIOS ? '如果没有自动跳转,请点击下方按钮重试' : '请在弹出的对话框中选择"打开微信"'} 提示: 1. 确保已安装微信 2. 点击"打开微信"按钮 3. 如果没有反应,请复制链接到微信打开 ); }; export default UrlSchemeLauncher;