style(EventCard): 事件卡片布局优化

- 投票按钮移至标题行右侧,红绿胶囊合并样式
- 浏览量图标换为 lucide Eye icon
- 浏览/收藏绝对定位到卡片右下角
- 收藏按钮改为深色胶囊背景+金色星星

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2026-01-15 16:31:39 +08:00
parent c6d7ac5d41
commit ed9f7ddabe
2 changed files with 132 additions and 115 deletions

View File

@@ -25,7 +25,7 @@ import {
} from './atoms'; } from './atoms';
import StockChangeIndicators from '@components/StockChangeIndicators'; import StockChangeIndicators from '@components/StockChangeIndicators';
import { GLASS_BLUR } from '@/constants/glassConfig'; import { GLASS_BLUR } from '@/constants/glassConfig';
import { TrendingUp, TrendingDown } from 'lucide-react'; import { TrendingUp, TrendingDown, Eye } from 'lucide-react';
// 数字格式化8600 → 8.6k // 数字格式化8600 → 8.6k
const formatCompactNumber = (num) => { const formatCompactNumber = (num) => {
@@ -206,127 +206,142 @@ const HorizontalDynamicNewsEventCard = React.memo(({
<VStack align="stretch" spacing={2}> <VStack align="stretch" spacing={2}>
{/* 第一行:概念标签 + 标题(内联布局) */} {/* 第一行:概念标签 + 标题 + 投票按钮 */}
<Tooltip <HStack justify="space-between" align="flex-start" spacing={2}>
label={event.title} {/* 左侧:概念 + 标题 */}
placement="top" <Tooltip
hasArrow label={event.title}
bg="gray.700" placement="top"
color="white" hasArrow
fontSize="sm" bg="gray.700"
p={2} color="white"
borderRadius="md" fontSize="sm"
isDisabled={event.title.length < 40} p={2}
> borderRadius="md"
<Box isDisabled={event.title.length < 40}
cursor="pointer"
onClick={(e) => onTitleClick?.(e, event)}
mt={1}
paddingLeft={isMobile ? '70px' : undefined}
lineHeight="1.6"
css={{
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
}}
> >
{/* 概念标签(内联) */} <Box
{conceptLabel && ( flex="1"
<Badge cursor="pointer"
as="span" onClick={(e) => onTitleClick?.(e, event)}
colorScheme="purple" mt={1}
fontSize="xs" paddingLeft={isMobile ? '70px' : undefined}
borderRadius="md" lineHeight="1.6"
px={1.5} css={{
py={0.5} display: '-webkit-box',
mr={1.5} WebkitLineClamp: 2,
verticalAlign="middle" WebkitBoxOrient: 'vertical',
> overflow: 'hidden',
{conceptLabel} }}
</Badge>
)}
{/* 标题(内联) */}
<Text
as="span"
fontSize={titleFontSize}
fontWeight="semibold"
color={linkColor}
_hover={{ textDecoration: 'underline' }}
> >
{event.title} {/* 概念标签(内联) */}
</Text> {conceptLabel && (
</Box> <Badge
</Tooltip> as="span"
colorScheme="purple"
fontSize="xs"
borderRadius="md"
px={1.5}
py={0.5}
mr={1.5}
verticalAlign="middle"
>
{conceptLabel}
</Badge>
)}
{/* 标题(内联) */}
<Text
as="span"
fontSize={titleFontSize}
fontWeight="semibold"
color={linkColor}
_hover={{ textDecoration: 'underline' }}
>
{event.title}
</Text>
</Box>
</Tooltip>
{/* 底部:左侧涨跌幅 + 右侧工具栏 */} {/* 右侧:投票按钮(紧密相连的圆角矩形) */}
<HStack justify="space-between" align="center" w="full" pt={1}> <HStack spacing={0} flexShrink={0} mt={1} borderRadius="lg" overflow="hidden" onClick={(e) => e.stopPropagation()}>
{/* 左侧:涨跌幅指标(保持默认样式) */} {/* 看涨 - 左半边 */}
<Tooltip label="看涨" placement="top" hasArrow>
<VStack
as="button"
bg="#C53030"
color="white"
px={3}
py={1.5}
spacing={0}
_hover={{ bg: '#9B2C2C' }}
transition="all 0.2s"
onClick={() => onVoteChange?.({ eventId: event.id, voteType: 'bullish' })}
>
<HStack spacing={1}>
<TrendingUp size={16} />
<Text fontSize="sm" fontWeight="semibold">{formatCompactNumber(event.bullish_count)}</Text>
</HStack>
<Text fontSize="xs">看涨</Text>
</VStack>
</Tooltip>
{/* 看跌 - 右半边 */}
<Tooltip label="看跌" placement="top" hasArrow>
<VStack
as="button"
bg="#38A169"
color="white"
px={3}
py={1.5}
spacing={0}
_hover={{ bg: '#2F855A' }}
transition="all 0.2s"
onClick={() => onVoteChange?.({ eventId: event.id, voteType: 'bearish' })}
>
<HStack spacing={1}>
<TrendingDown size={16} />
<Text fontSize="sm" fontWeight="semibold">{formatCompactNumber(event.bearish_count)}</Text>
</HStack>
<Text fontSize="xs">看跌</Text>
</VStack>
</Tooltip>
</HStack>
</HStack>
{/* 第二行:涨跌幅指标 */}
<Box pt={1}>
<StockChangeIndicators <StockChangeIndicators
avgChange={event.related_avg_chg} avgChange={event.related_avg_chg}
maxChange={event.related_max_chg} maxChange={event.related_max_chg}
expectationScore={event.expectation_score || event.expectation_surprise_score} expectationScore={event.expectation_score || event.expectation_surprise_score}
size="default" size="default"
/> />
</Box>
{/* 右侧:工具栏 */} {/* 右下角:浏览 + 收藏(绝对定位) */}
<HStack spacing={1} align="center" onClick={(e) => e.stopPropagation()}> <HStack
{/* 浏览量 - 上下结构 */} position="absolute"
<VStack spacing={0} align="center"> bottom={2}
<Text fontSize="xs" color="gray.400">👁</Text> right={2}
<Text fontSize="2xs" color="gray.400">{formatCompactNumber(event.view_count)}</Text> spacing={3}
</VStack> onClick={(e) => e.stopPropagation()}
>
{/* 收藏按钮 - 上下结构 */} {/* 浏览量 */}
<EventFollowButton <HStack spacing={0.5} color="gray.400">
isFollowing={isFollowing} <Eye size={16} />
followerCount={followerCount} <Text fontSize="xs">{formatCompactNumber(event.view_count)}</Text>
onToggle={() => onToggleFollow?.(event.id)}
size="sm"
showCount={true}
variant="minimal"
layout="vertical"
/>
{/* 合并投票按钮 - 左红右绿,上图标下文字 */}
<HStack spacing={0} borderRadius="md" overflow="hidden">
{/* 看涨 - 红色左半边 */}
<Tooltip label="看涨" placement="top" hasArrow>
<VStack
as="button"
bg="#C53030"
color="white"
px={2}
py={1}
spacing={0}
_hover={{ bg: '#9B2C2C' }}
transition="all 0.2s"
onClick={() => onVoteChange?.({ eventId: event.id, voteType: 'bullish' })}
>
<TrendingUp size={14} />
<Text fontSize="2xs" fontWeight="semibold">{formatCompactNumber(event.bullish_count)}</Text>
</VStack>
</Tooltip>
{/* 看跌 - 绿色右半边 */}
<Tooltip label="看跌" placement="top" hasArrow>
<VStack
as="button"
bg="#38A169"
color="white"
px={2}
py={1}
spacing={0}
_hover={{ bg: '#2F855A' }}
transition="all 0.2s"
onClick={() => onVoteChange?.({ eventId: event.id, voteType: 'bearish' })}
>
<TrendingDown size={14} />
<Text fontSize="2xs" fontWeight="semibold">{formatCompactNumber(event.bearish_count)}</Text>
</VStack>
</Tooltip>
</HStack>
</HStack> </HStack>
{/* 收藏按钮 */}
<EventFollowButton
isFollowing={isFollowing}
followerCount={followerCount}
onToggle={() => onToggleFollow?.(event.id)}
size="sm"
showCount={true}
variant="minimal"
layout="horizontal"
/>
</HStack> </HStack>
</VStack> </VStack>
</CardBody> </CardBody>

View File

@@ -39,18 +39,20 @@ const EventFollowButton = ({
<Tooltip label={isFollowing ? '取消关注' : '关注事件'} hasArrow placement="bottom"> <Tooltip label={isFollowing ? '取消关注' : '关注事件'} hasArrow placement="bottom">
<Stack <Stack
as="button" as="button"
spacing={isVertical ? 0 : 1.5} spacing={isVertical ? 0 : 1}
px={isVertical ? 2 : 3} px={isVertical ? 2 : 3}
py={isVertical ? 1 : 1.5} py={isVertical ? 1 : 1.5}
bg="rgba(50, 50, 60, 0.9)"
borderRadius="full"
cursor="pointer" cursor="pointer"
onClick={handleClick} onClick={handleClick}
align="center" align="center"
_hover={{ bg: 'rgba(255, 255, 255, 0.1)' }} _hover={{ bg: 'rgba(70, 70, 80, 0.95)' }}
transition="all 0.2s" transition="all 0.2s"
> >
<Star <Star
size={isVertical ? '14px' : iconSize} size={isVertical ? '14px' : iconSize}
color={isFollowing ? "#FFD700" : "#A0AEC0"} color="#FFD700"
fill={isFollowing ? "#FFD700" : "none"} fill={isFollowing ? "#FFD700" : "none"}
style={{ transition: 'all 0.2s' }} style={{ transition: 'all 0.2s' }}
/> />
@@ -58,7 +60,7 @@ const EventFollowButton = ({
<Text <Text
fontSize={isVertical ? "2xs" : "sm"} fontSize={isVertical ? "2xs" : "sm"}
fontWeight="semibold" fontWeight="semibold"
color={isFollowing ? "yellow.400" : "gray.400"} color={isFollowing ? "yellow.400" : "yellow.500"}
> >
{followerCount || 0} {followerCount || 0}
</Text> </Text>