From 97c5ce0d4d7ffdce766a268b0a643bea658371fe Mon Sep 17 00:00:00 2001
From: zdl <3489966805@qq.com>
Date: Sun, 26 Oct 2025 20:31:34 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E4=BA=8B=E4=BB=B6?=
=?UTF-8?q?=E4=B8=AD=E5=BF=83=E9=A1=B5=E9=9D=A2=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E5=90=8E=E7=9A=84=E6=96=87=E4=BB=B6=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
src/views/Community/
├── index.js (主组件,150行左右)
├── components/
│ ├── EventTimelineCard.js (新增)
│ ├── EventTimelineHeader.js (新增)
│ ├── EventListSection.js (新增)
│ ├── HotEventsSection.js (新增)
│ ├── EventModals.js (新增)
│ ├── UnifiedSearchBox.js (已有)
│ ├── EventList.js (已有)
│ └── ...
└── hooks/
├── useEventFilters.js (新增)
└── useEventData.js (新增)
---
.../Community/components/EventListSection.js | 65 ++++
src/views/Community/components/EventModals.js | 63 ++++
.../Community/components/EventTimelineCard.js | 80 +++++
.../components/EventTimelineHeader.js | 42 +++
.../Community/components/HotEventsSection.js | 38 +++
src/views/Community/hooks/useEventData.js | 91 +++++
src/views/Community/hooks/useEventFilters.js | 76 +++++
src/views/Community/index.js | 314 +++---------------
8 files changed, 500 insertions(+), 269 deletions(-)
create mode 100644 src/views/Community/components/EventListSection.js
create mode 100644 src/views/Community/components/EventModals.js
create mode 100644 src/views/Community/components/EventTimelineCard.js
create mode 100644 src/views/Community/components/EventTimelineHeader.js
create mode 100644 src/views/Community/components/HotEventsSection.js
create mode 100644 src/views/Community/hooks/useEventData.js
create mode 100644 src/views/Community/hooks/useEventFilters.js
diff --git a/src/views/Community/components/EventListSection.js b/src/views/Community/components/EventListSection.js
new file mode 100644
index 00000000..eb2339d3
--- /dev/null
+++ b/src/views/Community/components/EventListSection.js
@@ -0,0 +1,65 @@
+// src/views/Community/components/EventListSection.js
+// 事件列表区域组件(包含Loading、Empty、List三种状态)
+
+import React from 'react';
+import {
+ Center,
+ VStack,
+ Spinner,
+ Text
+} from '@chakra-ui/react';
+import EventList from './EventList';
+
+/**
+ * 事件列表区域组件
+ * @param {boolean} loading - 加载状态
+ * @param {Array} events - 事件列表
+ * @param {Object} pagination - 分页信息
+ * @param {Function} onPageChange - 分页变化回调
+ * @param {Function} onEventClick - 事件点击回调
+ * @param {Function} onViewDetail - 查看详情回调
+ */
+const EventListSection = ({
+ loading,
+ events,
+ pagination,
+ onPageChange,
+ onEventClick,
+ onViewDetail
+}) => {
+ // Loading 状态
+ if (loading) {
+ return (
+
+
+
+ 正在加载最新事件...
+
+
+ );
+ }
+
+ // Empty 状态
+ if (!events || events.length === 0) {
+ return (
+
+
+ 暂无事件数据
+
+
+ );
+ }
+
+ // List 状态
+ return (
+
+ );
+};
+
+export default EventListSection;
diff --git a/src/views/Community/components/EventModals.js b/src/views/Community/components/EventModals.js
new file mode 100644
index 00000000..eea09066
--- /dev/null
+++ b/src/views/Community/components/EventModals.js
@@ -0,0 +1,63 @@
+// src/views/Community/components/EventModals.js
+// 事件弹窗组合组件(包含详情Modal和股票Drawer)
+
+import React from 'react';
+import {
+ Modal,
+ ModalOverlay,
+ ModalContent,
+ ModalHeader,
+ ModalBody,
+ ModalCloseButton
+} from '@chakra-ui/react';
+import EventDetailModal from './EventDetailModal';
+import StockDetailPanel from './StockDetailPanel';
+
+/**
+ * 事件弹窗组合组件
+ * @param {Object} eventModalState - 事件详情Modal状态
+ * @param {boolean} eventModalState.isOpen - 是否打开
+ * @param {Function} eventModalState.onClose - 关闭回调
+ * @param {Object} eventModalState.event - 事件对象
+ * @param {Function} eventModalState.onEventClose - 事件关闭回调(清除状态)
+ * @param {Object} stockDrawerState - 股票详情Drawer状态
+ * @param {boolean} stockDrawerState.visible - 是否显示
+ * @param {Object} stockDrawerState.event - 事件对象
+ * @param {Function} stockDrawerState.onClose - 关闭回调
+ */
+const EventModals = ({
+ eventModalState,
+ stockDrawerState
+}) => {
+ return (
+ <>
+ {/* 事件详情模态框 - 使用Chakra UI Modal */}
+
+
+
+ 事件详情
+
+
+
+
+
+
+
+ {/* 股票详情抽屉 - 使用原组件自带的 Antd Drawer */}
+
+ >
+ );
+};
+
+export default EventModals;
diff --git a/src/views/Community/components/EventTimelineCard.js b/src/views/Community/components/EventTimelineCard.js
new file mode 100644
index 00000000..9e7ebd3b
--- /dev/null
+++ b/src/views/Community/components/EventTimelineCard.js
@@ -0,0 +1,80 @@
+// src/views/Community/components/EventTimelineCard.js
+// 事件时间轴卡片组件(整合Header + Search + List)
+
+import React, { forwardRef } from 'react';
+import {
+ Card,
+ CardHeader,
+ CardBody,
+ Box,
+ useColorModeValue
+} from '@chakra-ui/react';
+import EventTimelineHeader from './EventTimelineHeader';
+import UnifiedSearchBox from './UnifiedSearchBox';
+import EventListSection from './EventListSection';
+
+/**
+ * 事件时间轴卡片组件
+ * @param {Array} events - 事件列表
+ * @param {boolean} loading - 加载状态
+ * @param {Object} pagination - 分页信息
+ * @param {Object} filters - 筛选条件
+ * @param {Array} popularKeywords - 热门关键词
+ * @param {Date} lastUpdateTime - 最后更新时间
+ * @param {Function} onSearch - 搜索回调
+ * @param {Function} onPageChange - 分页变化回调
+ * @param {Function} onEventClick - 事件点击回调
+ * @param {Function} onViewDetail - 查看详情回调
+ * @param {Object} ref - 用于滚动的ref
+ */
+const EventTimelineCard = forwardRef(({
+ events,
+ loading,
+ pagination,
+ filters,
+ popularKeywords,
+ lastUpdateTime,
+ onSearch,
+ onPageChange,
+ onEventClick,
+ onViewDetail
+}, ref) => {
+ const cardBg = useColorModeValue('white', 'gray.800');
+ const borderColor = useColorModeValue('gray.200', 'gray.700');
+
+ return (
+
+ {/* 标题部分 */}
+
+
+
+
+ {/* 主体内容 */}
+
+ {/* 统一搜索组件(整合了话题、股票、行业、日期、排序、重要性、热门概念、筛选标签) */}
+
+
+
+
+ {/* 事件列表(包含Loading、Empty、List三种状态) */}
+
+
+
+ );
+});
+
+EventTimelineCard.displayName = 'EventTimelineCard';
+
+export default EventTimelineCard;
diff --git a/src/views/Community/components/EventTimelineHeader.js b/src/views/Community/components/EventTimelineHeader.js
new file mode 100644
index 00000000..b85c29c7
--- /dev/null
+++ b/src/views/Community/components/EventTimelineHeader.js
@@ -0,0 +1,42 @@
+// src/views/Community/components/EventTimelineHeader.js
+// 事件时间轴标题组件
+
+import React from 'react';
+import {
+ Flex,
+ VStack,
+ HStack,
+ Heading,
+ Text,
+ Badge
+} from '@chakra-ui/react';
+import { TimeIcon } from '@chakra-ui/icons';
+
+/**
+ * 事件时间轴标题组件
+ * @param {Date} lastUpdateTime - 最后更新时间
+ */
+const EventTimelineHeader = ({ lastUpdateTime }) => {
+ return (
+
+
+
+
+
+ 实时事件时间轴
+
+
+
+ 全网监控
+ 智能捕获
+ 深度分析
+
+
+
+ 最后更新: {lastUpdateTime.toLocaleTimeString()}
+
+
+ );
+};
+
+export default EventTimelineHeader;
diff --git a/src/views/Community/components/HotEventsSection.js b/src/views/Community/components/HotEventsSection.js
new file mode 100644
index 00000000..d8eafd27
--- /dev/null
+++ b/src/views/Community/components/HotEventsSection.js
@@ -0,0 +1,38 @@
+// src/views/Community/components/HotEventsSection.js
+// 热点事件区域组件
+
+import React from 'react';
+import {
+ Card,
+ CardHeader,
+ CardBody,
+ Heading,
+ useColorModeValue
+} from '@chakra-ui/react';
+import HotEvents from './HotEvents';
+
+/**
+ * 热点事件区域组件
+ * @param {Array} events - 热点事件列表
+ */
+const HotEventsSection = ({ events }) => {
+ const cardBg = useColorModeValue('white', 'gray.800');
+
+ // 如果没有热点事件,不渲染组件
+ if (!events || events.length === 0) {
+ return null;
+ }
+
+ return (
+
+
+ 🔥 热点事件
+
+
+
+
+
+ );
+};
+
+export default HotEventsSection;
diff --git a/src/views/Community/hooks/useEventData.js b/src/views/Community/hooks/useEventData.js
new file mode 100644
index 00000000..892dce00
--- /dev/null
+++ b/src/views/Community/hooks/useEventData.js
@@ -0,0 +1,91 @@
+// src/views/Community/hooks/useEventData.js
+// 事件数据加载逻辑 Hook
+
+import { useState, useEffect, useRef, useCallback } from 'react';
+import { debounce } from 'lodash';
+import { eventService } from '../../../services/eventService';
+import { logger } from '../../../utils/logger';
+
+/**
+ * 事件数据加载 Hook
+ * @param {Object} filters - 筛选条件
+ * @param {number} pageSize - 每页数量
+ * @returns {Object} 事件数据和加载状态
+ */
+export const useEventData = (filters, pageSize = 10) => {
+ const [events, setEvents] = useState([]);
+ const [pagination, setPagination] = useState({
+ current: 1,
+ pageSize: pageSize,
+ total: 0
+ });
+ const [loading, setLoading] = useState(false);
+ const [lastUpdateTime, setLastUpdateTime] = useState(new Date());
+
+ // 加载事件列表
+ const loadEvents = useCallback(async (page = 1) => {
+ logger.debug('useEventData', 'loadEvents 被调用', { page });
+ setLoading(true);
+
+ try {
+ const response = await eventService.getEvents({
+ ...filters,
+ page,
+ per_page: pagination.pageSize
+ });
+
+ if (response.success) {
+ setEvents(response.data.events);
+ setPagination({
+ current: response.data.pagination.page,
+ pageSize: response.data.pagination.per_page,
+ total: response.data.pagination.total
+ });
+ setLastUpdateTime(new Date());
+
+ logger.debug('useEventData', 'loadEvents 成功', {
+ count: response.data.events.length,
+ total: response.data.pagination.total
+ });
+ }
+ } catch (error) {
+ logger.error('useEventData', 'loadEvents', error, {
+ page,
+ filters
+ });
+ } finally {
+ setLoading(false);
+ }
+ }, [filters, pagination.pageSize]);
+
+ // 创建防抖的 loadEvents 函数(500ms 防抖延迟)
+ const debouncedLoadEvents = useRef(
+ debounce((page) => {
+ logger.debug('useEventData', '防抖后执行 loadEvents', { page });
+ loadEvents(page);
+ }, 500)
+ ).current;
+
+ // 监听 filters 变化,自动加载数据
+ // 防抖优化:用户快速切换筛选条件时,只执行最后一次请求
+ useEffect(() => {
+ logger.debug('useEventData', 'useEffect 触发,filters 变化', { filters });
+
+ // 使用防抖加载事件
+ debouncedLoadEvents(filters.page || 1);
+
+ // 组件卸载时取消防抖
+ return () => {
+ debouncedLoadEvents.cancel();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [filters]); // 监听 filters 状态变化
+
+ return {
+ events,
+ pagination,
+ loading,
+ lastUpdateTime,
+ loadEvents
+ };
+};
diff --git a/src/views/Community/hooks/useEventFilters.js b/src/views/Community/hooks/useEventFilters.js
new file mode 100644
index 00000000..af028c09
--- /dev/null
+++ b/src/views/Community/hooks/useEventFilters.js
@@ -0,0 +1,76 @@
+// src/views/Community/hooks/useEventFilters.js
+// 事件筛选逻辑 Hook
+
+import { useState, useCallback } from 'react';
+import { useSearchParams } from 'react-router-dom';
+import { logger } from '../../../utils/logger';
+
+/**
+ * 事件筛选逻辑 Hook
+ * @param {Object} options - 配置选项
+ * @param {Function} options.navigate - 路由导航函数
+ * @param {Function} options.onEventClick - 事件点击回调
+ * @param {Object} options.eventTimelineRef - 时间轴ref(用于滚动)
+ * @returns {Object} 筛选状态和处理函数
+ */
+export const useEventFilters = ({ navigate, onEventClick, eventTimelineRef } = {}) => {
+ const [searchParams] = useSearchParams();
+
+ // 筛选参数状态 - 初始化时从URL读取,之后只用本地状态
+ const [filters, setFilters] = useState(() => {
+ return {
+ sort: searchParams.get('sort') || 'new',
+ importance: searchParams.get('importance') || 'all',
+ date_range: searchParams.get('date_range') || '',
+ q: searchParams.get('q') || '',
+ industry_classification: searchParams.get('industry_classification') || '',
+ industry_code: searchParams.get('industry_code') || '',
+ stock_code: searchParams.get('stock_code') || '',
+ page: parseInt(searchParams.get('page') || '1', 10)
+ };
+ });
+
+ // 更新筛选参数 - 直接替换(由 UnifiedSearchBox 输出完整参数)
+ const updateFilters = useCallback((newFilters) => {
+ logger.debug('useEventFilters', 'updateFilters 接收到完整参数', newFilters);
+ setFilters(newFilters);
+ }, []);
+
+ // 处理分页变化
+ const handlePageChange = useCallback((page) => {
+ // 保持现有筛选条件,只更新页码
+ updateFilters({ ...filters, page });
+
+ // 滚动到实时事件时间轴(平滑滚动)
+ if (eventTimelineRef && eventTimelineRef.current) {
+ setTimeout(() => {
+ eventTimelineRef.current.scrollIntoView({
+ behavior: 'smooth', // 平滑滚动
+ block: 'start' // 滚动到元素顶部
+ });
+ }, 100); // 延迟100ms,确保DOM更新
+ }
+ }, [filters, updateFilters, eventTimelineRef]);
+
+ // 处理事件点击
+ const handleEventClick = useCallback((event) => {
+ if (onEventClick) {
+ onEventClick(event);
+ }
+ }, [onEventClick]);
+
+ // 处理查看详情
+ const handleViewDetail = useCallback((eventId) => {
+ if (navigate) {
+ navigate(`/event-detail/${eventId}`);
+ }
+ }, [navigate]);
+
+ return {
+ filters,
+ updateFilters,
+ handlePageChange,
+ handleEventClick,
+ handleViewDetail
+ };
+};
diff --git a/src/views/Community/index.js b/src/views/Community/index.js
index 33a74928..206c67b2 100644
--- a/src/views/Community/index.js
+++ b/src/views/Community/index.js
@@ -1,80 +1,30 @@
// src/views/Community/index.js
-import React, { useState, useEffect, useCallback, useRef } from 'react';
-import { useSearchParams, useNavigate } from 'react-router-dom';
+import React, { useState, useEffect, useRef } from 'react';
+import { useNavigate } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
-import { debounce } from 'lodash';
import { fetchPopularKeywords, fetchHotEvents } from '../../store/slices/communityDataSlice';
import {
Box,
Container,
- Grid,
- GridItem,
- Card,
- CardBody,
- CardHeader,
- Button,
- Text,
- Heading,
- VStack,
- HStack,
- Badge,
- Spinner,
- Flex,
- Tag,
- TagLabel,
- TagCloseButton,
- IconButton,
- Wrap,
- WrapItem,
- Stat,
- StatLabel,
- StatNumber,
- StatHelpText,
- Modal,
- ModalOverlay,
- ModalContent,
- ModalHeader,
- ModalBody,
- ModalCloseButton,
- Drawer,
- DrawerBody,
- DrawerHeader,
- DrawerOverlay,
- DrawerContent,
- DrawerCloseButton,
- useDisclosure,
- Center,
- Image,
- Divider,
useColorModeValue,
} from '@chakra-ui/react';
-import {
- RepeatIcon,
- TimeIcon,
- InfoIcon,
- SearchIcon,
- CalendarIcon,
- StarIcon,
- ChevronRightIcon,
- CloseIcon,
-} from '@chakra-ui/icons';
-
// 导入组件
import MidjourneyHeroSection from './components/MidjourneyHeroSection';
-import EventList from './components/EventList';
-import EventDetailModal from './components/EventDetailModal';
-import StockDetailPanel from './components/StockDetailPanel';
-import HotEvents from './components/HotEvents';
-import UnifiedSearchBox from './components/UnifiedSearchBox'; // 已整合 SearchBox、PopularKeywords、IndustryCascader
-import { eventService } from '../../services/eventService';
+import EventTimelineCard from './components/EventTimelineCard';
+import HotEventsSection from './components/HotEventsSection';
+import EventModals from './components/EventModals';
+
+// 导入自定义 Hooks
+import { useEventData } from './hooks/useEventData';
+import { useEventFilters } from './hooks/useEventFilters';
+
import { logger } from '../../utils/logger';
import { useNotification } from '../../contexts/NotificationContext';
// 导航栏已由 MainLayout 提供,无需在此导入
const Community = () => {
- const [searchParams, setSearchParams] = useSearchParams();
const navigate = useNavigate();
const dispatch = useDispatch();
@@ -83,12 +33,6 @@ const Community = () => {
// Chakra UI hooks
const bgColor = useColorModeValue('gray.50', 'gray.900');
- const cardBg = useColorModeValue('white', 'gray.800');
- const borderColor = useColorModeValue('gray.200', 'gray.700');
-
- // Modal/Drawer控制
- const { isOpen: isEventModalOpen, onOpen: onEventModalOpen, onClose: onEventModalClose } = useDisclosure();
- const { isOpen: isStockDrawerOpen, onOpen: onStockDrawerOpen, onClose: onStockDrawerClose } = useDisclosure();
// Ref:用于滚动到实时事件时间轴
const eventTimelineRef = useRef(null);
@@ -96,117 +40,18 @@ const Community = () => {
// ⚡ 通知权限引导
const { showCommunityGuide } = useNotification();
- // 状态管理
- const [events, setEvents] = useState([]);
- const [pagination, setPagination] = useState({
- current: 1,
- pageSize: 10,
- total: 0
- });
- const [loading, setLoading] = useState(false);
+ // Modal/Drawer状态
const [selectedEvent, setSelectedEvent] = useState(null);
const [selectedEventForStock, setSelectedEventForStock] = useState(null);
- const [lastUpdateTime, setLastUpdateTime] = useState(new Date());
- // 筛选参数状态 - 初始化时从URL读取,之后只用本地状态
- const [filters, setFilters] = useState(() => {
- return {
- sort: searchParams.get('sort') || 'new',
- importance: searchParams.get('importance') || 'all',
- date_range: searchParams.get('date_range') || '',
- q: searchParams.get('q') || '',
- industry_classification: searchParams.get('industry_classification') || '',
- industry_code: searchParams.get('industry_code') || '',
- stock_code: searchParams.get('stock_code') || '',
- page: parseInt(searchParams.get('page') || '1', 10)
- };
+ // 自定义 Hooks
+ const { filters, updateFilters, handlePageChange, handleEventClick, handleViewDetail } = useEventFilters({
+ navigate,
+ onEventClick: (event) => setSelectedEventForStock(event),
+ eventTimelineRef
});
- // 更新筛选参数 - 直接替换(由 UnifiedSearchBox 输出完整参数)
- const updateFilters = useCallback((newFilters) => {
- logger.debug('Community', 'updateFilters 接收到完整参数', newFilters);
- setFilters(newFilters);
- }, []);
-
- // 加载事件列表
- const loadEvents = useCallback(async (page = 1) => {
- logger.debug('Community', 'loadEvents 被调用', { page });
- setLoading(true);
- try {
- const response = await eventService.getEvents({
- ...filters,
- page,
- per_page: pagination.pageSize
- });
-
- if (response.success) {
- setEvents(response.data.events);
- setPagination({
- current: response.data.pagination.page,
- pageSize: response.data.pagination.per_page,
- total: response.data.pagination.total
- });
- setLastUpdateTime(new Date());
- }
- } catch (error) {
- logger.error('Community', 'loadEvents', error, {
- page,
- filters
- });
- } finally {
- setLoading(false);
- }
- }, [filters, pagination.pageSize]);
-
- // 处理分页变化
- const handlePageChange = useCallback((page) => {
- // 保持现有筛选条件,只更新页码
- updateFilters({ ...filters, page });
-
- // 滚动到实时事件时间轴(平滑滚动)
- setTimeout(() => {
- if (eventTimelineRef.current) {
- eventTimelineRef.current.scrollIntoView({
- behavior: 'smooth', // 平滑滚动
- block: 'start' // 滚动到元素顶部
- });
- }
- }, 100); // 延迟100ms,确保DOM更新
- }, [updateFilters, filters]);
-
- // 处理事件点击
- const handleEventClick = useCallback((event) => {
- setSelectedEventForStock(event);
- onStockDrawerOpen();
- }, [onStockDrawerOpen]);
-
- // 处理查看详情
- const handleViewDetail = useCallback((eventId) => {
- navigate(`/event-detail/${eventId}`);
- }, [navigate]);
-
- // 创建防抖的 loadEvents 函数(500ms 防抖延迟)
- const debouncedLoadEvents = useRef(
- debounce((page) => {
- logger.debug('Community', '防抖后执行 loadEvents', { page });
- loadEvents(page);
- }, 500)
- ).current;
-
- // 加载事件列表 - 监听 filters 状态变化
- // 防抖优化:用户快速切换筛选条件时,只执行最后一次请求
- useEffect(() => {
- logger.debug('Community', 'useEffect 触发,filters 变化', { filters });
-
- // 使用防抖加载事件
- debouncedLoadEvents(filters.page);
-
- // 组件卸载时取消防抖
- return () => {
- debouncedLoadEvents.cancel();
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [filters]); // 监听本地 filters 状态变化
+ const { events, pagination, loading, lastUpdateTime } = useEventData(filters);
// 加载热门关键词和热点事件(使用Redux,内部有缓存判断)
useEffect(() => {
@@ -235,106 +80,37 @@ const Community = () => {
{/* 主内容区域 */}
- {/* 实时事件时间轴 - 统一大卡片 */}
-
- {/* 标题部分 */}
-
-
-
-
-
-
- 实时事件时间轴
-
-
-
- 全网监控
- 智能捕获
- 深度分析
-
-
-
- 最后更新: {lastUpdateTime.toLocaleTimeString()}
-
-
-
+ {/* 实时事件时间轴卡片 */}
+
- {/* 主体内容 */}
-
- {/* 统一搜索组件(整合了话题、股票、行业、日期、排序、重要性、热门概念、筛选标签) */}
-
-
-
-
- {/* 事件列表 */}
- {loading ? (
-
-
-
- 正在加载最新事件...
-
-
- ) : events.length > 0 ? (
-
- ) : (
-
-
- 暂无事件数据
-
-
- )}
-
-
-
- {/* 热点事件 - 需要改造为Chakra UI版本 */}
- {hotEvents.length > 0 && (
-
-
- 🔥 热点事件
-
-
-
-
-
- )}
+ {/* 热点事件区域 */}
+
- {/* 事件详情模态框 - 使用Chakra UI Modal */}
-
-
-
- 事件详情
-
-
- {
- setSelectedEvent(null);
- onEventModalClose();
- }}
- />
-
-
-
-
- {/* 股票详情抽屉 - 使用原组件自带的 Antd Drawer,避免与 Chakra Drawer 重叠导致空白 */}
- {
- setSelectedEventForStock(null);
- onStockDrawerClose();
+ {/* 事件弹窗 */}
+ setSelectedEvent(null),
+ event: selectedEvent,
+ onEventClose: () => setSelectedEvent(null)
+ }}
+ stockDrawerState={{
+ visible: !!selectedEventForStock,
+ event: selectedEventForStock,
+ onClose: () => setSelectedEventForStock(null)
}}
/>