electron桌面应用webSoket实时弹框提示实现

一、实现效果:网页端或者移动端进行了审核操作,在电脑右下角提示用户查看。

        1、当有弹框提示的情况时,会弹出如下提示,点击查看自动跳转到当前地址,点击关闭则关闭当前提示窗口;

        2、当有两条及其以上的消息要审核时,弹框的内容会变成如下展示:

二、实现思路: 

1、在主进程main.js中创建弹框,并确定弹框的位置;

2、编写弹框内容和样式;

3、在登录成功后使用webSoket实时监听消息;

4、主进程收到消息后触发提示弹框展示;

三、代码实现:

1、主进程main.js中:

// main.js

// 监听
ipcMain.on('remindWindow:close', () => {
  remindWindow.close()
})

// 判断在弹框关闭前一共收到几次消息
let num = 1
ipcMain.on('open-remind', (event, task, twrUrl) => {
  if (remindWindow) {
    num++
    remindWindow.webContents.send('show-remind', task, twrUrl, num)
  } else {
    num = 1
    createRemindWindow(task, twrUrl)
  }
})

// 创建提示弹出窗
const iconPath = path.join(__dirname, './src/img/icon.png')
function createRemindWindow(task, twrUrl) {
  if (remindWindow) remindWindow.close()
  remindWindow = new BrowserWindow({
    height: 180,
    width: 300,
    resizable: false,
    frame: false,
    icon: iconPath,
    show: false,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false, //关闭上下文隔离的
      // preload: path.join(__dirname, './preload.js')
    },
  })

  // 打开控制台
  // remindWindow.webContents.openDevTools()
  remindWindow.removeMenu()
  // 右下角弹出
  const size = screen.getPrimaryDisplay().workAreaSize
  const { y } = tray.getBounds()
  const { height, width } = remindWindow.getBounds()
  const yPosition = y - height

  remindWindow.setBounds({
    x: size.width - width,
    y: yPosition,
    height,
    width,
  })
  remindWindow.setAlwaysOnTop(true)
  remindWindow.loadURL(`file://${__dirname}/src/remind.html`)
  remindWindow.show()
  // 发消息
  remindWindow.webContents.send('show-remind', task, twrUrl)
  remindWindow.on('closed', () => {
    remindWindow = null
  })
}

2、登录成功后获取实时信息弹框提示;

// login.js

  // 获取登录
  async function getLogin({ account, password }) {

   // do something

   if (response.ok) {
        // 登录成功后触发webSoket
        initWebSocket()
      }
  }

  const heartbeatInterval = 30000 // 心跳检测间隔,单位:毫秒
  const reconnectInterval = 3000 // 重连间隔,单位:毫秒
  let socket = null
  let isReconnecting = false
  // 心跳检测
  function startHeartbeat() {
    setInterval(() => {
      if (socket && socket.readyState === WebSocket.OPEN) {
        // 发送心跳消息到服务器
        socket.send('heartbeat')
      }
    }, heartbeatInterval)
  }

  // 获取实时信息弹框提示
  function initWebSocket() {
    const socUrl = 'ws://xxx/xxx'
    socket = new WebSocket(socUrl)
    // 监听连接事件
    socket.onopen = () => {
      console.log('WebSocket连接已建立')
      // 启动心跳检测
      startHeartbeat()
    }
    // 监听消息事件
    socket.onmessage = event => {
      console.log('收到数据:', event)
      // 启动心跳检测
      startHeartbeat()
      if (event.data === 'HeartBeatResp') {
        // 心跳响应消息不做处理
        return
      }
      const socketData = JSON.parse(event.data)
      // 收到消息后发消息给主进程 socketData:提示信息 | twrUrl.value:跳转地址
      if (socketData) {
        ipcRenderer.send('open-remind', socketData, twrUrl.value)
      }
    }

    // 监听关闭事件
    socket.onclose = event => {
      console.log(`websocket连接关闭 code: ${event.code}, reason: ${event.reason}, wasClean: ${event.wasClean}`)
      reconnectWebSocket()
    }

    // 监听错误事件
    socket.onerror = event => {
      console.log('websocket连接错误')
      reconnectWebSocket()
    }
  }
  // websocket重连
  function reconnectWebSocket() {
    if (!isReconnecting) {
      // 连接断开时,触发重连
      isReconnecting = true
      setTimeout(() => {
        initWebSocket()
        isReconnecting = false
      }, reconnectInterval)
    }
  }

