index.vue 7.41 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale';
  import { ref, unref } from 'vue';
  import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime';
  import { SvgIcon } from '/@/components/Icon';
  import { computed } from 'vue';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { useDataFetch } from '../../../hook/socket/useSocket';
  import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';
  import { useI18n } from '/@/hooks/web/useI18n';
  // import { isObject } from '/@/utils/is';

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

  const { t } = useI18n();

  const currentValue = ref<string | number>(123);

  const structuralData = ref<
    {
      label: string;
      value: string | number;
      icon: any;
      iconColor: string;
    }[]
  >([{ label: '温度', value: 20, icon: 'shuiwen', iconColor: '#367bff' }]);

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

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

  const getThingModelTsl = computed(() => {
    const { option } = props.config;

    const { deviceProfileId, attribute } = option;
    return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
  });

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

    const { componentInfo, attributeRename, structural, structuralLabel } = option;
    const { functionName } = unref(getThingModelTsl) || {};

    const {
      icon,
      iconColor,
      fontColor,
      showTime,
      unit,
      valueSize,
      fontSize,
      customIcon,
      defaultCustom,
    } = componentInfo || {};
    return {
      iconColor: iconColor || persetIconColor,
      unit: unit ?? perseUnit,
      icon: icon || persetIcon,
      fontColor: fontColor || persetFontColor,
      attribute: attributeRename || functionName,
      valueSize: valueSize || persetValueSize || 20,
      fontSize: fontSize || persetFontSize || 14,
      showTime: showTime || persetShowTime,
      defaultCustom: defaultCustom || 'default',
      customIcon: customIcon || [],
      structural: structural || [],
      structuralLabel: structuralLabel || [],
      componentInfo,
    };
  });

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

    const { structuralLabel, structural, componentInfo } = unref(getDesign) || {};
    const { defaultCustom } = componentInfo || {};

    time.value = timespan;
    if (structural?.length && structuralLabel?.length) {
      const values = JSON.parse(value);
      const newValues =
        defaultCustom === 'custom'
          ? structural.map((item, index) => {
              const option = {
                label: structuralLabel[index],
                value: values?.[item] || 0,
                icon: componentInfo[item + 'StructuralCustomIcon'],
                // iconColor: componentInfo[item + 'CustomIconColor'],
              };
              return option;
            })
          : structural.map((item, index) => {
              const option = {
                label: structuralLabel[index],
                value: values?.[item] || 0,
                icon: componentInfo[item + 'StructuralIcon'],
                iconColor: componentInfo[item + 'StructuralIconColor'],
              };
              return option;
            });
      structuralData.value = newValues;
      return;
    }

    currentValue.value = useThingsModelValueTransform(
      value,
      unref(getThingModelTsl)?.specs?.dataType
    );
  };

  useDataFetch(props, updateFn);

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

<template>
  <main
    :style="getScale"
    class="w-full h-full flex flex-col justify-center items-center"
    :class="!getDesign.showTime && 'p-5'"
  >
    <DeviceName :config="config" />
    <!-- <div class="flex-1 flex justify-center items-center flex-col w-full">
      <SvgIcon
        v-if="getDesign.defaultCustom !== 'custom'"
        :name="getDesign.icon!"
        prefix="iconfont"
        :size="getRatio ? getRatio * 70 : 70"
        :style="{ color: getDesign.iconColor }"
      />
      <img
        v-else
        :src="getDesign.customIcon[0]?.url"
        :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }"
        :alt="getDesign.customIcon[0]?.name"
      />
      <h1
        class="font-bold m-2 truncate w-full text-center"
        :style="{
          color: getDesign.fontColor,
          fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px',
        }"
      >
        <span> {{ currentValue || 0 }}</span>
        <span>{{ getDesign.unit }} </span>
      </h1>
      <div
        class="text-gray-500 truncate"
        :style="{
          fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px',
        }"
        >{{ getDesign.attribute || '温度' }}</div
      >
    </div> -->
    <div class="flex flex-1 justify-center items-center w-full flex-wrap">
      <div
        v-for="item in structuralData"
        :key="item.label"
        class="flex-1 flex justify-center items-center flex-col w-full"
      >
        <SvgIcon
          v-if="getDesign.defaultCustom !== 'custom'"
          :name="item.icon || 'shuiwen'"
          prefix="iconfont"
          :size="getRatio ? (getRatio * 70) / structuralData?.length || 1 : 70"
          :style="{ color: item.iconColor || '#367bff' }"
        />
        <img
          v-else
          :src="item.icon?.[0]?.url!"
          :style="{
            width: getRatio ? (getRatio * 70) / structuralData?.length + 'px' : '70px',
            height: getRatio ? (getRatio * 70) / structuralData?.length + 'px' : '70px',
          }"
          :alt="item.icon?.[0]?.name!"
        />
        <h1
          class="font-bold m-2 truncate w-full text-center"
          :style="{
            color: getDesign.fontColor,
            fontSize:
              (getRatio
                ? (getRatio * getDesign.valueSize) / structuralData?.length || 1
                : getDesign.valueSize) + 'px',
          }"
        >
          <span> {{ item.value || 0 }}</span>
          <span>{{ getDesign.unit }} </span>
        </h1>
        <div
          class="text-gray-500 truncate text-center"
          :style="{
            fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px',
            width: getRatio ? getRatio * 90 + 'px' : '90px',
          }"
          >{{
            (getDesign?.attribute || t('visual.board.structuralText')) + '-' + item.label ||
            t('visual.board.temperatureText')
          }}</div
        >
      </div>
    </div>
    <UpdateTime v-show="getDesign.showTime" :time="time" />
  </main>
</template>