From 94854fee3ec3cfbeba4b415615dfb24fd6611e2a Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Fri, 19 Dec 2025 14:20:46 +0800 Subject: [PATCH] =?UTF-8?q?refactor(MarketDataView):=20=E6=8F=90=E5=8F=96?= =?UTF-8?q?=20DataRow=20=E5=8E=9F=E5=AD=90=E7=BB=84=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 shared/DataRow.tsx:通用数据行组件(支持 gold/orange/red/green 变体) - 新增样式常量:financingRowStyle, securitiesRowStyle, buyRowStyle, sellRowStyle, dayCardStyle - FundingPanel: 使用 useMemo 缓存图表配置和数据,使用 DataRow 替代重复结构 - BigDealPanel: 使用 dayCardStyle 替代内联样式 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../components/panels/BigDealPanel.tsx | 10 +- .../components/panels/FundingPanel.tsx | 110 +++----- .../components/panels/UnusualPanel.tsx | 238 +++++++----------- .../components/shared/DataRow.tsx | 84 +++++++ .../MarketDataView/components/shared/index.ts | 18 +- .../components/shared/styles.ts | 75 ++++++ 6 files changed, 306 insertions(+), 229 deletions(-) create mode 100644 src/views/Company/components/MarketDataView/components/shared/DataRow.tsx diff --git a/src/views/Company/components/MarketDataView/components/panels/BigDealPanel.tsx b/src/views/Company/components/MarketDataView/components/panels/BigDealPanel.tsx index 81ebd87a..f52b6492 100644 --- a/src/views/Company/components/MarketDataView/components/panels/BigDealPanel.tsx +++ b/src/views/Company/components/MarketDataView/components/panels/BigDealPanel.tsx @@ -20,6 +20,7 @@ import { import { formatNumber } from '../../utils/formatUtils'; import { darkGoldTheme } from '../../constants'; import { DarkGoldCard, DarkGoldBadge, EmptyState } from '../shared'; +import { dayCardStyle } from '../shared/styles'; import type { BigDealData } from '../../types'; export interface BigDealPanelProps { @@ -32,14 +33,7 @@ const BigDealPanel: React.FC = ({ bigDealData }) => { {bigDealData?.daily_stats && bigDealData.daily_stats.length > 0 ? ( {bigDealData.daily_stats.map((dayStats, idx) => ( - + {dayStats.date} diff --git a/src/views/Company/components/MarketDataView/components/panels/FundingPanel.tsx b/src/views/Company/components/MarketDataView/components/panels/FundingPanel.tsx index a64db755..c0c66380 100644 --- a/src/views/Company/components/MarketDataView/components/panels/FundingPanel.tsx +++ b/src/views/Company/components/MarketDataView/components/panels/FundingPanel.tsx @@ -1,21 +1,14 @@ // src/views/Company/components/MarketDataView/components/panels/FundingPanel.tsx // 融资融券面板 - 黑金主题 -import React, { memo } from 'react'; -import { - Box, - Text, - VStack, - HStack, - Grid, - Heading, -} from '@chakra-ui/react'; +import React, { memo, useMemo } from 'react'; +import { Box, VStack, Grid } from '@chakra-ui/react'; import ECharts from '@components/Charts/ECharts'; import { formatNumber } from '../../utils/formatUtils'; import { getFundingDarkGoldOption } from '../../utils/chartOptions'; import { darkGoldTheme } from '../../constants'; -import { DarkGoldCard } from '../shared'; +import { DarkGoldCard, DataRow } from '../shared'; import { darkGoldCardFullStyle } from '../shared/styles'; import type { FundingDayData } from '../../types'; @@ -24,6 +17,17 @@ export interface FundingPanelProps { } const FundingPanel: React.FC = ({ fundingData }) => { + // 缓存图表配置 + const chartOption = useMemo(() => { + if (fundingData.length === 0) return {}; + return getFundingDarkGoldOption(fundingData); + }, [fundingData]); + + // 缓存最近5条数据(倒序) + const recentData = useMemo(() => { + return fundingData.slice(-5).reverse(); + }, [fundingData]); + return ( {/* 图表卡片 */} @@ -31,7 +35,7 @@ const FundingPanel: React.FC = ({ fundingData }) => { {fundingData.length > 0 && ( @@ -43,78 +47,30 @@ const FundingPanel: React.FC = ({ fundingData }) => { {/* 融资数据 */} - {fundingData - .slice(-5) - .reverse() - .map((item, idx) => ( - - - - {item.date} - - - - {formatNumber(item.financing.balance)} - - - 买入{formatNumber(item.financing.buy)} / 偿还 - {formatNumber(item.financing.repay)} - - - - - ))} + {recentData.map((item, idx) => ( + + ))} {/* 融券数据 */} - {fundingData - .slice(-5) - .reverse() - .map((item, idx) => ( - - - - {item.date} - - - - {formatNumber(item.securities.balance)} - - - 卖出{formatNumber(item.securities.sell)} / 偿还 - {formatNumber(item.securities.repay)} - - - - - ))} + {recentData.map((item, idx) => ( + + ))} diff --git a/src/views/Company/components/MarketDataView/components/panels/UnusualPanel.tsx b/src/views/Company/components/MarketDataView/components/panels/UnusualPanel.tsx index 95270f54..dbdda0b2 100644 --- a/src/views/Company/components/MarketDataView/components/panels/UnusualPanel.tsx +++ b/src/views/Company/components/MarketDataView/components/panels/UnusualPanel.tsx @@ -2,17 +2,12 @@ // 龙虎榜面板 - 黑金主题 import React, { memo } from 'react'; -import { - Box, - Text, - VStack, - HStack, - Grid, -} from '@chakra-ui/react'; +import { Box, Text, VStack, HStack, Grid } from '@chakra-ui/react'; import { formatNumber } from '../../utils/formatUtils'; import { darkGoldTheme } from '../../constants'; -import { DarkGoldCard, DarkGoldBadge, EmptyState } from '../shared'; +import { DarkGoldCard, DarkGoldBadge, EmptyState, DataRow } from '../shared'; +import { dayCardStyle } from '../shared/styles'; import type { UnusualData } from '../../types'; export interface UnusualPanelProps { @@ -23,144 +18,101 @@ const UnusualPanel: React.FC = ({ unusualData }) => { return ( {unusualData?.grouped_data && unusualData.grouped_data.length > 0 ? ( - - {unusualData.grouped_data.map((dayData, idx) => ( - - - - {dayData.date} - - - - 买入: {formatNumber(dayData.total_buy)} - - - 卖出: {formatNumber(dayData.total_sell)} - - 0 ? 'red' : 'green'}> - 净额: {formatNumber(dayData.net_amount)} - - + + {unusualData.grouped_data.map((dayData, idx) => ( + + + + {dayData.date} + + + + 买入: {formatNumber(dayData.total_buy)} + + + 卖出: {formatNumber(dayData.total_sell)} + + 0 ? 'red' : 'green'}> + 净额: {formatNumber(dayData.net_amount)} + + - - - - 买入前五 - - - {dayData.buyers && dayData.buyers.length > 0 ? ( - dayData.buyers.slice(0, 5).map((buyer, i) => ( - - - {buyer.dept_name} - - - {formatNumber(buyer.buy_amount)} - - - )) - ) : ( - - 暂无数据 - - )} - - - - - - 卖出前五 - - - {dayData.sellers && dayData.sellers.length > 0 ? ( - dayData.sellers.slice(0, 5).map((seller, i) => ( - - - {seller.dept_name} - - - {formatNumber(seller.sell_amount)} - - - )) - ) : ( - - 暂无数据 - - )} - - - - - {/* 信息类型标签 */} - - - 类型: + + + + 买入前五 - {dayData.info_types?.map((type, i) => ( - - {type} - - ))} - - - ))} - - ) : ( - - )} + + {dayData.buyers && dayData.buyers.length > 0 ? ( + dayData.buyers.slice(0, 5).map((buyer, i) => ( + + )) + ) : ( + + 暂无数据 + + )} + + + + + + 卖出前五 + + + {dayData.sellers && dayData.sellers.length > 0 ? ( + dayData.sellers.slice(0, 5).map((seller, i) => ( + + )) + ) : ( + + 暂无数据 + + )} + + + + + {/* 信息类型标签 */} + + + 类型: + + {dayData.info_types?.map((type, i) => ( + + {type} + + ))} + + + ))} + + ) : ( + + )} ); }; diff --git a/src/views/Company/components/MarketDataView/components/shared/DataRow.tsx b/src/views/Company/components/MarketDataView/components/shared/DataRow.tsx new file mode 100644 index 00000000..62f66e05 --- /dev/null +++ b/src/views/Company/components/MarketDataView/components/shared/DataRow.tsx @@ -0,0 +1,84 @@ +// src/views/Company/components/MarketDataView/components/shared/DataRow.tsx +// 通用数据行原子组件 + +import React, { memo } from 'react'; +import { Box, Text, VStack, HStack } from '@chakra-ui/react'; + +import { darkGoldTheme } from '../../constants'; +import { + financingRowStyle, + securitiesRowStyle, + buyRowStyle, + sellRowStyle, +} from './styles'; + +export type DataRowVariant = 'gold' | 'orange' | 'red' | 'green'; + +export interface DataRowProps { + /** 样式变体 */ + variant: DataRowVariant; + /** 左侧标签 */ + label: React.ReactNode; + /** 主要值 */ + value: React.ReactNode; + /** 次要值(可选) */ + subValue?: React.ReactNode; + /** 标签是否可截断 */ + isTruncated?: boolean; + /** 标签最大宽度 */ + maxLabelWidth?: string; +} + +// 样式映射 +const styleMap = { + gold: financingRowStyle, + orange: securitiesRowStyle, + red: buyRowStyle, + green: sellRowStyle, +}; + +// 颜色映射 +const colorMap = { + gold: darkGoldTheme.gold, + orange: darkGoldTheme.orange, + red: darkGoldTheme.red, + green: darkGoldTheme.green, +}; + +/** + * 通用数据行组件 + * 用于融资融券、龙虎榜等列表展示 + */ +const DataRow: React.FC = ({ + variant, + label, + value, + subValue, + isTruncated = false, + maxLabelWidth, +}) => { + return ( + + + {label} + + + + {value} + + {subValue && ( + + {subValue} + + )} + + + ); +}; + +export default memo(DataRow); diff --git a/src/views/Company/components/MarketDataView/components/shared/index.ts b/src/views/Company/components/MarketDataView/components/shared/index.ts index e2316013..16633ffd 100644 --- a/src/views/Company/components/MarketDataView/components/shared/index.ts +++ b/src/views/Company/components/MarketDataView/components/shared/index.ts @@ -4,5 +4,21 @@ export { default as DarkGoldCard } from './DarkGoldCard'; export { default as DarkGoldBadge } from './DarkGoldBadge'; export { default as EmptyState } from './EmptyState'; -export { darkGoldCardStyle, darkGoldCardHoverStyle } from './styles'; +export { default as DataRow } from './DataRow'; + +export { + darkGoldCardStyle, + darkGoldCardHoverStyle, + darkGoldCardFullStyle, + dataRowStyle, + tableRowHoverStyle, + tableBorderStyle, + financingRowStyle, + securitiesRowStyle, + buyRowStyle, + sellRowStyle, + dayCardStyle, +} from './styles'; + export type { DarkGoldBadgeVariant } from './DarkGoldBadge'; +export type { DataRowVariant, DataRowProps } from './DataRow'; diff --git a/src/views/Company/components/MarketDataView/components/shared/styles.ts b/src/views/Company/components/MarketDataView/components/shared/styles.ts index 76d48e37..e091ebb1 100644 --- a/src/views/Company/components/MarketDataView/components/shared/styles.ts +++ b/src/views/Company/components/MarketDataView/components/shared/styles.ts @@ -57,3 +57,78 @@ export const tableBorderStyle: SystemStyleObject = { borderBottom: '1px solid', borderColor: 'rgba(212, 175, 55, 0.1)', }; + +/** + * 融资行样式 (金色主题) + */ +export const financingRowStyle: SystemStyleObject = { + p: 3, + bg: 'rgba(212, 175, 55, 0.08)', + borderRadius: 'md', + border: '1px solid', + borderColor: 'rgba(212, 175, 55, 0.15)', + transition: 'all 0.2s', + _hover: { + bg: 'rgba(212, 175, 55, 0.12)', + borderColor: 'rgba(212, 175, 55, 0.3)', + }, +}; + +/** + * 融券行样式 (橙色主题) + */ +export const securitiesRowStyle: SystemStyleObject = { + p: 3, + bg: 'rgba(255, 149, 0, 0.08)', + borderRadius: 'md', + border: '1px solid', + borderColor: 'rgba(255, 149, 0, 0.15)', + transition: 'all 0.2s', + _hover: { + bg: 'rgba(255, 149, 0, 0.12)', + borderColor: 'rgba(255, 149, 0, 0.3)', + }, +}; + +/** + * 买入行样式 (红色主题) + */ +export const buyRowStyle: SystemStyleObject = { + p: 2, + bg: 'rgba(255, 68, 68, 0.08)', + borderRadius: 'md', + border: '1px solid', + borderColor: 'rgba(255, 68, 68, 0.15)', + transition: 'all 0.2s', + _hover: { + bg: 'rgba(255, 68, 68, 0.12)', + borderColor: 'rgba(255, 68, 68, 0.3)', + }, +}; + +/** + * 卖出行样式 (绿色主题) + */ +export const sellRowStyle: SystemStyleObject = { + p: 2, + bg: 'rgba(0, 200, 81, 0.08)', + borderRadius: 'md', + border: '1px solid', + borderColor: 'rgba(0, 200, 81, 0.15)', + transition: 'all 0.2s', + _hover: { + bg: 'rgba(0, 200, 81, 0.12)', + borderColor: 'rgba(0, 200, 81, 0.3)', + }, +}; + +/** + * 日期数据卡片样式 + */ +export const dayCardStyle: SystemStyleObject = { + p: 4, + bg: 'rgba(212, 175, 55, 0.05)', + borderRadius: 'lg', + border: '1px solid', + borderColor: 'rgba(212, 175, 55, 0.15)', +};