实现效果
多个相同类型消息(a,a-1)只会显示一个弹窗,然后叠加;不同类型消息(abc)显示多个弹窗,上下叠加,点击不同消息跳转不同页面
代码
notifi.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body onclick="clickBody()">
<image class="image_close" src="../../../public/images/ic_close.png" mode="scaleToFill" onclick="clickClose(event)" />
<div class="content">
<h3 id="title"></h3>
<h4 id="subtitle" style="display: none;"></h4>
<p id="content"></p>
</div>
</body>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
h1 {
font-size: 24px;
margin: 0 0 5px;
}
p {
font-size: 16px;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.image_close {
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
border-radius: 50%;
cursor: pointer;
}
</style>
<script>
const { ipcRenderer } = window.require('electron');
// 解析查询字符串为对象的函数
function getQueryParams() {
const queryParams = {};
// location.search 会返回 URL 的查询参数部分(以 '?' 开头)
const queryStr = window.location.search.substring(1);
const params = queryStr.split('&');
for (let i = 0; i < params.length; i++) {
const pair = params[i].split('=');
// decodeURIComponent 用于处理编码后的组件,确保特殊字符被正确解析
const key = decodeURIComponent(pair[0]);
const value = decodeURIComponent(pair[1] || '');
if (key) queryParams[key] = value;
}
return queryParams;
}
// 使用上面定义的函数来获取查询参数
const params = this.getQueryParams();
console.log('params', params);
// 获取要替换内容的元素
var titleElement = document.getElementById('title');
var subtitleElement = document.getElementById('subtitle');
var contentElement = document.getElementById('content');
// 替换内容
titleElement.innerHTML = params.title;
subtitleElement.innerHTML = params.subtitle;
contentElement.innerHTML = params.content;
//按钮关闭
function clickClose(event) {
// 阻止事件冒泡
event.stopPropagation();
var message = {};
message.type = 'close';
//弹窗id
message.id = params.id;
message.data = {};
ipcRenderer.send('html_message', message);
}
//点击内容
function clickBody() {
var message = {};
message.type = 'clickBody';
//弹窗id
message.id = params.id;
message.data = {};
ipcRenderer.send('html_message', message);
}
//声音
window.onload = function () {
if (params.isPlay == 'true') {
new Audio('./voice_noti.wav').play();
}
}
</script>
</html>
os.js
'use strict';
const { Service } = require('ee-core');
const { BrowserView, Notification } = require('electron');
const CoreWindow = require('ee-core/electron/window');
const Services = require('ee-core/services');
const { BrowserWindow, screen } = require('electron');
const path = require('path');
const url = require('url');
const { ipcMain } = require('electron');
/**
* os(service层为单例)
* @class
*/
class OsService extends Service {
constructor(ctx) {
super(ctx);
this.myBrowserView = null;
this.myNotification = null;
/**
* 数据结构
* { id: notification.id, notification: notification, data: data }
*/
this.notifications = [];
}
/**
* createBrowserView
*/
createBrowserView(contentUrl) {
// electron 实验性功能,慎用
const win = CoreWindow.getMainWindow();
this.myBrowserView = new BrowserView();
win.setBrowserView(this.myBrowserView);
this.myBrowserView.setBounds({
x: 300,
y: 170,
width: 650,
height: 400
});
this.myBrowserView.webContents.loadURL(contentUrl);
}
/**
* removeBrowserView
*/
removeBrowserView() {
this.myBrowserView.webContents.destroy();
}
/**
* createNotification
*/
createNotification(options, event) {
const channel = 'controller.os.sendNotification';
this.myNotification = new Notification(options);
if (options.clickEvent) {
this.myNotification.on('click', (e) => {
let data = {
type: 'click',
msg: '您点击了通知消息'
}
event.reply(`${channel}`, data)
});
}
if (options.closeEvent) {
this.myNotification.on('close', (e) => {
let data = {
type: 'close',
msg: '您关闭了通知消息'
}
event.reply(`${channel}`, data)
});
}
this.myNotification.show();
}
/**
* 自定义通知
*/
createSDNotification(options, event) {
options = JSON.parse(options);
this.statusdbOperation({
action: 'get',
key: 'soundStatus'
}).then(res => {
var isSound = true
if (res.result.length > 0) {
isSound = res.result[0].status
}
const channel = 'controller.os.sendSDNotification';
//移除旧的通知
this.closeNotificationBySysCategoryCode(options.sysCategoryCode)
const sdNotification = this.getCBrowserWindow(options, isSound);
sdNotification.showInactive();
// sdNotification.webContents.openDevTools();
this.addNotification(sdNotification, options);
//
/**
* 点击监听-数据结构
*msg.type=close or clickBody;
*msg.id=params.id;
*msg.data={};
*/
ipcMain.on('html_message', (ev, msg) => {
switch (msg.type) {
case 'close':
//移除
this.removeNotification(msg.id);
break;
case 'clickBody':
var showData = this.findNotifications(msg.id)
if (showData != null) {
let data = {
type: 'click',
msg: showData.data.jumpUrl,
}
event.reply(`${channel}`, data)
//移除
this.removeNotification(showData.id)
showData.notification.close();
}
break;
default:
break;
}
});
})
}
//移除旧的通知
closeNotificationBySysCategoryCode(sysCategoryCode) {
var notifData = this.findNotificationsBySysCategoryCode(sysCategoryCode)
if (notifData != null && notifData != undefined) {
notifData.notification.close()
//移除
this.removeNotification(notifData.id)
}
}
//创建弹窗
getCBrowserWindow(options, isPlay) {
const title = options.sysName + '-' + options.sysMsgTypeTitle
const subtitle = options.sysName + '-' + options.sysMsgTypeTitle
const content = options.msgTxt
//设置唯一标识
var win = new BrowserWindow({
width: 400,
height: 140,
show: false,
frame: false, // 无边框
skipTaskbar: true, // 使窗口不显示在任务栏中
movable: false, // 禁止窗口被用户移动
resizable: false, // 禁止窗口手动调整窗口大小
fullscreenable: false, // 禁止窗口可以进入全屏状态
alwaysOnTop: true, // 窗口是否永远在别的窗口的上面
webPreferences: {
contextIsolation: false, // 推荐启用
nodeIntegration: true, // 推荐禁用
},
});
// 创建带有查询参数的 URL
let notifiUrl = url.format({
pathname: path.join(__dirname, 'notifi/notifi.html'),
protocol: 'file:',
slashes: true,
query: {
isPlay: isPlay,
id: win.id,
title: title,
subtitle: subtitle,
content: content
}
});
win.loadURL(notifiUrl);
const sizeObj = screen.getPrimaryDisplay().workAreaSize;
const { width, height } = sizeObj;
const [cwidth, cheight] = win.getContentSize();
const left = parseInt(width - (cwidth || 0) - 10);
const top = parseInt(height - (cheight || 0) - 10);
win.setPosition(left, top);
return win;
}
async statusdbOperation(args) {
const { action, info, key, state, data_dir } = args;
const data = {
action,
result: null,
all_list: []
};
console.log('---systemjsondbOperation---', args)
const jsondbName = "database.statusdb"
switch (action) {
case 'add':
data.result = await Services.get(jsondbName).addData(info);
break;
case 'delete':
data.result = await Services.get(jsondbName).deleteDataByKey(key);
break;
case 'deleteAll':
data.result = await Services.get(jsondbName).deleteDataAll();
break;
case 'update':
data.result = await Services.get(jsondbName).updateStateByKey(key, state);
break;
case 'get':
data.result = await Services.get(jsondbName).getDataByKey(key);
break;
case 'getDataDir':
data.result = await Services.get(jsondbName).getDataDir();
break;
case 'setDataDir':
data.result = await Services.get(jsondbName).setCustomDataDir(data_dir);
break;
}
data.all_list = await Services.get(jsondbName).getAllData();
return data;
}
/**
* 添加通知,移除相同通知
* @param {*} notification
*/
addNotification(notification, data) {
//移除相同的通知
this.removeNotification(notification.id)
//添加通知到数组
this.notifications.push({ id: notification.id, notification: notification, data: data });
}
/**
* 删除通知
* @param {} id
*/
removeNotification(id) {
const index = this.notifications.findIndex(n => n.id == id);
if (index !== -1) {
const notification = this.notifications[index].notification;
if (process.platform != 'darwin') {
notification.close();
}
this.notifications.splice(index, 1);
}
}
/**
* 查找数组
* @param {} id
* @returns
*/
findNotifications(id) {
const index = this.notifications.findIndex(n => n.id == id);
if (index !== -1) {
return this.notifications[index];
}
return null;
}
/**
* 查找数组
* @param {} sysCategoryCode
* @returns
*/
findNotificationsBySysCategoryCode(sysCategoryCode) {
const index = this.notifications.findIndex(n => n.data.sysCategoryCode == sysCategoryCode);
if (index !== -1) {
return this.notifications[index];
}
return null;
}
}
OsService.toString = () => '[class OsService]';
module.exports = OsService;