系统简介

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

用户登录

登录页面代码

<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>

登录逻辑代码

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布局代码

<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相关逻辑

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来创建地图实例;
  • 本笔记主要就后台管理系统做笔记分析,高德地图此处不做过多介绍,若想进一步了解,请前往高德开放平台进行了解学习。

数据管理

<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>

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

视频播放器

<template>
<el-card shadow="never" class="index">
<template #header>
<div class="card_header">
<b>西瓜播放器</b>
</div>
</template>
<div id="xg"></div>
</el-card>
</template> <script>
import { onMounted, onBeforeUnmount, getCurrentInstance, ref } from "vue";
import Player from "xgplayer"; export default {
setup() {
const { proxy } = getCurrentInstance(); let player;
onMounted(() => {
initPlayer();
}); onBeforeUnmount(() => {
player.destroy();
player = null;
}); const initPlayer = () => {
player = new Player({
id: "xg",
url: "https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4",
poster: "https://img03.sogoucdn.com/app/a/07/f13b5c3830f02b6db698a2ae43ff6a67",
fitVideoSize: "auto",
fluid: true /* 流式布局 */,
// download: true /* 视频下载 */
// pip: true /* 画中画 */,
// errorTips: `请<span>刷新页面</span>试试` /* 自定义错误提示 */,
lang: "zh-cn"
});
}; return {};
}
};
</script> <style lang="scss" scoped>
.card_header {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>

注:

  • 安装西瓜视频播放器:yarn add xgplayer
  • 西瓜播放器官方文档:http://v2.h5player.bytedance.com/
  • 西瓜播放器适合手机版和PC电脑版视频点播或直播使用,详细参数配置请参考官方文档。

富文本编辑器

富文本编辑器插件封装

<template>
<div ref="editor" class="editor_ref"></div>
</template> <script>
import { onMounted, onBeforeUnmount, watch, getCurrentInstance, ref } from "vue";
import WEditor from "wangeditor"; export default {
props: {
defaultText: { type: String, default: "" }
},
setup(props, context) {
const { proxy } = getCurrentInstance();
const editor = ref(); let instance;
onMounted(() => {
initEditor();
}); onBeforeUnmount(() => {
instance.destroy();
instance = null;
}); watch(
() => props.defaultText,
nv => {
instance.txt.html(nv);
!!nv && context.emit("richHtml", nv);
}
); const initEditor = () => {
instance = new WEditor(editor.value);
// 配置富文本
Object.assign(instance.config, {
zIndex: 100,
// placeholder: "" /* 提示文字 */,
showFullScreen: true /* 显示全屏按钮 */,
showLinkImg: true /* 显示插入网络图片 */,
showLinkVideo: true /* 显示插入网络视频 */,
onchangeTimeout: 400 /* 触发 onchange 的时间频率,默认 200ms */,
uploadImgMaxLength: 1 /* 单次上传图片数量限制 */,
uploadImgMaxSize: 5 * 1024 * 1024 /* 上传图片大小限制 */,
uploadVideoAccept: ["mp4", "mov"] /* 上传视频格式限制 */,
uploadVideoMaxSize: 1024 * 1024 * 1024 /* 上传视频大小限制1024m */,
excludeMenus: ["strikeThrough", "todo", "code"] /* 移除系统菜单 */,
customAlert(msg, type) {
type == "success" ? proxy.$message.success(msg) : proxy.$message.error(msg);
},
customUploadImg(resultFiles, insertImgFn) {
/**
* @param {Object} file - 文件对象
* @param {String} rootPath - 文件根路径(默认为空、例:“filepath/”)
* @param {Array} fileType - 文件类型限制(默认 [] 不限制,例:['.png','.jpeg'])
* @param {Number} size - 文件大小限制(单位:兆、默认 0 不限制、例:1)
**/
proxy.$oss(resultFiles[0]).then(imgUrl => !!imgUrl && insertImgFn(imgUrl));
}, customUploadVideo(resultFiles, insertVideoFn) {
proxy.$oss(resultFiles[0]).then(videoUrl => !!videoUrl && insertVideoFn(videoUrl)); /* 参数同上 */
},
onchange(nv) {
context.emit("richHtml", nv);
}
});
instance.create();
}; return { editor };
}
};
</script> <style scoped>
div.editor_ref :deep(iframe) {
max-width: 100%;
max-height: auto;
width: 360px;
height: 180px;
}
</style>

组件内使用

<template>
<el-card shadow="never" class="index">
<template #header>
<div class="card_header">
<b>富文本编辑器</b>
</div>
</template>
<!-- 富文本 -->
<WEditor :defaultText="defaultText" @richHtml="getRichHtml" />
</el-card>
</template> <script>
import { onMounted, ref } from "vue";
import WEditor from "../../components/WEditor.vue"; export default {
components: { WEditor },
setup() {
const defaultText = ref("");
const richText = ref(""); onMounted(() => {
// 初始化数据
defaultText.value = "<h1>Editor</h1>";
}); const getRichHtml = nv => {
richText.value = nv;
}; return { defaultText, getRichHtml };
}
};
</script>

注:

  • 此次是基于Vue3封装的富文本编辑器,编辑器使用的是开源的富文本编辑器wangeditor;
  • 代码块一是基于官方文档和配置信息对富文本编辑器进行的相关配置,其中富文本编辑器使用的ali-OSS的云存储,若想详细了解请参照之前的“阿里云文件直传”博客笔记进行了解和学习;
  • ref相当于DOM元素的Id,要保持唯一,若一个页面要使用多个富文本编辑器,请做好区分,以便于区分组件的数据。

个人中心

总结

本篇文章主要介绍使用element-plus进行页面的布局和数据展示处理,后续笔记将继续分享和介绍动态路由菜单的处理,以及用户权限的动态校验。(。・・)ノ

源码地址

Vue3后台管理系统源代码地址

vue3后台管理系统(模板)的更多相关文章

  1. vue3项目后台管理系统模板

    Vue3.0 发布第一个版本至今有一段时间了,到现在一直在更新优化,在性能方面,对比 Vue2.x ,性能的提升比较明显,打包后体积更小 来看下 Vue3.x 新增了哪些功能和特性. Performa ...

  2. VUE3后台管理系统【路由鉴权】

    前言: 在"VUE3后台管理系统[模板构建]"文章中,详细的介绍了我使用vue3.0和vite2.0构建的后台管理系统,虽然只是简单的一个后台管理系统,其中涉及的技术基本都覆盖了, ...

  3. Admin Panel – 非常漂亮的后台管理系统模板

    网站或者应用系统的管理后台的设计虽然不像前台界面那样要求设计精美,但是也需要有清晰的管理模块划分,下面分享的这个后台管理模板的设计非常漂亮,特别是导航部分,头部还有未读的短消息和提醒的条数显示.赶紧下 ...

  4. easyui+ztree 后台管理系统模板

    用easyui+ztree做了个后台管理系统模板,效果图: 下载地址: csdn:http://download.csdn.net/detail/jackpay/6744505 github:http ...

  5. 3YAdmin-专注通用权限控制与表单的后台管理系统模板

    3YAdmin基于React+Antd构建.GitHub搜索React+Antd+Admin出来的结果没有上百也有几十个,为什么还要写这个东西呢? 一个后台管理系统的核心我认为应该是权限控制,表单以及 ...

  6. Bootstrap 轻量级后台管理系统模板--ACE使用介绍

    在上一篇基于Bootstrap介绍了一个免费的后台管理模板Charisma UI. 参见链接: 基于Jquery.Bootstrap的后台管理免费UI框架推荐--Charisma UI 今天继续分享一 ...

  7. SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后端篇(五): 数据表设计、使用 jwt、redis、sms 工具类完善注册登录逻辑

    (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(一):搭建基本环境:https://www.cnblogs.com/l-y-h/p ...

  8. SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后端篇(一): 搭建基本环境、整合 Swagger、MyBatisPlus、JSR303 以及国际化操作

    相关 (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(一):搭建基本环境:https://www.cnblogs.com/l-y- ...

  9. vue+element-ui JYAdmin后台管理系统模板-集成方案【项目搭建篇2】

    项目搭建时间:2020-06-29 本章节:讲述基于vue/cli, 项目的基础搭建. 本主题讲述了: 1.跨域配置 2.axios请求封装 3.eslint配置 4.环境dev,test,pro(开 ...

随机推荐

  1. 抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext

    长话短说,本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext 引言 C#异步编程语法糖async/await,使开发者很容易就能编写异步代码. ...

  2. rocketmq常见问题及使用 新手篇

    一 部署阶段 1.启动命令 nameServer启动:nohup sh bin/mqnamesrv  -n ip地址:9876 & broker启动:nohup sh bin/mqbroker ...

  3. PHP实现简单的socket与异步应用

    1.socket应用 (1)简单概念 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建立网络通信连接至少要一对端口号(socket).socket本质是编 ...

  4. fragment textWatcher的设置位置

    override fun onStart() { super.onStart() Log.d("------------", "1") val titleWat ...

  5. Jmeter+Ant+Jenkins接口自动化框架

    最近应公司要求,搭建一套接口自动化环境.看到通知邮件,没有多想就确定了Jmeter路线.可能有些人会 说,为啥不用python,相对而言高大上一些.因为公司内部现在项目有用到Jmeter,正好可以结合 ...

  6. 2021 docker安装宝塔面板

    拉取CentOS镜像 docker pull centos 创建 docker 容器 启动镜像,映射主机与容器内8888(宝塔面板).888(PHPMYADMIN)端口 -v 挂在目录 为了能够保存( ...

  7. zk客户端及锁的使用

    1.生成zk客户端对象 private CuratorFramework buildClient() { logger.info("zookeeper registry center ini ...

  8. 微信架构 & 支付架构(下)

    微信架构 & 支付架构(下) 3. 管理网络请求 首先看看原来 iOS 处理支付网络请求的缺陷: 原来支付的请求,都是通过一个单例网络中心去发起请求,然后收到回包后,通过抛通知,或者调用闭包的 ...

  9. Paddle Inference原生推理库

    Paddle Inference原生推理库 深度学习一般分为训练和推理两个部分,训练是神经网络"学习"的过程,主要关注如何搜索和求解模型参数,发现训练数据中的规律,生成模型.有了训 ...

  10. list 分批导入db, 每1000条数据一批 , 从字符串中获取数字,小数, 版本号比较

    //这个有个弊端: 分组后分批导入, 是阻塞的,我没有导入完成,别人就不能导入, 这里可以优化成异步,线程池 public static void main(String[] args) { Rand ...