diff --git a/src/views/Dashboard/components/EventDetailCard.tsx b/src/views/Dashboard/components/EventDetailCard.tsx index 149325f2..823d1bc7 100644 --- a/src/views/Dashboard/components/EventDetailCard.tsx +++ b/src/views/Dashboard/components/EventDetailCard.tsx @@ -84,15 +84,15 @@ export const EventDetailCard: React.FC = ({ return ( {/* 标题和标签 */} - - - + + + {event.title} {getEventBadge()} @@ -101,10 +101,10 @@ export const EventDetailCard: React.FC = ({ {/* 描述内容 - 支持展开/收起 */} {event.description && ( - + = ({ {/* 相关股票 */} {event.stocks && event.stocks.length > 0 && ( - - 相关股票: + + 相关股票: {event.stocks.map((stock, i) => ( diff --git a/src/views/Dashboard/components/EventPanel.tsx b/src/views/Dashboard/components/EventPanel.tsx index b70a38b7..01d62258 100644 --- a/src/views/Dashboard/components/EventPanel.tsx +++ b/src/views/Dashboard/components/EventPanel.tsx @@ -8,7 +8,7 @@ * - label: 显示文案 */ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useRef, memo, useCallback } from 'react'; import { Box, Badge, @@ -58,6 +58,135 @@ interface StatusInfo { text: string; } +/** + * 获取状态信息 + */ +const getStatusInfo = (status?: EventStatus): StatusInfo => { + switch (status) { + case 'completed': + return { icon: FiCheckCircle, color: 'green', text: '已完成' }; + case 'cancelled': + return { icon: FiXCircle, color: 'red', text: '已取消' }; + default: + return { icon: FiAlertCircle, color: 'blue', text: '进行中' }; + } +}; + +/** + * EventCard Props + */ +interface EventCardProps { + item: InvestmentEvent; + colorScheme: string; + label: string; + textColor: string; + secondaryText: string; + cardBg: string; + onEdit: (item: InvestmentEvent) => void; + onDelete: (id: number) => void; +} + +/** + * EventCard 组件(使用 memo 优化渲染性能) + */ +const EventCard = memo(({ + item, + colorScheme, + label, + textColor, + secondaryText, + cardBg, + onEdit, + onDelete, +}) => { + const statusInfo = getStatusInfo(item.status); + + return ( + + + + + + + + + {item.title} + + + + + + {dayjs(item.event_date || item.date).format('YYYY年MM月DD日')} + + + {statusInfo.text} + + + + + } + size="sm" + variant="ghost" + onClick={() => onEdit(item)} + aria-label={`编辑${label}`} + /> + } + size="sm" + variant="ghost" + colorScheme="red" + onClick={() => onDelete(item.id)} + aria-label={`删除${label}`} + /> + + + + {(item.content || item.description) && ( + + {item.content || item.description} + + )} + + + {item.stocks && item.stocks.length > 0 && ( + <> + {item.stocks.map((stock, idx) => ( + + + {stock} + + ))} + + )} + {item.tags && item.tags.length > 0 && ( + <> + {item.tags.map((tag, idx) => ( + + + {tag} + + ))} + + )} + + + + + ); +}); + +EventCard.displayName = 'EventCard'; + /** * EventPanel Props */ @@ -161,105 +290,10 @@ export const EventPanel: React.FC = ({ } }; - // 获取状态信息 - const getStatusInfo = (status?: EventStatus): StatusInfo => { - switch (status) { - case 'completed': - return { icon: FiCheckCircle, color: 'green', text: '已完成' }; - case 'cancelled': - return { icon: FiXCircle, color: 'red', text: '已取消' }; - default: - return { icon: FiAlertCircle, color: 'blue', text: '进行中' }; - } - }; - - // 渲染单个卡片 - const renderCard = (item: InvestmentEvent): React.ReactElement => { - const statusInfo = getStatusInfo(item.status); - - return ( - - - - - - - - - {item.title} - - - - - - {dayjs(item.event_date || item.date).format('YYYY年MM月DD日')} - - - {statusInfo.text} - - - - - } - size="sm" - variant="ghost" - onClick={() => handleOpenModal(item)} - aria-label={`编辑${label}`} - /> - } - size="sm" - variant="ghost" - colorScheme="red" - onClick={() => handleDelete(item.id)} - aria-label={`删除${label}`} - /> - - - - {(item.content || item.description) && ( - - {item.content || item.description} - - )} - - - {item.stocks && item.stocks.length > 0 && ( - <> - {item.stocks.map((stock, idx) => ( - - - {stock} - - ))} - - )} - {item.tags && item.tags.length > 0 && ( - <> - {item.tags.map((tag, idx) => ( - - - {tag} - - ))} - - )} - - - - - ); - }; + // 使用 useCallback 优化回调函数 + const handleEdit = useCallback((item: InvestmentEvent) => { + handleOpenModal(item); + }, []); return ( @@ -276,8 +310,20 @@ export const EventPanel: React.FC = ({ ) : ( - - {events.map(renderCard)} + + {events.map(event => ( + + ))} )} diff --git a/src/views/Dashboard/components/InvestmentPlanningCenter.tsx b/src/views/Dashboard/components/InvestmentPlanningCenter.tsx index 8209db25..3da07955 100644 --- a/src/views/Dashboard/components/InvestmentPlanningCenter.tsx +++ b/src/views/Dashboard/components/InvestmentPlanningCenter.tsx @@ -129,7 +129,6 @@ const InvestmentPlanningCenter: React.FC = () => { openPlanModalTrigger, openReviewModalTrigger, toast, - bgColor, borderColor, textColor, secondaryText,