diff --git a/src/components/EventCommentSection/CommentItem.js b/src/components/EventCommentSection/CommentItem.js index c2e9395a..6ebea5a8 100644 --- a/src/components/EventCommentSection/CommentItem.js +++ b/src/components/EventCommentSection/CommentItem.js @@ -13,10 +13,10 @@ import { Text, useColorModeValue, } from '@chakra-ui/react'; -import moment from 'moment'; -import 'moment/locale/zh-cn'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; -moment.locale('zh-cn'); +dayjs.locale('zh-cn'); const CommentItem = ({ comment }) => { const itemBg = useColorModeValue('gray.50', 'gray.700'); @@ -26,8 +26,8 @@ const CommentItem = ({ comment }) => { // 格式化时间 const formatTime = (timestamp) => { - const now = moment(); - const time = moment(timestamp); + const now = dayjs(); + const time = dayjs(timestamp); const diffMinutes = now.diff(time, 'minutes'); const diffHours = now.diff(time, 'hours'); const diffDays = now.diff(time, 'days'); diff --git a/src/components/StockChart/StockChartAntdModal.js b/src/components/StockChart/StockChartAntdModal.js index 0c5758fa..b3efef59 100644 --- a/src/components/StockChart/StockChartAntdModal.js +++ b/src/components/StockChart/StockChartAntdModal.js @@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef } from 'react'; import { Modal, Button, Spin, Typography } from 'antd'; import ReactECharts from 'echarts-for-react'; import * as echarts from 'echarts'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { stockService } from '../../services/eventService'; import CitedContent from '../Citation/CitedContent'; import { logger } from '../../utils/logger'; @@ -35,7 +35,7 @@ const StockChartAntdModal = ({ let adjustedEventTime = eventTime; if (eventTime) { try { - const eventMoment = moment(eventTime); + const eventMoment = dayjs(eventTime); if (eventMoment.isValid()) { // 如果是15:00之后的事件,推到下一个交易日的9:30 if (eventMoment.hour() >= 15) { @@ -92,7 +92,7 @@ const StockChartAntdModal = ({ let adjustedEventTime = eventTime; if (eventTime) { try { - const eventMoment = moment(eventTime); + const eventMoment = dayjs(eventTime); if (eventMoment.isValid()) { // 如果是15:00之后的事件,推到下一个交易日的9:30 if (eventMoment.hour() >= 15) { @@ -180,7 +180,7 @@ const StockChartAntdModal = ({ // 计算事件标记线位置 let markLineData = []; if (eventTime && times.length > 0) { - const eventMoment = moment(eventTime); + const eventMoment = dayjs(eventTime); const eventDate = eventMoment.format('YYYY-MM-DD'); if (activeChartType === 'timeline') { diff --git a/src/components/StockChart/StockChartModal.js b/src/components/StockChart/StockChartModal.js index f71f80d0..e637edef 100644 --- a/src/components/StockChart/StockChartModal.js +++ b/src/components/StockChart/StockChartModal.js @@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef } from 'react'; import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, Button, ButtonGroup, VStack, HStack, Text, Badge, Box, Flex, CircularProgress } from '@chakra-ui/react'; import ReactECharts from 'echarts-for-react'; import * as echarts from 'echarts'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { stockService } from '../../services/eventService'; import { logger } from '../../utils/logger'; import RiskDisclaimer from '../RiskDisclaimer'; @@ -50,7 +50,7 @@ const StockChartModal = ({ let adjustedEventTime = eventTime; if (eventTime) { try { - const eventMoment = moment(eventTime); + const eventMoment = dayjs(eventTime); if (eventMoment.isValid() && eventMoment.hour() >= 15) { const nextDay = eventMoment.clone().add(1, 'day'); nextDay.hour(9).minute(30).second(0).millisecond(0); @@ -111,7 +111,7 @@ const StockChartModal = ({ let adjustedEventTime = eventTime; if (eventTime) { try { - const eventMoment = moment(eventTime); + const eventMoment = dayjs(eventTime); if (eventMoment.isValid() && eventMoment.hour() >= 15) { const nextDay = eventMoment.clone().add(1, 'day'); nextDay.hour(9).minute(30).second(0).millisecond(0); @@ -182,7 +182,7 @@ const StockChartModal = ({ // 计算事件标记线位置 let eventMarkLineData = []; if (originalEventTime && times.length > 0) { - const eventMoment = moment(originalEventTime); + const eventMoment = dayjs(originalEventTime); const eventDate = eventMoment.format('YYYY-MM-DD'); const eventTime = eventMoment.format('HH:mm'); @@ -357,7 +357,7 @@ const StockChartModal = ({ // 计算事件标记线位置(重要修复) let eventMarkLineData = []; if (originalEventTime && dates.length > 0) { - const eventMoment = moment(originalEventTime); + const eventMoment = dayjs(originalEventTime); const eventDate = eventMoment.format('YYYY-MM-DD'); // 找到事件发生日期或最接近的交易日 diff --git a/src/utils/tradingTimeUtils.js b/src/utils/tradingTimeUtils.js index eeb09e22..4321b2b5 100644 --- a/src/utils/tradingTimeUtils.js +++ b/src/utils/tradingTimeUtils.js @@ -1,7 +1,13 @@ // src/utils/tradingTimeUtils.js // 交易时间相关工具函数 -import moment from 'moment'; +import dayjs from 'dayjs'; +import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; +import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; + +// 扩展 Day.js 插件 +dayjs.extend(isSameOrBefore); +dayjs.extend(isSameOrAfter); /** * 获取当前时间应该显示的实时要闻时间范围 @@ -12,7 +18,7 @@ import moment from 'moment'; * @returns {{ startTime: Date, endTime: Date, description: string }} */ export const getCurrentTradingTimeRange = () => { - const now = moment(); + const now = dayjs(); const currentHour = now.hour(); const currentMinute = now.minute(); @@ -25,18 +31,18 @@ export const getCurrentTradingTimeRange = () => { if (currentTimeInMinutes < cutoffTime1500) { // 15:00 之前:显示昨日 15:00 - 今日 15:00 - startTime = moment().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); - endTime = moment().hour(15).minute(0).second(0).millisecond(0).toDate(); + startTime = dayjs().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); + endTime = dayjs().hour(15).minute(0).second(0).millisecond(0).toDate(); description = '昨日15:00 - 今日15:00'; } else if (currentTimeInMinutes >= cutoffTime1530) { // 15:30 之后:显示今日 15:00 - 当前时间 - startTime = moment().hour(15).minute(0).second(0).millisecond(0).toDate(); + startTime = dayjs().hour(15).minute(0).second(0).millisecond(0).toDate(); endTime = now.toDate(); description = '今日15:00 - 当前时间'; } else { // 15:00 - 15:30 之间:过渡期,保持显示昨日 15:00 - 今日 15:00 - startTime = moment().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); - endTime = moment().hour(15).minute(0).second(0).millisecond(0).toDate(); + startTime = dayjs().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); + endTime = dayjs().hour(15).minute(0).second(0).millisecond(0).toDate(); description = '昨日15:00 - 今日15:00'; } @@ -55,7 +61,7 @@ export const getCurrentTradingTimeRange = () => { * @returns {{ startTime: Date, endTime: Date, description: string }} */ export const getMarketReviewTimeRange = () => { - const now = moment(); + const now = dayjs(); const currentHour = now.hour(); const currentMinute = now.minute(); @@ -67,13 +73,13 @@ export const getMarketReviewTimeRange = () => { if (currentTimeInMinutes >= cutoffTime1530) { // 15:30 之后:显示昨日 15:00 - 今日 15:00(刚刚完成的交易日) - startTime = moment().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); - endTime = moment().hour(15).minute(0).second(0).millisecond(0).toDate(); + startTime = dayjs().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); + endTime = dayjs().hour(15).minute(0).second(0).millisecond(0).toDate(); description = '昨日15:00 - 今日15:00'; } else { // 15:30 之前:显示前日 15:00 - 昨日 15:00(上一个完整交易日) - startTime = moment().subtract(2, 'days').hour(15).minute(0).second(0).millisecond(0).toDate(); - endTime = moment().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); + startTime = dayjs().subtract(2, 'days').hour(15).minute(0).second(0).millisecond(0).toDate(); + endTime = dayjs().subtract(1, 'day').hour(15).minute(0).second(0).millisecond(0).toDate(); description = '前日15:00 - 昨日15:00'; } @@ -102,15 +108,15 @@ export const filterEventsByTimeRange = (events, startTime, endTime) => { return events; } - const startMoment = moment(startTime); - const endMoment = moment(endTime); + const startMoment = dayjs(startTime); + const endMoment = dayjs(endTime); return events.filter(event => { if (!event.created_at) { return false; } - const eventTime = moment(event.created_at); + const eventTime = dayjs(event.created_at); return eventTime.isSameOrAfter(startMoment) && eventTime.isSameOrBefore(endMoment); }); }; @@ -138,8 +144,8 @@ export const getTimeRangeDescription = (startTime, endTime) => { return ''; } - const startStr = moment(startTime).format('MM-DD HH:mm'); - const endStr = moment(endTime).format('MM-DD HH:mm'); + const startStr = dayjs(startTime).format('MM-DD HH:mm'); + const endStr = dayjs(endTime).format('MM-DD HH:mm'); return `${startStr} - ${endStr}`; }; @@ -152,7 +158,7 @@ export const getTimeRangeDescription = (startTime, endTime) => { * @returns {boolean} */ export const isTradingDay = (date) => { - const day = moment(date).day(); + const day = dayjs(date).day(); // 0 = 周日, 6 = 周六 return day !== 0 && day !== 6; }; @@ -164,7 +170,7 @@ export const isTradingDay = (date) => { * @returns {Date} */ export const getPreviousTradingDay = (date) => { - let prevDay = moment(date).subtract(1, 'day'); + let prevDay = dayjs(date).subtract(1, 'day'); // 如果是周末,继续往前找 while (!isTradingDay(prevDay.toDate())) { diff --git a/src/views/Community/components/DynamicNewsDetail/EventHeaderInfo.js b/src/views/Community/components/DynamicNewsDetail/EventHeaderInfo.js index f1bc1e67..64b08a06 100644 --- a/src/views/Community/components/DynamicNewsDetail/EventHeaderInfo.js +++ b/src/views/Community/components/DynamicNewsDetail/EventHeaderInfo.js @@ -13,7 +13,7 @@ import { useColorModeValue, } from '@chakra-ui/react'; import { ViewIcon } from '@chakra-ui/icons'; -import moment from 'moment'; +import dayjs from 'dayjs'; import StockChangeIndicators from '../../../../components/StockChangeIndicators'; import EventFollowButton from '../EventCard/EventFollowButton'; @@ -98,7 +98,7 @@ const EventHeaderInfo = ({ event, importance, isFollowing, followerCount, onTogg {/* 日期 */} - {moment(event.created_at).format('YYYY年MM月DD日')} + {dayjs(event.created_at).format('YYYY年MM月DD日')} diff --git a/src/views/Community/components/DynamicNewsDetail/MiniKLineChart.js b/src/views/Community/components/DynamicNewsDetail/MiniKLineChart.js index 70ef090e..a13c39ea 100644 --- a/src/views/Community/components/DynamicNewsDetail/MiniKLineChart.js +++ b/src/views/Community/components/DynamicNewsDetail/MiniKLineChart.js @@ -1,7 +1,7 @@ // src/views/Community/components/DynamicNewsDetail/MiniKLineChart.js import React, { useState, useEffect, useMemo, useRef } from 'react'; import ReactECharts from 'echarts-for-react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { fetchKlineData, getCacheKey, @@ -26,7 +26,7 @@ const MiniKLineChart = React.memo(function MiniKLineChart({ stockCode, eventTime // 稳定的事件时间 const stableEventTime = useMemo(() => { - return eventTime ? moment(eventTime).format('YYYY-MM-DD HH:mm') : ''; + return eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : ''; }, [eventTime]); useEffect(() => { @@ -105,9 +105,9 @@ const MiniKLineChart = React.memo(function MiniKLineChart({ stockCode, eventTime let eventMarkLineData = []; if (stableEventTime && Array.isArray(dates) && dates.length > 0) { try { - const eventDate = moment(stableEventTime).format('YYYY-MM-DD'); + const eventDate = dayjs(stableEventTime).format('YYYY-MM-DD'); const eventIdx = dates.findIndex(d => { - const dateStr = typeof d === 'object' ? moment(d).format('YYYY-MM-DD') : String(d); + const dateStr = typeof d === 'object' ? dayjs(d).format('YYYY-MM-DD') : String(d); return dateStr.includes(eventDate); }); diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js index add48e52..6a8b159c 100644 --- a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js +++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js @@ -8,7 +8,7 @@ import { useColorModeValue, } from '@chakra-ui/react'; import { FaCalendarAlt } from 'react-icons/fa'; -import moment from 'moment'; +import dayjs from 'dayjs'; /** * 交易日期信息提示组件 @@ -28,9 +28,9 @@ const TradingDateInfo = ({ effectiveTradingDate, eventTime }) => { 涨跌幅数据:{effectiveTradingDate} - {eventTime && effectiveTradingDate !== moment(eventTime).format('YYYY-MM-DD') && ( + {eventTime && effectiveTradingDate !== dayjs(eventTime).format('YYYY-MM-DD') && ( - (事件发生于 {typeof eventTime === 'object' ? moment(eventTime).format('YYYY-MM-DD HH:mm') : moment(eventTime).format('YYYY-MM-DD HH:mm')},显示下一交易日数据) + (事件发生于 {typeof eventTime === 'object' ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : dayjs(eventTime).format('YYYY-MM-DD HH:mm')},显示下一交易日数据) )} diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js index 5df76c95..81cd1640 100644 --- a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js +++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js @@ -16,7 +16,7 @@ import { } from '@chakra-ui/react'; import { ChevronDownIcon, ChevronUpIcon } from '@chakra-ui/icons'; import { useNavigate } from 'react-router-dom'; -import moment from 'moment'; +import dayjs from 'dayjs'; import SimpleConceptCard from './SimpleConceptCard'; import DetailedConceptCard from './DetailedConceptCard'; import TradingDateInfo from './TradingDateInfo'; @@ -89,16 +89,16 @@ const RelatedConceptsSection = ({ let formattedTradeDate; try { // 不管传入的是什么格式,都用 moment 解析并格式化为 YYYY-MM-DD - formattedTradeDate = moment(effectiveTradingDate).format('YYYY-MM-DD'); + formattedTradeDate = dayjs(effectiveTradingDate).format('YYYY-MM-DD'); // 验证日期是否有效 - if (!moment(formattedTradeDate, 'YYYY-MM-DD', true).isValid()) { + if (!dayjs(formattedTradeDate, 'YYYY-MM-DD', true).isValid()) { console.warn('[RelatedConceptsSection] 无效日期,使用当前日期'); - formattedTradeDate = moment().format('YYYY-MM-DD'); + formattedTradeDate = dayjs().format('YYYY-MM-DD'); } } catch (error) { console.warn('[RelatedConceptsSection] 日期格式化失败,使用当前日期', error); - formattedTradeDate = moment().format('YYYY-MM-DD'); + formattedTradeDate = dayjs().format('YYYY-MM-DD'); } const requestBody = { diff --git a/src/views/Community/components/EventCard/CompactEventCard.js b/src/views/Community/components/EventCard/CompactEventCard.js index 469f4a1b..7f76e8c3 100644 --- a/src/views/Community/components/EventCard/CompactEventCard.js +++ b/src/views/Community/components/EventCard/CompactEventCard.js @@ -11,7 +11,7 @@ import { Text, useColorModeValue, } from '@chakra-ui/react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { getImportanceConfig } from '../../../../constants/importanceLevels'; // 导入子组件 @@ -137,7 +137,7 @@ const CompactEventCard = ({ @{event.creator?.username || 'Anonymous'} - {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + {dayjs(event.created_at).format('YYYY-MM-DD HH:mm')} diff --git a/src/views/Community/components/EventCard/DetailedEventCard.js b/src/views/Community/components/EventCard/DetailedEventCard.js index 080bfb3b..4a214b84 100644 --- a/src/views/Community/components/EventCard/DetailedEventCard.js +++ b/src/views/Community/components/EventCard/DetailedEventCard.js @@ -9,7 +9,7 @@ import { Text, useColorModeValue, } from '@chakra-ui/react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { getImportanceConfig } from '../../../../constants/importanceLevels'; // 导入子组件 @@ -127,7 +127,7 @@ const DetailedEventCard = ({ {/* 右侧:时间 + 作者 */} - {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + {dayjs(event.created_at).format('YYYY-MM-DD HH:mm')} @{event.creator?.username || 'Anonymous'} diff --git a/src/views/Community/components/EventCard/DynamicNewsEventCard.js b/src/views/Community/components/EventCard/DynamicNewsEventCard.js index a96a2da8..ab891daf 100644 --- a/src/views/Community/components/EventCard/DynamicNewsEventCard.js +++ b/src/views/Community/components/EventCard/DynamicNewsEventCard.js @@ -11,7 +11,7 @@ import { Tooltip, useColorModeValue, } from '@chakra-ui/react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { getImportanceConfig } from '../../../../constants/importanceLevels'; import { getChangeColor } from '../../../../utils/colorUtils'; @@ -54,7 +54,7 @@ const DynamicNewsEventCard = React.memo(({ * @returns {'pre-market' | 'morning-trading' | 'lunch-break' | 'afternoon-trading' | 'after-market'} */ const getTradingPeriod = (timestamp) => { - const eventTime = moment(timestamp); + const eventTime = dayjs(timestamp); const hour = eventTime.hour(); const minute = eventTime.minute(); const timeInMinutes = hour * 60 + minute; @@ -248,7 +248,7 @@ const DynamicNewsEventCard = React.memo(({ color={timeLabelStyle.textColor} lineHeight="1.3" > - {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + {dayjs(event.created_at).format('YYYY-MM-DD HH:mm')} {periodLabel && ( <> {' • '} diff --git a/src/views/Community/components/EventCard/EventTimeline.js b/src/views/Community/components/EventCard/EventTimeline.js index b5211d21..82f81723 100644 --- a/src/views/Community/components/EventCard/EventTimeline.js +++ b/src/views/Community/components/EventCard/EventTimeline.js @@ -1,7 +1,7 @@ // src/views/Community/components/EventCard/EventTimeline.js import React from 'react'; import { Box, VStack, Text, useColorModeValue, Badge } from '@chakra-ui/react'; -import moment from 'moment'; +import dayjs from 'dayjs'; /** * 事件时间轴组件 @@ -56,7 +56,7 @@ const EventTimeline = ({ createdAt, timelineStyle, borderColor, minHeight = '40p color={timelineStyle.textColor} lineHeight="1.2" > - {moment(createdAt).format('MM-DD')} + {dayjs(createdAt).format('MM-DD')} {/* 时间 HH:mm */} {/* 时间轴竖线 */} diff --git a/src/views/Community/components/EventDetailModal.js b/src/views/Community/components/EventDetailModal.js index a39d4307..633de5c7 100644 --- a/src/views/Community/components/EventDetailModal.js +++ b/src/views/Community/components/EventDetailModal.js @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'; import { Modal, Spin, Descriptions, Tag, List, Badge, Empty, Input, Button, message } from 'antd'; import { eventService } from '../../../services/eventService'; import { logger } from '../../../utils/logger'; -import moment from 'moment'; +import dayjs from 'dayjs'; const EventDetailModal = ({ visible, event, onClose }) => { const [loading, setLoading] = useState(false); @@ -143,7 +143,7 @@ const EventDetailModal = ({ visible, event, onClose }) => { <> - {moment(eventDetail.created_at).format('YYYY-MM-DD HH:mm:ss')} + {dayjs(eventDetail.created_at).format('YYYY-MM-DD HH:mm:ss')} {eventDetail.creator?.username || 'Anonymous'} @@ -234,7 +234,7 @@ const EventDetailModal = ({ visible, event, onClose }) => {
{comment.author?.username || 'Anonymous'} - {moment(comment.created_at).format('MM-DD HH:mm')} + {dayjs(comment.created_at).format('MM-DD HH:mm')}
} diff --git a/src/views/Community/components/HotEvents.js b/src/views/Community/components/HotEvents.js index 97412830..8d7411d8 100644 --- a/src/views/Community/components/HotEvents.js +++ b/src/views/Community/components/HotEvents.js @@ -11,7 +11,7 @@ import { ModalCloseButton, useDisclosure } from '@chakra-ui/react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import './HotEvents.css'; import defaultEventImage from '../../../assets/img/default-event.jpg'; import DynamicNewsDetailPanel from './DynamicNewsDetail'; @@ -181,9 +181,9 @@ const HotEvents = ({ events, onPageChange, onEventClick }) => {
{event.creator?.username || 'Anonymous'} - {moment(event.created_at).format('YYYY-MM-DD')} + {dayjs(event.created_at).format('YYYY-MM-DD')} {' '} - {moment(event.created_at).format('HH:mm')} + {dayjs(event.created_at).format('HH:mm')}
diff --git a/src/views/Community/components/InvestmentCalendar.js b/src/views/Community/components/InvestmentCalendar.js index 3df32c21..e9d73cdf 100644 --- a/src/views/Community/components/InvestmentCalendar.js +++ b/src/views/Community/components/InvestmentCalendar.js @@ -8,7 +8,7 @@ import { StarFilled, StarOutlined, CalendarOutlined, LinkOutlined, StockOutlined, TagsOutlined, ClockCircleOutlined, InfoCircleOutlined, LockOutlined, RobotOutlined } from '@ant-design/icons'; -import moment from 'moment'; +import dayjs from 'dayjs'; import ReactMarkdown from 'react-markdown'; import { eventService, stockService } from '../../../services/eventService'; import StockChartAntdModal from '../../../components/StockChart/StockChartAntdModal'; @@ -33,7 +33,7 @@ const InvestmentCalendar = () => { const [selectedDateEvents, setSelectedDateEvents] = useState([]); const [modalVisible, setModalVisible] = useState(false); const [loading, setLoading] = useState(false); - const [currentMonth, setCurrentMonth] = useState(moment()); + const [currentMonth, setCurrentMonth] = useState(dayjs()); // 新增状态 const [detailDrawerVisible, setDetailDrawerVisible] = useState(false); @@ -344,7 +344,7 @@ const InvestmentCalendar = () => { render: (time) => ( - {moment(time).format('HH:mm')} + {dayjs(time).format('HH:mm')} ) }, diff --git a/src/views/Community/components/MarketReviewCard.js b/src/views/Community/components/MarketReviewCard.js index 78d771d2..77164be4 100644 --- a/src/views/Community/components/MarketReviewCard.js +++ b/src/views/Community/components/MarketReviewCard.js @@ -20,7 +20,7 @@ import { GridItem, } from '@chakra-ui/react'; import { TimeIcon, InfoIcon } from '@chakra-ui/icons'; -import moment from 'moment'; +import dayjs from 'dayjs'; import CompactEventCard from './EventCard/CompactEventCard'; import EventHeader from './EventCard/EventHeader'; import EventStats from './EventCard/EventStats'; @@ -160,7 +160,7 @@ const MarketReviewCard = forwardRef(({ {/* 右侧:时间 + 作者 */} - {moment(selectedEvent.created_at).format('YYYY-MM-DD HH:mm')} + {dayjs(selectedEvent.created_at).format('YYYY-MM-DD HH:mm')} @{selectedEvent.creator?.username || 'Anonymous'} diff --git a/src/views/Community/components/StockDetailPanel.js b/src/views/Community/components/StockDetailPanel.js index fae14619..c626b761 100644 --- a/src/views/Community/components/StockDetailPanel.js +++ b/src/views/Community/components/StockDetailPanel.js @@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react' import { Drawer, Spin, Button, Alert } from 'antd'; import { CloseOutlined, LockOutlined, CrownOutlined } from '@ant-design/icons'; import { Tabs as AntdTabs } from 'antd'; -import moment from 'moment'; +import dayjs from 'dayjs'; // Services and Utils import { eventService } from '../../../services/eventService'; @@ -167,7 +167,7 @@ function StockDetailPanel({ visible, event, onClose }) { if (fixedCharts.length === 0) return null; const formattedEventTime = event?.start_time - ? moment(event.start_time).format('YYYY-MM-DD HH:mm') + ? dayjs(event.start_time).format('YYYY-MM-DD HH:mm') : undefined; return fixedCharts.map(({ stock }, index) => ( diff --git a/src/views/Community/components/StockDetailPanel/components/MiniTimelineChart.js b/src/views/Community/components/StockDetailPanel/components/MiniTimelineChart.js index 45c26d11..b2b55d04 100644 --- a/src/views/Community/components/StockDetailPanel/components/MiniTimelineChart.js +++ b/src/views/Community/components/StockDetailPanel/components/MiniTimelineChart.js @@ -2,7 +2,7 @@ import React, { useState, useEffect, useMemo, useRef } from 'react'; import ReactECharts from 'echarts-for-react'; import * as echarts from 'echarts'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { fetchKlineData, getCacheKey, @@ -27,7 +27,7 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve // 稳定的事件时间,避免因为格式化导致的重复请求 const stableEventTime = useMemo(() => { - return eventTime ? moment(eventTime).format('YYYY-MM-DD HH:mm') : ''; + return eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : ''; }, [eventTime]); useEffect(() => { @@ -109,7 +109,7 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve let eventMarkLineData = []; if (stableEventTime && Array.isArray(times) && times.length > 0) { try { - const eventMinute = moment(stableEventTime, 'YYYY-MM-DD HH:mm').format('HH:mm'); + const eventMinute = dayjs(stableEventTime, 'YYYY-MM-DD HH:mm').format('HH:mm'); const parseMinuteTime = (timeStr) => { const [h, m] = String(timeStr).split(':').map(Number); return h * 60 + m; diff --git a/src/views/Community/components/StockDetailPanel/components/StockTable.js b/src/views/Community/components/StockDetailPanel/components/StockTable.js index c78f230e..3edd9ca9 100644 --- a/src/views/Community/components/StockDetailPanel/components/StockTable.js +++ b/src/views/Community/components/StockDetailPanel/components/StockTable.js @@ -2,7 +2,7 @@ import React, { useState, useCallback, useMemo } from 'react'; import { Table, Button } from 'antd'; import { StarFilled, StarOutlined } from '@ant-design/icons'; -import moment from 'moment'; +import dayjs from 'dayjs'; import MiniTimelineChart from './MiniTimelineChart'; import { logger } from '../../../../../utils/logger'; @@ -31,7 +31,7 @@ const StockTable = ({ // 稳定的事件时间,避免重复渲染 const stableEventTime = useMemo(() => { - return eventTime ? moment(eventTime).format('YYYY-MM-DD HH:mm') : ''; + return eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : ''; }, [eventTime]); // 切换行展开状态 diff --git a/src/views/Community/components/StockDetailPanel/utils/klineDataCache.js b/src/views/Community/components/StockDetailPanel/utils/klineDataCache.js index 4bb1c194..55e42c5c 100644 --- a/src/views/Community/components/StockDetailPanel/utils/klineDataCache.js +++ b/src/views/Community/components/StockDetailPanel/utils/klineDataCache.js @@ -1,5 +1,5 @@ // src/views/Community/components/StockDetailPanel/utils/klineDataCache.js -import moment from 'moment'; +import dayjs from 'dayjs'; import { stockService } from '../../../../../services/eventService'; import { logger } from '../../../../../utils/logger'; @@ -19,7 +19,7 @@ const REQUEST_INTERVAL = 30000; // 30秒内不重复请求同一只股票的数 * @returns {string} 缓存键 */ export const getCacheKey = (stockCode, eventTime, chartType = 'timeline') => { - const date = eventTime ? moment(eventTime).format('YYYY-MM-DD') : moment().format('YYYY-MM-DD'); + const date = eventTime ? dayjs(eventTime).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD'); return `${stockCode}|${date}|${chartType}`; }; @@ -36,7 +36,7 @@ export const shouldRefreshData = (cacheKey) => { const elapsed = now - lastTime; // 如果是今天的数据且交易时间内,允许更频繁的更新 - const today = moment().format('YYYY-MM-DD'); + const today = dayjs().format('YYYY-MM-DD'); const isToday = cacheKey.includes(today); const currentHour = new Date().getHours(); const isTradingHours = currentHour >= 9 && currentHour < 16; @@ -76,7 +76,7 @@ export const fetchKlineData = async (stockCode, eventTime, chartType = 'timeline // 3. 发起新请求 logger.debug('klineDataCache', '发起新K线数据请求', { cacheKey, chartType }); - const normalizedEventTime = eventTime ? moment(eventTime).format('YYYY-MM-DD HH:mm') : undefined; + const normalizedEventTime = eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : undefined; const requestPromise = stockService .getKlineData(stockCode, chartType, normalizedEventTime) .then((res) => { diff --git a/src/views/Dashboard/components/InvestmentCalendarChakra.js b/src/views/Dashboard/components/InvestmentCalendarChakra.js index 1ee18f9d..1e0930a3 100644 --- a/src/views/Dashboard/components/InvestmentCalendarChakra.js +++ b/src/views/Dashboard/components/InvestmentCalendarChakra.js @@ -52,13 +52,13 @@ import { import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; -import moment from 'moment'; -import 'moment/locale/zh-cn'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; import { logger } from '../../../utils/logger'; import { getApiBase } from '../../../utils/apiConfig'; import './InvestmentCalendar.css'; -moment.locale('zh-cn'); +dayjs.locale('zh-cn'); export default function InvestmentCalendarChakra() { const { isOpen, onOpen, onClose } = useDisclosure(); @@ -140,12 +140,12 @@ export default function InvestmentCalendarChakra() { // 处理日期点击 const handleDateClick = (info) => { - const clickedDate = moment(info.date); + const clickedDate = dayjs(info.date); setSelectedDate(clickedDate); // 筛选当天的事件 const dayEvents = events.filter(event => - moment(event.start).isSame(clickedDate, 'day') + dayjs(event.start).isSame(clickedDate, 'day') ); setSelectedDateEvents(dayEvents); onOpen(); @@ -154,7 +154,7 @@ export default function InvestmentCalendarChakra() { // 处理事件点击 const handleEventClick = (info) => { const event = info.event; - const clickedDate = moment(event.start); + const clickedDate = dayjs(event.start); setSelectedDate(clickedDate); setSelectedDateEvents([{ title: event.title, @@ -173,7 +173,7 @@ export default function InvestmentCalendarChakra() { const eventData = { ...newEvent, - event_date: (selectedDate ? selectedDate.format('YYYY-MM-DD') : moment().format('YYYY-MM-DD')), + event_date: (selectedDate ? selectedDate.format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD')), stocks: newEvent.stocks.split(',').map(s => s.trim()).filter(s => s), }; @@ -274,7 +274,7 @@ export default function InvestmentCalendarChakra() { size="sm" colorScheme="blue" leftIcon={} - onClick={() => { if (!selectedDate) setSelectedDate(moment()); onAddOpen(); }} + onClick={() => { if (!selectedDate) setSelectedDate(dayjs()); onAddOpen(); }} > 添加计划 diff --git a/src/views/Dashboard/components/InvestmentPlanningCenter.js b/src/views/Dashboard/components/InvestmentPlanningCenter.js index 600b8439..d8c93994 100644 --- a/src/views/Dashboard/components/InvestmentPlanningCenter.js +++ b/src/views/Dashboard/components/InvestmentPlanningCenter.js @@ -66,13 +66,13 @@ import { import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; -import moment from 'moment'; -import 'moment/locale/zh-cn'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; import { logger } from '../../../utils/logger'; import { getApiBase } from '../../../utils/apiConfig'; import '../components/InvestmentCalendar.css'; -moment.locale('zh-cn'); +dayjs.locale('zh-cn'); // 创建 Context 用于跨标签页共享数据 const PlanningDataContext = createContext(); @@ -232,11 +232,11 @@ function CalendarPanel() { // 处理日期点击 const handleDateClick = (info) => { - const clickedDate = moment(info.date); + const clickedDate = dayjs(info.date); setSelectedDate(clickedDate); const dayEvents = allEvents.filter(event => - moment(event.event_date).isSame(clickedDate, 'day') + dayjs(event.event_date).isSame(clickedDate, 'day') ); setSelectedDateEvents(dayEvents); onOpen(); @@ -245,11 +245,11 @@ function CalendarPanel() { // 处理事件点击 const handleEventClick = (info) => { const event = info.event; - const clickedDate = moment(event.start); + const clickedDate = dayjs(event.start); setSelectedDate(clickedDate); const dayEvents = allEvents.filter(ev => - moment(ev.event_date).isSame(clickedDate, 'day') + dayjs(ev.event_date).isSame(clickedDate, 'day') ); setSelectedDateEvents(dayEvents); onOpen(); @@ -262,7 +262,7 @@ function CalendarPanel() { const eventData = { ...newEvent, - event_date: (selectedDate ? selectedDate.format('YYYY-MM-DD') : moment().format('YYYY-MM-DD')), + event_date: (selectedDate ? selectedDate.format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD')), stocks: newEvent.stocks.split(',').map(s => s.trim()).filter(s => s), }; @@ -368,7 +368,7 @@ function CalendarPanel() { size="sm" colorScheme="purple" leftIcon={} - onClick={() => { if (!selectedDate) setSelectedDate(moment()); onAddOpen(); }} + onClick={() => { if (!selectedDate) setSelectedDate(dayjs()); onAddOpen(); }} > 添加计划 @@ -619,7 +619,7 @@ function PlansPanel() { const { isOpen, onOpen, onClose } = useDisclosure(); const [editingItem, setEditingItem] = useState(null); const [formData, setFormData] = useState({ - date: moment().format('YYYY-MM-DD'), + date: dayjs().format('YYYY-MM-DD'), title: '', content: '', type: 'plan', @@ -638,13 +638,13 @@ function PlansPanel() { setEditingItem(item); setFormData({ ...item, - date: moment(item.event_date || item.date).format('YYYY-MM-DD'), + date: dayjs(item.event_date || item.date).format('YYYY-MM-DD'), content: item.description || item.content || '', }); } else { setEditingItem(null); setFormData({ - date: moment().format('YYYY-MM-DD'), + date: dayjs().format('YYYY-MM-DD'), title: '', content: '', type: 'plan', @@ -795,7 +795,7 @@ function PlansPanel() { - {moment(item.event_date || item.date).format('YYYY年MM月DD日')} + {dayjs(item.event_date || item.date).format('YYYY年MM月DD日')} - {moment(item.event_date || item.date).format('YYYY年MM月DD日')} + {dayjs(item.event_date || item.date).format('YYYY年MM月DD日')} diff --git a/src/views/Dashboard/components/InvestmentPlansAndReviews.js b/src/views/Dashboard/components/InvestmentPlansAndReviews.js index 87f9e8bb..fb4d81bd 100644 --- a/src/views/Dashboard/components/InvestmentPlansAndReviews.js +++ b/src/views/Dashboard/components/InvestmentPlansAndReviews.js @@ -60,12 +60,12 @@ import { FiXCircle, FiAlertCircle, } from 'react-icons/fi'; -import moment from 'moment'; -import 'moment/locale/zh-cn'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; import { logger } from '../../../utils/logger'; import { getApiBase } from '../../../utils/apiConfig'; -moment.locale('zh-cn'); +dayjs.locale('zh-cn'); export default function InvestmentPlansAndReviews({ type = 'both' }) { const { isOpen, onOpen, onClose } = useDisclosure(); @@ -83,7 +83,7 @@ export default function InvestmentPlansAndReviews({ type = 'both' }) { const [loading, setLoading] = useState(false); const [editingItem, setEditingItem] = useState(null); const [formData, setFormData] = useState({ - date: moment().format('YYYY-MM-DD'), + date: dayjs().format('YYYY-MM-DD'), title: '', content: '', type: 'plan', @@ -134,12 +134,12 @@ export default function InvestmentPlansAndReviews({ type = 'both' }) { setEditingItem(item); setFormData({ ...item, - date: moment(item.date).format('YYYY-MM-DD'), + date: dayjs(item.date).format('YYYY-MM-DD'), }); } else { setEditingItem(null); setFormData({ - date: moment().format('YYYY-MM-DD'), + date: dayjs().format('YYYY-MM-DD'), title: '', content: '', type: itemType, @@ -291,7 +291,7 @@ export default function InvestmentPlansAndReviews({ type = 'both' }) { - {moment(item.date).format('YYYY年MM月DD日')} + {dayjs(item.date).format('YYYY年MM月DD日')} - moment(a.calendar_time).valueOf() - moment(b.calendar_time).valueOf() + dayjs(a.calendar_time).valueOf() - dayjs(b.calendar_time).valueOf() ); setFutureEvents(sortedEvents); logger.debug('MyFutureEvents', '未来事件加载成功', { @@ -98,8 +98,8 @@ export default function MyFutureEvents({ limit = 5 }) { // 格式化时间 const formatEventTime = (time) => { - const eventTime = moment(time); - const now = moment(); + const eventTime = dayjs(time); + const now = dayjs(); const daysDiff = eventTime.diff(now, 'days'); if (daysDiff === 0) { diff --git a/src/views/EventDetail/components/RelatedConcepts.js b/src/views/EventDetail/components/RelatedConcepts.js index 00fa178e..34c53232 100644 --- a/src/views/EventDetail/components/RelatedConcepts.js +++ b/src/views/EventDetail/components/RelatedConcepts.js @@ -30,7 +30,7 @@ import { Divider } from '@chakra-ui/react'; import { FaEye, FaExternalLinkAlt, FaChartLine, FaCalendarAlt } from 'react-icons/fa'; -import moment from 'moment'; +import dayjs from 'dayjs'; import tradingDayUtils from '../../../utils/tradingDayUtils'; // 引入交易日工具 import { logger } from '../../../utils/logger'; import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme'; @@ -326,7 +326,7 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad if (typeof tradeDate === 'string') { formattedTradeDate = tradeDate; } else if (tradeDate instanceof Date) { - formattedTradeDate = moment(tradeDate).format('YYYY-MM-DD'); + formattedTradeDate = dayjs(tradeDate).format('YYYY-MM-DD'); } else if (moment.isMoment(tradeDate)) { formattedTradeDate = tradeDate.format('YYYY-MM-DD'); } else { @@ -334,7 +334,7 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad tradeDate, tradeDateType: typeof tradeDate }); - formattedTradeDate = moment().format('YYYY-MM-DD'); + formattedTradeDate = dayjs().format('YYYY-MM-DD'); } const requestBody = { @@ -414,18 +414,18 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad // 检查是否是Date对象 if (eventTime instanceof Date) { - eventMoment = moment(eventTime); + eventMoment = dayjs(eventTime); } else if (typeof eventTime === 'string') { - eventMoment = moment(eventTime); + eventMoment = dayjs(eventTime); } else if (typeof eventTime === 'number') { - eventMoment = moment(eventTime); + eventMoment = dayjs(eventTime); } else { logger.warn('RelatedConcepts', '未知的事件时间格式', { eventTime, eventTimeType: typeof eventTime, eventId }); - eventMoment = moment(); + eventMoment = dayjs(); } // 确保moment对象有效 @@ -434,7 +434,7 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad eventTime, eventId }); - eventMoment = moment(); + eventMoment = dayjs(); } formattedDate = eventMoment.format('YYYY-MM-DD'); @@ -448,7 +448,7 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad if (typeof nextTradingDay === 'string') { formattedDate = nextTradingDay; } else if (nextTradingDay instanceof Date) { - formattedDate = moment(nextTradingDay).format('YYYY-MM-DD'); + formattedDate = dayjs(nextTradingDay).format('YYYY-MM-DD'); } else { logger.warn('RelatedConcepts', '交易日工具返回了无效格式', { nextTradingDay, @@ -476,16 +476,16 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad if (typeof currentTradingDay === 'string') { formattedDate = currentTradingDay; } else if (currentTradingDay instanceof Date) { - formattedDate = moment(currentTradingDay).format('YYYY-MM-DD'); + formattedDate = dayjs(currentTradingDay).format('YYYY-MM-DD'); } else { logger.warn('RelatedConcepts', '当前交易日工具返回了无效格式', { currentTradingDay, eventId }); - formattedDate = moment().format('YYYY-MM-DD'); + formattedDate = dayjs().format('YYYY-MM-DD'); } } else { - formattedDate = moment().format('YYYY-MM-DD'); + formattedDate = dayjs().format('YYYY-MM-DD'); } } @@ -558,9 +558,9 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad 涨跌幅数据日期:{effectiveTradingDate} - {eventTime && effectiveTradingDate !== moment(eventTime).format('YYYY-MM-DD') && ( + {eventTime && effectiveTradingDate !== dayjs(eventTime).format('YYYY-MM-DD') && ( - (事件发生于 {typeof eventTime === 'object' ? moment(eventTime).format('YYYY-MM-DD HH:mm') : eventTime},显示下一交易日数据) + (事件发生于 {typeof eventTime === 'object' ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : eventTime},显示下一交易日数据) )}