├── src ├── electron-main │ ├── localConfig.json │ ├── tray │ │ ├── icone.ico │ │ └── index.js │ ├── windows │ │ ├── config.js │ │ ├── mainWindows.js │ │ ├── loginWindows.js │ │ ├── loadWindows.js │ │ ├── registerWindows.js │ │ └── resetPasswordWindows.js │ ├── modules │ │ ├── preload │ │ │ ├── load.js │ │ │ ├── register.js │ │ │ ├── resetPassword.js │ │ │ ├── main.js │ │ │ └── login.js │ │ └── controller │ │ │ └── main.js │ ├── shortcut │ │ └── index.js │ ├── main.js │ └── untils │ │ └── localFile.js ├── render │ ├── utils │ │ ├── index.ts │ │ └── imgLocalUrl.ts │ ├── styles │ │ ├── index.scss │ │ ├── element-theme.scss │ │ ├── layout.scss │ │ ├── main.scss │ │ ├── var.scss │ │ ├── element-var.scss │ │ └── clear.scss │ ├── assets │ │ ├── layout │ │ │ ├── home.png │ │ │ ├── logo.png │ │ │ ├── qq.png │ │ │ ├── user.png │ │ │ ├── avatar.png │ │ │ ├── review.png │ │ │ ├── history.png │ │ │ ├── operate.png │ │ │ ├── settings.png │ │ │ ├── shuaxin.png │ │ │ ├── top-close.png │ │ │ ├── top-info.png │ │ │ ├── top-mini.png │ │ │ ├── top-theme.png │ │ │ ├── top-utils.png │ │ │ ├── top-voice.png │ │ │ ├── close-bread.png │ │ │ ├── top-expand.png │ │ │ ├── top-close-dark.png │ │ │ ├── top-home-dark.png │ │ │ ├── top-info-dark.png │ │ │ ├── top-mini-dark.png │ │ │ ├── top-theme-dark.png │ │ │ ├── top-voice-dark.png │ │ │ ├── xiaoxitixing.png │ │ │ ├── top-expand-dark.png │ │ │ └── top-refresh-dark.png │ │ ├── load │ │ │ ├── close.png │ │ │ └── logo.png │ │ ├── login │ │ │ ├── logo.png │ │ │ ├── phone.png │ │ │ ├── yzm.png │ │ │ ├── _fuwu@2x.png │ │ │ ├── closeicon.png │ │ │ ├── duanxin@2x.png │ │ │ ├── password.png │ │ │ ├── selecttrue.png │ │ │ ├── username.png │ │ │ ├── zhuce@2x.png │ │ │ ├── diannao_1@2x.png │ │ │ ├── message-icon.png │ │ │ └── selectfalse.png │ │ └── vue.svg │ ├── store │ │ ├── index.ts │ │ └── modules │ │ │ ├── login.ts │ │ │ └── app.ts │ ├── hooks │ │ ├── useOpenByBrowser.ts │ │ ├── useCache.ts │ │ ├── watchTheme.ts │ │ └── watchRouter.ts │ ├── api │ │ └── login │ │ │ ├── types.ts │ │ │ └── index.ts │ ├── views │ │ ├── news │ │ │ └── index.vue │ │ ├── notice │ │ │ └── index.vue │ │ ├── review │ │ │ └── index.vue │ │ ├── user │ │ │ └── index.vue │ │ ├── settings │ │ │ └── index.vue │ │ ├── review-history │ │ │ └── index.vue │ │ ├── operate │ │ │ └── index.vue │ │ ├── home │ │ │ └── index.vue │ │ ├── load │ │ │ ├── index.vue │ │ │ └── old.vue │ │ └── login │ │ │ ├── login-message.vue │ │ │ ├── index.vue │ │ │ ├── login-password.vue │ │ │ ├── resetPassword │ │ │ └── index.vue │ │ │ └── register │ │ │ └── index.vue │ ├── layout │ │ ├── AppMain.vue │ │ ├── navBar │ │ │ ├── Navbar.vue │ │ │ ├── Navigation.vue │ │ │ ├── Breadcrumb.vue │ │ │ └── TopHeader.vue │ │ ├── sideBar │ │ │ ├── Tip.vue │ │ │ ├── Sidebar.vue │ │ │ ├── SidebarItem.vue │ │ │ └── Logo.vue │ │ └── index.vue │ ├── service │ │ └── axios │ │ │ ├── config.ts │ │ │ ├── index.ts │ │ │ └── service.ts │ └── router │ │ └── index.ts ├── auto-imports.d.ts ├── vite-env.d.ts ├── main.ts ├── components.d.ts └── App.vue ├── .vscode └── extensions.json ├── public ├── icon.ico ├── exeimg.ico ├── icone.ico └── music.ico ├── auto-imports.d.ts ├── .env.production ├── .env.development ├── tsconfig.node.json ├── README.md ├── .gitignore ├── index.html ├── types └── global │ └── global.d.ts ├── tsconfig.json ├── package.json ├── components.d.ts └── vite.config.ts /src/electron-main/localConfig.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /src/render/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const useDemo=()=>{ 2 | 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/public/icon.ico -------------------------------------------------------------------------------- /public/exeimg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/public/exeimg.ico -------------------------------------------------------------------------------- /public/icone.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/public/icone.ico -------------------------------------------------------------------------------- /public/music.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/public/music.ico -------------------------------------------------------------------------------- /auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | export {} 3 | declare global { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | export {} 3 | declare global { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/render/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import 'var'; 2 | @import 'main'; 3 | @import 'clear'; 4 | @import 'element-var'; -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | // 环境 2 | NODE_ENV=production 3 | # 接口前缀 4 | VITE_API_BASEPATH='pro' 5 | # 打包路径 6 | VITE_BASE_PATH='./' 7 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | // 环境 2 | NODE_ENV=development 3 | # 接口前缀 4 | VITE_API_BASEPATH='dev' 5 | # 打包路径 6 | VITE_BASE_PATH='/' 7 | -------------------------------------------------------------------------------- /src/electron-main/tray/icone.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/electron-main/tray/icone.ico -------------------------------------------------------------------------------- /src/render/assets/layout/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/home.png -------------------------------------------------------------------------------- /src/render/assets/layout/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/logo.png -------------------------------------------------------------------------------- /src/render/assets/layout/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/qq.png -------------------------------------------------------------------------------- /src/render/assets/layout/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/user.png -------------------------------------------------------------------------------- /src/render/assets/load/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/load/close.png -------------------------------------------------------------------------------- /src/render/assets/load/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/load/logo.png -------------------------------------------------------------------------------- /src/render/assets/login/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/logo.png -------------------------------------------------------------------------------- /src/render/assets/login/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/phone.png -------------------------------------------------------------------------------- /src/render/assets/login/yzm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/yzm.png -------------------------------------------------------------------------------- /src/render/assets/layout/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/avatar.png -------------------------------------------------------------------------------- /src/render/assets/layout/review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/review.png -------------------------------------------------------------------------------- /src/render/assets/layout/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/history.png -------------------------------------------------------------------------------- /src/render/assets/layout/operate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/operate.png -------------------------------------------------------------------------------- /src/render/assets/layout/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/settings.png -------------------------------------------------------------------------------- /src/render/assets/layout/shuaxin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/shuaxin.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-close.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-info.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-mini.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-theme.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-utils.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-utils.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-voice.png -------------------------------------------------------------------------------- /src/render/assets/login/_fuwu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/_fuwu@2x.png -------------------------------------------------------------------------------- /src/render/assets/login/closeicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/closeicon.png -------------------------------------------------------------------------------- /src/render/assets/login/duanxin@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/duanxin@2x.png -------------------------------------------------------------------------------- /src/render/assets/login/password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/password.png -------------------------------------------------------------------------------- /src/render/assets/login/selecttrue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/selecttrue.png -------------------------------------------------------------------------------- /src/render/assets/login/username.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/username.png -------------------------------------------------------------------------------- /src/render/assets/login/zhuce@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/zhuce@2x.png -------------------------------------------------------------------------------- /src/render/assets/layout/close-bread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/close-bread.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-expand.png -------------------------------------------------------------------------------- /src/render/assets/login/diannao_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/diannao_1@2x.png -------------------------------------------------------------------------------- /src/render/assets/login/message-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/message-icon.png -------------------------------------------------------------------------------- /src/render/assets/login/selectfalse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/login/selectfalse.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-close-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-close-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-home-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-home-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-info-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-info-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-mini-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-mini-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-theme-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-voice-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-voice-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/xiaoxitixing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/xiaoxitixing.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-expand-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-expand-dark.png -------------------------------------------------------------------------------- /src/render/assets/layout/top-refresh-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arvin-Cui/Vue3-Electron21-Vite2/HEAD/src/render/assets/layout/top-refresh-dark.png -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /src/render/store/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import { createPinia } from 'pinia' 3 | 4 | const store = createPinia() 5 | 6 | export const setupStore = (app: App) => { 7 | app.use(store) 8 | } 9 | 10 | export { store } 11 | -------------------------------------------------------------------------------- /src/render/styles/element-theme.scss: -------------------------------------------------------------------------------- 1 | @forward 'element-plus/theme-chalk/src/common/var.scss' with ( 2 | $colors: ( 3 | 'primary': ( 4 | 'base': #F44311 , 5 | ), 6 | ), 7 | ); 8 | //// 所有样式: 9 | //@use "element-plus/theme-chalk/src/index.scss" as *; -------------------------------------------------------------------------------- /src/render/hooks/useOpenByBrowser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 脱离客户端 使用浏览器打开窗口 3 | */ 4 | 5 | export const useOpenByBrowser=()=>{ 6 | const openByBrowser=(url:string)=>{ 7 | window.electronAPI.openByBrowser(url) 8 | } 9 | return { 10 | openByBrowser 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/render/api/login/types.ts: -------------------------------------------------------------------------------- 1 | export type UserLoginType = { 2 | username: string 3 | password: string 4 | } 5 | 6 | export type UserType = { 7 | username: string 8 | password: string 9 | role: string 10 | roleId: string 11 | permissions: string | string[] 12 | } 13 | -------------------------------------------------------------------------------- /src/electron-main/windows/config.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const ACHEME = "file"; 3 | const path=require('path') 4 | // const LOAD_URL = `${ACHEME}://${ __dirname}/index.html`; 5 | const LOAD_URL=`file://${path.join(__dirname, '../../../dist/index.html')}` 6 | module.exports={ 7 | ACHEME, 8 | LOAD_URL 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/views/notice/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 5 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/views/review/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 5 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/views/user/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 5 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/views/settings/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 5 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/hooks/useCache.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 配置浏览器本地存储的方式,可直接存储对象数组。 3 | */ 4 | 5 | import WebStorageCache from 'web-storage-cache' 6 | 7 | type CacheType = 'sessionStorage' | 'localStorage' 8 | 9 | export const useCache = (type: CacheType = 'sessionStorage') => { 10 | const wsCache: WebStorageCache = new WebStorageCache({ 11 | storage: type 12 | }) 13 | 14 | return { 15 | wsCache 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/render/views/review-history/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 5 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /src/render/layout/AppMain.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/render/layout/navBar/Navbar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | // 引入全局样式 4 | import '@/render/styles/index.scss' 5 | // 引入状态管理 6 | import { setupStore } from '@/render/store' 7 | // 引入路由 8 | import {setupRouter} from "@/render/router"; 9 | 10 | 11 | // 创建实例 12 | const setupAll = async () => { 13 | const app = createApp(App) 14 | setupStore(app) 15 | setupRouter(app) 16 | app.mount('#app') 17 | } 18 | 19 | setupAll() 20 | -------------------------------------------------------------------------------- /src/render/views/operate/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | Success 5 | 6 | 7 | 8 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /src/render/layout/navBar/Navigation.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /src/render/styles/layout.scss: -------------------------------------------------------------------------------- 1 | @import "element-theme"; 2 | $sideBarExpandWidth:210px; 3 | $sideBarWidth:64px; 4 | $sideBarLogoExpandHeight:235px; 5 | $sideBarLogoHeight:180px; 6 | $topHeaderHeight:64px; 7 | $navigationHeight:38px; 8 | :export { 9 | sideBarWidth: $sideBarWidth; 10 | sideBarLogoHeight:$sideBarLogoHeight; 11 | sideBarLogoExpandHeight:$sideBarLogoExpandHeight; 12 | topHeaderHeight:$topHeaderHeight; 13 | navigationHeight:$navigationHeight 14 | } -------------------------------------------------------------------------------- /src/render/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Vite + Vue + TS 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/render/styles/main.scss: -------------------------------------------------------------------------------- 1 | body{ 2 | height: 100%; 3 | user-select: none; 4 | -webkit-app-region: drag; 5 | } 6 | 7 | .wraper-container-no-drag{ 8 | -webkit-app-region: no-drag; 9 | } 10 | .wraper-container-drag{ 11 | -webkit-app-region: drag; 12 | } 13 | .wraper-container{ 14 | 15 | } 16 | .wraper-center{ 17 | position: fixed; 18 | left: 50%; 19 | top: 50%; 20 | transform: translate(-50%,-50%); 21 | } 22 | .wraper-center__absolute{ 23 | position: absolute; 24 | left: 50%; 25 | top: 50%; 26 | transform: translate(-50%,-50%); 27 | } -------------------------------------------------------------------------------- /src/render/api/login/index.ts: -------------------------------------------------------------------------------- 1 | import request from '@/render/service/axios' 2 | import type { UserType } from './types' 3 | export const loginApi = (data: Partial): Promise> => { 4 | return request.post({ url: '/auth/manage/login/pwd', data }) 5 | } 6 | 7 | // export const loginOutApi = (): Promise => { 8 | // return request.get({ url: '/user/loginOut' }) 9 | // } 10 | // 11 | // export const getUserListApi = ({ params }: AxiosConfig) => { 12 | // return request.get<{ 13 | // total: number 14 | // list: UserType[] 15 | // }>({ url: '/user/list', params }) 16 | // } 17 | -------------------------------------------------------------------------------- /src/components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/core/pull/3399 4 | import '@vue/runtime-core' 5 | 6 | export {} 7 | 8 | declare module '@vue/runtime-core' { 9 | export interface GlobalComponents { 10 | ElButton: typeof import('element-plus/es')['ElButton'] 11 | ElIcon: typeof import('element-plus/es')['ElIcon'] 12 | ElSwitch: typeof import('element-plus/es')['ElSwitch'] 13 | RouterLink: typeof import('vue-router')['RouterLink'] 14 | RouterView: typeof import('vue-router')['RouterView'] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/electron-main/modules/preload/main.js: -------------------------------------------------------------------------------- 1 | const { contextBridge, ipcRenderer } = require('electron') 2 | const setTitle=async (title)=>{ 3 | let result= await ipcRenderer.invoke('on-settitle-event', title) 4 | } 5 | // 浏览器打开页面 6 | const openByBrowser=(url)=>{ 7 | ipcRenderer.invoke('on-useOpenByBrowser-event',url) 8 | } 9 | // 页面全屏 缩小 关闭 10 | const setScreen=(value)=>{ 11 | ipcRenderer.invoke('on-setScreen-event',value) 12 | } 13 | 14 | contextBridge.exposeInMainWorld('electronAPI', { 15 | setTitle, 16 | openByBrowser, 17 | setScreen, 18 | ipcRenderer: { ...ipcRenderer, on: ipcRenderer.on.bind(ipcRenderer) } 19 | }) 20 | -------------------------------------------------------------------------------- /src/electron-main/modules/preload/login.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { contextBridge, ipcRenderer } = require('electron') 3 | // @ts-ignore 4 | const setLogin=async (content)=>{ 5 | let result= await ipcRenderer.invoke('on-setlogin-event', content) 6 | } 7 | const openRegister=async (content)=>{ 8 | let result= await ipcRenderer.invoke('on-openRegister-event', content) 9 | } 10 | const openRestPassword=async (content)=>{ 11 | let result= await ipcRenderer.invoke('on-openRestPassword-event', content) 12 | } 13 | contextBridge.exposeInMainWorld('electronAPI', { 14 | openRestPassword, 15 | openRegister, 16 | setLogin, 17 | ipcRenderer, 18 | }) 19 | -------------------------------------------------------------------------------- /types/global/global.d.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | declare global { 3 | interface Window { 4 | electronAPI?: any;//全局变量名 5 | } 6 | interface AxiosConfig { 7 | params?: any 8 | data?: any 9 | url?: string 10 | method?: AxiosMethod 11 | headersType?: string 12 | responseType?: AxiosResponseType 13 | } 14 | 15 | interface IResponse { 16 | code: string 17 | data: T extends any ? T : T & any 18 | } 19 | type AxiosHeaders = 20 | | 'application/json' 21 | | 'application/x-www-form-urlencoded' 22 | | 'multipart/form-data' 23 | } 24 | declare const window: any; 25 | 26 | 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["src/*"] 12 | }, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "esModuleInterop": true, 16 | "lib": ["ESNext", "DOM"], 17 | "skipLibCheck": true, 18 | "noEmit": true 19 | }, 20 | // "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 21 | "include": ["src/**/*", "types/**/*.d.ts", "mock/**/*.ts","types/global/global.d.ts"], 22 | "references": [{ "path": "./tsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /src/render/service/axios/config.ts: -------------------------------------------------------------------------------- 1 | const config: { 2 | base_url: { 3 | dev: string 4 | pro: string 5 | } 6 | result_code: number | string 7 | default_headers: AxiosHeaders; 8 | request_timeout: number 9 | } = { 10 | /** 11 | * api请求基础路径 12 | */ 13 | base_url: { 14 | // 开发环境接口前缀 15 | dev: '/api', 16 | 17 | // 打包生产环境接口前缀 18 | pro: 'https://sports.api.zxdev.top/api', 19 | }, 20 | 21 | /** 22 | * 接口成功返回状态码 23 | */ 24 | result_code: '0000', 25 | 26 | /** 27 | * 接口请求超时时间 28 | */ 29 | request_timeout: 60000, 30 | 31 | /** 32 | * 默认接口请求类型 33 | * 可选值:application/x-www-form-urlencoded multipart/form-data 34 | */ 35 | default_headers: 'application/json' 36 | } 37 | 38 | export { config } 39 | -------------------------------------------------------------------------------- /src/electron-main/shortcut/index.js: -------------------------------------------------------------------------------- 1 | const {app, globalShortcut } = require('electron') 2 | 3 | const initShortCut=()=>{ 4 | // globalShortcut.register('CommandOrControl+X', () => { 5 | // console.log('CommandOrControl+X is pressed') 6 | // }) 7 | // globalShortcut.register('g', () => { 8 | // console.log('g') 9 | // if(global.mainWindow){ 10 | // global.mainWindow.webContents.send('on-shortcut-event','g') 11 | // } 12 | // 13 | // }) 14 | } 15 | const unInstallShortCut=()=>{ 16 | // 注销快捷键 17 | globalShortcut.unregister('CommandOrControl+X') 18 | globalShortcut.unregister('g') 19 | // 注销所有快捷键 20 | globalShortcut.unregisterAll() 21 | } 22 | module.exports={ 23 | initShortCut, 24 | unInstallShortCut 25 | } 26 | -------------------------------------------------------------------------------- /src/electron-main/tray/index.js: -------------------------------------------------------------------------------- 1 | const { app, Menu, Tray,nativeImage } = require('electron') 2 | const path=require('path') 3 | let appIcon = null 4 | const initTray=()=>{ 5 | const iconPath = path.join(__dirname, '/icone.ico').replace('/\\/g','\\\\'); 6 | appIcon = new Tray(nativeImage.createFromPath(iconPath)) 7 | appIcon.setToolTip('This is my application.') 8 | const contextMenu = Menu.buildFromTemplate([ 9 | { label: '退出',type: 'radio', click:()=>{ 10 | app.quit() 11 | }}, 12 | { label: 'Item2', type: 'radio' } 13 | ]) 14 | 15 | // Make a change to the context menu 16 | contextMenu.items[1].checked = false 17 | 18 | // Call this again for Linux because we modified the context menu 19 | appIcon.setContextMenu(contextMenu) 20 | } 21 | 22 | module.exports={ 23 | initTray 24 | } 25 | -------------------------------------------------------------------------------- /src/render/hooks/watchTheme.ts: -------------------------------------------------------------------------------- 1 | import {computed, onMounted, ref, watchEffect} from 'vue' 2 | import {useAppStore} from "@/render/store/modules/app"; 3 | import {router} from "@/render/router"; 4 | export const watchTheme=()=>{ 5 | const appStore = useAppStore() 6 | let isDark=computed(()=>{ 7 | return appStore.isDark 8 | }) 9 | watchEffect(()=>{ 10 | if(isDark.value){ 11 | console.log('223') 12 | document.body.className = 'dark'; 13 | // document.documentElement.style.setProperty('--dark-bg-color','red') 14 | }else{ 15 | console.log('323213') 16 | document.body.className = ''; 17 | // document.documentElement.style.setProperty('--dark-bg-color','red') 18 | } 19 | console.log(isDark.value) 20 | }) 21 | } -------------------------------------------------------------------------------- /src/render/styles/var.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --menu-bg-color: #262F39; // 菜单背景色 3 | --top-header-back-color:#FFFFFF; // 头部操作栏背景色 4 | --navigation-back-color:linear-gradient(180deg, #A2ABB9 0%, #B4BCC8 100%); // 路由导航栏背景色 5 | --breadcrumb-back-color:rgba(0,0,0,0.3); // 面包屑背景色 6 | --breadcrumb-active-back-color:#F5F6F7; // 面包屑激活背景色 7 | --breadcrumb-text-color:#FFFFFF;// 面包屑字体色 8 | --breadcrumb-active-text-color:#3E3A39;// 面包屑激活字体色 9 | --menu-text-color:#FFFFFF; // 菜单栏文字颜色 10 | --top-header-time-color:#303741; // 顶部时间颜色 11 | } 12 | .dark{ 13 | --menu-bg-color: #1B1E25; 14 | --top-header-back-color:#1B1E25; 15 | --navigation-back-color:#35353C ; 16 | --breadcrumb-back-color:#20232B; 17 | --breadcrumb-text-color:#A3A6AB; 18 | --breadcrumb-active-back-color:#131218; 19 | --breadcrumb-active-text-color:#FFFFFF; 20 | --menu-text-color:#C7CED2 ; 21 | --top-header-time-color:#BCBCBC; 22 | } 23 | -------------------------------------------------------------------------------- /src/render/styles/element-var.scss: -------------------------------------------------------------------------------- 1 | $menuActiveBackground:#F44311; //菜单选中背景色 2 | $menuActiveTextColor:#FFFFFF; //菜单选中文字颜色色 3 | //$menuTextColor:#FFFFFF; // 菜单文字颜色 4 | .el-menu{ 5 | border-right:none !important; 6 | } 7 | .el-menu-item.is-active{ 8 | background: $menuActiveBackground !important; 9 | color: $menuActiveTextColor !important; 10 | } 11 | .el-menu-item:hover{ 12 | background: $menuActiveBackground !important; 13 | color: $menuActiveTextColor !important; 14 | } 15 | .el-menu-item{ 16 | color: var(--menu-text-color) !important; 17 | } 18 | .el-sub-menu{ 19 | .el-menu-item,.el-menu-item-group__title{ 20 | background: var(--menu-bg-color); 21 | } 22 | .el-sub-menu__title{ 23 | color: var(--menu-text-color) !important; 24 | background: var(--menu-bg-color); 25 | } 26 | .el-sub-menu__title:hover{ 27 | background: $menuActiveBackground !important; 28 | color: $menuActiveTextColor !important; 29 | } 30 | } -------------------------------------------------------------------------------- /src/render/service/axios/index.ts: -------------------------------------------------------------------------------- 1 | import { service } from './service' 2 | 3 | import { config } from './config' 4 | 5 | const { default_headers } = config 6 | 7 | const request = (option: any) => { 8 | const { url, method, params, data, headersType, responseType } = option 9 | return service({ 10 | url: url, 11 | method, 12 | params, 13 | data, 14 | responseType: responseType, 15 | headers: { 16 | 'Content-Type': headersType || default_headers 17 | } 18 | }) 19 | } 20 | export default { 21 | get: (option: any) => { 22 | return request({ method: 'get', ...option }) as unknown as T 23 | }, 24 | post: (option: any) => { 25 | return request({ method: 'post', ...option }) as unknown as T 26 | }, 27 | delete: (option: any) => { 28 | return request({ method: 'delete', ...option }) as unknown as T 29 | }, 30 | put: (option: any) => { 31 | return request({ method: 'put', ...option }) as unknown as T 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/render/store/modules/login.ts: -------------------------------------------------------------------------------- 1 | // stores/app.ts 2 | import { defineStore } from 'pinia' 3 | import {useCache} from "@/render/hooks/useCache"; 4 | 5 | const { wsCache } = useCache() 6 | 7 | interface LoginState { 8 | loginSetting:{ 9 | autoLogin:Boolean, 10 | rememberPassword:false 11 | } 12 | } 13 | export const useLoginStore = defineStore('login', { 14 | state: ():LoginState => { 15 | return { 16 | loginSetting:{ 17 | autoLogin:false, 18 | rememberPassword:false, 19 | } 20 | } 21 | }, 22 | actions: { 23 | setLoginSetting(e:String) { 24 | // @ts-ignore 25 | const bol=this.loginSetting[e] 26 | // @ts-ignore 27 | this.loginSetting[e]=!bol 28 | console.log(this.loginSetting) 29 | // wsCache.set('test','111') 30 | // const res= wsCache.get('test') 31 | // this.count++ 32 | }, 33 | }, 34 | }) 35 | -------------------------------------------------------------------------------- /src/render/styles/clear.scss: -------------------------------------------------------------------------------- 1 | // base.css 2 | /* 清除默认样式的代码 */ 3 | /* 去除常见标签默认的 margin 和 padding */ 4 | body, 5 | h1, 6 | h2, 7 | h3, 8 | h4, 9 | h5, 10 | h6, 11 | p, 12 | ul, 13 | ol, 14 | li, 15 | dl, 16 | dt, 17 | dd, 18 | input { 19 | margin: 0; 20 | padding: 0; 21 | } 22 | 23 | /* 內减模式 */ 24 | * { 25 | box-sizing: border-box; 26 | } 27 | 28 | /* 设置网页统一的字体大小、行高、字体系列相关属性 */ 29 | body { 30 | font: 16px/1.5 'Helvetica Neue', Helvetica, Arial, 'Microsoft Yahei', 'Hiragino Sans GB', 31 | 'Heiti SC', 'WenQuanYi Micro Hei', sans-serif; 32 | color: #333; 33 | } 34 | 35 | /* 去除列表默认样式 */ 36 | ul, 37 | ol { 38 | list-style: none; 39 | } 40 | 41 | /* 去除默认的倾斜效果 */ 42 | em, 43 | i { 44 | font-style: normal; 45 | } 46 | 47 | /* 去除a标签默认下划线,并设置默认文字颜色 */ 48 | a { 49 | text-decoration: none; 50 | color: #333; 51 | } 52 | 53 | /* 设置img的垂直对齐方式为居中对齐,去除img默认下间隙 */ 54 | img { 55 | vertical-align: middle; 56 | } 57 | 58 | /* 去除input默认样式 */ 59 | input { 60 | border: none; 61 | outline: none; 62 | color: #333; 63 | } 64 | 65 | /* 左浮动 */ 66 | .fl { 67 | float: left; 68 | } 69 | 70 | /* 右浮动 */ 71 | .fr { 72 | float: right; 73 | } 74 | 75 | /* 双伪元素清除法 */ 76 | .clearfix::before, 77 | .clearfix::after { 78 | content: ''; 79 | display: table; 80 | } 81 | .clearfix::after { 82 | clear: both; 83 | } 84 | -------------------------------------------------------------------------------- /src/render/layout/sideBar/Tip.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 987768887 7 | 8 | 9 | 10 | 24 | 25 | -------------------------------------------------------------------------------- /src/electron-main/windows/mainWindows.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { LOAD_URL }=require('./config.js'); 3 | const path = require('path') 4 | const isDev = require('electron-is-dev') 5 | //客户端尺寸位置记忆插件 6 | const windowStateKeeper = require('electron-window-state'); 7 | const mainWinURL = 8 | isDev ? `http://localhost:4000/#/` 9 | : `${LOAD_URL}#`; 10 | 11 | const createMainWindow=(BrowserWindow)=>{ 12 | // 默认窗口尺寸 13 | let mainWindowState = windowStateKeeper({ 14 | defaultWidth: 1000, 15 | defaultHeight: 800 16 | }); 17 | const win = new BrowserWindow({ 18 | 'x': mainWindowState.x, 19 | 'y': mainWindowState.y, 20 | 'width': mainWindowState.width, 21 | 'height': mainWindowState.height, 22 | focusable:true, 23 | show:false, 24 | frame:false, 25 | webPreferences: { 26 | webSecurity: true, 27 | nodeIntegration: true, 28 | contextIsolation: true, 29 | // 渲染器进程到主进程通信 定义预加载的ts 30 | preload: path.resolve(__dirname, '../modules/preload/main.js') 31 | } 32 | }) 33 | // 加载页面地址 线上内网可切换地址 34 | win.loadURL(mainWinURL) 35 | // 管理客户端尺寸位置记忆插件 36 | mainWindowState.manage(win); 37 | // 开发者工具 38 | win.webContents.openDevTools() 39 | // 优雅打开界面 40 | win.on('ready-to-show',()=>{ 41 | win.show() 42 | }) 43 | global.mainWindow=win 44 | } 45 | 46 | module.exports={ 47 | createMainWindow 48 | } 49 | -------------------------------------------------------------------------------- /src/render/views/home/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{count}} 4 | 操作 5 | 6 | 7 | 8 | 48 | 49 | 52 | -------------------------------------------------------------------------------- /src/electron-main/windows/loginWindows.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { LOAD_URL }=require('./config.js'); 3 | const path = require('path') 4 | const isDev = require('electron-is-dev') 5 | // //客户端尺寸位置记忆插件 6 | // const windowStateKeeper = require('electron-window-state'); 7 | const loginWinURL = 8 | isDev? `http://localhost:4000/#/login` 9 | : `${LOAD_URL}#login`; 10 | 11 | const createLoginWindow=(BrowserWindow)=>{ 12 | 13 | // // 默认窗口尺寸 14 | // let mainWindowState = windowStateKeeper({ 15 | // defaultWidth: 826, 16 | // defaultHeight: 528 17 | // }); 18 | const win = new BrowserWindow({ 19 | // 'x': mainWindowState.x, 20 | // 'y': mainWindowState.y, 21 | 'width': 826, 22 | 'height': 528, 23 | transparent: true, 24 | backgroundColor: '#00000000', 25 | focusable:true, 26 | show:false, 27 | frame:false, 28 | resizable:false, 29 | webPreferences: { 30 | webSecurity: false, 31 | nodeIntegration: true, 32 | contextIsolation: true, 33 | // 渲染器进程到主进程通信 定义预加载的界面ts 34 | preload: path.resolve(__dirname, '../modules/preload/login.js') 35 | } 36 | }) 37 | // 加载页面地址 线上内网可切换地址 38 | win.loadURL(loginWinURL) 39 | // // 管理客户端尺寸位置记忆插件 40 | // mainWindowState.manage(win); 41 | // 开发者工具 42 | // win.webContents.openDevTools() 43 | // 优雅打开界面 44 | win.on('ready-to-show',()=>{ 45 | win.show() 46 | }) 47 | 48 | } 49 | 50 | module.exports={ 51 | createLoginWindow 52 | } 53 | -------------------------------------------------------------------------------- /src/electron-main/windows/loadWindows.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { LOAD_URL }=require('./config.js'); 3 | const path = require('path') 4 | const isDev = require('electron-is-dev') 5 | //客户端尺寸位置记忆插件 6 | const windowStateKeeper = require('electron-window-state'); 7 | const url = require("url"); 8 | const loadWinURL = 9 | isDev? `http://localhost:4000/#/load` 10 | : `${LOAD_URL}#load`; 11 | 12 | const createLoadWindow=(BrowserWindow)=>{ 13 | 14 | // // 默认窗口尺寸 15 | // let mainWindowState = windowStateKeeper({ 16 | // defaultWidth: 1000, 17 | // defaultHeight: 800 18 | // }); 19 | const win = new BrowserWindow({ 20 | // 'x': mainWindowState.x, 21 | // 'y': mainWindowState.y, 22 | 'width': 480, 23 | 'height':310, 24 | focusable:true, 25 | transparent: true, 26 | backgroundColor: '#00000000', 27 | show:false, 28 | frame:false, 29 | resizable:false, 30 | webPreferences: { 31 | webSecurity: false, 32 | nodeIntegration: true, 33 | contextIsolation: true, 34 | // 渲染器进程到主进程通信 定义预加载的界面ts 35 | preload: path.resolve(__dirname, '../modules/preload/load.js') 36 | } 37 | }) 38 | // 加载页面地址 线上内网可切换地址 39 | win.loadURL(`${loadWinURL}`) 40 | // // 管理客户端尺寸位置记忆插件 41 | // mainWindowState.manage(win); 42 | // // 开发者工具 43 | // win.webContents.openDevTools() 44 | // 优雅打开界面 45 | win.on('ready-to-show',()=>{ 46 | win.show() 47 | }) 48 | 49 | } 50 | 51 | module.exports={ 52 | createLoadWindow 53 | } 54 | -------------------------------------------------------------------------------- /src/electron-main/windows/registerWindows.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { LOAD_URL }=require('./config.js'); 3 | const path = require('path') 4 | const isDev = require('electron-is-dev') 5 | // //客户端尺寸位置记忆插件 6 | // const windowStateKeeper = require('electron-window-state'); 7 | const registerWinURL = 8 | isDev? `http://localhost:4000/#/register` 9 | : `${LOAD_URL}#register`; 10 | 11 | const createRegisterWindow=(BrowserWindow)=>{ 12 | 13 | // // 默认窗口尺寸 14 | // let mainWindowState = windowStateKeeper({ 15 | // defaultWidth: 826, 16 | // defaultHeight: 528 17 | // }); 18 | const win = new BrowserWindow({ 19 | // 'x': mainWindowState.x, 20 | // 'y': mainWindowState.y, 21 | 'width': 600, 22 | 'height': 740, 23 | transparent: true, 24 | backgroundColor: '#00000000', 25 | focusable:true, 26 | show:false, 27 | frame:false, 28 | resizable:false, 29 | webPreferences: { 30 | webSecurity: false, 31 | nodeIntegration: true, 32 | contextIsolation: true, 33 | // 渲染器进程到主进程通信 定义预加载的界面ts 34 | preload: path.resolve(__dirname, '../modules/preload/register.js') 35 | } 36 | }) 37 | // 加载页面地址 线上内网可切换地址 38 | win.loadURL(registerWinURL) 39 | // // 管理客户端尺寸位置记忆插件 40 | // mainWindowState.manage(win); 41 | // //开发者工具 42 | // win.webContents.openDevTools() 43 | // 优雅打开界面 44 | win.on('ready-to-show',()=>{ 45 | win.show() 46 | }) 47 | 48 | } 49 | 50 | module.exports={ 51 | createRegisterWindow 52 | } 53 | -------------------------------------------------------------------------------- /src/electron-main/windows/resetPasswordWindows.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const { LOAD_URL }=require('./config.js'); 3 | const path = require('path') 4 | const isDev = require('electron-is-dev') 5 | // //客户端尺寸位置记忆插件 6 | // const windowStateKeeper = require('electron-window-state'); 7 | const resetPasswordWinURL = 8 | isDev? `http://localhost:4000/#/resetPassword` 9 | : `${LOAD_URL}#resetPassword`; 10 | 11 | const createResetPasswordWindow=(BrowserWindow)=>{ 12 | 13 | // // 默认窗口尺寸 14 | // let mainWindowState = windowStateKeeper({ 15 | // defaultWidth: 826, 16 | // defaultHeight: 528 17 | // }); 18 | const win = new BrowserWindow({ 19 | // 'x': mainWindowState.x, 20 | // 'y': mainWindowState.y, 21 | 'width': 490, 22 | 'height': 492, 23 | transparent: true, 24 | backgroundColor: '#00000000', 25 | focusable:true, 26 | show:false, 27 | frame:false, 28 | resizable:false, 29 | webPreferences: { 30 | webSecurity: false, 31 | nodeIntegration: true, 32 | contextIsolation: true, 33 | // 渲染器进程到主进程通信 定义预加载的界面ts 34 | preload: path.resolve(__dirname, '../modules/preload/resetPassword.js') 35 | } 36 | }) 37 | // 加载页面地址 线上内网可切换地址 38 | win.loadURL(resetPasswordWinURL) 39 | // // 管理客户端尺寸位置记忆插件 40 | // mainWindowState.manage(win); 41 | // //开发者工具 42 | // win.webContents.openDevTools() 43 | // 优雅打开界面 44 | win.on('ready-to-show',()=>{ 45 | win.show() 46 | }) 47 | 48 | } 49 | 50 | module.exports={ 51 | createResetPasswordWindow 52 | } 53 | -------------------------------------------------------------------------------- /src/electron-main/main.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const {InitController} =require('./modules/controller/main.js') 3 | const {app,BrowserWindow, Tray, Menu} =require ('electron') 4 | const {createMainWindow}=require( './windows/mainWindows.js') 5 | const {createLoginWindow}=require( './windows/loginWindows.js') 6 | const {createLoadWindow}=require( './windows/loadWindows.js') 7 | const {initTray}=require('./tray/index.js') 8 | const {initShortCut,unInstallShortCut}=require('./shortcut/index') 9 | app.whenReady().then(()=>{ 10 | // createMainWindow(BrowserWindow) 11 | createLoadWindow(BrowserWindow) 12 | app.on('activate', () => { 13 | // On macOS it's common to re-create a window in the app when the 14 | // dock icon is clicked and there are no other windows open. 15 | if (BrowserWindow.getAllWindows().length === 0) createLoginWindow(BrowserWindow) 16 | }) 17 | // 初始化监听事件 18 | InitController(app) 19 | // 初始化托盘 20 | initTray() 21 | // 初始化快捷键 22 | initShortCut() 23 | }) 24 | // 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 There, it's common 25 | // for applications and their menu bar to stay active until the user quits 26 | // explicitly with Cmd + Q. 27 | app.on('window-all-closed', () => { 28 | if (process.platform !== 'darwin') app.quit() 29 | }) 30 | // 客户端聚焦 31 | app.on('browser-window-focus',()=>{ 32 | // 初始化快捷键 33 | initShortCut() 34 | console.log('browser-window-focus') 35 | }) 36 | // 客户端失去焦点 37 | app.on('browser-window-blur',()=>{ 38 | // 注销快捷键 39 | unInstallShortCut() 40 | console.log('browser-window-blur') 41 | }) 42 | app.on('will-quit', () => { 43 | // 注销快捷键 44 | unInstallShortCut() 45 | }) 46 | -------------------------------------------------------------------------------- /src/render/layout/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 38 | 39 | 54 | -------------------------------------------------------------------------------- /src/render/hooks/watchRouter.ts: -------------------------------------------------------------------------------- 1 | import {computed, onMounted, ref, watchEffect} from 'vue' 2 | import {constantRouterMap} from '@/render/router' 3 | import {router} from "@/render/router" 4 | import {useAppStore} from "@/render/store/modules/app"; 5 | 6 | export const wacthRouter=(location:String)=>{ 7 | let currenPath=ref('/') 8 | let menuList = ref([]) 9 | const appStore = useAppStore() 10 | 11 | onMounted(()=>{ 12 | menuList.value=constantRouterMap.filter((item=>{ 13 | return !(item as any).hidden 14 | })) 15 | if(appStore.breadCrumbList.length===0){ 16 | const data={ 17 | title:router?.currentRoute?.value?.meta?.title as any, 18 | path:router?.currentRoute?.value?.path, 19 | showClose:false, 20 | type:'route' 21 | } 22 | appStore.setBreadCrumbList(data,'route') 23 | } 24 | }) 25 | watchEffect(()=>{ 26 | // const index=menuList.value[0]?.children?.findIndex((item:any)=>{ 27 | // return item.path===router?.currentRoute.value.path 28 | // }) 29 | // if(index!==undefined){ 30 | // currenPath.value=index 31 | // } 32 | if(location==='menu'){ 33 | if(router?.currentRoute.value.path && router?.currentRoute.value.path!=='/news'){ 34 | currenPath.value=router?.currentRoute.value.path 35 | } 36 | }else{ 37 | if(router?.currentRoute.value.path){ 38 | currenPath.value=router?.currentRoute.value.path 39 | } 40 | } 41 | 42 | }) 43 | return { 44 | currenPath, 45 | menuList 46 | } 47 | } -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 47 | 48 | 58 | -------------------------------------------------------------------------------- /src/render/store/modules/app.ts: -------------------------------------------------------------------------------- 1 | // stores/app.ts 2 | import { defineStore } from 'pinia' 3 | import {useCache} from "@/render/hooks/useCache"; 4 | 5 | const { wsCache } = useCache('localStorage') 6 | 7 | interface AppState { 8 | isCollapse:Boolean, 9 | breadCrumbList:Array, 10 | isDark:Boolean, 11 | } 12 | export interface BreadCrumbList { 13 | title:String, 14 | path:String, 15 | showClose:Boolean, 16 | type:String 17 | } 18 | export type ActionBread ='route' | 'news' 19 | 20 | export const useAppStore = defineStore('app', { 21 | state: ():AppState => { 22 | return { 23 | isCollapse: false, 24 | breadCrumbList:wsCache.get('breadCrumbList')?wsCache.get('breadCrumbList'):[], 25 | isDark:wsCache.get('isDark')?wsCache.get('isDark'):false, 26 | } 27 | }, 28 | actions: { 29 | // 设置主题切换 30 | setDark(){ 31 | this.isDark=!this.isDark 32 | wsCache.set('isDark',this.isDark) 33 | }, 34 | // 设置菜单合并 35 | setCollapse(e:Boolean) { 36 | this.isCollapse=e 37 | }, 38 | // 设置面包屑路由展示 39 | setBreadCrumbList(data:BreadCrumbList,action:ActionBread){ 40 | if(action==="route"){ 41 | const newData=[...this.breadCrumbList] 42 | const filterData=newData.map((item)=>{ 43 | if(item.type!=='route'){ 44 | return {...item} 45 | } 46 | }).filter(item=>item!==undefined) 47 | this.breadCrumbList=[data,...filterData as any,] 48 | }else{ 49 | this.breadCrumbList.push(data) 50 | } 51 | wsCache.set('breadCrumbList',this.breadCrumbList) 52 | } 53 | }, 54 | }) 55 | -------------------------------------------------------------------------------- /src/render/layout/sideBar/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 46 | 47 | -------------------------------------------------------------------------------- /src/render/layout/sideBar/SidebarItem.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{menuItem.children?menuItem.children[0].meta.title:menuItem.meta.title}} 6 | 7 | 8 | 9 | 10 | {{menuItem.meta.title}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 53 | 54 | 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "./", 3 | "name": "electron-vue3", 4 | "private": true, 5 | "version": "0.0.0", 6 | "main": "src/electron-main/main.js", 7 | "scripts": { 8 | "serve": "concurrently \"npm run dev\" \"npm run start\" ", 9 | "dev": "vite", 10 | "build": "vue-tsc && vite build", 11 | "preview": "vite preview", 12 | "start": "nodemon --exec electron . --watch ./ --ext .js,.html,.scss,.vue,.ts,.css", 13 | "app:dir": "electron-builder --dir", 14 | "app:dist": "electron-builder", 15 | "electron:dist": "vue-tsc && vite build && electron-builder" 16 | }, 17 | 18 | "build": { 19 | "appId": "com.clound.app", 20 | "productName": "clound", 21 | "win": { 22 | "icon": "./public/icon.ico", 23 | "artifactName": "${productName}.${ext}" 24 | }, 25 | "directories": { 26 | "output": "dist_electron" 27 | }, 28 | "files": ["./dist","./package.json","./src/electron-main"], 29 | "nsis": { 30 | "oneClick": false, 31 | "allowElevation": true, 32 | "allowToChangeInstallationDirectory": true, 33 | "createDesktopShortcut": true, 34 | "createStartMenuShortcut": true, 35 | "runAfterFinish": true, 36 | "installerIcon": "./public/icon.ico", 37 | "uninstallerIcon": "./public/icon.ico", 38 | "installerHeaderIcon": "./public/icon.ico", 39 | "shortcutName": "dclound" 40 | } 41 | }, 42 | "dependencies": { 43 | "@element-plus/icons-vue": "^2.0.10", 44 | "axios": "^1.2.0", 45 | "electron-window-state": "^5.0.3", 46 | "element-plus": "^2.2.22", 47 | "pinia": "^2.0.26", 48 | "qs": "^6.11.0", 49 | "unplugin-auto-import": "^0.11.5", 50 | "unplugin-icons": "^0.14.14", 51 | "unplugin-vue-components": "^0.22.11", 52 | "vue": "^3.2.41", 53 | "vue-router": "^4.1.6", 54 | "web-storage-cache": "^1.1.1", 55 | "electron-is-dev": "^2.0.0" 56 | }, 57 | "devDependencies": { 58 | "@iconify-json/ep": "^1.1.8", 59 | "@vitejs/plugin-vue": "^3.2.0", 60 | "electron": "^21.3.0", 61 | "electron-builder": "^23.6.0", 62 | "nodemon": "^2.0.20", 63 | "sass": "^1.56.1", 64 | "sass-loader": "^13.2.0", 65 | "typescript": "^4.6.4", 66 | "vite": "^3.2.3", 67 | "vue-tsc": "^1.0.9" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/render/service/axios/service.ts: -------------------------------------------------------------------------------- 1 | import axios, { 2 | AxiosInstance, 3 | AxiosRequestConfig, 4 | AxiosRequestHeaders, 5 | AxiosResponse, 6 | AxiosError 7 | } from 'axios' 8 | 9 | // @ts-ignore 10 | import qs from 'qs' 11 | 12 | import { config } from './config' 13 | 14 | import { ElMessage } from 'element-plus' 15 | 16 | const { result_code, base_url } = config 17 | // export const PATH_URL ='/api' 18 | // @ts-ignore 19 | export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] 20 | // 创建axios实例 21 | const service: AxiosInstance = axios.create({ 22 | baseURL: PATH_URL, // api 的 base_url 23 | timeout: config.request_timeout // 请求超时时间 24 | }) 25 | 26 | // request拦截器 27 | service.interceptors.request.use( 28 | (config: AxiosRequestConfig) => { 29 | if ( 30 | config.method === 'post' && 31 | (config.headers as AxiosRequestHeaders)['Content-Type'] === 32 | 'application/x-www-form-urlencoded' 33 | ) { 34 | config.data = qs.stringify(config.data) 35 | } 36 | // ;(config.headers as AxiosRequestHeaders)['Token'] = 'test test' 37 | // get参数编码 38 | if (config.method === 'get' && config.params) { 39 | let url = config.url as string 40 | url += '?' 41 | const keys = Object.keys(config.params) 42 | for (const key of keys) { 43 | if (config.params[key] !== void 0 && config.params[key] !== null) { 44 | url += `${key}=${encodeURIComponent(config.params[key])}&` 45 | } 46 | } 47 | url = url.substring(0, url.length - 1) 48 | config.params = {} 49 | config.url = url 50 | } 51 | return config 52 | }, 53 | (error: AxiosError) => { 54 | // Do something with request error 55 | console.log(error) // for debug 56 | Promise.reject(error) 57 | } 58 | ) 59 | 60 | // response 拦截器 61 | service.interceptors.response.use( 62 | (response: AxiosResponse) => { 63 | if (response.config.responseType === 'blob') { 64 | // 如果是文件流,直接过 65 | return response 66 | } else if (response.data.code === result_code) { 67 | return response.data 68 | } else { 69 | ElMessage.error(response.data.message) 70 | } 71 | }, 72 | (error: AxiosError) => { 73 | console.log('err' + error) // for debug 74 | ElMessage.error(error.message) 75 | return Promise.reject(error) 76 | } 77 | ) 78 | 79 | export { service } 80 | -------------------------------------------------------------------------------- /components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/core/pull/3399 4 | import '@vue/runtime-core' 5 | 6 | export {} 7 | 8 | declare module '@vue/runtime-core' { 9 | export interface GlobalComponents { 10 | ElButton: typeof import('element-plus/es')['ElButton'] 11 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] 12 | ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] 13 | ElCol: typeof import('element-plus/es')['ElCol'] 14 | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] 15 | ElDialog: typeof import('element-plus/es')['ElDialog'] 16 | ElForm: typeof import('element-plus/es')['ElForm'] 17 | ElFormItem: typeof import('element-plus/es')['ElFormItem'] 18 | ElIcon: typeof import('element-plus/es')['ElIcon'] 19 | ElInput: typeof import('element-plus/es')['ElInput'] 20 | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] 21 | ElMenu: typeof import('element-plus/es')['ElMenu'] 22 | ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] 23 | ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] 24 | ElOption: typeof import('element-plus/es')['ElOption'] 25 | ElRadio: typeof import('element-plus/es')['ElRadio'] 26 | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] 27 | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] 28 | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] 29 | ElSelect: typeof import('element-plus/es')['ElSelect'] 30 | ElSelectV2: typeof import('element-plus/es')['ElSelectV2'] 31 | ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] 32 | ElSwitch: typeof import('element-plus/es')['ElSwitch'] 33 | ElTimePicker: typeof import('element-plus/es')['ElTimePicker'] 34 | ElTooltip: typeof import('element-plus/es')['ElTooltip'] 35 | IEpClose: typeof import('~icons/ep/close')['default'] 36 | IEpCloseBold: typeof import('~icons/ep/close-bold')['default'] 37 | IEpExpand: typeof import('~icons/ep/expand')['default'] 38 | IEpFold: typeof import('~icons/ep/fold')['default'] 39 | IEpFullScreen: typeof import('~icons/ep/full-screen')['default'] 40 | IEpSemiSelect: typeof import('~icons/ep/semi-select')['default'] 41 | RouterLink: typeof import('vue-router')['RouterLink'] 42 | RouterView: typeof import('vue-router')['RouterView'] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/render/layout/navBar/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | {{item.title}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 33 | 34 | -------------------------------------------------------------------------------- /src/render/layout/sideBar/Logo.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 新闻信息终端 7 | 8 | 9 | 10 | 用户名 11 | 12 | 13 | 14 | 15 | 16 | 32 | 33 | -------------------------------------------------------------------------------- /src/render/views/load/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 新闻信息终端 8 | 丰富 · 实时 · 高效 · 智能 9 | 10 | 11 | 12 | 开始启动... 13 | 29% 14 | 15 | 16 | 17 | 18 | 37 | 38 | 103 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig,loadEnv} from 'vite' 2 | import type { UserConfig, ConfigEnv } from 'vite' 3 | import vue from '@vitejs/plugin-vue' 4 | import { resolve } from 'path' 5 | // 自动导入element-plus 6 | import AutoImport from 'unplugin-auto-import/vite' 7 | import Components from 'unplugin-vue-components/vite' 8 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 9 | import Icons from 'unplugin-icons/vite' 10 | import IconsResolver from 'unplugin-icons/resolver' 11 | 12 | const root = process.cwd() 13 | function pathResolve(dir: string) { 14 | return resolve(root, '.', dir) 15 | } 16 | 17 | export default defineConfig(({ command, mode }: ConfigEnv): UserConfig=>{ 18 | let env = {} as any 19 | const isBuild = command === 'build' 20 | if (!isBuild) { 21 | env = loadEnv((process.argv[3] === '--mode' ? process.argv[4] : process.argv[3]), root) 22 | } else { 23 | env = loadEnv(mode, root) 24 | } 25 | return { 26 | base: env.VITE_BASE_PATH, 27 | publicDir: resolve(__dirname, './dist'), 28 | assetsInclude: resolve(__dirname, 'src/render/assets'), 29 | server: { 30 | port: 4000, 31 | proxy: { 32 | // 选项写法 33 | '/api': { 34 | target: 'https://sports.api.zxdev.top/api', 35 | changeOrigin: true, 36 | rewrite: path => path.replace(/^\/api/, '') 37 | } 38 | }, 39 | hmr: { 40 | overlay: false 41 | }, 42 | host: '0.0.0.0' 43 | }, 44 | plugins: [ 45 | vue(), 46 | AutoImport({ 47 | // Auto import functions from Element Plus, e.g. ElMessage, ElMessageBox... (with style) 48 | // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式) 49 | resolvers: [ 50 | ElementPlusResolver({ 51 | importStyle:'sass' 52 | }), 53 | // Auto import icon components 54 | // 自动导入图标组件 55 | IconsResolver({ 56 | prefix: 'Icon', 57 | }), 58 | ], 59 | 60 | }), 61 | 62 | Components({ 63 | resolvers: [ 64 | // Auto register icon components 65 | // 自动注册图标组件 66 | IconsResolver({ 67 | enabledCollections: ['ep'], 68 | }), 69 | // Auto register Element Plus components 70 | // 自动导入 Element Plus 组件 71 | ElementPlusResolver({ 72 | importStyle:'sass' 73 | }), 74 | ], 75 | }), 76 | 77 | Icons({ 78 | autoInstall: true, 79 | }), 80 | 81 | ], 82 | css: { 83 | preprocessorOptions: { 84 | scss: { 85 | additionalData: `@use "@/render/styles/layout.scss" as *;`, 86 | } 87 | } 88 | }, 89 | resolve: { 90 | extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.less', '.css'], 91 | alias: [ 92 | // { 93 | // find: 'vue-i18n', 94 | // replacement: 'vue-i18n/dist/vue-i18n.cjs.js' 95 | // }, 96 | { 97 | find: /\@\//, 98 | replacement: `${pathResolve('src')}/` 99 | } 100 | ] 101 | }, 102 | } 103 | }) 104 | -------------------------------------------------------------------------------- /src/electron-main/untils/localFile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 读取本地配置 3 | */ 4 | const fs = require('fs') 5 | const path = require('path') 6 | /** 7 | * 判断配置文件是否存在 8 | */ 9 | function isExit() { 10 | let success = true; 11 | if (!(localConfig.config && typeof localConfig.config === 'object')) { 12 | success = initConfig(); 13 | } 14 | return success; 15 | } 16 | /** 17 | * 初始化config 18 | */ 19 | function initConfig() { 20 | try { 21 | const config = readConfig(); 22 | if (config) { 23 | localConfig.config = JSON.parse(config); 24 | return true; 25 | } 26 | const defalutConfig = {}; 27 | const content = JSON.stringify(defalutConfig); 28 | fs.writeFileSync(localConfig.configUrl, content); 29 | localConfig.config = defalutConfig; 30 | return true; 31 | } catch (e) { 32 | return false; 33 | } 34 | } 35 | /** 36 | * 读取文件 37 | */ 38 | function readConfig() { 39 | try { 40 | const result = fs.readFileSync(localConfig.configUrl); 41 | return result; 42 | } catch (error) { 43 | return false; 44 | } 45 | } 46 | /** 47 | * 写入文件 48 | */ 49 | function writeConfig(value) { 50 | try { 51 | const content = JSON.stringify(value); 52 | fs.writeFileSync(localConfig.configUrl, content); 53 | return true; 54 | } catch (e) { 55 | return false; 56 | } 57 | } 58 | 59 | 60 | const localConfig = { 61 | config: null, 62 | configUrl: path.join(__dirname, './localConfig.json'), 63 | setStoragePath: (path) => { 64 | localConfig.configUrl = path; 65 | }, 66 | getStoragePath: () => { 67 | return localConfig.configUrl; 68 | }, 69 | getItem: (key) => { 70 | const success = isExit(); 71 | if (success) { 72 | console.log(key,localConfig.config) 73 | const result = localConfig.config[key]; 74 | return result ? result : ''; 75 | } 76 | return null; 77 | }, 78 | setItem: (key, value) => { 79 | let success = isExit(); 80 | if (success) { 81 | const config = Object.assign({}, localConfig.config); 82 | config[key] = value; 83 | const suc = writeConfig(config); 84 | if (suc) { 85 | localConfig.config = config; 86 | return true; 87 | } 88 | } 89 | return false; 90 | }, 91 | getAll: () => { 92 | let success = isExit(); 93 | if (success) { 94 | return localConfig.config; 95 | } 96 | return null; 97 | }, 98 | removeItem: (key) => { 99 | const value = localConfig.getItem(key); 100 | if (value) { 101 | const config = Object.assign({}, localConfig.config); 102 | delete config[key]; 103 | const suc = writeConfig(config); 104 | if (suc) { 105 | localConfig.config = config; 106 | return true; 107 | } 108 | } 109 | return false; 110 | }, 111 | clear: () => { 112 | let success = isExit(); 113 | if (success) { 114 | const suc = writeConfig({}); 115 | if (suc) { 116 | localConfig.config = {}; 117 | return true; 118 | } 119 | } 120 | return false; 121 | } 122 | } 123 | 124 | module.exports = { 125 | localConfig, 126 | 127 | }; 128 | -------------------------------------------------------------------------------- /src/render/views/load/old.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 加载页面 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 30 | 31 | 148 | -------------------------------------------------------------------------------- /src/electron-main/modules/controller/main.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const {ipcMain,BrowserWindow,shell} =require('electron') 3 | const {createMainWindow} = require( '../../windows/mainWindows.js') 4 | const {createLoginWindow} = require("../../windows/loginWindows"); 5 | const {createRegisterWindow} = require("../../windows/registerWindows"); 6 | const {createResetPasswordWindow} = require("../../windows/resetPasswordWindows"); 7 | 8 | const settitle=()=>{ 9 | // @ts-ignore 10 | ipcMain.handle('on-settitle-event',(event,title)=>{ 11 | const webContents = event.sender 12 | const win = BrowserWindow.fromWebContents(webContents) 13 | win.setTitle(title) 14 | return '已收到' 15 | }) 16 | } 17 | // 浏览器打开页面 18 | const openByBrowser=()=>{ 19 | // @ts-ignore 20 | ipcMain.handle('on-useOpenByBrowser-event',(event,url)=>{ 21 | shell.openExternal(url) 22 | }) 23 | } 24 | // 登录 展示首页 25 | const setlogin=()=>{ 26 | // @ts-ignore 27 | ipcMain.handle('on-setlogin-event',(event,title)=>{ 28 | const webContents = event.sender 29 | const win = BrowserWindow.fromWebContents(webContents) 30 | win.close() 31 | createMainWindow(BrowserWindow) 32 | return '已经登录' 33 | }) 34 | } 35 | // 加载页判断登录或者展示首页 36 | const isShowLogin=()=>{ 37 | // @ts-ignore 38 | ipcMain.handle('on-isshowlogin-event',(event,value)=>{ 39 | if(value){ 40 | setTimeout(()=>{ 41 | const webContents = event.sender 42 | const win = BrowserWindow.fromWebContents(webContents) 43 | win.close() 44 | createLoginWindow(BrowserWindow) 45 | },3000) 46 | }else{ 47 | const webContents = event.sender 48 | const win = BrowserWindow.fromWebContents(webContents) 49 | win.close() 50 | createMainWindow(BrowserWindow) 51 | } 52 | 53 | // const webContents = event.sender 54 | // const win = BrowserWindow.fromWebContents(webContents) 55 | // win.close() 56 | // createMainWindow(BrowserWindow) 57 | return '' 58 | }) 59 | } 60 | // 首页屏幕缩小 放大 关闭控制 61 | const setScreen=()=>{ 62 | // @ts-ignore 63 | ipcMain.handle('on-setScreen-event',(event,value)=>{ 64 | const webContents = event.sender 65 | const win = BrowserWindow.fromWebContents(webContents) 66 | if(value==='miniScreen'){ 67 | win.minimize() 68 | }else if(value==='fullScreen'){ 69 | if(win.isMaximized()){ 70 | win.restore() 71 | }else{ 72 | win.maximize() 73 | } 74 | }else if(value==='closeScreen'){ 75 | 76 | } 77 | return '' 78 | }) 79 | } 80 | // 打开注册页面 81 | const openRegister=()=>{ 82 | // @ts-ignore 83 | ipcMain.handle('on-openRegister-event',(event,title)=>{ 84 | const webContents = event.sender 85 | const win = BrowserWindow.fromWebContents(webContents) 86 | win.close() 87 | createRegisterWindow(BrowserWindow) 88 | return '打开注册页面' 89 | }) 90 | } 91 | // 注册成功 92 | const setRegister=()=>{ 93 | // @ts-ignore 94 | ipcMain.handle('on-register-event',(event,title)=>{ 95 | const webContents = event.sender 96 | const win = BrowserWindow.fromWebContents(webContents) 97 | win.close() 98 | createLoginWindow(BrowserWindow) 99 | return '返回登录页面' 100 | }) 101 | } 102 | // 重置密码后返回登录页面 103 | const setBackLogin=()=>{ 104 | // @ts-ignore 105 | ipcMain.handle('on-backLogin-event',(event,title)=>{ 106 | const webContents = event.sender 107 | const win = BrowserWindow.fromWebContents(webContents) 108 | win.close() 109 | createLoginWindow(BrowserWindow) 110 | return '重置密码后返回登录页面' 111 | }) 112 | } 113 | // 打开重置密码 114 | const openRestPassword=()=>{ 115 | // @ts-ignore 116 | ipcMain.handle('on-openRestPassword-event',(event,title)=>{ 117 | const webContents = event.sender 118 | const win = BrowserWindow.fromWebContents(webContents) 119 | win.close() 120 | createResetPasswordWindow(BrowserWindow) 121 | return '重置密码后返回登录页面' 122 | }) 123 | } 124 | const InitController=(app)=>{ 125 | openRestPassword(), 126 | setBackLogin(), 127 | openRegister(), 128 | setRegister(), 129 | settitle(), 130 | openByBrowser(), 131 | setlogin(), 132 | isShowLogin(), 133 | setScreen() 134 | } 135 | 136 | module.exports={ 137 | InitController, 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/render/layout/navBar/TopHeader.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 2022/11/1 16:45:32 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 63 | 64 | 127 | -------------------------------------------------------------------------------- /src/render/views/login/login-message.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 获取验证码 27 | 28 | 29 | 30 | 31 | 32 | 33 | 登 录 34 | 35 | 36 | 37 | 38 | 125 | 126 | -------------------------------------------------------------------------------- /src/render/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, RouteRecordRaw,createWebHashHistory} from 'vue-router' 2 | import type { App } from 'vue' 3 | // 引入本地图片方法 4 | import {imgLocalUrl} from '@/render/utils/imgLocalUrl' 5 | 6 | type RouterCustorm={ 7 | hidden?:boolean, 8 | } 9 | const LayOut=()=> import('@/render/layout/index.vue') 10 | export const constantRouterMap: (RouteRecordRaw | RouterCustorm)[] = [ 11 | // 多层级 12 | // { 13 | // path: '/', 14 | // name: 'Index', 15 | // meta: { 16 | // title: '设置', 17 | // icon:imgLocalUrl('@/assets/layout/avatar.png'), 18 | // }, 19 | // component: LayOut, 20 | // children:[ 21 | // { 22 | // path: '/', 23 | // name: 'Welcome', 24 | // meta: { 25 | // title: '首页', 26 | // icon:imgLocalUrl('@/assets/layout/avatar.png'), 27 | // }, 28 | // component: () => import('@/render/views/home/index.vue'), 29 | // }, 30 | // { 31 | // path: '/news', 32 | // name: 'News', 33 | // meta: { 34 | // title: '新闻', 35 | // icon:imgLocalUrl('@/assets/layout/avatar.png'), 36 | // }, 37 | // component: () => import('@/render/views/home/index.vue'), 38 | // } 39 | // ] 40 | // }, 41 | { 42 | path: '/load', 43 | name: 'Load', 44 | hidden: true, 45 | component: () => import('@/render/views/load/index.vue'), 46 | }, 47 | { 48 | path: '/login', 49 | name: 'Login', 50 | hidden: true, 51 | component: () => import('@/render/views/login/index.vue'), 52 | }, 53 | { 54 | path: '/register', 55 | name: 'Register', 56 | hidden: true, 57 | component: () => import('@/render/views/login/register/index.vue'), 58 | }, 59 | { 60 | path: '/resetPassword', 61 | name: 'ResetPassword', 62 | hidden: true, 63 | component: () => import('@/render/views/login/resetPassword/index.vue'), 64 | }, 65 | { 66 | path: '/', 67 | name: 'Review', 68 | component: LayOut, 69 | children:[ 70 | { 71 | path: '/', 72 | name: 'ReviewIndex', 73 | meta: { 74 | title: '审阅区', 75 | icon:imgLocalUrl('@/assets/layout/review.png'), 76 | }, 77 | component: () => import('@/render/views/review/index.vue'), 78 | }, 79 | ] 80 | }, 81 | { 82 | path: '/reviewHistory', 83 | name: 'ReviewHistory', 84 | component: LayOut, 85 | children:[ 86 | { 87 | path: '/ReviewHistory', 88 | name: 'ReviewHistory', 89 | meta: { 90 | title: '审阅区历史', 91 | icon:imgLocalUrl('@/assets/layout/history.png'), 92 | }, 93 | component: () => import('@/render/views/review-history/index.vue'), 94 | }, 95 | ] 96 | }, 97 | { 98 | path: '/notice', 99 | name: 'Notice', 100 | component: LayOut, 101 | children:[ 102 | { 103 | path: '/notice', 104 | name: 'Notice', 105 | meta: { 106 | title: '消息提醒', 107 | icon:imgLocalUrl('@/assets/layout/xiaoxitixing.png'), 108 | }, 109 | component: () => import('@/render/views/notice/index.vue'), 110 | }, 111 | ] 112 | }, 113 | { 114 | path: '/settings', 115 | name: 'Settings', 116 | component: LayOut, 117 | children:[ 118 | { 119 | path: '/settings', 120 | name: 'Settings', 121 | meta: { 122 | title: '配置管理', 123 | icon:imgLocalUrl('@/assets/layout/settings.png'), 124 | }, 125 | component: () => import('@/render/views/settings/index.vue'), 126 | }, 127 | ] 128 | }, 129 | { 130 | path: '/user', 131 | name: 'User', 132 | component: LayOut, 133 | children:[ 134 | { 135 | path: '/user', 136 | name: 'User', 137 | meta: { 138 | title: '用户管理', 139 | icon:imgLocalUrl('@/assets/layout/user.png'), 140 | }, 141 | component: () => import('@/render/views/user/index.vue'), 142 | }, 143 | ] 144 | }, 145 | { 146 | path: '/operate', 147 | name: 'Operate', 148 | component: LayOut, 149 | children:[ 150 | { 151 | path: '/operate', 152 | name: 'Operate', 153 | meta: { 154 | title: '运营管理', 155 | icon:imgLocalUrl('@/assets/layout/operate.png'), 156 | }, 157 | component: () => import('@/render/views/operate/index.vue'), 158 | }, 159 | ] 160 | }, 161 | { 162 | path: '/news', 163 | name: 'News', 164 | component: LayOut as any, 165 | hidden: true, 166 | children:[ 167 | { 168 | path: '/news', 169 | name: 'News', 170 | component: () => import('@/render/views/news/index.vue'), 171 | }, 172 | ] 173 | }, 174 | ] 175 | export const router = createRouter({ 176 | history: createWebHashHistory(import.meta.env.VITE_BASE_PATH), 177 | routes: constantRouterMap as RouteRecordRaw[], 178 | scrollBehavior: () => ({ left: 0, top: 0 }) 179 | }) 180 | 181 | export const setupRouter = (app: App) => { 182 | app.use(router) 183 | } 184 | -------------------------------------------------------------------------------- /src/render/views/login/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 新闻信息终端 9 | 丰富 · 实时 · 高效 · 智能 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 切换登录方式 20 | 21 | 22 | 23 | 24 | {{item.title}} 25 | {{item.subTitle}} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 88 | 89 | 214 | -------------------------------------------------------------------------------- /src/render/views/login/login-password.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 自动登录 31 | 32 | 33 | 34 | 记住密码 35 | 36 | 37 | 38 | 重置密码 39 | 40 | 41 | 42 | 登 录 43 | 44 | 45 | 46 | 47 | 132 | 133 | -------------------------------------------------------------------------------- /src/render/views/login/resetPassword/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 新闻信息终端 7 | 8 | 9 | 10 | 11 | 12 | 重置密码 13 | 14 | 15 | 16 | 17 | 18 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 获取验证码 44 | 45 | 46 | 47 | 48 | 49 | 请输入新的登录密码 50 | 51 | 52 | 53 | 54 | 55 | 56 | 61 | 62 | 63 | 64 | 65 | 登 录 66 | 67 | 68 | 69 | 70 | 71 | 162 | 163 | 306 | -------------------------------------------------------------------------------- /src/render/views/login/register/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 新闻信息终端 7 | 8 | 9 | 10 | 11 | 12 | 新用户注册申请 13 | 14 | 15 | 16 | 17 | 18 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 获取验证码 60 | 61 | 62 | 63 | 64 | 65 | 返回登录界面 66 | 67 | 68 | 注册申请 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 新闻信息终端 78 | 79 | 80 | 81 | 82 | 83 | 新用户注册申请 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 已完成注册申请! 94 | 后续请关注注册手机短信,通知审核结果 95 | 96 | 返回登录界面 97 | 98 | 99 | 100 | 101 | 102 | 103 | 216 | 217 | 483 | --------------------------------------------------------------------------------
{{item.title}}
用户名
新闻信息终端
丰富 · 实时 · 高效 · 智能
2022/11/1 16:45:32
切换登录方式
{{item.subTitle}}
65 | 返回登录界面 66 |
已完成注册申请!
后续请关注注册手机短信,通知审核结果