2023-04-03 18:00:41 +08:00

103 lines
3.7 KiB
TypeScript

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;
}
}