vite2-electron-admin 一套轻量级的中后台系统解决方案。它整合了vite.js + electron12
开发实现。使用了最新的前端技术栈,包含了 i18n 国际化语言,动态权限路由,提供了多功能表格/表单
业务功能。css
electron-vite-admin 还支持新开多窗口,以以下换肤窗口为例,前面已经有过相关分享文章,这里就不详细介绍。前端
import { createWin } from '@/windows/actions' // 换肤窗口 const handleOpenTheme = () => { createWin({ title: '主题换肤', route: '/skin', width: 750, height: 480, }) }
如上图:为了项目UI一致性,顶部导航栏采用了自定义组件实现,风格有些相似mac导航。vue
<template> <WinBar zIndex="1000"> <template #wbtn> <MsgMenu /> <Lang /> <a class="wbtn" title="换肤" @click="handleSkinWin"><i class="iconfont icon-huanfu"></i></a> <Setting /> <a class="wbtn" title="刷新" @click="handleRefresh"><i class="iconfont el-icon-refresh"></i></a> <a class="wbtn" :class="{'on': isAlwaysOnTop}" :title="isAlwaysOnTop ? '取消置顶' : '置顶'" @click="handleAlwaysTop"><i class="iconfont icon-ding"></i></a> <Avatar @logout="handleLogout" /> </template> </WinBar> </template>
至于具体的实现方式,这里不做过多介绍了。以前有过一些相关分享文章。vue-router
/** * 渲染进程主入口 * @author XiaoYan */ import { createApp } from 'vue' import App from './App.vue' import Router from './router' import Store from './store' // 引入公共配置 import gPlugins from './plugins' import { winCfg, loadWin } from './windows/actions' loadWin().then(config => { winCfg.window = config createApp(App).use(Router).use(Store).use(gPlugins).mount('#app') })
/** * 公共组件/插件配置文件 * @author XiaoYan */ // 引入公共样式 import "@/assets/fonts/iconfont.css" import "@/assets/css/common.scss" // 引入elementPlus组件库 import ELPlus from "element-plus" // 引入国际化配置 import VueI18n, { elPlusLang, getLang } from './i18n' // 引入vue3自定义组件 import V3Layer from '@/components/v3layer' import V3Scroll from '@/components/v3scroll' // 引入公共组件模板 import WinBar from '@/components/winbar' import WinBtn from '@/components/winbar/winbtn.vue' import MacBtn from '@/components/winbar/macbtn.vue' import Icon from '@/components/Icon' import Utils from '@/utils' import ElUtil from './elUtil' const gPlugins = (app) => { app.use(ELPlus, { size: 'small', locale: elPlusLang[getLang()] }) app.use(VueI18n) app.use(V3Layer) app.use(V3Scroll) // 注册公共组件 app.component('WinBar', WinBar) app.component('WinBtn', WinBtn) app.component('MacBtn', MacBtn) app.component('Icon', Icon) // 注入全局依赖 app.provide('utils', Utils) app.provide('elUtil', ElUtil) }
新建一个i18n.js用来引入国际化语言配置。vuex
/** * 国际化配置 VueI18n util * @author XiaoYan Q:282310962 */ import { createI18n } from "vue-i18n" import Storage from "@/utils/storage" // 默认值 export const langKey = 'lang' export const langVal = 'zh-CN' /* elementPlus国际化配置 */ import enUS from "element-plus/lib/locale/lang/en" import zhCN from "element-plus/lib/locale/lang/zh-cn" import zhTW from "element-plus/lib/locale/lang/zh-tw" export const elPlusLang = { 'en-US': enUS, 'zh-CN': zhCN, 'zh-TW': zhTW, } /* 初始化多语言 */ export const $messages = importAllLang() export const $lang = getLang() const i18n = createI18n({ legacy: false, locale: $lang, messages: $messages }) /* 获取语言 */ export function getLang() { const lang = Storage.get(langKey) return lang || langVal } /** * 持久化存储 * @param lang 语言类型 zh-CN / zh-TW / en-US */ export function setLang(lang, reload = false) { if(getLang() !== lang) { Storage.set(langKey, lang || '') // 设置全局语言 // i18n.global.locale.value = lang // 重载页面 if(reload) { window.location.reload() } } } /** * 自动化导入本地locale目录下语言配置 */ export function importAllLang() { const langModule = {} try { const localeCtx = require.context('@/locale', true, /([a-z]{2})-?([A-Z]{2})?\.js$/) localeCtx.keys().map(path => { const pathCtx = localeCtx(path) if(pathCtx.default) { const pathName = path.replace(/(.*\/)*([^.]+).*/ig, '$2') if(langModule[pathName]) { langModule[pathName] = { ...langModule[pathName], ...pathCtx.default } }else { langModule[pathName] = pathCtx.default } } }) } catch (error) { console.log(error) } return langModule }
项目布局分为Auth和Main两个主要模块。vue-cli
<template> <div class="vadmin__wrapper"> <router-view class="vadmin__layouts-auth"></router-view> </div> </template> <script> import { useRoute } from "vue-router" import useTitle from '@/hooks/useTitle' export default { components: {}, setup() { const route = useRoute() // 设置标题 useTitle(route) } } </script>
<template> <div class="vadmin__wrapper" :style="{'--themeSkin': store.state.skin}"> <div v-if="!route.meta.isNewin" class="vadmin__layouts-main flexbox flex-col"> <!-- 顶部导航 --> <div class="layout__topbar"> <TopNav /> </div> <div class="layout__workpanel flex1 flexbox"> <!-- 侧边栏 --> <div v-show="rootRouteEnable" class="panel__leftlayer"> <SideMenu :routes="mainRoutes" :rootRoute="rootRoute" /> </div> <!-- 中间栏 --> <div class="panel__middlelayer" :class="{'collapsed': collapsed}"> <RouteMenu :routes="getAllRoutes" :rootRoute="rootRoute" :defaultActive="defaultActive" :rootRouteEnable="rootRouteEnable" /> </div> <!-- //右边栏 --> <div class="panel__rightlayer flex1 flexbox flex-col"> <!-- 面包屑 --> <BreadCrumb /> <v3-scroll autohide> <div class="lay__container"> <permission :roles="route.meta.roles"> <template #tooltips> <Forbidden /> </template> <router-view></router-view> </permission> </div> </v3-scroll> </div> </div> </div> <router-view v-else class="vadmin__layouts-main flexbox flex-col"></router-view> </div> </template>
为了简化图表调用,封装一个图表hooks。使用到了element-resize-detector来监测dom尺寸变化。segmentfault
import { onMounted, onBeforeUnmount, ref } from "vue" import * as echarts from "echarts" import elementResizeDetectorMaker from "element-resize-detector" import utils from "@/utils" export default function useChart(refs, options) { let chartInst let chartRef = ref(null) let erd = elementResizeDetectorMaker() const handleResize = utils.debounce(() => { chartInst.resize() }, 100) onMounted(() => { if(refs.value) { chartInst = echarts.init(refs.value) chartInst.setOption(options) chartRef.value = chartInst } erd.listenTo(refs.value, handleResize) }) onBeforeUnmount(() => { chartInst.dispose() erd.removeListener(refs.value, handleResize) }) return chartRef }
这样每次调用的时候,只需传入图表dom元素和图表数据便可快速生成一个图表。windows
Okey,运用electron+vite.js跨端开发后台管理系统暂时分享到这里。app
最后附上Electron+Vue3桌面端仿都有短视频+直播
https://segmentfault.com/a/1190000039725671echarts