index.vue 4.01 KB
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, toRaw, unref } from 'vue'
import { init } from 'echarts'
import type { ECharts, EChartsOption } from 'echarts'
import { defaultOption } from './index.config'
import type { CreateComponentType, RenderComponentExposeType } from '@/core/Library/types'
import { useOnMessage } from '@/core/Library/hook/useOnMessage'
import type { NodeDataDataSourceJsonType } from '@/api/node/model'
import { SocketSubscriberEnum } from '@/enums/datasource'
import type { SubscriptionData } from '@/core/websocket/type/message'
import { formatToDateTime } from '@/utils/dateUtil'
import type { CommandSource } from '@/core/websocket/processor'
import { useProductsStore } from '@/store/modules/products'

const props = defineProps<{
  config: CreateComponentType
}>()

const getCellBounds = computed(() => props.config.cellBounds || { width: 300, height: 300, x: 0, y: 0 })

const chartElRef = ref<Nullable<HTMLDivElement>>()

const chartInstance = ref<Nullable<ECharts>>()

const seriesData = ref<any>([])
const XAxisData = ref<any>([])
const titleATTR = ref<string[] | any>([])

function initChartInstance() {
  chartInstance.value = init(unref(chartElRef))
  chartInstance.value.setOption(defaultOption())
}

const productsStore = useProductsStore()

const handleHistoryData = (commandSource: CommandSource, message: SubscriptionData) => {
  const { data } = commandSource
  const { attr, deviceName } = data as NodeDataDataSourceJsonType as any

  attr.forEach((item: any) => { // 得到所有时间
    XAxisData.value.push(...message[item].map((item1) => {
      const [ts] = item1
      return ts
    }))
  })
  XAxisData.value = Array.from(new Set(XAxisData.value)).sort((a: any, b: any) => a - b)// 去重获取到的时间
  // 初始化有几个柱
  seriesData.value.forEach((item: any) => {
    item.data = unref(XAxisData).map((time: any) => ({ name: time, value: '' }))
  })

  // 跟每个柱添加数据
  seriesData.value.forEach((item: any) => {
    item.data.forEach((item1: any) => {
      message[item.attribute].forEach((messageItem) => {
        const [ts, value] = messageItem
        if (item1.name === ts)
          item1.value = value || ''
          // item1.name = formatToDateTime(item1.name)
      })
    })
  })

  unref(chartInstance)?.setOption({
    title: {
      text: `${deviceName || ''}`,
    },
    xAxis: [
      {
        type: 'category',
        data: toRaw(unref(XAxisData.value.map((item: string | number) => formatToDateTime(item)))),
      },
    ],
    legend: {
      data: unref(titleATTR),
    },
    series: toRaw(unref(seriesData).map((item: { type: string; name: string; data: any; attribute: string }) => {
      const { type, name, data } = item
      return {
        type,
        name,
        data: data.map((item: any) => item.value),
      }
    })),
  } as EChartsOption)
}

const { onMessage } = useOnMessage({
  onReceiveDataSourceMessage(commandSource, message) {
    const { data } = commandSource
    const { chartOption, attr, deviceProfileId } = data as NodeDataDataSourceJsonType
    const { queryType } = chartOption || {}
    if (!seriesData.value.length) {
      (attr as string[]).forEach((item: string) => {
        titleATTR.value.push(productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName)
        seriesData.value.push({ attribute: item, data: [], type: 'bar', name: productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName })
      })
    }

    if (queryType === SocketSubscriberEnum.HISTORY_CMDS)
      handleHistoryData(commandSource, message.data)
  },
})

onMounted(() => {
  initChartInstance()
})

onUnmounted(() => {
  chartInstance.value?.dispose()
  chartInstance.value = null
})

defineExpose<RenderComponentExposeType>({ onMessage })
</script>

<template>
  <div class="w-full h-full justify-center flex items-center">
    <div
      ref="chartElRef"
      :style="{ width: `${getCellBounds.width}px`, height: `${getCellBounds.height}px` }"
      class="w-full h-full"
    />
  </div>
</template>