index.vue 5.06 KB
<script lang="ts" setup>
  import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { DEFAULT_VALUE, option, SwitchItemType } from './config';
  import { SvgIcon } from '/@/components/Icon';
  import { Switch } from 'ant-design-vue';
  import { computed, ref, toRaw } from 'vue';
  import { useComponentScale } from '../../../hook/useComponentScale';
  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 { useModal } from '/@/components/Modal';
  import PasswordModal from '../component/PasswordModal.vue';
  import {
    DoCommandDeliverDataSourceType,
    useCommandDelivery,
  } from '../../../hook/useCommandDelivery';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';

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

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

  const getDesign = computed(() => {
    const { persetOption = {}, option } = props.config;
    const { dataSource = [] } = option || {};
    const {
      unit: persetUnit,
      fontColor: persetFontColor,
      icon: persetIcon,
      iconColor: persetIconColor,
      fontSize: persetFontSize,
      password: persetPassword,
    } = persetOption || {};
    return {
      dataSource: dataSource.map((item) => {
        const { fontColor, icon, iconColor, unit, showDeviceName, password, fontSize } =
          item.componentInfo;
        const {
          attribute,
          attributeRename,
          deviceId,
          deviceName,
          deviceRename,
          commandType,
          deviceProfileId,
          openCommand,
          closeCommand,
          openService,
          closeService,
        } = item;

        const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);

        return {
          unit: unit ?? persetUnit,
          deviceProfileId,
          deviceId,
          fontColor: fontColor ?? persetFontColor,
          icon: icon ?? persetIcon,
          iconColor: iconColor ?? persetIconColor,
          attribute: attribute,
          attributeName: attributeRename || tsl?.functionName || attribute,
          showDeviceName,
          deviceName: deviceRename || deviceName,
          id: deviceId,
          commandType,
          fontSize: fontSize || persetFontSize || 14,
          password: password || persetPassword,
          checked: false,
          openCommand,
          closeCommand,
          openService,
          closeService,
        } as SwitchItemType;
      }),
    };
  });

  const handleChange = async (item) => {
    if (item.password) {
      openModal(true, { password: item.password });
      return;
    }
    handleSendCommand(item);
  };

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

  const controlList = ref(
    props.config.option.dataSource ? unref(getDesign).dataSource : DEFAULT_VALUE
  );

  const { loading, doCommandDeliver } = useCommandDelivery();
  const handleSendCommand = async (modalData: SwitchItemType) => {
    if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return;
    await doCommandDeliver(
      toRaw(unref(modalData)) as DoCommandDeliverDataSourceType,
      Number(unref(modalData).checked)
    );
  };

  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);
  const [registerModal, { openModal }] = useModal();
</script>

<template>
  <main class="w-full h-full flex flex-col justify-evenly items-center">
    <DeviceName :config="config" />
    <div
      v-for="item in controlList"
      :key="item.id"
      class="flex justify-between items-center w-full px-4"
    >
      <SvgIcon
        :name="item.icon!"
        prefix="iconfont"
        :size="getRatio ? 30 * getRatio : 30"
        :style="{ color: item.iconColor }"
      />
      <div
        class="text-gray-500 truncate mx-2"
        :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }"
      >
        {{ `${item.deviceName} - ${item.attributeName}` }}
      </div>
      <Switch
        v-model:checked="item.checked"
        :loading="loading"
        @change="handleChange(item)"
        :style="{ transform: `scale(${getRatio || 1})` }"
      />
    </div>
    <PasswordModal @register="registerModal" @success="handleSendCommand" />
  </main>
</template>