refactor(MarketDataView): 使用通用 SubTabContainer 简化代码
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user