增加主力数据
This commit is contained in:
@@ -1,28 +1,25 @@
|
||||
/**
|
||||
* MainForceInfo - 主力动态原子组件
|
||||
*
|
||||
* 显示主力资金和机构相关指标:
|
||||
* - 主力净流入(带正负颜色)
|
||||
* - 机构持仓比例
|
||||
* - 买卖比例进度条
|
||||
* 显示主力资金流向指标(数据来源:stock_main_capital_flow 表):
|
||||
* - 主力净流入(万元,带正负颜色)
|
||||
* - 主力流入占比(%)
|
||||
* - 净主动买入占比(%,进度条展示)
|
||||
*
|
||||
* 注意:标题由外层 GlassSection 提供
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { Box, VStack, HStack, Text, Progress } from '@chakra-ui/react';
|
||||
import { formatNetInflow } from './formatters';
|
||||
import { DEEP_SPACE_THEME as T } from './theme';
|
||||
|
||||
export interface MainForceInfoProps {
|
||||
/** 主力净流入(亿) */
|
||||
mainNetInflow: number;
|
||||
/** 机构持仓比例(%) */
|
||||
institutionHolding: number;
|
||||
/** 买入比例(%) */
|
||||
buyRatio: number;
|
||||
/** 卖出比例(%) */
|
||||
sellRatio: number;
|
||||
/** 主力净流入(万元) */
|
||||
netInflow: number | null;
|
||||
/** 主力净流入量占比(%) */
|
||||
mainInflowRatio: number | null;
|
||||
/** 净主动买入额占比(%) */
|
||||
netActiveBuyRatio: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,6 +51,32 @@ const MetricRow: React.FC<MetricRowProps> = ({
|
||||
</HStack>
|
||||
);
|
||||
|
||||
/**
|
||||
* 格式化主力净流入显示
|
||||
* 根据数值大小自动选择万/亿单位
|
||||
*/
|
||||
const formatNetInflowValue = (value: number | null): string => {
|
||||
if (value === null || value === undefined) return '--';
|
||||
const absValue = Math.abs(value);
|
||||
const sign = value >= 0 ? '+' : '';
|
||||
|
||||
if (absValue >= 10000) {
|
||||
// 超过1亿,显示为亿
|
||||
return `${sign}${(value / 10000).toFixed(2)}亿`;
|
||||
}
|
||||
// 否则显示万
|
||||
return `${sign}${value.toFixed(2)}万`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化百分比显示
|
||||
*/
|
||||
const formatPercent = (value: number | null): string => {
|
||||
if (value === null || value === undefined) return '--';
|
||||
const sign = value >= 0 ? '+' : '';
|
||||
return `${sign}${value.toFixed(2)}%`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 主力动态展示组件
|
||||
*
|
||||
@@ -61,51 +84,75 @@ const MetricRow: React.FC<MetricRowProps> = ({
|
||||
* 应由 GlassSection 包装以提供标题
|
||||
*/
|
||||
export const MainForceInfo: React.FC<MainForceInfoProps> = memo(({
|
||||
mainNetInflow,
|
||||
institutionHolding,
|
||||
buyRatio,
|
||||
sellRatio,
|
||||
netInflow,
|
||||
mainInflowRatio,
|
||||
netActiveBuyRatio,
|
||||
}) => {
|
||||
const inflowColor = mainNetInflow >= 0 ? T.upColor : T.downColor;
|
||||
const inflowColor = (netInflow ?? 0) >= 0 ? T.upColor : T.downColor;
|
||||
const ratioColor = (mainInflowRatio ?? 0) >= 0 ? T.upColor : T.downColor;
|
||||
|
||||
// 净主动买入占比用于进度条,范围可能是 -100 ~ 100,需要转换
|
||||
// 负值表示主动卖出多,正值表示主动买入多
|
||||
const buyRatioValue = netActiveBuyRatio ?? 0;
|
||||
// 转换为 0-100 的进度条值(50为中点)
|
||||
const progressValue = Math.min(100, Math.max(0, 50 + buyRatioValue / 2));
|
||||
|
||||
return (
|
||||
<VStack align="stretch" spacing={2}>
|
||||
<MetricRow
|
||||
label="主力净流入"
|
||||
value={formatNetInflow(mainNetInflow)}
|
||||
value={formatNetInflowValue(netInflow)}
|
||||
valueColor={inflowColor}
|
||||
highlight
|
||||
/>
|
||||
<MetricRow
|
||||
label="机构持仓"
|
||||
value={`${institutionHolding.toFixed(2)}%`}
|
||||
valueColor={T.purple}
|
||||
label="流入占比"
|
||||
value={formatPercent(mainInflowRatio)}
|
||||
valueColor={ratioColor}
|
||||
highlight
|
||||
/>
|
||||
|
||||
{/* 买卖比例进度条 */}
|
||||
{/* 净主动买入占比进度条 */}
|
||||
<Box mt={2}>
|
||||
<Progress
|
||||
value={buyRatio}
|
||||
size="sm"
|
||||
sx={{
|
||||
'& > div': {
|
||||
bg: T.upColor,
|
||||
boxShadow: T.upGlow,
|
||||
},
|
||||
}}
|
||||
bg={T.downColor}
|
||||
borderRadius="full"
|
||||
h="8px"
|
||||
/>
|
||||
<HStack justify="space-between" mt={2} fontSize="13px">
|
||||
<Text color={T.upColor} fontWeight="600">
|
||||
买入 {buyRatio}%
|
||||
</Text>
|
||||
<Text color={T.downColor} fontWeight="600">
|
||||
卖出 {sellRatio}%
|
||||
<HStack justify="space-between" mb={1} fontSize="12px">
|
||||
<Text color={T.textMuted}>净主动买入</Text>
|
||||
<Text
|
||||
color={buyRatioValue >= 0 ? T.upColor : T.downColor}
|
||||
fontWeight="600"
|
||||
>
|
||||
{formatPercent(netActiveBuyRatio)}
|
||||
</Text>
|
||||
</HStack>
|
||||
<Box position="relative">
|
||||
<Progress
|
||||
value={progressValue}
|
||||
size="sm"
|
||||
sx={{
|
||||
'& > div': {
|
||||
bg: buyRatioValue >= 0 ? T.upColor : T.downColor,
|
||||
boxShadow: buyRatioValue >= 0 ? T.upGlow : T.downGlow,
|
||||
transition: 'all 0.3s ease',
|
||||
},
|
||||
}}
|
||||
bg="rgba(255,255,255,0.1)"
|
||||
borderRadius="full"
|
||||
h="8px"
|
||||
/>
|
||||
{/* 中点标记 */}
|
||||
<Box
|
||||
position="absolute"
|
||||
left="50%"
|
||||
top="0"
|
||||
bottom="0"
|
||||
w="2px"
|
||||
bg="rgba(255,255,255,0.3)"
|
||||
transform="translateX(-50%)"
|
||||
/>
|
||||
</Box>
|
||||
<HStack justify="space-between" mt={1} fontSize="11px">
|
||||
<Text color={T.downColor}>卖出</Text>
|
||||
<Text color={T.upColor}>买入</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</VStack>
|
||||
);
|
||||
|
||||
@@ -19,11 +19,3 @@ export const formatChangePercent = (percent: number): string => {
|
||||
const sign = percent >= 0 ? '+' : '';
|
||||
return `${sign}${percent.toFixed(2)}%`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化主力净流入显示
|
||||
*/
|
||||
export const formatNetInflow = (value: number): string => {
|
||||
const sign = value >= 0 ? '+' : '';
|
||||
return `${sign}${value.toFixed(2)}亿`;
|
||||
};
|
||||
|
||||
@@ -42,11 +42,10 @@ const transformQuoteData = (apiData: any, stockCode: string): StockQuoteCardData
|
||||
week52Low: apiData.week52_low || apiData.week52Low || 0,
|
||||
week52High: apiData.week52_high || apiData.week52High || 0,
|
||||
|
||||
// 主力动态
|
||||
mainNetInflow: apiData.main_net_inflow || apiData.mainNetInflow || 0,
|
||||
institutionHolding: apiData.institution_holding || apiData.institutionHolding || 0,
|
||||
buyRatio: apiData.buy_ratio || apiData.buyRatio || 50,
|
||||
sellRatio: apiData.sell_ratio || apiData.sellRatio || 50,
|
||||
// 主力动态(数据来源:stock_main_capital_flow 表)
|
||||
netInflow: apiData.net_inflow ?? apiData.netInflow ?? null, // 主力净流入量(万元)
|
||||
mainInflowRatio: apiData.main_inflow_ratio ?? apiData.mainInflowRatio ?? null, // 主力净流入量占比(%)
|
||||
netActiveBuyRatio: apiData.net_active_buy_ratio ?? apiData.netActiveBuyRatio ?? null, // 净主动买入额占比(%)
|
||||
|
||||
// 更新时间
|
||||
updateTime: apiData.update_time || apiData.updateTime || new Date().toLocaleString(),
|
||||
|
||||
@@ -179,10 +179,9 @@ const StockQuoteCard: React.FC<StockQuoteCardProps> = ({
|
||||
{/* 第三列:主力动态 */}
|
||||
<GlassSection title="主力动态" flex={1}>
|
||||
<MainForceInfo
|
||||
mainNetInflow={quoteData.mainNetInflow || 0}
|
||||
institutionHolding={quoteData.institutionHolding}
|
||||
buyRatio={quoteData.buyRatio}
|
||||
sellRatio={quoteData.sellRatio}
|
||||
netInflow={quoteData.netInflow}
|
||||
mainInflowRatio={quoteData.mainInflowRatio}
|
||||
netActiveBuyRatio={quoteData.netActiveBuyRatio}
|
||||
/>
|
||||
</GlassSection>
|
||||
</Flex>
|
||||
|
||||
@@ -33,11 +33,10 @@ export interface StockQuoteCardData {
|
||||
week52Low: number; // 52周最低
|
||||
week52High: number; // 52周最高
|
||||
|
||||
// 主力动态
|
||||
mainNetInflow: number; // 主力净流入(亿)
|
||||
institutionHolding: number; // 机构持仓比例(百分比)
|
||||
buyRatio: number; // 买入比例(百分比)
|
||||
sellRatio: number; // 卖出比例(百分比)
|
||||
// 主力动态(数据来源:stock_main_capital_flow 表)
|
||||
netInflow: number | null; // 主力净流入量(万元)
|
||||
mainInflowRatio: number | null; // 主力净流入量占比(%)
|
||||
netActiveBuyRatio: number | null; // 净主动买入额占比(%)
|
||||
|
||||
// 更新时间
|
||||
updateTime: string; // 格式:YYYY-MM-DD HH:mm:ss
|
||||
|
||||
Reference in New Issue
Block a user