feat: 登陆状态调整

This commit is contained in:
zdl
2025-10-20 13:58:07 +08:00
parent b2681231b0
commit d695f8ff7b
8 changed files with 37 additions and 70 deletions

View File

@@ -11,7 +11,8 @@
"Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/Automotive.js)", "Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/Automotive.js)",
"Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/CRM.js)", "Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/CRM.js)",
"Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/SmartHome.js)", "Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/SmartHome.js)",
"Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/Landing.js)" "Bash(rm /Users/qiye/Desktop/jzqy/vf_react/src/views/Dashboard/Landing.js)",
"mcp__ide__getDiagnostics"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

View File

@@ -603,7 +603,7 @@ export default function HomeNavbar() {
error: error.message error: error.message
}); });
} }
}, [isAuthenticated, user]); // 移除 getApiBase 依赖,因为它现在在组件外部 }, [isAuthenticated, user?.id]); // 只依赖 user.id,避免 user 对象变化导致无限循环
// 监听用户变化,重置检查标志(用户切换或退出登录时) // 监听用户变化,重置检查标志(用户切换或退出登录时)
React.useEffect(() => { React.useEffect(() => {
@@ -622,7 +622,7 @@ export default function HomeNavbar() {
const timer = setTimeout(checkProfileCompleteness, 1000); const timer = setTimeout(checkProfileCompleteness, 1000);
return () => clearTimeout(timer); return () => clearTimeout(timer);
} }
}, [isAuthenticated, user, checkProfileCompleteness]); }, [isAuthenticated, user?.id, checkProfileCompleteness]); // 只依赖 user.id,避免无限循环
// 加载订阅信息 // 加载订阅信息
React.useEffect(() => { React.useEffect(() => {

View File

@@ -24,12 +24,12 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { logger } from '../../utils/logger'; import { logger } from '../../utils/logger';
import { useAuth } from '../../contexts/AuthContext';
// Icons // Icons
import { import {
FaWeixin, FaWeixin,
FaGem, FaGem,
FaStar,
FaCheck, FaCheck,
FaQrcode, FaQrcode,
FaClock, FaClock,
@@ -38,6 +38,9 @@ import {
} from 'react-icons/fa'; } from 'react-icons/fa';
export default function SubscriptionContent() { export default function SubscriptionContent() {
// Auth context
const { user } = useAuth();
// Chakra color mode // Chakra color mode
const textColor = useColorModeValue('gray.700', 'white'); const textColor = useColorModeValue('gray.700', 'white');
const borderColor = useColorModeValue('gray.200', 'gray.600'); const borderColor = useColorModeValue('gray.200', 'gray.600');
@@ -50,7 +53,6 @@ export default function SubscriptionContent() {
// State // State
const [subscriptionPlans, setSubscriptionPlans] = useState([]); const [subscriptionPlans, setSubscriptionPlans] = useState([]);
const [currentUser, setCurrentUser] = useState(null);
const [selectedPlan, setSelectedPlan] = useState(null); const [selectedPlan, setSelectedPlan] = useState(null);
const [selectedCycle, setSelectedCycle] = useState('monthly'); const [selectedCycle, setSelectedCycle] = useState('monthly');
const [paymentOrder, setPaymentOrder] = useState(null); const [paymentOrder, setPaymentOrder] = useState(null);
@@ -63,7 +65,7 @@ export default function SubscriptionContent() {
// 加载订阅套餐数据 // 加载订阅套餐数据
useEffect(() => { useEffect(() => {
fetchSubscriptionPlans(); fetchSubscriptionPlans();
fetchCurrentUser(); // 不再需要 fetchCurrentUser(),直接使用 AuthContext 的 user
}, []); }, []);
// 倒计时更新 // 倒计时更新
@@ -124,30 +126,8 @@ export default function SubscriptionContent() {
} }
}; };
const fetchCurrentUser = async () => {
try {
const response = await fetch('/api/auth/session', {
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
logger.debug('SubscriptionContent', '用户数据获取成功', { data });
if (data.success) {
setCurrentUser(data.user);
logger.debug('SubscriptionContent', '用户信息已更新', {
userId: data.user?.id,
subscriptionType: data.user?.subscription_type,
subscriptionStatus: data.user?.subscription_status
});
}
}
} catch (error) {
logger.error('SubscriptionContent', 'fetchCurrentUser', error);
}
};
const handleSubscribe = (plan) => { const handleSubscribe = (plan) => {
if (!currentUser) { if (!user) {
toast({ toast({
title: '请先登录', title: '请先登录',
status: 'warning', status: 'warning',
@@ -287,25 +267,9 @@ export default function SubscriptionContent() {
} }
}; };
const handleRefreshUserStatus = async () => { const handleRefreshUserStatus = () => {
try { // 刷新页面以重新加载用户数据
await fetchCurrentUser(); window.location.reload();
toast({
title: '用户状态已刷新',
description: '订阅信息已更新',
status: 'success',
duration: 3000,
isClosable: true,
});
} catch (error) {
toast({
title: '刷新失败',
description: '请稍后重试',
status: 'error',
duration: 3000,
isClosable: true,
});
}
}; };
const handleForceUpdatePayment = async () => { const handleForceUpdatePayment = async () => {
@@ -459,7 +423,7 @@ export default function SubscriptionContent() {
return ( return (
<VStack spacing={6} align="stretch" w="100%"> <VStack spacing={6} align="stretch" w="100%">
{/* 当前订阅状态 */} {/* 当前订阅状态 */}
{currentUser && ( {user && (
<Box <Box
p={6} p={6}
borderRadius="xl" borderRadius="xl"
@@ -487,8 +451,8 @@ export default function SubscriptionContent() {
<HStack spacing={2} mb={2}> <HStack spacing={2} mb={2}>
<Badge <Badge
colorScheme={ colorScheme={
currentUser.subscription_type === 'max' ? 'purple' : user.subscription_type === 'max' ? 'purple' :
currentUser.subscription_type === 'pro' ? 'blue' : 'gray' user.subscription_type === 'pro' ? 'blue' : 'gray'
} }
variant="subtle" variant="subtle"
px={3} px={3}
@@ -496,29 +460,30 @@ export default function SubscriptionContent() {
borderRadius="full" borderRadius="full"
fontSize="sm" fontSize="sm"
> >
{currentUser.subscription_type === 'free' ? '基础版' : 1SubscriptionContent {user.subscription_type}
currentUser.subscription_type === 'pro' ? 'Pro 专业版' : 'Max 旗舰版'} {user.subscription_type === 'free' ? '基础版' :
user.subscription_type === 'pro' ? 'Pro 专业版' : 'Max 旗舰版'}
</Badge> </Badge>
<Badge <Badge
colorScheme={currentUser.subscription_status === 'active' ? 'green' : 'red'} colorScheme={user.subscription_status === 'active' ? 'green' : 'red'}
variant="subtle" variant="subtle"
px={3} px={3}
py={1} py={1}
borderRadius="full" borderRadius="full"
> >
{currentUser.subscription_status === 'active' ? '已激活' : '未激活'} {user.subscription_status === 'active' ? '已激活' : '未激活'}
</Badge> </Badge>
</HStack> </HStack>
{currentUser.subscription_end_date && ( {user.subscription_end_date && (
<Text fontSize="sm" color={secondaryText}> <Text fontSize="sm" color={secondaryText}>
到期时间: {new Date(currentUser.subscription_end_date).toLocaleDateString('zh-CN')} 到期时间: {new Date(user.subscription_end_date).toLocaleDateString('zh-CN')}
</Text> </Text>
)} )}
</Box> </Box>
{currentUser.subscription_status === 'active' && currentUser.subscription_type !== 'free' && ( {user.subscription_status === 'active' && user.subscription_type !== 'free' && (
<Icon <Icon
as={currentUser.subscription_type === 'max' ? FaCrown : FaGem} as={user.subscription_type === 'max' ? FaCrown : FaGem}
color={currentUser.subscription_type === 'max' ? 'purple.400' : 'blue.400'} color={user.subscription_type === 'max' ? 'purple.400' : 'blue.400'}
boxSize={8} boxSize={8}
/> />
)} )}
@@ -665,16 +630,16 @@ export default function SubscriptionContent() {
variant="solid" variant="solid"
onClick={() => handleSubscribe(plan)} onClick={() => handleSubscribe(plan)}
isDisabled={ isDisabled={
currentUser?.subscription_type === plan.name && user?.subscription_type === plan.name &&
currentUser?.subscription_status === 'active' user?.subscription_status === 'active'
} }
_hover={{ _hover={{
transform: 'scale(1.02)', transform: 'scale(1.02)',
}} }}
transition="all 0.2s" transition="all 0.2s"
> >
{currentUser?.subscription_type === plan.name && {user?.subscription_type === plan.name &&
currentUser?.subscription_status === 'active' user?.subscription_status === 'active'
? '✓ 已订阅' ? '✓ 已订阅'
: `选择 ${plan.display_name}` : `选择 ${plan.display_name}`
} }

View File

@@ -106,7 +106,8 @@ export const useSubscription = () => {
useEffect(() => { useEffect(() => {
fetchSubscriptionInfo(); fetchSubscriptionInfo();
}, [isAuthenticated, user]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [isAuthenticated, user?.id]); // 只依赖 user.id,避免 user 对象变化导致无限循环
// 获取订阅级别数值 // 获取订阅级别数值
const getSubscriptionLevel = (type = null) => { const getSubscriptionLevel = (type = null) => {

View File

@@ -112,7 +112,7 @@ export default function CenterDashboard() {
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, [user]); }, [user?.id]); // 只依赖 user.id,避免无限循环
// 加载实时行情 // 加载实时行情
const loadRealtimeQuotes = useCallback(async () => { const loadRealtimeQuotes = useCallback(async () => {
@@ -198,7 +198,7 @@ export default function CenterDashboard() {
}; };
document.addEventListener('visibilitychange', onVis); document.addEventListener('visibilitychange', onVis);
return () => document.removeEventListener('visibilitychange', onVis); return () => document.removeEventListener('visibilitychange', onVis);
}, [user, location.pathname, loadData]); }, [user?.id, location.pathname, loadData]); // 只依赖 user.id,避免无限循环
// 定时刷新实时行情(每分钟一次) // 定时刷新实时行情(每分钟一次)
useEffect(() => { useEffect(() => {

View File

@@ -37,7 +37,7 @@ export default function HomePage() {
nickname: user.nickname nickname: user.nickname
} : null } : null
}); });
}, [user, isAuthenticated, isLoading]); }, [user?.id, isAuthenticated, isLoading]); // 只依赖 user.id,避免无限循环
// 统计数据动画 // 统计数据动画
const [stats, setStats] = useState({ const [stats, setStats] = useState({

View File

@@ -35,7 +35,7 @@ export default function HomePage() {
isAuthenticated, isAuthenticated,
hasUser: !!user hasUser: !!user
}); });
}, [user, isAuthenticated]); }, [user?.id, isAuthenticated]); // 只依赖 user.id,避免无限循环
// 核心功能配置 - 5个主要功能 // 核心功能配置 - 5个主要功能
const coreFeatures = [ const coreFeatures = [

View File

@@ -92,7 +92,7 @@ export default function TradingSimulation() {
userId: user?.id, userId: user?.id,
userName: user?.name userName: user?.name
}); });
}, [isAuthenticated, user]); }, [isAuthenticated, user?.id]); // 只依赖 user.id,避免无限循环
// 获取资产历史数据的 useEffect // 获取资产历史数据的 useEffect
useEffect(() => { useEffect(() => {