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 日历组件 */}
-