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

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

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

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

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

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

  const getOffset = (length: number, index: number) => {
    const offsetList = ref<any>([]);
    switch (length) {
      case 1:
        return (offsetList.value = [
          ['0%', '0%'],
          ['0%', '15%'],
        ]);
        break;
      case 2:
        return (offsetList.value = [
          index == 0 ? ['0%', '-35%'] : ['0%', '0%'],
          index == 0 ? ['0%', '-20%'] : ['0%', '18%'],
        ]);
        break;
      case 3:
        return (offsetList.value = [
          index == 0 ? ['0%', '-35%'] : index == 1 ? ['0%', '0%'] : ['0%', '35%'],
          index == 0 ? ['0%', '-20%'] : index == 1 ? ['0%', '18%'] : ['0%', '50%'],
        ]);
        break;
      case 4:
        return (offsetList.value = [
          index == 0
            ? ['0%', '-45%']
            : index == 1
            ? ['0%', '-15%']
            : index == 2
            ? ['0%', '15%']
            : ['0%', '45%'],
          index == 0
            ? ['0%', '-30%']
            : index == 1
            ? ['0%', '0%']
            : index == 2
            ? ['0%', '30%']
            : ['0%', '60%'],
        ]);
        break;
      case 5:
        return (offsetList.value = [
          index == 0
            ? ['0%', '-50%']
            : index == 1
            ? ['0%', '-25%']
            : index == 2
            ? ['0%', '0%']
            : index == 3
            ? ['0%', '25%']
            : ['0%', '50%'],
          index == 0
            ? ['0%', '-40%']
            : index == 1
            ? ['0%', '-15%']
            : index == 2
            ? ['0%', '10%']
            : index == 3
            ? ['0%', '35%']
            : ['0%', '60%'],
        ]);
        break;
      case 6:
        return (offsetList.value = [
          index == 0
            ? ['0%', '-55%']
            : index == 1
            ? ['0%', '-35%']
            : index == 2
            ? ['0%', '-15%']
            : index == 3
            ? ['0%', '5%']
            : index == 4
            ? ['0%', '25%']
            : ['0%', '45%'],
          index == 0
            ? ['0%', '-45%']
            : index == 1
            ? ['0%', '-25%']
            : index == 2
            ? ['0%', '-5%']
            : index == 3
            ? ['0%', '15%%']
            : index == 4
            ? ['0%', '35%']
            : ['0%', '55%'],
        ]);
        break;
    }
    return unref(offsetList);
  };

  const series = ref(
    unref(getDesign).dataSource.map((item, index) => ({
      value: 30,
      name: `${item.showDeviceName ? `${item.deviceRename || item.deviceName}-` : ''}${
        item.attributeRename || item.attributeName || item.attribute
      }`,
      attribute: item.attribute,
      id: item.id,
      title: {
        color: item.fontColor,
        offsetCenter: getOffset(unref(getDesign).dataSource.length, index)[0],
      },
      detail: {
        color: item.fontColor,
        valueAnimation: true,
        offsetCenter: getOffset(unref(getDesign).dataSource.length, index)[1],
        formatter: `{value} ${item.unit ?? ''}`,
      },
    }))
  );

  const gaugeData = [
    {
      value: 30,
      name: '',
      title: {
        offsetCenter: ['0%', '-35%'],
      },
      detail: {
        valueAnimation: true,
        offsetCenter: ['0%', '-20%'],
      },
    },
    {
      value: 40,
      name: '',
      title: {
        offsetCenter: ['0%', '0%'],
      },
      detail: {
        valueAnimation: true,
        offsetCenter: ['0%', '15%'],
      },
    },
  ];

  const options = (): EChartsOption => {
    // const { fontColor } = unref(getDesign);
    const { fontColor } = unref(getDesign).dataSource[0] || [];
    return {
      color: ['#377DFF', '#FD666D', '#00F0F0'],
      series: [
        {
          type: 'gauge',
          startAngle: 90,
          endAngle: -270,
          pointer: {
            show: false,
          },
          progress: {
            show: true,
            overlap: false,
            roundCap: true,
            clip: false,
            itemStyle: {
              borderWidth: 1,
              borderColor: '#464646',
            },
          },
          axisLine: {
            lineStyle: {
              width: unref(getRatio) ? 25 * unref(getRatio) : 18,
            },
          },
          splitLine: {
            show: false,
            distance: 0,
            length: 10,
          },
          axisTick: {
            show: false,
          },
          axisLabel: {
            show: false,
            distance: 50,
          },
          data: gaugeData,
          title: {
            fontSize: unref(getRatio) ? 10 * unref(getRatio) : 10,
          },
          detail: {
            width: 50,
            height: 16,
            fontSize: unref(getRatio) ? 10 * unref(getRatio) : 10,
            color: fontColor || 'inherit',
          },
        },
      ],
    };
  };

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

  const { forEachGroupMessage } = useReceiveMessage();
  const { getNumberValue } = useReceiveValue();
  const updateFn: MultipleDataFetchUpdateFn = (message, deviceId, attribute) => {
    forEachGroupMessage(message, deviceId, attribute, (attribute, value) => {
      series.value.forEach((item) => {
        if (item.id === deviceId && item.attribute === attribute && value) {
          item.value = getNumberValue(value);
        }
      });
    });
    unref(chartInstance)?.setOption({
      series: [{ data: unref(series), pointer: { show: false } }],
      color: unref(series).map((item) => item.title.color),
    });
  };

  useMultipleDataFetch(props, updateFn);

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

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

    // 修改echarts大小
    unref(chartInstance)?.setOption({
      series: [
        {
          title: {
            fontSize: 10 * unref(getRatio),
          },
          detail: {
            fontSize: 10 * unref(getRatio),
          },
          axisLine: {
            lineStyle: {
              width: 25 * unref(getRatio),
            },
          },
        },
      ],
      title: {
        textStyle: {
          fontSize: 12 * unref(getRatio),
        },
      },
    });
    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 justify-center items-center flex-col flex">
    </div>
    <!-- <UpdateTime :time="time" /> -->
  </main>
</template>