main.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. const { app, BrowserWindow, Menu, ipcMain, globalShortcut, dialog, screen, Tray } = require('electron');
  2. const { join } = require('path');
  3. const { fork } = require('child_process');
  4. const { platform } = require('process');
  5. const mqtt = require('mqtt')
  6. const client = mqtt.connect('mqtt://127.0.0.1:49800', { manualConnect: true })
  7. const sleep = (ms) => new Promise(res => setTimeout(res, ms));
  8. class MainSerivce {
  9. #mqttChannel = ''
  10. constructor() {
  11. Menu.setApplicationMenu(null) // 去掉菜单栏
  12. app.commandLine.appendSwitch('wm-window-animations-disabled') // 拖动闪屏
  13. app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
  14. this.loadingWin = null
  15. this.mainWin = null
  16. this.icon = join(__dirname, './icon/playGame.png')
  17. this.contrlEvent = null
  18. app.on('ready', this.onRead.bind(this))
  19. app.on('activate', (e, isVisible) => {
  20. if (!isVisible && this.mainWin) {
  21. // 兼容Mac dock 栏点击
  22. this.mainWin.show()
  23. }
  24. })
  25. app.on('window-all-closed', () => app.quit())
  26. }
  27. createLoading() {
  28. const { size: { width, height } } = screen.getPrimaryDisplay()
  29. this.loadingWin = new BrowserWindow({
  30. frame: false, // 无边框(窗口、工具栏等),只包含网页内容
  31. width,
  32. height,
  33. resizable: false,
  34. center: true,
  35. icon: this.icon,
  36. alwaysOnTop: true,
  37. transparent: true // 窗口是否支持透明,如果想做高级效果最好为true
  38. })
  39. this.loadingWin.loadFile('loading.html')
  40. this.loadingWin.on('close', () => {
  41. this.loadingWin = null
  42. })
  43. }
  44. createWindow() {
  45. this.mainWin = new BrowserWindow({
  46. minWidth: 1300,
  47. minHeight: 760,
  48. width: 1300,
  49. height: 760,
  50. frame: false,
  51. transparent: true,
  52. icon: this.icon,
  53. webPreferences: {
  54. contextIsolation: true,
  55. nodeIntegration: true,
  56. webSecurity: false, // 去掉跨越
  57. nodeIntegrationInWorker: true,
  58. preload: join(__dirname, './preload.js')
  59. },
  60. show: false
  61. })// 创建一个窗口
  62. // 不同环境加载不同文件
  63. if (app.isPackaged) {
  64. this.mainWin.loadFile('dist/index.html')
  65. } else {
  66. this.mainWin.loadURL('http://localhost:6547/')
  67. }
  68. // 事件监听
  69. this.mainWin.on('close', () => { this.mainWin = null })
  70. }
  71. onRead() {
  72. this.createLoading()
  73. this.createWindow()
  74. // 图标
  75. const tray = new Tray(this.icon)
  76. const contextMenu = Menu.buildFromTemplate([
  77. {
  78. label: '退出',
  79. click: () => {
  80. this.mainWin.close()
  81. app.quit()
  82. }
  83. }
  84. ])
  85. tray.setToolTip('控制端')
  86. tray.on('click', () => this.mainWin.show())
  87. // 注册调试模式
  88. globalShortcut.register('Ctrl+F12', () => {
  89. this.mainWin.webContents.toggleDevTools()
  90. })
  91. // 系统环境
  92. if (platform === 'win32') {
  93. // 右键
  94. tray.setContextMenu(contextMenu)
  95. // 禁用右键
  96. this.mainWin.hookWindowMessage(278, () => {
  97. this.mainWin.setEnabled(false);//窗口禁用
  98. setTimeout(() => {
  99. this.mainWin.setEnabled(true);
  100. }, 100) //延时太快会立刻启动,太慢会妨碍窗口其他操作,可自行测试最佳时间
  101. return true
  102. })
  103. } else if (platform === 'darwin') {
  104. app.dock.setIcon(join(__dirname, './icon/playGame@2x.png'))
  105. }
  106. // 通信
  107. ipcMain.on('signal', (_, evt, data) => {
  108. if (evt === 'close-loading') {
  109. if (this.loadingWin) this.loadingWin.close()
  110. this.mainWin.show()
  111. // if (this.mainWin.isVisible()) this.connectLogi()
  112. } else if (evt === 'minWin') {
  113. this.mainWin.minimize()
  114. } else if (evt === 'closeWin') {
  115. client.end()
  116. this.mainWin.close()
  117. } else if (evt === 'maxWin') {
  118. const { width, height } = screen.getPrimaryDisplay().size
  119. if (data) { this.mainWin.setBounds({ x: 0, y: 0, width, height }) } else {
  120. this.mainWin.setBounds({ width: 1300, height: 760 })
  121. this.mainWin.center()
  122. }
  123. } else if (evt === 'loginMqtt') {
  124. client.options.username = data.room
  125. client.options.password = data.name
  126. client.connect()
  127. } else if (evt === 'closeMqtt') {
  128. client.end()
  129. } else if (evt === 'sendMqtt') {
  130. try {
  131. const db = JSON.stringify(data)
  132. if (client.connected && this.#mqttChannel) client.publish(this.#mqttChannel, db)
  133. } catch (error) {
  134. console.log(error);
  135. }
  136. }
  137. })
  138. // 监听
  139. client.on('connect', () => this.mainWin.webContents.send('message', { type: 'connect' }))
  140. client.on('message', (_, msg, __) => {
  141. try {
  142. const db = JSON.parse(msg.toString())
  143. if (db.type === 'join') this.#mqttChannel = db.channel
  144. this.mainWin.webContents.send('message', db)
  145. } catch (error) {
  146. console.log(error);
  147. }
  148. })
  149. client.on('error', (e) => {
  150. this.#mqttChannel = ''
  151. this.mainWin.webContents.send('message', { type: 'disconnect' })
  152. client.end(true)
  153. })
  154. }
  155. connectLogi() {
  156. this.contrlEvent = fork(join(__dirname, './logiControl.js'));
  157. this.contrlEvent.on('message', msg => {
  158. if (!msg || msg.type === 'err' || !msg.data || !msg.data[44]) {
  159. this.contrlEvent.disconnect()
  160. this.contrlEvent.kill(msg.pid ?? 'SIGKILL')
  161. this.contrlEvent = null
  162. dialog.showMessageBox(this.mainWin, { message: '请尝试旋转方向或重新插入USB或重启客户端!', type: 'error', title: '连接错误' }).then(async ({ response }) => {
  163. if (!response) {
  164. await sleep(2000)
  165. this.connectLogi()
  166. }
  167. })
  168. } else {
  169. if (this.mainWin && !this.mainWin.isDestroyed() && this.contrlEvent) this.mainWin?.webContents.send('message', { type: 'contrl', content: msg.data })
  170. }
  171. })
  172. }
  173. };
  174. new MainSerivce()