index.vue 5.51 KB
<script lang="ts" setup>
  import { option } from './config';
  import { ComponentPropsConfigType } from '../../../index.type';
  import { Slider } from 'ant-design-vue';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { useReceiveMessage } from '../../../hook/useReceiveMessage';
  import { buildUUID } from '/@/utils/uuid';
  import { useReceiveValue } from '../../../hook/useReceiveValue';
  import { ref, computed, unref, onMounted } from 'vue';
  import { useMultipleDataFetch } from '../../../hook/socket/useSocket';
  import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useComponentScale } from '../../../hook/useComponentScale';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';

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

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

  interface PercentType {
    value?: number;
    fontColor: string;
    backgroundColor: string;
    unit: string;
    id: string;
    attribute?: string;
    attributeRename?: string;
    deviceId?: string;
    deviceName?: string;
    attributeName?: string;
    deviceRename?: string;
    maxNumber?: number;
    [key: string]: number | string | undefined;
  }

  const defaultValue: PercentType[] = [
    {
      value: 20,
      fontColor: '#377dff',
      backgroundColor: '#377dff',
      unit: '℃',
      deviceName: '温湿度',
      attribute: '温度',
      fontSize: 14,
      valueSize: 20,
      id: buildUUID(),
    },
    {
      value: 66,
      fontColor: '#1E8667',
      backgroundColor: '#1E8667',
      unit: '℃',
      deviceName: '温湿度',
      attribute: '湿度',
      id: buildUUID(),
    },
  ];

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

  const getDesign = computed(() => {
    const { persetOption = {}, option } = props.config;
    const { dataSource = [] } = option || {};
    const {
      unit: presetUnit,
      fontColor: presetFontColor,
      backgroundColor: persetBackgroundColor,
      maxNumber: persetMaxNumber,
      valueSize: persetValueSize,
      fontSize: persetFontSize,
    } = persetOption || {};
    return {
      dataSource: dataSource.map((item) => {
        const { unit, fontColor, backgroundColor, maxNumber, valueSize, fontSize } =
          item.componentInfo || {};
        const { attribute, attributeRename, deviceProfileId, deviceName, deviceRename, deviceId } =
          item;

        const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
        return {
          unit: unit ?? presetUnit,
          fontColor: fontColor ?? presetFontColor,
          backgroundColor: backgroundColor ?? persetBackgroundColor,
          deviceName: deviceRename || deviceName,
          attribute,
          attributeName: attributeRename || tsl?.functionName,
          maxNumber: maxNumber || persetMaxNumber,
          id: deviceId,
          valueSize: valueSize || persetValueSize || 20,
          fontSize: fontSize || persetFontSize || 14,
        } as PercentType;
      }),
    };
  });
  const percentList = ref<any>(
    props.config.option.dataSource ? unref(getDesign).dataSource : defaultValue
  );

  const { forEachGroupMessage } = useReceiveMessage();

  const { getNumberValue } = useReceiveValue();
  const updateFn: MultipleDataFetchUpdateFn = (message, deviceId, attribute) => {
    forEachGroupMessage(message, deviceId, attribute, (attribute, value, timespan) => {
      percentList.value.forEach((item) => {
        if (item.id === deviceId && item.attribute === attribute && value) {
          item.value = getNumberValue(value);
          time.value = timespan;
        }
      });
    });
  };

  onMounted(() => {});

  useMultipleDataFetch(props, updateFn);
  const { getRatios } = useComponentScale(props);
</script>

<template>
  <main class="w-full h-full flex flex-col justify-evenly">
    <DeviceName :config="config" />

    <div v-for="item in percentList" :key="item.id" class="flex flex-col ml-3 mr-3 items-stretch">
      <div class="flex justify-between items-center">
        <div
          class="text-gray-500 flex w-7/10"
          :style="{
            color: item.fontColor,
            fontSize: (getRatios ? getRatios * item.fontSize : item.fontSize) + 'px',
          }"
        >
          <div class="max-w-4/6 overflow-ellipsis overflow-hidden whitespace-nowrap">{{
            item.deviceName
          }}</div>
          <span>-</span>
          <div>{{ item.attributeName || item.attribute || '温度' }}</div>
        </div>
        <span
          class="text-lg max-w-3/10"
          :style="{
            color: item.fontColor,
            fontSize: (getRatios ? getRatios * item.valueSize : item.valueSize) + 'px',
          }"
          >{{ item.value }} {{ item.unit }}</span
        >
      </div>
      <div class="">
        <Slider
          ref="sliderEl"
          :style="{ '--slider-color': item.backgroundColor }"
          :value="item.value"
          :disabled="true"
          :min="0"
          :max="item.maxNumber"
        />
      </div>
    </div>
  </main>
</template>
<style lang="less" scoped>
  :deep(.ant-progress-success-bg, .ant-progress-bg) {
    background: #2196f3 !important;
  }

  :deep(.ant-slider-handle) {
    all: unset;
  }

  :deep(.ant-slider-track) {
    background: var(--slider-color) !important;
    height: 8px;
  }

  :deep(.ant-slider-rail) {
    height: 8px;
  }

  :deep(.ant-slider-disabled) {
    cursor: auto !important;
  }
</style>