update pay ui

This commit is contained in:
2025-12-03 13:43:55 +08:00
parent 9a6230e51e
commit 51ed56726c
5 changed files with 51 additions and 116 deletions

4
app.py
View File

@@ -5601,6 +5601,8 @@ def get_historical_event_stocks(event_id):
if event_trading_date:
try:
# 查询股票在事件对应交易日的数据
# ea_dailyline 表的 seccode 不带后缀,需要去掉 .SH/.SZ 后缀
base_stock_code = stock.stock_code.split('.')[0] if stock.stock_code else ''
with engine.connect() as conn:
query = text("""
SELECT close_price, change_pct
@@ -5612,7 +5614,7 @@ def get_historical_event_stocks(event_id):
""")
result = conn.execute(query, {
'stock_code': stock.stock_code,
'stock_code': base_stock_code,
'trading_date': event_trading_date
}).fetchone()

View File

@@ -2,7 +2,8 @@
import React, { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import * as echarts from 'echarts';
import { stockService } from '@services/eventService';
import dayjs from 'dayjs';
import { klineDataCache, getCacheKey, fetchKlineData } from '@views/Community/components/StockDetailPanel/utils/klineDataCache';
/**
* 股票信息
@@ -63,7 +64,7 @@ const KLineChartModal: React.FC<KLineChartModalProps> = ({
error
});
// 加载K线数据
// 加载K线数据(优先使用缓存)
const loadData = async () => {
if (!stock?.stock_code) return;
@@ -71,20 +72,30 @@ const KLineChartModal: React.FC<KLineChartModalProps> = ({
setError(null);
try {
const response = await stockService.getKlineData(
stock.stock_code,
'daily',
eventTime || undefined
);
// 标准化事件时间
const stableEventTime = eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : '';
console.log('[KLineChartModal] API响应:', response);
// 先检查缓存
const cacheKey = getCacheKey(stock.stock_code, stableEventTime, 'daily');
const cachedData = klineDataCache.get(cacheKey);
if (!response || !response.data || response.data.length === 0) {
if (cachedData && cachedData.length > 0) {
console.log('[KLineChartModal] 使用缓存数据, 数据条数:', cachedData.length);
setData(cachedData);
setLoading(false);
return;
}
// 缓存没有则请求(会自动存入缓存)
console.log('[KLineChartModal] 缓存未命中,发起请求');
const result = await fetchKlineData(stock.stock_code, stableEventTime, 'daily');
if (!result || result.length === 0) {
throw new Error('暂无K线数据');
}
console.log('[KLineChartModal] 数据条数:', response.data.length);
setData(response.data);
console.log('[KLineChartModal] 数据条数:', result.length);
setData(result);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : '数据加载失败';
setError(errorMsg);

View File

@@ -17,7 +17,8 @@ import {
AlertIcon,
} from '@chakra-ui/react';
import * as echarts from 'echarts';
import { stockService } from '@services/eventService';
import dayjs from 'dayjs';
import { klineDataCache, getCacheKey, fetchKlineData } from '@views/Community/components/StockDetailPanel/utils/klineDataCache';
/**
* 股票信息
@@ -67,7 +68,7 @@ const TimelineChartModal: React.FC<TimelineChartModalProps> = ({
const [error, setError] = useState<string | null>(null);
const [data, setData] = useState<TimelineDataPoint[]>([]);
// 加载分时图数据
// 加载分时图数据(优先使用缓存)
const loadData = async () => {
if (!stock?.stock_code) return;
@@ -75,20 +76,30 @@ const TimelineChartModal: React.FC<TimelineChartModalProps> = ({
setError(null);
try {
const response = await stockService.getKlineData(
stock.stock_code,
'timeline',
eventTime || undefined
);
// 标准化事件时间
const stableEventTime = eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : '';
console.log('[TimelineChartModal] API响应:', response);
// 先检查缓存
const cacheKey = getCacheKey(stock.stock_code, stableEventTime, 'timeline');
const cachedData = klineDataCache.get(cacheKey);
if (!response || !response.data || response.data.length === 0) {
if (cachedData && cachedData.length > 0) {
console.log('[TimelineChartModal] 使用缓存数据, 数据条数:', cachedData.length);
setData(cachedData);
setLoading(false);
return;
}
// 缓存没有则请求(会自动存入缓存)
console.log('[TimelineChartModal] 缓存未命中,发起请求');
const result = await fetchKlineData(stock.stock_code, stableEventTime, 'timeline');
if (!result || result.length === 0) {
throw new Error('暂无分时数据');
}
console.log('[TimelineChartModal] 数据条数:', response.data.length);
setData(response.data);
console.log('[TimelineChartModal] 数据条数:', result.length);
setData(result);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : '数据加载失败';
setError(errorMsg);

View File

@@ -14,12 +14,9 @@ import {
Center,
Wrap,
WrapItem,
Icon,
Progress,
useColorModeValue,
useToast,
} from '@chakra-ui/react';
import { FaChartLine } from 'react-icons/fa';
import { getImportanceConfig } from '../../../../constants/importanceLevels';
import { eventService } from '../../../../services/eventService';
import { useEventStocks } from '../StockDetailPanel/hooks/useEventStocks';
@@ -338,76 +335,6 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
{/* 事件描述 */}
<EventDescriptionSection description={event.description} />
{/* 超预期得分显示 - 参考历史事件对比的样式 */}
{expectationScore != null && expectationScore > 0 && (
<Box
p={3}
bg={useColorModeValue(
expectationScore >= 60 ? 'red.50' : expectationScore >= 40 ? 'orange.50' : 'yellow.50',
expectationScore >= 60 ? 'red.900' : expectationScore >= 40 ? 'orange.900' : 'yellow.900'
)}
borderColor={useColorModeValue(
expectationScore >= 60 ? 'red.200' : expectationScore >= 40 ? 'orange.200' : 'yellow.200',
expectationScore >= 60 ? 'red.700' : expectationScore >= 40 ? 'orange.700' : 'yellow.700'
)}
borderWidth="1px"
borderRadius="md"
>
<HStack spacing={3} justify="space-between">
<HStack spacing={2}>
<Icon
as={FaChartLine}
color={useColorModeValue(
expectationScore >= 60 ? 'red.600' : expectationScore >= 40 ? 'orange.600' : 'yellow.600',
expectationScore >= 60 ? 'red.300' : expectationScore >= 40 ? 'orange.300' : 'yellow.300'
)}
boxSize="18px"
/>
<Text
fontSize="sm"
fontWeight="bold"
color={useColorModeValue(
expectationScore >= 60 ? 'red.700' : expectationScore >= 40 ? 'orange.700' : 'yellow.800',
expectationScore >= 60 ? 'red.200' : expectationScore >= 40 ? 'orange.200' : 'yellow.200'
)}
>
超预期得分
</Text>
</HStack>
<HStack spacing={3} flex={1} maxW="200px">
<Progress
value={expectationScore}
max={100}
size="sm"
flex={1}
colorScheme={expectationScore >= 60 ? 'red' : expectationScore >= 40 ? 'orange' : 'yellow'}
borderRadius="full"
bg={useColorModeValue('gray.200', 'gray.600')}
/>
<Text
fontSize="lg"
fontWeight="bold"
color={useColorModeValue(
expectationScore >= 60 ? 'red.600' : expectationScore >= 40 ? 'orange.600' : 'yellow.700',
expectationScore >= 60 ? 'red.300' : expectationScore >= 40 ? 'orange.300' : 'yellow.300'
)}
minW="40px"
textAlign="right"
>
{expectationScore}
</Text>
</HStack>
</HStack>
<Text
fontSize="xs"
color={useColorModeValue('gray.600', 'gray.400')}
mt={1}
>
基于历史事件判断当前事件的超预期情况满分100分
</Text>
</Box>
)}
{/* 相关股票(可折叠) - 懒加载 - 需要 PRO 权限 - 支持精简/详细模式 */}
<CollapsibleSection
title="相关股票"

