Commit 4d78bfbdaa59e2f37ef4faa36aab0dc543f43c46

Authored by fengwotao
1 parent 4b3a9162

perf(src/packages): 优化封装ws数据格式hook

  1 +/**
  2 + * 此hook的作用是 ws 组装图表需要的数据格式
  3 + * @param data {'wendu':[[xxxxxx,xxxx]]}
  4 + * @returns keys:[xx,xx,xx] record:{'x':'xx'}
  5 + */
  6 +import dayjs from 'dayjs'
  7 +
  8 +export const useAssembleDataHooks = (data: Record<string, string | [number, string]>) => {
  9 + const formatValueToNumber = (value: string | number, defaultValue = 0) =>
  10 + isNaN(value as number) ? defaultValue : Number(value)
  11 +
  12 + const keys = Object.keys(data)
  13 +
  14 + const record = keys.reduce((prev, next) => {
  15 + const [latest] = data[next] || []
  16 + const [ts, value] = latest as unknown as string[]
  17 + //把值转为number类型 wendu:"23" 转为 wendu:23
  18 + return { ...prev, ts: dayjs(ts).format('YYYY-MM-DD HH:mm:ss'), [next]: formatValueToNumber(value) }
  19 + }, {})
  20 +
  21 + return {
  22 + keys,
  23 + record
  24 + }
  25 +}
1 <template> 1 <template>
2 <v-chart 2 <v-chart
3 - ref="vChartRef"  
4 - :init-options="initOptions"  
5 - :theme="themeColor"  
6 - :option="option"  
7 - :manual-update="isPreview()"  
8 - :update-options="{ 3 + ref="vChartRef"
  4 + :init-options="initOptions"
  5 + :theme="themeColor"
  6 + :option="option"
  7 + :manual-update="isPreview()"
  8 + :update-options="{
9 replaceMerge: replaceMergeArr 9 replaceMerge: replaceMergeArr
10 }" 10 }"
11 - autoresize  
12 - @mouseover="handleHighlight"  
13 - @mouseout="handleDownplay" 11 + autoresize
  12 + @mouseover="handleHighlight"
  13 + @mouseout="handleDownplay"
14 > 14 >
15 </v-chart> 15 </v-chart>
16 </template> 16 </template>
17 17
18 <script setup lang="ts"> 18 <script setup lang="ts">
19 -import {ref, nextTick, computed, watch, PropType, onMounted} from 'vue' 19 +import { ref, nextTick, computed, watch, PropType, onMounted } from 'vue'
20 import VChart from 'vue-echarts' 20 import VChart from 'vue-echarts'
21 -import {useCanvasInitOptions} from '@/hooks/useCanvasInitOptions.hook'  
22 -import {use} from 'echarts/core'  
23 -import {CanvasRenderer} from 'echarts/renderers'  
24 -import {BarChart} from 'echarts/charts'  
25 -import config, {includes, seriesItem} from './config'  
26 -import {mergeTheme} from '@/packages/public/chart'  
27 -import {useChartDataFetch} from '@/hooks'  
28 -import {CreateComponentType} from '@/packages/index.d'  
29 -import {useChartEditStore} from '@/store/modules/chartEditStore/chartEditStore'  
30 -import {isPreview} from '@/utils'  
31 -import {DatasetComponent, GridComponent, TooltipComponent, LegendComponent} from 'echarts/components' 21 +import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
  22 +import { use } from 'echarts/core'
  23 +import { CanvasRenderer } from 'echarts/renderers'
  24 +import { BarChart } from 'echarts/charts'
  25 +import config, { includes, seriesItem } from './config'
  26 +import { mergeTheme } from '@/packages/public/chart'
  27 +import { useChartDataFetch } from '@/hooks'
  28 +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  29 +import { isPreview } from '@/utils'
  30 +import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
32 import isObject from 'lodash/isObject' 31 import isObject from 'lodash/isObject'
33 import dataJson from './data.json' 32 import dataJson from './data.json'
34 -import {useFullScreen} from '../../utls/fullScreen' 33 +import { useFullScreen } from '../../utls/fullScreen'
  34 +import cloneDeep from 'lodash/cloneDeep'
  35 +import { useAssembleDataHooks } from '@/hooks/external/useAssembleData.hook'
  36 +import { SocketReceiveMessageType } from '@/store/external/modules/socketStore.d'
