Vue + Element UI 前端篇(十二):用户管理模块
Vue + Element UI 实现权限管理系统 前端篇(十二):用户管理模块
用户管理模块
添加接口
在 http/moduls/user.js 中添加用户管理相关接口。
import axios from '../axios'/* * 用户管理模块*/// 保存 export const save = (params) => {return axios({url: '/user/save',method: 'post',params}) }// 删除 export const del = (params) => {return axios({url: '/user/delete',method: 'post',params}) } // 分页查询 export const findPage = (params) => {return axios({url: '/user/findPage',method: 'post',params}) }
模拟数据
在 mock/moduls/user.js 中添加用户管理相关mock接口。
/* * 用户管理模块*/// 保存 export function save() {return {url: 'http://localhost:8080/user/save',type: 'post',data: {"code": 200,"msg": null,"data": 1}} }// 删除 export function del() {return {url: 'http://localhost:8080/user/delete',type: 'post',data: {"code": 200,"msg": null,"data": 1}} } // 分页查询 export function findPage() {return {url: 'http://localhost:8080/user/findPage',type: 'post',data: findPageData} }
提取根路径
为了可以统一控制mock的开启与关闭,把mock的根路径提取出来。
而具体的Mock接口,把根路径移除,因为在生成Mock的时候会自动把根路径加上去。
用户界面
用户管理界面主要是用户信息的表格展示,并提供基础的增删改查功能。
User.vue
<template><div class="container" style="width:100%;"><!--工具栏--><div class="toolbar" style="float:left; padding:18px;"><el-form :inline="true" :model="filters" size="small"><el-form-item><el-input v-model="filters.name" placeholder="用户名"></el-input></el-form-item><el-form-item><el-button type="primary" v-on:click="findPage(null)">查询</el-button></el-form-item><el-form-item><kt-button label="新增" perms="sys:user:add" type="primary" @click="handleAdd" /></el-form-item></el-form></div><!--表格内容栏--><kt-table permsEdit="sys:user:edit" permsDelete="sys:user:delete":data="pageResult" :columns="columns" @findPage="findPage" @handleEdit="handleEdit" @handleDelete="handleDelete"></kt-table><!--新增编辑界面--><el-dialog :title="operation?'新增':'编辑'" width="40%" :visible.sync="editDialogVisible" :close-on-click-modal="false"><el-form :model="dataForm" label-width="80px" :rules="dataFormRules" ref="dataForm"><el-form-item label="ID" prop="id"><el-input v-model="dataForm.id" :disabled="true" auto-complete="off"></el-input></el-form-item><el-form-item label="用户名" prop="name"><el-input v-model="dataForm.name" auto-complete="off"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input v-model="dataForm.password" type="password" auto-complete="off"></el-input></el-form-item><el-form-item label="机构" prop="deptName"><popup-tree-input :data="deptData" :props="deptTreeProps" :prop="dataForm.deptName" :nodeKey="''+dataForm.deptId" :currentChangeHandle="deptTreeCurrentChangeHandle"></popup-tree-input></el-form-item><el-form-item label="邮箱" prop="email"><el-input v-model="dataForm.email" auto-complete="off"></el-input></el-form-item><el-form-item label="手机" prop="mobile"><el-input v-model="dataForm.mobile" auto-complete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click.native="editDialogVisible = false">取消</el-button><el-button type="primary" @click.native="editSubmit" :loading="editLoading">提交</el-button></div></el-dialog></div> </template><script> import PopupTreeInput from "@/components/PopupTreeInput" import KtTable from "@/views/Core/KtTable" import KtButton from "@/views/Core/KtButton" export default {components:{PopupTreeInput,KtTable,KtButton},data() {return {filters: {name: ''},columns: [{prop:"id", label:"ID", minWidth:40, sortable:"false"},{prop:"name", label:"用户名", minWidth:120, sortable:"true"},{prop:"deptName", label:"机构", minWidth:120, sortable:"true"},{prop:"email", label:"邮箱", minWidth:120, sortable:"true"},{prop:"mobile", label:"手机", minWidth:120, sortable:"true"}],pageRequest: { pageNum: 1, pageSize: 8 },pageResult: {},operation: false, // true:新增, false:编辑editDialogVisible: false, // 新增编辑界面是否显示editLoading: false,dataFormRules: {name: [{ required: true, message: '请输入用户名', trigger: 'blur' }]},// 新增编辑界面数据dataForm: {id: 0,name: '',password: '123456',deptId: 1,deptName: '',email: 'test@qq.com',mobile: '13889700023',status: 1},deptData: [],deptTreeProps: {label: 'name',children: 'children'}}},methods: {// 获取分页数据findPage: function (data) {if(data !== null) {this.pageRequest = data.pageRequest}this.pageRequest.columnFilters = {name: {name:'name', value:this.filters.name}}this.$api.user.findPage(this.pageRequest).then((res) => {this.pageResult = res.data})},// 批量删除handleDelete: function (data) {this.$api.user.batchDelete(data.params).then(data.callback)},// 显示新增界面handleAdd: function () {this.editDialogVisible = truethis.operation = truethis.dataForm = {id: 0,name: '',password: '',deptId: 1,deptName: '',email: 'test@qq.com',mobile: '13889700023',status: 1}},// 显示编辑界面handleEdit: function (params) {this.editDialogVisible = truethis.operation = falsethis.dataForm = Object.assign({}, params.row)},// 编辑editSubmit: function () {this.$refs.dataForm.validate((valid) => {if (valid) {this.$confirm('确认提交吗?', '提示', {}).then(() => {this.editLoading = truelet params = Object.assign({}, this.dataForm)this.$api.user.save(params).then((res) => {this.editLoading = falsethis.$message({ message: '提交成功', type: 'success' })this.$refs['dataForm'].resetFields()this.editDialogVisible = falsethis.findPage(null)})})}})},// 获取部门列表findDeptTree: function () {this.$api.dept.findDeptTree().then((res) => {this.deptData = res.data})},// 菜单树选中deptTreeCurrentChangeHandle (data, node) {this.dataForm.deptId = data.idthis.dataForm.deptName = data.name}},mounted() {this.findDeptTree()} } </script><style scoped></style>
表格组件封装
为了可以实现表格的代码复用,封装表格组件。
src/views/Core/KtTable.vue
<template><div><!--表格栏--><el-table :data="data.content" stripe highlight-current-row @selection-change="selectionChange" :v-loading="loading" :max-height="maxHeight" :size="size" :align="align" style="width:100%;" ><el-table-column type="selection" width="40"></el-table-column><el-table-column v-for="column in columns" :prop="column.prop" :label="column.label" :width="column.width" :min-width="column.minWidth" :sortable="column.sortable" :fixed="column.fixed" :key="column.prop" :type="column.type"></el-table-column><el-table-column label="操作" width="150" fixed="right"><template slot-scope="scope"><kt-button label="编辑" :perms="permsEdit" :size="size" @click="handleEdit(scope.$index, scope.row)" /><kt-button label="删除" :perms="permsDelete" :size="size" type="danger" @click="handleDelete(scope.$index, scope.row)" /></template></el-table-column></el-table><!--分页栏--><div class="toolbar" style="padding:10px;"><kt-button label="批量删除" :perms="permsDelete" :size="size" type="danger" @click="handleBatchDelete()" :disabled="this.selections.length===0" style="float:left;"/><el-pagination layout="total, prev, pager, next, jumper" @current-change="refreshPageRequest" :current-page="pageRequest.pageNum" :page-size="pageRequest.pageSize" :total="data.totalSize" style="float:right;"></el-pagination></div></div> </template><script> import KtButton from "@/views/Core/KtButton" export default {name: 'KtTable',components:{KtButton},props: {columns: Array, // 表格列配置data: Object, // 表格分页数据permsEdit: String, // 编辑权限标识permsDelete: String, // 删除权限标识size: { // 尺寸样式type: String,default: 'mini'},align: { // 文本对齐方式type: String,default: 'left'},maxHeight: { // 表格最大高度type: Number,default: 420}},data() {return {// 分页信息pageRequest: {pageNum: 1,pageSize: 8},loading: false, // 加载标识selections: [] // 列表选中列}},methods: {// 分页查询findPage: function () {this.$emit('findPage', {pageRequest:this.pageRequest})},// 选择切换selectionChange: function (selections) {this.selections = selections},// 换页刷新refreshPageRequest: function (pageNum) {this.pageRequest.pageNum = pageNumthis.findPage()},// 编辑handleEdit: function (index, row) {this.$emit('handleEdit', {index:index, row:row})},// 删除handleDelete: function (index, row) {this.delete(row.id)},// 批量删除handleBatchDelete: function () {let ids = this.selections.map(item => item.id).toString()this.delete(ids)},// 删除操作delete: function (ids) {this.$confirm('确认删除选中记录吗?', '提示', {type: 'warning'}).then(() => {let params = []let idArray = (ids+'').split(',')for(var i=0; i<idArray.length; i++) {params.push({'id':idArray[i]})}let callback = res => {this.$message({message: '删除成功', type: 'success'})this.findPage()}this.$emit('handleDelete', {params:params, callback:callback})}).catch(() => {})}},mounted() {this.refreshPageRequest(1)} } </script><style scoped></style>
权限按钮封装
为了可以实现对表格数据进行新增、编辑、删除操作按钮的权限控制,封装权限按钮组件。
src/views/Core/KtButton.vue
<template><el-button :size="size" :type="type" :loading="loading" :disabled="!hasPerms(perms)" @click="handleClick">{{label}}</el-button> </template><script> import { hasPermission } from '@/permission/index.js' export default {name: 'KtButton',props: {label: {type: String,default: 'Button'},size: {type: String,default: 'mini'},type: {type: String,default: null},loading: {type: Boolean,default: false},disabled: {type: Boolean,default: false},perms: {type: String,default: null}},data() {return {}},methods: {handleClick: function () {this.$emit('click', {})}, hasPerms: function (perms) {return hasPermission(perms) & !this.disabled}},mounted() {} } </script><style scoped></style>
测试效果
测试效果如下,增删改功能,mock不能实际操作数据库,可以结合本教程的后端代码一起测试。
源码下载
后端:kitty: 基于Spring Boot、Spring Cloud、Vue.js 、Element UI实现,采用前后端分离架构的权限管理系统,JAVA快速开发平台。
前端:kitty-ui: Kitty 前端,基于 Vue + Element 实现的权限管理系统。
相关文章:

Vue + Element UI 前端篇(十二):用户管理模块
Vue Element UI 实现权限管理系统 前端篇(十二):用户管理模块 用户管理模块 添加接口 在 http/moduls/user.js 中添加用户管理相关接口。 import axios from ../axios/* * 用户管理模块*/// 保存 export const save (params) > {ret…...

C# 设计保存文件
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...

Leetcode 1486.数组异或操作
给你两个整数,n 和 start 。 数组 nums 定义为:nums[i] start 2*i(下标从 0 开始)且 n nums.length 。 请返回 nums 中所有元素按位异或(XOR)后得到的结果。 示例 1: 输入:n 5, …...

【Java】Java核心API概述
Java核心API是Java编程语言的基础,包含了Java应用程序中常用的类和接口。本文将介绍Java核心API中的一些重要部分,包括输入输出流、异常处理、集合框架、多线程和网络编程等。 1、输入输出流 Java的输入输出流API是Java IO,它提供了处理输入…...

微信小程序检查版本更新
新建文件 version-util.js // 小程序启动时检查版本 class VersionUtil {/*** 检查更新*/checkUpdate(){const updateManager wx.getUpdateManager();updateManager.onCheckForUpdate((hasUpdate)>{if(hasUpdate){updateManager.onUpdateReady(()>{wx.showModal({title…...

Linux查看是虚拟机还是物理机
第一种方式:dmesg命令 [roottest ~]# dmesg | grep -i hypervisor [ 0.000000] Hypervisor detected: VMware [ 0.001000] TSC freq read from hypervisor : 2903.999 MHz [ 6.311621] [drm] Max dedicated hypervisor surface memory is 0 kiB第二种方式…...

【数据结构】二叉搜索树——二叉搜索树的概念和介绍、二叉搜索树的简单实现、二叉搜索树的增删查改
文章目录 二叉搜索树1. 二叉搜索树的概念和介绍2. 二叉搜索树的简单实现2.1二叉搜索树的插入2.2二叉搜索树的查找2.3二叉搜索树的遍历2.4二叉搜索树的删除2.5完整代码和测试 二叉搜索树 1. 二叉搜索树的概念和介绍 二叉搜索树又称二叉排序树,它或者是一棵空树&…...

通过linux定时任务删除es日志索引
能过linux定时任务删除es日志索引 项目用上了elk,产生的日志索引要定时,其一个方法,通过linux定时任务,调用es接口删除索引。 #!/bin/bash #删除ELK30天前的日志 #计算索引名称包含的日期,比如这里是 %Y.%m.%d (2023…...

【跟小嘉学 Rust 编程】二十二、常用 API
系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

【ES6】Class中this指向
先上代码: 正常运行的代码: class Logger{printName(name kexuexiong){this.print(hello ${name});}print(text){console.log(text);} }const logger new Logger(); logger.printName("kexueixong xiong");输出: 单独调用函数p…...

Python 编程竟然如此幽默!揭秘程序员们的搞笑日常,快来看看吧!
食用原文效果更佳,原文链接 Python 编程竟然如此幽默!揭秘程序员们的搞笑日常,快来看看吧! 在 Python 编程的世界里,充满了智慧与创造力。 当然,也少不了轻松幽默的段子,这些段子让程序员们在…...

Linux c++开发-03-使用CMake组织工程
一、简单文件的编译 有如下的目录结构: 其中 helloworld.cpp如下: #include <iostream> using namespace std; int main() {printf("hello world my name is Ty!");return 0; }CMakeLists.txt如下: cmake_minimum_requir…...

【C++】函数重载 ④ ( 函数指针定义的三种方式 | 直接定义函数指针 | 通过 函数类型 定义 函数指针 | 通过 函数指针类型 定义 函数指针 )
文章目录 一、函数指针定义方法1、直接定义函数指针2、通过 函数类型 定义 函数指针3、通过 函数指针类型 定义 函数指针4、代码示例 - 不同方式定义函数指针 博客总结 : 重载函数 : 使用 相同 的 函数名 , 定义 不同 的 函数参数列表 ;判定标准 : 只有 函数参数 的 个数 / 类…...

异常-java
目录 一、异常的概念和体系结构 1.1 异常的概念 1.2 异常的体系结构 1.3 异常的分类 二、异常的处理 2.1 防御式编程 2.2 异常抛出 2.3 异常捕获 2.4 异常处理流程 三、自定义异常类 一、异常的概念和体系结构 1.1 异常的概念 程序员在开发过程中,想要将代码写得…...

软件测试/测试开发丨Selenium Web自动化测试 高级控件交互方法
点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接:https://ceshiren.com/t/topic/27045 一、使用场景 使用场景对应事件复制粘贴键盘事件拖动元素到某个位置鼠标事件鼠标悬停鼠标事件滚动到某个元素滚动事件使用触控笔点击触控笔事件&am…...

深入Go语言:进阶指南
深入Go语言:进阶指南 欢迎来到深入Go语言的进阶指南。如果你已经熟悉Go语言的基础知识,想要更深入地探索这门语言的高级特性和技巧,那么本篇博客将为你提供有关Go语言的更多深入内容。 Go语言的并发编程 Go语言以其强大的并发支持而闻名。…...

FOXBORO FBM232 P0926GW 自动化控制模块
Foxboro FBM232 P0926GW 是 Foxboro(福克斯博罗)自动化控制系统的一部分,通常用于监测和控制工业过程。以下是关于这种类型的自动化控制模块可能具有的一些常见功能: 数字输入通道: FBM232 P0926GW 控制模块通常具有多…...

【C# Programming】编程入门:方法和参数
一、方法 1、方法的定义 由一系列以执行特定的操作或计算结果语句组成。方法总是和类关联,类型将相关的方法分为一组。 方法名称 形参和实参(parameter & argument)返回值 2、命名空间 一种分类机制,用于组合功能相关的所有类型。命名空间是分级…...

【报错】 Cannot create property ‘showColumn‘ on number ‘-1‘
1、报错原因: 代码如下: 报错是因为:this.findObject(this.option.column, "thirdId")是一个number ,没有.showColumn属性 2、修改代码 将其变成object属性就行了...

C++容器string的运用和注意
介绍 首先,先说明,string在C的string头文件中定义,而在C语言中的字符串就是字符数组,在C中,string容器相当于C语言中的字符数组,string比C语言中的字符数组更为好用,如:C中cin/cout可…...

用对工具,你的全渠道电子商务业务就成功了一半
希望将全渠道电子商务纳入您的业务战略,但不确定从哪里开始?我们为您提供保障。这篇文章将指导您了解全渠道商务的基础知识,以及它与多渠道方法的区别,还将探讨利用全渠道方法的众多好处,并讨论企业如何通过全渠道客户…...

TDengine学习(1):采集量(Metric),标签(label),数据采集点,表,超级表,子表、库
因为TDengine是面向物联网诞生的一种数据库,所以在一些概念的命名上有一点相应的特色。 一、数据采集点 比如需要对一辆高铁上的各种信息进行采集,采集信息存入数据库中。我们可以对高铁车厢内的一些数据进行采集,比如:车厢内温…...

【洛谷 P1029】[NOIP2001 普及组] 最大公约数和最小公倍数问题 题解(辗转相除法)
[NOIP2001 普及组] 最大公约数和最小公倍数问题 题目描述 输入两个正整数 x 0 , y 0 x_0, y_0 x0,y0,求出满足下列条件的 P , Q P, Q P,Q 的个数: P , Q P,Q P,Q 是正整数。 要求 P , Q P, Q P,Q 以 x 0 x_0 x0 为最大公约数,以…...

Golang 中的 errors 包详解:返回自定义 error 类型
之前的文章《Golang 中的 errors 包详解》详细讲解了 errors 包的主要类型和函数,以及它们的使用方法。本文结合之前讲解的知识,来讲解一下根据自己或团队的项目要求如何返回自定义的 error 类型。 为什么需要自定义 error 类型? 在日常开发…...

C#开发的OpenRA游戏之信标按钮
前面已经分析了两个按钮:变卖和维修,接着下来就是分析信标按钮,这个按钮使用是比较少,但是对于多人游戏时,使用这个信号就很方便同盟军过来查看和帮助了,相当于一个朋友之间共同查看的地址。当你经过同盟标记的标志时,就会听到beacon detected,检测到信标,这就是你的盟…...

16字节协议的串口通信
1.协议要求 协议为帧传输,一共16字节。主要是2字节的固定帧头 EB 90,2字节的帧计数(用来计数发出的帧),10字节的数据和2字节的校验位 帧头:2字节,固定值 8’HEB、8’H90 帧计数:2字节,用来说明发出去帧是…...

升哲科技城市级“算力+数字底座”服务亮相2023服贸会
9月2日至6日,以“开放引领发展,合作共赢未来”为主题的2023年中国国际服务贸易交易会在北京隆重举办。作为城市级数据服务商,升哲科技(SENSORO)连续第四年参加服贸会,携城市级“算力数字底座”服务及在城市…...

动态规划之简单多状态
简单多状态 1. 按摩师(easy)2. 打家劫舍II (medium)3. 删除并获得点数(medium)4. 买卖股票的最佳时机含冷冻期(medium)5. 买卖股票的最佳时机III(hard) 1. 按…...

跨数据中心Multi-Fabric解决方案:L2和L3网络的高效连接和扩展
云数据中心里,为什么需要DCI互通? 云化数据中心,网络资源通过虚拟化技术形成资源池,实现业务与物理网络解耦,通过网络虚拟化,物理网络资源可以被分成多个虚拟网络资源,从而提高网络资源的使用效…...

upload-labs靶场通关详解
文章目录 Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16Pass-17Pass-18Pass-19Pass-20方法一(文件夹名欺骗绕过)方法二(%00截断攻击) Pass-21 Pass-01 绕过…...