vue3后台管理系统(模板)

2021-11-25 15:11:00 浏览数 (1)

系统简介

  • 此管理系统是基于Vite2和Vue3.0构建生成的后台管理系统。目的在于学习vite和vue3等新技术,以便于后续用于实际开发工作中;
  • 本文章将从管理系统页面布局、vue路由鉴权、vuex状态管理、数据持久化、用户信息加密等方面进行介绍和记录;
  • 这也是我边学习边实践的过程,此次记录一是方便自己日后开发过程中有用到时候便于借鉴和复习,再次是为了初学vue3和尝试上手vite2和vue3搭建管理系统的小伙伴提供一些学习方法和技术点;
  • 本Vue后台管理系统使用的技术点主要有:vite2、vue3、vue-router4.x、vuex4.x、vuex-persistedstate(vuex数据持久化)、Element Plus等。

用户登录

登录页面代码
代码语言:javascript复制
<template>
    <div class="login">
        <el-card class="login_center">
            <template #header>
                <div class="card_header">
                    <span>用户登录</span>
                </div>
            </template>
            <el-form :model="loginFormState" :rules="rules" ref="loginFormRef">
                <el-form-item prop="name">
                    <el-input
                        prefix-icon="el-icon-user-solid"
                        v-model.trim="loginFormState.name"
                        maxlength="32"
                        placeholder="请输入账号"
                        clearable
                    ></el-input>
                </el-form-item>
                <el-form-item prop="pwd">
                    <el-input
                        prefix-icon="el-icon-lock"
                        v-model.trim="loginFormState.pwd"
                        maxlength="16"
                        show-password
                        placeholder="请输入密码"
                        clearable
                        @keyup.enter.exact="handleLogin"
                    ></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" style="width: 100%" :loading="loginFormState.loading" @click="handleLogin">登 录</el-button>
                </el-form-item>
            </el-form>
        </el-card>
    </div>
