import IWHNotify from "../../interface/IWHNotify"; import NotificationUtils from "./NotificationUtils"; import MathUtils from "./MathUtils"; import NOTIFY_HTML from "../../../static/html/notify.html"; import WindowActiveState from "../action/WindowActiveState"; import { Container } from "../../container/Container"; import Logger from "../Logger"; import ClassName from "../../container/ClassName"; @ClassName('Alert') export default class Alert { private static container: HTMLElement = null; private static totalCounter: number = 0; private notify: MyHTMLElement = null; private intervalID = -1; private readonly callback: Function; public constructor( msg: string, options: IWHNotify = {}, private readonly mathUtils: MathUtils = Container.factory(MathUtils), private readonly windowActiveState: WindowActiveState = Container.factory(WindowActiveState), private readonly notificationUtils: NotificationUtils = Container.factory(NotificationUtils), private readonly logger: Logger = Container.factory(Logger), ) { let { timeout, callback, sysNotify, force } = options; // 后台窗口、iframe内判断 if (!this.windowActiveState.get() || (self !== top)) { if (!force) { this.logger.warn('后台通知已被屏蔽'); return null; } else { this.logger.info('强制后台通知'); } } // 通知的容器 this.logger.info('通知的容器', Alert.container); if (!Alert.container || !document.contains(Alert.container)) Alert.initContainer(); this.callback = callback || (() => null); Alert.create(this, msg, timeout || 3); Alert.totalCounter++; this.logger.info('创建新通知:', this, msg); if (sysNotify) this.notificationUtils.push(msg, options); } private static create(that: Alert, msg, timeout): void { // 通知的唯一id const uid = '' + that.mathUtils.getRandomInt(1000, 9999); // 每条通知 const element: MyHTMLElement = document.createElement('div'); element.id = `wh-notify-${ uid }`; element.classList.add('wh-notify-item'); element.innerHTML = NOTIFY_HTML.replace('{{}}', msg); this.container.append(element); // 进度条node const progressBar: HTMLElement = element.querySelector('.wh-notify-bar'); // 是否hover let mouse_enter = false; element.addEventListener('mouseenter', () => mouse_enter = true, true); element.addEventListener('mouseleave', () => mouse_enter = false); // 通知进度条 TODO 改进 let progressCount = 101; // 计时器 that.intervalID = window.setInterval(() => { if (mouse_enter) { progressCount = 101; progressBar.style.width = '100%'; return; } progressCount--; progressBar.style.width = `${ progressCount }%`; if (progressCount === 0) { that.close(); } }, timeout * 1000 / 100) as unknown as number; element.querySelector('.wh-notify-close').addEventListener('click', () => that.close()); that.notify = element; } private static initContainer() { this.container = document.createElement('div'); this.container.id = 'wh-notify'; document.body.append(this.container); } public close() { this.notify.remove(); this.notify = null; this.callback(); window.clearInterval(this.intervalID); Alert.totalCounter--; } public getElement() { return this.notify; } }