Kaynağa Gözat

图表更新

li.shaoyi 4 yıl önce
ebeveyn
işleme
deff849496

+ 110 - 91
src/common/components/echart/echart-kline/index.vue

@@ -8,7 +8,7 @@ import { QueryHistoryDatasRsp, QueryQuoteDayRsp, QueryHistoryDatas, CycleType }
 import { QueryHistoryDatas as queryHistoryDatas } from '@/services/go/quote';
 import { debounce } from '@/utils/time';
 import EchartBase from '../echart-base/index.vue';
-import { handleEchart } from './setup';
+import { handleEchart, Source } from './setup';
 import moment from 'moment';
 
 export default defineComponent({
@@ -41,62 +41,67 @@ export default defineComponent({
 
         // 处理图表数据
         const handleData = (rawData: QueryHistoryDatasRsp[]): void => {
-            historyIndexs.length = 0; // 清空数据
-            const datas: number[][] = [],
-                times: string[] = [],
-                volume: number[] = [];
+            const { source } = chartData.value;
+            source.length = 0;
+            historyIndexs.length = 0;
 
             rawData.forEach((item, index) => {
                 const { o, c, h, l, ts, tv } = item;
-                datas.push([o, c, l, h]);
-                times.push(moment(ts).format('YYYY-MM-DD HH:mm:ss'));
-                volume.push(tv);
+                source.push({
+                    date: moment(ts).format('YYYY-MM-DD HH:mm:ss'),
+                    open: o,
+                    close: c,
+                    lowest: l,
+                    highest: h,
+                    ma5: '-',
+                    ma10: '-',
+                    ma15: '-',
+                    vol: tv,
+                    macd: '-',
+                    dif: '-',
+                    dea: '-',
+                    k: '-',
+                    d: '-',
+                    j: '-',
+                    cci: '-',
+                });
                 if (!item.f) historyIndexs.push(index); // 排除补充数据
             });
 
-            chartData.datas = datas;
-            chartData.times = times;
-            chartData.volume = volume;
-            chartData.ma5 = calcMA(datas, 5);
-            chartData.ma10 = calcMA(datas, 10);
-            chartData.ma15 = calcMA(datas, 15);
-
-            const { macd, dif, dea } = calcMACD(datas);
-            chartData.macd = macd;
-            chartData.dif = dif;
-            chartData.dea = dea;
-
-            chartData.kdj = calcKDJ(datas);
-            chartData.cci = clacCCI(datas);
+            calcMA('ma5', 5);
+            calcMA('ma10', 10);
+            calcMA('ma15', 15);
+            calcMACD();
+            calcKDJ();
+            clacCCI();
         };
 
         // 计算平均线
-        const calcMA = (data: number[][], count: number) => {
-            const ma: string[] = [];
-            if (data.length >= count) {
+        const calcMA = (key: keyof Source, count: number) => {
+            const { source } = chartData.value;
+            let result: Source[keyof Source] = '-';
+
+            if (source.length >= count) {
                 // 均线起始位置
                 const startIndex = historyIndexs[count - 1] ?? count;
-                for (let i = 0; i < data.length; i++) {
-                    if (i < startIndex) {
-                        ma.push('-');
-                    } else {
+                for (let i = 0; i < source.length; i++) {
+                    if (i > startIndex) {
                         const j = historyIndexs.findIndex((val) => val === i);
                         // 判断是否补充数据
                         if (j === -1) {
-                            // 取上个平均值
-                            ma.push(ma[ma.length - 1]);
+                            result = source[i - 1][key]; // 取上个平均值
                         } else {
                             // 向后取MA数
                             const maIndexs = historyIndexs.slice(j - (count - 1), j + 1);
-                            // 计算总价,data[val][1]=收盘价
-                            const total = maIndexs.reduce((sum, val) => sum + data[val][1], 0);
+                            // 计算总价
+                            const total = maIndexs.reduce((sum, val) => sum + source[val].close, 0);
                             // 计算均线
-                            ma.push((total / count).toFixed(2));
+                            result = (total / count).toFixed(2);
                         }
                     }
+                    (<typeof result>source[i][key]) = result;
                 }
             }
-            return ma;
         };
 
         // 计算EMA
@@ -136,79 +141,83 @@ export default defineComponent({
         };
 
         // 计算MACD
-        const calcMACD = (data: number[][]) => {
-            const macd = [],
-                close = data.map((val) => val[1]), // 收盘价数据
+        const calcMACD = () => {
+            const { source } = chartData.value,
+                close = source.map((item) => item.close),
                 dif = calcDIF(close),
                 dea = calcDEA(dif);
 
-            for (let i = 0; i < close.length; i++) {
-                macd.push(((dif[i] - dea[i]) * 2).toFixed(3));
+            for (let i = 0; i < source.length; i++) {
+                source[i].dif = dif[i].toFixed(2);
+                source[i].dea = dea[i].toFixed(2);
+                source[i].macd = ((dif[i] - dea[i]) * 2).toFixed(2);
             }
-            return {
-                dif: dif.map((val) => val.toFixed(3)),
-                dea: dea.map((val) => val.toFixed(3)),
-                macd,
-            };
         };
 
         // 计算KDJ
-        const calcKDJ = (data: number[][]) => {
-            const kdj: string[][] = []; // [[k,d,j]]
-            for (let i = 0; i < data.length; i++) {
+        const calcKDJ = () => {
+            const { source } = chartData.value;
+            for (let i = 0; i < source.length; i++) {
+                const item = source[i];
                 if (i < 8) {
-                    kdj.push(['-', '-', '-']);
+                    item.k = '-';
+                    item.d = '-';
+                    item.j = '-';
                 } else {
                     let rsv = 50; // 如果最低价等于最高价,RSV默认值为50
-                    if (data[i][2] !== data[i][3]) {
-                        const n9 = data.slice(i - 8, i + 1).map((val) => val[1]), // 取前9个收盘价
+                    if (item.lowest !== item.highest) {
+                        const n9 = source.slice(i - 8, i + 1).map((item) => item.close), // 取前9个收盘价
                             max = Math.max(...n9),
                             min = Math.min(...n9);
                         // 计算RSV
-                        rsv = ((data[i][1] - min) / (max - min)) * 100;
+                        rsv = ((item.close - min) / (max - min)) * 100;
                     }
 
-                    const yestK = Number(kdj[kdj.length - 1][0]); // 取前一日K值
-                    const yestD = Number(kdj[kdj.length - 1][1]); // 取前一日D值
+                    const yestK = Number(source[i - 1].k); // 取前一日K值
+                    const yestD = Number(source[i - 1].d); // 取前一日D值
 
                     if (isNaN(yestK) || isNaN(yestD)) {
                         // 如果前一日的K值或D值不存在则默认值为50
-                        kdj.push(['50', '50', '50']);
+                        item.k = '50';
+                        item.d = '50';
+                        item.j = '50';
                     } else {
                         const k = (2 / 3) * yestK + (1 / 3) * rsv,
                             d = (2 / 3) * yestD + (1 / 3) * yestK,
                             j = 3 * k - 2 * d;
 
-                        kdj.push([k.toFixed(2), d.toFixed(2), j.toFixed(2)]);
+                        item.k = k.toFixed(2);
+                        item.d = d.toFixed(2);
+                        item.j = j.toFixed(2);
                     }
                 }
             }
-            return kdj;
         };
 
-        const clacCCI = (data: number[][]) => {
-            const cci: string[] = [];
-            for (let i = 0; i < data.length; i++) {
+        // 计算CCI
+        const clacCCI = () => {
+            const { source } = chartData.value;
+            for (let i = 0; i < source.length; i++) {
+                const item = source[i];
                 if (i < 13) {
-                    cci.push('-');
+                    item.cci = '-';
                 } else {
-                    const tp = (data[i][1] + data[i][2] + data[i][3]) / 3, // (收盘价 + 最低价 + 最高价) / 3
-                        n14 = data.slice(i - 13, i + 1), // 取前14条数据
-                        ma = n14.reduce((sum, val) => sum + (val[1] + val[2] + val[3]) / 3, 0) / 14, // 计算前14条数据的(TP)价总和÷N
-                        md = n14.reduce((sum, val) => sum + Math.abs(ma - (val[1] + val[2] + val[3]) / 3), 0) / 14, // 计算前14条数据的(MA-TP)价总和÷N
+                    const tp = (item.close + item.lowest + item.highest) / 3, // (收盘价 + 最低价 + 最高价) / 3
+                        n14 = source.slice(i - 13, i + 1), // 取前14条数据
+                        ma = n14.reduce((sum, e) => sum + (e.close + e.lowest + e.highest) / 3, 0) / 14, // 计算前14条数据的(TP)价总和÷N
+                        md = n14.reduce((sum, e) => sum + Math.abs(ma - (e.close + e.lowest + e.highest) / 3), 0) / 14, // 计算前14条数据的(MA-TP)价总和÷N
                         result = (tp - ma) / md / 0.015;
 
-                    cci.push(result.toFixed(2));
+                    item.cci = result.toFixed(2);
                 }
             }
-            return cci;
         };
 
         // 更新图表K线数据
         const updateChartData = () => {
-            const { datas, times, volume } = chartData,
-                lastIndex = datas.length - 1, // 历史行情最后索引位置
-                lastTime = moment(times[times.length - 1]), // 历史行情最后时间
+            const { source } = chartData.value,
+                lastIndex = source.length - 1, // 历史行情最后索引位置
+                lastTime = moment(source[lastIndex].date), // 历史行情最后时间
                 newTime = moment(props.quoteData.lasttime), // 实时行情最新时间
                 newPrice = props.quoteData.last; // 实时行情最新价
 
@@ -239,33 +248,43 @@ export default defineComponent({
             // 判断时间差是否大于周期时间
             if (diffTime > cycleMilliseconds) {
                 lastTime.add(cycleMilliseconds, 'ms');
-                times.push(lastTime.format('YYYY-MM-DD HH:mm:ss')); // 添加历史行情时间
-                datas.push([newPrice, newPrice, newPrice, newPrice]); // 添加历史行情数据
-                volume.push(0);
+                // 添加历史行情
+                source.push({
+                    date: lastTime.format('YYYY-MM-DD HH:mm:ss'),
+                    open: newPrice,
+                    close: newPrice,
+                    lowest: newPrice,
+                    highest: newPrice,
+                    ma5: '-',
+                    ma10: '-',
+                    ma15: '-',
+                    vol: 0,
+                    macd: '-',
+                    dif: '-',
+                    dea: '-',
+                    k: '-',
+                    d: '-',
+                    j: '-',
+                    cci: '-',
+                });
                 historyIndexs.push(lastIndex + 1); // 添加历史行情索引
             } else {
-                const lastPrice = datas[lastIndex];
-                if (lastPrice[2] > newPrice) {
-                    lastPrice[2] = newPrice; //更新最低价
+                const lastData = source[lastIndex];
+                if (lastData.lowest > newPrice) {
+                    lastData.lowest = newPrice; //更新最低价
                 }
-                if (lastPrice[3] < newPrice) {
-                    lastPrice[3] = newPrice; //更新最高价
+                if (lastData.highest < newPrice) {
+                    lastData.highest = newPrice; //更新最高价
                 }
-                lastPrice[1] = newPrice; //更新收盘价
-                datas[lastIndex] = lastPrice; // 更新历史行情数据
+                lastData.close = newPrice; //更新收盘价
             }
 
-            chartData.ma5 = calcMA(datas, 5);
-            chartData.ma10 = calcMA(datas, 10);
-            chartData.ma15 = calcMA(datas, 15);
-
-            const { dif, dea, macd } = calcMACD(datas);
-            chartData.dif = dif;
-            chartData.dea = dea;
-            chartData.macd = macd;
-
-            chartData.kdj = calcKDJ(datas);
-            chartData.cci = clacCCI(datas);
+            calcMA('ma5', 5);
+            calcMA('ma10', 10);
+            calcMA('ma15', 15);
+            calcMACD();
+            calcKDJ();
+            clacCCI();
 
             // 延迟图表更新,减少卡顿
             debounce(() => {

+ 84 - 157
src/common/components/echart/echart-kline/setup.ts

@@ -18,19 +18,28 @@ type Colors = {
     equalColor: string,
 }
 
+export type Source = {
+    date: string, // xAxis数据,必须是第一个属性
+    open: number,
+    close: number,
+    lowest: number,
+    highest: number,
+    ma5: string,
+    ma10: string,
+    ma15: string,
+    vol: number,
+    macd: string,
+    dif: string,
+    dea: string,
+    k: string,
+    d: string,
+    j: string,
+    cci: string,
+}
+
 // 图表数据
-export type ChartData = {
-    datas: number[][], // 历史数据
-    times: string[], // 历史日期
-    ma5: string[], //均线数据
-    ma10: string[], //均线数据
-    ma15: string[], //均线数据
-    dif: string[],
-    dea: string[],
-    macd: string[],
-    volume: number[],
-    kdj: string[][], // [[k,d,j]]
-    cci: string[]
+type ChartData = {
+    source: Source[],
 }
 
 export function handleEchart() {
@@ -38,24 +47,18 @@ export function handleEchart() {
     // 当前主题
     const theme = getTheme();
     // 图表数据
-    const chartData: ChartData = {
-        datas: [],
-        times: [],
-        ma5: [],
-        ma10: [],
-        ma15: [],
-        dif: [],
-        dea: [],
-        macd: [],
-        volume: [],
-        kdj: [],
-        cci: [],
-    };
+    const chartData = ref<ChartData>({
+        source: []
+    });
 
     // 初始化图表配置
     const initOptions = (seriesType: string) => {
-        const { datas, times, ma5, ma10, ma15, dea, dif, macd, volume, kdj, cci } = chartData;
+        const { source } = chartData.value;
         const option: EChartsOption = {
+            dataset: {
+                dimensions: ['date', 'open', 'close', 'lowest', 'highest', 'ma5', 'ma10', 'ma15', 'vol', 'macd', 'dif', 'dea', 'k', 'd', 'j', 'cci'],
+                source
+            },
             animation: false,
             axisPointer: {
                 link: [
@@ -64,32 +67,28 @@ export function handleEchart() {
                     }
                 ],
             },
-            legend: [
-                {
-                    //图例控件,点击图例控制哪些系列不显示
-                    type: 'scroll',
-                    data: ['MA5', 'MA10', 'MA15'],
-                    itemWidth: 14,
-                    itemHeight: 2,
-                    left: '5%',
-                    top: 0,
-                    textStyle: {
-                        fontSize: 12,
-                    },
+            legend: {
+                //图例控件,点击图例控制哪些系列不显示
+                type: 'scroll',
+                data: ['MA5', 'MA10', 'MA15'],
+                selected: {
+                    VOL: seriesType === 'VOL',
+                    MACD: seriesType === 'MACD',
+                    DIF: seriesType === 'MACD',
+                    DEA: seriesType === 'MACD',
+                    K: seriesType === 'KDJ',
+                    D: seriesType === 'KDJ',
+                    J: seriesType === 'KDJ',
+                    CCI: seriesType === 'CCI',
                 },
-                {
-                    //图例控件,点击图例控制哪些系列不显示
-                    type: 'scroll',
-                    data: [],
-                    itemWidth: 14,
-                    itemHeight: 2,
-                    left: '5%',
-                    top: '68%',
-                    textStyle: {
-                        fontSize: 12,
-                    },
+                itemWidth: 14,
+                itemHeight: 2,
+                left: '5%',
+                top: 0,
+                textStyle: {
+                    fontSize: 12,
                 },
-            ],
+            },
             // 悬浮框
             tooltip: {
                 trigger: 'axis',
@@ -107,31 +106,16 @@ export function handleEchart() {
                     let result = '';
                     params.forEach((item: any, index: number) => {
                         if (index === 0) {
-                            result += '<div class="tooltip-title">' + moment(item.name).format('YYYY-MM-DD HH:mm') + '</div>';
+                            result += '<div class="tooltip-title">' + moment(item.data.date).format('YYYY-MM-DD HH:mm') + '</div>';
                         }
                         if (item.seriesType === 'candlestick') {
-                            item.value.forEach((data: number[], i: number) => {
-                                if (i > 0) {
-                                    result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>';
-                                    switch (i) {
-                                        case 1:
-                                            result += '开盘';
-                                            break;
-                                        case 2:
-                                            result += '收盘';
-                                            break;
-                                        case 3:
-                                            result += '最低';
-                                            break;
-                                        case 4:
-                                            result += '最高';
-                                            break;
-                                    }
-                                    result += '</span><span>' + data + '</span></div>';
-                                }
-                            })
+                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>开盘</span><span>' + item.data.open + '</span></div>';
+                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>收盘</span><span>' + item.data.close + '</span></div>';
+                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>最低</span><span>' + item.data.lowest + '</span></div>';
+                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>最高</span><span>' + item.data.highest + '</span></div>';
                         } else {
-                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>' + item.seriesName + '</span><span>' + item.value + '</span></div>';
+                            const key = item.dimensionNames[item.encode.y[0]];
+                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>' + item.seriesName + '</span><span>' + item.data[key] + '</span></div>';
                         }
                     })
                     return result;
@@ -157,7 +141,6 @@ export function handleEchart() {
                 // K线时间轴
                 {
                     type: 'category',
-                    data: times,
                     axisLabel: {
                         formatter: (val: any) => moment(val).format('YYYY/MM/DD'),
                     },
@@ -168,7 +151,6 @@ export function handleEchart() {
                 // MACD、VOL、KDJ时间轴
                 {
                     type: 'category',
-                    data: times,
                     gridIndex: 1,
                     axisLabel: {
                         show: false,
@@ -198,8 +180,8 @@ export function handleEchart() {
                 {
                     type: 'inside',
                     xAxisIndex: [0, 1],
-                    startValue: times.length - 120, // 起始显示K线条数(最新120条)
-                    endValue: times.length,
+                    startValue: source.length - 120, // 起始显示K线条数(最新120条)
+                    endValue: source.length,
                     minValueSpan: 60, // 限制窗口缩放显示最少数据条数
                     maxValueSpan: 400, // 限制窗口缩放显示最大数据条数
                 },
@@ -214,7 +196,6 @@ export function handleEchart() {
                     name: 'K线',
                     type: 'candlestick',
                     // Y轴数据
-                    data: datas,
                     markLine: {
                         animation: false,
                         // 标线两端图标
@@ -231,7 +212,7 @@ export function handleEchart() {
                         data: [
                             {
                                 // 当前价
-                                yAxis: datas.length ? datas[datas.length - 1][1] : 0,
+                                yAxis: source.length ? source[source.length - 1].close : 0,
                             },
                         ],
                     },
@@ -240,7 +221,6 @@ export function handleEchart() {
                     name: 'MA5',
                     type: 'line',
                     sampling: 'average', //折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率
-                    data: ma5,
                     smooth: true,
                     symbol: 'none',
                     lineStyle: {
@@ -252,7 +232,6 @@ export function handleEchart() {
                     name: 'MA10',
                     type: 'line',
                     sampling: 'average',
-                    data: ma10,
                     smooth: true,
                     symbol: 'none',
                     lineStyle: {
@@ -264,7 +243,6 @@ export function handleEchart() {
                     name: 'MA15',
                     type: 'line',
                     sampling: 'average',
-                    data: ma15,
                     smooth: true,
                     symbol: 'none',
                     lineStyle: {
@@ -276,7 +254,6 @@ export function handleEchart() {
                     name: 'VOL',
                     type: 'bar',
                     sampling: 'average',
-                    data: seriesType === 'VOL' ? volume : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     barWidth: '60%',
@@ -285,7 +262,6 @@ export function handleEchart() {
                     name: 'MACD',
                     type: 'bar',
                     sampling: 'average',
-                    data: seriesType === 'MACD' ? macd : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     barWidth: '20%',
@@ -294,7 +270,6 @@ export function handleEchart() {
                     name: 'DIF',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'MACD' ? dif : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -308,7 +283,6 @@ export function handleEchart() {
                     name: 'DEA',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'MACD' ? dea : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -322,7 +296,6 @@ export function handleEchart() {
                     name: 'K',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'KDJ' ? kdj.map((val) => val[0]) : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -336,7 +309,6 @@ export function handleEchart() {
                     name: 'D',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'KDJ' ? kdj.map((val) => val[1]) : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -350,7 +322,6 @@ export function handleEchart() {
                     name: 'J',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'KDJ' ? kdj.map((val) => val[2]) : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -364,7 +335,6 @@ export function handleEchart() {
                     name: 'CCI',
                     type: 'line',
                     sampling: 'average',
-                    data: seriesType === 'CCI' ? cci : [],
                     xAxisIndex: 1,
                     yAxisIndex: 1,
                     smooth: true,
@@ -382,76 +352,37 @@ export function handleEchart() {
 
     // 动态更新数据
     const updateOptions = (seriesType: string) => {
-        const { datas, times, ma5, ma10, ma15, macd, dif, dea, volume, kdj, cci } = chartData;
-        if (datas.length) {
+        const { source } = chartData.value;
+        if (source.length) {
             options.value = {
-                xAxis: [
-                    {
-                        data: times,
-                    },
-                    {
-                        data: times,
+                legend: {
+                    selected: {
+                        VOL: seriesType === 'VOL',
+                        MACD: seriesType === 'MACD',
+                        DIF: seriesType === 'MACD',
+                        DEA: seriesType === 'MACD',
+                        K: seriesType === 'KDJ',
+                        D: seriesType === 'KDJ',
+                        J: seriesType === 'KDJ',
+                        CCI: seriesType === 'CCI',
                     },
-                ],
+                },
+                dataset: {
+                    source
+                },
                 series: [
                     {
                         name: 'K线',
-                        data: datas,
                         markLine: {
                             data: [
                                 {
-                                    // 当前价
-                                    yAxis: datas.length ? datas[datas.length - 1][1] : 0,
+                                    yAxis: source[source.length - 1].close,
                                 },
                             ],
                         },
                     },
-                    {
-                        name: 'MA5',
-                        data: ma5,
-                    },
-                    {
-                        name: 'MA10',
-                        data: ma10,
-                    },
-                    {
-                        name: 'MA15',
-                        data: ma15,
-                    },
-                    {
-                        name: 'VOL',
-                        data: seriesType === 'VOL' ? volume : [],
-                    },
-                    {
-                        name: 'MACD',
-                        data: seriesType === 'MACD' ? macd : [],
-                    },
-                    {
-                        name: 'DIF',
-                        data: seriesType === 'MACD' ? dif : [],
-                    },
-                    {
-                        name: 'DEA',
-                        data: seriesType === 'MACD' ? dea : [],
-                    },
-                    {
-                        name: 'K',
-                        data: seriesType === 'KDJ' ? kdj.map((val) => val[0]) : [],
-                    },
-                    {
-                        name: 'D',
-                        data: seriesType === 'KDJ' ? kdj.map((val) => val[1]) : [],
-                    },
-                    {
-                        name: 'J',
-                        data: seriesType === 'KDJ' ? kdj.map((val) => val[2]) : [],
-                    },
-                    {
-                        name: 'CCI',
-                        data: seriesType === 'CCI' ? cci : [],
-                    },
                 ],
-            };
+            }
         }
     };
 
@@ -465,13 +396,11 @@ export function handleEchart() {
                     color: colors.axisPointerLabelColor,
                 },
             },
-            legend: [
-                {
-                    textStyle: {
-                        color: colors.legendTextColor,
-                    },
-                }
-            ],
+            legend: {
+                textStyle: {
+                    color: colors.legendTextColor,
+                },
+            },
             xAxis: [
                 {
                     splitLine: {
@@ -535,10 +464,8 @@ export function handleEchart() {
                     name: 'VOL',
                     itemStyle: {
                         color: (params: any) => {
-                            const i = params.dataIndex;
-                            const data = chartData.datas[i];
                             // 判断收盘价是否高于或等于开盘价
-                            if (data[1] >= data[0]) {
+                            if (params.data.close >= params.data.open) {
                                 return colors.upColor;
                             } else {
                                 return colors.downColor;
@@ -550,7 +477,7 @@ export function handleEchart() {
                     name: 'MACD',
                     itemStyle: {
                         color: (params: any) => {
-                            if (params.data > 0) {
+                            if (params.data.macd > 0) {
                                 return colors.upColor;
                             } else {
                                 return colors.downColor;

+ 16 - 13
src/common/components/echart/echart-timeline/index.vue

@@ -55,13 +55,15 @@ export default defineComponent({
             });
 
             chartData.value = {
-                datas,
-                times,
-                xAxisTimes,
                 yestclose,
                 decimal,
-                ma5: calcMA(datas, 5, decimal),
+                rawTime: times,
                 ...calcDataLine(datas, yestclose),
+                source: {
+                    time: xAxisTimes,
+                    data: datas,
+                    ma5: calcMA(datas, 5, decimal),
+                },
             };
         };
 
@@ -127,11 +129,11 @@ export default defineComponent({
             return result;
         };
 
-        // 更新图表K线数据
+        // 更新分时数据
         const updateChartData = () => {
-            const { datas, times } = chartData.value,
-                lastIndex = datas.length - 1, // 历史行情最后索引位置
-                lastTime = moment(times[times.length - 1]), // 历史行情最后时间
+            const { source, rawTime } = chartData.value,
+                lastIndex = source.data.length - 1, // 历史行情最后索引位置
+                lastTime = moment(rawTime[rawTime.length - 1]), // 历史行情最后时间
                 newTime = moment(props.quoteData.lasttime), // 实时行情最新时间
                 newPrice = props.quoteData.last; // 实时行情最新价
 
@@ -141,15 +143,16 @@ export default defineComponent({
             // 判断时间差是否大于周期时间
             if (diffTime > cycleMilliseconds) {
                 lastTime.add(cycleMilliseconds, 'ms');
-                times.push(lastTime.format('YYYY-MM-DD HH:mm:ss')); // 添加历史行情时间
-                datas.push(newPrice); // 添加历史行情数据
+                rawTime.push(lastTime.format('YYYY-MM-DD HH:mm:ss')); // 添加历史行情时间
+                source.data.push(newPrice); // 添加历史行情数据
                 historyIndexs.push(lastIndex + 1); // 添加历史行情索引
             } else {
-                datas[lastIndex] = newPrice; // 更新历史行情数据
+                source.data[lastIndex] = newPrice; // 更新历史行情数据
             }
 
-            const { min, max } = calcDataLine(datas, chartData.value.yestclose);
-            chartData.value.ma5 = calcMA(datas, 5, chartData.value.decimal);
+            source.ma5 = calcMA(source.data, 5, chartData.value.decimal);
+
+            const { min, max } = calcDataLine(source.data, chartData.value.yestclose);
             chartData.value.min = min;
             chartData.value.max = max;
 

+ 43 - 56
src/common/components/echart/echart-timeline/setup.ts

@@ -23,14 +23,16 @@ type Colors = {
 
 // 图表数据
 export type ChartData = {
-    datas: number[], // 历史数据
-    times: string[], // 历史时间
-    xAxisTimes: string[], // X轴时间数据
     yestclose: number, // 昨日收盘价
     decimal: number, // 保留小数位
-    min: number, // Y轴最低指标线
-    max: number, // Y轴最高指标线
-    ma5: (number | string)[], //均线数据
+    min: number, // yAxis最低指标线
+    max: number, // yAxis最高指标线
+    rawTime: string[], // 原始时间数据
+    source: {
+        time: string[], // xAxis数据,必须是第一个属性
+        data: number[], // series数据
+        ma5: string[],
+    },
 }
 
 export function handleEchart() {
@@ -39,14 +41,16 @@ export function handleEchart() {
     const theme = getTheme();
     // 图表数据
     const chartData = ref<ChartData>({
-        datas: [],
-        times: [],
-        xAxisTimes: [],
         yestclose: 0,
         decimal: 0,
         min: 0,
         max: 0,
-        ma5: []
+        rawTime: [],
+        source: {
+            time: [],
+            data: [],
+            ma5: [],
+        }
     });
 
     // 计算涨跌幅百分比,涨跌幅=(今日收盘价-昨日收盘价)/昨日收盘价*100%
@@ -57,8 +61,11 @@ export function handleEchart() {
 
     // 初始化图表配置
     const initOptions = () => {
-        const { datas, times, yestclose, min, max, ma5, decimal, xAxisTimes } = chartData.value;
+        const { yestclose, min, max, decimal, source, rawTime } = chartData.value;
         const option: EChartsOption = {
+            dataset: {
+                source,
+            },
             animation: false,
             legend: {
                 //图例控件,点击图例控制哪些系列不显示
@@ -86,13 +93,16 @@ export function handleEchart() {
                 formatter: (params: any) => {
                     let result = '';
                     params.forEach((item: any, index: number) => {
-                        if (index === 0) {
-                            result += '<div class="tooltip-title">' + moment(times[item.dataIndex]).format('YYYY-MM-DD HH:mm') + '</div>';
-                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>收盘</span><span>' + item.value + '</span></div>';
-                        }
-                        if (index === 2) {
-                            result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>均价</span><span>' + item.value + '</span></div>';
-                            result += '<div class="tooltip-item"><span><i></i>涨幅</span><span>' + calcRatio(item.value) + '</span></div>';
+                        // item.value = [time, data, ma5]
+                        if (item.value[1] !== undefined) {
+                            if (index === 0) {
+                                result += '<div class="tooltip-title">' + moment(rawTime[item.dataIndex]).format('YYYY-MM-DD HH:mm') + '</div>';
+                                result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>收盘</span><span>' + item.value[1] + '</span></div>';
+                            }
+                            if (index === 1) {
+                                result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>均价</span><span>' + item.value[2] + '</span></div>';
+                                result += '<div class="tooltip-item"><span><i></i>涨幅</span><span>' + calcRatio(item.value[2]) + '</span></div>';
+                            }
                         }
                     })
                     return result;
@@ -106,8 +116,6 @@ export function handleEchart() {
             },
             xAxis: {
                 type: 'category',
-                // X轴时间线
-                data: xAxisTimes,
                 splitLine: {
                     // 坐标分隔线
                     show: true,
@@ -119,7 +127,7 @@ export function handleEchart() {
                 }
             },
             yAxis: [
-                // Y轴左侧标签
+                // Y轴左侧数值标签
                 {
                     id: 'leftPrice',
                     scale: true,
@@ -129,7 +137,7 @@ export function handleEchart() {
                         formatter: (val: number) => toDecimalFull(val, decimal),
                     }
                 },
-                // Y轴右侧标签
+                // Y轴右侧涨跌幅标签
                 {
                     id: 'rightRatio',
                     scale: true,
@@ -149,7 +157,6 @@ export function handleEchart() {
                     name: '分时',
                     type: 'line',
                     yAxisId: 'leftPrice',
-                    data: datas,
                     smooth: true,
                     symbol: 'none', //中时有小圆点
                     lineStyle: {
@@ -163,7 +170,7 @@ export function handleEchart() {
                         data: [
                             {
                                 // 当前价
-                                yAxis: datas[datas.length - 1] ?? 0,
+                                yAxis: source.data[source.data.length - 1] ?? 0,
                             },
                             {
                                 // 昨结价
@@ -176,18 +183,8 @@ export function handleEchart() {
                     },
                 },
                 {
-                    type: 'line',
-                    yAxisId: 'rightRatio', // 关联Y轴右侧涨跌幅标签
-                    data: datas,
-                    symbol: 'none',
-                    lineStyle: {
-                        width: 0,
-                    },
-                },
-                {
                     name: '均价',
                     type: 'line',
-                    data: ma5,
                     smooth: true,
                     symbol: 'none',
                     lineStyle: {
@@ -203,32 +200,19 @@ export function handleEchart() {
 
     // 动态更新数据
     const updateOptions = () => {
-        const { datas, yestclose, ma5, min, max } = chartData.value;
-        if (datas.length) {
+        const { source, min, max, yestclose } = chartData.value;
+        if (source.data.length) {
             options.value = {
-                yAxis: [
-                    // Y轴左侧标签
-                    {
-                        id: 'leftPrice',
-                        min: min,
-                        max: max,
-                    },
-                    // Y轴右侧标签
-                    {
-                        id: 'rightRatio',
-                        min: min,
-                        max: max,
-                    },
-                ],
+                dataset: {
+                    source
+                },
                 series: [
                     {
                         name: '分时',
-                        data: datas,
                         markLine: {
                             data: [
                                 {
-                                    // 当前价
-                                    yAxis: datas[datas.length - 1],
+                                    yAxis: source.data[source.data.length - 1],
                                 },
                                 {
                                     // 昨结价
@@ -240,12 +224,15 @@ export function handleEchart() {
                             ],
                         },
                     },
+                ],
+                yAxis: [
                     {
-                        data: datas,
+                        min: min,
+                        max: max,
                     },
                     {
-                        name: '均价',
-                        data: ma5,
+                        min: min,
+                        max: max,
                     },
                 ],
             };