feat:Community 组件 (2个文件,8个console)

- EventDetailModal.js - 2个
  - InvestmentCalendar.js - 6个

  EventDetail 组件 (5个文件,54个console)

  - TransmissionChainAnalysis.js - 43个 ⚠️ 最复杂
  - RelatedConcepts.js - 14个
  - LimitAnalyse.js - 5个 (保留2个toast)
  - RelatedStocks.js - 3个 (保留4个toast)
  - HistoricalEvents.js - 1个

  StockChart 组件 (1个文件,4个console)
This commit is contained in:
zdl
2025-10-18 10:23:23 +08:00
parent 3a3cac75f7
commit 87b77af187
5 changed files with 106 additions and 23 deletions

View File

@@ -6,6 +6,7 @@ import * as echarts from 'echarts';
import moment from 'moment'; import moment from 'moment';
import { stockService } from '../../services/eventService'; import { stockService } from '../../services/eventService';
import CitedContent from '../Citation/CitedContent'; import CitedContent from '../Citation/CitedContent';
import { logger } from '../../utils/logger';
const { Text } = Typography; const { Text } = Typography;
@@ -43,14 +44,25 @@ const StockChartAntdModal = ({
} }
} }
} catch (e) { } catch (e) {
console.warn('事件时间解析失败:', e); logger.warn('StockChartAntdModal', '事件时间解析失败', {
eventTime,
error: e.message
});
} }
} }
const response = await stockService.getKlineData(stock.stock_code, type, adjustedEventTime); const response = await stockService.getKlineData(stock.stock_code, type, adjustedEventTime);
setPreloadedData(prev => ({...prev, [type]: response})); setPreloadedData(prev => ({...prev, [type]: response}));
logger.debug('StockChartAntdModal', '数据预加载成功', {
stockCode: stock.stock_code,
type,
dataLength: response?.data?.length || 0
});
} catch (err) { } catch (err) {
console.error(`预加载${type}数据失败:`, err); logger.error('StockChartAntdModal', 'preloadData', err, {
stockCode: stock?.stock_code,
type
});
} }
}; };
@@ -89,7 +101,10 @@ const StockChartAntdModal = ({
} }
} }
} catch (e) { } catch (e) {
console.warn('事件时间解析失败:', e); logger.warn('StockChartAntdModal', '事件时间解析失败', {
eventTime,
error: e.message
});
} }
} }
@@ -97,8 +112,16 @@ const StockChartAntdModal = ({
} }
setChartData(data); setChartData(data);
logger.debug('StockChartAntdModal', '图表数据加载成功', {
stockCode: stock.stock_code,
chartType: activeChartType,
dataLength: data?.data?.length || 0
});
} catch (error) { } catch (error) {
console.error('加载图表数据失败:', error); logger.error('StockChartAntdModal', 'loadChartData', error, {
stockCode: stock?.stock_code,
chartType: activeChartType
});
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -41,6 +41,7 @@ import { FaHeart, FaRegHeart, FaComment } from 'react-icons/fa';
import { format } from 'date-fns'; import { format } from 'date-fns';
import { zhCN } from 'date-fns/locale'; import { zhCN } from 'date-fns/locale';
import { eventService } from '../../../services/eventService'; import { eventService } from '../../../services/eventService';
import { logger } from '../../../utils/logger';
const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussionType = '事件讨论' }) => { const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussionType = '事件讨论' }) => {
const [posts, setPosts] = useState([]); const [posts, setPosts] = useState([]);
@@ -73,7 +74,16 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
if (response.ok && result.success) { if (response.ok && result.success) {
setPosts(result.data || []); setPosts(result.data || []);
logger.debug('EventDiscussionModal', '帖子列表加载成功', {
eventId,
postsCount: result.data?.length || 0
});
} else { } else {
logger.error('EventDiscussionModal', 'loadPosts', new Error('API返回错误'), {
eventId,
status: response.status,
message: result.message
});
toast({ toast({
title: '加载帖子失败', title: '加载帖子失败',
status: 'error', status: 'error',
@@ -82,7 +92,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
}); });
} }
} catch (error) { } catch (error) {
console.error('Failed to load posts:', error); logger.error('EventDiscussionModal', 'loadPosts', error, { eventId });
toast({ toast({
title: '加载帖子失败', title: '加载帖子失败',
status: 'error', status: 'error',
@@ -107,9 +117,13 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
if (response.ok && result.success) { if (response.ok && result.success) {
setPostComments(prev => ({ ...prev, [postId]: result.data || [] })); setPostComments(prev => ({ ...prev, [postId]: result.data || [] }));
logger.debug('EventDiscussionModal', '评论加载成功', {
postId,
commentsCount: result.data?.length || 0
});
} }
} catch (error) { } catch (error) {
console.error('Failed to load comments:', error); logger.error('EventDiscussionModal', 'loadPostComments', error, { postId });
} finally { } finally {
setLoadingComments(prev => ({ ...prev, [postId]: false })); setLoadingComments(prev => ({ ...prev, [postId]: false }));
} }
@@ -147,6 +161,10 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
setNewPostContent(''); setNewPostContent('');
setNewPostTitle(''); setNewPostTitle('');
loadPosts(); loadPosts();
logger.info('EventDiscussionModal', '帖子发布成功', {
eventId,
postId: result.data?.id
});
toast({ toast({
title: '帖子发布成功', title: '帖子发布成功',
status: 'success', status: 'success',
@@ -154,6 +172,10 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
isClosable: true, isClosable: true,
}); });
} else { } else {
logger.error('EventDiscussionModal', 'handleSubmitPost', new Error('API返回错误'), {
eventId,
message: result.message
});
toast({ toast({
title: result.message || '帖子发布失败', title: result.message || '帖子发布失败',
status: 'error', status: 'error',
@@ -162,7 +184,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
}); });
} }
} catch (error) { } catch (error) {
console.error('Failed to submit post:', error); logger.error('EventDiscussionModal', 'handleSubmitPost', error, { eventId });
toast({ toast({
title: '帖子发布失败', title: '帖子发布失败',
status: 'error', status: 'error',
@@ -188,6 +210,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
if (response.ok && result.success) { if (response.ok && result.success) {
loadPosts(); loadPosts();
logger.info('EventDiscussionModal', '帖子删除成功', { postId });
toast({ toast({
title: '帖子已删除', title: '帖子已删除',
status: 'success', status: 'success',
@@ -195,6 +218,10 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
isClosable: true, isClosable: true,
}); });
} else { } else {
logger.error('EventDiscussionModal', 'handleDeletePost', new Error('API返回错误'), {
postId,
message: result.message
});
toast({ toast({
title: result.message || '删除失败', title: result.message || '删除失败',
status: 'error', status: 'error',
@@ -203,7 +230,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
}); });
} }
} catch (error) { } catch (error) {
console.error('Failed to delete post:', error); logger.error('EventDiscussionModal', 'handleDeletePost', error, { postId });
toast({ toast({
title: '删除失败', title: '删除失败',
status: 'error', status: 'error',
@@ -225,14 +252,19 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
if (response.ok && result.success) { if (response.ok && result.success) {
// 更新帖子列表中的点赞状态 // 更新帖子列表中的点赞状态
setPosts(prev => prev.map(post => setPosts(prev => prev.map(post =>
post.id === postId post.id === postId
? { ...post, likes_count: result.likes_count, liked: result.liked } ? { ...post, likes_count: result.likes_count, liked: result.liked }
: post : post
)); ));
logger.debug('EventDiscussionModal', '点赞操作成功', {
postId,
liked: result.liked,
likesCount: result.likes_count
});
} }
} catch (error) { } catch (error) {
console.error('Failed to like post:', error); logger.error('EventDiscussionModal', 'handleLikePost', error, { postId });
toast({ toast({
title: '操作失败', title: '操作失败',
status: 'error', status: 'error',
@@ -263,11 +295,15 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
// 重新加载该帖子的评论 // 重新加载该帖子的评论
await loadPostComments(postId); await loadPostComments(postId);
// 更新帖子的评论数 // 更新帖子的评论数
setPosts(prev => prev.map(post => setPosts(prev => prev.map(post =>
post.id === postId post.id === postId
? { ...post, comments_count: (post.comments_count || 0) + 1 } ? { ...post, comments_count: (post.comments_count || 0) + 1 }
: post : post
)); ));
logger.info('EventDiscussionModal', '评论发布成功', {
postId,
commentId: result.data?.id
});
toast({ toast({
title: '评论发布成功', title: '评论发布成功',
status: 'success', status: 'success',
@@ -276,7 +312,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
}); });
} }
} catch (error) { } catch (error) {
console.error('Failed to submit comment:', error); logger.error('EventDiscussionModal', 'handleSubmitComment', error, { postId });
toast({ toast({
title: '评论发布失败', title: '评论发布失败',
status: 'error', status: 'error',
@@ -302,11 +338,12 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
// 重新加载该帖子的评论 // 重新加载该帖子的评论
await loadPostComments(postId); await loadPostComments(postId);
// 更新帖子的评论数 // 更新帖子的评论数
setPosts(prev => prev.map(post => setPosts(prev => prev.map(post =>
post.id === postId post.id === postId
? { ...post, comments_count: Math.max(0, (post.comments_count || 0) - 1) } ? { ...post, comments_count: Math.max(0, (post.comments_count || 0) - 1) }
: post : post
)); ));
logger.info('EventDiscussionModal', '评论删除成功', { commentId, postId });
toast({ toast({
title: '评论已删除', title: '评论已删除',
status: 'success', status: 'success',
@@ -315,7 +352,7 @@ const EventDiscussionModal = ({ isOpen, onClose, eventId, eventTitle, discussion
}); });
} }
} catch (error) { } catch (error) {
console.error('Failed to delete comment:', error); logger.error('EventDiscussionModal', 'handleDeleteComment', error, { commentId, postId });
toast({ toast({
title: '删除失败', title: '删除失败',
status: 'error', status: 'error',

View File

@@ -5,6 +5,7 @@ import { FilterOutlined } from '@ant-design/icons';
import moment from 'moment'; import moment from 'moment';
import locale from 'antd/es/date-picker/locale/zh_CN'; import locale from 'antd/es/date-picker/locale/zh_CN';
import { industryService } from '../../../services/industryService'; import { industryService } from '../../../services/industryService';
import { logger } from '../../../utils/logger';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const { Option } = Select; const { Option } = Select;
@@ -36,8 +37,11 @@ const EventFilters = ({ filters, onFilterChange, loading }) => {
try { try {
const response = await industryService.getClassifications(); const response = await industryService.getClassifications();
setIndustryData(prev => ({ ...prev, classifications: response.data })); setIndustryData(prev => ({ ...prev, classifications: response.data }));
logger.debug('EventFilters', '行业分类加载成功', {
count: response.data?.length || 0
});
} catch (error) { } catch (error) {
console.error('Failed to load industry classifications:', error); logger.error('EventFilters', 'loadIndustryClassifications', error);
} }
}; };
@@ -50,8 +54,12 @@ const EventFilters = ({ filters, onFilterChange, loading }) => {
for (let l = level + 1; l <= 4; l++) { for (let l = level + 1; l <= 4; l++) {
setIndustryData(prev => ({ ...prev, [`level${l}`]: [] })); setIndustryData(prev => ({ ...prev, [`level${l}`]: [] }));
} }
logger.debug('EventFilters', '行业层级数据加载成功', {
level,
count: response.data?.length || 0
});
} catch (error) { } catch (error) {
console.error('Failed to load industry levels:', error); logger.error('EventFilters', 'loadIndustryLevels', error, { level, params });
} }
}; };

View File

@@ -51,6 +51,7 @@ import {
} from '@chakra-ui/icons'; } from '@chakra-ui/icons';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import moment from 'moment'; import moment from 'moment';
import { logger } from '../../../utils/logger';
// ========== 工具函数定义在组件外部 ========== // ========== 工具函数定义在组件外部 ==========
// 涨跌颜色配置中国A股配色红涨绿跌- 分档次显示 // 涨跌颜色配置中国A股配色红涨绿跌- 分档次显示
@@ -186,10 +187,12 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai
const map = {}; const map = {};
(data.data || []).forEach(ev => { map[ev.id] = true; }); (data.data || []).forEach(ev => { map[ev.id] = true; });
setFollowingMap(map); setFollowingMap(map);
logger.debug('EventList', '关注状态加载成功', {
followingCount: Object.keys(map).length
});
} }
} catch (e) { } catch (e) {
// 静默失败 logger.warn('EventList', '加载关注状态失败', { error: e.message });
console.warn('load following failed', e);
} }
}; };
loadFollowing(); loadFollowing();
@@ -210,8 +213,16 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai
const count = data.data?.follower_count ?? 0; const count = data.data?.follower_count ?? 0;
setFollowingMap(prev => ({ ...prev, [eventId]: isFollowing })); setFollowingMap(prev => ({ ...prev, [eventId]: isFollowing }));
setFollowCountMap(prev => ({ ...prev, [eventId]: count })); setFollowCountMap(prev => ({ ...prev, [eventId]: count }));
logger.debug('EventList', '关注状态切换成功', {
eventId,
isFollowing,
followerCount: count
});
} catch (e) { } catch (e) {
console.warn('toggle follow failed', e); logger.warn('EventList', '关注操作失败', {
eventId,
error: e.message
});
} }
}; };

View File

@@ -2,6 +2,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Card, Tag, Space, Spin, Empty, Button } from 'antd'; import { Card, Tag, Space, Spin, Empty, Button } from 'antd';
import { FireOutlined, RightOutlined } from '@ant-design/icons'; import { FireOutlined, RightOutlined } from '@ant-design/icons';
import { logger } from '../../../utils/logger';
const API_BASE_URL = process.env.NODE_ENV === 'production' const API_BASE_URL = process.env.NODE_ENV === 'production'
? '/concept-api' ? '/concept-api'
@@ -44,9 +45,12 @@ const PopularKeywords = ({ onKeywordClick }) => {
concept_id: item.concept_id concept_id: item.concept_id
})); }));
setKeywords(formattedData); setKeywords(formattedData);
logger.debug('PopularKeywords', '热门概念加载成功', {
count: formattedData.length
});
} }
} catch (error) { } catch (error) {
console.error('Failed to load popular concepts:', error); logger.error('PopularKeywords', 'loadPopularConcepts', error);
setKeywords([]); setKeywords([]);
} finally { } finally {
setLoading(false); setLoading(false);