election-egg 自定义通知弹窗兼容win7和win10

实现效果

多个相同类型消息(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;  

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值