</template>
登录逻辑代码
代码语言:javascript复制
import { getCurrentInstance, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import { encode } from "js-base64";
​
export default {
    setup() {
        const { proxy } = getCurrentInstance();
        const router = useRouter();
        const store = useStore();
        const loginFormRef = ref();
​
        const loginFormState = reactive({
            name: "",
            pwd: "",
            loading: false
        });
​
        const rules = {
            name: [{ required: true, message: "账号不能为空", trigger: "blur" }],
            pwd: [
                { required: true, message: "密码不能为空", trigger: "blur" },
                { min: 5, max: 16, message: "密码长度为5-16位", trigger: "blur" }
            ]
        };
​
        const handleLogin = () => {
            loginFormRef.value.validate(valid => {
                if (!valid) {
                    return false;
                }
​
                loginFormState.loading = true;
​
                let params = { name: loginFormState.name, pwd: loginFormState.pwd };
​
                setTimeout(() => {
                    let users = { role: loginFormState.name === "admin" ? "admin" : "", username: loginFormState.name };
                    Object.assign(params, users);
                    sessionStorage.setItem("jwt", encode(JSON.stringify(params)));
                    store.dispatch("setUser", params);
                    loginFormState.loading = false;
                    router.replace("/");
                }, 1000);
​
                // proxy.$axios
                //  .post("/user/login", proxy.$qs.stringify(params))
                //  .then(res => {
                //      let { code, result_data, message } = res.data;
                //      if (code == 1) {
                //          console.log("login_success", result_data);
                //          ElMessage.success("登录成功");
                //      } else {
                //          ElMessage.error("登录失败:"   message);
                //      }
                //  })
                //  .catch(err => {
                //      console.log("login err", err);
                //      ElMessage.error("登录失败");
                //  });
            });
        };
​
        return { loginFormRef, loginFormState, rules, handleLogin };
    }
};
登录简介:
  • 登录页面采用的是一级录用,与控制台的路由同级,这样写便于对vue-router路由权限校验的控制;
  • 在vue2中我们频繁使用 this 来处理事件函数和组件数据,vue3大多事件函数和数据状态的存储基本都实在setup函数中完成的,在vue3中无法通过 this 来获取当前组件的实例,故无法像vue2中那样操作数据和事件函数;
  • vue3中为了获取到当前组件的实例,我们可以采用 vue3 中提供的 getCurrentInstance 来获取组件的实例;
  • 当我们使用全局对象或者函数时,我们大多是将事件函数绑定在vue的原型实例上,当再次访问时只需使用过this来访问自己指定的事件名即可;
  • 在vue3中我们若是使用全局变量或者事件函数时,我们需要借助 globalProperties 来实现全局事件函数的绑定;此时在需要使用的地方可以通过当前组件实例来访问全局的 property 属性;
  • 对登录用的的信息进行加密处理,我采用的是 js-base64 的 encode 方法来实现登录信息的加密。使用方式为:encode(“需要加密的JSON字符串”)。

系统主页

Layout布局代码
代码语言:javascript复制
<template>
    <el-header height="56px">
        <!-- header -->
        <div class="header_left">Element-Plus Create By Vite</div>
        <div class="header_right">
            <!-- 退出全屏、进入全屏按钮 -->
            <el-tooltip :content="isFullScreen ? '退出全屏' : '全屏'">
                <i class="el-icon-full-screen" @click="handleFullScreen"></i>
            </el-tooltip>
            <!-- 下拉菜单 -->
            <el-dropdown size="medium" @command="handleCommand">
                <!-- 用户信息 -->
                <div class="user_info">
                    <!-- 用户头像 -->
                    <el-avatar :size="36" :src="avatar" />
                    <!-- 用户名宁 -->
                    <span class="username">{{ userName }}</span>
                </div>
                <template #dropdown>
                    <!-- 折叠菜单 -->
                    <el-dropdown-menu>
                        <el-dropdown-item icon="el-icon-user" command="user">个人中心</el-dropdown-item>
                        <el-dropdown-item icon="el-icon-switch-button" command="logout">退出登录</el-dropdown-item>
                    </el-dropdown-menu>
                </template>
            </el-dropdown>
        </div>
    </el-header>
</template>
​
<!-- 二级路由公用路由页面 -->
<template>
    <router-view v-slot="{ Component }">
        <transition name="fade" mode="out-in">
            <component :is="Component" />
        </transition>
    </router-view>
</template>
主页Header相关逻辑
代码语言:javascript复制
import { computed, getCurrentInstance, reactive, toRefs } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import screenfull from "screenfull";
import avatar from "@/assets/img/admin.png";
​
export default {
    setup() {
        const { proxy } = getCurrentInstance();
        const router = useRouter();
        const store = useStore();
​
        const state = reactive({
            isFullScreen: false,
            avatar,
            screenfull
        });
        const userName = computed(() => store.getters.getUserName);
​
        const handleCommand = command => {
            if (command === "user") {
                router.push("/user");
            } else {
                proxy.$message.success("退出成功");
                store.dispatch("clearUser");
                router.replace("/login");
                sessionStorage.clear();
                localStorage.clear();
            }
        };
​
        const handleFullScreen = () => {
            if (screenfull.isEnabled) {
                state.isFullScreen = !state.isFullScreen;
                screenfull.toggle();
            }
        };
​
        return {
            userName,
            handleCommand,
            handleFullScreen,
            ...toRefs(state)
        };
    }
};

注:

  • Header分左右两部分,其中左侧为系统的名字,右侧为用户登录的账户相关的信息以及进入和退出全屏的按钮;
  • 不同用户权限会对应不同的账户头像,会对不同账户的用户权限做相应的限制处理;
  • 全屏的切换借助的是第三方的插件进行处理的,此方式减少代码量的同时也减少了不同浏览器兼容性问题的出现;
  • 退出账户逻辑的处理,当用户点击退出账户的时候进行相应的退出登录的弹窗提示,在退出后进行数据的初始化和本地存储信息的清除处理,并跳转到用户登录页。
  • 主页使用了地图模块,地图模块是借助的“高德地图”API实现的H5版的网页地图,此Demo需要使用注册高德地图开发者来获取开发的keys来创建地图实例;
  • 本笔记主要就后台管理系统做笔记分析,高德地图此处不做过多介绍,若想进一步了解,请前往 高德开放平台进行了解学习。

数据管理

代码语言:javascript复制
<template>
    <el-card shadow="never" class="index">
        <template #header>
            <div class="card_header">
                <b>数据列表</b>
            </div>
        </template>
        <el-empty description="暂无数据"></el-empty>
    </el-card>
</template>
​
<script></script>
​
<style lang="scss" scoped>
.card_header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
</style>

注:没有数据时的提示信息;

视频播放器

代码语言:javascript复制
<template>
    <el-card shadow="never" class="index">
        <template #header>
            <div class="card_header">
                <b>


	

0 人点赞