diff --git a/src/components/Auth/WechatRegister.js b/src/components/Auth/WechatRegister.js index 67f81447..d0049911 100644 --- a/src/components/Auth/WechatRegister.js +++ b/src/components/Auth/WechatRegister.js @@ -15,6 +15,8 @@ import { FaQrcode } from "react-icons/fa"; import { FiAlertCircle } from "react-icons/fi"; import { useNavigate } from "react-router-dom"; import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/authService"; +import { useAuthModal } from "../../contexts/AuthModalContext"; +import { useAuth } from "../../contexts/AuthContext"; import { logger } from "../../utils/logger"; // 配置常量 @@ -45,6 +47,10 @@ const getStatusText = (status) => { }; export default function WechatRegister() { + // 获取关闭弹窗方法 + const { closeModal } = useAuthModal(); + const { refreshSession } = useAuth(); + // 状态管理 const [wechatAuthUrl, setWechatAuthUrl] = useState(""); const [wechatSessionId, setWechatSessionId] = useState(""); @@ -58,6 +64,7 @@ export default function WechatRegister() { const timeoutRef = useRef(null); const isMountedRef = useRef(true); // 追踪组件挂载状态 const containerRef = useRef(null); // 容器DOM引用 + const sessionIdRef = useRef(null); // 存储最新的 sessionId,避免闭包陷阱 const navigate = useNavigate(); const toast = useToast(); @@ -90,6 +97,7 @@ export default function WechatRegister() { /** * 清理所有定时器 + * 注意:不清理 sessionIdRef,因为 startPolling 时也会调用此函数 */ const clearTimers = useCallback(() => { if (pollIntervalRef.current) { @@ -124,14 +132,14 @@ export default function WechatRegister() { } showSuccess( - status === WECHAT_STATUS.LOGIN_SUCCESS ? "登录成功" : "注册成功", - "正在跳转..." + status === WECHAT_STATUS.LOGIN_SUCCESS ? "登录成功" : "欢迎回来!" ); - // 延迟跳转,让用户看到成功提示 - setTimeout(() => { - navigate("/home"); - }, 1000); + // 刷新 AuthContext 状态 + await refreshSession(); + + // 关闭认证弹窗,留在当前页面 + closeModal(); } else { throw new Error(response?.error || '登录失败'); } @@ -139,17 +147,27 @@ export default function WechatRegister() { logger.error('WechatRegister', 'handleLoginSuccess', error, { sessionId }); showError("登录失败", error.message || "请重试"); } - }, [navigate, showSuccess, showError]); + }, [showSuccess, showError, closeModal, refreshSession]); /** * 检查微信扫码状态 + * 使用 sessionIdRef.current 避免闭包陷阱 */ const checkWechatStatus = useCallback(async () => { - // 检查组件是否已卸载 - if (!isMountedRef.current || !wechatSessionId) return; + // 检查组件是否已卸载,使用 ref 获取最新的 sessionId + if (!isMountedRef.current || !sessionIdRef.current) { + logger.debug('WechatRegister', 'checkWechatStatus 跳过', { + isMounted: isMountedRef.current, + hasSessionId: !!sessionIdRef.current + }); + return; + } + + const currentSessionId = sessionIdRef.current; + logger.debug('WechatRegister', '检查微信状态', { sessionId: currentSessionId }); try { - const response = await authService.checkWechatStatus(wechatSessionId); + const response = await authService.checkWechatStatus(currentSessionId); // 安全检查:确保 response 存在且包含 status if (!response || typeof response.status === 'undefined') { @@ -158,6 +176,7 @@ export default function WechatRegister() { } const { status } = response; + logger.debug('WechatRegister', '微信状态', { status }); // 组件卸载后不再更新状态 if (!isMountedRef.current) return; @@ -167,23 +186,14 @@ export default function WechatRegister() { // 处理成功状态 if (status === WECHAT_STATUS.LOGIN_SUCCESS || status === WECHAT_STATUS.REGISTER_SUCCESS) { clearTimers(); // 停止轮询 + sessionIdRef.current = null; // 清理 sessionId - // 显示"扫码成功,登录中"提示 - if (isMountedRef.current) { - toast({ - title: "扫码成功", - description: "正在登录,请稍候...", - status: "info", - duration: 2000, - isClosable: false, - }); - } - - await handleLoginSuccess(wechatSessionId, status); + await handleLoginSuccess(currentSessionId, status); } // 处理过期状态 else if (status === WECHAT_STATUS.EXPIRED) { clearTimers(); + sessionIdRef.current = null; // 清理 sessionId if (isMountedRef.current) { toast({ title: "授权已过期", @@ -195,11 +205,12 @@ export default function WechatRegister() { } } } catch (error) { - logger.error('WechatRegister', 'checkWechatStatus', error, { sessionId: wechatSessionId }); + logger.error('WechatRegister', 'checkWechatStatus', error, { sessionId: currentSessionId }); // 轮询过程中的错误不显示给用户,避免频繁提示 // 但如果错误持续发生,停止轮询避免无限重试 if (error.message.includes('网络连接失败')) { clearTimers(); + sessionIdRef.current = null; // 清理 sessionId if (isMountedRef.current) { toast({ title: "网络连接失败", @@ -211,12 +222,17 @@ export default function WechatRegister() { } } } - }, [wechatSessionId, handleLoginSuccess, clearTimers, toast]); + }, [handleLoginSuccess, clearTimers, toast]); /** * 启动轮询 */ const startPolling = useCallback(() => { + logger.debug('WechatRegister', '启动轮询', { + sessionId: sessionIdRef.current, + interval: POLL_INTERVAL + }); + // 清理旧的定时器 clearTimers(); @@ -227,7 +243,9 @@ export default function WechatRegister() { // 设置超时 timeoutRef.current = setTimeout(() => { + logger.debug('WechatRegister', '二维码超时'); clearTimers(); + sessionIdRef.current = null; // 清理 sessionId setWechatStatus(WECHAT_STATUS.EXPIRED); }, QR_CODE_TIMEOUT); }, [checkWechatStatus, clearTimers]); @@ -254,10 +272,17 @@ export default function WechatRegister() { throw new Error(response.message || '获取二维码失败'); } + // 同时更新 ref 和 state,确保轮询能立即读取到最新值 + sessionIdRef.current = response.data.session_id; setWechatAuthUrl(response.data.auth_url); setWechatSessionId(response.data.session_id); setWechatStatus(WECHAT_STATUS.WAITING); + logger.debug('WechatRegister', '获取二维码成功', { + sessionId: response.data.session_id, + authUrl: response.data.auth_url + }); + // 启动轮询检查扫码状态 startPolling(); } catch (error) { @@ -293,21 +318,26 @@ export default function WechatRegister() { return () => { isMountedRef.current = false; clearTimers(); + sessionIdRef.current = null; // 清理 sessionId }; }, [clearTimers]); /** * 备用轮询机制 - 防止丢失状态 - * 每3秒检查一次,仅在获取到二维码URL且状态为waiting时执行 + * 每3秒检查一次,在 waiting 和 scanned 状态下都保持运行 + * ⚠️ 已临时注释,测试主轮询是否足够可靠 */ + /** useEffect(() => { - // 只在有auth_url、session_id且状态为waiting时启动备用轮询 - if (wechatAuthUrl && wechatSessionId && wechatStatus === WECHAT_STATUS.WAITING) { - logger.debug('WechatRegister', '备用轮询:启动备用轮询机制'); + // 在有auth_url、session_id且状态为waiting或scanned时启动备用轮询 + if (wechatAuthUrl && wechatSessionId && + (wechatStatus === WECHAT_STATUS.WAITING || wechatStatus === WECHAT_STATUS.SCANNED)) { + logger.debug('WechatRegister', '备用轮询:启动备用轮询机制', { status: wechatStatus }); backupPollIntervalRef.current = setInterval(() => { try { - if (wechatStatus === WECHAT_STATUS.WAITING && isMountedRef.current) { + if ((wechatStatus === WECHAT_STATUS.WAITING || wechatStatus === WECHAT_STATUS.SCANNED) && + isMountedRef.current && wechatAuthUrl) { logger.debug('WechatRegister', '备用轮询:检查微信状态'); // 添加 .catch() 静默处理异步错误,防止被 ErrorBoundary 捕获 checkWechatStatus().catch(error => { @@ -329,7 +359,7 @@ export default function WechatRegister() { } }; }, [wechatAuthUrl, wechatSessionId, wechatStatus, checkWechatStatus]); - + */ /** * 测量容器尺寸并计算缩放比例 */ @@ -397,7 +427,7 @@ export default function WechatRegister() { textAlign="center" mb={3} // 12px底部间距 > - 微信扫码 + 微信登陆 {/* ========== 二维码区域 ========== */} @@ -414,19 +444,26 @@ export default function WechatRegister() { bg="gray.50" boxShadow="sm" // ✅ 添加轻微阴影 > - {wechatStatus === WECHAT_STATUS.WAITING ? ( + {wechatStatus !== WECHAT_STATUS.NONE ? ( /* 已获取二维码:显示iframe */