update pay promo
This commit is contained in:
@@ -10,7 +10,7 @@ import type { KLineModuleProps, OverlayMetricData } from '../../../types';
|
||||
import type { ChartMode } from './constants';
|
||||
|
||||
// 子组件导入
|
||||
import { KLineToolbar, DailyKLineChart, MinuteChartWithOrderBook } from './components';
|
||||
import { KLineToolbar, DailyKLineChart, MinuteChartWithOrderBook, IndicatorGuide } from './components';
|
||||
|
||||
// 重新导出类型供外部使用
|
||||
export type { KLineModuleProps } from '../../../types';
|
||||
@@ -40,6 +40,7 @@ const KLineModule: React.FC<KLineModuleProps> = ({
|
||||
const [drawingType, setDrawingType] = useState<DrawingType>('NONE');
|
||||
const [overlayMetrics, setOverlayMetrics] = useState<OverlayMetricData[]>([]);
|
||||
const [showOrderBook, setShowOrderBook] = useState<boolean>(true);
|
||||
const [showIndicatorGuide, setShowIndicatorGuide] = useState<boolean>(false);
|
||||
|
||||
// ========== 计算属性 ==========
|
||||
const hasMinuteData = minuteData && minuteData.data && minuteData.data.length > 0;
|
||||
@@ -73,6 +74,11 @@ const KLineModule: React.FC<KLineModuleProps> = ({
|
||||
setShowOrderBook(prev => !prev);
|
||||
}, []);
|
||||
|
||||
// 切换显示/隐藏指标说明
|
||||
const handleToggleIndicatorGuide = useCallback(() => {
|
||||
setShowIndicatorGuide(prev => !prev);
|
||||
}, []);
|
||||
|
||||
// 添加叠加指标
|
||||
const handleAddOverlayMetric = useCallback((metric: OverlayMetricData) => {
|
||||
setOverlayMetrics(prev => [...prev, metric]);
|
||||
@@ -119,6 +125,8 @@ const KLineModule: React.FC<KLineModuleProps> = ({
|
||||
onAddOverlayMetric={handleAddOverlayMetric}
|
||||
onRemoveOverlayMetric={handleRemoveOverlayMetric}
|
||||
stockDateRange={stockDateRange}
|
||||
showIndicatorGuide={showIndicatorGuide}
|
||||
onToggleIndicatorGuide={handleToggleIndicatorGuide}
|
||||
minuteData={minuteData}
|
||||
minuteLoading={minuteLoading}
|
||||
showOrderBook={showOrderBook}
|
||||
@@ -126,6 +134,9 @@ const KLineModule: React.FC<KLineModuleProps> = ({
|
||||
onRefreshMinuteData={onLoadMinuteData}
|
||||
/>
|
||||
|
||||
{/* 指标说明面板(可折叠) */}
|
||||
{mode === 'daily' && <IndicatorGuide isOpen={showIndicatorGuide} />}
|
||||
|
||||
{/* 图表内容区域 */}
|
||||
<Box pt={4}>
|
||||
{/* 加载中骨架屏 */}
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
// src/views/Company/components/MarketDataView/components/panels/TradeDataPanel/components/IndicatorGuide.tsx
|
||||
// 技术指标说明组件 - 可折叠面板
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Text,
|
||||
VStack,
|
||||
HStack,
|
||||
Collapse,
|
||||
Badge,
|
||||
SimpleGrid,
|
||||
Divider,
|
||||
} from '@chakra-ui/react';
|
||||
import { darkGoldTheme } from '../../../../constants';
|
||||
|
||||
interface IndicatorGuideProps {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
// 自定义颜色(补充主题中没有的颜色)
|
||||
const INDICATOR_COLORS = {
|
||||
cyan: '#00BCD4',
|
||||
magenta: '#E040FB',
|
||||
gold: darkGoldTheme.gold,
|
||||
green: darkGoldTheme.green,
|
||||
orange: darkGoldTheme.orange,
|
||||
};
|
||||
|
||||
// 指标说明数据
|
||||
const INDICATOR_DEFINITIONS = {
|
||||
main: [
|
||||
{
|
||||
name: 'MA(移动平均线)',
|
||||
abbr: 'MA',
|
||||
formula: 'MA(N) = 最近N日收盘价之和 / N',
|
||||
description: '反映一段时间内的平均成本,用于判断趋势方向。',
|
||||
params: 'MA5、MA10、MA20',
|
||||
usage: '短期MA上穿长期MA为金叉(买入信号),下穿为死叉(卖出信号)',
|
||||
color: INDICATOR_COLORS.cyan,
|
||||
},
|
||||
{
|
||||
name: 'BOLL(布林带)',
|
||||
abbr: 'BOLL',
|
||||
formula: '中轨 = MA(20)\n上轨 = 中轨 + 2×标准差\n下轨 = 中轨 - 2×标准差',
|
||||
description: '基于统计学原理,显示价格的波动范围和趋势。',
|
||||
params: '周期20,标准差倍数2',
|
||||
usage: '价格触及上轨可能超买,触及下轨可能超卖;收窄预示变盘',
|
||||
color: INDICATOR_COLORS.magenta,
|
||||
},
|
||||
],
|
||||
sub: [
|
||||
{
|
||||
name: 'MACD(平滑异同移动平均线)',
|
||||
abbr: 'MACD',
|
||||
formula: 'DIF = EMA(12) - EMA(26)\nDEA = EMA(DIF, 9)\nMACD柱 = (DIF - DEA) × 2',
|
||||
description: '趋势跟踪指标,用于判断买卖时机和趋势强弱。',
|
||||
params: '快线12,慢线26,信号线9',
|
||||
usage: 'DIF上穿DEA为金叉(买入),下穿为死叉(卖出);柱状体由负转正看多',
|
||||
color: INDICATOR_COLORS.gold,
|
||||
},
|
||||
{
|
||||
name: 'KDJ(随机指标)',
|
||||
abbr: 'KDJ',
|
||||
formula: 'RSV = (收盘价-最低价)/(最高价-最低价)×100\nK = 2/3×前K + 1/3×RSV\nD = 2/3×前D + 1/3×K\nJ = 3K - 2D',
|
||||
description: '动量指标,反映价格相对于近期波动范围的位置。',
|
||||
params: '周期9,K平滑3,D平滑3',
|
||||
usage: 'K/D<20超卖区,>80超买区;K上穿D为金叉;J值>100超买,<0超卖',
|
||||
color: INDICATOR_COLORS.cyan,
|
||||
},
|
||||
{
|
||||
name: 'RSI(相对强弱指标)',
|
||||
abbr: 'RSI',
|
||||
formula: 'RS = 平均涨幅 / 平均跌幅\nRSI = 100 - 100/(1+RS)',
|
||||
description: '衡量价格变动的速度和幅度,判断超买超卖。',
|
||||
params: 'RSI6(短期)、RSI12(中期)、RSI24(长期)',
|
||||
usage: 'RSI>70超买区,<30超卖区;背离现象预示反转',
|
||||
color: INDICATOR_COLORS.magenta,
|
||||
},
|
||||
{
|
||||
name: 'WR(威廉指标)',
|
||||
abbr: 'WR',
|
||||
formula: 'WR = (最高价-收盘价)/(最高价-最低价)×(-100)',
|
||||
description: '衡量市场的超买超卖程度,数值在-100到0之间。',
|
||||
params: 'WR6、WR14',
|
||||
usage: 'WR<-80超卖,>-20超买;从超买/超卖区回落时为反转信号',
|
||||
color: INDICATOR_COLORS.green,
|
||||
},
|
||||
{
|
||||
name: 'CCI(商品通道指标)',
|
||||
abbr: 'CCI',
|
||||
formula: 'TP = (最高+最低+收盘)/3\nCCI = (TP-MA(TP))/(0.015×平均绝对偏差)',
|
||||
description: '测量价格偏离统计平均值的程度,适用于周期性波动。',
|
||||
params: '周期14',
|
||||
usage: 'CCI>+100超买,<-100超卖;突破±100为趋势启动信号',
|
||||
color: INDICATOR_COLORS.orange,
|
||||
},
|
||||
{
|
||||
name: 'BIAS(乖离率)',
|
||||
abbr: 'BIAS',
|
||||
formula: 'BIAS = (收盘价-MA)/MA × 100%',
|
||||
description: '衡量价格偏离移动平均线的程度,用于判断回归。',
|
||||
params: 'BIAS6、BIAS12、BIAS24',
|
||||
usage: '正值过大表示超买,负值过大表示超卖;均值回归时机',
|
||||
color: INDICATOR_COLORS.cyan,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const IndicatorCard: React.FC<{
|
||||
indicator: typeof INDICATOR_DEFINITIONS.main[0];
|
||||
}> = ({ indicator }) => {
|
||||
return (
|
||||
<Box
|
||||
p={3}
|
||||
bg="rgba(26, 32, 44, 0.6)"
|
||||
borderRadius="md"
|
||||
border="1px solid"
|
||||
borderColor="rgba(212, 175, 55, 0.2)"
|
||||
_hover={{ borderColor: 'rgba(212, 175, 55, 0.4)' }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<HStack justify="space-between" mb={2}>
|
||||
<HStack spacing={2}>
|
||||
<Badge
|
||||
bg={indicator.color}
|
||||
color="black"
|
||||
fontSize="xs"
|
||||
fontWeight="bold"
|
||||
px={2}
|
||||
py={0.5}
|
||||
borderRadius="sm"
|
||||
>
|
||||
{indicator.abbr}
|
||||
</Badge>
|
||||
<Text fontSize="sm" fontWeight="bold" color="white">
|
||||
{indicator.name}
|
||||
</Text>
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
<VStack align="stretch" spacing={1.5} fontSize="xs">
|
||||
<Box>
|
||||
<Text color={darkGoldTheme.textMuted} mb={0.5}>计算公式</Text>
|
||||
<Text
|
||||
color="rgba(255, 255, 255, 0.8)"
|
||||
fontFamily="mono"
|
||||
whiteSpace="pre-line"
|
||||
bg="rgba(0, 0, 0, 0.3)"
|
||||
px={2}
|
||||
py={1}
|
||||
borderRadius="sm"
|
||||
>
|
||||
{indicator.formula}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text color={darkGoldTheme.textMuted} mb={0.5}>参数设置</Text>
|
||||
<Text color="rgba(255, 255, 255, 0.7)">{indicator.params}</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text color={darkGoldTheme.textMuted} mb={0.5}>使用方法</Text>
|
||||
<Text color="rgba(255, 255, 255, 0.7)">{indicator.usage}</Text>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const IndicatorGuide: React.FC<IndicatorGuideProps> = ({ isOpen }) => {
|
||||
return (
|
||||
<Collapse in={isOpen} animateOpacity>
|
||||
<Box
|
||||
mt={3}
|
||||
p={4}
|
||||
bg="rgba(26, 32, 44, 0.8)"
|
||||
borderRadius="lg"
|
||||
border="1px solid"
|
||||
borderColor="rgba(212, 175, 55, 0.3)"
|
||||
backdropFilter="blur(10px)"
|
||||
>
|
||||
<VStack align="stretch" spacing={4}>
|
||||
{/* 标题 */}
|
||||
<HStack justify="space-between">
|
||||
<Text
|
||||
fontSize="md"
|
||||
fontWeight="bold"
|
||||
bgGradient={`linear(to-r, ${darkGoldTheme.gold}, ${darkGoldTheme.orange})`}
|
||||
bgClip="text"
|
||||
>
|
||||
技术指标说明
|
||||
</Text>
|
||||
<Text fontSize="xs" color={darkGoldTheme.textMuted}>
|
||||
点击「指标说明」按钮可收起此面板
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
{/* 主图指标 */}
|
||||
<Box>
|
||||
<HStack mb={2}>
|
||||
<Badge
|
||||
bg="rgba(212, 175, 55, 0.2)"
|
||||
color={darkGoldTheme.gold}
|
||||
fontSize="xs"
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
主图指标
|
||||
</Badge>
|
||||
<Text fontSize="xs" color={darkGoldTheme.textMuted}>
|
||||
叠加在K线图上显示
|
||||
</Text>
|
||||
</HStack>
|
||||
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={3}>
|
||||
{INDICATOR_DEFINITIONS.main.map((indicator) => (
|
||||
<IndicatorCard key={indicator.abbr} indicator={indicator} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
|
||||
<Divider borderColor="rgba(212, 175, 55, 0.2)" />
|
||||
|
||||
{/* 副图指标 */}
|
||||
<Box>
|
||||
<HStack mb={2}>
|
||||
<Badge
|
||||
bg="rgba(212, 175, 55, 0.2)"
|
||||
color={darkGoldTheme.gold}
|
||||
fontSize="xs"
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
副图指标
|
||||
</Badge>
|
||||
<Text fontSize="xs" color={darkGoldTheme.textMuted}>
|
||||
显示在K线图下方独立区域
|
||||
</Text>
|
||||
</HStack>
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={3}>
|
||||
{INDICATOR_DEFINITIONS.sub.map((indicator) => (
|
||||
<IndicatorCard key={indicator.abbr} indicator={indicator} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
|
||||
{/* 风险提示 */}
|
||||
<Box
|
||||
p={3}
|
||||
bg="rgba(239, 68, 68, 0.1)"
|
||||
borderRadius="md"
|
||||
border="1px solid"
|
||||
borderColor="rgba(239, 68, 68, 0.3)"
|
||||
>
|
||||
<Text fontSize="xs" color="rgba(239, 68, 68, 0.9)">
|
||||
⚠️ 风险提示:技术指标仅供参考,不构成投资建议。市场有风险,投资需谨慎。建议结合基本面分析和市场环境综合判断。
|
||||
</Text>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
</Collapse>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(IndicatorGuide);
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
MenuItem,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { BarChart2, TrendingUp, Calendar, LineChart, Activity, Pencil, RefreshCw, ChevronDown, Eye, EyeOff } from 'lucide-react';
|
||||
import { BarChart2, TrendingUp, Calendar, LineChart, Activity, Pencil, RefreshCw, ChevronDown, Eye, EyeOff, HelpCircle } from 'lucide-react';
|
||||
|
||||
import { darkGoldTheme, PERIOD_OPTIONS } from '../../../../constants';
|
||||
import type { IndicatorType, MainIndicatorType, DrawingType } from '../../../../utils/chartOptions';
|
||||
@@ -59,6 +59,10 @@ export interface KLineToolbarProps {
|
||||
onRemoveOverlayMetric: (metricId: string) => void;
|
||||
stockDateRange?: { startDate: string; endDate: string };
|
||||
|
||||
// 指标说明
|
||||
showIndicatorGuide: boolean;
|
||||
onToggleIndicatorGuide: () => void;
|
||||
|
||||
// 分时模式
|
||||
minuteData?: MinuteData | null;
|
||||
minuteLoading: boolean;
|
||||
@@ -84,6 +88,8 @@ const KLineToolbar: React.FC<KLineToolbarProps> = ({
|
||||
onAddOverlayMetric,
|
||||
onRemoveOverlayMetric,
|
||||
stockDateRange,
|
||||
showIndicatorGuide,
|
||||
onToggleIndicatorGuide,
|
||||
minuteData,
|
||||
minuteLoading,
|
||||
showOrderBook,
|
||||
@@ -274,6 +280,20 @@ const KLineToolbar: React.FC<KLineToolbarProps> = ({
|
||||
onRemoveMetric={onRemoveOverlayMetric}
|
||||
stockDateRange={stockDateRange}
|
||||
/>
|
||||
|
||||
{/* 指标说明按钮 */}
|
||||
<Tooltip label={showIndicatorGuide ? '收起指标说明' : '展开指标说明'} placement="top" hasArrow>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
leftIcon={<HelpCircle size={14} />}
|
||||
onClick={onToggleIndicatorGuide}
|
||||
{...(showIndicatorGuide ? ACTIVE_BUTTON_STYLE : INACTIVE_BUTTON_STYLE)}
|
||||
minW="90px"
|
||||
>
|
||||
指标说明
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@@ -9,3 +9,5 @@ export type { DailyKLineChartProps } from './DailyKLineChart';
|
||||
|
||||
export { default as MinuteChartWithOrderBook } from './MinuteChartWithOrderBook';
|
||||
export type { MinuteChartWithOrderBookProps } from './MinuteChartWithOrderBook';
|
||||
|
||||
export { default as IndicatorGuide } from './IndicatorGuide';
|
||||
|
||||
Reference in New Issue
Block a user