/** * 预测话题卡片组件 * 展示预测市场的话题概览 */ import React, { useMemo, useState, useEffect } from 'react'; import { Box, Text, HStack, VStack, Badge, Progress, Flex, Avatar, Icon, } from '@chakra-ui/react'; import { motion } from 'framer-motion'; import { TrendingUp, TrendingDown, Crown, Users, Coins, Zap, Lock, CheckCircle2, } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { forumColors } from '@theme/forumTheme'; import CountdownTimer, { useCountdown } from './CountdownTimer'; const MotionBox = motion(Box); const PredictionTopicCard = ({ topic }) => { const navigate = useNavigate(); // 使用倒计时 Hook 获取实时状态 const timeLeft = useCountdown(topic.deadline); // 处理卡片点击 const handleCardClick = () => { navigate(`/value-forum/prediction/${topic.id}`); }; // 格式化数字 const formatNumber = (num) => { if (num >= 10000) return `${(num / 10000).toFixed(1)}万`; if (num >= 1000) return `${(num / 1000).toFixed(1)}K`; return num; }; // 计算实际状态(基于截止时间自动判断) const [effectiveStatus, setEffectiveStatus] = useState(topic.status); useEffect(() => { // 如果已经是结算状态,保持不变 if (topic.status === 'settled') { setEffectiveStatus('settled'); return; } // 如果已过截止时间,自动变为已截止 if (timeLeft.expired && topic.status === 'active') { setEffectiveStatus('trading_closed'); return; } setEffectiveStatus(topic.status); }, [topic.status, timeLeft.expired]); // 获取选项数据 const yesData = topic.positions?.yes || { total_shares: 0, current_price: 500, lord_id: null }; const noData = topic.positions?.no || { total_shares: 0, current_price: 500, lord_id: null }; // 计算总份额 const totalShares = yesData.total_shares + noData.total_shares; // 计算百分比 const yesPercent = totalShares > 0 ? (yesData.total_shares / totalShares) * 100 : 50; const noPercent = totalShares > 0 ? (noData.total_shares / totalShares) * 100 : 50; // 状态颜色(使用 effectiveStatus) const statusColorMap = { active: forumColors.success[500], trading_closed: forumColors.warning[500], settled: forumColors.text.secondary, }; const statusLabelMap = { active: '交易中', trading_closed: '等待结算', settled: '已结算', }; const statusIconMap = { active: Zap, trading_closed: Lock, settled: CheckCircle2, }; return ( {/* 头部:状态标识 */} {statusLabelMap[effectiveStatus]} {effectiveStatus === 'active' ? '可交易' : effectiveStatus === 'trading_closed' ? '待结算' : '已完成'} {/* 内容区域 */} {/* 话题标题 */} {topic.title} {/* 描述 */} {topic.description && ( {topic.description} )} {/* 双向价格卡片 */} {/* Yes 方 */} {/* 领主徽章 */} {yesData.lord_id && ( )} 看涨 / Yes {Math.round(yesData.current_price)} 积分 {yesData.total_shares}份 · {yesPercent.toFixed(0)}% {/* No 方 */} {/* 领主徽章 */} {noData.lord_id && ( )} 看跌 / No {Math.round(noData.current_price)} 积分 {noData.total_shares}份 · {noPercent.toFixed(0)}% {/* 市场情绪进度条 */} 市场情绪 {yesPercent.toFixed(0)}% vs {noPercent.toFixed(0)}% div': { bg: 'linear-gradient(90deg, #48BB78 0%, #38A169 100%)', }, }} /> {/* 奖池和数据 */} {formatNumber(topic.total_pool)} 奖池 {topic.participants_count || topic.stats?.unique_traders?.size || 0}人 {/* 使用新的倒计时组件 */} {/* 底部:作者信息 */} {topic.author_name} {/* 分类标签 */} {topic.category && ( {topic.category} )} ); }; export default PredictionTopicCard;