update pay function
This commit is contained in:
BIN
public/LOGO_badge.png
Normal file
BIN
public/LOGO_badge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -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 key={idx} fontSize="xs">
|
|
||||||
{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>
|
</Text>
|
||||||
</HStack>
|
</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="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
|
||||||
|
|||||||
@@ -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: [],
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user