From d9dbf65e7d587ca9624b1e633ec26346d451dc64 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Tue, 23 Dec 2025 17:44:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor(Concept):=20ConceptTimelineModal=20?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=88=B0=20BaseCalendar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Concept/ConceptTimelineModal.js | 352 +++++++++------------- 1 file changed, 136 insertions(+), 216 deletions(-) diff --git a/src/views/Concept/ConceptTimelineModal.js b/src/views/Concept/ConceptTimelineModal.js index aa4731e8..48f8afb6 100644 --- a/src/views/Concept/ConceptTimelineModal.js +++ b/src/views/Concept/ConceptTimelineModal.js @@ -2,11 +2,10 @@ import React, { useState, useEffect, useMemo } from 'react'; import { logger } from '../../utils/logger'; import { useConceptTimelineEvents } from './hooks/useConceptTimelineEvents'; import RiskDisclaimer from '../../components/RiskDisclaimer'; -import FullCalendar from '@fullcalendar/react'; -import dayGridPlugin from '@fullcalendar/daygrid'; -import interactionPlugin from '@fullcalendar/interaction'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; +// 使用新的公共日历组件 +import { BaseCalendar } from '@components/Calendar'; import { Modal, ModalOverlay, @@ -198,93 +197,19 @@ const ConceptTimelineModal = ({ } }; - // 转换时间轴数据为日历事件格式(一天拆分为多个独立事件) - const calendarEvents = useMemo(() => { - const events = []; - + // 按日期索引的事件数据(用于日历单元格渲染) + const eventsByDate = useMemo(() => { + const map = {}; timelineData.forEach(item => { - const priceInfo = getPriceInfo(item.price); - const newsCount = (item.events || []).filter(e => e.type === 'news').length; - const reportCount = (item.events || []).filter(e => e.type === 'report').length; - const hasPriceData = item.price && item.price.avg_change_pct !== null; - - // 如果有新闻,添加新闻事件 - if (newsCount > 0) { - events.push({ - id: `${item.date}-news`, - title: `📰 ${newsCount} 条新闻`, - date: item.date, - start: item.date, - backgroundColor: '#9F7AEA', - borderColor: '#9F7AEA', - extendedProps: { - eventType: 'news', - count: newsCount, - originalData: item, - } - }); - } - - // 如果有研报,添加研报事件 - if (reportCount > 0) { - events.push({ - id: `${item.date}-report`, - title: `📊 ${reportCount} 篇研报`, - date: item.date, - start: item.date, - backgroundColor: '#805AD5', - borderColor: '#805AD5', - extendedProps: { - eventType: 'report', - count: reportCount, - originalData: item, - } - }); - } - - // 如果有价格数据,添加价格事件 - if (hasPriceData) { - const changePercent = item.price.avg_change_pct; - const isSignificantRise = changePercent >= 3; // 涨幅 >= 3% 为重大利好 - let bgColor = '#e2e8f0'; - let title = priceInfo.text; - - if (priceInfo.color === 'red') { - if (isSignificantRise) { - // 涨幅 >= 3%,使用醒目的橙红色 + 火焰图标 - bgColor = '#F56565'; // 更深的红色 - title = `🔥 ${priceInfo.text}`; - } else { - bgColor = '#FC8181'; // 普通红色(上涨) - } - } else if (priceInfo.color === 'green') { - bgColor = '#68D391'; // 绿色(下跌) - } - - events.push({ - id: `${item.date}-price`, - title: title, - date: item.date, - start: item.date, - backgroundColor: bgColor, - borderColor: isSignificantRise ? '#C53030' : bgColor, // 深红色边框强调 - extendedProps: { - eventType: 'price', - priceInfo, - originalData: item, - isSignificantRise, // 标记重大涨幅 - } - }); - } + map[item.date] = item; }); - - return events; + return map; }, [timelineData]); - // 处理日期点击 - const handleDateClick = (info) => { - const clickedDate = info.dateStr; - const dateData = timelineData.find(item => item.date === clickedDate); + // 处理日期选择(点击日期单元格) + const handleDateSelect = (date) => { + const clickedDate = date.format('YYYY-MM-DD'); + const dateData = eventsByDate[clickedDate]; if (dateData) { setSelectedDate(clickedDate); @@ -296,16 +221,128 @@ const ConceptTimelineModal = ({ } }; - // 处理事件点击 - const handleEventClick = (info) => { - // 从事件的 extendedProps 中获取原始数据 - const dateData = info.event.extendedProps?.originalData; + // 自定义日期单元格内容渲染 + const renderCellContent = (date) => { + const dateStr = date.format('YYYY-MM-DD'); + const item = eventsByDate[dateStr]; - if (dateData) { - setSelectedDate(dateData.date); - setSelectedDateData(dateData); - onDateDetailOpen(); + if (!item) return null; + + const priceInfo = getPriceInfo(item.price); + const newsCount = (item.events || []).filter(e => e.type === 'news').length; + const reportCount = (item.events || []).filter(e => e.type === 'report').length; + const hasPriceData = item.price && item.price.avg_change_pct !== null; + + const events = []; + + // 新闻事件 + if (newsCount > 0) { + events.push( + + + 📰 {newsCount} 条新闻 + + + ); } + + // 研报事件 + if (reportCount > 0) { + events.push( + + + 📊 {reportCount} 篇研报 + + + ); + } + + // 涨跌数据 + if (hasPriceData) { + const changePercent = item.price.avg_change_pct; + const isSignificantRise = changePercent >= 3; + let bgColor = 'rgba(226, 232, 240, 0.2)'; + let textColor = '#e2e8f0'; + let title = priceInfo.text; + + if (priceInfo.color === 'red') { + if (isSignificantRise) { + bgColor = 'rgba(245, 101, 101, 0.3)'; + textColor = '#F56565'; + title = `🔥 ${priceInfo.text}`; + } else { + bgColor = 'rgba(252, 129, 129, 0.2)'; + textColor = '#FC8181'; + } + } else if (priceInfo.color === 'green') { + bgColor = 'rgba(104, 211, 145, 0.2)'; + textColor = '#68D391'; + } + + events.push( + + + {title} + + + ); + } + + // 最多显示 3 个事件,超出显示 "更多" + const maxDisplay = 3; + const displayEvents = events.slice(0, maxDisplay); + const remainingCount = events.length - maxDisplay; + + return ( + + {displayEvents} + {remainingCount > 0 && ( + + +{remainingCount} 更多 + + )} + + ); }; // 获取时间轴数据 @@ -833,7 +870,7 @@ const ConceptTimelineModal = ({ - {/* FullCalendar 日历组件 */} + {/* Ant Design 日历组件 */} -