Vite2-ElectronVadmin 基于vue3+electron12精美UI中后台桌面端管理系统
发布于 3 年前 作者 xiaoyan2015 2321 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

随着项目需求的愈来愈迭进,一些公司的后台管理系统由原先的浏览器端逐步转向了桌面端。Electron是一款成熟的跨端桌面框架,加上vite2.x的更新及electron12的推出,一款基于vite2.x整合electron.js的后台管理系统应运而生了。

electron-vite2-vue3-admin 中后台管理系统桌面应用程序,使用最新前端技术栈开发,内含 i18n 国际化方案。 https://segmentfault.com/a/1190000040015181

360截图20210522085519215.png

electron-vadmin 一款支持主题换肤的多窗口精致UI界面管理系统。

360截图20210519155443809.png

功能特点

  • 支持桌面端及平板响应式布局
  • 支持组件式+指令式两种权限控制方式
  • 支持中英文/繁体国际化语言
  • 支持表格拖拽排序、全屏、树形表格等功能
  • 支持多主题换肤切换

038360截图20210516121336621.png

技术实现

  • 技术栈:vite2.1.5 / vue3.0 / vuex4 / vue-router@4
  • 桌面框架:electron^12.0.4
  • 构建打包:vue-cli-plugin-electron-builder
  • UI组件库:element-plus (饿了么vue3桌面端组件库)
  • 拖拽表格:sortablejs^1.13.0
  • 图表组件:echarts^5.1.1
  • 国际化:vue-i18n^9.1.6
  • 模拟请求:mockjs^1.1.0

项目架构目录

360截图20210519155645223.png

360截图20210519155833005.png

010360截图20210516113039513.png

012360截图20210516113528127.png

014360截图20210516113701984.png

017360截图20210516114110152.png

018360截图20210516114234351.png

019360截图20210516114440807.png

021360截图20210516115151967.png

023360截图20210516115405742.png

026360截图20210516115832245.png

029360截图20210516120154710.png

033360截图20210516120831039.png

035360截图20210516120937615.png

360截图20210519155855681.png

037360截图20210516121145110.png

042360截图20210516141010831.png

vite.js主入口配置

/**
 * 渲染进程主入口
 * @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')
})

vue-router路由配置

/**
 * 路由配置 Router util
 * @author XiaoYan
 */
 
import { createRouter, createWebHashHistory } from "vue-router"
 
import { ElLoading } from "element-plus"
import { loginWin } from "@/windows/actions"
 
import store from '@/store'
 
// 导入公共模板/路由配置
import mainLayout from "@/layouts/main"
import authLayout from "@/layouts/auth"
import mainRoutes from "@/layouts/main/routes.js"
import authRoutes from "@/layouts/auth/routes.js"
 
const RoutesLs = [
    // 主页面模块
    {
        path: '/',
        redirect: '/home/index',
        component: mainLayout,
        children: mainRoutes,
    },
    // 验证模块
    {
        path: '/auth',
        redirect: '/auth/login',
        component: authLayout,
        children: authRoutes,
    },
    // 错误模块
    {
        path: '/:pathMatch(.*)*',
        component: () => import('@/views/error/404.vue'),
        meta: {
            title: 'app__global-page-notfound',
        }
    }
]
 
const router = createRouter({
    history: createWebHashHistory(),
    routes: RoutesLs,
})

let loadingIns
router.beforeEach((to, from, next) => {
    // 开启加载提示
    loadingIns = ElLoading.service({
        lock: true,
        text: 'Loading...',
        spinner: 'el-icon-loading',
        background: 'rgba(19, 209, 122, .1)'
    })
 
    // 判断当前路由状态
    const isLogined = store.state.isLogin
    if(to.meta.auth) {
        if(isLogined) {
            next()
        }else {
            loginWin()
            loadingIns.close()
        }
    }else {
        next()
    }
})
 
router.afterEach(() => {
    loadingIns.close()
})

vite+electron自定义导航栏组件

项目中顶部导航条采用自定义组件实现效果。风格类似imac导航条。

360截图-60a23d9111142.png

<!-- //仿Mac导航条 -->
<template>
   <WinBar zIndex="1000">
       <template #wbtn>
           <MsgMenu />
           <Lang />
           <a class="wbtn" @click="handleSkinWin"><i class="iconfont icon-huanfu"></i></a>
           <Setting />
           <a class="wbtn" @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-i18n 国际化配置

目前vue-i18n已经支持vue3版本了。只需安装插件 npm i vue-i18n@next

360截图20210518221144948.png

/**
* [@desc](/user/desc)	vue-i18n国际化配置文件
* [@Time](/user/Time)	andy by 2021-05
* [@Author](/user/Author)      Q:282310962  wx:xy190310
*/

import { createI18n } from 'vue-i18n'
import Storage from '@/utils/storage'

// 默认设置
export const langKey = 'lang'
export const langVal = 'zh-CN'

/**
* 引入element-plus国际化包
*/
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 = importLang()
export const $lang = getLang()
const i18n = createI18n({
  legacy: false,
  locale: $lang,
  messages: $messages
})

/**
* 自动导入语言配置
*/
export function importLang() {
  const localeModule = {}
  try {
      // 导入 @/layouts 文件夹下包含子目录locale中的xxx.js文件
      const layoutsCtx = require.context('@/layouts', true, /[/\\]locale[/\\]([a-z]{2})-?([A-Z]{2})?\.js$/)
      layoutsCtx.keys().map(path => {
          const pathCtx = layoutsCtx(path)
          if(pathCtx.default) {
              const pathName = path.replace(/(.*\/)*([^.]+).*/ig, '$2')
              if(localeModule[pathName]) {
                  localeModule[pathName] = {
                      ...localeModule[pathName], ...pathCtx.default
                  }
              }else {
                  localeModule[pathName] = pathCtx.default
              }
          }
      })
  } catch (error) {
      console.log(error)
  }

  return localeModule
}

/**
* 存储设置语言
* [@param](/user/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()
      }
  }
}

/**
* 获取语言
*/
export function getLang() {
  const lang = Storage.get(langKey)
  return lang || langVal
}

主模板布局

项目整体采用顶部、侧边栏、右侧内容三大模块。

<!-- //Main主模块模板 -->
<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>

Ok,运用vite.js+electron开发桌面端后台系统就分享到这里。 electron+vitejs+vant3桌面端短视频|直播实例

duitang.gif

回到顶部