建设了网站怎么管理系统销售平台
JS通知总结下来有4种方法,分别是声音提醒、通知提醒、标题变化、icon变化; 比较常见的是标题变化和icon变化;
方式1:声音通知
人性化提示音:xxx平台收到音视频呼叫,请接听; 您有收到一条新的消息;
- 优点:通知即时,无干扰和历史残留;
- 缺点:
- 浏览器要求必须和页面发生一次交互,才能播放; 静音后将无法收到提醒;
- 浏览器静音/系统静音将无法听到播放声音;
备注: 如果手动开启浏览器声音播放权限;将不会有必须与页面发生交互的错误;
方式2:Notification通知(强提醒)
- 优点:强提醒,用户隐藏tab也会收到;
- 缺点
- win系统5-6秒左右会自动隐藏;
- 无法指定常驻时间,设置自定义样式;
- 如果用户拒绝过,将无法再次弹出授权通知,需要用户手动去设置中开启;
- 无法自定义按钮,只能触发点击事件;
- 如果用户授权, 但是系统设置里面关闭了浏览器通知,将无法监测到;
- 大部分用户拒绝后,可能自己找不到设置中哪里开启;
- 由于刷新或异常关闭,会导致老旧的通知存在任务栏;无法释放;
备注:可以手动开启浏览器通知权限; 并设置系统允许浏览器通知
相关代码
/*Notification.requestPermission; - 'denied': 用户拒绝显示通知- 'granted': 用户接受显示通知- 'default': 用户选择是未知的*/function notifyMe() {if (!("Notification" in window)) {// 检查浏览器是否支持通知alert("当前浏览器不支持桌面通知");} else if (Notification.permission === "granted") {// 检查是否已授予通知权限;如果是的话,创建一个通知const notification = new Notification("你好!");// …} else if (Notification.permission !== "denied") {// 我们需要征求用户的许可Notification.requestPermission().then((permission) => {// 如果用户接受,我们就创建一个通知if (permission === "granted") {const notification = new Notification("你好!");// 或者 const notification = new Notification("通知标题:", {body: '通知内容', icon: '',})}});}
}// 判断当前浏览器是否支持通知
if (!("Notification" in window)) {console.log("此浏览器不支持通知API");
}
// 如果用户已经禁用了通知,提示用户手动开启
if (Notification.permission === "denied") {alert("您已阻止通知,请在浏览器设置中开启通知权限以获得最佳体验。");
}
// 绑定事件
notification.onclick = function () {window.focus(); // 点击通知时将焦点切换回窗口notification.close(); // 关闭通知
};
// 点击通知时打开指定页面
notification.onclick = function () {window.open("https://baidu.com");
};
方式3:修改Favicon(弱提醒)
- 多个tab也可以看到变化
- 缺点
- 如果最小化将无法看到效果;
- 使用定时器刷新,影响性能;
相关代码
/*也可以直接替换icon<link rel="icon" href="/favicon.ico"/>
*/
function changeFavicon(url) {const link = document.querySelector("link[rel*='icon']") || document.createElement("link");link.type = "image/x-icon";link.rel = "shortcut icon";link.href = url;document.getElementsByTagName("head")[0].appendChild(link);
}// 动态生成带数字的Favicon
// 可以生成一个红底里面放数字的图标
function drawFaviconWithNumber(number) {const canvas = document.createElement("canvas");canvas.width = 16;canvas.height = 16;const context = canvas.getContext("2d");context.fillStyle = "red";context.beginPath();context.arc(8, 8, 8, 0, 2 * Math.PI);context.fill();context.fillStyle = "white";context.font = "10px Arial";context.textAlign = "center";context.textBaseline = "middle";context.fillText(number, 8, 8);const url = canvas.toDataURL("image/png");changeFavicon(url);
}
标题闪烁提示(弱提醒)
- 缺点
- 如果用户切到别的tab,任务栏看不到名称变化效果;
- 当有多个tab时候提示不明显;
- 使用定时器刷新,影响性能;
let title = '有新消息'
setInterval(() => {if (title === '有新消息'){document.title = 'xxx平台'title = 'xxx平台'} else {document.title = '有新消息'title = '有新消息'}
}, 1000)
辅助方法
// 监听页面可见性变化
document.addEventListener("visibilitychange", () => {/*- 如果页面处于前台且可见,document.hidden 的值为 false- 如果页面处于后台或被隐藏,document.hidden 的值为 true*/if (document.hidden) {console.log("页面已隐藏,可以弹出通知");} else {console.log("页面已激活,不弹出通知");}
});
// 监听页面关闭或刷新是清空当前弹窗
window.addEventListener('beforeunload', (event) => {
});
封装方法
import notifIcon from '@/assets/icon.png';
// 页面默认icon <link rel="icon" href="/favicon.ico"/>
import faviconIco from '@/assets/favicon.ico';
// 新消息icon <link rel="icon" href="/inCallIcon.ico"/>
import inCallIcon from '@/assets/inCallIcon.svg';import { Modal } from 'antd';
const { warning } = Modal;class MediaNotic {pageIsHide: boolean;openPageHideNotUpdate: boolean;toggleTime: any;notiPerWarning: any;notification: any;constructor () {// 当前页面是是否显示: true_隐藏 false_页面激活;this.pageIsHide = false;// 是否开启页面不可见才弹出通知this.openPageHideNotUpdate = false;// 切换定时器this.toggleTime = null;// 通知权限弹窗this.notiPerWarning = null;// 当前通知系统弹窗this.notification = null;this.init();}init() {this.getCurentDocumentHide();this.bindDocumentVisiChange();this.firstLoadingNotiPermission();}/*是否设置开启页面隐藏才触发通知*/setOpenPageHideNotUpdate(open: boolean) {this.openPageHideNotUpdate = open;}open() {// 如果开启页面隐藏才弹窗if (this.openPageHideNotUpdate) {if (!this.pageIsHide) { this.close();return;};}this.toggleTime = setTimeout(() => {this.toggleTime = null;const title = document.title;if (title === '有新来电'){this.resetTitleFavicon();} else {document.title = '有新来电';// this.drawFaviconWithNumber(1);this.changeFavicon(inCallIcon);}this.open();}, 1000);}close() {if (this.toggleTime) {clearTimeout(this.toggleTime);this.toggleTime = null;};this.resetTitleFavicon();if (this.notification) {this.notification.close();this.notification = null;};}resetTitleFavicon() {document.title = '三级调度平台';this.changeFavicon(faviconIco);}changeFavicon(url: string) {const link: any = document.querySelector("link[rel*='icon']") || document.createElement("link");link.type = "image/x-icon";link.rel = "shortcut icon";link.href = url;document.getElementsByTagName("head")[0].appendChild(link);}/* 获取当前页面是否可见 */getCurentDocumentHide() {this.pageIsHide = document.hidden;}/* 监听页面可见性变化 */bindDocumentVisiChange() {/*- 如果页面处于前台且可见,document.hidden 的值为 false- 如果页面处于后台或被隐藏,document.hidden 的值为 true*/document.addEventListener("visibilitychange", () => {this.pageIsHide = document.hidden;// 如果开启页面隐藏才弹窗if (this.openPageHideNotUpdate && !this.pageIsHide) {this.close();}});window.addEventListener('beforeunload', (event) => {this.close();});}// 动态生成带数字的FavicondrawFaviconWithNumber(number: number) {const canvas = document.createElement("canvas");canvas.width = 16;canvas.height = 16;const context: any = canvas.getContext("2d");context.fillStyle = "red";context.beginPath();context.arc(8, 8, 8, 0, 2 * Math.PI);context.fill();context.fillStyle = "white";context.font = "10px Arial";context.textAlign = "center";context.textBaseline = "middle";// context.fillText(number, 8, 8);const url = canvas.toDataURL("image/png");this.changeFavicon(url);}/* 通知权限- 如果用户没有赋予就去申请一下;- 如果用户判断已经拒绝, 就简单提示一下;*/firstLoadingNotiPermission() {if (!("Notification" in window)) {return;}const notPerm = Notification.permission;// 表示用户还没有指定通知权限if (notPerm === 'default') {// 主动获取通知权限Notification.requestPermission();return;} else if (notPerm === 'denied') {// alert 会阻塞页面加载,不建议使用// alert('您已阻止通知, 请在浏览器设置中开启通知权限以获得最佳体验!');if (this.notiPerWarning) {this.notiPerWarning.destroy();this.notiPerWarning = null;};this.notiPerWarning = warning({icon: '',title: '提示',content: '您已选择关闭通知权限,将无法收到来电邀请通知, 请在设置中开启通知权限以获得最佳体验!',okText: '确定',onCancel: () => {this.notiPerWarning = null;}});// // 超时关闭// setTimeout(() => {// if (this.notiPerWarning) {// this.notiPerWarning.destroy();// this.notiPerWarning = null;// }// }, 15 * 1000);return;}}openNoti() {// 如果开启页面隐藏才弹窗if (this.openPageHideNotUpdate) {if (!this.pageIsHide) { this.close();return;};}if (!("Notification" in window)) {return;}if (this.notification) {this.notification.close();this.notification = null;};Notification.requestPermission().then((permission) => {// 如果用户接受,我们就创建一个通知if (permission === "granted") {if (this.notification) {this.notification.close();this.notification = null;};this.notification = new Notification("来电提醒", {body: 'xxx平台收到音视频邀请, 请前往接听!', icon: notifIcon,});// 绑定事件this.notification.onclick = function () {window.focus(); // 点击通知时将焦点切换回窗口this.notification.close(); // 关闭通知};// 系统大概5秒后会自己消失setTimeout(() => {if (this.notification) {this.notification.close();this.notification = null;};}, 30 * 1000);}});}
}
const InCallMediaNotic = new MediaNotic();
export default InCallMediaNotic;