index.vue 7.07 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 { computed, watch } from 'vue';
  import { ref, onMounted, unref } from 'vue';
  import { useIntervalFn } from '@vueuse/core';
  import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime';
  import { useCustomDataFetch } from '../../../hook/socket/useSocket';
  import { ReceiveAlarmDataCmdsMessageType } from '../../../hook/socket/useSocket.type';
  import { useDataBoardContext } from '/@/views/visual/palette/hooks/useDataBoardContext';
  import { useAlarmContext } from '/@/views/visual/palette/hooks/useAlarmTime';
  import { getMessage } from '../config';
  import { useI18n } from '/@/hooks/web/useI18n';

  interface IStatus {
    text: string;
    color: string;
  }

  interface IAlarmStatusList {
    id: string;
    deviceName: string;
    showDeviceName: boolean;
    showTime: boolean;
    status: IStatus;
    time: number;
    fontSize?: number | any;
  }

  const { t } = useI18n();

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

  const isOpenClose = ref<boolean>(true);

  const { send } = useDataBoardContext();

  const currentCmdId = ref();

  const alarmLevel = (type: string): IStatus => {
    if (type === 'CRITICAL') {
      return { text: t('enum.alarmLevel.CRITICAL'), color: 'alarm_state_critical' };
    } else if (type === 'MAJOR') {
      return { text: t('enum.alarmLevel.MAJOR'), color: 'alarm_state_major' };
    } else if (type === 'MINOR') {
      return { text: t('enum.alarmLevel.MINOR'), color: 'alarm_state_minor' };
    } else if (type === 'WARNING') {
      return { text: t('enum.alarmLevel.WARNING'), color: 'alarm_state_warning' };
    } else {
      return { text: t('enum.alarmLevel.INDETERMINATE'), color: 'alarm_state_other' };
    }
  };

  const getDesign = computed(() => {
    const { persetOption = {}, option } = props.config;
    const { dataSource } = option;
    const {
      showDeviceName: presetShowDeviceName,
      showTime: persetShowTime,
      fontSize: persetFontSize,
    } = persetOption;

    return {
      dataSource: dataSource?.map((item) => {
        const { deviceId, deviceName, deviceRename, componentInfo } = item;
        return {
          id: deviceId,
          deviceName: deviceRename || deviceName,
          showDeviceName: componentInfo.showDeviceName ?? presetShowDeviceName,
          showTime: componentInfo.showTime ?? persetShowTime,
          fontSize: componentInfo.fontSize || persetFontSize,
        };
      }),
    };
  });

  const randomFn = () => {
    useIntervalFn(() => {
      isOpenClose.value = !unref(isOpenClose);
    }, 4000);
  };

  const alarmStatusList = ref<IAlarmStatusList[]>([
    {
      id: '1',
      deviceName: t('business.deviceText'),
      status: { text: t('enum.alarmLevel.CRITICAL'), color: 'alarm_state_major' },
      time: 1689574726,
      showDeviceName: true,
      showTime: true,
      fontSize: 14,
    },
  ]);

  const { alarmForm } = useAlarmContext();

  watch(
    () => alarmForm?.value,
    () => {
      if (props.config.option.mode == 'SELECT_PREVIEW') return;
      send?.(JSON.stringify(getMessage(unref(currentCmdId), unref(getDesign), unref(alarmForm))));
    },
    { immediate: false }
  );

  const transformMessage = (cmdId: number) => {
    if (props.config.option.mode == 'SELECT_PREVIEW') return;
    currentCmdId.value = cmdId;
    send?.(JSON.stringify(getMessage(cmdId, unref(getDesign), unref(alarmForm))));
  };

  const getReduce = (data) => {
    const list = data.reduce((acc, obj) => {
      const found = acc.find((item) => item.entityId.id == obj.entityId.id);
      if (!found) {
        acc.push(obj);
      }
      return acc;
    }, []);

    data.forEach((item) => {
      list?.forEach((item1) => {
        if (item.entityId.id == item1.entityId.id) {
          item1.time = Number(item1.createdTime > item.createdTime)
            ? item1.createdTime
            : item.createdTime;
        }
      });
    });

    return list;
  };

  const updateFn = (message: ReceiveAlarmDataCmdsMessageType) => {
    alarmStatusList.value = unref(getDesign).dataSource?.map((item) => {
      return {
        id: item.id,
        deviceName: item.deviceName,
        showDeviceName: item.showDeviceName,
        showTime: item.showTime,
        status: { text: '', color: '' },
        time: 0,
        fontSize: item.fontSize || 14,
      };
    }) as any;
    const { data, update } = message;
    const alarmList = data?.data || update;
    const uniData = getReduce(alarmList); //去重得到最新的事件对象

    // if (!data?.data.length) return;
    uniData.forEach((item) => {
      alarmStatusList.value?.forEach((item1) => {
        if (item.entityId.id == item1.id) {
          item1.status = alarmLevel(item.severity);
          item1.time = item.createdTime;
        }
      });
    });
  };

  onMounted(() => {
    !props.config.option.uuid && randomFn();
  });

  useCustomDataFetch(props, transformMessage, updateFn);

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

<template>
  <main :style="getScale" class="w-full h-full flex justify-center items-center">
    <div v-for="item in alarmStatusList" :key="item.id" class="flex flex-col items-center">
      <div class="flex justify-center items-center flex-col">
        <div
          class="text-gray-500 truncate"
          :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }"
          >{{
            item.status.text
              ? item.showDeviceName
                ? item.deviceName + '-'
                : ''
              : t('visual.board.noAlarm')
          }}{{ item.status.text }}</div
        >
        <div
          :class="item.status.color"
          :style="{
            height: (getRatio ? getRatio * 70 : 70) + 'px',
            width: (getRatio ? getRatio * 70 : 70) + 'px',
          }"
        ></div>
      </div>
      <UpdateTime v-show="item.showTime" :time="item.time" />
    </div>
  </main>
</template>
<style lang="less" scoped>
  .alarm_state_critical {
    background: #cf1322;
    box-shadow: 0 -1px 7px 1px rgba(0, 0, 0, 0.2), inset 0 -1px 9px #304701, 0 2px 12px #cf1322;
    border-radius: 50%;
    margin: 10px 0;
  }

  .alarm_state_major {
    background: #ff6e03;
    box-shadow: 0 -1px 7px 1px rgba(0, 0, 0, 0.2), inset 0 -1px 9px #304701, 0 2px 12px #ff6e03;
    border-radius: 50%;
    margin: 10px 0;
  }

  .alarm_state_minor {
    background: #ff0;
    box-shadow: 0 -1px 7px 1px rgba(0, 0, 0, 0.2), inset 0 -1px 9px #304701, 0 2px 12px #ff0;
    border-radius: 50%;
    margin: 10px 0;
  }

  .alarm_state_warning {
    background: #edf760;
    box-shadow: 0 -1px 7px 1px rgba(0, 0, 0, 0.2), inset 0 -1px 9px #304701, 0 2px 12px #edf760;
    border-radius: 50%;
    margin: 10px 0;
  }

  .alarm_state_other {
    background: #d3adf7;
    box-shadow: 0 -1px 7px 1px rgba(0, 0, 0, 0.2), inset 0 -1px 9px #304701, 0 2px 12px #d3adf7;
    border-radius: 50%;
    margin: 10px 0;
  }
</style>