refactor(MarketDataView): 使用通用 SubTabContainer 简化代码

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-16 15:29:05 +08:00
parent 91ed649220
commit 00f2937a34

View File

@@ -1,37 +1,31 @@
// src/views/Company/components/MarketDataView/index.tsx // src/views/Company/components/MarketDataView/index.tsx
// MarketDataView 主组件 - 股票市场数据综合展示 // MarketDataView 主组件 - 股票市场数据综合展示
import React, { useState, useEffect, ReactNode } from 'react'; import React, { useState, useEffect, ReactNode, useMemo, useCallback } from 'react';
import { import {
Box, Box,
Container, Container,
Tabs,
TabList,
TabPanels,
Tab,
TabPanel,
Text,
CardBody, CardBody,
Spinner, Spinner,
Center, Center,
VStack, VStack,
HStack, Text,
Select,
Button,
Icon,
useDisclosure, useDisclosure,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { import {
ChevronUpIcon, ChevronUp,
RepeatIcon, Unlock,
ArrowUpIcon, ArrowUp,
StarIcon, Star,
LockIcon, Lock,
UnlockIcon, } from 'lucide-react';
} from '@chakra-ui/icons';
// 通用组件
import SubTabContainer from '@components/SubTabContainer';
import type { SubTabConfig } from '@components/SubTabContainer';
// 内部模块导入 // 内部模块导入
import { themes, DEFAULT_PERIOD, PERIOD_OPTIONS } from './constants'; import { themes, DEFAULT_PERIOD } from './constants';
import { useMarketData } from './hooks/useMarketData'; import { useMarketData } from './hooks/useMarketData';
import { import {
ThemedCard, ThemedCard,
@@ -88,7 +82,8 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
}, [propStockCode, stockCode]); }, [propStockCode, stockCode]);
// 处理图表点击事件 // 处理图表点击事件
const handleChartClick = (params: { seriesName?: string; data?: [number, number] }) => { const handleChartClick = useCallback(
(params: { seriesName?: string; data?: [number, number] }) => {
if (params.seriesName === '涨幅分析' && params.data) { if (params.seriesName === '涨幅分析' && params.data) {
const dataIndex = params.data[0]; const dataIndex = params.data[0];
const analysis = analysisMap[dataIndex]; const analysis = analysisMap[dataIndex];
@@ -98,12 +93,56 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
onOpen(); onOpen();
} }
} }
}; },
[analysisMap, theme, onOpen]
);
// Tab 配置 - 使用通用 SubTabContainer
const tabConfigs: SubTabConfig[] = [
{ key: 'trade', name: '交易数据', icon: ChevronUp, component: TradeDataPanel },
{ key: 'funding', name: '融资融券', icon: Unlock, component: FundingPanel },
{ key: 'bigDeal', name: '大宗交易', icon: ArrowUp, component: BigDealPanel },
{ key: 'unusual', name: '龙虎榜', icon: Star, component: UnusualPanel },
{ key: 'pledge', name: '股权质押', icon: Lock, component: PledgePanel },
];
// 传递给 Tab 组件的 props
const componentProps = useMemo(
() => ({
theme,
tradeData,
minuteData,
minuteLoading,
analysisMap,
onLoadMinuteData: loadMinuteData,
onChartClick: handleChartClick,
selectedPeriod,
onPeriodChange: setSelectedPeriod,
fundingData,
bigDealData,
unusualData,
pledgeData,
}),
[
theme,
tradeData,
minuteData,
minuteLoading,
analysisMap,
loadMinuteData,
handleChartClick,
selectedPeriod,
fundingData,
bigDealData,
unusualData,
pledgeData,
]
);
return ( return (
<Box bg={theme.bgMain} minH="100vh" color={theme.textPrimary}> <Box bg={'#1A202C'} minH="100vh" color={theme.textPrimary}>
<Container maxW="container.xl" py={6}> <Container maxW="container.xl" py={6}>
<VStack spacing={6} align="stretch"> <VStack align="stretch">
{/* 股票概览 */} {/* 股票概览 */}
{summary && <StockSummaryCard summary={summary} theme={theme} />} {summary && <StockSummaryCard summary={summary} theme={theme} />}
@@ -126,152 +165,14 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
</CardBody> </CardBody>
</ThemedCard> </ThemedCard>
) : ( ) : (
<Tabs <SubTabContainer
variant="soft-rounded" tabs={tabConfigs}
colorScheme="blue" componentProps={componentProps}
themePreset="blackGold"
index={activeTab} index={activeTab}
onChange={setActiveTab} onTabChange={(index) => setActiveTab(index)}
> isLazy
{/* Tab 导航栏 */}
<Box
bg={theme.bgCard}
p={4}
borderRadius="xl"
border="1px solid"
borderColor={theme.border}
>
<HStack justify="space-between" align="center" spacing={4}>
<TabList overflowX="auto" border="none" flex="1">
<Tab
color={theme.textMuted}
_selected={{ color: 'white', bg: theme.primary }}
fontSize="sm"
px={3}
>
<HStack spacing={1}>
<Icon as={ChevronUpIcon} boxSize={4} />
<Text></Text>
</HStack>
</Tab>
<Tab
color={theme.textMuted}
_selected={{ color: 'white', bg: theme.primary }}
fontSize="sm"
px={3}
>
<HStack spacing={1}>
<Icon as={UnlockIcon} boxSize={4} />
<Text></Text>
</HStack>
</Tab>
<Tab
color={theme.textMuted}
_selected={{ color: 'white', bg: theme.primary }}
fontSize="sm"
px={3}
>
<HStack spacing={1}>
<Icon as={ArrowUpIcon} boxSize={4} />
<Text></Text>
</HStack>
</Tab>
<Tab
color={theme.textMuted}
_selected={{ color: 'white', bg: theme.primary }}
fontSize="sm"
px={3}
>
<HStack spacing={1}>
<Icon as={StarIcon} boxSize={4} />
<Text></Text>
</HStack>
</Tab>
<Tab
color={theme.textMuted}
_selected={{ color: 'white', bg: theme.primary }}
fontSize="sm"
px={3}
>
<HStack spacing={1}>
<Icon as={LockIcon} boxSize={4} />
<Text></Text>
</HStack>
</Tab>
</TabList>
{/* 时间范围选择和刷新按钮 */}
<HStack spacing={2} flexShrink={0} ml="auto">
<Text color={theme.textPrimary} whiteSpace="nowrap" fontSize="sm">
</Text>
<Select
size="sm"
value={selectedPeriod}
onChange={(e) => setSelectedPeriod(Number(e.target.value))}
bg={theme.bgDark}
borderColor={theme.border}
color={theme.textPrimary}
maxW="120px"
>
{PERIOD_OPTIONS.map((option) => (
<option
key={option.value}
value={option.value}
style={{ background: theme.bgDark }}
>
{option.label}
</option>
))}
</Select>
<Button
leftIcon={<RepeatIcon />}
variant="outline"
colorScheme="blue"
onClick={refetch}
isLoading={loading}
size="sm"
>
</Button>
</HStack>
</HStack>
</Box>
<TabPanels>
{/* 交易数据 Tab */}
<TabPanel px={0}>
<TradeDataPanel
theme={theme}
tradeData={tradeData}
minuteData={minuteData}
minuteLoading={minuteLoading}
analysisMap={analysisMap}
onLoadMinuteData={loadMinuteData}
onChartClick={handleChartClick}
/> />
</TabPanel>
{/* 融资融券 Tab */}
<TabPanel px={0}>
<FundingPanel theme={theme} fundingData={fundingData} />
</TabPanel>
{/* 大宗交易 Tab */}
<TabPanel px={0}>
<BigDealPanel theme={theme} bigDealData={bigDealData} />
</TabPanel>
{/* 龙虎榜 Tab */}
<TabPanel px={0}>
<UnusualPanel theme={theme} unusualData={unusualData} />
</TabPanel>
{/* 股权质押 Tab */}
<TabPanel px={0}>
<PledgePanel theme={theme} pledgeData={pledgeData} />
</TabPanel>
</TabPanels>
</Tabs>
)} )}
</VStack> </VStack>
</Container> </Container>