diff --git a/src/views/Company/CompanyOverview.js b/src/views/Company/CompanyOverview.js index 44909a76..e4ab6372 100644 --- a/src/views/Company/CompanyOverview.js +++ b/src/views/Company/CompanyOverview.js @@ -15,10 +15,10 @@ import { chakra } from '@chakra-ui/react'; -import { +import { FaBuilding, FaMapMarkerAlt, FaChartLine, FaLightbulb, FaRocket, - FaNetworkWired, FaChevronDown, FaChevronUp, FaCog, FaTrophy, - FaShieldAlt, FaBrain, FaChartPie, FaHistory, FaCheckCircle, + FaNetworkWired, FaChevronDown, FaChevronUp, FaChevronLeft, FaChevronRight, + FaCog, FaTrophy, FaShieldAlt, FaBrain, FaChartPie, FaHistory, FaCheckCircle, FaExclamationCircle, FaArrowUp, FaArrowDown, FaLink, FaStar, FaUserTie, FaIndustry, FaDollarSign, FaBalanceScale, FaChartBar, FaEye, FaFlask, FaHandshake, FaUsers, FaClock, FaCalendarAlt, @@ -26,7 +26,7 @@ import { FaUniversity, FaGraduationCap, FaVenusMars, FaPassport, FaFileAlt, FaNewspaper, FaBullhorn, FaUserShield, FaShareAlt, FaSitemap, FaSearch, FaDownload, FaExternalLinkAlt, FaInfoCircle, FaCrown, - FaCertificate, FaAward, FaExpandAlt, FaCompressAlt + FaCertificate, FaAward, FaExpandAlt, FaCompressAlt, FaGavel, FaFire } from 'react-icons/fa'; import { @@ -797,6 +797,14 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { const [newsEvents, setNewsEvents] = useState([]); const [newsLoading, setNewsLoading] = useState(false); const [newsSearchQuery, setNewsSearchQuery] = useState(''); + const [newsPagination, setNewsPagination] = useState({ + page: 1, + per_page: 10, + total: 0, + pages: 0, + has_next: false, + has_prev: false + }); const [error, setError] = useState(null); @@ -886,38 +894,53 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { }, [stockCode]); // 加载新闻事件 - const loadNewsEvents = async (searchQuery = '') => { + const loadNewsEvents = async (page = 1, searchQuery = '') => { setNewsLoading(true); try { // 构建查询参数 const params = new URLSearchParams({ - per_page: '20', + page: page.toString(), + per_page: '10', sort: 'new', - include_creator: 'false', + include_creator: 'true', include_stats: 'true' }); - // 如果有搜索关键词,添加搜索参数 - if (searchQuery) { - params.append('q', searchQuery); - params.append('search_fields', 'title,description,content'); - } - - // 如果有股票代码,添加相关筛选(这里假设事件表有stock_code字段) - // 如果没有直接的stock_code字段,可以通过tags或keywords搜索 - if (basicInfo?.SECNAME) { - params.append('keywords', basicInfo.SECNAME); + // 搜索关键词优先级: + // 1. 用户输入的搜索关键词 + // 2. 股票简称 + const queryText = searchQuery || basicInfo?.SECNAME || ''; + if (queryText) { + params.append('q', queryText); } const response = await fetch(`${API_BASE_URL}/api/events?${params.toString()}`); const data = await response.json(); - // API可能返回 data.data.events 或 data.events + // API返回 data.data.events const events = data.data?.events || data.events || []; + const pagination = data.data?.pagination || { + page: 1, + per_page: 10, + total: 0, + pages: 0, + has_next: false, + has_prev: false + }; + setNewsEvents(events); + setNewsPagination(pagination); } catch (err) { - logger.error('CompanyOverview', 'loadNewsEvents', err, { stockCode, searchQuery }); + logger.error('CompanyOverview', 'loadNewsEvents', err, { stockCode, searchQuery, page }); setNewsEvents([]); + setNewsPagination({ + page: 1, + per_page: 10, + total: 0, + pages: 0, + has_next: false, + has_prev: false + }); } finally { setNewsLoading(false); } @@ -926,13 +949,20 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { // 当基本信息加载完成后,加载新闻事件 useEffect(() => { if (basicInfo) { - loadNewsEvents(); + loadNewsEvents(1); } }, [basicInfo]); // 处理搜索 const handleNewsSearch = () => { - loadNewsEvents(newsSearchQuery); + loadNewsEvents(1, newsSearchQuery); + }; + + // 处理分页 + const handleNewsPageChange = (newPage) => { + loadNewsEvents(newPage, newsSearchQuery); + // 滚动到新闻列表顶部 + document.getElementById('news-list-top')?.scrollIntoView({ behavior: 'smooth' }); }; // 管理层职位分类 @@ -2183,172 +2213,319 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { {/* 新闻动态标签页 */} - - - - {/* 搜索框 */} - - - - - - setNewsSearchQuery(e.target.value)} - onKeyPress={(e) => e.key === 'Enter' && handleNewsSearch()} - /> - - - + + + + + {/* 搜索框和统计信息 */} + + + + + + + setNewsSearchQuery(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleNewsSearch()} + /> + + + - {/* 新闻列表 */} - {newsLoading ? ( -
- - - 正在加载新闻... - -
- ) : newsEvents.length > 0 ? ( - - {newsEvents.map((event, idx) => { - const importanceColor = { - 'S': 'red', - 'A': 'orange', - 'B': 'yellow', - 'C': 'green' - }[event.importance] || 'gray'; + {newsPagination.total > 0 && ( + + + + 共找到 {newsPagination.total} 条新闻 + + + )} +
- return ( - - - - - - - - - {event.title} - - - - {event.importance && ( - - 重要度: {event.importance} - - )} - {event.event_type && ( - - {event.event_type} - - )} - {event.tags && event.tags.length > 0 && ( - <> - {event.tags.slice(0, 3).map((tag, tidx) => ( - - {tag} - - ))} - - )} - - - - - {event.created_at ? new Date(event.created_at).toLocaleDateString('zh-CN') : ''} - - {event.view_count && ( - - +
+ + {/* 新闻列表 */} + {newsLoading ? ( +
+ + + 正在加载新闻... + +
+ ) : newsEvents.length > 0 ? ( + <> + + {newsEvents.map((event, idx) => { + const importanceColor = { + 'S': 'red', + 'A': 'orange', + 'B': 'yellow', + 'C': 'green' + }[event.importance] || 'gray'; + + const eventTypeIcon = { + '企业公告': FaBullhorn, + '政策': FaGavel, + '技术突破': FaFlask, + '企业融资': FaDollarSign, + '政策监管': FaShieldAlt, + '政策动态': FaFileAlt, + '行业事件': FaIndustry + }[event.event_type] || FaNewspaper; + + return ( + + + + {/* 标题栏 */} + + + + + + {event.title} + + + + {/* 标签栏 */} + + {event.importance && ( + + {event.importance}级 + + )} + {event.event_type && ( + + {event.event_type} + + )} + {event.invest_score && ( + + 投资分: {event.invest_score} + + )} + {event.keywords && event.keywords.length > 0 && ( + <> + {event.keywords.slice(0, 4).map((keyword, kidx) => ( + + {keyword} + + ))} + + )} + + + + {/* 右侧信息栏 */} + - {event.view_count} + {event.created_at ? new Date(event.created_at).toLocaleDateString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }) : ''} - + + {event.view_count !== undefined && ( + + + {event.view_count} + + )} + {event.hot_score !== undefined && ( + + + {event.hot_score.toFixed(1)} + + )} + + {event.creator && ( + + @{event.creator.username} + + )} + + + + {/* 描述 */} + {event.description && ( + + {event.description} + + )} + + {/* 收益率数据 */} + {(event.related_avg_chg !== null || event.related_max_chg !== null || event.related_week_chg !== null) && ( + + + + + 相关涨跌: + + {event.related_avg_chg !== null && event.related_avg_chg !== undefined && ( + + 平均 + 0 ? 'red.500' : 'green.500'} + > + {event.related_avg_chg > 0 ? '+' : ''}{event.related_avg_chg.toFixed(2)}% + + + )} + {event.related_max_chg !== null && event.related_max_chg !== undefined && ( + + 最大 + 0 ? 'red.500' : 'green.500'} + > + {event.related_max_chg > 0 ? '+' : ''}{event.related_max_chg.toFixed(2)}% + + + )} + {event.related_week_chg !== null && event.related_week_chg !== undefined && ( + + + 0 ? 'red.500' : 'green.500'} + > + {event.related_week_chg > 0 ? '+' : ''}{event.related_week_chg.toFixed(2)}% + + + )} + + )} - + + + ); + })} + - {event.description && ( - - {event.description} - - )} + {/* 分页控件 */} + {newsPagination.pages > 1 && ( + + + {/* 分页信息 */} + + 第 {newsPagination.page} / {newsPagination.pages} 页 + - {(event.related_avg_chg !== null || event.related_max_chg !== null || event.related_week_chg !== null) && ( - - 相关涨跌: - {event.related_avg_chg !== null && event.related_avg_chg !== undefined && ( - - 平均: - 0 ? 'red.500' : 'green.500'} - > - {event.related_avg_chg > 0 ? '+' : ''}{event.related_avg_chg}% - - - )} - {event.related_max_chg !== null && event.related_max_chg !== undefined && ( - - 最大: - 0 ? 'red.500' : 'green.500'} - > - {event.related_max_chg > 0 ? '+' : ''}{event.related_max_chg}% - - - )} - {event.related_week_chg !== null && event.related_week_chg !== undefined && ( - - 周涨幅: - 0 ? 'red.500' : 'green.500'} - > - {event.related_week_chg > 0 ? '+' : ''}{event.related_week_chg}% - - - )} - - )} - - - - ); - })} - - ) : ( -
- - - 暂无相关新闻 - - {newsSearchQuery ? '尝试修改搜索关键词' : '该公司暂无新闻动态'} - - -
- )} - - - + {/* 分页按钮 */} + + + + + {/* 页码按钮 */} + {(() => { + const currentPage = newsPagination.page; + const totalPages = newsPagination.pages; + const pageButtons = []; + + // 显示当前页及前后各2页 + let startPage = Math.max(1, currentPage - 2); + let endPage = Math.min(totalPages, currentPage + 2); + + // 如果开始页大于1,显示省略号 + if (startPage > 1) { + pageButtons.push( + ... + ); + } + + for (let i = startPage; i <= endPage; i++) { + pageButtons.push( + + ); + } + + // 如果结束页小于总页数,显示省略号 + if (endPage < totalPages) { + pageButtons.push( + ... + ); + } + + return pageButtons; + })()} + + + + +
+
+ )} + + ) : ( +
+ + + 暂无相关新闻 + + {newsSearchQuery ? '尝试修改搜索关键词' : '该公司暂无新闻动态'} + + +
+ )} + + + +