3、在src文件夹下新建remind.html实现提示弹框具体内容;

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      .custom-toolbar {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px;
        font-weight: bold;
        background-color: rgb(236, 233, 233);
      }
      .custom-toolbar .close-button {
        cursor: pointer;
        font-size: 20px;
        position: relative;
        bottom: 1px;
      }
      .custom-toolbar .title-text {
        font-size: 16px;
      }
      .custom-toolbar .title-text > img {
        width: 16px;
        height: 16px;
        position: relative;
        top: 2px;
      }
      .reminder {
        text-align: left;
        font-size: 14px;
        height: 100px;
        padding: 10px;
        padding-top: 0;
        line-height: 24px;
        /* letter-spacing: 1.2px; */
        overflow: auto;
      }
      .close,
      .detail-button {
        position: absolute;
        font-size: 14px;
        color: dodgerblue;
        bottom: 10px;
        cursor: pointer;
        z-index: 1;
      }
      .close {
        right: 10px;
      }
      .detail-button {
        right: 50px;
      }
      .num {
        color: dodgerblue;
        font-weight: bold;
      }
    </style>
  </head>
  <body>
    <div class="custom-toolbar">
      <div class="title-text">
        <img src="./img/icon.png" alt="" />
        xxx小助手
      </div>
      <div class="close-button">×</div>
    </div>
    <span class="detail-button">查看</span>
    <span class="close-button close">关闭</span>
    <div class="reminder"></div>
  </body>
  <script>
    const electron = require('electron')
    const { ipcRenderer } = electron
    const { shell } = require('electron/common')
    const reminder = document.querySelector('.reminder')
    const closeBtns = document.querySelectorAll('.close-button')
    const detailBtn = document.querySelector('.detail-button')
    let socketData
    let url
    ipcRenderer.on('show-remind', (event, task, twrUrl, num) => {
      socketData = task
      url = twrUrl
      if (num) {
        reminder.innerHTML = `您有<span class="num">${num}</span>条信息需要处理,请及时登录xxx系统操作。`
      } else {
        reminder.innerHTML = `<span>${socketData.msgContent}</span>`
      }
      
    })
    // 关闭
    closeBtns.forEach(i => {
      i.addEventListener('click', () => {
        ipcRenderer.send('remindWindow:close')
      })
    })
    // 查看-点击自动跳转到默认浏览器
    detailBtn.addEventListener('click', () => {
      shell.openExternal(`http://${url}/xxx/#/xxx`)
    })
  </script>
</html>

4、综上所述,即可完成桌面提示功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/172026.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis--高可用之持久化

redis高可用相关知识 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#xff0c;除了保证提供正常服务( 如主…

前端css粘性布局,顶部吸附效果(position: sticky)

sticky属性设置 /* 设置粘性布局 */ position: sticky; /* 拖动滚动条&#xff0c;当前元素超出文档0的位置时&#xff0c;触发定位效果&#xff08;同级元素位置不会受影响&#xff09; */ top: 0;页面初始效果 设置前&#xff08;滚动页面时&#xff0c;标签栏随页面滚动&a…

数字电路的基础知识

一、数字电路概述 用数字信号完成对数字量进行逻辑运算和算术运算的电路称为数字电路。 由于它具有逻辑运算和逻辑处理功能&#xff0c;所以又称为数字逻辑电路。 现代的数字电路由半导体工艺制成的数字集成器件构造而成。 逻辑门是数字电路的基本单元电路&#xff0c;就如同在…

海康威视监控相机的SDK与opencv调用(非工业相机)

1.研究内容 本篇主要对海康威视的监控相机的SDK回调进行研究&#xff0c;并于opencv结合&#xff0c;保存图像,以供后续其他处理&#xff0c;开发语言为C 2.步骤及方法 2.1 海康SDK介绍 海康SDK下载地址 根据自身编译环境&#xff0c;下载对应的SDK&#xff0c;需要注意的是…

百度爬虫的工作原理解析

百度作为中国最大的搜索引擎&#xff0c;其工作原理备受关注。本文将深入探讨百度爬虫的工作原理&#xff0c;介绍其基本流程以及关键技术&#xff0c;帮助读者更好地理解搜索引擎背后的技术核心。 百度爬虫是百度搜索引擎的重要基石&#xff0c;它们被广泛用于收集互联网上的网…

竞赛选题 身份证识别系统 - 图像识别 深度学习

文章目录 0 前言1 实现方法1.1 原理1.1.1 字符定位1.1.2 字符识别1.1.3 深度学习算法介绍1.1.4 模型选择 2 算法流程3 部分关键代码 4 效果展示5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计 图像识别 深度学习 身份证识别…

创建域名邮箱邮件地址的方法与步骤

如何创建域名邮箱邮件地址?使用Zoho Mail创建域名邮箱邮件地址的步骤简单易懂&#xff0c;操作便捷。从其他邮箱迁移到Zoho Mail的过程也相当顺畅&#xff0c;您可以轻松为所有员工创建具有企业邮箱域名的电子邮件地址。 步骤1&#xff1a;添加并验证您的域名 首先&#xff0c…

fastdfs-client-java-1.30 maven 打包安装

