index.vue 2.06 KB
<script lang="ts" setup>
import { computed, onMounted, ref, unref } from 'vue'
import { init } from 'echarts'
import type { ECharts, EChartsOption } from 'echarts'
import { getDefaultOption } from './index.config'
import type { CreateComponentType, RenderComponentExposeType } from '@/core/Library/types'
import { useLatestMessageValue } from '@/core/Library/hook/useLatestMessageValue'
import { useOnMessage } from '@/core/Library/hook/useOnMessage'
import type { CommandSource } from '@/core/websocket/processor'
import type { NodeDataDataSourceJsonType } from '@/api/node/model'
import type { SubscriptionUpdateMsg } from '@/core/websocket/type/message'
import { useContentDataStore } from '@/store/modules/contentData'

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 contentDataStore = useContentDataStore()

function initChartInstance() {
  chartInstance.value = init(unref(chartElRef))
  const currentNodeData = unref(contentDataStore.getCurrentNodeDataById(props.config))

  chartInstance.value.setOption(getDefaultOption(currentNodeData?.dataSourceJson.chartOption?.unit))
}

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

const onReceiveDataSourceMessage = (commandSource: CommandSource, message: SubscriptionUpdateMsg) => {
  const { data } = commandSource
  const { attr } = data as NodeDataDataSourceJsonType
  const { latestValue } = useLatestMessageValue(message.data, attr)
  unref(chartInstance)?.setOption({ series: [{ data: [{ value: latestValue }] }] } as EChartsOption)
}

const { onMessage } = useOnMessage({ onReceiveDataSourceMessage })

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>