From ea627f867ec8a288448020e1578cceb306b1a739 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Sat, 18 Oct 2025 08:46:56 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0mock=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. ✅ Profile 和 Settings 页面(2个文件) 2. ✅ EventDetail 页面(1个文件) 3. ✅ 身份验证组件(WechatRegister.js) 4. ✅ Company 页面(CompanyOverview, index, FinancialPanorama, MarketDataView) 5. ✅ Concept 页面(ConceptTimelineModal, ConceptStatsPanel, index) --- src/views/Company/FinancialPanorama.js | 47 +++++++++---------- src/views/Company/MarketDataView.js | 45 ++++++++---------- src/views/Company/index.js | 23 +++++++-- src/views/Concept/ConceptTimelineModal.js | 26 +++++----- .../Concept/components/ConceptStatsPanel.js | 18 ++++--- src/views/Concept/index.js | 23 +++++---- 6 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/views/Company/FinancialPanorama.js b/src/views/Company/FinancialPanorama.js index 722a6ed0..1839fa21 100644 --- a/src/views/Company/FinancialPanorama.js +++ b/src/views/Company/FinancialPanorama.js @@ -1,5 +1,6 @@ // src/views/Company/FinancialPanorama.jsx import React, { useState, useEffect, useMemo } from 'react'; +import { logger } from '../../utils/logger'; import { Box, Container, @@ -112,6 +113,7 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { // 加载所有财务数据 const loadFinancialData = async () => { if (!stockCode || stockCode.length !== 6) { + logger.warn('FinancialPanorama', 'loadFinancialData', '无效的股票代码', { stockCode }); toast({ title: '请输入有效的6位股票代码', status: 'warning', @@ -120,9 +122,10 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { return; } + logger.debug('FinancialPanorama', '开始加载财务数据', { stockCode, selectedPeriods }); setLoading(true); setError(null); - + try { // 并行加载所有数据 const [ @@ -158,19 +161,14 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { if (rankRes.success) setIndustryRank(rankRes.data); if (comparisonRes.success) setComparison(comparisonRes.data); - toast({ - title: '财务数据加载成功', - status: 'success', - duration: 2000, - }); + // ❌ 移除数据加载成功toast + logger.info('FinancialPanorama', '财务数据加载成功', { stockCode }); } catch (err) { setError(err.message); - toast({ - title: '数据加载失败', - description: err.message, - status: 'error', - duration: 5000, - }); + logger.error('FinancialPanorama', 'loadFinancialData', err, { stockCode, selectedPeriods }); + + // ❌ 移除数据加载失败toast + // toast({ title: '数据加载失败', description: err.message, status: 'error', duration: 5000 }); } finally { setLoading(false); } @@ -1501,6 +1499,7 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { const loadCompareData = async () => { if (!compareStock || compareStock.length !== 6) { + logger.warn('FinancialPanorama', 'loadCompareData', '无效的对比股票代码', { compareStock }); toast({ title: '请输入有效的6位股票代码', status: 'warning', @@ -1508,7 +1507,8 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { }); return; } - + + logger.debug('FinancialPanorama', '开始加载对比数据', { currentStock, compareStock }); setCompareLoading(true); try { const [stockInfoRes, metricsRes, comparisonRes] = await Promise.all([ @@ -1516,25 +1516,20 @@ const FinancialPanorama = ({ stockCode: propStockCode }) => { financialService.getFinancialMetrics(compareStock, 4), financialService.getPeriodComparison(compareStock, 4) ]); - + setCompareData({ stockInfo: stockInfoRes.data, metrics: metricsRes.data, comparison: comparisonRes.data }); - - toast({ - title: '对比数据加载成功', - status: 'success', - duration: 2000, - }); + + // ❌ 移除对比数据加载成功toast + logger.info('FinancialPanorama', '对比数据加载成功', { currentStock, compareStock }); } catch (error) { - toast({ - title: '加载对比数据失败', - description: error.message, - status: 'error', - duration: 3000, - }); + logger.error('FinancialPanorama', 'loadCompareData', error, { currentStock, compareStock }); + + // ❌ 移除对比数据加载失败toast + // toast({ title: '加载对比数据失败', description: error.message, status: 'error', duration: 3000 }); } finally { setCompareLoading(false); } diff --git a/src/views/Company/MarketDataView.js b/src/views/Company/MarketDataView.js index 0743d346..4259d383 100644 --- a/src/views/Company/MarketDataView.js +++ b/src/views/Company/MarketDataView.js @@ -1,5 +1,6 @@ // src/views/Market/MarketDataPro.jsx import React, { useState, useEffect, useMemo } from 'react'; +import { logger } from '../../utils/logger'; import { Box, Container, @@ -151,7 +152,7 @@ const marketService = { } return response.json(); } catch (error) { - console.error(`API request failed for ${url}:`, error); + logger.error('marketService', 'apiRequest', error, { url }); throw error; } }, @@ -317,6 +318,7 @@ const MarketDataView = ({ stockCode: propStockCode }) => { // 加载数据 const loadMarketData = async () => { + logger.debug('MarketDataView', '开始加载市场数据', { stockCode, selectedPeriod }); setLoading(true); try { const [summaryRes, tradeRes, fundingRes, bigDealRes, unusualRes, pledgeRes, riseAnalysisRes] = await Promise.all([ @@ -337,12 +339,12 @@ const MarketDataView = ({ stockCode: propStockCode }) => { if (pledgeRes.success) setPledgeData(pledgeRes.data); if (riseAnalysisRes.success) { setRiseAnalysisData(riseAnalysisRes.data); - + // 创建分析数据映射 const tempAnalysisMap = {}; if (tradeRes.success && tradeRes.data && riseAnalysisRes.data) { riseAnalysisRes.data.forEach(analysis => { - const dateIndex = tradeRes.data.findIndex(item => + const dateIndex = tradeRes.data.findIndex(item => item.date.substring(0, 10) === analysis.trade_date ); if (dateIndex !== -1) { @@ -352,22 +354,14 @@ const MarketDataView = ({ stockCode: propStockCode }) => { } setAnalysisMap(tempAnalysisMap); } - - toast({ - title: '数据加载成功', - status: 'success', - duration: 2000, - isClosable: true, - }); + + // ❌ 移除数据加载成功toast + logger.info('MarketDataView', '市场数据加载成功', { stockCode }); } catch (error) { - console.error('Failed to load market data:', error); - toast({ - title: '数据加载失败', - description: error.message, - status: 'error', - duration: 5000, - isClosable: true, - }); + logger.error('MarketDataView', 'loadMarketData', error, { stockCode, selectedPeriod }); + + // ❌ 移除数据加载失败toast + // toast({ title: '数据加载失败', description: error.message, status: 'error', duration: 5000, isClosable: true }); } finally { setLoading(false); } @@ -375,6 +369,7 @@ const MarketDataView = ({ stockCode: propStockCode }) => { // 获取分钟频数据 const loadMinuteData = async () => { + logger.debug('MarketDataView', '开始加载分钟频数据', { stockCode }); setMinuteLoading(true); try { const response = await fetch( @@ -394,19 +389,17 @@ const MarketDataView = ({ stockCode: propStockCode }) => { const data = await response.json(); if (data.data && Array.isArray(data.data)) { setMinuteData(data); + logger.info('MarketDataView', '分钟频数据加载成功', { stockCode, dataPoints: data.data.length }); } else { setMinuteData({ data: [], code: stockCode, name: '', trade_date: '', type: 'minute' }); + logger.warn('MarketDataView', '分钟频数据为空', { stockCode }); } } catch (error) { - console.error('Failed to load minute data:', error); - toast({ - title: '分钟数据加载失败', - description: error.message, - status: 'error', - duration: 3000, - isClosable: true, - }); + logger.error('MarketDataView', 'loadMinuteData', error, { stockCode }); + + // ❌ 移除分钟数据加载失败toast + // toast({ title: '分钟数据加载失败', description: error.message, status: 'error', duration: 3000, isClosable: true }); setMinuteData({ data: [], code: stockCode, name: '', trade_date: '', type: 'minute' }); } finally { setMinuteLoading(false); diff --git a/src/views/Company/index.js b/src/views/Company/index.js index d84e1568..2f9f4cd8 100644 --- a/src/views/Company/index.js +++ b/src/views/Company/index.js @@ -29,6 +29,7 @@ import { SearchIcon, MoonIcon, SunIcon, StarIcon } from '@chakra-ui/icons'; import { FaChartLine, FaMoneyBillWave, FaChartBar, FaInfoCircle } from 'react-icons/fa'; import HomeNavbar from '../../components/Navbars/HomeNavbar'; import { useAuth } from '../../contexts/AuthContext'; +import { logger } from '../../utils/logger'; import FinancialPanorama from './FinancialPanorama'; import ForecastReport from './ForecastReport'; import MarketDataView from './MarketDataView'; @@ -99,10 +100,12 @@ const CompanyIndex = () => { const handleWatchlistToggle = async () => { if (!stockCode) { + logger.warn('CompanyIndex', 'handleWatchlistToggle', '无效的股票代码', { stockCode }); toast({ title: '无效的股票代码', status: 'error', duration: 2000 }); return; } if (!isAuthenticated) { + logger.warn('CompanyIndex', 'handleWatchlistToggle', '用户未登录', { stockCode }); toast({ title: '请先登录后再加入自选', status: 'warning', duration: 2000 }); return; } @@ -110,25 +113,39 @@ const CompanyIndex = () => { setIsWatchlistLoading(true); const base = getApiBase(); if (isInWatchlist) { - const resp = await fetch(base + `/api/account/watchlist/${stockCode}`, { + logger.debug('CompanyIndex', '准备从自选移除', { stockCode }); + const url = base + `/api/account/watchlist/${stockCode}`; + logger.api.request('DELETE', url, { stockCode }); + + const resp = await fetch(url, { method: 'DELETE', credentials: 'include' }); + + logger.api.response('DELETE', url, resp.status); if (!resp.ok) throw new Error('删除失败'); setIsInWatchlist(false); toast({ title: '已从自选移除', status: 'info', duration: 1500 }); } else { - const resp = await fetch(base + '/api/account/watchlist', { + logger.debug('CompanyIndex', '准备添加到自选', { stockCode }); + const url = base + '/api/account/watchlist'; + const body = { stock_code: stockCode }; + logger.api.request('POST', url, body); + + const resp = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', - body: JSON.stringify({ stock_code: stockCode }) + body: JSON.stringify(body) }); + + logger.api.response('POST', url, resp.status); if (!resp.ok) throw new Error('添加失败'); setIsInWatchlist(true); toast({ title: '已加入自选', status: 'success', duration: 1500 }); } } catch (error) { + logger.error('CompanyIndex', 'handleWatchlistToggle', error, { stockCode, isInWatchlist }); toast({ title: '操作失败,请稍后重试', status: 'error', duration: 2000 }); } finally { setIsWatchlistLoading(false); diff --git a/src/views/Concept/ConceptTimelineModal.js b/src/views/Concept/ConceptTimelineModal.js index d31bd9bf..a44049f1 100644 --- a/src/views/Concept/ConceptTimelineModal.js +++ b/src/views/Concept/ConceptTimelineModal.js @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { logger } from '../../utils/logger'; import { Modal, ModalOverlay, @@ -111,13 +112,13 @@ const ConceptTimelineModal = ({ `end_date=${endDateStr}` ).then(res => { if (!res.ok) { - console.error('Price API error:', res.status); + logger.error('ConceptTimelineModal', 'fetchTimelineData - Price API', new Error(`HTTP ${res.status}`), { conceptId, startDateStr, endDateStr }); throw new Error(`Price API error: ${res.status}`); } return res.json(); }) .catch(err => { - console.error('Price API error:', err); + logger.error('ConceptTimelineModal', 'fetchTimelineData - Price API', err, { conceptId }); return { timeseries: [] }; }) ); @@ -138,13 +139,13 @@ const ConceptTimelineModal = ({ .then(async res => { if (!res.ok) { const text = await res.text(); - console.error('News API error:', res.status, text); + logger.error('ConceptTimelineModal', 'fetchTimelineData - News API', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); return []; } return res.json(); }) .catch(err => { - console.error('News API error:', err); + logger.error('ConceptTimelineModal', 'fetchTimelineData - News API', err, { conceptName }); return []; }) ); @@ -165,13 +166,13 @@ const ConceptTimelineModal = ({ .then(async res => { if (!res.ok) { const text = await res.text(); - console.error('Report API error:', res.status, text); + logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); return { results: [] }; } return res.json(); }) .catch(err => { - console.error('Report API error:', err); + logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API', err, { conceptName }); return { results: [] }; }) ); @@ -296,15 +297,12 @@ const ConceptTimelineModal = ({ setTimelineData(timeline); + logger.info('ConceptTimelineModal', '时间轴数据加载成功', { conceptId, conceptName, timelineCount: timeline.length }); } catch (error) { - console.error('获取时间轴数据失败:', error); - toast({ - title: '获取数据失败', - description: error.message, - status: 'error', - duration: 3000, - isClosable: true, - }); + logger.error('ConceptTimelineModal', 'fetchTimelineData', error, { conceptId, conceptName }); + + // ❌ 移除获取数据失败toast + // toast({ title: '获取数据失败', description: error.message, status: 'error', duration: 3000, isClosable: true }); } finally { setLoading(false); } diff --git a/src/views/Concept/components/ConceptStatsPanel.js b/src/views/Concept/components/ConceptStatsPanel.js index 707db185..23117993 100644 --- a/src/views/Concept/components/ConceptStatsPanel.js +++ b/src/views/Concept/components/ConceptStatsPanel.js @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { logger } from '../../../utils/logger'; import { Box, SimpleGrid, @@ -96,7 +97,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { throw new Error(`Concept API错误: ${response.status}`); } } catch (conceptApiError) { - console.warn('concept-api路由失败,尝试直接访问:', conceptApiError.message); + logger.warn('ConceptStatsPanel', 'concept-api路由失败,尝试直接访问', { error: conceptApiError.message, days, startDate, endDate }); // 备用方案:直接访问concept_api服务(开发环境回退) try { @@ -105,6 +106,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { result = await response.json(); if (result.success && result.data) { setStatsData(result.data); + logger.info('ConceptStatsPanel', '统计数据加载成功(备用API)', { dataKeys: Object.keys(result.data) }); return; } else { throw new Error(result.note || '直接API返回错误'); @@ -113,20 +115,16 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { throw new Error(`直接API错误: ${response.status}`); } } catch (directError) { - console.error('所有API都失败:', directError); + logger.error('ConceptStatsPanel', '所有API都失败', directError, { days, startDate, endDate }); throw new Error('无法访问概念统计API'); } } } catch (error) { - console.error('获取统计数据失败:', error); - toast({ - title: '获取统计数据失败', - description: '正在使用默认数据,请稍后刷新重试', - status: 'warning', - duration: 3000, - isClosable: true, - }); + logger.error('ConceptStatsPanel', 'fetchStatsData', error, { days, startDate, endDate }); + + // ❌ 移除获取统计数据失败toast + // toast({ title: '获取统计数据失败', description: '正在使用默认数据,请稍后刷新重试', status: 'warning', duration: 3000, isClosable: true }); // 使用简化的默认数据作为最后的fallback setStatsData({ diff --git a/src/views/Concept/index.js b/src/views/Concept/index.js index 3e103ed0..3d13e2f3 100644 --- a/src/views/Concept/index.js +++ b/src/views/Concept/index.js @@ -1,5 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useSearchParams, useNavigate } from 'react-router-dom'; +import { logger } from '../../utils/logger'; import { Box, Container, @@ -175,7 +176,7 @@ const ConceptCenter = () => { } } } catch (error) { - console.error('获取最新交易日期失败:', error); + logger.error('ConceptCenter', 'fetchLatestTradeDate', error); } return null; }, []); @@ -286,17 +287,14 @@ const ConceptCenter = () => { setSelectedDate(new Date(data.price_date)); } } catch (error) { - toast({ - title: '获取数据失败', - description: error.message, - status: 'error', - duration: 3000, - isClosable: true, - }); + logger.error('ConceptCenter', 'fetchConcepts', error, { query, page, date: date?.toISOString(), sortToUse }); + + // ❌ 移除获取数据失败toast + // toast({ title: '获取数据失败', description: error.message, status: 'error', duration: 3000, isClosable: true }); } finally { setLoading(false); } - }, [pageSize, sortBy, toast]); + }, [pageSize, sortBy]); // 清除搜索 const handleClearSearch = () => { @@ -401,7 +399,7 @@ const ConceptCenter = () => { }; } } catch (error) { - console.warn(`获取股票 ${seccode} 行情数据失败:`, error); + logger.warn('ConceptCenter', `获取股票行情数据失败`, { stockCode: seccode, error: error.message }); } return null; }); @@ -413,10 +411,11 @@ const ConceptCenter = () => { } }); } - + setStockMarketData(newMarketData); + logger.info('ConceptCenter', '股票行情数据批量加载完成', { totalStocks: stocks.length, loadedCount: Object.keys(newMarketData).length }); } catch (error) { - console.error('批量获取股票行情数据失败:', error); + logger.error('ConceptCenter', 'fetchStockMarketData', error, { stockCount: stocks?.length }); } finally { setLoadingStockData(false); }