feat: 手机验证码调试
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from "react";
|
||||
import React, { useState, useEffect, useLayoutEffect, useRef, useCallback } from "react";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -15,6 +15,7 @@ import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/auth
|
||||
// 配置常量
|
||||
const POLL_INTERVAL = 2000; // 轮询间隔:2秒
|
||||
const QR_CODE_TIMEOUT = 300000; // 二维码超时:5分钟
|
||||
const ENABLE_MOCK = 'true'; // 通过环境变量控制 mock
|
||||
|
||||
export default function WechatRegister() {
|
||||
// 状态管理
|
||||
@@ -22,11 +23,13 @@ export default function WechatRegister() {
|
||||
const [wechatSessionId, setWechatSessionId] = useState("");
|
||||
const [wechatStatus, setWechatStatus] = useState(WECHAT_STATUS.NONE);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [scale, setScale] = useState(1); // iframe 缩放比例
|
||||
|
||||
// 使用 useRef 管理定时器,避免闭包问题和内存泄漏
|
||||
const pollIntervalRef = useRef(null);
|
||||
const timeoutRef = useRef(null);
|
||||
const isMountedRef = useRef(true); // 追踪组件挂载状态
|
||||
const containerRef = useRef(null); // 容器DOM引用
|
||||
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
@@ -189,9 +192,42 @@ export default function WechatRegister() {
|
||||
* 获取微信二维码
|
||||
*/
|
||||
const getWechatQRCode = async () => {
|
||||
debugger
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
// 开发环境:使用 mock 数据
|
||||
if (ENABLE_MOCK) {
|
||||
console.log('🔧 开发模式:使用 Mock 数据');
|
||||
|
||||
// 模拟网络延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
// 检查组件是否已卸载
|
||||
if (!isMountedRef.current) return;
|
||||
|
||||
// Mock 数据 - 使用一个测试页面
|
||||
const mockResponse = {
|
||||
auth_url: 'https://open.weixin.qq.com/connect/qrconnect?appid=mock&redirect_uri=mock&response_type=code&scope=snsapi_login&state=mock#wechat_redirect',
|
||||
session_id: 'mock-session-' + Date.now()
|
||||
};
|
||||
|
||||
setWechatAuthUrl(mockResponse.auth_url);
|
||||
setWechatSessionId(mockResponse.session_id);
|
||||
setWechatStatus(WECHAT_STATUS.WAITING);
|
||||
|
||||
toast({
|
||||
title: "Mock 模式",
|
||||
description: "正在使用测试数据展示",
|
||||
status: "info",
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 不启动轮询(避免无效请求)
|
||||
return;
|
||||
}
|
||||
|
||||
// 生产环境:调用真实 API
|
||||
const response = await authService.getWechatQRCode();
|
||||
|
||||
// 检查组件是否已卸载
|
||||
@@ -236,6 +272,46 @@ export default function WechatRegister() {
|
||||
};
|
||||
}, [clearTimers]);
|
||||
|
||||
/**
|
||||
* 测量容器尺寸并计算缩放比例
|
||||
*/
|
||||
useLayoutEffect(() => {
|
||||
// 微信授权页面的原始尺寸
|
||||
const ORIGINAL_WIDTH = 600;
|
||||
const ORIGINAL_HEIGHT = 800;
|
||||
|
||||
const calculateScale = () => {
|
||||
if (containerRef.current) {
|
||||
const { width, height } = containerRef.current.getBoundingClientRect();
|
||||
|
||||
// 计算宽高比例,取较小值确保完全适配
|
||||
const scaleX = width / ORIGINAL_WIDTH;
|
||||
const scaleY = height / ORIGINAL_HEIGHT;
|
||||
const newScale = Math.min(scaleX, scaleY, 1.0); // 最大不超过1.0
|
||||
|
||||
// 设置最小缩放比例为0.3,避免过小
|
||||
setScale(Math.max(newScale, 0.3));
|
||||
}
|
||||
};
|
||||
|
||||
// 初始计算
|
||||
calculateScale();
|
||||
|
||||
// 使用 ResizeObserver 监听容器尺寸变化
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
calculateScale();
|
||||
});
|
||||
|
||||
if (containerRef.current) {
|
||||
resizeObserver.observe(containerRef.current);
|
||||
}
|
||||
|
||||
// 清理
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, [wechatStatus]); // 当状态变化时重新计算
|
||||
|
||||
/**
|
||||
* 渲染状态提示文本
|
||||
*/
|
||||
@@ -246,96 +322,119 @@ export default function WechatRegister() {
|
||||
|
||||
return (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
{STATUS_MESSAGES[wechatStatus] || STATUS_MESSAGES[WECHAT_STATUS.WAITING]}
|
||||
{STATUS_MESSAGES[wechatStatus]}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<VStack spacing={2}>
|
||||
<Text fontSize="lg" fontWeight="bold" color="gray.700" whiteSpace="nowrap">
|
||||
微信扫一扫
|
||||
</Text>
|
||||
|
||||
<Box
|
||||
position="relative"
|
||||
minH="120px"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{/* 灰色二维码底图 - 始终显示 */}
|
||||
{wechatStatus === WECHAT_STATUS.WAITING ? (
|
||||
<Box position="relative" width="96px" height="96px">
|
||||
<VStack spacing={2} display="flex" alignItems="center" justifyContent="center">
|
||||
{wechatStatus === WECHAT_STATUS.WAITING ? (
|
||||
<>
|
||||
<Text fontSize="lg" fontWeight="bold" color="gray.700" whiteSpace="nowrap">
|
||||
微信扫码
|
||||
</Text>
|
||||
<Box
|
||||
ref={containerRef}
|
||||
position="relative"
|
||||
width="150px"
|
||||
height="100px"
|
||||
maxWidth="100%"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
overflow="hidden"
|
||||
>
|
||||
<iframe
|
||||
src={wechatAuthUrl}
|
||||
width="96"
|
||||
height="96"
|
||||
style={{ borderRadius: '8px', border: 'none' }}
|
||||
width="300"
|
||||
height="350"
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
transform: `scale(${scale})`,
|
||||
transformOrigin: 'center center'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Icon as={FaQrcode} w={24} h={24} color="gray.300" />
|
||||
)}
|
||||
{renderStatusText()}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text fontSize="lg" fontWeight="bold" color="gray.700" whiteSpace="nowrap">
|
||||
微信扫码
|
||||
</Text>
|
||||
|
||||
{/* 加载动画 */}
|
||||
{isLoading && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
position="relative"
|
||||
minH="120px"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Spinner
|
||||
size="lg"
|
||||
color="green.500"
|
||||
thickness="4px"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{/* 灰色二维码底图 - 始终显示 */}
|
||||
<Icon as={FaQrcode} w={24} h={24} color="gray.300" />
|
||||
|
||||
{/* 显示获取/刷新二维码按钮 */}
|
||||
{(wechatStatus === WECHAT_STATUS.NONE || wechatStatus === WECHAT_STATUS.EXPIRED) && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
bg="rgba(255, 255, 255, 0.3)"
|
||||
backdropFilter="blur(2px)"
|
||||
>
|
||||
<VStack spacing={2}>
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="green"
|
||||
size="sm"
|
||||
onClick={getWechatQRCode}
|
||||
isLoading={isLoading}
|
||||
leftIcon={<Icon as={FaQrcode} />}
|
||||
_hover={{ bg: "green.50" }}
|
||||
{/* 加载动画 */}
|
||||
{isLoading && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED ? "点击刷新" : "获取二维码"}
|
||||
</Button>
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED && (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
二维码已过期
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Spinner
|
||||
size="lg"
|
||||
color="green.500"
|
||||
thickness="4px"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* 扫码状态提示 */}
|
||||
{renderStatusText()}
|
||||
{/* 显示获取/刷新二维码按钮 */}
|
||||
{(wechatStatus === WECHAT_STATUS.NONE || wechatStatus === WECHAT_STATUS.EXPIRED) && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
bg="rgba(255, 255, 255, 0.3)"
|
||||
backdropFilter="blur(2px)"
|
||||
>
|
||||
<VStack spacing={2}>
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="green"
|
||||
size="sm"
|
||||
onClick={getWechatQRCode}
|
||||
isLoading={isLoading}
|
||||
leftIcon={<Icon as={FaQrcode} />}
|
||||
_hover={{ bg: "green.50" }}
|
||||
>
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED ? "点击刷新" : "获取二维码"}
|
||||
</Button>
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED && (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
二维码已过期
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* 扫码状态提示 */}
|
||||
{/* {renderStatusText()} */}
|
||||
</>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user