feat: 添加Company 页面 Tab 切换组件
This commit is contained in:
45
src/views/Company/components/CompanyTabs/TabNavigation.js
Normal file
45
src/views/Company/components/CompanyTabs/TabNavigation.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// src/views/Company/components/CompanyTabs/TabNavigation.js
|
||||
// Tab 导航组件 - 动态渲染 Tab 按钮
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
TabList,
|
||||
Tab,
|
||||
HStack,
|
||||
Icon,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { COMPANY_TABS, TAB_SELECTED_STYLE } from '../../constants';
|
||||
|
||||
/**
|
||||
* Tab 导航组件
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {string} props.tabBg - Tab 列表背景色
|
||||
* @param {string} props.activeBg - 激活状态背景色
|
||||
*/
|
||||
const TabNavigation = ({ tabBg, activeBg }) => {
|
||||
return (
|
||||
<TabList p={4} bg={tabBg}>
|
||||
{COMPANY_TABS.map((tab, index) => (
|
||||
<Tab
|
||||
key={tab.key}
|
||||
_selected={{
|
||||
bg: activeBg,
|
||||
color: 'white',
|
||||
...TAB_SELECTED_STYLE,
|
||||
}}
|
||||
mr={index < COMPANY_TABS.length - 1 ? 2 : 0}
|
||||
>
|
||||
<HStack spacing={2}>
|
||||
<Icon as={tab.icon} />
|
||||
<Text>{tab.name}</Text>
|
||||
</HStack>
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabNavigation;
|
||||
100
src/views/Company/components/CompanyTabs/index.js
Normal file
100
src/views/Company/components/CompanyTabs/index.js
Normal file
@@ -0,0 +1,100 @@
|
||||
// src/views/Company/components/CompanyTabs/index.js
|
||||
// Tab 容器组件 - 管理 Tab 切换和内容渲染
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardBody,
|
||||
Tabs,
|
||||
TabPanels,
|
||||
TabPanel,
|
||||
Divider,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import TabNavigation from './TabNavigation';
|
||||
import { COMPANY_TABS, getTabNameByIndex } from '../../constants';
|
||||
|
||||
// 子组件导入
|
||||
import FinancialPanorama from '../../FinancialPanorama';
|
||||
import ForecastReport from '../../ForecastReport';
|
||||
import MarketDataView from '../../MarketDataView';
|
||||
import CompanyOverview from '../../CompanyOverview';
|
||||
|
||||
/**
|
||||
* Tab 组件映射
|
||||
* key 与 COMPANY_TABS 中的 key 对应
|
||||
*/
|
||||
const TAB_COMPONENTS = {
|
||||
overview: CompanyOverview,
|
||||
market: MarketDataView,
|
||||
financial: FinancialPanorama,
|
||||
forecast: ForecastReport,
|
||||
};
|
||||
|
||||
/**
|
||||
* Tab 容器组件
|
||||
*
|
||||
* 功能:
|
||||
* - 管理 Tab 切换状态
|
||||
* - 动态渲染 Tab 导航和内容
|
||||
* - 触发 Tab 变更追踪
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {string} props.stockCode - 当前股票代码
|
||||
* @param {Function} props.onTabChange - Tab 变更回调 (index, tabName, prevIndex) => void
|
||||
* @param {string} props.bgColor - 背景颜色
|
||||
*/
|
||||
const CompanyTabs = ({ stockCode, onTabChange, bgColor }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// 主题相关颜色
|
||||
const tabBg = useColorModeValue('gray.50', 'gray.700');
|
||||
const activeBg = useColorModeValue('blue.500', 'blue.400');
|
||||
|
||||
/**
|
||||
* 处理 Tab 切换
|
||||
*/
|
||||
const handleTabChange = (index) => {
|
||||
const tabName = getTabNameByIndex(index);
|
||||
|
||||
// 触发追踪回调
|
||||
onTabChange?.(index, tabName, currentIndex);
|
||||
|
||||
// 更新状态
|
||||
setCurrentIndex(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card bg={bgColor} shadow="lg">
|
||||
<CardBody p={0}>
|
||||
<Tabs
|
||||
variant="soft-rounded"
|
||||
colorScheme="blue"
|
||||
size="lg"
|
||||
index={currentIndex}
|
||||
onChange={handleTabChange}
|
||||
>
|
||||
{/* Tab 导航 */}
|
||||
<TabNavigation tabBg={tabBg} activeBg={activeBg} />
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* Tab 内容面板 */}
|
||||
<TabPanels>
|
||||
{COMPANY_TABS.map((tab) => {
|
||||
const Component = TAB_COMPONENTS[tab.key];
|
||||
return (
|
||||
<TabPanel key={tab.key} p={6}>
|
||||
<Component stockCode={stockCode} />
|
||||
</TabPanel>
|
||||
);
|
||||
})}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompanyTabs;
|
||||
53
src/views/Company/constants/index.js
Normal file
53
src/views/Company/constants/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// src/views/Company/constants/index.js
|
||||
// 公司详情页面常量配置
|
||||
|
||||
import { FaChartLine, FaMoneyBillWave, FaChartBar, FaInfoCircle } from 'react-icons/fa';
|
||||
|
||||
/**
|
||||
* Tab 配置
|
||||
* @type {Array<{key: string, name: string, icon: React.ComponentType}>}
|
||||
*/
|
||||
export const COMPANY_TABS = [
|
||||
{ key: 'overview', name: '公司概览', icon: FaInfoCircle },
|
||||
{ key: 'market', name: '股票行情', icon: FaChartLine },
|
||||
{ key: 'financial', name: '财务全景', icon: FaMoneyBillWave },
|
||||
{ key: 'forecast', name: '盈利预测', icon: FaChartBar },
|
||||
];
|
||||
|
||||
/**
|
||||
* Tab 选中状态样式
|
||||
*/
|
||||
export const TAB_SELECTED_STYLE = {
|
||||
transform: 'scale(1.02)',
|
||||
transition: 'all 0.2s',
|
||||
};
|
||||
|
||||
/**
|
||||
* Toast 消息配置
|
||||
*/
|
||||
export const TOAST_MESSAGES = {
|
||||
WATCHLIST_ADD: { title: '已加入自选', status: 'success', duration: 1500 },
|
||||
WATCHLIST_REMOVE: { title: '已从自选移除', status: 'info', duration: 1500 },
|
||||
WATCHLIST_ERROR: { title: '操作失败,请稍后重试', status: 'error', duration: 2000 },
|
||||
INVALID_CODE: { title: '无效的股票代码', status: 'error', duration: 2000 },
|
||||
LOGIN_REQUIRED: { title: '请先登录后再加入自选', status: 'warning', duration: 2000 },
|
||||
};
|
||||
|
||||
/**
|
||||
* 默认股票代码
|
||||
*/
|
||||
export const DEFAULT_STOCK_CODE = '000001';
|
||||
|
||||
/**
|
||||
* URL 参数名
|
||||
*/
|
||||
export const URL_PARAM_NAME = 'scode';
|
||||
|
||||
/**
|
||||
* 根据索引获取 Tab 名称
|
||||
* @param {number} index - Tab 索引
|
||||
* @returns {string} Tab 名称
|
||||
*/
|
||||
export const getTabNameByIndex = (index) => {
|
||||
return COMPANY_TABS[index]?.name || 'Unknown';
|
||||
};
|
||||
Reference in New Issue
Block a user