当前位置 博文首页 > xiaoyan2017:Electron-Vue3-Vadmin后台系统|vite2+electron桌面

    xiaoyan2017:Electron-Vue3-Vadmin后台系统|vite2+electron桌面

    作者:xiaoyan2017 时间:2021-05-17 18:29

    基于vite2.x+electron12桌面端后台管理系统Vite2ElectronVAdmin

    继上一次分享vite2整合electron搭建后台框架,这次带来的是最新开发的跨桌面中后台权限管理系统。使用最新的前端技术栈,内置 i18n 国际化解决方案,动态权限路由,权限验证,整合了典型的表格/表单等业务模块功能。

    一、技术栈

    • 编码器:vscode
    • vue3技术:vite2.1.5+vue3.0+vuex4+vue-router@4
    • 跨端框架:electron^12.0.4
    • 打包工具:vue-cli-plugin-electron-builder
    • UI组件库:element-plus^1.0.2 (饿了么vue3组件库)
    • 表格拖拽:sortablejs^1.13.0
    • 图表组件:echarts^5.1.1
    • 国际化方案:vue-i18n^9.1.6
    • 数据模拟:mockjs^1.1.0

    二、主要特性

    1. 前端技术栈Vite2、Vue3、Electron12、Element Plus、Vue-i18n、Echarts5.x、Sortable、Mockjs。
    2. 权限认证支持组件式+指令式两种方式。
    3. 支持中文/英文/繁体国际化解决方案。
    4. 支持表格拖拽排序、缩放、树形表格等功能。
    5. 支持加载动态权限菜单,多方式轻松权限控制。
    6. 高效率开发,整个框架已经搭建完毕,只需新增相应模块即可。

    三、项目结构图

    整个项目使用最新vue3语法编码,采用标准的分层目录结构形式,数据均是使用Mock.js进行模拟。

    ◆ electron支持多开新窗口

    项目支持打开多个窗口,如主题换肤、关于等窗口。只需通过如下的方式调用即可。

    import { winCfg, createWin } from '@/windows/actions'
    
    // 换肤窗口
    const handleOpenTheme = () => {
        createWin({
            title: '个性装扮',
            route: '/skin',
            width: 750,
            height: 480,
            modal: true,
            parent: winCfg.window.id,
            resize: false,
        })
    }

    大家如果对electron创建多窗口模式感兴趣的话,可以去看看下面这篇文章。

    https://www.cnblogs.com/xiaoyan2017/p/14403820.html

    ◆ electron实现无边框Mac导航栏效果

    如上图:顶部导航栏默认是Mac风格,也支持自定义标题、背景/文字颜色、是否沉浸式透明背景等功能。

    设置 -webkit-app-region: drag 实现导航条可拖拽,标题及按钮 -webkit-app-region:no-drag 可响应点击事件。

    <!-- //顶部导航 -->
    <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>

    对于自定义导航条的实现方式,由于之前有过相关分享文章,这里就不详细介绍了。

    https://www.cnblogs.com/xiaoyan2017/p/14449570.html

    ◆ Vite2|electron项目布局模板

    为了使得项目分层结构更加清晰,布局分为 Auth 和 Main 两大模块。

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

    ◆ 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()
    })

    ◆ Vue-I18n国际化解决方案

    项目中路由采用了 vue-i18n 国际化,支持中文|繁体|英文三种语言。

    目前vue-i18n插件支持vue3项目了,大家需安装最新版本即可。

    npm i vue-i18n@next -D

    如上图:新建locale目录用来处理相应模块语言配置。

    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"