'use strict' import { app, protocol, globalShortcut, BrowserWindow, ipcMain, Menu, dialog } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import { autoUpdater } from 'electron-updater' const contextMenu = require('electron-context-menu') contextMenu({ labels: { cut: '剪切', copy: '复制', paste: '粘贴', save: '保存', saveImageAs: '图片另存为' }, prepend: () => [ { type: 'separator' }, { type: 'separator' }, { label: 'Invisible', visible: false }, { type: 'separator' }, { type: 'separator' } ], append: () => {}, showSearchWithGoogle: false, showCopyImageAddress: false, showSaveImageAs: true, showSaveImage: false, showCopyImage: false, showInspectElement: false }) global.windows = {} const Store = require('electron-store') const localStore = new Store() localStore.delete('token') const log = require('electron-log') log.transports.file.level = 'silly' const isDevelopment = process.env.NODE_ENV !== 'production' const path = require('path') // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let win let canQuit = false let workerWin // Scheme must be registered before the app is ready protocol.registerStandardSchemes(['app'], { secure: true }) const { download } = require('electron-dl') function createWindow () { // Create the browser window. win = new BrowserWindow({ width: 800, height: 600, show: false, icon: path.join(__static, process.env.VUE_APP_LOGO ? process.env.VUE_APP_LOGO + '.png' : 'icon.png'), webPreferences: { webSecurity: false, plugins: true } }) global.windows.index = win.webContents.id win.maximize() win.show() log.info('当前软件版本号', app.getVersion()) if (process.env.WEBPACK_DEV_SERVER_URL) { // Load the url of the dev server if in development mode win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) if (!process.env.IS_TEST) win.webContents.openDevTools() } else { createProtocol('app') // Load the index.html when not in development win.loadURL('app://./index.html') } win.on('closed', () => { win = null workerWin && workerWin.close() }) win.on('close', (e) => { if (canQuit) { app.quit() } else { e.preventDefault() dialog.showMessageBox({ type: 'info', title: '提示', message: '确定退出软件吗?', buttons: ['是', '否'] }, (index) => { if (index === 0) { canQuit = true app.quit() } }) } }) ipcMain.on('updateReady', (event, updateUrl) => { console.log('check update', updateUrl) checkForUpdates(updateUrl) }) ipcMain.on('getPrinters', (event, updateUrl) => { win.webContents.send('sendPrinters', win.webContents.getPrinters()) }) ipcMain.on('open-directory-dialog', (event) => { dialog.showOpenDialog({ properties: ['openDirectory'] // 'openFile', 'openDirectory' }, (files) => { if (files) event.sender.send('selected-directory', files) }) }) ipcMain.on('open-file-dialog', (event) => { dialog.showOpenDialog({ properties: ['openFile'] // 'openFile', 'openDirectory' }, (files) => { if (files) event.sender.send('selected-file', files) }) }) ipcMain.on('download', async (event, args) => { log.info('下载', args) try { const file = await download(win, args, { saveAs: true, errorTitle: '下载出错' }) event.sender.send('downloadSuccess', file) } catch (e) { console.log(JSON.stringify(e)) event.sender.send('downloadError', e.message) } }) globalShortcut.register('CommandOrControl+P', () => { localStore.openInEditor() }) globalShortcut.register('F3', () => { BrowserWindow.getFocusedWindow().webContents.openDevTools() }) } // 创建人脸识别弹框,放在主窗口识别预热,会导致页面卡顿 function createWorker (devPath, prodPath) { // create hidden worker window workerWin = new BrowserWindow({ show: true, // process.env.NODE_ENV !== 'production', alwaysOnTop: true, fullscreen: true, // process.env.NODE_ENV === 'production' webPreferences: { nodeIntegration: true, webSecurity: false } }) workerWin.hide() global.windows.faceDetector = workerWin.webContents.id if (process.env.WEBPACK_DEV_SERVER_URL) { workerWin.loadURL(process.env.WEBPACK_DEV_SERVER_URL + devPath) } else { workerWin.loadURL(`app://./${prodPath}`) } workerWin.on('closed', () => { workerWin = null }) } if (!isDevelopment) { // 单例应用,防止同时打开多个软件窗口 const gotTheLock = app.requestSingleInstanceLock() if (!gotTheLock) { app.quit() } else { app.on('second-instance', (event, commandLine, workingDirectory) => { // Someone tried to run a second instance, we should focus our window. if (win) { if (win.isMinimized()) win.restore() win.focus() } }) } } // Quit when all windows are closed. app.on('window-all-closed', () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (win === null) { createWindow() setMenu() } }) // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', async () => { if (isDevelopment && !process.env.IS_TEST) { // Install Vue Devtools try { // await installVueDevtools() } catch (e) { console.error('Vue Devtools failed to install:', e.toString()) } } createWindow() setMenu() createWorker('worker', 'worker.html') }) // Exit cleanly on request from parent process in development mode. if (isDevelopment) { if (process.platform === 'win32') { process.on('message', data => { if (data === 'graceful-exit') { app.quit() } }) } else { process.on('SIGTERM', () => { app.quit() }) } } const sendUpdateMessage = (message, data) => { log.warn(message) win.webContents.send('message', { message, data }) } export function checkForUpdates (url) { if (process.env.NODE_ENV !== 'production') return // 设置自动更新 autoUpdater.setFeedURL(url) autoUpdater.on('error', function (message) { sendUpdateMessage('error', message) }) autoUpdater.on('checking-for-update', function (message) { sendUpdateMessage('checking-for-update', message) }) autoUpdater.on('update-available', function (message) { sendUpdateMessage('update-available', message) }) autoUpdater.on('update-not-available', function (message) { sendUpdateMessage('update-not-available', message) }) // 更新下载进度事件 autoUpdater.on('download-progress', function (progressObj) { sendUpdateMessage('downloadProgress', progressObj) }) autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) { log.info(`已下载${event.version}`) var fs = require('fs-extra') var path = require('path') var fileName = event.downloadedFile var sourceFile = path.join(fileName) var destPath = path.join('C://售票软件', event.path) fs.copySync(sourceFile, destPath) log.info(`安装包移动完成`) ipcMain.on('updateNow', (e, arg) => { // some code here to handle event autoUpdater.quitAndInstall() }) sendUpdateMessage('isUpdateNow') }) // 执行自动更新检查 autoUpdater.checkForUpdates().catch(e => { sendUpdateMessage('error', e) }) // 取消退出软件后的自动更新 autoUpdater.autoInstallOnAppQuit = false } export function setMenu () { // const version = app.getVersion() let template = [ { label: '工具', submenu: [ { label: '强制刷新', role: 'forcereload' }, { label: '开发者工具', role: 'toggledevtools' } ] }, { label: '配置', role: 'config', click: function () { win.webContents.send('goConfig') } }, { label: '刷新', role: 'reload' } // { // label: '帮助', // submenu: [ // { // label: `Version ${version}`, // enabled: false // }, // { // label: '检查更新', // click: function () { // // require('electron').autoUpdater.quitAndInstall() // } // } // ] // } ] process.env.NODE_ENV === 'development' && (template.push( { label: 'Pos调试', click: function () { win.webContents.send('goPos') } } )) const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) }