import { reactive, toRefs, computed } from 'vue' import { queryHistoryDatas } from '@/services/api/quote' import { ChartCycleType } from '@/constants/chart' import { echarts, ECOption } from '@/components/base/echarts/core' import { useFuturesStore } from '@/stores' import { useDataset } from '@/hooks/echarts/candlestick/dataset' import moment from 'moment' export function useCandlestick(goodsCode: string) { const { dataset, handleData, clearData } = useDataset() const { quoteWatch } = useFuturesStore() const state = reactive({ loading: false, dataIndex: -1, cycleType: ChartCycleType.Minutes }) // 当前选中的数据项 const selectedItem = computed(() => { if (state.dataIndex > -1 && dataset.candlestick.source.length > state.dataIndex) { const { open, close, highest, lowest, ma5, ma10, ma15 } = dataset.candlestick.source[state.dataIndex] const { macd, dif, dea } = dataset.macd.source[state.dataIndex] const { vol } = dataset.vol.source[state.dataIndex] const { k, d, j } = dataset.kdj.source[state.dataIndex] const { cci } = dataset.cci.source[state.dataIndex] return { open, close, highest, lowest, ma5, ma10, ma15, macd, dif, dea, vol, k, d, j, cci } } else { return { open: '--', close: '--', highest: '--', lowest: '--', ma5: '--', ma10: '--', ma15: '--', macd: '--', dif: '--', dea: '--', vol: '--', k: '--', d: '--', j: '--', cci: '--' } } }) // 获取历史行情 const getHistoryData = async () => { try { clearData() state.dataIndex = -1 state.loading = true const res = await queryHistoryDatas({ data: { goodsCode, cycleType: state.cycleType, count: 1440, } }) // 日期升序排序 const data = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf()) state.dataIndex = data.length - 1 handleData(data) } finally { state.loading = false } } let chartInstance: echarts.ECharts let asyncHistoryData = getHistoryData() const createCandlestick = (chart: echarts.ECharts) => { chartInstance = chart asyncHistoryData.then(() => { const { source, dimensions } = dataset.candlestick const opt: ECOption = { grid: [ { top: '0', height: "70%" }, { top: '70%', height: "18%" } ], xAxis: [ { type: 'category', axisLabel: { formatter: (val: string) => { if (val) { switch (state.cycleType) { case ChartCycleType.Day: { return moment(val).format('YYYY-MM-DD') } default: { return moment(val).format('HH:mm') } } } return '' } } }, { type: 'category', gridIndex: 1 } ], yAxis: [ { type: 'value', scale: true, }, { type: 'value', scale: true, gridIndex: 1 } ], dataZoom: { type: 'inside', startValue: source.length - 60, // 起始显示K线条数(最新60条) end: 100, minValueSpan: 30, // 限制窗口缩放显示最少数据条数 maxValueSpan: 200, // 限制窗口缩放显示最大数据条数 xAxisIndex: [0, 1] }, dataset: { dimensions, source, }, series: [ { name: 'KLine', type: 'candlestick' }, { name: 'MACD', type: 'bar', xAxisIndex: 1, yAxisIndex: 1, } ] } chart.setOption(opt) }) } const initChart = (cycleType: ChartCycleType) => { state.cycleType = cycleType asyncHistoryData = getHistoryData() } /** * 格式化日期 * @param value * @returns */ const formatDate = (value: string) => { switch (state.cycleType) { case ChartCycleType.Day: { return moment(value).format('YYYY-MM-DD') } case ChartCycleType.Hours2: case ChartCycleType.Hours4: { return moment(value).format('YYYY-MM-DD HH:00:00') } default: { return moment(value).format('YYYY-MM-DD HH:mm:00') } } } quoteWatch(goodsCode, (q) => { if (chartInstance) { asyncHistoryData.then(() => { const { last, lasttime } = q if (last && lasttime) { const { candlestick, macd, vol, kdj, cci } = dataset const lastIndex = candlestick.source.length - 1 // 历史数据最后索引位置 const oldTime = lastIndex === -1 ? moment(lasttime) : moment(candlestick.source[lastIndex].date) // 历史行情最后时间 const diffTime = moment(lasttime).valueOf() - oldTime.valueOf() // 计算时间差 // 判断时间差是否大于周期时间 if (lastIndex === -1 || diffTime > 60 * 1000) { const newtime = formatDate(lasttime) // 新增K线数据 candlestick.source.push({ date: newtime, open: last, close: last, lowest: last, highest: last, ma5: '-', ma10: '-', ma15: '-', }) // 新增MACD数据 macd.source.push({ date: newtime, ema12: 0, ema26: 0, dif: 0, dea: 0, macd: 0, }) // 新增VOL数据 vol.source.push({ date: newtime, vol: 0, }) // 新增KDJ数据 kdj.source.push({ date: newtime, k: '-', d: '-', j: '-', }) // 新增CCI数据 cci.source.push({ date: newtime, cci: '-', }) } else { // 更新列表中最后一条记录的数据 const record = candlestick.source[lastIndex] if (record.lowest > last) { record.lowest = last // 更新最低价 } if (record.highest < last) { record.highest = last // 更新最高价 } record.close = last // 更新收盘价 } // chartInstance.setOption({ // dataset: { // source: candlestick.source // } // }) } }) } }) return { ...toRefs(state), selectedItem, createCandlestick, initChart } }