diff --git a/.gitignore b/.gitignore index 0b3569a..f63a285 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.swp node_modules app/data.json + +OutApp* \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d9d1f3b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}\\app\\main\\index.js" + } + ] +} \ No newline at end of file diff --git a/app/main/SinceTimeTool.js b/app/main/SinceTimeTool.js new file mode 100644 index 0000000..d592086 --- /dev/null +++ b/app/main/SinceTimeTool.js @@ -0,0 +1,39 @@ +let globalSinceTime = {} + +async function sinceTime(title = '默认标记') { + try { + let startTime = 0 + if (performance) { + startTime = performance.now() + } else { + startTime = new Date().getTime() + } + globalSinceTime[title] = startTime + return Promise.resolve(true) + } catch (e) { + return Promise.reject(e) + } +} + +async function sinceTimeEnd(title = '默认标记') { + try { + let endTime = 0 + if (performance) { + endTime = performance.now() + } else { + endTime = new Date().getTime() + } + let startTime = 0 + if (globalSinceTime.hasOwnProperty(title)) { + startTime = globalSinceTime[title] + } + let since = endTime - startTime + console.log(title + ' 耗时:', since, '毫秒') + return Promise.resolve(since) + } catch (e) { + return Promise.reject(e) + } +} + +exports.sinceTime = sinceTime +exports.sinceTimeEnd = sinceTimeEnd diff --git a/app/main/assets/big.png b/app/main/assets/big.png new file mode 100644 index 0000000..81eb223 Binary files /dev/null and b/app/main/assets/big.png differ diff --git a/app/main/assets/close-new.png b/app/main/assets/close-new.png new file mode 100644 index 0000000..c52dd64 Binary files /dev/null and b/app/main/assets/close-new.png differ diff --git a/app/main/assets/mainphoto.png b/app/main/assets/mainphoto.png new file mode 100644 index 0000000..6c72db7 Binary files /dev/null and b/app/main/assets/mainphoto.png differ diff --git a/app/main/assets/small.png b/app/main/assets/small.png new file mode 100644 index 0000000..26ad13f Binary files /dev/null and b/app/main/assets/small.png differ diff --git a/app/main/assets/test1.pdf b/app/main/assets/test1.pdf new file mode 100644 index 0000000..e688541 Binary files /dev/null and b/app/main/assets/test1.pdf differ diff --git a/app/main/child_process.js b/app/main/child_process.js index 984eb79..814bd66 100644 --- a/app/main/child_process.js +++ b/app/main/child_process.js @@ -28,7 +28,7 @@ function start(command, args, options = {}) { } function kill(pid) { - const childProgress = pidMap[pid] + let childProgress = pidMap[pid] let status = false if (childProgress && !childProgress.killed) { status = childProgress.kill() diff --git a/app/main/constant.js b/app/main/constant.js index 98a81ac..5c8fa98 100644 --- a/app/main/constant.js +++ b/app/main/constant.js @@ -17,16 +17,18 @@ try { data = {schema:"QB"} } const schema = data.schema; -let url = ""; +// let url = "file://" + path.resolve(__dirname, './index.html') switch (schema) { case 'KT': - url = 'http://localhost:8080/'; + url = 'http://localhost:3806/'; break; case 'QB': - url = 'http://localhost:8080/TIS_PLATFORM/'; + url = 'http://localhost:3806/TIS_PLATFORM/'; + // url = 'http://localhost:8080/TIS_PLATFORM/'; + // url = 'http://tis.inscloudtech.com:9009/TIS_PLATFORM/#/pc'; break; default: - url = 'http://localhost:8080/TIS_PLATFORM/'; + url = 'http://localhost:3806/TIS_PLATFORM/'; break; } exports.MAIN_WINDOW_URL = url; diff --git a/app/main/index.html b/app/main/index.html new file mode 100644 index 0000000..2a821b2 --- /dev/null +++ b/app/main/index.html @@ -0,0 +1,152 @@ + + + + + + 系统运行监控 + + + + + + +
+
+
+ + 系统运行监控 +
+
+ + + +
+
+
+
+ + + + +
+ + + + + \ No newline at end of file diff --git a/app/main/index.js b/app/main/index.js index 0670304..b2a0075 100644 --- a/app/main/index.js +++ b/app/main/index.js @@ -1,16 +1,50 @@ -const { app, BrowserWindow, dialog, protocol } = require('electron') -const { create: createMainWindow } = require('./windows/main') -const { MANUAL_CREATED_FLAG } = require('./constant') +const {app, BrowserWindow, dialog, protocol, ipcMain} = require('electron') +const {create: createMainWindow} = require('./windows/main') +const {MANUAL_CREATED_FLAG,} = require('./constant') const handleIPC = require('./ipc') -app.commandLine.appendSwitch("--disable-http-cache"); +const {sinceTime,sinceTimeEnd} = require('./SinceTimeTool') +sinceTime() +const store = require('./windows/lib/store'); +const isFirstInstall = store.get("firstInstall"); +if (isFirstInstall) { + console.log('<========清除历史缓存=====>') + app.commandLine.appendSwitch("--disable-http-cache"); + store.set("firstInstall", false); +} +// 关闭GPU加速 +// app.disableHardwareAcceleration() +// app.allowRendererProcessReuse = true app.whenReady().then(() => { + // 启动应用时自动启动监控平台接口服务 + // const child_process = require('child_process') + // if (global.worker !== 'start') { + // let worker = child_process.fork('D:\\linyun\\workspace\\front-monitor-api\\src\\app.js',[]) + // global.worker = 'start' + // } + + const gotTheLock = app.requestSingleInstanceLock(); + console.log('gotTheLock',gotTheLock) + // if (!gotTheLock) { + // dialog.showMessageBox(win,{ + // type: "warning", + // title: "提示", + // message: "您已打开指挥系统!请勿重复操作", + // }).then(() => { + // app.exit() + // }) + // return; + // } protocol.registerFileProtocol('file', (request, callback) => { const pathname = decodeURI(request.url.replace('file:///', '')); callback(pathname); }); + sinceTimeEnd('whenReady') handleIPC(); - createMainWindow() + sinceTimeEnd('handleIPC') + createMainWindow(); + sinceTimeEnd('createWindowEnd') + app.on('browser-window-created', (event, window) => { setTimeout(() => { if (window[MANUAL_CREATED_FLAG]) { // allow safe created manually @@ -42,4 +76,4 @@ app.whenReady().then(() => { // explicitly with Cmd + Q. app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit() -}) \ No newline at end of file +}) diff --git a/app/main/ipc.js b/app/main/ipc.js index efd0781..f7fb7ad 100644 --- a/app/main/ipc.js +++ b/app/main/ipc.js @@ -1,4 +1,6 @@ -const {BrowserWindow} = require('electron'); +const {BrowserWindow, desktopCapturer} = require('electron'); +// const {net} = require('electron'); +const electron = require('electron'); const ipc = require('electron').ipcMain; // const screen = require('electron').screen; const store = require('./windows/lib/store'); @@ -6,56 +8,61 @@ const {create: createMainWindow} = require('./windows/main') // const { create: createLoginWindow } = require('./windows/login') // const { create: createAppWindow } = require('./windows/app') const childProcess = require('./child_process') -const { create: openWindow } = require('./windows/application') - +const {create: openWindow} = require('./windows/application') +// const querystring = require("querystring"); const {MAIN_WINDOW_FLAG, SUSPENSION_WINDOW_FLAG} = require('./constant'); +const { ipcRenderer } = require('electron/renderer'); // const installApp = require('./ipc/installApp'); // const getApps = require('./ipc/getApps'); // const removeApp = require('./ipc/removeApp'); // connect redis -const { createClient } = require('redis') -;(async () => { - /** - * createClient({ - * url: 'redis://alice:foobared@awesome.redis.server:6380' - * }); - */ - const client = createClient() - client.on('error', (err) => console.log('Redis Client Error', err)); - await client.connect() +// const {createClient} = require('redis') +// ;(async () => { +// /** +// * createClient({ +// * url: 'redis://alice:foobared@awesome.redis.server:6380' +// * }); +// */ +// const client = createClient( +// // { +// // url: "redis://localhost:3807" +// // } +// ); +// // client.on('error', (err) => console.log('Redis Client Error', err)); +// await client.connect() - // 订阅者 - const subscriber = client.duplicate(); - await subscriber.connect(); +// // 订阅者 +// const subscriber = client.duplicate(); +// await subscriber.connect(); - // 发布者 - const publisher = client.duplicate() - await publisher.connect() +// // 发布者 +// const publisher = client.duplicate() +// await publisher.connect() - // 通过main向外发布消息 - ipc.on('publishMessage', (events, { channel, ...message }) => { - publisher.publish(channel, JSON.stringify(message)) - }) +// // 通过main向外发布消息 +// ipc.on('publishMessage', (events, {channel, ...message}) => { +// publisher.publish(channel, JSON.stringify(message)) +// }) - // 订阅外部消息 - subscriber.subscribe('openMap', message => { - const windows = BrowserWindow.getAllWindows() - const found = windows.find((window) => { - return window[MAIN_WINDOW_FLAG] - }); - found.webContents.send('openMap', JSON.parse(message)) - }) +// // 订阅外部消息 +// subscriber.subscribe('openMap', message => { +// const windows = BrowserWindow.getAllWindows() +// const found = windows.find((window) => { +// return window[MAIN_WINDOW_FLAG] +// }); +// found.webContents.send('openMap', JSON.parse(message)) +// }) - // 订阅外部消息(正则) - subscriber.pSubscribe('openMap*', (message, channel) => { - const windows = BrowserWindow.getAllWindows() - const found = windows.find((window) => { - return window[MAIN_WINDOW_FLAG] - }); - found.webContents.send(channel, JSON.parse(message)) - }) -})(); +// // 订阅外部消息(正则) +// subscriber.pSubscribe('openMap*', (message, channel) => { +// const windows = BrowserWindow.getAllWindows() +// const found = windows.find((window) => { +// return window[MAIN_WINDOW_FLAG] +// }); +// found.webContents.send(channel, JSON.parse(message)) +// }) +// })(); module.exports = () => { let winStartPostion = {x: 0, y: 0}; @@ -86,21 +93,21 @@ module.exports = () => { let sWidth = areaSize.width; // console.log(sWidth - x); if (sWidth - x === 130) { - win.setSize(640, 130, true); + win.setSize(410, 130, true); win.setPosition(sWidth - 660, y, true); } win.webContents.send("getUnReadMessage", [message]) } }); - ipc.on("showSuspensionWindow",()=>{ + ipc.on("showSuspensionWindow", () => { let areaSize = require('electron').screen.getPrimaryDisplay().workAreaSize; const windows = BrowserWindow.getAllWindows() const win = windows.find((window) => { return window[SUSPENSION_WINDOW_FLAG] }); console.log('恢复原始大小') - win.setSize(640, 130, true); + win.setSize(410, 130, true); const y = win.getPosition()[1]; win.setPosition(areaSize.width - win.getSize()[0], y, true); win.webContents.send("winResize", [win.getSize()]) @@ -113,11 +120,11 @@ module.exports = () => { return window[SUSPENSION_WINDOW_FLAG] }); const startWidth = win.getSize()[0]; - if(startWidth < 640){ + if (startWidth < 410) { const x = win.getPosition()[0]; const y = win.getPosition()[1]; - win.setSize(640, 130, true); - if(x > areaSize.width - win.getSize()[0] ){ + win.setSize(410, 130, true); + if (x > areaSize.width - win.getSize()[0]) { win.setPosition(areaSize.width - win.getSize()[0] - 50, y, true); } @@ -133,8 +140,8 @@ module.exports = () => { /** * 窗口移动事件 */ + if (!win) return; if (canMoving) { - if (!win) return; //读取原位置 const winPosition = win.getPosition(); winStartPostion = {x: winPosition[0], y: winPosition[1]}; @@ -145,10 +152,13 @@ module.exports = () => { } //新开 movingInterVal = setInterval(() => { + if(!win){ + clearInterval(movingInterVal); + return; + } const cursorPosition = screen.getCursorScreenPoint(); const x = winStartPostion.x + cursorPosition.x - mouseStartPosition.x; const y = winStartPostion.y + cursorPosition.y - mouseStartPosition.y; - win.setPosition(x, y, true) }, 20) } else { @@ -156,22 +166,22 @@ module.exports = () => { let areaSize = require('electron').screen.getPrimaryDisplay().workAreaSize; const x = win.getPosition()[0]; const y = win.getPosition()[1]; - store.set("position",{x,y}); + store.set("position", {x, y}); let sWidth = areaSize.width; let winWidth = win.getSize()[0]; // console.log(x + winWidth >= sWidth, sWidth - x - winWidth); // 靠边吸附效果 - console.log("0000000",x + winWidth >= sWidth,sWidth - x - winWidth <= 20) + console.log("0000000", x + winWidth >= sWidth, sWidth - x - winWidth <= 20) if (x + winWidth >= sWidth || sWidth - x - winWidth <= 20) { win.setResizable(true); - win.setSize(130,130,true) + win.setSize(130, 130, true) win.setPosition(sWidth - 130, y, true); win.setResizable(false); - console.log("靠边吸附",win.getSize(),win.getPosition()) + console.log("靠边吸附", win.getSize(), win.getPosition()) //通知渲染进程大小发生改变 - }else{ - win.setSize(650,130,true) + } else { + win.setSize(410, 130, true) } win.webContents.send("winResize", [win.getSize()]) movingInterVal = null; @@ -191,6 +201,7 @@ module.exports = () => { return true }); ipc.on('hideMainWindow', () => { + console.log('最小化hideMainWindow'); const windows = BrowserWindow.getAllWindows() const found = windows.find((window) => { return window[MAIN_WINDOW_FLAG] @@ -201,14 +212,20 @@ module.exports = () => { return true }); ipc.on('minimize', () => { - const windows = BrowserWindow.getAllWindows() - const found = windows.find((window) => { - return window[MAIN_WINDOW_FLAG] - }) - if (found) { - found.minimize(); - } - return true + // const windows = BrowserWindow.getAllWindows() + // const found = windows.find((window) => { + // return window[MAIN_WINDOW_FLAG] + // }) + // if (found) { + // found.minimize(); + // } + // return true + try { + const windows = BrowserWindow.getAllWindows() + for (let win of windows) { + win && win.minimize() + } + }catch (e) {} }); ipc.on('hideSuspensionWindow', (event, arg) => { @@ -228,16 +245,18 @@ module.exports = () => { }); ipc.on('exitSystem', () => { - const windows = BrowserWindow.getAllWindows() - const mainWindow = windows.find((window) => { - return window[MAIN_WINDOW_FLAG] - }) - const suspWindow = windows.find((window) => { - return window[SUSPENSION_WINDOW_FLAG] - }); - store.delete("unReadMessage"); - mainWindow && mainWindow.close(); - suspWindow && suspWindow.close(); + console.log('global',global.worker); + try { + const windows = BrowserWindow.getAllWindows() + + for (let win of windows) { + win && win.close() + } + global.worker === 'stop' + store.delete("unReadMessage"); + }catch (e) { + + } }); // ipc.handle('openWidget', (event, widget = {}) => { // createAppWindow(widget) @@ -255,55 +274,141 @@ module.exports = () => { // // ipc.handle('removeApp', removeApp); - /* 示例:在网页中调用ipcRenderer模块 - ipcRenderer.send('spawn', { - command: '微信.exe', - args: null || ['--disable-cache'], - key: + new Date // 唯一key,用来做关闭识别, - }) - */ - ipc.on('spawn', (event, arg) => { - const { pid, promise } = childProcess.start(arg.command, arg.args, arg.key) - event.sender.send('spawn-success', { - key: arg.key, - pid + /* 示例:在网页中调用ipcRenderer模块 + ipcRenderer.send('spawn', { + command: '微信.exe', + args: null || ['--disable-cache'], + key: + new Date // 唯一key,用来做关闭识别, + }) + */ + ipc.on('spawn', (event, arg) => { + const {pid, promise} = childProcess.start(arg.command, arg.args, arg.key) + event.sender.send('spawn-success', { + key: arg.key, + pid + }) + promise.then(data => { + event.sender.send('spawn-success', { + key: arg.key, + data + }) + }) + promise.catch(err => { + event.sender.send('spawn-error', { + key: arg.key, + err + }) + }) }) - promise.then(data => { - event.sender.send('spawn-success', { - key: arg.key, - data - }) + + // ipcRenderer.send('kill-process', [pid]) + ipc.on('kill-process', function (event, arg) { + childProcess.kill(arg[0]) }) - promise.catch(err => { - event.sender.send('spawn-error', { - key: arg.key, - err - }) + + // 通信桥梁 + ipc.on('bridge', function (event, {channel, targetId, ...message}) { + console.log('bridge message', channel, message) + const windows = BrowserWindow.getAllWindows() + // const found = windows.find((window) => { + // return window[SUSPENSION_WINDOW_FLAG] + // }); + for (let win of windows) { + if (!targetId || win[targetId]) { + win.webContents.send(channel, message); + } + } + }) - }) + const windowMap = new Map(); + // 通过main打开新窗口 + ipc.on('openWindow', function (event, arg) { + //如果存在第二块屏幕,在第二块屏幕打开 + let displays = electron.screen.getAllDisplays(); + let externalDisplay = displays.find((display)=>{ + return display.bounds.x !== 0 || display.bounds.y !== 0 + }); + let options = {}; + if(externalDisplay){ + options = { + fullscreen:true, + x:externalDisplay.bounds.x, + y:externalDisplay.bounds.y, + }; + + //关闭上一个,同一时间在拓展屏只能打开两个,打开多个或引起卡顿 + if(windowMap.size > 2){ + const win = windowMap.values().next().value; + win.close(); + windowMap.delete(windowMap.keys().next().value); + } + } + console.log('openWindow request from renderer process', arg); + const windows = BrowserWindow.getAllWindows(); + const found = windows.find((window) => { + return window[arg.id] + }); + if (!arg.id || !arg.entry) { + return; + } + //未打开过,新建窗口 + if(!found){ + const temp = openWindow(arg,options) + windowMap.set(arg.id,temp); + }else{//打开且未关闭,切换至前台 + found.focus() + } - // ipcRenderer.send('kill-process', [pid]) - ipc.on('kill-process', function (event, arg) { - childProcess.kill(arg[0]) - }) - // 通信桥梁 - ipc.on('bridge', function (event, { channel, targetId, ...message }) { - const windows = BrowserWindow.getAllWindows() - for (let win of windows) { - if (win.webContents.id === event.sender.id) continue; - if (!targetId || win[targetId]) { - win.webContents.send(channel, message) - } - } - }) + }) + //返回上一个窗口 + ipc.on("backPreviousApp",function (event,arg) { + const keys = [...windowMap.keys()]; + const curKey = keys.findIndex(v=>v === arg.id); + if(keys.length > 1){ + let preKey = curKey > 0? curKey - 1 : keys.length - 1; + const preId = keys[preKey]; + windowMap.get(preId).focus(); + } - // 通过main打开新窗口 - ipc.on('openWindow', function (event, arg) { - console.log('openWindow request from renderer process', arg) - if (!arg.id || !arg.entry) { - return; - } - openWindow(arg) - }) + }); + //根据指定id关闭窗口 + ipc.on('closeWindowById', function (event, arg) { + const windows = BrowserWindow.getAllWindows(); + const found = windows.find((window) => { + return window[arg.id] + }); + found.close(); + windowMap.delete(arg.id); + }) + // 监听调用截屏事件 + ipc.on('PrtSc', function (event, arg) { + const windows = BrowserWindow.getAllWindows() + const found = windows.find((window) => { + return window[MAIN_WINDOW_FLAG] + }) + if (found) { + found.webContents.send('PrtSc'); + } + }) + // 监听下载截屏的图片 + ipc.on('downloadImg', function (event, arg) { + const windows = BrowserWindow.getAllWindows() + const found = windows.find((window) => { + return window[MAIN_WINDOW_FLAG] + }) + if (found) { + found.webContents.send('downloadImg'); + } + }) + // 取消截屏显示 + ipc.on('removeCanvas', function (event, arg) { + const windows = BrowserWindow.getAllWindows() + const found = windows.find((window) => { + return window[MAIN_WINDOW_FLAG] + }) + if (found) { + found.webContents.send('removeCanvas'); + } + }) } diff --git a/app/main/windows/application.js b/app/main/windows/application.js index d7930fb..6264ee6 100644 --- a/app/main/windows/application.js +++ b/app/main/windows/application.js @@ -1,8 +1,8 @@ -const { BrowserWindow } = require('electron') +const { BrowserWindow } = require('electron') const { createWindow } = require('./lib/common') // props: { id: 'TIS_APP_TEMPLATE_KT', entry: '' } -const create = props => { +const create = (props,options) => { const windows = BrowserWindow.getAllWindows() const found = windows.find(w => w[props.id]) if (found) { @@ -12,9 +12,10 @@ const create = props => { } const win = createWindow(props.entry, { - show: true + show: true, + ...options, }) - win[props.id] = true + win[props.id] = Symbol(props.id); return win } diff --git a/app/main/windows/lib/common.js b/app/main/windows/lib/common.js index 4067492..823c816 100644 --- a/app/main/windows/lib/common.js +++ b/app/main/windows/lib/common.js @@ -1,14 +1,24 @@ -const { BrowserWindow } = require('electron') +const { BrowserWindow,Menu,globalShortcut, ipcMain, desktopCapturer } = require('electron') const path = require('path') - const { MANUAL_CREATED_FLAG } = require('../../constant') +const {sinceTimeEnd} = require('../../SinceTimeTool') +// 引入初始化remote模块 +const remote = require('@electron/remote/main') +remote.initialize() function createWindow(url,options,node=false) { - // let areaSize = require('electron').screen.getPrimaryDisplay().workAreaSize - const window = new BrowserWindow({ + Menu.setApplicationMenu(null); + const win = new BrowserWindow({ // width: 870, // height: 530, webPreferences: { + // webSecurity: false, + // contextIsolation: false, + // enableRemoteModule:true, + nodeIntegration: node, + // webviewTag: true, + // devTools: true, + // preload: path.join(__dirname, 'preload.js') webSecurity: false, contextIsolation: false, enableRemoteModule:true, @@ -18,12 +28,29 @@ function createWindow(url,options,node=false) { ...options }) - window[MANUAL_CREATED_FLAG] = true + win[MANUAL_CREATED_FLAG] = true console.log('openWindow', url) - window.loadURL(url) - // window.webContents.openDevTools() // Open the DevTools. - return window + win.loadURL(url); + sinceTimeEnd('loadURL') + + // 清除缓存 + // const ses = win.webContents.session + // ses.clearCache() + + // 启用remote模块 + remote.enable(win.webContents) + // 注册快捷键 + win.on('focus', () => { + globalShortcut.register('CommandOrControl+Alt+F', function () { + win && win.webContents.toggleDevTools(); + }) + }); + win.on('blur', () => { + globalShortcut.unregisterAll() // 注销键盘事件 + }) + // win.webContents.openDevTools() // Open the DevTools. + return win } module.exports = { createWindow } \ No newline at end of file diff --git a/app/main/windows/lib/data.json b/app/main/windows/lib/data.json index 2eb6c2e..685f42d 100644 --- a/app/main/windows/lib/data.json +++ b/app/main/windows/lib/data.json @@ -1 +1 @@ -{"test":{"a":1},"test2":{"name":"我是你爹"}} \ No newline at end of file +{"firstInstall":false,"position":{"x":1155,"y":775}} \ No newline at end of file diff --git a/app/main/windows/lib/preload.js b/app/main/windows/lib/preload.js index b2bfe66..7a31a3b 100644 --- a/app/main/windows/lib/preload.js +++ b/app/main/windows/lib/preload.js @@ -1,38 +1,99 @@ // All of the Node.js APIs are available in the preload process. // It has the same sandbox as a Chrome extension. -const {ipcRenderer} = require('electron') - +const {ipcRenderer, desktopCapturer} = require('electron'); +const remote = require('@electron/remote'); +window.currentFrame = 'platform'; window.api = [ - "showSuspensionWindow", - "resizeWindow", - "setUnReadMessage", - "getUnReadMessage", - "windowMoveHandle", - "exitSystem", - "openDevTools", - "hideMainWindow", - "showMainWindow", - "minimize", - "hideSuspensionWindow" -].reduce((acc, apiName) => { + 'showSuspensionWindow', + 'resizeWindow', + 'setUnReadMessage', + 'getUnReadMessage', + 'windowMoveHandle', + 'exitSystem', + 'openDevTools', + 'hideMainWindow', + 'showMainWindow', + 'minimize', + 'hideSuspensionWindow', + 'closeWindowById', + 'PrtSc', + 'downloadImg', + 'removeCanvas', +].reduce( + (acc, apiName) => { acc[apiName] = (...params) => { - return ipcRenderer.send(apiName, ...params) - } - return acc -}, { + return ipcRenderer.send(apiName, ...params); + }; + return acc; + }, + { on: ipcRenderer.on.bind(ipcRenderer), send: ipcRenderer.send.bind(ipcRenderer), - removeListener: ipcRenderer.removeListener.bind(ipcRenderer) -}); + removeListener: ipcRenderer.removeListener.bind(ipcRenderer), + } +); ipcRenderer.on('getUnReadMessage', (e, args) => { - window.getUnReadMessage(args[0]); + window.getUnReadMessage(args[0]); }); -window.addEventListener("keydown", e => { - const {altKey, ctrlKey, keyCode} = e; - if (altKey && ctrlKey && keyCode === 70) { - const currentWindow = require('electron').remote.getCurrentWindow(); - currentWindow && currentWindow.toggleDevTools(); - e.preventDefault(); + +let ImgSrc = null; +// 监听用户截屏 +ipcRenderer.on('PrtSc', (e, args) => { + // 显示截屏区域 + let screenContent = document.querySelector('.screen-canvas'); + screenContent.style.display = 'block'; + // 获取当前屏幕的宽高 + const {width, height} = remote.getCurrentWindow().getBounds(); + console.log(width, height); + // 获取canvas元素 + const canvas = document.getElementById('thumbnailCanvas'); + const ctx = canvas.getContext('2d'); + // 这里的300可根据需要自定义,显示的是截屏后图片显示的大小 + canvas.width = (height - 300) * 16 / 9; + canvas.height = height - 300; + desktopCapturer.getSources({types: ['screen'], thumbnailSize: {width: canvas.width, height: canvas.height}}).then(async sources => { + try { + sources.forEach(source => { + const img = new Image(); + img.src = source.thumbnail.toDataURL(); + ImgSrc = img.src + img.onload = () => { + ctx.drawImage(img, 0, 0); + }; + }); + } catch (error) { + console.log(error); } -}) + }); +}); + +// 监听用户下载截屏图片 +ipcRenderer.on('downloadImg', (e, args) => { + downLoadImage(ImgSrc); +}); + +// 下载图片 +function downLoadImage(src) { + const link = document.createElement('a'); + link.href = src; + link.download = new Date().getTime() + '.png'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} + +// 监听用户取消截屏图片显示 +ipcRenderer.on('removeCanvas', (e, args) => { + removeCanvas() +}); +function removeCanvas() { + // 获取canvas元素 + const canvas = document.getElementById('thumbnailCanvas'); + const ctx = canvas.getContext('2d'); + // 清除画布 + ctx.clearRect(0, 0, canvas.width, canvas.height); + // 隐藏截屏区域 + let screenContent = document.querySelector('.screen-canvas'); + screenContent.style.display = 'none'; +} diff --git a/app/main/windows/lib/store.js b/app/main/windows/lib/store.js index bafd209..d839f71 100644 --- a/app/main/windows/lib/store.js +++ b/app/main/windows/lib/store.js @@ -1,28 +1,28 @@ // const Store = require('electron-store'); // const store = new Store();// - -const data_path = "./data.json"; +const path = require("path") +const data_path = path.join(__dirname, './data.json'); const fs = require("fs") class Store { constructor(){ - fs.writeFileSync(data_path,JSON.stringify({})) + // fs.writeFileSync(data_path,JSON.stringify({})) } set(key, param) { // let saveData = {key:param}; - console.log("------",key,param); - let oldData = require('./data.json'); + // console.log("------",key,param); + let oldData = require(data_path); oldData[key] = param; - // console.log('======',oldData); + // console.log('======',JSON.stringify(oldData),data_path); fs.writeFileSync(data_path,JSON.stringify(oldData)) } get(key){ const data = JSON.parse(fs.readFileSync(data_path,'utf-8')); - // console.log('get>>>>>>>>>',data[key]) + // console.log('get>>>>>>>>>',data[key],data_path) return data[key]; } delete(key){ - let oldData = require('./data.json'); + let oldData = require(data_path); delete oldData[key]; fs.writeFileSync(data_path,JSON.stringify(oldData)) } diff --git a/app/main/windows/main.js b/app/main/windows/main.js index cbe9642..b54a64f 100644 --- a/app/main/windows/main.js +++ b/app/main/windows/main.js @@ -1,37 +1,85 @@ -const { MAIN_WINDOW_FLAG, MAIN_WINDOW_URL } = require("../constant") -const { createWindow } = require('./lib/common') -const { BrowserWindow } = require('electron') -const { create: createSuspensionWindow } = require('./suspension'); +const {MAIN_WINDOW_FLAG, MAIN_WINDOW_URL} = require("../constant") +const {createWindow} = require('./lib/common') +const {BrowserWindow} = require('electron') +const {create: createSuspensionWindow} = require('./suspension'); +const screen = require("./screen.json"); +const {sinceTimeEnd} = require('../SinceTimeTool') +const exec = require('child_process') +const start = () => { + // 任何你期望执行的cmd命令,ls都可以 + // let cmdStr1 = 'node D:\linyun\2022-06-07\front-monitor-api\src\app.js' + let cmdStr1 = 'D:\linyun\2022-06-07\front-monitor-api\src\app.js' + + let cmdPath = '../../../../../2022-06-07/front-monitor-api/' + // 子进程名称 + let workerProcess + function runExec (cmdStr) { + workerProcess = exec.fork(cmdStr) + // 打印正常的后台可执行程序输出 + workerProcess.stdout.on('data', function (data) { + console.log('stdout: ' + data) + }) + // 打印错误的后台可执行程序输出 + workerProcess.stderr.on('data', function (data) { + console.log('stderr: ' + data) + }) + // 退出之后的输出 + workerProcess.on('close', function (code) { + console.log('out code:' + code) + }) + } + runExec(cmdStr1) +} const create = () => { - const windows = BrowserWindow.getAllWindows() - const found = windows.find((window) => { - return window[MAIN_WINDOW_FLAG] - }) - - if (found) { - found.show(); - found.center(); - found.maximize(); - return found; - } else { - const win = createWindow(MAIN_WINDOW_URL,{ - fullscreen:true, - offScreen:false, - frame: false, //要创建无边框窗口 - show:true + const windows = BrowserWindow.getAllWindows() + const found = windows.find((window) => { + return window[MAIN_WINDOW_FLAG] }) - win[MAIN_WINDOW_FLAG] = true - // win.on('ready-to-show', () => { - // win.show(); - // }); - win.on('hide', () => { - createSuspensionWindow(); - }); - return create(); - } + if (found) { + found.show(); + found.center(); + found.maximize(); + return found; + } else { + let areaSize = require('electron').screen.getPrimaryDisplay().workAreaSize; + let width = areaSize.width; + let height = areaSize.height; + let resizable = true; + if (screen.width > 0 && screen.height > 0) { + const ratios = screen.width / screen.height; + height = areaSize.height; + width = Math.floor(areaSize.height * ratios); + resizable = false; + } + const win = createWindow(MAIN_WINDOW_URL, { + //alwaysOnTop: true, //窗口是否总是显示在其他窗口之前 + fullscreen: true, + offScreen: false, + frame: false, //要创建无边框窗口 + width: width, //悬浮窗口的宽度 比实际DIV的宽度要多2px 因为有1px的边框 + height: height, //悬浮窗口的高度 比实际DIV的高度要多2px 因为有1px的边框 + resizable: resizable, //禁止窗口大小缩放 + show: false, //先不让窗口显示 + // backgroundColor: "#0a0a0a" + }) + win[MAIN_WINDOW_FLAG] = true +// start() + sinceTimeEnd('createWindow') + win.on('ready-to-show', () => { + + sinceTimeEnd('ready-to-show') + win.show(); + sinceTimeEnd('win.show') + }); + win.on('hide', () => { + console.log('窗口hide'); + createSuspensionWindow(); + }); + return create(); + } } -module.exports = { create } \ No newline at end of file +module.exports = {create} \ No newline at end of file diff --git a/app/main/windows/screen.json b/app/main/windows/screen.json new file mode 100644 index 0000000..2e2d8c1 --- /dev/null +++ b/app/main/windows/screen.json @@ -0,0 +1,4 @@ +{ + "width":0, + "height":0 +} diff --git a/app/main/windows/suspension.js b/app/main/windows/suspension.js index 1ca63f2..c40af65 100644 --- a/app/main/windows/suspension.js +++ b/app/main/windows/suspension.js @@ -24,7 +24,7 @@ const create = () => { // maximizable: false, // resizable: false, // focusable: true - width: 427, //悬浮窗口的宽度 比实际DIV的宽度要多2px 因为有1px的边框 + width: 310, //悬浮窗口的宽度 比实际DIV的宽度要多2px 因为有1px的边框 height: 130, //悬浮窗口的高度 比实际DIV的高度要多2px 因为有1px的边框 // width: 500, // height: 500, diff --git a/app/package.json b/app/package.json index bb56d76..e62d2de 100644 --- a/app/package.json +++ b/app/package.json @@ -33,12 +33,13 @@ "devDependencies": { "asar": "^3.0.3", "cross-env": "^5.2.0", - "electron": "4.1.2", + "electron": "15.5.7", "electron-builder": "^22.6.1", "electron-packager": "^13.1.1", "electron-store": "^8.0.0" }, "dependencies": { + "@electron/remote": "^2.0.8", "redis": "^4.0.1" } } diff --git a/app/renderer/pages/suspension/index.html b/app/renderer/pages/suspension/index.html index 1e8c6ce..b31f102 100644 --- a/app/renderer/pages/suspension/index.html +++ b/app/renderer/pages/suspension/index.html @@ -125,7 +125,7 @@