feat: 调整注册逻辑

This commit is contained in:
zdl
2025-10-14 16:02:33 +08:00
parent cd50d718fe
commit e0ca328e1c
12 changed files with 1570 additions and 1206 deletions

View File

@@ -17,14 +17,19 @@ import {
IconButton,
Link as ChakraLink,
Center,
useDisclosure
useDisclosure,
FormErrorMessage
} from "@chakra-ui/react";
import { ViewIcon, ViewOffIcon } from "@chakra-ui/icons";
import { FaMobile, FaWeixin, FaLock, FaQrcode } from "react-icons/fa";
import { useNavigate, Link, useLocation } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom";
import { useAuth } from "../../../contexts/AuthContext";
import PrivacyPolicyModal from "../../../components/PrivacyPolicyModal";
import UserAgreementModal from "../../../components/UserAgreementModal";
import AuthBackground from "../../../components/Auth/AuthBackground";
import AuthHeader from "../../../components/Auth/AuthHeader";
import AuthFooter from "../../../components/Auth/AuthFooter";
import VerificationCodeInput from "../../../components/Auth/VerificationCodeInput";
// API配置
const isProduction = process.env.NODE_ENV === 'production';
@@ -38,6 +43,7 @@ export default function SignInIllustration() {
// 页面状态
const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState({});
// 检查URL参数中的错误信息微信登录失败时
useEffect(() => {
@@ -45,38 +51,38 @@ export default function SignInIllustration() {
const error = params.get('error');
if (error) {
let errorMessage = '登录失败';
switch (error) {
case 'wechat_auth_failed':
errorMessage = '微信授权失败';
break;
case 'session_expired':
errorMessage = '会话已过期,请重新登录';
break;
case 'token_failed':
errorMessage = '获取微信授权失败';
break;
case 'userinfo_failed':
errorMessage = '获取用户信息失败';
break;
case 'login_failed':
errorMessage = '登录处理失败,请重试';
break;
default:
errorMessage = '登录失败,请重试';
}
let errorMessage = '登录失败';
switch (error) {
case 'wechat_auth_failed':
errorMessage = '微信授权失败';
break;
case 'session_expired':
errorMessage = '会话已过期,请重新登录';
break;
case 'token_failed':
errorMessage = '获取微信授权失败';
break;
case 'userinfo_failed':
errorMessage = '获取用户信息失败';
break;
case 'login_failed':
errorMessage = '登录处理失败,请重试';
break;
default:
errorMessage = '登录失败,请重试';
}
toast({
title: "登录失败",
description: errorMessage,
status: "error",
duration: 5000,
isClosable: true,
});
toast({
title: "登录失败",
description: errorMessage,
status: "error",
duration: 5000,
isClosable: true,
});
// 清除URL参数
const newUrl = window.location.pathname;
window.history.replaceState({}, document.title, newUrl);
// 清除URL参数
const newUrl = window.location.pathname;
window.history.replaceState({}, document.title, newUrl);
}
}, [location, toast]);
@@ -110,8 +116,8 @@ export default function SignInIllustration() {
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
...prev,
[name]: value
}));
};
@@ -194,17 +200,13 @@ export default function SignInIllustration() {
}
};
// 获取微信授权URL
const getWechatQRCode = async () => {
};
// 点击扫码,打开微信登录窗口
const openWechatLogin = async() => {
const openWechatLogin = async () => {
try {
setIsLoading(true);
console.log("请求微信登录1...");
// 获取微信二维码地址
const response = await fetch(`${API_BASE_URL}/api/auth/wechat/qrcode`);
@@ -281,7 +283,7 @@ export default function SignInIllustration() {
const credential = formData.phone;
const authLoginType = 'phone';
if(useVerificationCode) { // 验证码登陆
if (useVerificationCode) { // 验证码登陆
if (!credential || !formData.verificationCode) {
toast({
title: "请填写完整信息",
@@ -346,291 +348,144 @@ export default function SignInIllustration() {
};
// 切换登录方式
const handleChangeMethod = (status) => {
if (!status) {
const handleChangeMethod = () => {
setUseVerificationCode(!useVerificationCode);
// 切换到密码模式时清空验证码
if (useVerificationCode) {
setFormData(prev => ({ ...prev, verificationCode: "" }));
}
setUseVerificationCode(!useVerificationCode);
}
};
return (
<Flex minH="100vh" position="relative" overflow="hidden">
{/* 流体波浪背景 */}
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
zIndex={0}
background={`
linear-gradient(45deg,
rgba(139, 69, 19, 0.9) 0%,
rgba(160, 82, 45, 0.8) 15%,
rgba(205, 133, 63, 0.7) 30%,
rgba(222, 184, 135, 0.8) 45%,
rgba(245, 222, 179, 0.6) 60%,
rgba(255, 228, 196, 0.7) 75%,
rgba(139, 69, 19, 0.8) 100%
)
`}
_before={{
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: `
conic-gradient(from 0deg at 30% 20%,
rgba(255, 140, 0, 0.6) 0deg,
rgba(255, 69, 0, 0.4) 60deg,
rgba(139, 69, 19, 0.5) 120deg,
rgba(160, 82, 45, 0.6) 180deg,
rgba(205, 133, 63, 0.4) 240deg,
rgba(255, 140, 0, 0.5) 300deg,
rgba(255, 140, 0, 0.6) 360deg
)
`,
mixBlendMode: 'multiply',
animation: 'fluid-rotate 20s linear infinite'
}}
_after={{
content: '""',
position: 'absolute',
top: '10%',
left: '20%',
width: '60%',
height: '80%',
borderRadius: '50%',
background: 'radial-gradient(ellipse at center, rgba(255, 165, 0, 0.3) 0%, rgba(255, 140, 0, 0.2) 50%, transparent 70%)',
filter: 'blur(40px)',
animation: 'wave-pulse 8s ease-in-out infinite'
}}
sx={{
'@keyframes fluid-rotate': {
'0%': { transform: 'rotate(0deg) scale(1)' },
'50%': { transform: 'rotate(180deg) scale(1.1)' },
'100%': { transform: 'rotate(360deg) scale(1)' }
},
'@keyframes wave-pulse': {
'0%, 100%': { opacity: 0.4, transform: 'scale(1)' },
'50%': { opacity: 0.8, transform: 'scale(1.2)' }
}
}}
/>
{/* 背景 */}
<AuthBackground />
{/* 主要内容 */}
<Flex
width="100%"
align="center"
justify="center"
position="relative"
zIndex={1}
px={6}
py={12}
>
<Flex width="100%" align="center" justify="center" position="relative" zIndex={1} px={6} py={12}>
{/* 登录卡片 */}
<Box
bg="white"
borderRadius="2xl"
boxShadow="2xl"
p={8}
width="100%"
maxW="600px"
backdropFilter="blur(20px)"
border="1px solid rgba(255, 255, 255, 0.2)"
>
<Box bg="white" borderRadius="2xl" boxShadow="2xl" p={8} width="100%" maxW="800px" backdropFilter="blur(20px)" border="1px solid rgba(255, 255, 255, 0.2)">
{/* 头部区域 */}
<VStack spacing={6} mb={8}>
<VStack spacing={2}>
<Heading size="xl" color="gray.800" fontWeight="bold">
欢迎回来
</Heading>
<Text color="gray.600" fontSize="md">
登录价值前沿继续您的投资之旅
</Text>
</VStack>
<AuthHeader title="欢迎回来" subtitle="登录价值前沿,继续您的投资之旅" />
{/* 左右布局 */}
<HStack spacing={8} align="stretch">
{/* 左侧:手机号登陆 - 80% 宽度 */}
<Box flex="4">
<form onSubmit={handleTraditionalLogin}>
<VStack spacing={4}>
<Heading size="md" color="gray.700" alignSelf="flex-start">
手机号登陆
</Heading>
<FormControl isRequired isInvalid={!!errors.phone}>
<Input
name="phone"
value={formData.phone}
onChange={handleInputChange}
placeholder="请输入11位手机号"
pr="2.5rem"
/>
<FormErrorMessage>{errors.phone}</FormErrorMessage>
</FormControl>
{/* 登录表单 */}
{/* setLoginType */}
<VStack spacing={2} align="stretch">
<HStack justify="center">
{/* 传统登录 */}
<form onSubmit={handleTraditionalLogin}>
<VStack spacing={4}>
<HStack spacing={2} width="100%" align="center"> {/* 设置 HStack 宽度为 100% */}
<Text fontSize="md" fontWeight="bold" color="gray.700" minWidth="70px" mr={2} noOfLines={1} overflow="hidden" textOverflow="ellipsis">
账号
</Text>
<FormControl isRequired flex="1 1 auto">
<InputGroup>
<Input
name={"phone"}
value={formData.phone}
onChange={handleInputChange}
placeholder={"请输入手机号"}
size="lg"
borderRadius="lg"
bg="gray.50"
border="1px solid"
borderColor="gray.200"
_focus={{
borderColor: "blue.500",
boxShadow: "0 0 0 1px #667eea"
}}
/>
<InputRightElement pointerEvents="none">
<Icon as={FaMobile} color="gray.400" />
</InputRightElement>
</InputGroup>
</FormControl>
</HStack>
{/* 密码输入框 */}
{useVerificationCode ? (
// 验证码输入框
<HStack spacing={2}>
<Text fontSize="md" fontWeight="bold" color={"gray.700"} minWidth="80px">验证码</Text>
<VStack spacing={3} align="stretch">
<HStack>
<FormControl isRequired flex="1 1 auto">
<InputGroup size="lg">
<Input
name="verificationCode"
value={formData.verificationCode}
onChange={handleInputChange}
placeholder="请输入验证码"
borderRadius="lg"
bg="gray.50"
border="1px solid"
borderColor="gray.200"
_focus={{
borderColor: "green.500",
boxShadow: "0 0 0 1px #48bb78"
}}
maxLength={6}
/>
{/* <InputRightElement>
<Icon as={FaCode} color="gray.400"/>
</InputRightElement> */}
</InputGroup>
</FormControl>
<Button
flex="0 0 auto" // 让按钮大小根据内容自适应
size="md"
colorScheme="green"
variant="outline"
onClick={sendVerificationCode}
isLoading={sendingCode}
isDisabled={verificationCodeSent && countdown > 0}
borderRadius="lg"
fontSize="sm" // 调整字体大小
whiteSpace="nowrap" // 防止文本换行
minWidth="120px" // 设置按钮最小宽度
>
{sendingCode ? "发送中..." : verificationCodeSent && countdown > 0 ? `${countdown}s` : "发送验证码"}
</Button>
</HStack>
</VStack>
</HStack>
):(
<HStack spacing={2}>
<Text fontSize="md" fontWeight="bold" color="gray.700" minWidth="70px" mr={2} noOfLines={1} overflow="hidden" textOverflow="ellipsis">
密码
</Text>
<FormControl isRequired flex="1 1 auto">
<InputGroup size="lg">
<Input
name="password"
type={showPassword ? "text" : "password"}
value={formData.password}
onChange={handleInputChange}
placeholder="请输入密码"
borderRadius="lg"
bg="gray.50"
border="1px solid"
borderColor="gray.200"
_focus={{
borderColor: "blue.500",
boxShadow: "0 0 0 1px #667eea"
}}
/>
<InputRightElement>
<IconButton
variant="ghost"
aria-label={showPassword ? "隐藏密码" : "显示密码"}
icon={showPassword ? <ViewOffIcon /> : <ViewIcon />}
onClick={() => setShowPassword(!showPassword)}
/>
</InputRightElement>
</InputGroup>
</FormControl>
</HStack>
)}
<HStack justify="space-between" width="100%">
<HStack spacing={1} as={Link} to="/auth/sign-up">
<Text fontSize="sm" color="gray.600">还没有账号</Text>
<Text fontSize="sm" color="blue.500" fontWeight="bold">去注册</Text>
</HStack>
<ChakraLink href="#" fontSize="sm" color="blue.500" fontWeight="bold" onClick={handleChangeMethod}>
{useVerificationCode ? '密码登陆' : '验证码登陆'}
</ChakraLink>
</HStack>
<Button
type="submit"
width="100%"
size="lg"
colorScheme="green"
color="white"
borderRadius="lg"
_hover={{
transform: "translateY(-2px)",
boxShadow: "lg"
}}
_active={{ transform: "translateY(0)" }}
{/* 密码/验证码输入框 */}
{useVerificationCode ? (
<VerificationCodeInput
value={formData.verificationCode}
onChange={handleInputChange}
onSendCode={sendVerificationCode}
countdown={countdown}
isLoading={isLoading}
loadingText="登录中..."
fontWeight="bold"
cursor={"pointer"}
>
<Icon as={FaLock} mr={2} />登录
</Button>
</VStack>
</form>
isSending={sendingCode}
error={errors.verificationCode}
colorScheme="green"
/>
) : (
<FormControl isRequired isInvalid={!!errors.password}>
<InputGroup>
<Input
name="password"
type={showPassword ? "text" : "password"}
value={formData.password}
onChange={handleInputChange}
pr="3rem"
placeholder="请输入密码"
_focus={{
borderColor: "blue.500",
boxShadow: "0 0 0 1px #667eea"
}}
/>
<InputRightElement width="3rem">
<IconButton
size="sm"
variant="ghost"
icon={showPassword ? <ViewOffIcon /> : <ViewIcon />}
onClick={() => setShowPassword(!showPassword)}
aria-label={showPassword ? "Hide password" : "Show password"}
/>
</InputRightElement>
</InputGroup>
<FormErrorMessage>{errors.password}</FormErrorMessage>
</FormControl>
)}
{/* 微信登录 - 简化版 */}
<VStack spacing={6}>
<Center width="100%" bg="gray.50" borderRadius="lg" p={8}>
<VStack spacing={6}>
<VStack spacing={2}>
<Text fontSize="lg" fontWeight="bold" color={"gray.700"}>
微信扫一扫
</Text>
</VStack>
<Icon as={FaQrcode} w={20} h={20} color={"green.500"} />
{/* isLoading={isLoading || !wechatAuthUrl} */}
<Button
colorScheme="green"
size="lg"
leftIcon={<Icon as={FaWeixin} />}
onClick={openWechatLogin}
_hover={{ transform: "translateY(-2px)", boxShadow: "lg" }}
_active={{ transform: "translateY(0)" }}
>
扫码登录
</Button>
</VStack>
</Center>
<AuthFooter
linkText="还没有账号,"
linkLabel="去注册"
linkTo="/auth/sign-up"
useVerificationCode={useVerificationCode}
onSwitchMethod={handleChangeMethod}
/>
<Button
type="submit"
width="100%"
size="lg"
colorScheme="green"
color="white"
borderRadius="lg"
_hover={{
transform: "translateY(-2px)",
boxShadow: "lg"
}}
_active={{ transform: "translateY(0)" }}
isLoading={isLoading}
loadingText="登录中..."
fontWeight="bold"
cursor={"pointer"}
>
<Icon as={FaLock} mr={2} />登录
</Button>
</VStack>
</HStack>
</VStack>
</VStack>
</form>
</Box>
{/* 右侧:微信登陆 - 20% 宽度 */}
<Box flex="1">
<Center width="100%" bg="gray.50" borderRadius="lg" p={8}>
<VStack spacing={6}>
<VStack spacing={2}>
<Text fontSize="lg" fontWeight="bold" color={"gray.700"}>
微信扫一扫
</Text>
</VStack>
<Icon as={FaQrcode} w={20} h={20} color={"green.500"} />
{/* isLoading={isLoading || !wechatAuthUrl} */}
<Button
colorScheme="green"
size="lg"
leftIcon={<Icon as={FaWeixin} />}
onClick={openWechatLogin}
_hover={{ transform: "translateY(-2px)", boxShadow: "lg" }}
_active={{ transform: "translateY(0)" }}
>
扫码登录
</Button>
</VStack>
</Center>
</Box>
</HStack>
{/* 底部链接 */}
<VStack spacing={4} mt={6}>