From f521b89c2796f5cf2749719a94ee8a0436a02792 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Thu, 4 Dec 2025 12:20:27 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=87=AA=E9=80=89=E8=82=A1=E6=B2=A1=E5=8F=8D=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mocks/handlers/account.js | 29 +++++- .../DynamicNewsDetailPanel.js | 95 +++++++++++++------ .../DynamicNewsDetail/StockListItem.js | 2 +- 3 files changed, 94 insertions(+), 32 deletions(-) diff --git a/src/mocks/handlers/account.js b/src/mocks/handlers/account.js index bc60c6b0..2e4d46c8 100644 --- a/src/mocks/handlers/account.js +++ b/src/mocks/handlers/account.js @@ -188,6 +188,22 @@ export const accountHandlers = [ mockWatchlist.push(newItem); + // 同步添加到 mockRealtimeQuotes(导航栏自选股菜单使用此数组) + mockRealtimeQuotes.push({ + stock_code: stock_code, + stock_name: stock_name, + current_price: null, + change_percent: 0, + change: 0, + volume: 0, + turnover: 0, + high: 0, + low: 0, + open: 0, + prev_close: 0, + update_time: new Date().toTimeString().slice(0, 8) + }); + return HttpResponse.json({ success: true, message: '添加成功', @@ -210,9 +226,20 @@ export const accountHandlers = [ const { id } = params; console.log('[Mock] 删除自选股:', id); - const index = mockWatchlist.findIndex(item => item.id === parseInt(id)); + // 支持按 stock_code 或 id 匹配删除 + const index = mockWatchlist.findIndex(item => + item.stock_code === id || item.id === parseInt(id) + ); + if (index !== -1) { + const stockCode = mockWatchlist[index].stock_code; mockWatchlist.splice(index, 1); + + // 同步从 mockRealtimeQuotes 移除 + const quotesIndex = mockRealtimeQuotes.findIndex(item => item.stock_code === stockCode); + if (quotesIndex !== -1) { + mockRealtimeQuotes.splice(quotesIndex, 1); + } } return HttpResponse.json({ diff --git a/src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js b/src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js index d2deb64a..214d24ba 100644 --- a/src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js +++ b/src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js @@ -17,11 +17,11 @@ import { useColorModeValue, useToast, } from '@chakra-ui/react'; -import { getImportanceConfig } from '../../../../constants/importanceLevels'; -import { eventService } from '../../../../services/eventService'; +import { getImportanceConfig } from '@constants/importanceLevels'; +import { eventService } from '@services/eventService'; import { useEventStocks } from '../StockDetailPanel/hooks/useEventStocks'; -import { toggleEventFollow, selectEventFollowStatus } from '../../../../store/slices/communityDataSlice'; -import { useAuth } from '../../../../contexts/AuthContext'; +import { toggleEventFollow, selectEventFollowStatus } from '@store/slices/communityDataSlice'; +import { useAuth } from '@contexts/AuthContext'; import EventHeaderInfo from './EventHeaderInfo'; import CompactMetaBar from './CompactMetaBar'; import EventDescriptionSection from './EventDescriptionSection'; @@ -29,12 +29,13 @@ import RelatedConceptsSection from './RelatedConceptsSection'; import RelatedStocksSection from './RelatedStocksSection'; import CompactStockItem from './CompactStockItem'; import CollapsibleSection from './CollapsibleSection'; -import HistoricalEvents from '../../../EventDetail/components/HistoricalEvents'; -import TransmissionChainAnalysis from '../../../EventDetail/components/TransmissionChainAnalysis'; -import SubscriptionBadge from '../../../../components/SubscriptionBadge'; -import SubscriptionUpgradeModal from '../../../../components/SubscriptionUpgradeModal'; -import { PROFESSIONAL_COLORS } from '../../../../constants/professionalTheme'; -import EventCommentSection from '../../../../components/EventCommentSection'; +import HistoricalEvents from '@views/EventDetail/components/HistoricalEvents'; +import TransmissionChainAnalysis from '@views/EventDetail/components/TransmissionChainAnalysis'; +import SubscriptionBadge from '@components/SubscriptionBadge'; +import SubscriptionUpgradeModal from '@components/SubscriptionUpgradeModal'; +import { PROFESSIONAL_COLORS } from '@constants/professionalTheme'; +import { getApiBase } from '@utils/apiConfig'; +import EventCommentSection from '@components/EventCommentSection'; /** * 动态新闻详情面板主组件 @@ -255,37 +256,71 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => { }, [dispatch, event?.id]); // 切换自选股 - const handleWatchlistToggle = useCallback(async (stockCode, isInWatchlist) => { + const handleWatchlistToggle = useCallback(async (stockCode, stockName, isInWatchlist) => { try { - const newWatchlist = new Set(watchlistSet); + const base = getApiBase(); if (isInWatchlist) { - newWatchlist.delete(stockCode); - toast({ - title: '已移除自选股', - status: 'info', - duration: 2000, - isClosable: true, + // 移除自选股 + const resp = await fetch(base + `/api/account/watchlist/${stockCode}`, { + method: 'DELETE', + credentials: 'include' }); + const data = await resp.json().catch(() => ({})); + if (resp.ok && data.success !== false) { + const newWatchlist = new Set(watchlistSet); + newWatchlist.delete(stockCode); + setWatchlistSet(newWatchlist); + localStorage.setItem('stock_watchlist', JSON.stringify(Array.from(newWatchlist))); + toast({ + title: '已移除自选股', + status: 'info', + duration: 2000, + isClosable: true, + }); + } else { + toast({ + title: '移除失败', + status: 'error', + duration: 2000, + isClosable: true, + }); + } } else { - newWatchlist.add(stockCode); - toast({ - title: '已添加至自选股', - status: 'success', - duration: 2000, - isClosable: true, + // 添加自选股 + const resp = await fetch(base + '/api/account/watchlist/add', { + method: 'POST', + credentials: 'include', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ stock_code: stockCode, stock_name: stockName }) }); + const data = await resp.json().catch(() => ({})); + if (resp.ok && data.success) { + const newWatchlist = new Set(watchlistSet); + newWatchlist.add(stockCode); + setWatchlistSet(newWatchlist); + localStorage.setItem('stock_watchlist', JSON.stringify(Array.from(newWatchlist))); + toast({ + title: '已添加至自选股', + status: 'success', + duration: 2000, + isClosable: true, + }); + } else { + toast({ + title: '添加失败', + status: 'error', + duration: 2000, + isClosable: true, + }); + } } - - setWatchlistSet(newWatchlist); - localStorage.setItem('stock_watchlist', JSON.stringify(Array.from(newWatchlist))); } catch (error) { console.error('切换自选股失败:', error); toast({ - title: '操作失败', - description: error.message, + title: '网络错误', status: 'error', - duration: 3000, + duration: 2000, isClosable: true, }); } diff --git a/src/views/Community/components/DynamicNewsDetail/StockListItem.js b/src/views/Community/components/DynamicNewsDetail/StockListItem.js index 35fe821e..8e3b2a52 100644 --- a/src/views/Community/components/DynamicNewsDetail/StockListItem.js +++ b/src/views/Community/components/DynamicNewsDetail/StockListItem.js @@ -74,7 +74,7 @@ const StockListItem = ({ const handleWatchlistClick = (e) => { e.stopPropagation(); - onWatchlistToggle?.(stock.stock_code, isInWatchlist); + onWatchlistToggle?.(stock.stock_code, stock.stock_name, isInWatchlist); }; // 格式化涨跌幅显示