35 37
36 const props = defineProps({ 38 const props = defineProps({
37 themeSetting: { 39 themeSetting: {
@@ -77,33 +79,46 @@ const toolBoxOption = { @@ -77,33 +79,46 @@ const toolBoxOption = {
77 } 79 }
78 props.chartConfig.option = { 80 props.chartConfig.option = {
79 ...props.chartConfig.option, 81 ...props.chartConfig.option,
80 - ...{toolbox: toolBoxOption} 82 + ...{ toolbox: toolBoxOption }
81 } 83 }
82 84
83 // dataset 无法变更条数的补丁 85 // dataset 无法变更条数的补丁
84 watch( 86 watch(
85 - () => props.chartConfig.option.dataset,  
86 - (newData: { dimensions: any }, oldData) => {  
87 - try {  
88 - if (!isObject(newData) || !('dimensions' in newData)) return  
89 - if (Array.isArray(newData?.dimensions)) {  
90 - const seriesArr = []  
91 - for (let i = 0; i < newData.dimensions.length - 1; i++) {  
92 - seriesArr.push(seriesItem) 87 + () => props.chartConfig.option.dataset,
  88 + (newData: { dimensions: any }, oldData) => {
  89 + try {
  90 + if (!isObject(newData) || !('dimensions' in newData)) return
  91 + if (Array.isArray(newData?.dimensions)) {
  92 + const seriesArr = []
  93 + // 对oldData进行判断,防止传入错误数据之后对旧维度判断产生干扰
  94 + // 此处计算的是dimensions的Y轴维度,若是dimensions.length为0或1,则默认为1,排除X轴维度干扰
  95 + const oldDimensions =
  96 + Array.isArray(oldData?.dimensions) && oldData.dimensions.length >= 1 ? oldData.dimensions.length : 1
  97 + const newDimensions = newData.dimensions.length >= 1 ? newData.dimensions.length : 1
  98 + const dimensionsGap = newDimensions - oldDimensions
  99 + if (dimensionsGap < 0) {
  100 + props.chartConfig.option.series.splice(newDimensions - 1)
  101 + } else if (dimensionsGap > 0) {
  102 + if (!oldData || !oldData?.dimensions || !Array.isArray(oldData?.dimensions) || !oldData?.dimensions.length) {
  103 + props.chartConfig.option.series = []
93 } 104 }
94 - replaceMergeArr.value = ['series']  
95 - props.chartConfig.option.series = seriesArr  
96 - nextTick(() => {  
97 - replaceMergeArr.value = []  
98 - }) 105 + for (let i = 0; i < dimensionsGap; i++) {
  106 + seriesArr.push(cloneDeep(seriesItem))
  107 + }
  108 + props.chartConfig.option.series.push(...seriesArr)
99 } 109 }
100 - } catch (error) {  
101 - console.log(error) 110 + replaceMergeArr.value = ['series']
  111 + nextTick(() => {
  112 + replaceMergeArr.value = []
  113 + })
102 } 114 }
103 - },  
104 - {  
105 - deep: false 115 + } catch (error) {
  116 + console.log(error)
106 } 117 }
  118 + },
  119 + {
  120 + deep: false
  121 + }
107 ) 122 )
108 123
109 let seriesDataNum = -1 124 let seriesDataNum = -1
@@ -167,30 +182,51 @@ const handleDownplay = () => { @@ -167,30 +182,51 @@ const handleDownplay = () => {
167 } 182 }
168 183
169 watch( 184 watch(
170 - () => props.chartConfig.option.isCarousel,  
171 - newData => {  
172 - if (newData) {  
173 - addPieInterval(undefined, true)  
174 - props.chartConfig.option.legend.show = false  
175 - } else {  
176 - props.chartConfig.option.legend.show = true  
177 - clearPieInterval()  
178 - } 185 + () => props.chartConfig.option.isCarousel,
  186 + newData => {
  187 + if (newData) {
  188 + addPieInterval(undefined, true)
  189 + props.chartConfig.option.legend.show = false
  190 + } else {
  191 + props.chartConfig.option.legend.show = true
  192 + clearPieInterval()
179 } 193 }
  194 + }
180 ) 195 )
181 196
182 //fix 修复v-chart图表绑定联动组件视图不更新问题 197 //fix 修复v-chart图表绑定联动组件视图不更新问题
183 -const updateVChart = (newData: any) => {  
184 - if (!newData) return  
185 - vChartRef.value?.clear()  
186 - vChartRef.value?.setOption({  
187 - ...option.value,  
188 - dataset: newData  
189 - }) 198 +const updateVChart = (newData:SocketReceiveMessageType) => {
  199 + //区分是普通请求还是ws请求
  200 + if (!isObject(newData) || !('dimensions' in newData)) {
  201 + const { data } = newData
  202 + const { keys, record } = useAssembleDataHooks(data)
  203 + vChartRef.value?.setOption({
  204 + dataset: {
  205 + dimensions: ['ts', ...keys],
  206 + source: [record]
  207 + }
  208 + })
  209 + } else {
  210 + //异步更新,同步更新会造成联动组件控制,图表不及时更新
  211 + new Promise((resolve) => {
  212 + setTimeout(() => {
  213 + resolve(
  214 + vChartRef.value?.setOption(
  215 + {
  216 + ...option.value,
  217 + dataset: newData
  218 + },
  219 + {
  220 + notMerge: true
  221 + }
  222 + )
  223 + )
  224 + }, 100)
  225 + })
  226 + }
190 } 227 }
191 228
192 -const {vChartRef} = useChartDataFetch(props.chartConfig, useChartEditStore, (newData) => {  
193 - // addPieInterval(newData) 229 +const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, newData => {
194 updateVChart(newData) 230 updateVChart(newData)
195 }) 231 })
196 232
@@ -31,7 +31,7 @@ import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } fr @@ -31,7 +31,7 @@ import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } fr
31 import dataJson from './data.json' 31 import dataJson from './data.json'
32 import { useFullScreen } from '../../utls/fullScreen' 32 import { useFullScreen } from '../../utls/fullScreen'
33 import { SocketReceiveMessageType } from '@/store/external/modules/socketStore.d' 33 import { SocketReceiveMessageType } from '@/store/external/modules/socketStore.d'
34 -import dayjs from 'dayjs' 34 +import { useAssembleDataHooks } from '@/hooks/external/useAssembleData.hook'
35 35
36 const props = defineProps({ 36 const props = defineProps({
37 themeSetting: { 37 themeSetting: {
@@ -161,20 +161,11 @@ watch( @@ -161,20 +161,11 @@ watch(
161 } 161 }
162 ) 162 )
163 163
164 -const formatValueToNumber = (value: string | number, defaultValue = 0) =>  
165 - isNaN(value as number) ? defaultValue : Number(value)  
166 -  
167 //fix 修复v-chart图表绑定联动组件视图不更新问题 164 //fix 修复v-chart图表绑定联动组件视图不更新问题
168 const updateVChart = (newData: SocketReceiveMessageType) => { 165 const updateVChart = (newData: SocketReceiveMessageType) => {
169 if (!newData) return 166 if (!newData) return
170 const { data } = newData 167 const { data } = newData
171 - const keys = Object.keys(data)  
172 - const record = keys.reduce((prev, next) => {  
173 - const [latest] = data[next] || []  
174 - const [ts, value] = latest as unknown as string[]  
175 - return { ...prev, ts: dayjs(ts).format('YYYY-MM-DD HH:mm:ss'), [next]: formatValueToNumber(value) }  
176 - // return { ...prev, ts, [next]: formatValueToNumber(value) }  
177 - }, {}) 168 + const {keys,record}= useAssembleDataHooks(data)
178 if (unref(realTimeList).length >= chartMaxDataPoint.value) { 169 if (unref(realTimeList).length >= chartMaxDataPoint.value) {
179 unref(realTimeList).splice(0, 1) 170 unref(realTimeList).splice(0, 1)
180 } 171 }