diff --git a/src/components/Auth/WechatRegister.js b/src/components/Auth/WechatRegister.js index 9f32451c..9a01abc9 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) { @@ -128,16 +136,14 @@ export default function WechatRegister() { } showSuccess( - status === WECHAT_STATUS.LOGIN_SUCCESS ? "登录成功" : "注册成功", - "正在跳转..." + status === WECHAT_STATUS.LOGIN_SUCCESS ? "登录成功" : "欢迎回来!" ); - logger.info('WechatRegister', '准备跳转到首页'); + // 刷新 AuthContext 状态 + await refreshSession(); - // 延迟跳转,让用户看到成功提示 - setTimeout(() => { - navigate("/home"); - }, 1000); + // 关闭认证弹窗,留在当前页面 + closeModal(); } else { throw new Error(response?.error || '登录失败'); } @@ -145,17 +151,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') { @@ -164,6 +180,7 @@ export default function WechatRegister() { } const { status } = response; + logger.debug('WechatRegister', '微信状态', { status }); logger.debug('WechatRegister', '检测到微信状态', { sessionId: wechatSessionId.substring(0, 8) + '...', @@ -180,23 +197,14 @@ export default function WechatRegister() { if (status === WECHAT_STATUS.LOGIN_SUCCESS || status === WECHAT_STATUS.REGISTER_SUCCESS) { logger.info('WechatRegister', '检测到登录成功状态,停止轮询', { status }); 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: "授权已过期", @@ -208,11 +216,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: "网络连接失败", @@ -224,12 +233,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(); @@ -240,7 +254,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]); @@ -267,10 +283,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) { @@ -306,43 +329,10 @@ export default function WechatRegister() { return () => { isMountedRef.current = false; clearTimers(); + sessionIdRef.current = null; // 清理 sessionId }; }, [clearTimers]); - /** - * 备用轮询机制 - 防止丢失状态 - * 每3秒检查一次,仅在获取到二维码URL且状态为waiting时执行 - */ - useEffect(() => { - // 只在有auth_url、session_id且状态为waiting时启动备用轮询 - if (wechatAuthUrl && wechatSessionId && wechatStatus === WECHAT_STATUS.WAITING) { - logger.debug('WechatRegister', '备用轮询:启动备用轮询机制'); - - backupPollIntervalRef.current = setInterval(() => { - try { - if (wechatStatus === WECHAT_STATUS.WAITING && isMountedRef.current) { - logger.debug('WechatRegister', '备用轮询:检查微信状态'); - // 添加 .catch() 静默处理异步错误,防止被 ErrorBoundary 捕获 - checkWechatStatus().catch(error => { - logger.warn('WechatRegister', '备用轮询检查失败(静默处理)', { error: error.message }); - }); - } - } catch (error) { - // 捕获所有同步错误,防止被 ErrorBoundary 捕获 - logger.warn('WechatRegister', '备用轮询执行出错(静默处理)', { error: error.message }); - } - }, BACKUP_POLL_INTERVAL); - } - - // 清理备用轮询 - return () => { - if (backupPollIntervalRef.current) { - clearInterval(backupPollIntervalRef.current); - backupPollIntervalRef.current = null; - } - }; - }, [wechatAuthUrl, wechatSessionId, wechatStatus, checkWechatStatus]); - /** * 测量容器尺寸并计算缩放比例 */ @@ -410,7 +400,7 @@ export default function WechatRegister() { textAlign="center" mb={3} // 12px底部间距 > - 微信扫码 + 微信登陆 {/* ========== 二维码区域 ========== */} @@ -427,19 +417,26 @@ export default function WechatRegister() { bg="gray.50" boxShadow="sm" // ✅ 添加轻微阴影 > - {wechatStatus === WECHAT_STATUS.WAITING ? ( + {wechatStatus !== WECHAT_STATUS.NONE ? ( /* 已获取二维码:显示iframe */