useAlarmNotify.ts 4.61 KB
import { clearOrAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager';
import { notification, Button, Tag } from 'ant-design-vue';
import { h, onMounted, onUnmounted } from 'vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { alarmLevel } from '/@/views/device/list/config/detail.config';
import { RoleEnum } from '/@/enums/roleEnum';
import { usePermission } from '/@/hooks/web/usePermission';
import { useUserStore } from '/@/store/modules/user';
import { useGlobSetting } from '/@/hooks/setting';
import { AlarmStatus } from '/@/enums/alarmEnum';
import { useI18n } from '/@/hooks/web/useI18n';

interface UseAlarmNotifyParams {
  alarmNotifyStatus?: AlarmStatus;
  interval?: number;
  color?: string;
  duration?: number;
}

export enum AlarmPermissionKey {
  GLOBAL_NOTIFY = 'api:alarm:global:notify',
}

export function useAlarmNotify(params: UseAlarmNotifyParams = {}) {
  const { alarmNotifyDuration, alarmPollingInterval } = useGlobSetting();
  const {
    alarmNotifyStatus = AlarmStatus.ACTIVE_UN_ACK,
    interval = Number(alarmPollingInterval) || 60000,
    duration = Number(alarmNotifyDuration) || 5,
    color = 'orange',
  } = params;
  const { t } = useI18n();
  const alarmNotifyStatusMean = t(`enum.alarmStaus.${alarmNotifyStatus}`);

  const handleMarkRead = async (id: string) => {
    try {
      await clearOrAckAlarm(id, false);
    } catch (error) {}
  };

  let timeout: Nullable<NodeJS.Timer> = null;

  const { hasPermission } = usePermission();
  const getRoleHasNotifyFlag = () => {
    const hasPermissionRole = [RoleEnum.CUSTOMER_USER, RoleEnum.TENANT_ADMIN];
    const userInfo = useUserStore().getUserInfo;
    const userRoles = userInfo.roles || [];

    let roleHasPermission = false;
    for (const item of userRoles) {
      const flag = hasPermissionRole.find((each) => item === each);
      if (flag) {
        roleHasPermission = true;
        break;
      }
    }

    return hasPermission(AlarmPermissionKey.GLOBAL_NOTIFY) && roleHasPermission;
  };

  const getAlarmLog = async () => {
    try {
      if (!getRoleHasNotifyFlag()) {
        clearTimeout();
        return;
      }
      const { items = [] } =
        (await getDeviceAlarm({ status: alarmNotifyStatus, page: 1, pageSize: 10 })) || {};

      if (items.length) {
        const first = items.at(0)!;
        const { deviceAlias, deviceName, id, severity, type } = first;

        let key: Nullable<string> = `open-notify-${id}`;

        const severityMean = alarmLevel(severity);

        notification.open({
          message: t('visual.board.alarmComponent.deviceAlarm'),
          duration: Number(duration),
          key,
          description: h('div', {}, [
            h('div', { style: { marginRight: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, `${t('business.deviceText')}:`),
              h('span', {}, `[${deviceAlias ?? deviceName}]`),
            ]),
            h('div', { style: { marginRight: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, `${t('common.alarmScenarioText')}:`),
              h('span', {}, `[${type}]`),
            ]),
            h('div', { style: { marginTop: '5px' } }, [
              h(
                'span',
                { style: { marginRight: '5px' } },
                `${t('monitor.alarm.log.table.status')}:`
              ),
              h(Tag, { color }, () => `${alarmNotifyStatusMean}`),
            ]),
            h('div', { style: { marginTop: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, `${t('common.alarmLevel1Text')}:`),
              h(Tag, { color: '#f50' }, () => `${severityMean}`),
            ]),
          ]),
          icon: h(ExclamationCircleOutlined, { style: { color: '#faa22d' } }),
          onClose: () => {
            key = null;
          },
          btn: h(
            Button,
            {
              type: 'primary',
              size: 'small',
              onClick: async () => {
                await handleMarkRead(id);
                notification.close(key!);
                key = null;
              },
            },
            () => t('common.markRead')
          ),
        });
      }
    } catch (error) {}
  };

  const polling = () => {
    timeout = setInterval(() => {
      getAlarmLog();
    }, interval);
  };

  const clearTimeout = () => {
    clearInterval(timeout as NodeJS.Timer);
    timeout = null;
  };

  onMounted(() => {
    if (getRoleHasNotifyFlag()) polling();
  });

  document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
      clearTimeout();
    } else {
      polling();
    }
  });

  onUnmounted(() => {
    clearTimeout();
  });
}