index.vue 4.59 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 seriesList = [
    { value: 120, name: '123', itemStyle: { color: '#02E5F0' } },
    { value: 150, name: '456', itemStyle: { color: '#028CF0' } },
    { value: 40, name: '789', itemStyle: { color: '#F09202' } },
  ];
  const data = ['温度', '湿度', '温度1'];
  const options = (): EChartsOption => {
    // getStageColor(gradientInfo);
    return {
      color: ['#3398DB'],
      tooltip: {
        // 提示框
        trigger: 'axis',
        axisPointer: {
          type: 'shadow',
        },
      },
      xAxis: {
        type: 'category',
        data: data,
        axisTick: {
          alignWithLabel: true,
        },
        axisPointer: {
          type: 'line',
        },
      },
      grid: {
        top: '15%',
        left: '20%',
        bottom: '15%',
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          name: '',
          type: 'bar',
          barWidth: '60%',
          data: seriesList,
        },
      ],
    };
  };

  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'], xAxisData) => {
    unref(chartInstance)?.setOption({
      series: [{ data }],
      xAxis: { data: xAxisData },
      // 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'];
    });
    const xAxisData = series.map((item) => {
      const { name } = item as any;
      return name;
    });
    // }
    // console.log(message, 'message', series, 'series', sum);
    updateChart(series, xAxisData);
  };

  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>