index.vue 4.76 KB
<script lang="ts" setup>
  import { EChartsOption, SeriesOption, ECharts, init } from 'echarts';
  import { unref, ref, onMounted, computed, nextTick } from 'vue';
  import { useMultipleDataFetch } from '../../../hook/useSocket';
  import { ComponentPropsConfigType, MultipleDataFetchUpdateFn } from '../../../index.type';
  import { option } from './config';
  import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime';
  import { useComponentScale } from '../../../hook/useComponentScale';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { useReceiveMessage } from '../../../hook/useReceiveMessage';
  import { useReceiveValue } from '../../../hook/useReceiveValue';

  const props = defineProps<{
    config: ComponentPropsConfigType<typeof option>;
  }>();

  const chartRefEl = ref<Nullable<HTMLDivElement>>(null);

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

  const time = ref<Nullable<number>>(null);

  const getDesign = computed(() => {
    const { persetOption, option } = props.config;
    const { dataSource = [] } = option || {};
    const {
      unit: presetUnit,
      fontColor: presetFontColor,
      presetShowDeviceName,
    } = persetOption || {};
    return {
      dataSource: dataSource?.map((item) => {
        const { unit, fontColor, showDeviceName } = item.componentInfo || {};
        const { attribute, attributeName, attributeRename, deviceName, deviceRename, deviceId } =
          item;
        return {
          unit: unit ?? presetUnit,
          fontColor: fontColor ?? presetFontColor,
          attribute,
          attributeRename,
          attributeName,
          showDeviceName: showDeviceName ?? presetShowDeviceName,
          deviceName,
          deviceRename,
          id: deviceId,
        };
      }),
    };
  });

  const series = ref(
    unref(getDesign).dataSource.map((item) => ({
      value: 0,
      name: `${item.showDeviceName ? `${item.deviceRename || item.deviceName}-` : ''}${
        item.attributeRename || item.attributeName || item.attribute
      }`,
      attribute: item.attribute,
      id: item.id,
      itemStyle: {
        color: item.fontColor,
      },
      tooltip: {
        valueFormatter(value) {
          return `${value} ${item.unit ?? ''}`;
        },
      },
    }))
  );
  // console.log(unref(series), 'series');

  const options = (): EChartsOption => {
    // getStageColor(gradientInfo);
    return {
      tooltip: {
        trigger: 'item',
        confine: true,
      },
      legend: {
        top: '5%',
        left: 'center',
        textStyle: {
          fontSize: unref(getRatio) ? 14 * unref(getRatio) : 14,
        },
      },
      series: [
        {
          name: '',
          type: 'pie',
          radius: ['%', '70%'],
          center: ['50%', '65%'],
          avoidLabelOverlap: false,
          itemStyle: {
            borderRadius: 4,
            borderColor: '#fff',
            borderWidth: 2,
          },
          label: {
            show: false,
            position: 'center',
          },
          labelLine: {
            show: false,
          },
          data: [
            { value: 1048, name: '数据1' },
            { value: 735, name: '数据2' },
            { value: 580, name: '数据3' },
          ],
        },
      ],
    };
  };

  const initial = () => {
    chartInstance.value = init(unref(chartRefEl)! as HTMLElement);
    chartInstance.value.setOption(options());
  };

  const updateChart = (data: SeriesOption['data']) => {
    unref(chartInstance)?.setOption({
      series: [{ data }],
    } as EChartsOption);
  };

  const { forEachGroupMessage } = useReceiveMessage();
  const { getNumberValue } = useReceiveValue();
  const updateFn: MultipleDataFetchUpdateFn = (message, deviceId, attribute) => {
    forEachGroupMessage(message, deviceId, attribute, (attribute, value, timespan) => {
      series.value.forEach((item) => {
        if (item.id === deviceId && item.attribute === attribute) {
          item.value = getNumberValue(value);
          time.value = timespan;
        }
      });
    });

    updateChart(unref(series));
  };

  useMultipleDataFetch(props, updateFn);

  onMounted(() => {
    initial();
    !props.config.option.uuid;
  });

  const resize = async () => {
    await nextTick();

    // 修改echarts大小
    unref(chartInstance)?.setOption({
      legend: {
        textStyle: {
          fontSize: 14 * unref(getRatio),
        },
      },
    } as EChartsOption);
    unref(chartInstance)?.resize();
  };

  const { getRatio } = useComponentScale(props, resize);
</script>

<template>
  <main class="w-full h-full flex flex-col justify-center items-center">
    <DeviceName :config="config" />
    <div ref="chartRefEl" class="flex-1 w-full h-full"> </div>
    <UpdateTime :time="time" />
  </main>
</template>