update pay function

This commit is contained in:
2025-11-23 09:19:32 +08:00
parent 04c13f3a6c
commit b1d042d0e3
3 changed files with 93 additions and 123 deletions

BIN
public/LOGO_badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom'; import { useSearchParams, useNavigate } from 'react-router-dom';
import { logger } from '../../utils/logger'; import { logger } from '../../utils/logger';
import defaultEventImage from '../../assets/img/default-event.jpg'; import defaultEventImage from '../../assets/img/default-event.jpg';
import companyLogo from '../../../public/LOGO_badge.png';
import { import {
Box, Box,
Container, Container,
@@ -630,46 +631,20 @@ const ConceptCenter = () => {
); );
}; };
// 格式化日期显示 // 格式化添加日期显示
const formatHappenedTimes = (times) => { const formatAddedDate = (concept) => {
if (!times || times.length === 0) return null; // 优先使用 created_at 或 added_date 字段
const addedDate = concept.created_at || concept.added_date || concept.happened_times?.[0];
if (times.length === 1) { if (!addedDate) return null;
return (
<HStack spacing={1}>
<Icon as={CalendarIcon} boxSize={3} color="purple.500" />
<Text fontSize="xs" color="gray.600">{new Date(times[0]).toLocaleDateString('zh-CN')}</Text>
</HStack>
);
}
const sortedTimes = [...times].sort((a, b) => new Date(b) - new Date(a));
const latestDate = new Date(sortedTimes[0]).toLocaleDateString('zh-CN');
return ( return (
<Tooltip <HStack spacing={2}>
label={ <Icon as={CalendarIcon} boxSize={3} color="blue.500" />
<VStack align="start" spacing={1}> <Text fontSize="xs" color="gray.600" fontWeight="medium">
<Text fontWeight="bold">历史爆发日期</Text> 添加于 {new Date(addedDate).toLocaleDateString('zh-CN')}
{sortedTimes.map((time, idx) => ( </Text>
<Text key={idx} fontSize="xs"> </HStack>
{new Date(time).toLocaleDateString('zh-CN')}
</Text>
))}
</VStack>
}
bg="purple.600"
color="white"
borderRadius="md"
p={3}
>
<HStack spacing={2} cursor="pointer">
<Icon as={FaHistory} boxSize={3} color="orange.500" />
<Text fontSize="xs" color="orange.600" fontWeight="medium">
{latestDate} ({times.length})
</Text>
</HStack>
</Tooltip>
); );
}; };
@@ -777,6 +752,25 @@ const ConceptCenter = () => {
))} ))}
</Box> </Box>
{/* 公司 Logo 层 */}
<Box
position="absolute"
top="50%"
left="50%"
transform="translate(-50%, -50%)"
width="120px"
height="120px"
opacity={0.15}
>
<Image
src={companyLogo}
alt="Company Logo"
width="100%"
height="100%"
objectFit="contain"
/>
</Box>
{/* 毛玻璃层 */} {/* 毛玻璃层 */}
<Box <Box
position="absolute" position="absolute"
@@ -808,6 +802,33 @@ const ConceptCenter = () => {
bgGradient="linear(to-r, transparent, rgba(255,255,255,0.5), transparent)" bgGradient="linear(to-r, transparent, rgba(255,255,255,0.5), transparent)"
/> />
{/* 左上角涨跌幅 Badge */}
{hasChange && (
<Badge
position="absolute"
top={3}
left={3}
bg={changeColor === 'red' ? 'red.500' : changeColor === 'green' ? 'green.500' : 'gray.500'}
color="white"
fontSize="sm"
px={3}
py={1}
borderRadius="full"
fontWeight="bold"
boxShadow="0 4px 12px rgba(0, 0, 0, 0.3)"
display="flex"
alignItems="center"
gap={1}
animation={Math.abs(changePercent) > 5 ? `${pulseAnimation} 2s infinite` : 'none'}
>
<Icon
as={changePercent > 0 ? FaArrowUp : changePercent < 0 ? FaArrowDown : null}
boxSize={3}
/>
{formatChangePercent(changePercent)}
</Badge>
)}
{/* 右上角股票数量徽章 */} {/* 右上角股票数量徽章 */}
<Badge <Badge
position="absolute" position="absolute"
@@ -830,7 +851,7 @@ const ConceptCenter = () => {
</Box> </Box>
<CardBody p={4}> <CardBody p={4}>
<VStack align="start" spacing={3}> <VStack align="start" spacing={2}>
{/* 概念名称 */} {/* 概念名称 */}
<Heading <Heading
size="sm" size="sm"
@@ -848,49 +869,6 @@ const ConceptCenter = () => {
{concept.description || '暂无描述信息'} {concept.description || '暂无描述信息'}
</Text> </Text>
{/* 涨跌幅信息卡片 */}
{hasChange && concept.price_info?.trade_date && (
<Box
w="100%"
p={2}
borderRadius="md"
bgGradient={
changePercent > 0
? "linear(to-r, rgba(139, 92, 246, 0.1), rgba(168, 85, 247, 0.05))"
: "linear(to-r, rgba(236, 72, 153, 0.1), rgba(251, 113, 133, 0.05))"
}
border="1px solid"
borderColor={changePercent > 0 ? "purple.200" : "pink.200"}
>
<Flex align="center" justify="space-between">
<HStack spacing={2}>
<Icon
as={FaCalendarAlt}
boxSize={3}
color={changePercent > 0 ? "purple.500" : "pink.500"}
/>
<Text fontSize="xs" color="gray.600">
{new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}
</Text>
</HStack>
<HStack spacing={1}>
<Icon
as={changePercent > 0 ? FaArrowUp : FaArrowDown}
boxSize={3}
color={changePercent > 0 ? "red.500" : "green.500"}
/>
<Text
fontWeight="bold"
fontSize="sm"
color={changePercent > 0 ? "red.500" : "green.500"}
>
{formatChangePercent(changePercent)}
</Text>
</HStack>
</Flex>
</Box>
)}
{concept.stocks && concept.stocks.length > 0 && ( {concept.stocks && concept.stocks.length > 0 && (
<Box <Box
width="100%" width="100%"
@@ -968,7 +946,7 @@ const ConceptCenter = () => {
<Divider borderColor="purple.100" /> <Divider borderColor="purple.100" />
<Flex width="100%" justify="space-between" align="center"> <Flex width="100%" justify="space-between" align="center">
{formatHappenedTimes(concept.happened_times)} {formatAddedDate(concept)}
<Button <Button
size="sm" size="sm"
@@ -1097,7 +1075,7 @@ const ConceptCenter = () => {
</HStack> </HStack>
)} )}
{formatHappenedTimes(concept.happened_times)} {formatAddedDate(concept)}
</HStack> </HStack>
</VStack> </VStack>
</Box> </Box>
@@ -1410,26 +1388,31 @@ const ConceptCenter = () => {
<Box w="100%" maxW="3xl"> <Box w="100%" maxW="3xl">
<VStack spacing={2}> <VStack spacing={2}>
<Box w="100%" position="relative"> <Box w="100%" position="relative">
<HStack <Flex
spacing={0} align="center"
w="100%"
boxShadow="0 8px 32px rgba(0, 0, 0, 0.4)"
borderRadius="full"
overflow="hidden"
bg="rgba(255, 255, 255, 0.95)" bg="rgba(255, 255, 255, 0.95)"
backdropFilter="blur(10px)" backdropFilter="blur(10px)"
border="1px solid" borderRadius="full"
borderColor="whiteAlpha.400" overflow="hidden"
boxShadow="0 8px 32px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(139, 92, 246, 0.2)"
transition="all 0.3s"
_hover={{
boxShadow: '0 12px 40px rgba(139, 92, 246, 0.4), 0 0 0 2px rgba(139, 92, 246, 0.4)',
transform: 'translateY(-2px)',
}}
> >
<InputGroup size="lg" flex={1}> <InputGroup size="lg" flex={1}>
<InputLeftElement pointerEvents="none"> <InputLeftElement pointerEvents="none" h="full">
<SearchIcon color="gray.400" /> <Icon as={SearchIcon} color="purple.400" boxSize={5} />
</InputLeftElement> </InputLeftElement>
<Input <Input
placeholder="搜索概念板块、个股、关键词..." placeholder="搜索概念板块、个股、关键词..."
bg="transparent" bg="transparent"
color="gray.800" color="gray.800"
border="none" border="none"
fontSize="md"
fontWeight="medium"
pl={12}
_placeholder={{ color: 'gray.400' }} _placeholder={{ color: 'gray.400' }}
_focus={{ _focus={{
outline: 'none', outline: 'none',
@@ -1438,12 +1421,12 @@ const ConceptCenter = () => {
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
pr={searchQuery ? "40px" : "16px"} pr={searchQuery ? "50px" : "16px"}
/> />
{searchQuery && ( {searchQuery && (
<IconButton <IconButton
position="absolute" position="absolute"
right="8px" right="10px"
top="50%" top="50%"
transform="translateY(-50%)" transform="translateY(-50%)"
size="sm" size="sm"
@@ -1451,7 +1434,8 @@ const ConceptCenter = () => {
icon={<CloseIcon />} icon={<CloseIcon />}
variant="ghost" variant="ghost"
color="gray.500" color="gray.500"
_hover={{ color: 'gray.700', bg: 'gray.100' }} borderRadius="full"
_hover={{ color: 'gray.700', bg: 'gray.200' }}
onClick={handleClearSearch} onClick={handleClearSearch}
zIndex={1} zIndex={1}
/> />
@@ -1459,28 +1443,33 @@ const ConceptCenter = () => {
</InputGroup> </InputGroup>
<Button <Button
size="lg" size="lg"
borderRadius="0" borderRadius="0 50px 50px 0"
bgGradient="linear(to-r, purple.500, pink.500)" bgGradient="linear(135deg, #667eea 0%, #764ba2 100%)"
color="white" color="white"
leftIcon={<SearchIcon />}
_hover={{ _hover={{
bgGradient: 'linear(to-r, purple.600, pink.600)', bgGradient: 'linear(135deg, #5568d3 0%, #663a8e 100%)',
boxShadow: '0 0 20px rgba(168, 85, 247, 0.4)' transform: 'scale(1.02)',
}} }}
_active={{ _active={{
bgGradient: 'linear(to-r, purple.700, pink.700)', bgGradient: 'linear(135deg, #4a5abf 0%, #58327a 100%)',
transform: 'scale(0.98)',
}} }}
onClick={handleSearch} onClick={handleSearch}
isLoading={loading} isLoading={loading}
loadingText="搜索中" loadingText="搜索中"
px={8} px={8}
minW="120px" minW="140px"
fontWeight="bold"
fontSize="md"
transition="all 0.2s" transition="all 0.2s"
border="none" border="none"
height="100%" height="100%"
boxShadow="inset 0 1px 0 rgba(255, 255, 255, 0.2)"
> >
搜索 搜索
</Button> </Button>
</HStack> </Flex>
</Box> </Box>
{searchQuery && sortBy === '_score' && ( {searchQuery && sortBy === '_score' && (
<Text fontSize="xs" color="cyan.200" opacity={0.9}> <Text fontSize="xs" color="cyan.200" opacity={0.9}>
@@ -1535,6 +1524,7 @@ const ConceptCenter = () => {
<option value="_score">相关度</option> <option value="_score">相关度</option>
<option value="stock_count">股票数量</option> <option value="stock_count">股票数量</option>
<option value="concept_name">概念名称</option> <option value="concept_name">概念名称</option>
<option value="added_date">添加日期</option>
</Select> </Select>
{searchQuery && sortBy === '_score' && ( {searchQuery && sortBy === '_score' && (
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。"> <Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">

View File

@@ -1,20 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
// 只扫描 AgentChat 页面(唯一使用 Hero UI 的地方)
// 使用精确路径,避免误匹配 node_modules
content: [
"./src/views/AgentChat/index.js",
"./src/providers/AppProviders.js", // HeroUIProvider
// HeroUI v3 不再需要扫描 node_modules样式通过 CSS 导入加载
],
darkMode: "class",
theme: {
extend: {},
},
// HeroUI v3 不再需要 plugins样式通过 @import "@heroui/styles" 加载
plugins: [],
}