From 3a3cac75f7320077c81b1d2ede6c84eebf443820 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Sat, 18 Oct 2025 09:53:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=A7=E7=BB=AD=E9=87=8D=E6=9E=84=20?= =?UTF-8?q?Community=20=E5=AD=90=E7=BB=84=E4=BB=B6=E5=92=8C=20EventDetail?= =?UTF-8?q?=20=E5=AD=90=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Community/components/StockDetailPanel.js | 82 ++++++++---- src/views/Pages/Account/Subscription.js | 118 +++++++++++------- 2 files changed, 133 insertions(+), 67 deletions(-) diff --git a/src/views/Community/components/StockDetailPanel.js b/src/views/Community/components/StockDetailPanel.js index 4e69381e..c32ec53b 100644 --- a/src/views/Community/components/StockDetailPanel.js +++ b/src/views/Community/components/StockDetailPanel.js @@ -15,6 +15,7 @@ import EventDiscussionModal from './EventDiscussionModal'; import { useSubscription } from '../../../hooks/useSubscription'; import SubscriptionUpgradeModal from '../../../components/SubscriptionUpgradeModal'; import moment from 'moment'; +import { logger } from '../../../utils/logger'; const { Title, Text } = Typography; const { TabPane } = Tabs; @@ -58,24 +59,24 @@ const shouldRefreshData = (cacheKey) => { // 获取K线数据(带缓存和防重复请求) const fetchKlineData = async (stockCode, eventTime) => { const cacheKey = getCacheKey(stockCode, eventTime); - + // 1. 检查缓存 if (klineDataCache.has(cacheKey)) { // 检查是否需要刷新 if (!shouldRefreshData(cacheKey)) { - console.log(`使用缓存数据: ${cacheKey}`); + logger.debug('StockDetailPanel', '使用缓存数据', { cacheKey }); return klineDataCache.get(cacheKey); } } - + // 2. 检查是否有正在进行的请求 if (pendingRequests.has(cacheKey)) { - console.log(`等待进行中的请求: ${cacheKey}`); + logger.debug('StockDetailPanel', '等待进行中的请求', { cacheKey }); return pendingRequests.get(cacheKey); } - + // 3. 发起新请求 - console.log(`发起新请求: ${cacheKey}`); + logger.debug('StockDetailPanel', '发起新K线数据请求', { cacheKey }); const normalizedEventTime = eventTime ? moment(eventTime).format('YYYY-MM-DD HH:mm') : undefined; const requestPromise = stockService .getKlineData(stockCode, 'minute', normalizedEventTime) @@ -86,11 +87,14 @@ const fetchKlineData = async (stockCode, eventTime) => { lastRequestTime.set(cacheKey, Date.now()); // 清除pending状态 pendingRequests.delete(cacheKey); - console.log(`请求完成并缓存: ${cacheKey}`); + logger.debug('StockDetailPanel', 'K线数据请求完成并缓存', { + cacheKey, + dataPoints: data.length + }); return data; }) .catch((error) => { - console.error(`获取${stockCode}的K线数据失败:`, error); + logger.error('StockDetailPanel', 'fetchKlineData', error, { stockCode, cacheKey }); // 清除pending状态 pendingRequests.delete(cacheKey); // 如果有旧缓存,返回旧数据 @@ -99,10 +103,10 @@ const fetchKlineData = async (stockCode, eventTime) => { } return []; }); - + // 保存pending请求 pendingRequests.set(cacheKey, requestPromise); - + return requestPromise; }; @@ -284,7 +288,11 @@ const StockDetailModal = ({ stock, onClose, fixed, eventTime }) => { }; function StockDetailPanel({ visible, event, onClose }) { - console.log('StockDetailPanel 组件已加载,visible:', visible, 'event:', event?.id); + logger.debug('StockDetailPanel', '组件加载', { + visible, + eventId: event?.id, + eventTitle: event?.title + }); // 权限控制 const { hasFeatureAccess, getRequiredLevel, getUpgradeRecommendation } = useSubscription(); @@ -362,7 +370,10 @@ function StockDetailPanel({ visible, event, onClose }) { const codes = relatedStocks.map(s => s.stock_code); stockService.getQuotes(codes, event?.created_at) .then(quotes => setStockQuotes(quotes)) - .catch(error => console.error('更新行情失败:', error)); + .catch(error => logger.error('StockDetailPanel', 'updateQuotes', error, { + stockCodes: codes, + eventTime: event?.created_at + })); }; updateQuotes(); @@ -391,9 +402,12 @@ function StockDetailPanel({ visible, event, onClose }) { if (data.success && data.data) { const watchlistSet = new Set(data.data.map(item => item.stock_code)); setWatchlistStocks(watchlistSet); + logger.debug('StockDetailPanel', '自选股列表加载成功', { + count: watchlistSet.size + }); } } catch (error) { - console.error('加载自选股列表失败:', error); + logger.error('StockDetailPanel', 'loadWatchlist', error); } }, []); @@ -452,7 +466,10 @@ function StockDetailPanel({ visible, event, onClose }) { // 初始化数据加载 useEffect(() => { - console.log('[StockDetailPanel] useEffect 触发, visible:', visible, 'event:', event?.id); + logger.debug('StockDetailPanel', 'useEffect 触发', { + visible, + eventId: event?.id + }); if (visible && event) { setActiveTab('stocks'); loadAllData(); @@ -461,27 +478,40 @@ function StockDetailPanel({ visible, event, onClose }) { // 加载所有数据的函数 const loadAllData = useCallback(() => { - console.log('[StockDetailPanel] loadAllData 被调用, event:', event?.id); + logger.debug('StockDetailPanel', 'loadAllData 被调用', { + eventId: event?.id + }); if (!event) return; // 加载自选股列表 loadWatchlist(); - + // 加载相关标的 setLoading(true); eventService.getRelatedStocks(event.id) .then(res => { - console.log('[前端] 接收到事件相关股票数据:', res); + logger.debug('StockDetailPanel', '接收到事件相关股票数据', { + eventId: event.id, + success: res.success, + stockCount: res.data?.length || 0 + }); if (res.success) { - console.log('[前端] 股票数据数组:', res.data); - console.log('[前端] 第一只股票:', res.data[0]); - console.log('[前端] 第一只股票的 relation_desc:', res.data[0]?.relation_desc); + if (res.data && res.data[0]) { + logger.debug('StockDetailPanel', '第一只股票数据', { + stockCode: res.data[0].stock_code, + stockName: res.data[0].stock_name, + hasRelationDesc: !!res.data[0].relation_desc + }); + } setRelatedStocks(res.data); if (res.data.length > 0) { const codes = res.data.map(s => s.stock_code); stockService.getQuotes(codes, event.created_at) .then(quotes => setStockQuotes(quotes)) - .catch(error => console.error('加载行情失败:', error)); + .catch(error => logger.error('StockDetailPanel', 'getQuotes', error, { + stockCodes: codes, + eventTime: event.created_at + })); } } }) @@ -593,7 +623,10 @@ function StockDetailPanel({ visible, event, onClose }) { key: 'relation_desc', width: 300, render: (relationDesc, record) => { - console.log('[表格渲染] 股票:', record.stock_code, 'relation_desc:', relationDesc); + logger.debug('StockDetailPanel', '表格渲染 - 股票关联描述', { + stockCode: record.stock_code, + hasRelationDesc: !!relationDesc + }); // 处理 relation_desc 的两种格式 let text = ''; @@ -611,7 +644,10 @@ function StockDetailPanel({ visible, event, onClose }) { .filter(s => s) .join(';') || '--'; } else { - console.warn('[表格渲染] 未知的 relation_desc 格式:', relationDesc); + logger.warn('StockDetailPanel', '未知的 relation_desc 格式', { + stockCode: record.stock_code, + relationDescType: typeof relationDesc + }); return '--'; } diff --git a/src/views/Pages/Account/Subscription.js b/src/views/Pages/Account/Subscription.js index c91ec910..8e50dff3 100644 --- a/src/views/Pages/Account/Subscription.js +++ b/src/views/Pages/Account/Subscription.js @@ -24,6 +24,7 @@ import { Divider, } from '@chakra-ui/react'; import React, { useState, useEffect } from 'react'; +import { logger } from '../../../utils/logger'; // Custom components import Card from 'components/Card/Card.js'; @@ -100,34 +101,35 @@ function Subscription() { const fetchSubscriptionPlans = async () => { try { - console.log('🔄 正在获取订阅套餐...'); + logger.debug('Subscription', '正在获取订阅套餐'); const response = await fetch('/api/subscription/plans'); - console.log('📡 套餐API响应状态:', response.status); - + if (response.ok) { const data = await response.json(); - console.log('📦 套餐API响应数据:', data); - + if (data.success && Array.isArray(data.data)) { // 确保每个套餐都有必要的字段 - const validPlans = data.data.filter(plan => - plan && - plan.name && - typeof plan.monthly_price === 'number' && + const validPlans = data.data.filter(plan => + plan && + plan.name && + typeof plan.monthly_price === 'number' && typeof plan.yearly_price === 'number' ); - console.log('✅ 有效套餐数量:', validPlans.length); + logger.debug('Subscription', '套餐加载成功', { + status: response.status, + validPlansCount: validPlans.length + }); setSubscriptionPlans(validPlans); } else { - console.warn('⚠️ 套餐数据格式异常:', data); + logger.warn('Subscription', '套餐数据格式异常', { data }); setSubscriptionPlans([]); } } else { - console.error('❌ 获取套餐失败,状态码:', response.status); + logger.error('Subscription', 'fetchSubscriptionPlans', new Error(`HTTP ${response.status}`)); setSubscriptionPlans([]); } } catch (error) { - console.error('❌ 获取订阅套餐失败:', error); + logger.error('Subscription', 'fetchSubscriptionPlans', error); setSubscriptionPlans([]); } }; @@ -139,14 +141,18 @@ function Subscription() { }); if (response.ok) { const data = await response.json(); - console.log('👤 用户数据:', data); + logger.debug('Subscription', '用户数据获取成功', { data }); if (data.success) { setCurrentUser(data.user); - console.log('✅ 用户信息已更新:', data.user); + logger.debug('Subscription', '用户信息已更新', { + userId: data.user?.id, + subscriptionType: data.user?.subscription_type, + subscriptionStatus: data.user?.subscription_status + }); } } } catch (error) { - console.error('获取用户信息失败:', error); + logger.error('Subscription', 'fetchCurrentUser', error); } }; @@ -243,23 +249,28 @@ function Subscription() { // 自动检查支付状态 const startAutoPaymentCheck = (orderId) => { - console.log('🔄 开始自动检查支付状态...'); - + logger.info('Subscription', '开始自动检查支付状态', { orderId }); + const checkInterval = setInterval(async () => { try { const response = await fetch(`/api/payment/order/${orderId}/status`, { credentials: 'include' }); - + if (response.ok) { const data = await response.json(); - console.log('📡 支付状态检查结果:', data); - + logger.debug('Subscription', '支付状态检查结果', { + orderId, + paymentSuccess: data.payment_success, + data + }); + if (data.success && data.payment_success) { // 支付成功 clearInterval(checkInterval); setAutoCheckInterval(null); - + + logger.info('Subscription', '自动检测到支付成功', { orderId }); toast({ title: '支付成功!', description: '订阅已激活,正在跳转...', @@ -267,7 +278,7 @@ function Subscription() { duration: 3000, isClosable: true, }); - + // 延迟2秒后跳转到个人中心 setTimeout(() => { onPaymentModalClose(); @@ -276,10 +287,10 @@ function Subscription() { } } } catch (error) { - console.error('自动检查支付状态失败:', error); + logger.error('Subscription', 'startAutoPaymentCheck', error, { orderId }); } }, 10000); // 每10秒检查一次 - + setAutoCheckInterval(checkInterval); }; @@ -287,7 +298,7 @@ function Subscription() { if (autoCheckInterval) { clearInterval(autoCheckInterval); setAutoCheckInterval(null); - console.log('⏹️ 停止自动检查支付状态'); + logger.debug('Subscription', '停止自动检查支付状态'); } }; @@ -316,22 +327,26 @@ function Subscription() { // 强制更新支付状态 const handleForceUpdatePayment = async () => { if (!paymentOrder) return; - + setForceUpdating(true); try { const response = await fetch(`/api/payment/order/${paymentOrder.id}/force-update`, { method: 'POST', credentials: 'include' }); - + if (response.ok) { const data = await response.json(); - console.log('🔧 强制更新支付状态结果:', data); - + logger.info('Subscription', '强制更新支付状态结果', { + orderId: paymentOrder.id, + paymentSuccess: data.payment_success, + data + }); + if (data.success && data.payment_success) { // 支付成功 stopAutoPaymentCheck(); - + toast({ title: '状态更新成功!', description: '订阅已激活,正在刷新页面...', @@ -339,7 +354,7 @@ function Subscription() { duration: 3000, isClosable: true, }); - + setTimeout(() => { onPaymentModalClose(); window.location.reload(); @@ -357,6 +372,9 @@ function Subscription() { throw new Error('网络错误'); } } catch (error) { + logger.error('Subscription', 'handleForceUpdatePayment', error, { + orderId: paymentOrder?.id + }); toast({ title: '强制更新失败', description: error.message, @@ -372,24 +390,29 @@ function Subscription() { // 手动检查支付状态 const handleCheckPaymentStatus = async () => { if (!paymentOrder) return; - + setCheckingPayment(true); try { const response = await fetch(`/api/payment/order/${paymentOrder.id}/status`, { credentials: 'include' }); - + if (response.ok) { const data = await response.json(); - console.log('🔍 手动检查支付状态结果:', data); - console.log('🔍 支付成功标志:', data.payment_success); - console.log('🔍 订单数据:', data.data); - + logger.info('Subscription', '手动检查支付状态结果', { + orderId: paymentOrder.id, + paymentSuccess: data.payment_success, + data: data.data + }); + if (data.success) { if (data.payment_success) { // 支付成功 stopAutoPaymentCheck(); - + + logger.info('Subscription', '手动检测到支付成功', { + orderId: paymentOrder.id + }); toast({ title: '支付成功!', description: '订阅已激活,正在跳转...', @@ -397,12 +420,12 @@ function Subscription() { duration: 3000, isClosable: true, }); - + setTimeout(() => { onPaymentModalClose(); window.location.reload(); }, 2000); - + } else { // 还未支付 toast({ @@ -420,6 +443,9 @@ function Subscription() { throw new Error('网络错误'); } } catch (error) { + logger.error('Subscription', 'handleCheckPaymentStatus', error, { + orderId: paymentOrder?.id + }); toast({ title: '查询失败', description: error.message, @@ -788,8 +814,8 @@ function Subscription() { size='sm' variant='ghost' onClick={() => { - console.log('🔍 当前支付订单:', paymentOrder); - console.log('🔍 用户信息:', currentUser); + logger.debug('Subscription', '调试信息 - 当前支付订单', { paymentOrder }); + logger.debug('Subscription', '调试信息 - 用户信息', { currentUser }); }} > 调试信息 @@ -870,7 +896,11 @@ function Subscription() { -