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

3 篇文章 0 订阅
3 篇文章 0 订阅

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

        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、综上所述,即可完成桌面提示功能。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Electron是一个使用JavaScript,HTML和CSS构建桌面应用程序的框架。通过将Chromium和Node.js嵌入到其二进制文件中,Electron允许开发者维护一个JavaScript代码库,并创建可在Windows,macOS和Linux上运行的跨平台应用程序,无需本机开发经验。使用Electron开发桌面应用可以将现有的Web技术与原生应用的功能相结合,同时还能够利用Electron丰富的API和工具来增强应用的功能和性能。 创建一个Electron应用程序遵循与其他Node.js项目相同的一般结构。首先需要在电脑上安装Node.js,然后通过命令行创建一个文件夹并初始化一个npm包。接下来,可以使用npm安装Electron依赖和其他必要的库。在初始化完成后,可以开始编写应用程序的主要代码,使用HTML,CSS和JavaScript来创建用户界面和实现应用功能。最后,使用Electron提供的打包工具将应用程序打包成可执行文件,可以在各个操作系统上进行安装和运行。 使用Electron可以快速开发出一个功能完善的桌面应用程序,并且能够跨平台运行,为用户提供更好的用户体验。同时,由于使用了Web技术,开发者可以充分利用现有的前端开发经验和工具,提高开发效率。因此,Electron成为了很多开发者选择的框架之一。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [使用Electron构建桌面应用](https://download.csdn.net/download/weixin_38749268/15444248)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【Electron桌面应用开发](https://blog.csdn.net/weixin_64172426/article/details/126094153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值