index.vue 3.48 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { SvgIcon } from '/@/components/Icon';
  import { computed, ref } from 'vue';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime';
  import { useDataFetch } from '../../../hook/socket/useSocket';
  import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useReceiveValue } from '../../../hook/useReceiveValue';
  import { useComponentScale } from '../../../hook/useComponentScale';

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

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

  const getDesign = computed(() => {
    const { persetOption = {}, option } = props.config;
    const {
      iconColor: persetIconColor,
      unit: perseUnit,
      icon: persetIcon,
      fontColor: persetFontColor,
      iconClose: persetIconCLose,
      iconColorClose: persetIconColorClose,
      showTime: persetShowTime,
      fontSize: persetFontSize,
    } = persetOption;

    const { componentInfo, attributeName, attributeRename } = option;

    const {
      icon,
      iconColor,
      fontColor,
      unit,
      iconClose,
      iconColorClose,
      showTime,
      fontSize,
      customIcon,
      customIconClose,
      defaultCustom,
    } = componentInfo || {};
    return {
      iconColor: iconColor || persetIconColor,
      unit: unit ?? perseUnit,
      icon: icon || persetIcon,
      fontColor: fontColor || persetFontColor,
      attribute: attributeRename || attributeName,
      iconClose: iconClose || persetIconCLose,
      iconColorClose: iconColorClose || persetIconColorClose,
      showTime: showTime ?? persetShowTime,
      fontSize: fontSize || persetFontSize || 14,
      defaultCustom: defaultCustom || 'default',
      customIcon: customIcon || [],
      customIconClose: customIconClose || [],
    };
  });

  const { getNumberValue } = useReceiveValue();

  const updateFn: DataFetchUpdateFn = (message, attribute) => {
    const { data = {} } = message;
    const [latest] = data[attribute] || [];
    if (!latest.length) return;
    const [timespan, value] = latest;
    time.value = timespan;
    isOpenClose.value = Boolean(getNumberValue(value));
  };

  useDataFetch(props, updateFn);

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

<template>
  <main class="w-full h-full flex flex-col justify-center items-center">
    <DeviceName :config="config" />
    <div class="flex flex-1 flex-col justify-center items-center">
      <SvgIcon
        v-if="getDesign.defaultCustom !== 'custom'"
        :name="getDesign.iconClose"
        prefix="iconfont"
        :size="getRatio ? getRatio * 70 : 70"
        :style="{ color: isOpenClose ? getDesign.iconColor : getDesign.iconColorClose }"
      />
      <img
        v-else
        :src="isOpenClose ? getDesign.customIcon[0]?.url : getDesign.customIconClose[0]?.url"
        :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }"
        :alt="getDesign.customIcon[0]?.name"
      />
      <div
        class="text-gray-500 truncate m-2"
        :style="{
          fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px',
        }"
        >{{ getDesign.attribute || '' }}</div
      >
    </div>
    <UpdateTime v-show="getDesign.showTime" :time="time" />
  </main>
</template>