update pay ui
This commit is contained in:
4
app.py
4
app.py
@@ -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()
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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="相关股票"
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user