feat: 微信UI调整
This commit is contained in:
@@ -502,7 +502,7 @@ export default function AuthFormContent() {
|
||||
{/* 桌面端:右侧二维码扫描 */}
|
||||
{!isMobile && (
|
||||
<Box flex={{ base: "1", md: "0 0 auto" }}> {/* ✅ 桌面端让右侧自适应宽度 */}
|
||||
<Center width="100%" bg="gray.50" borderRadius="lg" p={0}> {/* ✅ 完全移除padding,最大化空间利用 */}
|
||||
<Center width="100%"> {/* ✅ 移除bg和p,WechatRegister自带白色背景和padding */}
|
||||
<WechatRegister />
|
||||
</Center>
|
||||
</Box>
|
||||
|
||||
@@ -3,14 +3,18 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
VStack,
|
||||
HStack,
|
||||
Center,
|
||||
Text,
|
||||
Heading,
|
||||
Icon,
|
||||
useToast,
|
||||
Spinner
|
||||
} from "@chakra-ui/react";
|
||||
import { FaQrcode } from "react-icons/fa";
|
||||
import { FiAlertCircle } from "react-icons/fi";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { authService, WECHAT_STATUS } from "../../services/authService";
|
||||
import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/authService";
|
||||
import { logger } from "../../utils/logger";
|
||||
|
||||
// 配置常量
|
||||
@@ -18,6 +22,28 @@ const POLL_INTERVAL = 2000; // 轮询间隔:2秒
|
||||
const BACKUP_POLL_INTERVAL = 3000; // 备用轮询间隔:3秒
|
||||
const QR_CODE_TIMEOUT = 300000; // 二维码超时:5分钟
|
||||
|
||||
/**
|
||||
* 获取状态文字颜色
|
||||
*/
|
||||
const getStatusColor = (status) => {
|
||||
switch(status) {
|
||||
case WECHAT_STATUS.WAITING: return "gray.600"; // ✅ 灰色文字
|
||||
case WECHAT_STATUS.SCANNED: return "green.600"; // ✅ 绿色文字
|
||||
case WECHAT_STATUS.AUTHORIZED: return "green.600"; // ✅ 绿色文字
|
||||
case WECHAT_STATUS.EXPIRED: return "orange.600"; // ✅ 橙色文字
|
||||
case WECHAT_STATUS.LOGIN_SUCCESS: return "green.600"; // ✅ 绿色文字
|
||||
case WECHAT_STATUS.REGISTER_SUCCESS: return "green.600";
|
||||
default: return "gray.600";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取状态文字
|
||||
*/
|
||||
const getStatusText = (status) => {
|
||||
return STATUS_MESSAGES[status] || "点击按钮获取二维码";
|
||||
};
|
||||
|
||||
export default function WechatRegister() {
|
||||
// 状态管理
|
||||
const [wechatAuthUrl, setWechatAuthUrl] = useState("");
|
||||
@@ -141,6 +167,18 @@ export default function WechatRegister() {
|
||||
// 处理成功状态
|
||||
if (status === WECHAT_STATUS.LOGIN_SUCCESS || status === WECHAT_STATUS.REGISTER_SUCCESS) {
|
||||
clearTimers(); // 停止轮询
|
||||
|
||||
// 显示"扫码成功,登录中"提示
|
||||
if (isMountedRef.current) {
|
||||
toast({
|
||||
title: "扫码成功",
|
||||
description: "正在登录,请稍候...",
|
||||
status: "info",
|
||||
duration: 2000,
|
||||
isClosable: false,
|
||||
});
|
||||
}
|
||||
|
||||
await handleLoginSuccess(wechatSessionId, status);
|
||||
}
|
||||
// 处理过期状态
|
||||
@@ -296,9 +334,9 @@ export default function WechatRegister() {
|
||||
* 测量容器尺寸并计算缩放比例
|
||||
*/
|
||||
useLayoutEffect(() => {
|
||||
// 微信授权页面的原始尺寸
|
||||
const ORIGINAL_WIDTH = 600;
|
||||
const ORIGINAL_HEIGHT = 800;
|
||||
// 微信授权页面的原始尺寸(需要与iframe实际尺寸匹配)
|
||||
const ORIGINAL_WIDTH = 300; // ✅ 修正:与iframe width匹配
|
||||
const ORIGINAL_HEIGHT = 350; // ✅ 修正:与iframe height匹配
|
||||
|
||||
const calculateScale = () => {
|
||||
if (containerRef.current) {
|
||||
@@ -345,116 +383,145 @@ export default function WechatRegister() {
|
||||
// };
|
||||
|
||||
return (
|
||||
<VStack spacing={2} display="flex" alignItems="center" justifyContent="center">
|
||||
{wechatStatus === WECHAT_STATUS.WAITING ? (
|
||||
<>
|
||||
<Text fontSize="lg" fontWeight="bold" color="gray.700" whiteSpace="nowrap">
|
||||
微信扫码
|
||||
</Text>
|
||||
<VStack
|
||||
spacing={0} // ✅ 手动控制间距
|
||||
alignItems="stretch" // ✅ 拉伸对齐
|
||||
justifyContent="flex-start" // ✅ 顶部对齐(标题对齐关键)
|
||||
width="auto" // ✅ 自适应宽度
|
||||
>
|
||||
{/* ========== 标题区域 ========== */}
|
||||
<Heading
|
||||
size="md" // ✅ 16px,与左侧"登陆/注册"一致
|
||||
fontWeight="600"
|
||||
color="gray.800"
|
||||
textAlign="center"
|
||||
mb={3} // 12px底部间距
|
||||
>
|
||||
微信扫码
|
||||
</Heading>
|
||||
|
||||
{/* ========== 二维码区域 ========== */}
|
||||
<Box
|
||||
ref={containerRef}
|
||||
position="relative"
|
||||
width="230px" // ✅ 升级尺寸
|
||||
height="230px"
|
||||
mx="auto"
|
||||
overflow="hidden"
|
||||
borderRadius="md"
|
||||
border="1px solid"
|
||||
borderColor="gray.200"
|
||||
bg="gray.50"
|
||||
boxShadow="sm" // ✅ 添加轻微阴影
|
||||
>
|
||||
{wechatStatus === WECHAT_STATUS.WAITING ? (
|
||||
/* 已获取二维码:显示iframe */
|
||||
<iframe
|
||||
src={wechatAuthUrl}
|
||||
title="微信扫码登录"
|
||||
width="300"
|
||||
height="350"
|
||||
style={{
|
||||
border: 'none',
|
||||
transform: 'scale(0.77) translateY(-20px)', // ✅ 裁剪顶部logo
|
||||
transformOrigin: 'top left',
|
||||
marginLeft: '-5px'
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
/* 未获取:显示占位符 */
|
||||
<Center width="100%" height="100%" flexDirection="column">
|
||||
<Icon as={FaQrcode} w={16} h={16} color="gray.300" mb={4} />
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="green"
|
||||
onClick={handleGetQRCodeClick}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED ? "刷新二维码" : "获取二维码"}
|
||||
</Button>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
{/* ========== 过期蒙层 ========== */}
|
||||
{wechatStatus === WECHAT_STATUS.EXPIRED && (
|
||||
<Box
|
||||
ref={containerRef}
|
||||
position="relative"
|
||||
width="150px"
|
||||
height="100px"
|
||||
maxWidth="100%"
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
bg="rgba(0,0,0,0.6)"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
overflow="hidden"
|
||||
backdropFilter="blur(4px)"
|
||||
>
|
||||
<iframe
|
||||
src={wechatAuthUrl}
|
||||
title="微信扫码登录"
|
||||
width="300"
|
||||
height="350"
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
border: 'none',
|
||||
transform: `scale(${scale})`,
|
||||
transformOrigin: 'center center'
|
||||
}}
|
||||
/>
|
||||
<VStack spacing={2}>
|
||||
<Icon as={FiAlertCircle} w={8} h={8} color="white" />
|
||||
<Text color="white" fontSize="sm">二维码已过期</Text>
|
||||
<Button
|
||||
size="xs"
|
||||
colorScheme="whiteAlpha"
|
||||
onClick={handleGetQRCodeClick}
|
||||
>
|
||||
点击刷新
|
||||
</Button>
|
||||
</VStack>
|
||||
</Box>
|
||||
{/* {renderStatusText()} */}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text fontSize="lg" fontWeight="bold" color="gray.700" whiteSpace="nowrap">
|
||||
微信扫码
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* ========== 状态指示器 ========== */}
|
||||
{wechatStatus !== WECHAT_STATUS.NONE && (
|
||||
<Text
|
||||
mt={3}
|
||||
fontSize="sm"
|
||||
fontWeight="500" // ✅ 半粗体
|
||||
textAlign="center"
|
||||
color={getStatusColor(wechatStatus)} // ✅ 根据状态显示不同颜色
|
||||
>
|
||||
{getStatusText(wechatStatus)}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* ========== Mock 模式控制按钮(仅开发环境) ========== */}
|
||||
{process.env.REACT_APP_ENABLE_MOCK === 'true' && wechatStatus === WECHAT_STATUS.WAITING && wechatSessionId && (
|
||||
<Box mt={3} pt={3} borderTop="1px solid" borderColor="gray.200">
|
||||
<Button
|
||||
size="xs"
|
||||
width="100%"
|
||||
colorScheme="purple"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
if (window.mockWechatScan) {
|
||||
const success = window.mockWechatScan(wechatSessionId);
|
||||
if (success) {
|
||||
toast({
|
||||
title: "Mock 模拟触发成功",
|
||||
description: "正在模拟扫码登录...",
|
||||
status: "info",
|
||||
duration: 2000,
|
||||
isClosable: false,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
toast({
|
||||
title: "Mock API 未加载",
|
||||
description: "请刷新页面重试",
|
||||
status: "warning",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}}
|
||||
leftIcon={<Text fontSize="lg">🧪</Text>}
|
||||
>
|
||||
模拟扫码成功(测试)
|
||||
</Button>
|
||||
<Text fontSize="xs" color="gray.400" textAlign="center" mt={1}>
|
||||
开发模式 | 自动登录: 5秒
|
||||
</Text>
|
||||
|
||||
<Box
|
||||
position="relative"
|
||||
width="150px"
|
||||
height="100px"
|
||||
maxWidth="100%"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
overflow="hidden"
|
||||
>
|
||||
{/* 灰色二维码底图 - 始终显示 */}
|
||||
<Icon as={FaQrcode} w={24} h={24} color="gray.300" />
|
||||
|
||||
{/* 加载动画 */}
|
||||
{isLoading && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom="0"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Spinner
|
||||
size="lg"
|
||||
color="green.500"
|
||||
thickness="4px"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* 显示获取/刷新二维码按钮 */}
|
||||
{(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={handleGetQRCodeClick}
|
||||
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()} */}
|
||||
</>
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user