refactor(Center): 重构个人中心为左右布局
- 左侧自适应:投资仪表盘、规划中心、论坛 - 右侧固定200px:关注股票、关注事件 - 使用 THEME 黑金配色 - 宽度与导航栏保持一致 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -61,9 +61,13 @@ import {
|
|||||||
FiAlertCircle,
|
FiAlertCircle,
|
||||||
FiUsers,
|
FiUsers,
|
||||||
} from 'react-icons/fi';
|
} from 'react-icons/fi';
|
||||||
import MyFutureEvents from './components/MyFutureEvents';
|
|
||||||
import InvestmentPlanningCenter from './components/InvestmentPlanningCenter';
|
import InvestmentPlanningCenter from './components/InvestmentPlanningCenter';
|
||||||
import { getEventDetailUrl } from '@/utils/idEncoder';
|
import { getEventDetailUrl } from '@/utils/idEncoder';
|
||||||
|
import MarketDashboard from '@views/Profile/components/MarketDashboard';
|
||||||
|
import StrategyCenter from '@views/Profile/components/StrategyCenter';
|
||||||
|
import ForumCenter from '@views/Profile/components/ForumCenter';
|
||||||
|
import WatchSidebar from '@views/Profile/components/WatchSidebar';
|
||||||
|
import { THEME } from '@views/Profile/components/MarketDashboard/constants';
|
||||||
|
|
||||||
export default function CenterDashboard() {
|
export default function CenterDashboard() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@@ -273,336 +277,64 @@ export default function CenterDashboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box bg={sectionBg} minH="100vh" overflowX="hidden">
|
<Box bg={THEME.bg.primary} minH="100vh" overflowX="hidden">
|
||||||
<Box px={{ base: 3, md: 8 }} py={{ base: 4, md: 6 }} maxW="1400px" mx="auto">
|
<Box px={{ base: 3, md: 4 }} py={{ base: 4, md: 6 }} maxW="container.xl" mx="auto">
|
||||||
{/* 主要内容区域 */}
|
{/* 左右布局:左侧自适应,右侧固定200px */}
|
||||||
<Grid templateColumns={{ base: '1fr', lg: 'repeat(3, 1fr)' }} gap={6} mb={8}>
|
<Flex gap={4}>
|
||||||
{/* 左列:自选股票 */}
|
{/* 左侧主内容区 */}
|
||||||
<VStack spacing={6} align="stretch" minW={0}>
|
<Box flex={1} minW={0}>
|
||||||
<Card bg={cardBg} shadow="md" maxW="100%" height={{ base: 'auto', md: '600px' }} minH={{ base: '300px', md: '600px' }} display="flex" flexDirection="column">
|
{/* 市场概览仪表盘 */}
|
||||||
<CardHeader pb={{ base: 2, md: 4 }}>
|
<Box mb={4}>
|
||||||
<Flex justify="space-between" align="center">
|
<MarketDashboard />
|
||||||
<HStack>
|
</Box>
|
||||||
<Icon as={FiBarChart2} color="blue.500" boxSize={{ base: 4, md: 5 }} />
|
|
||||||
<Heading size={{ base: 'sm', md: 'md' }}>自选股票</Heading>
|
{/* 投资规划中心 */}
|
||||||
<Badge colorScheme="blue" variant="subtle">
|
<Box mb={4}>
|
||||||
{watchlist.length}
|
<StrategyCenter />
|
||||||
</Badge>
|
</Box>
|
||||||
{quotesLoading && <Spinner size="sm" color="blue.500" />}
|
|
||||||
</HStack>
|
{/* 价值论坛 / 互动中心 */}
|
||||||
<IconButton
|
<Box mb={4}>
|
||||||
icon={<FiPlus />}
|
<ForumCenter />
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => navigate('/stocks')}
|
|
||||||
aria-label="添加自选股"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody pt={0} flex="1" overflowY="auto">
|
|
||||||
{watchlist.length === 0 ? (
|
|
||||||
<Center py={8}>
|
|
||||||
<VStack spacing={3}>
|
|
||||||
<Icon as={FiBarChart2} boxSize={12} color="gray.300" />
|
|
||||||
<Text color={secondaryText} fontSize="sm">
|
|
||||||
暂无自选股
|
|
||||||
</Text>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
colorScheme="blue"
|
|
||||||
onClick={() => navigate('/stocks')}
|
|
||||||
>
|
|
||||||
添加自选股
|
|
||||||
</Button>
|
|
||||||
</VStack>
|
|
||||||
</Center>
|
|
||||||
) : (
|
|
||||||
<VStack align="stretch" spacing={2}>
|
|
||||||
{watchlist.slice(0, 10).map((stock) => (
|
|
||||||
<LinkBox
|
|
||||||
key={stock.stock_code}
|
|
||||||
p={3}
|
|
||||||
borderRadius="md"
|
|
||||||
_hover={{ bg: hoverBg }}
|
|
||||||
transition="all 0.2s"
|
|
||||||
cursor="pointer"
|
|
||||||
>
|
|
||||||
<HStack justify="space-between">
|
|
||||||
<VStack align="start" spacing={0}>
|
|
||||||
<LinkOverlay
|
|
||||||
as={Link}
|
|
||||||
to={`/company/${stock.stock_code}`}
|
|
||||||
>
|
|
||||||
<Text fontWeight="medium" fontSize="sm">
|
|
||||||
{stock.stock_name || stock.stock_code}
|
|
||||||
</Text>
|
|
||||||
</LinkOverlay>
|
|
||||||
<HStack spacing={2}>
|
|
||||||
<Badge variant="subtle" fontSize="xs">
|
|
||||||
{stock.stock_code}
|
|
||||||
</Badge>
|
|
||||||
{realtimeQuotes[stock.stock_code] ? (
|
|
||||||
<Badge
|
|
||||||
colorScheme={realtimeQuotes[stock.stock_code].change_percent > 0 ? 'red' : 'green'}
|
|
||||||
fontSize="xs"
|
|
||||||
>
|
|
||||||
{realtimeQuotes[stock.stock_code].change_percent > 0 ? '+' : ''}
|
|
||||||
{realtimeQuotes[stock.stock_code].change_percent.toFixed(2)}%
|
|
||||||
</Badge>
|
|
||||||
) : stock.change_percent ? (
|
|
||||||
<Badge
|
|
||||||
colorScheme={stock.change_percent > 0 ? 'red' : 'green'}
|
|
||||||
fontSize="xs"
|
|
||||||
>
|
|
||||||
{stock.change_percent > 0 ? '+' : ''}
|
|
||||||
{stock.change_percent}%
|
|
||||||
</Badge>
|
|
||||||
) : null}
|
|
||||||
</HStack>
|
|
||||||
</VStack>
|
|
||||||
<VStack align="end" spacing={0}>
|
|
||||||
<Text fontWeight="bold" fontSize="sm">
|
|
||||||
{realtimeQuotes[stock.stock_code]?.current_price?.toFixed(2) || stock.current_price || '--'}
|
|
||||||
</Text>
|
|
||||||
<Text fontSize="xs" color={secondaryText}>
|
|
||||||
{realtimeQuotes[stock.stock_code]?.update_time || stock.industry || '未分类'}
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
</HStack>
|
|
||||||
</LinkBox>
|
|
||||||
))}
|
|
||||||
{watchlist.length > 10 && (
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => navigate('/stocks')}
|
|
||||||
>
|
|
||||||
查看全部 ({watchlist.length})
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
)}
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</VStack>
|
|
||||||
|
|
||||||
{/* 中列:关注事件 */}
|
|
||||||
<VStack spacing={6} align="stretch" minW={0}>
|
|
||||||
{/* 关注事件 */}
|
|
||||||
<Card bg={cardBg} shadow="md" maxW="100%" height={{ base: 'auto', md: '600px' }} minH={{ base: '300px', md: '600px' }} display="flex" flexDirection="column">
|
|
||||||
<CardHeader pb={{ base: 2, md: 4 }}>
|
|
||||||
<Flex justify="space-between" align="center">
|
|
||||||
<HStack>
|
|
||||||
<Icon as={FiStar} color="yellow.500" boxSize={{ base: 4, md: 5 }} />
|
|
||||||
<Heading size={{ base: 'sm', md: 'md' }}>关注事件</Heading>
|
|
||||||
<Badge colorScheme="yellow" variant="subtle">
|
|
||||||
{followingEvents.length}
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
<IconButton
|
|
||||||
icon={<FiPlus />}
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => navigate('/community')}
|
|
||||||
aria-label="添加关注事件"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody pt={0} flex="1" overflowY="auto">
|
|
||||||
{followingEvents.length === 0 ? (
|
|
||||||
<Center py={8}>
|
|
||||||
<VStack spacing={3}>
|
|
||||||
<Icon as={FiActivity} boxSize={12} color="gray.300" />
|
|
||||||
<Text color={secondaryText} fontSize="sm">
|
|
||||||
暂无关注事件
|
|
||||||
</Text>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
colorScheme="blue"
|
|
||||||
onClick={() => navigate('/community')}
|
|
||||||
>
|
|
||||||
探索事件
|
|
||||||
</Button>
|
|
||||||
</VStack>
|
|
||||||
</Center>
|
|
||||||
) : (
|
|
||||||
<VStack align="stretch" spacing={3}>
|
|
||||||
{followingEvents.slice(0, 5).map((event) => (
|
|
||||||
<LinkBox
|
|
||||||
key={event.id}
|
|
||||||
p={4}
|
|
||||||
borderRadius="lg"
|
|
||||||
border="1px"
|
|
||||||
borderColor={borderColor}
|
|
||||||
_hover={{ shadow: 'md', transform: 'translateY(-2px)' }}
|
|
||||||
transition="all 0.2s"
|
|
||||||
>
|
|
||||||
<VStack align="stretch" spacing={3}>
|
|
||||||
<LinkOverlay
|
|
||||||
as={Link}
|
|
||||||
to={getEventDetailUrl(event.id)}
|
|
||||||
>
|
|
||||||
<Text fontWeight="medium" fontSize="md" noOfLines={2}>
|
|
||||||
{event.title}
|
|
||||||
</Text>
|
|
||||||
</LinkOverlay>
|
|
||||||
|
|
||||||
{/* 事件标签 */}
|
|
||||||
{event.tags && event.tags.length > 0 && (
|
|
||||||
<Wrap>
|
|
||||||
{event.tags.slice(0, 3).map((tag, idx) => (
|
|
||||||
<WrapItem key={idx}>
|
|
||||||
<Tag size="sm" variant="subtle" colorScheme="blue">
|
|
||||||
<TagLabel>{tag}</TagLabel>
|
|
||||||
</Tag>
|
|
||||||
</WrapItem>
|
|
||||||
))}
|
|
||||||
</Wrap>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 事件统计 */}
|
|
||||||
<HStack spacing={4} fontSize="sm" color={secondaryText}>
|
|
||||||
{event.related_avg_chg !== undefined && event.related_avg_chg !== null && (
|
|
||||||
<Badge
|
|
||||||
colorScheme={event.related_avg_chg > 0 ? 'red' : 'green'}
|
|
||||||
variant="subtle"
|
|
||||||
>
|
|
||||||
平均超额 {event.related_avg_chg > 0 ? '+' : ''}{Number(event.related_avg_chg).toFixed(2)}%
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
<HStack spacing={1}>
|
|
||||||
<Icon as={FiUsers} />
|
|
||||||
<Text>{event.follower_count || 0} 关注</Text>
|
|
||||||
</HStack>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{/* 事件信息 */}
|
|
||||||
<Flex justify="space-between" align="center">
|
|
||||||
<HStack spacing={2} fontSize="xs" color={secondaryText}>
|
|
||||||
<Avatar
|
|
||||||
size="xs"
|
|
||||||
name={event.creator?.username || '系统'}
|
|
||||||
src={event.creator?.avatar_url}
|
|
||||||
/>
|
|
||||||
<Text>{event.creator?.username || '系统'}</Text>
|
|
||||||
<Text>·</Text>
|
|
||||||
<Text>{formatDate(event.created_at)}</Text>
|
|
||||||
</HStack>
|
|
||||||
{event.exceed_expectation_score && (
|
|
||||||
<Badge
|
|
||||||
colorScheme={event.exceed_expectation_score > 70 ? 'red' : 'orange'}
|
|
||||||
variant="solid"
|
|
||||||
fontSize="xs"
|
|
||||||
>
|
|
||||||
超预期 {event.exceed_expectation_score}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</VStack>
|
|
||||||
</LinkBox>
|
|
||||||
))}
|
|
||||||
{followingEvents.length > 5 && (
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => navigate('/community')}
|
|
||||||
>
|
|
||||||
查看全部 ({followingEvents.length})
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
)}
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
</VStack>
|
|
||||||
|
|
||||||
{/* 右列:我的评论 */}
|
|
||||||
<VStack spacing={6} align="stretch" minW={0}>
|
|
||||||
{/* 我的评论 */}
|
|
||||||
<Card bg={cardBg} shadow="md" maxW="100%" height={{ base: 'auto', md: '600px' }} minH={{ base: '300px', md: '600px' }} display="flex" flexDirection="column">
|
|
||||||
<CardHeader pb={{ base: 2, md: 4 }}>
|
|
||||||
<Flex justify="space-between" align="center">
|
|
||||||
<HStack>
|
|
||||||
<Icon as={FiMessageSquare} color="purple.500" boxSize={{ base: 4, md: 5 }} />
|
|
||||||
<Heading size={{ base: 'sm', md: 'md' }}>我的评论</Heading>
|
|
||||||
<Badge colorScheme="purple" variant="subtle">
|
|
||||||
{eventComments.length}
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
</Flex>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody pt={0} flex="1" overflowY="auto">
|
|
||||||
{eventComments.length === 0 ? (
|
|
||||||
<Center py={8}>
|
|
||||||
<VStack spacing={3}>
|
|
||||||
<Icon as={FiMessageSquare} boxSize={12} color="gray.300" />
|
|
||||||
<Text color={secondaryText} fontSize="sm">
|
|
||||||
暂无评论记录
|
|
||||||
</Text>
|
|
||||||
<Text color={secondaryText} fontSize="xs" textAlign="center">
|
|
||||||
参与事件讨论,分享您的观点
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
</Center>
|
|
||||||
) : (
|
|
||||||
<VStack align="stretch" spacing={3}>
|
|
||||||
{eventComments.slice(0, 5).map((comment) => (
|
|
||||||
<Box
|
|
||||||
key={comment.id}
|
|
||||||
p={3}
|
|
||||||
borderRadius="md"
|
|
||||||
border="1px"
|
|
||||||
borderColor={borderColor}
|
|
||||||
_hover={{ bg: hoverBg }}
|
|
||||||
transition="all 0.2s"
|
|
||||||
>
|
|
||||||
<VStack align="stretch" spacing={2}>
|
|
||||||
<Text fontSize="sm" noOfLines={3}>
|
|
||||||
{comment.content}
|
|
||||||
</Text>
|
|
||||||
<HStack justify="space-between" fontSize="xs" color={secondaryText} spacing={2}>
|
|
||||||
<HStack flexShrink={0}>
|
|
||||||
<Icon as={FiClock} />
|
|
||||||
<Text>{formatDate(comment.created_at)}</Text>
|
|
||||||
</HStack>
|
|
||||||
{comment.event_title && (
|
|
||||||
<Tooltip label={comment.event_title}>
|
|
||||||
<Badge
|
|
||||||
variant="subtle"
|
|
||||||
fontSize="xs"
|
|
||||||
maxW={{ base: '120px', md: '180px' }}
|
|
||||||
overflow="hidden"
|
|
||||||
textOverflow="ellipsis"
|
|
||||||
whiteSpace="nowrap"
|
|
||||||
>
|
|
||||||
{comment.event_title}
|
|
||||||
</Badge>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</HStack>
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
|
||||||
{eventComments.length > 5 && (
|
|
||||||
<Text fontSize="sm" color={secondaryText} textAlign="center">
|
|
||||||
共 {eventComments.length} 条评论
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
)}
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</VStack>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* 投资规划中心(整合了日历、计划、复盘) */}
|
{/* 投资规划中心(整合了日历、计划、复盘) */}
|
||||||
<Box>
|
<Box>
|
||||||
<InvestmentPlanningCenter />
|
<InvestmentPlanningCenter />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* 右侧固定宽度侧边栏 */}
|
||||||
|
<Box
|
||||||
|
w={{ base: '100%', md: '200px' }}
|
||||||
|
flexShrink={0}
|
||||||
|
display={{ base: 'none', md: 'block' }}
|
||||||
|
position="sticky"
|
||||||
|
top="80px"
|
||||||
|
alignSelf="flex-start"
|
||||||
|
maxH="calc(100vh - 100px)"
|
||||||
|
overflowY="auto"
|
||||||
|
css={{
|
||||||
|
'&::-webkit-scrollbar': { width: '4px' },
|
||||||
|
'&::-webkit-scrollbar-track': { background: 'transparent' },
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
background: 'rgba(212, 175, 55, 0.3)',
|
||||||
|
borderRadius: '2px',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<WatchSidebar
|
||||||
|
watchlist={watchlist}
|
||||||
|
realtimeQuotes={realtimeQuotes}
|
||||||
|
followingEvents={followingEvents}
|
||||||
|
onStockClick={(stock) => navigate(`/company/${stock.stock_code}`)}
|
||||||
|
onEventClick={(event) => navigate(getEventDetailUrl(event.id))}
|
||||||
|
onAddStock={() => navigate('/stocks')}
|
||||||
|
onAddEvent={() => navigate('/community')}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user