index.vue 5.78 KB
<script lang="ts" setup>
  import { EChartsOption, SeriesOption, ECharts, init } from 'echarts';
  import { unref, ref, onMounted, computed, nextTick, toRaw } from 'vue';
  import { ComponentPropsConfigType } 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';
  import { useMultipleDataFetch } from '../../../hook/socket/useSocket';
  import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';
  import { useI18n } from '/@/hooks/web/useI18n';

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

  const { t } = useI18n();
  const chartRefEl = ref<Nullable<HTMLDivElement>>(null);

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

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

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

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

  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 = [
    t('visual.board.humidityText'),
    t('visual.board.temperatureText'),
    t('visual.board.temperatureText'),
  ];

  const options = (): EChartsOption => {
    return {
      color: ['#3398DB'],
      tooltip: {
        // 提示框
        trigger: 'item',
        confine: true,
        axisPointer: {
          type: 'shadow',
        },
      },
      xAxis: {
        type: 'category',
        data: data,
        axisTick: {
          alignWithLabel: true,
        },
      },
      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);
    toRaw(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) => {
    toRaw(unref(chartInstance))?.setOption({
      series: [{ data }],
      xAxis: { data: xAxisData },
      // color: unref(list).map((item) => item.title.color),
    } as EChartsOption);
  };

  const { forEachGroupMessage } = useReceiveMessage();
  const { getNumberValue } = useReceiveValue();

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

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

    updateChart(toRaw(unref(series)), xAxisData);
  };

  useMultipleDataFetch(props, updateFn);

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

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

    // 修改echarts大小
    toRaw(unref(chartInstance))?.setOption({
      legend: {
        textStyle: {
          fontSize: 14 * unref(getRatio),
        },
      },
    } as EChartsOption);
    toRaw(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-7/8 flex justify-center items-center flex-col mb-3"
    >
    </div>
    <!-- <UpdateTime :time="time" /> -->
  </main>
</template>