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