import { ref, computed, watch } from 'vue' //import { timerInterceptor } from '@/utils/timer' import { ChartCycleType } from '@/constants/chart' import { queryHistoryDatas } from '@/services/api/quote' import { useFuturesStore } from '@/stores' import { useDataset } from './dataset' import { useOptions } from './options' import moment from 'moment' export function useCandlestickChart(goodscode: string) { const futuresStore = useFuturesStore() const { dataset, handleData, clearData, calcIndicator } = useDataset(); const { options, initOptions, updateOptions } = useOptions(dataset); const loading = ref(false); const isEmpty = ref(true); const dataIndex = ref(-1); // 当前数据索引值 const quote = futuresStore.getQuoteInfo(goodscode); // 实时行情 // 当前选中的数据项 const selectedItem = computed(() => { let result: { [key: string]: number | string } = { open: '--', close: '--', highest: '--', lowest: '--', ma5: '--', ma10: '--', ma15: '--', macd: '--', dif: '--', dea: '--', vol: '--', k: '--', d: '--', j: '--', cci: '--' } if (dataIndex.value > -1) { const { open, close, highest, lowest, ma5, ma10, ma15 } = dataset.candlestick.source[dataIndex.value]; const { macd, dif, dea } = dataset.macd.source[dataIndex.value]; const { vol } = dataset.vol.source[dataIndex.value]; const { k, d, j } = dataset.kdj.source[dataIndex.value]; const { cci } = dataset.cci.source[dataIndex.value]; result = { open, close, highest, lowest, ma5, ma10, ma15, macd, dif, dea, vol, k, d, j, cci } } return result; }) /** * 初始化数据 * @param cycletype 周期类型 */ const initData = (cycletype: ChartCycleType) => { clearData(); dataIndex.value = -1; options.cycleType = cycletype; loading.value = true; isEmpty.value = true; // 获取历史行情 queryHistoryDatas({ data: { cycleType: cycletype, goodsCode: goodscode, count: 1440, } }).then((res) => { // 日期升序排序 const data = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf()); if (data.length) { dataIndex.value = data.length - 1; isEmpty.value = false; handleData(data); } }).finally(() => { loading.value = false; }) } /** * 获取周期毫秒数 * @returns */ const getCycleMilliseconds = () => { const milliseconds = 60 * 1000; // 一分钟毫秒数 switch (options.cycleType) { case ChartCycleType.Minutes5: { return milliseconds * 5; } case ChartCycleType.Minutes30: { return milliseconds * 30; } case ChartCycleType.Minutes60: { return milliseconds * 60; } case ChartCycleType.Hours2: { return milliseconds * 2 * 60; } case ChartCycleType.Hours4: { return milliseconds * 4 * 60; } case ChartCycleType.Day: { return milliseconds * 24 * 60; } default: { return milliseconds; } } } /** * 更新图表数据 */ const updateChart = () => { if (quote.value) { const { last, lasttime } = quote.value; const { candlestick, macd, vol, kdj, cci } = dataset; const lastIndex = candlestick.source.length - 1; // 历史数据最后索引位置 const cycleMilliseconds = getCycleMilliseconds(); const oldTime = lastIndex === -1 ? moment(lasttime) : moment(candlestick.source[lastIndex].date); // 历史行情最后时间 const diffTime = moment(lasttime).valueOf() - oldTime.valueOf(); // 计算时间差 if (diffTime > cycleMilliseconds * 2) { // 时间间隔超过两个周期,重新请求历史数据 //timerInterceptor.debounce(() => initData(cycleType.value), 1000, 'updateChart'); } else { // 判断时间差是否大于周期时间 if (lastIndex === -1 || diffTime > cycleMilliseconds) { oldTime.add(cycleMilliseconds, 'ms'); const lastDate = oldTime.format('YYYY-MM-DD HH:mm:ss'); // 新增K线数据 candlestick.source.push({ date: lastDate, open: last, close: last, lowest: last, highest: last, ma5: '-', ma10: '-', ma15: '-', }) // 新增MACD数据 macd.source.push({ date: lastDate, ema12: 0, ema26: 0, dif: 0, dea: 0, macd: 0, }) // 新增VOL数据 vol.source.push({ date: lastDate, vol: 0, }) // 新增KDJ数据 kdj.source.push({ date: lastDate, k: '-', d: '-', j: '-', }) // 新增CCI数据 cci.source.push({ date: lastDate, cci: '-', }) } else { // 更新列表中最后一条记录的数据 const record = candlestick.source[lastIndex]; if (record.lowest > last) { record.lowest = last; // 更新最低价 } if (record.highest < last) { record.highest = last; // 更新最高价 } record.close = last; // 更新收盘价 } // 计算各项指标 calcIndicator(lastIndex === -1 ? 0 : lastIndex); updateOptions(); } } } // 监听行情推送 watch(() => quote.value?.last, () => { if (!loading.value && !isEmpty.value) { updateChart(); } }) return { loading, isEmpty, dataIndex, options, selectedItem, initData, initOptions, } }