index.vue 4.31 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';

  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 } = persetOption || {};
    return {
      dataSource: dataSource?.map((item) => {
        const { unit, fontColor } = item.componentInfo || {};
        const { attribute, attributeRename } = item;
        return {
          unit: unit ?? presetUnit,
          fontColor: fontColor ?? presetFontColor,
          attribute,
          attributeRename,
        };
      }),
    };
  });

  const options = (): EChartsOption => {
    // getStageColor(gradientInfo);
    return {
      tooltip: {
        trigger: 'item',
      },
      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 randomFn = () => {
  //   useIntervalFn(() => {
  //     const value = (Math.random() * 100).toFixed(0);
  //     unref(chartInstance)?.setOption({
  //       series: [{ data: [{ value }] }, { data: [{ value }] }],
  //     } as EChartsOption);
  //   }, 3000);
  // };

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

  const updateFn: MultipleDataFetchUpdateFn = (message) => {
    const { data = {} } = message;
    const { dataSource } = unref(getDesign);
    const series = dataSource.map((item) => {
      const { attribute, attributeRename, fontColor, unit } = item;
      const [latest] = data[attribute] || [];
      const [_timespan, value] = latest || [];

      return {
        value,
        name: attributeRename ?? attribute,
        itemStyle: { color: fontColor },
        tooltip: {
          valueFormatter(value) {
            return `${value} ${unit ?? ''}`;
          },
        },
      } as SeriesOption['data'];
    });
    updateChart(series);
  };

  useMultipleDataFetch(props, updateFn);

  onMounted(() => {
    initial();
    // !props.config.option.uuid && randomFn();
    !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>