1. 进入源代码目录&#xff0c;打开cmd mvn clean install 或者 mvn package 问题不大的话会在同级目录target目录下生成打包后文件 2. 当前目录下cmd进行maven安装 mvn install:install-file -DgroupIdorg.csource -DartifactIdfastdfs-client-java -Dversion${version} -D…

设计模式—命令模式

1.什么是命令模式&#xff1f; 命令模式是一种行为型设计模式&#xff0c;核心是将每种请求或操作封装为一个独立的对象&#xff0c;从而可以集中管理这些请求或操作&#xff0c;比如将请求队列化依次执行、或者对操作进行记录和撤销。 命令模式通过将请求的发送者&#xff0…

关于校园网使用罗技flow功能

目录 情况概述问题及解决方案 情况概述 我目前设备是一台Macbook air m1处理器&#xff0c;学校给配了一台windows台式&#xff0c;台式机不能连蓝牙&#xff0c;不能连wifi&#xff0c;只能用网线&#xff0c;我的需求是想让mac和windows共用一套键鼠&#xff0c;在了解到罗技…

注意这“一前一后” 覆盖伦敦金价格形态的缺点

在伦敦金交易中&#xff0c;投资者除了应用技术指标和K线信号做交易以外&#xff0c;还会采取价格形态作为入场触发的信号。但在实际交易中&#xff0c;价格形态的灵敏程度比前面说的那两者要差一点&#xff0c;那我们要如何应用好价格形态作为触发信号呢&#xff1f;下面我们就…

第四代可燃气体监测仪:可燃气体监测仪在燃气管网中的作用有哪些

燃气管网如同城市的血脉&#xff0c;纵横交错着覆盖在每一寸土地。然而如此复杂的管网&#xff0c;仅靠人工巡查难免有些力不从心。毕竟人工监测的范围有其局限性&#xff0c;难以做到全方位、全天候的紧密监测&#xff0c;难免会有疏忽和遗漏。如何将安全隐患消灭于萌芽状态&a…

电脑便签工具推荐哪个?电脑上好用的便签软件使用哪一款

对于职场办公人士来讲&#xff0c;一款好用的电脑便签工具可以给日常工作带来极大的便利&#xff0c;如果您的日常工作离不开电脑工具&#xff0c;您就会知晓电脑便签工具在日常工作中的重要&#xff0c;电脑便签通常以一个小的窗口呈现在电脑桌面上&#xff0c;记录一些工作中…

js实现页面滚动时自动切换Sidebar标签,点击标签自动滚动页面

js实现页面滚动时自动切换Sidebar侧边导航标签&#xff0c;点击标签自动滚动页面 <van-sidebar class"sidebar" v-model"activeKey"><van-sidebar-item :title"i.title" click"onChange(i)" v-for"(i,k) in activeList&…

从小米14安装不上应用说起【适配64位】

一、原因 某天早上&#xff0c;同事突然对我说我换了小米14pro手机但是安装不了公司的打卡软件&#xff0c;怎么办呀。一时间&#xff0c;我也不知道原因&#xff0c;看到给我发的安装不上的截图陷入了沉思。随即打开在git仓库里找到这个项目&#xff0c;到本地编译打开&#…

STM32——STM32Cubemx的学习使用总结

文章目录 一、简介二、STM32Cube IDE与MX区别&#xff1f;三、界面介绍和使用四、使用整体框架 一、简介 STM32CubeMX是一个图形化工具&#xff0c;可以非常容易地配置STM32微控制器和微处理器&#xff0c;以及为ArmCortex-M 内核或部分 Linux 设备树生成相应的初始化C代码&…

DeepStream--测试TrafficCamNet检测模型

模型地址&#xff1a;https://catalog.ngc.nvidia.com/orgs/nvidia/teams/tao/models/trafficcamnet/version 目前模型是nvidia的加密格式etlt。 nvinfer的配置 [property] gpu-id0 net-scale-factor0.0039215697906911373 tlt-model-keytlt_encode tlt-encoded-modeltraffic…

电脑上可以写便签的软件哪些界面比较可爱且好用?

电脑上可以安装使用的便签类软件比较多&#xff0c;在选择使用电脑便签软件时&#xff0c;很多人对便签的外观界面还是比较在意的&#xff0c;一个好看的便签界面在一方面可以引起大家的注意&#xff0c;另一方面可以增加电脑桌面背景和便签类软件的协调性。 电脑便签软件通常…

层层剥开Android14升级后异常弹框的神秘面纱

本篇文章将会通过研究源码的方式给您讲述Android系统升级到Android14后出现的两个异常弹框并给出消除它们的方案。闲话少叙&#xff0c;我们开始。 问题描述 在Android 14升级后&#xff0c;出现两个弹窗的异常情况。这里是异常的截图&#xff1a; 接下来&#xff0c;我们对这…