diff --git a/build/icons/icon.icns b/build/icons/icon.icns new file mode 100644 index 0000000..ee72102 Binary files /dev/null and b/build/icons/icon.icns differ diff --git a/build/icons/icon.ico b/build/icons/icon.ico new file mode 100644 index 0000000..ee72102 Binary files /dev/null and b/build/icons/icon.ico differ diff --git a/package.json b/package.json index 3980ad3..071792e 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "electron-vue-admin", + "name": "sqhj-workbench-pc", "version": "0.0.1", - "author": "sky ", - "description": "An electron-vue project", + "author": "langye", + "description": "sqhj-workbench-pc", "license": "MIT", "main": "./dist/electron/main.js", "scripts": { @@ -27,8 +27,12 @@ "url": "http://127.0.0.1" } ], - "productName": "electron-vue-admin", - "appId": "org.Sky.electron-vue", + "productName": "内控信息化系统", + "appId": "org.langye.sqhj-workbench-pc", + "nsis": { + "guid": "org.langye.sqhj-workbench-pc", + "include": "build/installer.nsh" + }, "directories": { "output": "build" }, diff --git a/src/main/config/StaticPath.js b/src/main/config/StaticPath.js index a833ace..e7f54c3 100644 --- a/src/main/config/StaticPath.js +++ b/src/main/config/StaticPath.js @@ -14,5 +14,6 @@ if (process.env.NODE_ENV !== 'development') { export const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}` : `file://${__dirname}/index.html` export const loadingURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}/static/loader.html` : `file://${__static}/loader.html` export const libPath = process.env.libPath - -export const adminWebUri = process.env.NODE_ENV === 'development' ? "http://contract-sqhj-test.ali251.langye.net/admin_test/#/" : "http://contract-sqhj.ali251.langye.net/admin/#/" +export const remindURL = 'development' ? `http://localhost:${process.env.PORT}/#/remind` : `file://${__dirname}/index.html/#/remind` +//export const adminWebUri = process.env.NODE_ENV === 'development' ? "http://contract-sqhj-test.ali251.langye.net/admin_test/#/" : "http://contract-sqhj.ali251.langye.net/admin/#/" +export const adminWebUri = "http://contract-sqhj-test.ali251.langye.net/admin_test/#/" diff --git a/src/main/config/menu.js b/src/main/config/menu.js index add125d..3149a53 100644 --- a/src/main/config/menu.js +++ b/src/main/config/menu.js @@ -9,10 +9,6 @@ const menu = [ label: '快速重启', accelerator: 'F5', role: 'reload' - }, { - label: '退出', - accelerator: 'CmdOrCtrl+F4', - role: 'close' }] }, { @@ -54,6 +50,14 @@ const menu = [ info() } }] + }, + { + type: "separator" + }, + { + label: '退出', + accelerator: 'CmdOrCtrl+F4', + role: 'close' }] function info() { dialog.showMessageBox({ diff --git a/src/main/index.js b/src/main/index.js index cab8567..1d4e949 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,12 +1,14 @@ 'use strict' import { app } from 'electron' -import { initWindow } from './services/windowManager' +import { initWindow, initTrayIcon, tray } from './services/windowManager' import DisableButton from './config/DisableButton' import electronDevtoolsInstaller, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' - +import { init } from "./services/notices" function onAppReady () { initWindow() + initTrayIcon() + init() DisableButton.Disablef12() if (process.env.NODE_ENV === 'development') { electronDevtoolsInstaller(VUEJS_DEVTOOLS) @@ -24,6 +26,9 @@ app.isReady() ? onAppReady() : app.on('ready', onAppReady) app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors') app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + tray.destroy(); + } // 所有平台均为所有窗口关闭就退出软件 app.quit() }) diff --git a/src/main/services/ipcMain.js b/src/main/services/ipcMain.js index ac7aca9..83f11ad 100644 --- a/src/main/services/ipcMain.js +++ b/src/main/services/ipcMain.js @@ -4,11 +4,53 @@ import { winURL } from '../config/StaticPath' import downloadFile from './downloadFile' import Update from './checkupdate' import { updater } from './HotUpdater' -import { createAdminWindow, toggleMainWindowResizable, mainWindowResize } from "./windowManager" +import { createNotification } from "./notices" +import { + createAdminWindow, + toggleMainWindowResizable, + mainWindowResize, + setAdminViewBounds, + hideAdminView, + adminView, + setAdminCookie, + setTrayTitle, + destroyAdminView, + createAdminView, + remindWindow +} from "./windowManager" export default { Mainfunc(IsUseSysTitle) { const allUpdater = new Update(); + ipcMain.handle('create-notice', async (event, args) => { + const { title,body } = args + createNotification(title,body) + }) + ipcMain.handle('remind-win-toggle', async (event,status) => { + status ? remindWindow.show() : remindWindow.hide() + }) + ipcMain.handle("set-tray-title",async (event, title) => { + setTrayTitle(title) + }) + ipcMain.handle('set-admin-cookie', async (event, _) => { + setAdminCookie() + }) + ipcMain.handle('exec-admin-view-js',(event, js) => { + adminView?.webContents.executeJavaScript(js,true) + }) + ipcMain.handle('create-admin-view',async (event, _) => { + await createAdminView() + }) + ipcMain.handle('destroy-admin-view', async (event, _) => { + await destroyAdminView() + }) + ipcMain.handle('hide-admin-view', async (event, _) => { + await hideAdminView() + }) + ipcMain.handle('set-admin-view-bounds', (event, args) => { + const { x,y,width,height } = args + setAdminViewBounds(x,y,width,height) + }) ipcMain.handle('main-window-resize', (event, arg) => { mainWindowResize(arg.width, arg.height) }) diff --git a/src/main/services/notices.js b/src/main/services/notices.js index db7bfd2..3f7b1f7 100644 --- a/src/main/services/notices.js +++ b/src/main/services/notices.js @@ -1,4 +1,16 @@ import { Notification } from "electron"; +let notification = null; +export function init () { + notification = new Notification() +} export function createNotification(title,body) { + if (Notification.isSupported()) { + notification.title = title; + notification.body = body; + notification.silent=true + notification.show(); + } else { + console.log('notification 不支持') + } } diff --git a/src/main/services/windowManager.js b/src/main/services/windowManager.js index 16cef5f..e71028e 100644 --- a/src/main/services/windowManager.js +++ b/src/main/services/windowManager.js @@ -1,21 +1,84 @@ -import { BrowserWindow, Menu, app, session } from 'electron' +import { BrowserWindow, Menu, app, session, BrowserView, Tray, screen } from 'electron' import { platform } from "os" import menuconfig from '../config/menu' import { openDevTools, IsUseSysTitle, UseStartupChart } from '../config/const' import setIpc from './ipcMain' -import { winURL, loadingURL, adminWebUri } from '../config/StaticPath' +import { winURL, loadingURL, adminWebUri, libPath, remindURL } from '../config/StaticPath' import { createNotification } from "./notices" +import path from "path" var loadWindow = null var mainWindow = null setIpc.Mainfunc(IsUseSysTitle) var adminWindow = null +var tray = null +var adminView = null +var remindWindow = null export function toggleMainWindowResizable (status) { mainWindow.setResizable(status) } export function mainWindowResize (w,h) { mainWindow.setSize(w,h) } +export function setAdminViewBounds (x,y,width,height) { + adminView.setBounds({x,y,width,height}) +} +export async function hideAdminView () { + await adminView.setBounds({ + x: 0, + y: 0, + width: 0, + height: 0 + }) +} +function destroyAdminView () { + adminView.destroy() + adminView = null +} +function createAdminView () { + if (adminView) { + setAdminCookie() + return + } + adminView = new BrowserView() + mainWindow.setBrowserView(adminView) + mainWindow?.webContents.executeJavaScript("window.localStorage.getItem('token')",true).then((token) => { + session.defaultSession.cookies.set({ + url: adminWebUri, + name: "sqhj_workerbench_web_token", + value: token + }).then(_ => { + adminView.webContents.loadURL(adminWebUri) + }) + }) + adminView.webContents.on('dom-ready', () => { + adminView.webContents.executeJavaScript("window.hideTopBar()",true).then(r => {}).catch(err => { + console.log(err,'err') + }) + adminView.setAutoResize({ + width: true, + height: true, + horizontal: true, + vertical: false + }) + }) + if (process.env.NODE_ENV === 'development' || openDevTools) { + adminView.webContents.on('console-message', (e, level, message, line, sourceId) => { + console.log(`Message: ${JSON.stringify(message)}, Line: ${line}, Source Id: ${sourceId}`); + }); + } +} +export function setAdminCookie () { + mainWindow?.webContents.executeJavaScript("window.localStorage.getItem('token')",true).then((token) => { + session.defaultSession.cookies.set({ + url: adminWebUri, + name: "sqhj_workerbench_web_token", + value: token + }).then(_ => { + adminView?.webContents.reload() + }) + }) +} function createAdminWindow() { adminWindow = new BrowserWindow({ height: 800, @@ -49,6 +112,8 @@ function createAdminWindow() { adminWindow.webContents.once('dom-ready', () => { adminWindow.show() + + mainWindow.setBrowserView(adminWindow) if (process.env.NODE_ENV === 'development' || openDevTools) adminWindow.webContents.openDevTools(true) }) adminWindow.on('maximize', () => { @@ -60,18 +125,48 @@ function createAdminWindow() { adminWindow.on('closed', () => { adminWindow.destroy() adminWindow = null - mainWindow.show() }) } +function initTrayIcon () { + tray = new Tray(path.join(__static,"./ico.png")) + tray.setToolTip("江苏省宿迁环境监测中心") + const menu = Menu.buildFromTemplate(menuconfig) + tray.setContextMenu(menu) + tray.on('click', () => { + app.show() + }) +} +let trayTimer = null; +const blankPng = path.join(__static,"./blank.png") +const noticePng = path.join(__static,"./notice.png") +function noticeFlash () { + clearInterval(trayTimer) + let temp = false; + trayTimer = setInterval(() => { + if (temp) { + tray.setImage(blankPng) + } else { + tray.setImage(noticePng) + } + temp = !temp; + },800) +} +function setTrayTitle (title) { + if (process.platform === "darwin") { + tray.setTitle(title.toString()) + } else { + noticeFlash() + } +} function createMainWindow() { /** * Initial window options */ mainWindow = new BrowserWindow({ - height: 504, + height: 800, useContentSize: true, - width: 302, - resizable: false, + width: 1200, + resizable: true, show: false, frame: IsUseSysTitle, titleBarStyle: platform().includes('win32') ? 'default' : 'hidden', @@ -107,11 +202,11 @@ function createMainWindow() { Menu.setApplicationMenu(menu) mainWindow.loadURL(winURL) - mainWindow.webContents.once('dom-ready', () => { mainWindow.show() if (process.env.NODE_ENV === 'development' || openDevTools) mainWindow.webContents.openDevTools(true) if (UseStartupChart) loadWindow.destroy() + createAdminView() }) mainWindow.on('maximize', () => { mainWindow.webContents.send("w-max", true) @@ -121,10 +216,34 @@ function createMainWindow() { }) mainWindow.on('closed', () => { mainWindow = null + adminView = null + remindWindow = null app.quit(); }) } +function createRemindWindow () { + remindWindow = new BrowserWindow({ + width: 240, + height: 160, + frame: false, + backgroundColor: '#222', + skipTaskbar: true, + transparent: true, + resizable: false, + show: false, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + webSecurity: false, + experimentalFeatures: true, + devTools: process.env.NODE_ENV === 'development' || openDevTools, } + }) + remindWindow.loadURL(remindURL) + const screenSize = screen.getPrimaryDisplay().workAreaSize; + // 计算窗口的位置,使其显示在右下角 + remindWindow.setPosition(screenSize.width - 200, screenSize.height - 200); +} function loadingWindow() { loadWindow = new BrowserWindow({ width: 400, @@ -157,7 +276,15 @@ function initWindow() { return createMainWindow() } } + export { initWindow, - createAdminWindow + createAdminWindow, + adminView, + initTrayIcon, + tray, + setTrayTitle, + destroyAdminView, + createAdminView, + remindWindow } diff --git a/src/renderer/App.vue b/src/renderer/App.vue index bf81a4f..c9f9d41 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -9,7 +9,14 @@ \ No newline at end of file + diff --git a/src/renderer/icons/svg/book.svg b/src/renderer/icons/svg/book.svg new file mode 100644 index 0000000..d03dab6 --- /dev/null +++ b/src/renderer/icons/svg/book.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/icons/svg/contract.svg b/src/renderer/icons/svg/contract.svg new file mode 100644 index 0000000..cf84df8 --- /dev/null +++ b/src/renderer/icons/svg/contract.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/icons/svg/dashboard.svg b/src/renderer/icons/svg/dashboard.svg new file mode 100644 index 0000000..5317d37 --- /dev/null +++ b/src/renderer/icons/svg/dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/icons/svg/logo.svg b/src/renderer/icons/svg/logo.svg index 82e2e6e..1df9bee 100644 --- a/src/renderer/icons/svg/logo.svg +++ b/src/renderer/icons/svg/logo.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/renderer/icons/svg/logout.svg b/src/renderer/icons/svg/logout.svg new file mode 100644 index 0000000..1cf8cf9 --- /dev/null +++ b/src/renderer/icons/svg/logout.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/icons/svg/oa.svg b/src/renderer/icons/svg/oa.svg new file mode 100644 index 0000000..643840d --- /dev/null +++ b/src/renderer/icons/svg/oa.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/layout/components/AppMain.vue b/src/renderer/layout/components/AppMain.vue index 846bc93..009e9b9 100644 --- a/src/renderer/layout/components/AppMain.vue +++ b/src/renderer/layout/components/AppMain.vue @@ -1,14 +1,17 @@ diff --git a/src/renderer/layout/components/Navbar.vue b/src/renderer/layout/components/Navbar.vue index 163b185..d67575d 100644 --- a/src/renderer/layout/components/Navbar.vue +++ b/src/renderer/layout/components/Navbar.vue @@ -2,37 +2,47 @@
- +
{{ time }}
- -
- -
- -
-
- +
+ + + + + + - - - 返回首页 - - - 切换账号 - - - 退出登录 - - - +
+ + + + + + + + + + + + + + + + + + + + + + + +
@@ -59,8 +69,8 @@ const isMac = process.platform === "darwin" let timer = null onMounted(() => { timer = setInterval(() => { - time.value = format(new Date(), "yyyy/MM/dd HH:mm"); - }, 60000); + time.value = format(new Date(), "yyyy/MM/dd HH:mm:ss"); + }, 1000); }) onUnmounted(() => { clearInterval(timer); @@ -69,22 +79,11 @@ onUnmounted(() => { const { ToggleSideBar, sidebarStatus } = useAppStore() const sidebarComp = computed(() => sidebarStatus) -const toggleSideBar = () => { - ToggleSideBar() -} const { logOut, name } = useUserStore() +const userStore = useUserStore() const router = useRouter() -const userName = computed(() => name) -const logout = () => { - logOut().then(() => { - Message({ - message: "退出成功", - type: "success" - }); - router.push('/login') - }) -} +const userName = computed(() => userStore.name) \ No newline at end of file +::v-deep .el-badge__content.is-fixed { + top: 8px; + right: 8px; +} + diff --git a/src/renderer/layout/components/Sidebar/index.vue b/src/renderer/layout/components/Sidebar/index.vue index e39e269..841728e 100644 --- a/src/renderer/layout/components/Sidebar/index.vue +++ b/src/renderer/layout/components/Sidebar/index.vue @@ -1,15 +1,14 @@ diff --git a/src/renderer/layout/components/Sidebar/logo.vue b/src/renderer/layout/components/Sidebar/logo.vue index 1fb855d..c0904fc 100644 --- a/src/renderer/layout/components/Sidebar/logo.vue +++ b/src/renderer/layout/components/Sidebar/logo.vue @@ -1,11 +1,11 @@