ElectronVue3Admin 轻量级中后台前端管理系统|electron+vite2后台框架

electron-vite-admin 基于 electron+vite.js 整合开发的后台管理框架

本项目基于 vite2+electron12+vue3+vuex+element-plus+vue-i18n+echarts 等技术栈搭建开发,所有的请求数据都使用Mock.js进行模拟。支持动态权限控制、整合i18n国际化解决方案。

实现技术

  • 编码工具:vscode
  • vue3框架:vue3.0+vuex4+vue-router@4
  • 跨端框架:electron^12.0.4
  • 构建打包:vite.js + 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

支持动态化主题换肤国际化多语言配置(中英文/繁体),自定义实时导航栏标题

需提前在本地安装 node.js 和 @vue/cli。本项目技术栈基于 VScode、vite2、electron12、vue3、vuex、vue-router 、element-plus、vue-i18n、echarts,提前了解和学习这些知识会对项目开发有很大的帮助。

项目目录结构

vue3.x,vite2,electron12跨平台后台管理框架模板 electron-vite2-vue3-admin支持电脑、平板响应式布局。

主入口main.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')
})

VueRouter路由配置

使用了el-loading显示加载提示。大家也可以选择NProgress组件。

/**
 * 路由配置 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.js+electron无边框Mac导航条

导航栏标题根据路由而动态改变。支持自定义背景色、标题颜色及镂空背景等功能。

<!-- //仿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>

electron自定义顶部导航栏功能

Vite.js动态化标题Hook

通过监听路由来实时改变导航条标题。

import { onMounted, watchEffect } from "vue"
import { useI18n } from "vue-i18n"
import store from "@/store"

export default function useTitle(route) {
    if(!route.meta) return

    const { t } = useI18n()
    const defaultTitle = 'Electron-Vue3-Vadmin'

    const Title = async () => {
        if(route.meta.title) {
            document.title = `${t(route.meta.title)} - ${defaultTitle}`
        }else {
            document.title = defaultTitle
        }
        store.commit('SET_WINTITLE', document.title)
    }

    watchEffect(Title)

    onMounted(() => {
        Title()
    })
}

Vite.js+Echarts图表Hook

由于多处需要使用图表功能,只能自定义一个Hook函数来封装调用。实时监听Dom尺寸变化使用了element-resize-detector组件。

/**
 * 动态化图表Hook
 * @author XiaoYan
 */

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
        }
        // window.addEventListener('resize', handleResize)
        erd.listenTo(refs.value, handleResize)
    })

    onBeforeUnmount(() => {
        chartInst.dispose()
        // window.removeEventListener('resize', handleResize)
        erd.removeListener(refs.value, handleResize)
    })

    return chartRef
}

主模块模板

<!-- //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-i18n国际化语言配置

需要安装vue-i18n国际化方案,目前已经支持vue3版本。

npm i vue-i18n@next

新建i18n.js文件配置国际化语言。

/**
 * @desc	vue-i18n国际化配置文件
 * @Time	andy by 2021-03
 * @About	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 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.js中引入配置。

// 引入element-plus组件库
import ElPlus from 'element-plus'

// 引入多语言
import VueI18n, { ElPlusLang, getLang } from '@/plugins/i18n'

app.use(ElPlus, {
    size: 'small',
    locale: ElPlusLang[getLang()]
})
app.use(VueI18n)

路由权限管理

新建一个permission.vue用来判断控制路由权限。

<!-- //权限验证模板 -->
<template>
  <slot v-if="isPermission"/>
  <slot v-else name="tooltips">
    <el-alert title="对不起,您没有权限操作此页面!" type="error" show-icon></el-alert>
  </slot>
</template>
<script>
import { computed } from "vue";
import { useStore } from "vuex";
import { getPermissionRoute } from "@/utils/routes";
export default {
  props: { roles: { type: [String, Array] } },
  components: {},
  setup(props) {
    const store = useStore();
    // 判断是否有权限
    const isPermission = computed(() =>
      getPermissionRoute(JSON.stringify(store.state.roles), props.roles)
    );
    return { isPermission };
  }
};
</script>

通过如下的方式调用即可。

<Permission roles="user">
    <template #tooltips>
        <h2 style="color:red;">无权操作User模块。</h2>
    </template>
    <el-button type="primary" icon="el-icon-plus">新增</el-button>
</Permission>

<el-divider />

<Permission roles="editor">
    <template #tooltips>
        <h2 style="color:red;">无权操作Editor模块。</h2>
    </template>
    <el-button type="primary" icon="el-icon-edit">编辑</el-button>
    <el-button type="warning" icon="el-icon-delete">删除</el-button>
</Permission>

end~ 以上就是基于vite.js+electron开发后台管理系统的一些技术分享,希望大家喜欢哈!

最后放上一个Electron+Vite小视频|直播实例项目

https://blog.csdn.net/yanxinyun1990/article/details/115262402

 

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyan_2018

你的鼓励将是我持续作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值