index.vue 5.77 KB
<script lang="ts" setup>
  import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { Slider, Spin } from 'ant-design-vue';
  import { computed, ref, unref } from 'vue';
  import { useComponentScale } from '../../../hook/useComponentScale';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
  import { useReceiveValue } from '../../../hook/useReceiveValue';
  import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
  import { useDataFetch } from '../../../hook/socket/useSocket';
  import PasswordModal from '../component/PasswordModal.vue';
  import { useModal } from '/@/components/Modal';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';
  import { useControlComand } from '../../../hook/useControlCommand';

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

  const sliderValue = ref<number>(33);
  const sliderElRef = ref<InstanceType<typeof Slider>>();

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

  const getDesign = computed(() => {
    const { option, persetOption } = props.config;
    const { componentInfo, attribute, deviceProfileId, attributeRename, commandType } = option;

    const {
      controlBarColor: persetControlBarColor,
      fonColor: persetFontColor,
      minNumber: persetMinNumber,
      maxNumber: persetMaxNumber,
      textColor: persetTextColor,
      valueSize: persetValueSize,
      fontSize: persetFontSize,
      password: persetPassword,
    } = persetOption || {};

    const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
    const {
      controlBarColor,
      password,
      fontColor,
      minNumber,
      maxNumber,
      textColor,
      valueSize,
      fontSize,
    } = componentInfo || {};
    return {
      attribute: attributeRename || tsl?.functionName || attribute,
      controlBarColor: controlBarColor ?? persetControlBarColor,
      fontColor: fontColor ?? persetFontColor,
      minNumber: minNumber ?? persetMinNumber,
      maxNumber: maxNumber ?? persetMaxNumber,
      commandType,
      textColor: textColor || persetTextColor,
      valueSize: valueSize || persetValueSize || 20,
      fontSize: fontSize || persetFontSize || 14,
      password: password || persetPassword,
    };
  });

  const sendValue = ref(0);
  const handleChange = async (value: number) => {
    sendValue.value = value;
  };

  const { loading, doControlSendCommand } = useControlComand();

  const handleAfterChange = () => {
    if (unref(getDesign).password) {
      openModal(true, { password: unref(getDesign).password });
      unref(sliderElRef)?.blur();
      return;
    }
    handleSendCommand();
  };

  const handleSendCommand = async () => {
    if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return;
    const value = unref(sendValue);
    const { option } = props.config || {};
    const result = await doControlSendCommand(option, value);
    unref(sliderElRef)?.blur();
    sliderValue.value = result ? value : unref(sliderValue);
  };

  const { getNumberValue } = useReceiveValue();
  const updateFn: DataFetchUpdateFn = (message, attribute) => {
    const { data = {} } = message;
    const [latest] = data[attribute] || [];
    const [name, value] = latest;
    if (!name && !value) return;
    sliderValue.value = getNumberValue(value);
  };

  useDataFetch(props, updateFn);
  const { getScale, getRatio } = useComponentScale(props);
  const [registerModal, { openModal }] = useModal();
</script>

<template>
  <main class="w-full h-full flex flex-col justify-center">
    <DeviceName :config="config" class="text-center" />
    <main :style="getScale">
      <Spin :spinning="loading" class="w-full h-full">
        <div class="flex flex-col" style="width: 80%">
          <span
            :style="{
              color: getDesign.fontColor,
              fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px',
            }"
            class="font-bold text-xl mt-3 text-center"
          >
            {{ sliderValue }}
          </span>
          <Slider
            ref="sliderElRef"
            :style="{
              '--slider-color': getDesign.controlBarColor,
              '--slider-handle': (getRatio ? getRatio * 14 : 14) + 'px',
              '--slider-height': (getRatio ? getRatio * 4 : 4) + 'px',
              '--slider-top': -(getRatio ? getRatio * 5 : 5) + 'px',
            }"
            class="no-drag"
            :value="sliderValue"
            :min="getDesign.minNumber"
            :max="getDesign.maxNumber"
            @change="handleChange"
            @afterChange="handleAfterChange"
          />

          <span
            :style="{
              color: getDesign.textColor,
              fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px',
            }"
            class="mt-3 truncate font-bold text-center"
          >
            {{ getDesign.attribute || '属性' }}
          </span>
        </div>
      </Spin>
    </main>
    <PasswordModal @register="registerModal" @success="handleSendCommand" />
  </main>
</template>
<style lang="less" scoped>
  :deep(.ant-slider-track) {
    background: var(--slider-color) !important;
    height: var(--slider-height) !important;
  }

  :deep(.ant-slider-handle) {
    height: var(--slider-handle) !important;
    width: var(--slider-handle) !important;
    margin-top: var(--slider-top) !important;
  }

  :deep(.ant-slider-step) {
    height: var(--slider-height) !important;
  }

  :deep(.ant-slider-rail) {
    height: var(--slider-height) !important;
  }

  :deep(.ant-spin-container) {
    display: flex !important;
    justify-content: center !important;
  }
</style>