feat(ForumCenter): 新增价值论坛/互动中心组件

- 我的预测卡片(看涨/看跌投票)
- 社区动态卡片(我发布的/我参与的)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-22 16:51:08 +08:00
parent 10e34d911f
commit bc844bb4dc
4 changed files with 342 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
// 社区动态卡片
import React, { useState } from 'react';
import { Box, Text, VStack, HStack, Icon, Button } from '@chakra-ui/react';
import { Newspaper, Flame, MessageCircle } from 'lucide-react';
const CommunityFeedCard = ({
myPosts = [
{ id: 1, title: '关于新能源车下半场的思考', date: '2025/12/18', replies: 32, isHot: true },
{ id: 2, title: '半导体行业深度分析', date: '2025/12/15', replies: 18, isHot: false },
],
participatedPosts = [
{ id: 3, title: 'AI产业链投资机会分析', date: '2025/12/17', replies: 45, isHot: true },
{ id: 4, title: '消费板块复苏节奏讨论', date: '2025/12/14', replies: 12, isHot: false },
],
onPostClick,
}) => {
const [activeTab, setActiveTab] = useState('my'); // 'my' | 'participated'
const currentPosts = activeTab === 'my' ? myPosts : participatedPosts;
return (
<Box
bg="rgba(26, 26, 46, 0.7)"
borderRadius="lg"
overflow="hidden"
border="1px solid"
borderColor="rgba(212, 175, 55, 0.15)"
backdropFilter="blur(8px)"
>
{/* 标题栏 */}
<HStack
px={4}
py={2}
bg="rgba(15, 15, 26, 0.8)"
borderBottom="1px solid"
borderColor="rgba(212, 175, 55, 0.1)"
>
<Icon as={Newspaper} boxSize={4} color="#3B82F6" />
<Text fontSize="sm" fontWeight="bold" color="rgba(255, 255, 255, 0.95)">
社区动态
</Text>
</HStack>
{/* 内容区 */}
<Box p={4}>
<VStack spacing={3} align="stretch">
{/* Tab 切换 */}
<HStack spacing={4}>
<Button
variant="ghost"
size="sm"
color={activeTab === 'my' ? 'rgba(212, 175, 55, 0.9)' : 'rgba(255, 255, 255, 0.5)'}
fontWeight={activeTab === 'my' ? 'bold' : 'normal'}
_hover={{ color: 'rgba(212, 175, 55, 0.9)' }}
onClick={() => setActiveTab('my')}
px={2}
>
[我发布的]
</Button>
<Button
variant="ghost"
size="sm"
color={activeTab === 'participated' ? 'rgba(212, 175, 55, 0.9)' : 'rgba(255, 255, 255, 0.5)'}
fontWeight={activeTab === 'participated' ? 'bold' : 'normal'}
_hover={{ color: 'rgba(212, 175, 55, 0.9)' }}
onClick={() => setActiveTab('participated')}
px={2}
>
[我参与的]
</Button>
</HStack>
{/* 帖子列表 */}
<VStack spacing={3} align="stretch">
{currentPosts.map((post) => (
<Box
key={post.id}
p={3}
bg="rgba(37, 37, 64, 0.5)"
borderRadius="md"
cursor="pointer"
transition="all 0.2s"
_hover={{
bg: 'rgba(37, 37, 64, 0.8)',
transform: 'translateX(4px)',
}}
onClick={() => onPostClick?.(post)}
>
<Text
fontSize="sm"
fontWeight="medium"
color="rgba(255, 255, 255, 0.9)"
noOfLines={1}
mb={1}
>
{post.title}
</Text>
<HStack spacing={3} fontSize="xs" color="rgba(255, 255, 255, 0.5)">
<Text>{post.date}</Text>
<Text>·</Text>
<HStack spacing={1}>
{post.isHot ? (
<Icon as={Flame} boxSize={3} color="#F97316" />
) : (
<Icon as={MessageCircle} boxSize={3} />
)}
<Text color={post.isHot ? '#F97316' : 'inherit'}>
{post.replies}回复
</Text>
</HStack>
</HStack>
</Box>
))}
</VStack>
</VStack>
</Box>
</Box>
);
};
export default CommunityFeedCard;

View File

