/** * KLineChart 主题配置 * * 适配 klinecharts@10.0.0-beta1 * 参考: https://github.com/klinecharts/KLineChart/blob/main/docs/en-US/guide/styles.md */ /* eslint-disable @typescript-eslint/no-explicit-any */ // ⚠️ 使用 any 类型绕过 KLineChart 类型定义的限制(beta 版本类型不完整) import type { DeepPartial, Styles } from 'klinecharts'; /** * 图表主题颜色配置 */ export const CHART_COLORS = { // 涨跌颜色(中国市场习惯:红涨绿跌) up: '#ef5350', // 上涨红色 down: '#26a69a', // 下跌绿色 neutral: '#888888', // 平盘灰色 // 主题色(继承自 Argon Dashboard) primary: '#1b3bbb', // Navy 500 secondary: '#728fea', // Navy 300 background: '#ffffff', backgroundDark: '#1B254B', // 文本颜色 text: '#333333', textSecondary: '#888888', textDark: '#ffffff', // 网格颜色 grid: '#e0e0e0', gridDark: '#2d3748', // 边框颜色 border: '#e0e0e0', borderDark: '#2d3748', // 事件标记颜色 eventMarker: '#ff9800', eventMarkerText: '#ffffff', }; /** * 浅色主题配置(默认) */ export const lightTheme: any = { candle: { type: 'candle_solid', // 实心蜡烛图 bar: { upColor: CHART_COLORS.up, downColor: CHART_COLORS.down, noChangeColor: CHART_COLORS.neutral, }, priceMark: { show: true, high: { color: CHART_COLORS.up, }, low: { color: CHART_COLORS.down, }, }, tooltip: { showRule: 'always', showType: 'standard', // labels: ['时间: ', '开: ', '收: ', '高: ', '低: ', '成交量: '], // ❌ KLineChart 类型不支持自定义 labels text: { size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', color: CHART_COLORS.text, }, }, }, indicator: { tooltip: { showRule: 'always', showType: 'standard', text: { size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', color: CHART_COLORS.text, }, }, }, xAxis: { axisLine: { show: true, color: CHART_COLORS.border, }, tickLine: { show: true, length: 3, color: CHART_COLORS.border, }, tickText: { show: true, color: CHART_COLORS.textSecondary, family: 'Helvetica, Arial, sans-serif', weight: 'normal', size: 12, }, }, yAxis: { axisLine: { show: true, color: CHART_COLORS.border, }, tickLine: { show: true, length: 3, color: CHART_COLORS.border, }, tickText: { show: true, color: CHART_COLORS.textSecondary, family: 'Helvetica, Arial, sans-serif', weight: 'normal', size: 12, }, type: 'normal', // 'normal' | 'percentage' | 'log' }, grid: { show: true, horizontal: { show: true, size: 1, color: CHART_COLORS.grid, style: 'dashed', }, vertical: { show: false, // 垂直网格线通常关闭,避免过于密集 }, }, separator: { size: 1, color: CHART_COLORS.border, }, crosshair: { show: true, horizontal: { show: true, line: { show: true, style: 'dashed', dashedValue: [4, 2], // ✅ 修复: 使用 dashedValue 而非 dashValue size: 1, color: CHART_COLORS.primary, }, text: { show: true, color: CHART_COLORS.textDark, size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', backgroundColor: CHART_COLORS.primary, }, }, vertical: { show: true, line: { show: true, style: 'dashed', dashedValue: [4, 2], // ✅ 修复: 使用 dashedValue 而非 dashValue size: 1, color: CHART_COLORS.primary, }, text: { show: true, color: CHART_COLORS.textDark, size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', backgroundColor: CHART_COLORS.primary, }, }, }, overlay: { // 事件标记覆盖层样式 point: { color: CHART_COLORS.eventMarker, borderColor: CHART_COLORS.eventMarker, borderSize: 1, radius: 5, activeColor: CHART_COLORS.eventMarker, activeBorderColor: CHART_COLORS.eventMarker, activeBorderSize: 2, activeRadius: 6, }, line: { style: 'solid', smooth: false, color: CHART_COLORS.eventMarker, size: 1, dashedValue: [2, 2], }, text: { style: 'fill', color: CHART_COLORS.eventMarkerText, size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', offset: [0, 0], }, rect: { style: 'fill', color: CHART_COLORS.eventMarker, borderColor: CHART_COLORS.eventMarker, borderSize: 1, borderRadius: 4, borderStyle: 'solid', borderDashedValue: [2, 2], }, }, }; /** * 深色主题配置 */ export const darkTheme: any = { ...lightTheme, candle: { ...lightTheme.candle, tooltip: { ...lightTheme.candle?.tooltip, text: { ...lightTheme.candle?.tooltip?.text, color: CHART_COLORS.textDark, }, }, }, indicator: { ...lightTheme.indicator, tooltip: { ...lightTheme.indicator?.tooltip, text: { ...lightTheme.indicator?.tooltip?.text, color: CHART_COLORS.textDark, }, }, }, xAxis: { ...lightTheme.xAxis, axisLine: { show: true, color: CHART_COLORS.borderDark, }, tickLine: { show: true, length: 3, color: CHART_COLORS.borderDark, }, tickText: { ...lightTheme.xAxis?.tickText, color: CHART_COLORS.textDark, }, }, yAxis: { ...lightTheme.yAxis, axisLine: { show: true, color: CHART_COLORS.borderDark, }, tickLine: { show: true, length: 3, color: CHART_COLORS.borderDark, }, tickText: { ...lightTheme.yAxis?.tickText, color: CHART_COLORS.textDark, }, }, grid: { show: true, horizontal: { show: true, size: 1, color: CHART_COLORS.gridDark, style: 'dashed', }, vertical: { show: false, }, }, separator: { size: 1, color: CHART_COLORS.borderDark, }, }; /** * 分时图专用主题配置 * 特点:面积图样式、均价线、百分比Y轴 */ export const timelineTheme: any = { ...lightTheme, candle: { type: 'area', // ✅ 面积图模式(分时线) area: { lineSize: 2, lineColor: CHART_COLORS.up, // 默认红色,实际会根据涨跌动态调整 value: 'close', backgroundColor: [ { offset: 0, color: 'rgba(239, 83, 80, 0.2)', // 红色半透明渐变(顶部) }, { offset: 1, color: 'rgba(239, 83, 80, 0.01)', // 红色几乎透明(底部) }, ], }, priceMark: { show: true, high: { show: false, // 分时图不显示最高最低价标记 }, low: { show: false, }, last: { show: true, upColor: CHART_COLORS.up, downColor: CHART_COLORS.down, noChangeColor: CHART_COLORS.neutral, line: { show: true, style: 'dashed', dashedValue: [4, 2], // ✅ 修复: 使用 dashedValue 而非 dashValue size: 1, }, text: { show: true, size: 12, paddingLeft: 4, paddingTop: 2, paddingRight: 4, paddingBottom: 2, borderRadius: 2, }, }, }, tooltip: { showRule: 'always', showType: 'standard', // ❌ KLineChart 类型不支持自定义 labels 和 formatter(需要在运行时通过 API 设置) // labels: ['时间: ', '现价: ', '涨跌: ', '均价: ', '昨收: ', '成交量: '], // formatter: (data: any, indicator: any) => { ... }, text: { size: 12, family: 'Helvetica, Arial, sans-serif', weight: 'normal', color: CHART_COLORS.text, }, }, }, yAxis: { ...lightTheme.yAxis, type: 'percentage', // ✅ 百分比模式 position: 'left', // Y轴在左侧 inside: false, reverse: false, tickText: { ...lightTheme.yAxis?.tickText, // ❌ KLineChart 类型不支持自定义 formatter(需要在运行时通过 API 设置) // formatter: (value: any) => { // const percent = (value * 100).toFixed(2); // if (Math.abs(value) < 0.0001) return '0.00%'; // return value > 0 ? `+${percent}%` : `${percent}%`; // }, }, }, grid: { show: true, horizontal: { show: true, size: 1, color: CHART_COLORS.grid, style: 'solid', // 分时图使用实线网格 }, vertical: { show: false, }, }, }; /** * 分时图深色主题 */ export const timelineThemeDark: any = { ...timelineTheme, ...darkTheme, candle: { ...timelineTheme.candle, tooltip: { ...timelineTheme.candle?.tooltip, text: { ...timelineTheme.candle?.tooltip?.text, color: CHART_COLORS.textDark, }, }, }, grid: { ...timelineTheme.grid, horizontal: { ...timelineTheme.grid?.horizontal, color: CHART_COLORS.gridDark, }, }, }; /** * 获取主题配置(根据 Chakra UI colorMode) */ export const getTheme = (colorMode: 'light' | 'dark' = 'light'): any => { return colorMode === 'dark' ? darkTheme : lightTheme; }; /** * 获取分时图主题配置 */ export const getTimelineTheme = (colorMode: 'light' | 'dark' = 'light'): any => { const baseTheme = colorMode === 'dark' ? timelineThemeDark : timelineTheme; // ✅ 添加成交量指标样式(蓝色渐变柱状图)+ 成交量单位格式化 return { ...baseTheme, indicator: { ...baseTheme.indicator, bars: [ { upColor: 'rgba(59, 130, 246, 0.6)', // 蓝色(涨) downColor: 'rgba(59, 130, 246, 0.6)', // 蓝色(跌)- 分时图成交量统一蓝色 noChangeColor: 'rgba(59, 130, 246, 0.6)', } ], // ❌ KLineChart 类型不支持自定义 formatter(需要在运行时通过 API 设置) tooltip: { ...baseTheme.indicator?.tooltip, // formatter: (params: any) => { // if (params.name === 'VOL' && params.calcParamsText) { // const volume = params.calcParamsText.match(/\d+/)?.[0]; // if (volume) { // const hands = Math.floor(Number(volume) / 100); // return `成交量: ${hands.toLocaleString()}手`; // } // } // return params.calcParamsText || ''; // }, }, }, }; };