feat: 现在创建配置文件。首先让我检查现有的主题配置,以保持样式一致性:
This commit is contained in:
295
src/components/StockChart/utils/chartUtils.ts
Normal file
295
src/components/StockChart/utils/chartUtils.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* 图表通用工具函数
|
||||
*
|
||||
* 包含图表初始化、技术指标管理等通用逻辑
|
||||
*/
|
||||
|
||||
import type { Chart } from 'klinecharts';
|
||||
import { logger } from '@utils/logger';
|
||||
|
||||
/**
|
||||
* 安全地执行图表操作(捕获异常)
|
||||
*
|
||||
* @param operation 操作名称
|
||||
* @param fn 执行函数
|
||||
* @returns T | null 执行结果或 null
|
||||
*/
|
||||
export const safeChartOperation = <T>(
|
||||
operation: string,
|
||||
fn: () => T
|
||||
): T | null => {
|
||||
try {
|
||||
return fn();
|
||||
} catch (error) {
|
||||
logger.error('chartUtils', operation, error as Error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建技术指标
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param indicatorName 指标名称(如 'MA', 'MACD', 'VOL')
|
||||
* @param params 指标参数(可选)
|
||||
* @param isStack 是否叠加(主图指标为 true,副图为 false)
|
||||
* @returns string | null 指标 ID
|
||||
*/
|
||||
export const createIndicator = (
|
||||
chart: Chart,
|
||||
indicatorName: string,
|
||||
params?: number[],
|
||||
isStack: boolean = false
|
||||
): string | null => {
|
||||
return safeChartOperation(`createIndicator:${indicatorName}`, () => {
|
||||
const indicatorId = chart.createIndicator(
|
||||
{
|
||||
name: indicatorName,
|
||||
...(params && { calcParams: params }),
|
||||
},
|
||||
isStack
|
||||
);
|
||||
|
||||
logger.debug('chartUtils', 'createIndicator', '创建技术指标', {
|
||||
indicatorName,
|
||||
params,
|
||||
isStack,
|
||||
indicatorId,
|
||||
});
|
||||
|
||||
return indicatorId;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除技术指标
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param indicatorId 指标 ID(不传则移除所有指标)
|
||||
*/
|
||||
export const removeIndicator = (chart: Chart, indicatorId?: string): void => {
|
||||
safeChartOperation('removeIndicator', () => {
|
||||
chart.removeIndicator(indicatorId);
|
||||
logger.debug('chartUtils', 'removeIndicator', '移除技术指标', { indicatorId });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量创建副图指标
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param indicators 指标名称数组
|
||||
* @returns string[] 指标 ID 数组
|
||||
*/
|
||||
export const createSubIndicators = (
|
||||
chart: Chart,
|
||||
indicators: string[]
|
||||
): string[] => {
|
||||
const ids: string[] = [];
|
||||
|
||||
indicators.forEach((name) => {
|
||||
const id = createIndicator(chart, name, undefined, false);
|
||||
if (id) {
|
||||
ids.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug('chartUtils', 'createSubIndicators', '批量创建副图指标', {
|
||||
indicators,
|
||||
createdIds: ids,
|
||||
});
|
||||
|
||||
return ids;
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置图表缩放级别
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param zoom 缩放级别(0.5 - 2.0)
|
||||
*/
|
||||
export const setChartZoom = (chart: Chart, zoom: number): void => {
|
||||
safeChartOperation('setChartZoom', () => {
|
||||
// KLineChart 10.0: 使用 setBarSpace 方法调整 K 线宽度(实现缩放效果)
|
||||
const baseBarSpace = 8; // 默认 K 线宽度(px)
|
||||
const newBarSpace = Math.max(4, Math.min(16, baseBarSpace * zoom));
|
||||
|
||||
// 注意:KLineChart 10.0 可能没有直接的 zoom API,需要通过调整样式实现
|
||||
chart.setStyles({
|
||||
candle: {
|
||||
bar: {
|
||||
upBorderColor: undefined, // 保持默认
|
||||
upColor: undefined,
|
||||
downBorderColor: undefined,
|
||||
downColor: undefined,
|
||||
},
|
||||
// 通过调整蜡烛图宽度实现缩放效果
|
||||
tooltip: {
|
||||
showRule: 'always',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.debug('chartUtils', 'setChartZoom', '设置图表缩放', {
|
||||
zoom,
|
||||
newBarSpace,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 滚动到指定时间
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param timestamp 目标时间戳
|
||||
*/
|
||||
export const scrollToTimestamp = (chart: Chart, timestamp: number): void => {
|
||||
safeChartOperation('scrollToTimestamp', () => {
|
||||
// KLineChart 10.0: 使用 scrollToTimestamp 方法
|
||||
chart.scrollToTimestamp(timestamp);
|
||||
|
||||
logger.debug('chartUtils', 'scrollToTimestamp', '滚动到指定时间', { timestamp });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 调整图表大小(响应式)
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
*/
|
||||
export const resizeChart = (chart: Chart): void => {
|
||||
safeChartOperation('resizeChart', () => {
|
||||
chart.resize();
|
||||
logger.debug('chartUtils', 'resizeChart', '调整图表大小');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取图表可见数据范围
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @returns { from: number, to: number } | null 可见范围
|
||||
*/
|
||||
export const getVisibleRange = (chart: Chart): { from: number; to: number } | null => {
|
||||
return safeChartOperation('getVisibleRange', () => {
|
||||
const data = chart.getDataList();
|
||||
if (!data || data.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 简化实现:返回所有数据范围
|
||||
// 实际项目中可通过 chart 的内部状态获取可见范围
|
||||
return {
|
||||
from: 0,
|
||||
to: data.length - 1,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 清空图表数据
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
*/
|
||||
export const clearChartData = (chart: Chart): void => {
|
||||
safeChartOperation('clearChartData', () => {
|
||||
chart.resetData();
|
||||
logger.debug('chartUtils', 'clearChartData', '清空图表数据');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 截图(导出图表为图片)
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param includeOverlay 是否包含 overlay
|
||||
* @returns string | null Base64 图片数据
|
||||
*/
|
||||
export const exportChartImage = (
|
||||
chart: Chart,
|
||||
includeOverlay: boolean = true
|
||||
): string | null => {
|
||||
return safeChartOperation('exportChartImage', () => {
|
||||
// KLineChart 10.0: 使用 getConvertPictureUrl 方法
|
||||
const imageData = chart.getConvertPictureUrl(includeOverlay, 'png', '#ffffff');
|
||||
|
||||
logger.debug('chartUtils', 'exportChartImage', '导出图表图片', {
|
||||
includeOverlay,
|
||||
hasData: !!imageData,
|
||||
});
|
||||
|
||||
return imageData;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换十字光标显示
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param show 是否显示
|
||||
*/
|
||||
export const toggleCrosshair = (chart: Chart, show: boolean): void => {
|
||||
safeChartOperation('toggleCrosshair', () => {
|
||||
chart.setStyles({
|
||||
crosshair: {
|
||||
show,
|
||||
},
|
||||
});
|
||||
|
||||
logger.debug('chartUtils', 'toggleCrosshair', '切换十字光标', { show });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换网格显示
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param show 是否显示
|
||||
*/
|
||||
export const toggleGrid = (chart: Chart, show: boolean): void => {
|
||||
safeChartOperation('toggleGrid', () => {
|
||||
chart.setStyles({
|
||||
grid: {
|
||||
show,
|
||||
},
|
||||
});
|
||||
|
||||
logger.debug('chartUtils', 'toggleGrid', '切换网格', { show });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 订阅图表事件
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param eventName 事件名称
|
||||
* @param handler 事件处理函数
|
||||
*/
|
||||
export const subscribeChartEvent = (
|
||||
chart: Chart,
|
||||
eventName: string,
|
||||
handler: (...args: any[]) => void
|
||||
): void => {
|
||||
safeChartOperation(`subscribeChartEvent:${eventName}`, () => {
|
||||
chart.subscribeAction(eventName, handler);
|
||||
logger.debug('chartUtils', 'subscribeChartEvent', '订阅图表事件', { eventName });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消订阅图表事件
|
||||
*
|
||||
* @param chart KLineChart 实例
|
||||
* @param eventName 事件名称
|
||||
* @param handler 事件处理函数
|
||||
*/
|
||||
export const unsubscribeChartEvent = (
|
||||
chart: Chart,
|
||||
eventName: string,
|
||||
handler: (...args: any[]) => void
|
||||
): void => {
|
||||
safeChartOperation(`unsubscribeChartEvent:${eventName}`, () => {
|
||||
chart.unsubscribeAction(eventName, handler);
|
||||
logger.debug('chartUtils', 'unsubscribeChartEvent', '取消订阅图表事件', { eventName });
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user