@@ -0,0 +1,169 @@
// 我的预测卡片
import React from 'react';
import { Box, Text, VStack, HStack, Button, Icon } from '@chakra-ui/react';
import { Zap, History, TrendingUp, TrendingDown } from 'lucide-react';
const PredictionCard = ({
question = '大A 2025年收盘价?',
myBet = { type: '看涨', points: 500 },
winRate = 58,
odds = 1.8,
onBullish,
onBearish,
onViewHistory,
}) => {
return (
<Box
bg="rgba(26, 26, 46, 0.7)"
borderRadius="lg"
overflow="hidden"
border="1px solid"
borderColor="rgba(212, 175, 55, 0.15)"
backdropFilter="blur(8px)"
>
{/* 标题栏 */}
<HStack
px={4}
py={2}
bg="rgba(15, 15, 26, 0.8)"
borderBottom="1px solid"
borderColor="rgba(212, 175, 55, 0.1)"
>
<Icon as={Zap} boxSize={4} color="#FBBF24" />
<Text fontSize="sm" fontWeight="bold" color="rgba(255, 255, 255, 0.95)">
我的预测
</Text>
</HStack>
{/* 内容区 */}
<Box p={4}>
<VStack spacing={4} align="stretch">
{/* 预测问题 - 带渐变背景 */}
<Box
bg="linear-gradient(135deg, rgba(30, 30, 50, 0.9) 0%, rgba(20, 20, 35, 0.95) 100%)"
borderRadius="lg"
p={4}
textAlign="center"
position="relative"
overflow="hidden"
>
{/* 装饰性弧线 */}
<Box
position="absolute"
top="50%"
left="50%"
transform="translate(-50%, -50%)"
w="120px"
h="60px"
borderRadius="50%"
border="2px solid"
borderColor="rgba(212, 175, 55, 0.2)"
borderBottomColor="transparent"
borderLeftColor="transparent"
/>
<Text
fontSize="lg"
fontWeight="bold"
color="rgba(255, 255, 255, 0.95)"
position="relative"
zIndex={1}
>
{question}
</Text>
{/* 看涨/看跌按钮 */}
<HStack spacing={3} mt={4} justify="center">
<Button
flex={1}
maxW="140px"
h="40px"
bg="linear-gradient(135deg, #DC2626 0%, #EF4444 100%)"
color="white"
fontWeight="bold"
fontSize="md"
borderRadius="full"
_hover={{
bg: 'linear-gradient(135deg, #B91C1C 0%, #DC2626 100%)',
transform: 'scale(1.02)',
}}
_active={{ transform: 'scale(0.98)' }}
leftIcon={<Icon as={TrendingUp} boxSize={4} />}
onClick={onBullish}
>
看涨
</Button>
<Button
flex={1}
maxW="140px"
h="40px"
bg="linear-gradient(135deg, #16A34A 0%, #22C55E 100%)"
color="white"
fontWeight="bold"
fontSize="md"
borderRadius="full"
_hover={{
bg: 'linear-gradient(135deg, #15803D 0%, #16A34A 100%)',
transform: 'scale(1.02)',
}}
_active={{ transform: 'scale(0.98)' }}
leftIcon={<Icon as={TrendingDown} boxSize={4} />}
onClick={onBearish}
>
看跌
</Button>
</HStack>
</Box>
{/* 底部信息 */}
<HStack justify="space-between" fontSize="xs" px={1}>
<HStack spacing={4}>
<HStack spacing={1}>
<Text color="rgba(255, 255, 255, 0.5)">我的下注:</Text>
<Text color="#EF4444" fontWeight="medium">
{myBet.type}
</Text>
<Text color="rgba(212, 175, 55, 0.9)" fontWeight="medium">
{myBet.points}积分
</Text>
</HStack>
</HStack>
</HStack>
<HStack justify="space-between" fontSize="xs" px={1}>
<HStack spacing={4}>
<HStack spacing={1}>
<Text color="rgba(255, 255, 255, 0.5)">当前胜率:</Text>
<Text color="rgba(255, 255, 255, 0.9)" fontWeight="medium">
{winRate}%
</Text>
</HStack>
<HStack spacing={1}>
<Text color="rgba(255, 255, 255, 0.5)">赔率:</Text>
<Text color="rgba(255, 255, 255, 0.9)" fontWeight="medium">
{odds}
</Text>
</HStack>
</HStack>
<Button
size="xs"
variant="ghost"
color="rgba(255, 255, 255, 0.6)"
leftIcon={<Icon as={History} boxSize={3} />}
_hover={{
color: 'rgba(212, 175, 55, 0.9)',
bg: 'rgba(212, 175, 55, 0.1)',
}}
onClick={onViewHistory}
>
历史战绩
</Button>
</HStack>
</VStack>
</Box>
</Box>
);
};
export default PredictionCard;

View File

@@ -0,0 +1,3 @@
// 价值论坛子组件导出
export { default as PredictionCard } from './PredictionCard';
export { default as CommunityFeedCard } from './CommunityFeedCard';

View File

@@ -0,0 +1,49 @@
// 价值论坛 / 互动中心组件 (Forum Center)
import React from 'react';
import { Box, Text, HStack, SimpleGrid, Icon } from '@chakra-ui/react';
import { MessageCircle } from 'lucide-react';
import GlassCard from '@components/GlassCard';
import { PredictionCard, CommunityFeedCard } from './components';
const ForumCenter = () => {
return (
<GlassCard
variant="transparent"
rounded="2xl"
padding="md"
hoverable={false}
cornerDecor
>
{/* 标题栏 */}
<HStack mb={4} spacing={2}>
<Icon
as={MessageCircle}
boxSize={5}
color="rgba(212, 175, 55, 0.9)"
/>
<Text
fontSize="lg"
fontWeight="bold"
color="rgba(255, 255, 255, 0.95)"
letterSpacing="wide"
>
价值论坛 / 互动中心
</Text>
<Box
h="1px"
flex={1}
bgGradient="linear(to-r, rgba(212, 175, 55, 0.4), transparent)"
ml={2}
/>
</HStack>
{/* 两列布局:预测卡片 + 社区动态 */}
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={4}>
<PredictionCard />
<CommunityFeedCard />
</SimpleGrid>
</GlassCard>
);
};
export default ForumCenter;