关键词:
用户管理模块
添加接口
在 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 = true this.operation = true this.dataForm = { id: 0, name: '', password: '', deptId: 1, deptName: '', email: 'test@qq.com', mobile: '13889700023', status: 1 } }, // 显示编辑界面 handleEdit: function (params) { this.editDialogVisible = true this.operation = false this.dataForm = Object.assign({}, params.row) }, // 编辑 editSubmit: function () { this.$refs.dataForm.validate((valid) => { if (valid) { this.$confirm('确认提交吗?', '提示', {}).then(() => { this.editLoading = true let params = Object.assign({}, this.dataForm) this.$api.user.save(params).then((res) => { this.editLoading = false this.$message({ message: '提交成功', type: 'success' }) this.$refs['dataForm'].resetFields() this.editDialogVisible = false this.findPage(null) }) }) } }) }, // 获取部门列表 findDeptTree: function () { this.$api.dept.findDeptTree().then((res) => { this.deptData = res.data }) }, // 菜单树选中 deptTreeCurrentChangeHandle (data, node) { this.dataForm.deptId = data.id this.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 = pageNum this.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不能实际操作数据库,可以结合本教程的后端代码一起测试。
源码下载
后端:https://gitee.com/liuge1988/kitty
前端:https://gitee.com/liuge1988/kitty-ui.git
作者:朝雨忆轻尘
出处:https://www.cnblogs.com/xifengxiaoma/
版权所有,欢迎转载,转载请注明原文作者及出处。
手把手教你实现java权限管理系统前端篇(十六):系统备份还原
系统备份还原在很多时候,我们需要系统数据进行备份还原。我们这里就使用MySql的备份还原命令实现系统备份还原的功能。后台接口准备系统备份还原是对数据库的备份还原,所以必须有后台接口的支持,我们准备好了接口,... 查看详情
手把手教你实现java权限管理系统前端篇(十五):嵌套外部网页
嵌套外部网页在有些时候,我们需要在我们的内容栏主区域显示外部网页。如查看服务端提供的SQL监控页面,接口文档页面等。这个时候就要求我们的导航菜单能够解析嵌套网页的URL,并根据URL路由到相应的嵌套组件。接下来我... 查看详情
手把手教你实现java权限管理系统后端篇(十三):系统备份还原
系统备份还原在很多时候,我们需要系统数据进行备份还原。我们这里就使用MySql的备份还原命令实现系统备份还原的功能。新建工程新建一个maven项目,并添加相关依赖,可以用Springboot脚手架生成。新建kitty-bakcup工程,这是一... 查看详情
手把手教你实现java权限管理系统后端篇(十六):容器部署项目
容器部署项目这一章我们引入docker,采用docker容器的方式部署我们的项目。首先需要有一个linux环境,并且安装java和maven以及docker环境,这个教程多如牛毛,不再赘述。这里以kitty-monitor为例。添加配置在 pom.xml的properties ... 查看详情
手把手教你实现java权限管理系统后端篇:解决跨域问题
什么是跨域?同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。同源策略是浏览器安全的基石。如果一个请求地址里面的协议、域名和端口号都相同,就属于同源。举个栗子... 查看详情
手把手教你做系统权限设计,看完不要说还不会
...是发起操作的主体,按类型分可分为2B和2C用户,可以是后台管理系统的用户,可以是OA系统的内部员工,也可以是面向C端的用户,比如阿里云的用户。角色起到了桥梁的作用,连接了用户和权限的关系,每个角色可以关联多个权限,同时一... 查看详情
手把手教你用java实现一套简单的鉴权服务(springboot,ssm)(万字长文)(代码片段)
...、利用servlet+jdbc实现简单的用户登录程序1.明确思路2.手把手教你实现一个简单的web登录程序①创建web项目②编写简单的登录页面③编写servlet程序④封装jdbc操作,编写简单的数据库连接池⑤操作数据库⑥配置web.xml⑦idea运... 查看详情
实现业务系统中的用户权限管理--实现篇
在设计篇中,我们已经为大家阐述了有关权限管理系统的数据库设计。在本篇中,我们将重点放在事实上现代码部分。为了让你可以更直接更有效的看到所有动作的代码。我们使用“动作分解列表”的方式来陈述每一个动作... 查看详情
手把手教你前后分离架构系统认证鉴权实现(代码片段)
...是比认证更加精细度的划分用户的行为。比如说一个教务管理系统中,学生登陆之后只能查看信息,不能修改信息。而班主任就可以修改学生的信息。这就是利用授权来限定不同身份用户的行为。安全是应用中不可缺少... 查看详情
手把手教你做javaweb项目:登录模块
...怎么制作吗?今天就为你娓娓道来:用户登录在各大信息管理系统中,登录功能是必不可少的,他的作用就是验证用户的身份,判断用户是否是本站的会员,只有会员才能访问当前系统登录的实现步骤:1.用户填写账号和密码,提交到后... 查看详情
实现业务系统中的用户权限管理--设计篇
...具有特殊的client,所以訪问用户的权限检測能够通过client实现或通过client+server检測实现,而B/S中,浏览器是每一台计算机都已具备的,假设不建立一个完整的权限检測,那么一个“非法用户”非常可能就能通过浏览器轻易訪问... 查看详情
手把手教你在vue3中自定义指令(代码片段)
文章目录1.成果展示2.指令基础2.1两种作用域2.1.1局部指令2.1.2全局指令2.2七个钩子函数2.3四个参数2.4动态参数3.自定义权限指令TienChin项目前端是Vue3,前端有这样的一个需求:有一些前端页面上的按钮要根据用户的权限来... 查看详情
手把手教你在vue3中自定义指令(代码片段)
文章目录1.成果展示2.指令基础2.1两种作用域2.1.1局部指令2.1.2全局指令2.2七个钩子函数2.3四个参数2.4动态参数3.自定义权限指令TienChin项目前端是Vue3,前端有这样的一个需求:有一些前端页面上的按钮要根据用户的权限来... 查看详情
手把手教你shiro整合jwt实现登录认证(代码片段)
1.所用技术SpringBootMybatis-plusShiroJWTRedis2.前置知识Shiro:Shiro是一个基于Java的开源的安全框架。在Shiro的核心架构里面,Subject是访问系统的用户。SecurityManager是安全管理器,负责用户的认证和授权,相当于Shiro的老大... 查看详情
vue+elementui实现权限管理系统前端篇:工具模块封装(代码片段)
封装axios模块封装背景使用axios发起一个请求是比较简单的事情,但是axios没有进行封装复用,项目越大的话会造成代码冗(rǒng )余,维护会越来越难。所以在此二次封装,是项目中各个组件能够复用,让代码更容易维护。封... 查看详情
手把手教你基于springboot+mybatis实现员工管理系统附完整源码(代码片段)
一、写在前面Hello,你好呀,我是灰小猿,一个超会写BUG的程序猿🙊!近期在学习springboot框架相关的内容,相比于SSM,SpringBoot最大的特点就是集成了Spring和SpringMVC,让之前繁琐的配置工作变得更加... 查看详情
手把手教你基于springboot+mybatis实现员工管理系统附完整源码(代码片段)
一、写在前面Hello,你好呀,我是灰小猿,一个超会写BUG的程序猿🙊!近期在学习springboot框架相关的内容,相比于SSM,SpringBoot最大的特点就是集成了Spring和SpringMVC,让之前繁琐的配置工作变得更加... 查看详情
手把手教你实现一个抽奖系统(java版)(代码片段)
点击关注公众号,实用技术文章及时了解来源:blog.csdn.net/wang258533488/article/details/789013031概述项目开发中经常会有抽奖这样的营销活动的需求,例如:积分大转盘、刮刮乐、老虎机等等多种形式,其实后台的实... 查看详情