update pay function

This commit is contained in:
2025-11-23 18:11:48 +08:00
parent b582de9bc2
commit 7b3907a3bd
9 changed files with 3229 additions and 91 deletions

View File

@@ -22,26 +22,38 @@ import {
useDisclosure,
Flex,
Badge,
Tabs,
TabList,
TabPanels,
Tab,
TabPanel,
Icon,
} from '@chakra-ui/react';
import { Search, PenSquare, TrendingUp, Clock, Heart } from 'lucide-react';
import { Search, PenSquare, TrendingUp, Clock, Heart, Zap } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { forumColors } from '@theme/forumTheme';
import { getPosts, searchPosts } from '@services/elasticsearchService';
import { getTopics } from '@services/predictionMarketService';
import PostCard from './components/PostCard';
import PredictionTopicCard from './components/PredictionTopicCard';
import CreatePostModal from './components/CreatePostModal';
import CreatePredictionModal from './components/CreatePredictionModal';
const MotionBox = motion(Box);
const ValueForum = () => {
const [posts, setPosts] = useState([]);
const [predictionTopics, setPredictionTopics] = useState([]);
const [loading, setLoading] = useState(true);
const [searchKeyword, setSearchKeyword] = useState('');
const [sortBy, setSortBy] = useState('created_at');
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [hasMore, setHasMore] = useState(true);
const [activeTab, setActiveTab] = useState(0);
const { isOpen, onOpen, onClose } = useDisclosure();
const { isOpen: isPostModalOpen, onOpen: onPostModalOpen, onClose: onPostModalClose } = useDisclosure();
const { isOpen: isPredictionModalOpen, onOpen: onPredictionModalOpen, onClose: onPredictionModalClose } = useDisclosure();
// 获取帖子列表
const fetchPosts = async (currentPage = 1, reset = false) => {
@@ -78,10 +90,27 @@ const ValueForum = () => {
}
};
// 获取预测话题列表
const fetchPredictionTopics = () => {
try {
setLoading(true);
const topics = getTopics({ status: 'active', sortBy });
setPredictionTopics(topics);
} catch (error) {
console.error('获取预测话题失败:', error);
} finally {
setLoading(false);
}
};
// 初始化加载
useEffect(() => {
fetchPosts(1, true);
}, [sortBy]);
if (activeTab === 0) {
fetchPosts(1, true);
} else {
fetchPredictionTopics();
}
}, [sortBy, activeTab]);
// 搜索处理
const handleSearch = () => {
@@ -102,6 +131,11 @@ const ValueForum = () => {
fetchPosts(1, true);
};
// 预测话题创建成功回调
const handlePredictionCreated = (newTopic) => {
setPredictionTopics((prev) => [newTopic, ...prev]);
};
// 排序选项
const sortOptions = [
{ value: 'created_at', label: '最新发布', icon: Clock },
@@ -143,21 +177,41 @@ const ValueForum = () => {
</VStack>
{/* 发帖按钮 */}
<Button
leftIcon={<PenSquare size={18} />}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
size="lg"
fontWeight="bold"
onClick={onOpen}
_hover={{
transform: 'translateY(-2px)',
boxShadow: forumColors.shadows.goldHover,
}}
_active={{ transform: 'translateY(0)' }}
>
发布帖子
</Button>
<HStack spacing="3">
<Button
leftIcon={<PenSquare size={18} />}
bg={forumColors.background.card}
color={forumColors.text.primary}
size="lg"
fontWeight="bold"
border="1px solid"
borderColor={forumColors.border.default}
onClick={onPostModalOpen}
_hover={{
transform: 'translateY(-2px)',
borderColor: forumColors.border.gold,
}}
_active={{ transform: 'translateY(0)' }}
>
发布帖子
</Button>
<Button
leftIcon={<Zap size={18} />}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
size="lg"
fontWeight="bold"
onClick={onPredictionModalOpen}
_hover={{
transform: 'translateY(-2px)',
boxShadow: forumColors.shadows.goldHover,
}}
_active={{ transform: 'translateY(0)' }}
>
发起预测
</Button>
</HStack>
</Flex>
{/* 搜索和筛选栏 */}
@@ -224,86 +278,190 @@ const ValueForum = () => {
</VStack>
</MotionBox>
{/* 帖子网格 */}
{loading && page === 1 ? (
<Center py="20">
<VStack spacing="4">
<Spinner
size="xl"
thickness="4px"
speed="0.8s"
color={forumColors.primary[500]}
/>
<Text color={forumColors.text.secondary}>加载中...</Text>
</VStack>
</Center>
) : posts.length === 0 ? (
<Center py="20">
<VStack spacing="4">
<Text color={forumColors.text.secondary} fontSize="lg">
{searchKeyword ? '未找到相关帖子' : '暂无帖子,快来发布第一篇吧!'}
</Text>
{!searchKeyword && (
<Button
leftIcon={<PenSquare size={18} />}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
onClick={onOpen}
_hover={{ opacity: 0.9 }}
{/* 标签页 */}
<Tabs
index={activeTab}
onChange={setActiveTab}
variant="soft-rounded"
colorScheme="yellow"
>
<TabList mb="8" bg={forumColors.background.card} p="2" borderRadius="xl">
<Tab
_selected={{
bg: forumColors.gradients.goldPrimary,
color: forumColors.background.main,
}}
>
<HStack spacing="2">
<Icon as={PenSquare} boxSize="16px" />
<Text>社区帖子</Text>
</HStack>
</Tab>
<Tab
_selected={{
bg: forumColors.gradients.goldPrimary,
color: forumColors.background.main,
}}
>
<HStack spacing="2">
<Icon as={Zap} boxSize="16px" />
<Text>预测市场</Text>
<Badge
bg="red.500"
color="white"
borderRadius="full"
px="2"
fontSize="xs"
>
发布帖子
</Button>
)}
</VStack>
</Center>
) : (
<>
<SimpleGrid columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing="6">
<AnimatePresence>
{posts.map((post, index) => (
<MotionBox
key={post.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, delay: index * 0.05 }}
>
<PostCard post={post} />
</MotionBox>
))}
</AnimatePresence>
</SimpleGrid>
NEW
</Badge>
</HStack>
</Tab>
</TabList>
{/* 加载更多按钮 */}
{hasMore && (
<Center mt="10">
<Button
onClick={loadMore}
isLoading={loading}
loadingText="加载中..."
bg={forumColors.background.card}
color={forumColors.text.primary}
border="1px solid"
borderColor={forumColors.border.default}
_hover={{
borderColor: forumColors.border.gold,
bg: forumColors.background.hover,
}}
>
加载更多
</Button>
</Center>
)}
</>
)}
<TabPanels>
{/* 普通帖子标签页 */}
<TabPanel p="0">
{loading && page === 1 ? (
<Center py="20">
<VStack spacing="4">
<Spinner
size="xl"
thickness="4px"
speed="0.8s"
color={forumColors.primary[500]}
/>
<Text color={forumColors.text.secondary}>加载中...</Text>
</VStack>
</Center>
) : posts.length === 0 ? (
<Center py="20">
<VStack spacing="4">
<Text color={forumColors.text.secondary} fontSize="lg">
{searchKeyword ? '未找到相关帖子' : '暂无帖子,快来发布第一篇吧!'}
</Text>
{!searchKeyword && (
<Button
leftIcon={<PenSquare size={18} />}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
onClick={onPostModalOpen}
_hover={{ opacity: 0.9 }}
>
发布帖子
</Button>
)}
</VStack>
</Center>
) : (
<>
<SimpleGrid columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing="6">
<AnimatePresence>
{posts.map((post, index) => (
<MotionBox
key={post.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, delay: index * 0.05 }}
>
<PostCard post={post} />
</MotionBox>
))}
</AnimatePresence>
</SimpleGrid>
{/* 加载更多按钮 */}
{hasMore && (
<Center mt="10">
<Button
onClick={loadMore}
isLoading={loading}
loadingText="加载中..."
bg={forumColors.background.card}
color={forumColors.text.primary}
border="1px solid"
borderColor={forumColors.border.default}
_hover={{
borderColor: forumColors.border.gold,
bg: forumColors.background.hover,
}}
>
加载更多
</Button>
</Center>
)}
</>
)}
</TabPanel>
{/* 预测市场标签页 */}
<TabPanel p="0">
{loading ? (
<Center py="20">
<VStack spacing="4">
<Spinner
size="xl"
thickness="4px"
speed="0.8s"
color={forumColors.primary[500]}
/>
<Text color={forumColors.text.secondary}>加载中...</Text>
</VStack>
</Center>
) : predictionTopics.length === 0 ? (
<Center py="20">
<VStack spacing="4">
<Icon as={Zap} boxSize="48px" color={forumColors.text.tertiary} />
<Text color={forumColors.text.secondary} fontSize="lg">
暂无预测话题快来发起第一个吧
</Text>
<Button
leftIcon={<Zap size={18} />}
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
onClick={onPredictionModalOpen}
_hover={{ opacity: 0.9 }}
>
发起预测
</Button>
</VStack>
</Center>
) : (
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing="6">
<AnimatePresence>
{predictionTopics.map((topic, index) => (
<MotionBox
key={topic.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, delay: index * 0.05 }}
>
<PredictionTopicCard topic={topic} />
</MotionBox>
))}
</AnimatePresence>
</SimpleGrid>
)}
</TabPanel>
</TabPanels>
</Tabs>
</Container>
{/* 发帖模态框 */}
<CreatePostModal
isOpen={isOpen}
onClose={onClose}
isOpen={isPostModalOpen}
onClose={onPostModalClose}
onPostCreated={handlePostCreated}
/>
{/* 发起预测模态框 */}
<CreatePredictionModal
isOpen={isPredictionModalOpen}
onClose={onPredictionModalClose}
onTopicCreated={handlePredictionCreated}
/>
</Box>
);
};