useAlarmNotify.ts 2.94 KB
import { AlarmStatus, AlarmStatusMean } from '../config/detail.config';
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';

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

export function useAlarmNotify(params: UseAlarmNotifyParams = {}) {
  const {
    alarmNotifyStatus = AlarmStatus.ACTIVE_UN_ACK,
    interval = import.meta.env.VITE_ALARM_NOTIFY_POLLING_INTERVAL_TIME,
    color = 'orange',
  } = params;
  const alarmNotifyStatusMean = AlarmStatusMean[alarmNotifyStatus];

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

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

  let currentNotifyId: Nullable<string> = null;

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

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

        const key = `open-notify-${Date.now()}`;

        const severityMean = alarmLevel(severity);
        notification.open({
          message: '设备告警',
          duration: null,
          key,
          description: h('div', {}, [
            h('div', { style: { marginRight: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, '设备:'),
              h('span', {}, `[${deviceName}]`),
            ]),
            h('div', { style: { marginTop: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, '告警状态:'),
              h(Tag, { color }, () => `${alarmNotifyStatusMean}`),
            ]),
            h('div', { style: { marginTop: '5px' } }, [
              h('span', { style: { marginRight: '5px' } }, '告警级别:'),
              h(Tag, { color: '#f50' }, () => `${severityMean}`),
            ]),
          ]),
          icon: h(ExclamationCircleOutlined, { style: { color: '#faa22d' } }),
          onClose: () => (currentNotifyId = null),
          btn: h(
            Button,
            {
              type: 'primary',
              size: 'small',
              onClick: async () => {
                await handleMarkRead(id);
                notification.close(key);
              },
            },
            () => '标记已读'
          ),
        });
      }
    } catch (error) {}
  };

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

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

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