diff --git a/src/views/Company/components/DynamicTracking/index.js b/src/views/Company/components/DynamicTracking/index.js index f7f76d64..fa9f1a9d 100644 --- a/src/views/Company/components/DynamicTracking/index.js +++ b/src/views/Company/components/DynamicTracking/index.js @@ -1,204 +1,65 @@ // src/views/Company/components/DynamicTracking/index.js // 动态跟踪 - 独立一级 Tab 组件(包含新闻动态等二级 Tab) -import React, { useState, useEffect, useCallback } from "react"; -import { - Box, - Tabs, - TabList, - TabPanels, - Tab, - TabPanel, -} from "@chakra-ui/react"; -import { FaNewspaper, FaBullhorn, FaCalendarAlt } from "react-icons/fa"; +import React, { useState, useEffect, useMemo } from 'react'; +import { Box } from '@chakra-ui/react'; +import { FaNewspaper, FaBullhorn, FaCalendarAlt, FaChartBar } from 'react-icons/fa'; -import { logger } from "@utils/logger"; -import { getApiBase } from "@utils/apiConfig"; -import NewsEventsTab from "../CompanyOverview/NewsEventsTab"; -import AnnouncementsPanel from "../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel"; -import DisclosureSchedulePanel from "../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel"; -import { THEME } from "../CompanyOverview/BasicInfoTab/config"; - -// API配置 -const API_BASE_URL = getApiBase(); +import SubTabContainer from '@components/SubTabContainer'; +import AnnouncementsPanel from '../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel'; +import DisclosureSchedulePanel from '../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel'; +import { NewsPanel, ForecastPanel } from './components'; // 二级 Tab 配置 const TRACKING_TABS = [ - { key: "news", name: "新闻动态", icon: FaNewspaper }, - { key: "announcements", name: "公司公告", icon: FaBullhorn }, - { key: "disclosure", name: "财报披露日程", icon: FaCalendarAlt }, + { key: 'news', name: '新闻动态', icon: FaNewspaper, component: NewsPanel }, + { key: 'announcements', name: '公司公告', icon: FaBullhorn, component: AnnouncementsPanel }, + { key: 'disclosure', name: '财报披露日程', icon: FaCalendarAlt, component: DisclosureSchedulePanel }, + { key: 'forecast', name: '业绩预告', icon: FaChartBar, component: ForecastPanel }, ]; /** * 动态跟踪组件 * * 功能: - * - 二级 Tab 结构 - * - Tab1: 新闻动态(复用 NewsEventsTab) - * - 预留后续扩展 + * - 使用 SubTabContainer 实现二级导航 + * - Tab1: 新闻动态 + * - Tab2: 公司公告 + * - Tab3: 财报披露日程 + * - Tab4: 业绩预告 * * @param {Object} props * @param {string} props.stockCode - 股票代码 */ const DynamicTracking = ({ stockCode: propStockCode }) => { - const [stockCode, setStockCode] = useState(propStockCode || "000001"); + const [stockCode, setStockCode] = useState(propStockCode || '000001'); const [activeTab, setActiveTab] = useState(0); - // 新闻动态状态 - const [newsEvents, setNewsEvents] = useState([]); - const [newsLoading, setNewsLoading] = useState(false); - const [newsPagination, setNewsPagination] = useState({ - page: 1, - per_page: 10, - total: 0, - pages: 0, - has_next: false, - has_prev: false, - }); - const [searchQuery, setSearchQuery] = useState(""); - const [stockName, setStockName] = useState(""); - const [dataLoaded, setDataLoaded] = useState(false); - // 监听 props 中的 stockCode 变化 useEffect(() => { if (propStockCode && propStockCode !== stockCode) { setStockCode(propStockCode); - setDataLoaded(false); - setNewsEvents([]); - setStockName(""); - setSearchQuery(""); } }, [propStockCode, stockCode]); - // 获取股票名称(用于搜索) - const fetchStockName = useCallback(async () => { - try { - const response = await fetch( - `${API_BASE_URL}/api/stock/${stockCode}/basic-info` - ); - const result = await response.json(); - if (result.success && result.data) { - const name = result.data.SECNAME || result.data.ORGNAME || stockCode; - setStockName(name); - return name; - } - return stockCode; - } catch (err) { - logger.error("DynamicTracking", "fetchStockName", err, { stockCode }); - return stockCode; - } - }, [stockCode]); - - // 加载新闻事件数据 - const loadNewsEvents = useCallback( - async (query, page = 1) => { - setNewsLoading(true); - try { - const searchTerm = query || stockName || stockCode; - const response = await fetch( - `${API_BASE_URL}/api/events?q=${encodeURIComponent(searchTerm)}&page=${page}&per_page=10` - ); - const result = await response.json(); - - if (result.success) { - setNewsEvents(result.data || []); - setNewsPagination({ - page: result.pagination?.page || page, - per_page: result.pagination?.per_page || 10, - total: result.pagination?.total || 0, - pages: result.pagination?.pages || 0, - has_next: result.pagination?.has_next || false, - has_prev: result.pagination?.has_prev || false, - }); - } - } catch (err) { - logger.error("DynamicTracking", "loadNewsEvents", err, { stockCode }); - setNewsEvents([]); - } finally { - setNewsLoading(false); - } - }, - [stockCode, stockName] + // 传递给子组件的 props + const componentProps = useMemo( + () => ({ + stockCode, + }), + [stockCode] ); - // 首次加载 - useEffect(() => { - const initLoad = async () => { - if (stockCode && !dataLoaded) { - const name = await fetchStockName(); - await loadNewsEvents(name, 1); - setDataLoaded(true); - } - }; - initLoad(); - }, [stockCode, dataLoaded, fetchStockName, loadNewsEvents]); - - // 搜索处理 - const handleSearchChange = (value) => { - setSearchQuery(value); - }; - - const handleSearch = () => { - loadNewsEvents(searchQuery || stockName, 1); - }; - - // 分页处理 - const handlePageChange = (page) => { - loadNewsEvents(searchQuery || stockName, page); - }; - return ( - - + setActiveTab(index)} isLazy - > - - {TRACKING_TABS.map((tab) => ( - - {tab.name} - - ))} - - - - {/* 新闻动态 Tab */} - - - - - {/* 公司公告 Tab */} - - - - - {/* 财报披露日程 Tab */} - - - - - + /> ); };