View File

@@ -1,6 +1,5 @@
// src/views/EventDetail/components/HistoricalEvents.js
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Box,
VStack,
@@ -21,7 +20,6 @@ import {
ModalHeader,
ModalCloseButton,
ModalBody,
Link,
Flex,
Collapse
} from '@chakra-ui/react';
@@ -42,8 +40,6 @@ const HistoricalEvents = ({
loading = false,
error = null
}) => {
const navigate = useNavigate();
// 状态管理
const [selectedEventForStocks, setSelectedEventForStocks] = useState(null);
const [stocksModalOpen, setStocksModalOpen] = useState(false);
@@ -117,10 +113,10 @@ const HistoricalEvents = ({
setSelectedEventForStocks(null);
};
// 处理卡片点击跳转到事件详情页
const handleCardClick = (event) => {
navigate(`/event-detail/${event.id}`);
};
// 历史事件卡片不需要点击跳转历史事件ID与主事件不同链接无效
// const handleCardClick = (event) => {
// navigate(`/event-detail/${event.id}`);
// };
// 获取重要性颜色
const getImportanceColor = (importance) => {
@@ -250,8 +246,6 @@ const HistoricalEvents = ({
borderRadius="lg"
position="relative"
overflow="visible"
cursor="pointer"
onClick={() => handleCardClick(event)}
_before={{
content: '""',
position: 'absolute',
@@ -263,10 +257,6 @@ const HistoricalEvents = ({
borderTopLeftRadius: 'lg',
borderTopRightRadius: 'lg',
}}
_hover={{
boxShadow: 'lg',
borderColor: 'blue.400',
}}
transition="all 0.2s"
>
<VStack align="stretch" spacing={3} p={4}>
@@ -280,12 +270,6 @@ const HistoricalEvents = ({
fontWeight="bold"
color={useColorModeValue('blue.500', 'blue.300')}
lineHeight="1.4"
cursor="pointer"
onClick={(e) => {
e.stopPropagation();
handleCardClick(event);
}}
_hover={{ textDecoration: 'underline' }}
>
{event.title || '未命名事件'}
</Text>