index.vue 5.22 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { SvgIcon } from '/@/components/Icon';
  import { Switch } from 'ant-design-vue';
  import { computed, ref } from 'vue';
  import { useComponentScale } from '../../../hook/useComponentScale';
  import { useSendCommand } from '../../../hook/useSendCommand';
  import { unref } from 'vue';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useMultipleDataFetch } from '../../../hook/socket/useSocket';
  import { useReceiveMessage } from '../../../hook/useReceiveMessage';
  import { useReceiveValue } from '../../../hook/useReceiveValue';
  import { DataSource } from '/@/views/visual/palette/types';
  import { getSendValues, CommandTypeEnumLIst } from '../config';

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

  const svgList = ref<any>([
    {
      value: 26.2,
      deviceName: '光照设备',
      attributeName: '光照',
      icon: 'zongfushe',
      unit: 'kw',
      iconColor: '#367BFF',
      fontColor: '#357CFB',
      checked: false,
      id: 0,
    },
    {
      value: 53.7,
      deviceName: '风机设备',
      attributeName: '风机',
      icon: 'guangzhaoqiangdu',
      unit: '℃',
      iconColor: '#FFA000',
      fontColor: '#FFA000',
      checked: true,
      id: 1,
    },
  ]);

  const getDesign = computed(() => {
    const { persetOption = {}, option } = props.config;
    const { dataSource = [] } = option || {};
    const {
      unit: persetUnit,
      fontColor: persetFontColor,
      icon: persetIcon,
      iconColor: persetIconColor,
      fontSize: persetFontSize,
    } = persetOption || {};
    return {
      dataSource: dataSource.map((item) => {
        const { fontColor, icon, iconColor, unit, showDeviceName, fontSize } = item.componentInfo;
        const {
          attribute,
          attributeRename,
          attributeName,
          deviceId,
          deviceName,
          deviceRename,
          commandType,
          extensionDesc,
          codeType,
          deviceCode,
          customCommand,
        } = item;
        return {
          unit: unit ?? persetUnit,
          fontColor: fontColor ?? persetFontColor,
          icon: icon ?? persetIcon,
          iconColor: iconColor ?? persetIconColor,
          attribute: attribute,
          attributeName: attributeRename || attributeName,
          showDeviceName,
          deviceName: deviceRename || deviceName,
          id: deviceId,
          extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
          commandType,
          codeType,
          deviceCode,
          customCommand,
          fontSize: fontSize || persetFontSize || 14,
        };
      }),
    };
  });

  const { loading, sendCommand } = useSendCommand();
  const handleChange = async (index: number, checked: Boolean) => {
    const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } =
      props.config.option;
    const data = {
      ...dataSource?.[index],
      heightPx,
      itemHeightRatio,
      itemWidthRatio,
      mode,
      widthPx,
    } as DataSource;
    const { values, isModbusCommand, sendValue } =
      (await getSendValues(data, unref(getDesign).dataSource[index], checked)) || {};

    const flag = await sendCommand(values, isModbusCommand ? sendValue : checked, isModbusCommand);
    if (!flag) controlList.value[index].checked = !checked;
  };

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

  const controlList = ref(
    props.config.option.dataSource
      ? unref(getDesign).dataSource.map((item) => {
          return { ...item, checked: false };
        })
      : svgList
  );

  const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => {
    forEachGroupMessage(message, deviceId, attribute, (attribute, value) => {
      controlList.value.forEach((item) => {
        if (item.id === deviceId && item.attribute === attribute && value) {
          item.checked = Boolean(getNumberValue(value));
        }
      });
    });
  };

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

<template>
  <main class="w-full h-full flex flex-col justify-evenly items-center">
    <DeviceName :config="config" />
    <div
      style="width: 86%"
      v-for="(item, index) in controlList"
      :key="item.id"
      class="flex justify-between items-center"
    >
      <div class="flex items-center">
        <SvgIcon
          :name="item.icon!"
          prefix="iconfont"
          :size="getRatio ? 25 * getRatio : 25"
          :style="{ color: item.iconColor }"
        />

        <div class="text-gray-500 truncate ml-6" :style="{ fontSize: item.fontSize + 'px' }">{{
          `${item.deviceName} - ${
            item.commandType ? CommandTypeEnumLIst[item.commandType].name : item.attributeName
          }`
        }}</div>
      </div>

      <Switch
        v-model:checked="item.checked"
        :loading="loading"
        @change="handleChange(index, item.checked)"
      />
    </div>
  </main>
</template>