(三)Springboot + vue + 达梦数据库构建RBAC权限模型前后端分离脚手架保姆级教程(前端项目)
XX后台管理系统
开源地址:git clone https://gitee.com/mrlumin/x-dm-pc.git
1.技术选型与环境要求
1.1 项目技术选型
1.1.1 前端技术
HTML 5
CSS 3
lavaScript
Vue
Element UI
1.1.2 后端技术
SpringBoot
MyBatis Plus
Spring Security
jwt
DM8
1.2 项目环境要求
1.2.1前端环境要求
node.js
VSCode
git
1.2.2 后端环境要求
jdk8 +
maven 3.6 +
Spring Boot 2+
开发工具:idea
git
2. 搭建前端项目环境
1 环境安装
node
2 脚手架下载
2.1 下载地址
https://github.com/PanJiaChen/vue-admin-template.git
2.2 项目重命名
解压vue-admin-template-master.zip到指定项目文件夹,不要带中文、空格、特殊字符的文件夹下面。
修改vue-admin-template-master项目名称和文件名称为自己项目名称:x-dm-pc
3 脚手架启动
3.1 进入项目目录
cd x-dm-pc
3.2 安装依赖
npm install
3.3 淘宝镜像
解决依赖下载速度慢的问题,安装淘宝镜像
npm install --registry=https://registry.npm.taobao.org
3.4 启动服务
npm run dev
3.5 浏览器访问
http://localhost:9528
4 项目配置修改
4.1 项目端口修改
vue.config.js
const name = defaultSettings.title || 'XX后台管理系统' // page title
const port = process.env.port || process.env.npm_config_port || 6666 // dev port
4.2 项目名称修改
package.json、package-lock.json
name: x-dm-pc
4.3 项目标题修改
src\settings.js
src\utils\get-page-title.js
title: 'XX后台管理系统'
4.4 项目首页修改
src\router\index.js
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '系统首页', icon: 'dashboard' }
}]
}
4.5 项目logo修改
src\layout\components\Sidebar\Logo.vue
data() {
return {
title: 'XX后台管理系统',
logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
}
}
5 登录组件修改
5.1 登录框样式修改
src\view\login\Login.vue
<template>
<div class="login-container">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container">
<h3 class="title">XX后台管理系统</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="请输入用户名"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="请输入密码"
name="password"
tabindex="2"
auto-complete="on"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登 录</el-button>
<!-- 提示不需要注释掉 -->
<!-- <div class="tips">
<span style="margin-right:20px;">username: admin</span>
<span> password: any</span>
</div> -->
</el-form>
</div>
</template>
<script>
import { validUsername } from '@/utils/validate'
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('请输入正确的用户名'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('密码长度不能小于6位'))
} else {
callback()
}
}
return {
loginForm: {
username: 'admin',
password: '111111'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
},
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ path: this.redirect || '/' })
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#283443;
$light_gray:#fff;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
background-image: url('../../assets/img/bg.jpg');
background-size: 100%;
display: flex;
align-items: center;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 35px 35px 0;
margin: 0 auto;
overflow: hidden;
background-color: #2d3a4b;
border-radius: 10px;
opacity: 0.6;
}
// .login-form {
// position: relative;
// width: 520px;
// max-width: 100%;
// padding: 160px 35px 0;
// margin: 0 auto;
// overflow: hidden;
// }
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>
5.2 背景图片增加
background-image: url('../../assets/img/bg.jpg');
background-size: 100%;
display: flex;
align-items: center;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 35px 35px 0;
margin: 0 auto;
overflow: hidden;
background-color: #2d3a4b;
border-radius: 10px;
opacity: 0.6;
}
6 用户下拉菜单修改
src\layout\components\Navbar.vue
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<router-link to="/">
<el-dropdown-item>
系统首页
</el-dropdown-item>
</router-link>
<a target="_blank" href="">
<el-dropdown-item>个人中心</el-dropdown-item>
</a>
<a target="_blank" href="">
<el-dropdown-item>使用手册</el-dropdown-item>
</a>
<el-dropdown-item divided
@click.native="logout">
<span style="display:block;">注销登录</span>
</el-dropdown-item>
7.系统管理
7.1 新增系统管理组件
在src\view\system\新建系统管理组件
src\view\system\user\index.vue
src\view\system\role\index.vue
src\view\system\menu\index.vue
7.2 菜单路由修改
src\router\index.js
7.2.1 删除不需要的路由
/*
{
path: '/example',
component: Layout,
redirect: '/example/table',
name: 'Example',
meta: { title: 'Example', icon: 'el-icon-s-help' },
children: [
{
path: 'table',
name: 'Table',
component: () => import('@/views/table/index'),
meta: { title: 'Table', icon: 'table' }
},
{
path: 'tree',
name: 'Tree',
component: () => import('@/views/tree/index'),
meta: { title: 'Tree', icon: 'tree' }
}
]
},
{
path: '/form',
component: Layout,
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: 'Form', icon: 'form' }
}
]
},
{
path: '/nested',
component: Layout,
redirect: '/nested/menu1',
name: 'Nested',
meta: {
title: 'Nested',
icon: 'nested'
},
children: [
{
path: 'menu1',
component: () => import('@/views/nested/menu1/index'), // Parent router-view
name: 'Menu1',
meta: { title: 'Menu1' },
children: [
{
path: 'menu1-1',
component: () => import('@/views/nested/menu1/menu1-1'),
name: 'Menu1-1',
meta: { title: 'Menu1-1' }
},
{
path: 'menu1-2',
component: () => import('@/views/nested/menu1/menu1-2'),
name: 'Menu1-2',
meta: { title: 'Menu1-2' },
children: [
{
path: 'menu1-2-1',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
name: 'Menu1-2-1',
meta: { title: 'Menu1-2-1' }
},
{
path: 'menu1-2-2',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
name: 'Menu1-2-2',
meta: { title: 'Menu1-2-2' }
}
]
},
{
path: 'menu1-3',
component: () => import('@/views/nested/menu1/menu1-3'),
name: 'Menu1-3',
meta: { title: 'Menu1-3' }
}
]
},
{
path: 'menu2',
component: () => import('@/views/nested/menu2/index'),
name: 'Menu2',
meta: { title: 'menu2' }
}
]
},
{
path: 'external-link',
component: Layout,
children: [
{
path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
meta: { title: 'External Link', icon: 'link' }
}
]
},
*/
7.2.2 新增系统管理路由
{
path: '/system',
component: Layout,
redirect: '/system',
name: 'systemManage',
meta: { title: '系统管理', icon: 'el-icon-menu' },
children: [
{
path: 'user',
name: 'user',
component: () => import('@/views/system/user/index'),
meta: { title: '用户管理', icon: 'el-icon-user' }
},
{
path: 'role',
name: 'role',
component: () => import('@/views/system/role/index'),
meta: { title: '角色管理', icon: 'el-icon-s-custom' }
},
{
path: 'menu',
name: 'menuList',
component: () => import('@/views/system/menu/index'),
meta: { title: '菜单管理', icon: 'el-icon-s-custom' }
}
]
}
7.2.3 导航栏首页标题修改
src\components\Breadcrumb\index.vue
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: '系统首页' }}].concat(matched)
}
8 快捷导航(标签栏导航)
8.1 新增监听路由
src\layout\components\AppMain.vue
<!-- 1. 注释掉原先路由跳转,并新增监听缓存页面的路由跳转 -->
<!-- <router-view :key="key" /> -->
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
computed: {
key() {
return this.$route.path
},
<!-- 2. 在计算属性中新增缓存的页面 -->
cachedViews() {
// 注意:从state中取cachedViews值的路径,路径错误会导致cachedViews无法读取的错误 // [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined // (reading 'cachedViews')"
// return this.$store.state.tagView.cachedViews
return this.$store.state.tagsView.cachedViews
}
}
8.2 复制标签组件
复制集成方案vue-element-admin中的文件到相应的目录中
src\layout\components\TagsView
src\store\modules\tagsView.js
src\store\modules\permission.js
8.3 获取标签组件
修改src\store\getters.js
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters
8.4 将标签组件存入状态管理库
修改src\store\index.js
import permission from './modules/permission'
import tagsView from './modules/tagsView'
modules: {
app,
settings,
user,
permission,
tagsView
},
8.5 将标签组件公布成全局组件
src\layout\components\index.js
export { default as TagsView } from './TagsView'
8.6 使用标签组件
src\layout\index.vue
// 1. 导入TagsView标签组件
import { Navbar, Sidebar, AppMain, TagsView } from './components'
components: {
Navbar,
Sidebar,
AppMain,
TagsView
},
<div :class="{'fixed-header':fixedHeader}">
<navbar />
<!-- 2. 导航栏中添加tagsView标签组件 -->
<tags-view />
</div>
8.7 使用标签组件错误处理
8.7.1 错误一:编译错误
①复制集成方案vue-element-admin中的ParentView到src\components下
②复制集成方案vue-element-admin中的routers.js到src\router下
③修改src\layout\components\index.js中公布标签组件路径
修改:export { default as TagsView } from '../TagsView'
成为:export { default as TagsView } from './TagsView'
ERROR Failed to compile with 3 errors
These dependencies were not found:
* @/components/ParentView in ./src/store/modules/permission.js
* @/router/routers in ./src/store/modules/permission.js
To install them, you can run: npm install --save @/components/ParentView @/router/routers
This relative module was not found:
* ../TagsView in ./src/layout/components/index.js
8.7.2 错误二:刷新tab标签丢失
页面刷新后点开的导航标签丢失
8.7.2.1 刷新前
8.7.2.2 刷新后
8.7.2.3 解决步骤
第一步:在 \src\layout\components\TagsView\index.vue添加调用
mounted() {
this.initTags()
this.addTags()
this.tagsViewCache()
},
第二步:添加方法(实现效果)
tagsViewCache() {
window.addEventListener('beforeunload', () => {
const tabViews = this.visitedViews.map(item => {
return {
fullPath: item.fullPath,
hash: item.hash,
meta: { ...item.meta },
name: item.name,
params: { ...item.params },
path: item.path,
query: { ...item.query },
title: item.title
}
})
sessionStorage.setItem('tabViews', JSON.stringify(tabViews))
})
const oldViews = JSON.parse(sessionStorage.getItem('tabViews')) || []
if (oldViews.length > 0) {
this.$store.state.tagsView.visitedViews = oldViews
}
},
8.7.3 错误三:cachedViews错误
这个问题是由于在AppMain.vue中引用cachedViews错误,解决:修改cachedViews引用路径
// 2. 在计算属性中新增缓存的页面
cachedViews() {
// TODO 注意:从state中取cachedViews值的路径,路径错误会导致cachedViews无法读取的错误,
// TODO [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'cachedViews')"
// return this.$store.state.tagView.cachedViews
return this.$store.state.tagsView.cachedViews
}
8.7.4 错误四:显示上次登录页面
注销的时候删除所有的tagView,重新登录或换用户登录后,会显示上次登录的页面
在 \src\layout\components\Navbar.vue 添加
,
/* async logout() {
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
} */
async logout() {
await this.$store.dispatch('user/logout')
await this.$store.dispatch('tagsView/delAllViews')
sessionStorage.removeItem('tabViews')
// 这里如果不改的情况下,重新登录或换用户登录后,会显示上次登录的页面
// this.$router.push(`/login?redirect=${this.$route.fullPath}`)
this.$router.push(`/login`)
}
8.7.5 错误四:默认Tab标签可以删除
设置默认Tab标签不能删除
// meta: { title: '系统首页', icon: 'dashboard' }
meta: { title: '系统首页', icon: 'dashboard', affix: true, noCache: false }
9 登录接口梳理
9.1 登录所需接口
接口名称 | url | method |
---|---|---|
登录 | /user/login | post |
获取用户信息 | /user/info | get |
注销 | /user/logout | post |
9.1.1 用户登录
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/login
{username: "admin", password: "111111"}
// 响应
{"code":20000,"data":{"token":"admin-token"}}
9.1.2 获取用户信息
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/info?token=admin-token
{token: "admin-token"}
// 响应
{
"code": 20000,
"data": {
"roles": [
"admin"
],
"introduction": "I am a super administrator",
"avatar": "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
"name": "Super Admin"
}
}
9.1.3 注销登录
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/logout
{token: "admin-token"}
// 响应
{"code":20000,"data":"success"}
10 前后端对接
10.1 修改后端接口规格一致
在src\api\user.js中将前端请求接口地址与后端接口地址一致。
10.1.1 登录接口
前端请求接口地址:url: '/vue-admin-template/user/login'
后端接口地址:url: '/system/user/login'
10.1.2 获取用户信息接口
前端请求接口地址:url: '/vue-admin-template/user/info'
后端接口地址:url: '/system/user/info'
10.1.3 注销登录
前端请求接口地址: url: '/vue-admin-template/user/logout'
后端接口地址:url: '/system/user/logout'
10.2 修改前端请求后端配置
修改配置文件:.env.development
# VUE_APP_BASE_API = '/api'
VUE_APP_BASE_API = 'http://localhost:9999'
10.3 注释mock模拟服务
注释掉 vue.config.js 中mock服务
// before: require('./mock/mock-server.js')
10.4 解决前后端跨越问题
注意,修改后需要重新启动项目,前端请求后端接口会出现跨越问题,可以前端nginx代理解决,也可以后端配置过滤器解决,这里选择的后端配置过滤器解决
Access to XMLHttpRequest at 'http://localhost:9999/system/user/login' from origin
'http://localhost:9528' has been blocked by CORS policy: Response to preflight request
doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
11 系统管理
用户管理布局中内边距需要在src\App.vue中设置
<style>
.app-main {
padding: 10px;
}
</style>
Vue.js Devtools 极简插件下载 ,非常友好
https://chrome.zzzmh.cn/info/nhdogjmejiglipccpnnnanhbledajbpd
11.1 用户管理
11.1.1 用户列表
11.1.1 界面布局
<template>
<div>
<!-- 搜索栏 -->
<el-card id="search">
<el-row>
<el-col :span="20">
<el-input v-model="searchModel.username" placeholder="请输入用户名" />
<el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
<el-button type="primary" round icon="el-icon-search">搜索</el-button>
</el-col>
<el-col :span="4" align="right">
<el-button type="primary" icon="el-icon-plus" circle />
</el-col>
</el-row>
</el-card>
<!-- 用户列表 -->
<el-card>
<el-table stripe style="width: 100%">
<el-table-column label="#" width="80" align="center">
<template slot-scope="scope">
{{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="" label="账户" align="center" />
<el-table-column prop="" label="邮箱" align="center" />
<el-table-column prop="" label="状态" align="center">
<template slot-scope="scope">
{{ scope.row.status !== 1 ? '停用' : '启用' }}
</template>
</el-table-column>
<el-table-column prop="" label="电话" align="center" />
<el-table-column label="操作" width="200" align="center">
<template>
<el-button type="primary" icon="el-icon-edit" circle size="small" />
<el-button type="danger" icon="el-icon-delete" circle size="small" />
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 分页 -->
<el-pagination
:current-page="searchModel.pageNo"
:page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
:page-size="searchModel.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import userManage from '@/api/system/userManage'
export default {
name: 'Index',
data() {
return {
userList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
username: '',
phone: ''
}
}
},
mounted() {
},
created() {
},
methods: {
}
}
</script>
<style scoped lang="scss">
#search .el-input {
width: 160px;
margin-right: 10px;
}
</style>
11.1.2 用户列表
11.1.2.1 新增请求
第一步: 新增请求后端api接口
src\api\system\userManage.js
import request from '@/utils/request'
export default {
// 查询用户列表
getUserList(searchModel) {
return request({
url: '/system/user/list',
method: 'get',
params: {
pageNo: searchModel.pageNo,
pageSize: searchModel.pageSize,
username: searchModel.username,
phone: searchModel.phone
}
})
}
}
11.1.2.2 发送请求
第二步: 发送获取用户列表请求
src\views\system\user\index.vue
①引入请求后端api接口
import userManage from "@/api/system/userManage";
②发送获取用户列表请求
// 1.获取用户列表
getUserList()
{
userManage.getUserList(this.searchModel).then(res => {
this.userList = res.data.records
this.total = res.data.total
})
}
11.1.2.3 数据回显
第三步: 前端用户列表数据展示
①在data中定义userList接收后端返回的用户列表数据
data() {
return {
userList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
username: '',
phone: ''
},
userList: []
};
},
②将后端查询的用户列表数据赋值给userList数组对象
getUserList() {
userManage.getUserList(this.searchModel).then(res => {
// console.log("1.用户列表",res.data);
this.userList = res.data.rows;
this.total = res.data.total;
});
},
③将数据赋值表格中的userList,然后将属性值赋值给对应的字段
<el-table :data="userList" stripe style="width: 100%">
全部代码如下:
<template>
<div>
<!-- 搜索栏 -->
<el-card id="search">
<el-row>
<el-col :span="20">
<el-input v-model="searchModel.username" placeholder="请输入用户名" />
<el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
<el-button type="primary" round icon="el-icon-search" @click="getUserList">搜索</el-button>
</el-col>
<el-col :span="4" align="right">
<el-button type="primary" icon="el-icon-plus" circle />
</el-col>
</el-row>
</el-card>
<!-- 用户列表 -->
<el-card>
<el-table :data="userList" stripe style="width: 100%">
<el-table-column label="#" width="80" align="center">
<template slot-scope="scope">
{{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="username" label="账户" align="center" />
<el-table-column prop="email" label="邮箱" align="center" />
<el-table-column prop="status" label="状态" align="center">
<template slot-scope="scope">
{{ scope.row.status !== 1 ? '停用' : '启用' }}
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" align="center" />
<el-table-column label="操作" width="200" align="center">
<template>
<el-button type="primary" icon="el-icon-edit" circle size="small" />
<el-button type="danger" icon="el-icon-delete" circle size="small" />
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 分页 -->
<el-pagination
:current-page="searchModel.pageNo"
:page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
:page-size="searchModel.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import userManage from '@/api/system/userManage'
export default {
name: 'Index',
data() {
return {
userList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
username: '',
phone: ''
}
}
},
mounted() {
this.getUserList()
},
created() {
this.getUserList()
},
methods: {
// 1.获取用户列表
getUserList() {
userManage.getUserList(this.searchModel).then(res => {
this.userList = res.data.rows
this.total = res.data.total
})
},
handleSizeChange(pageSize) {
this.searchModel.pageSize = pageSize
this.getUserList()
},
handleCurrentChange(pageNo) {
this.searchModel.pageNo = pageNo
this.getUserList()
}
}
}
</script>
<style scoped lang="scss">
#search .el-input {
width: 160px;
margin-right: 10px;
}
</style>
11.1.3 新增用户
11.1.3.1 界面布局
<!-- 新增用户 -->
<el-dialog title="新增用户" :visible.sync="dialogFormVisible" @close="clearForm">
<el-form ref="userFormRef" :rules="rules" :model="userForm">
<el-form-item label="账户" :label-width="formLabelWidth" prop="username">
<el-input v-model="userForm.username" autocomplete="off" />
</el-form-item>
<el-form-item v-if="userForm.id == null || userForm.id == undefined" label="密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="userForm.password" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="状态" :label-width="formLabelWidth" prop="status">
<el-switch
v-model="userForm.status"
:active-value="0"
:inactive-value="1"
/>
</el-form-item>
<el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
<el-input v-model="userForm.email" autocomplete="off" />
</el-form-item>
<el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
<el-input v-model="userForm.phone" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
</div>
</el-dialog>
data函数中规则和接收数组定义
rules: {
username: [
{ required: true, message: '请输入账户名', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
{ validator: checkPhone, trigger: 'blur' }
]
},
userForm: {
username: '',
password: '',
status: '',
email: '',
phone: ''
},
dialogFormVisible: false,
formLabelWidth: '120px',
const checkEmail = (rule, value, callback) => {
const reg = /^([a-zA-Z]|[0-9])(\w|\-|\.)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
if (!value) return callback(new Error('请输入收件人邮箱'))
if (!reg.test(value)) {
callback(new Error('邮箱格式错误'))
} else {
callback()
}
}
const checkPhone = (rule, value, callback) => {
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
if (!value) return callback(new Error('请输入联系人电话'))
if (!reg.test(value)) {
callback(new Error('电话格式错误'))
} else {
callback()
}
}
11.1.3.2 新增请求
①在src\api\system\userManage.js新增请求
// 2.添加用户
addUser(user) {
return request({
url: '/system/user',
method: 'post',
data: user
})
}
11.1.3.3 发送请求
// 2.添加用户
saveUser() {
// 触发表单验证
this.$refs.userFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
userManage.addUser(this.userForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getUserList()
})
} else {
console.log('error submit!!')
return false
}
})
},
11.1.3.4 数据回显
<!-- 添加用户 -->
<el-dialog title="添加用户" :visible.sync="dialogFormVisible" @close="clearForm">
<el-form ref="userFormRef" :rules="rules" :model="userForm">
<el-form-item label="账户" :label-width="formLabelWidth" prop="username">
<el-input v-model="userForm.username" autocomplete="off" />
</el-form-item>
<el-form-item label="密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="userForm.password" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="状态" :label-width="formLabelWidth" prop="status">
<el-switch
v-model="userForm.status"
:active-value="0"
:inactive-value="1"
/>
</el-form-item>
<el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
<el-input v-model="userForm.email" autocomplete="off" />
</el-form-item>
<el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
<el-input v-model="userForm.phone" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveUser">确 定</el-button>
</div>
</el-dialog>
全部代码为:
<template>
<div>
<!-- 搜索栏 -->
<el-card id="search">
<el-row>
<el-col :span="20">
<el-input v-model="searchModel.username" placeholder="请输入用户名" />
<el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
<el-button type="primary" round icon="el-icon-search" @click="getUserList">搜索</el-button>
</el-col>
<el-col :span="3" align="right">
<el-button type="primary" icon="el-icon-plus" circle @click="dialogFormVisible = true" />
</el-col>
</el-row>
</el-card>
<!-- 用户列表 -->
<el-card>
<el-table :data="userList" stripe style="width: 100%">
<el-table-column label="#" width="80" align="center">
<template slot-scope="scope">
{{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="username" label="账户" align="center" />
<el-table-column prop="email" label="邮箱" align="center" />
<el-table-column prop="status" label="状态" align="center">
<template slot-scope="scope">
{{ scope.row.status !== 1 ? '停用' : '启用' }}
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" align="center" />
<el-table-column label="操作" width="200" align="center">
<template>
<el-button type="primary" icon="el-icon-edit" circle size="small" />
<el-button type="danger" icon="el-icon-delete" circle size="small" />
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加用户 -->
<el-dialog title="添加用户" :visible.sync="dialogFormVisible" @close="clearForm">
<el-form ref="userFormRef" :rules="rules" :model="userForm">
<el-form-item label="账户" :label-width="formLabelWidth" prop="username">
<el-input v-model="userForm.username" autocomplete="off" />
</el-form-item>
<el-form-item label="密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="userForm.password" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="状态" :label-width="formLabelWidth" prop="status">
<el-switch
v-model="userForm.status"
:active-value="0"
:inactive-value="1"
/>
</el-form-item>
<el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
<el-input v-model="userForm.email" autocomplete="off" />
</el-form-item>
<el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
<el-input v-model="userForm.phone" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveUser">确 定</el-button>
</div>
</el-dialog>
<!-- 分页 -->
<el-pagination
:current-page="searchModel.pageNo"
:page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
:page-size="searchModel.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import userManage from '@/api/system/userManage'
export default {
name: 'Index',
data: function() {
const checkEmail = (rule, value, callback) => {
const reg = /^([a-zA-Z]|[0-9])(\w|\-|\.)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
if (!value) return callback(new Error('请输入收件人邮箱'))
if (!reg.test(value)) {
callback(new Error('邮箱格式错误'))
} else {
callback()
}
}
const checkPhone = (rule, value, callback) => {
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
if (!value) return callback(new Error('请输入联系人电话'))
if (!reg.test(value)) {
callback(new Error('电话格式错误'))
} else {
callback()
}
}
return {
rules: {
username: [
{ required: true, message: '请输入账户名', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
{ validator: checkPhone, trigger: 'blur' }
]
},
userForm: {},
dialogFormVisible: false,
formLabelWidth: '120px',
userList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
username: '',
phone: ''
}
}
},
created() {
this.getUserList()
},
mounted() {
this.getUserList()
},
methods: {
clearForm() {
this.userForm = {}
this.dialogFormVisible = false
this.$refs.userFormRef.clearValidate()
},
// 2.添加用户
saveUser() {
// 触发表单验证
this.$refs.userFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
userManage.addUser(this.userForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getUserList()
})
} else {
console.log('error submit!!')
return false
}
})
},
// 1.获取用户列表
getUserList() {
userManage.getUserList(this.searchModel).then(res => {
this.userList = res.data.rows
this.total = res.data.total
})
},
handleSizeChange(pageSize) {
this.searchModel.pageSize = pageSize
this.getUserList()
},
handleCurrentChange(pageNo) {
this.searchModel.pageNo = pageNo
this.getUserList()
}
}
}
</script>
<style scoped lang="scss">
#search .el-input {
width: 160px;
margin-right: 10px;
}
</style>
11.1.4 修改用户
11.1.4.1 界面布局
复用添加用户界面,通过点击,是否存在用户ID来判断添加还是修改
①添加用户
<!-- 用户ID为空,判断出该用户不存在,即为添加用户操作 -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
②修改用户
<!-- 用户ID不为空,判断出该用户已存在,即为修改用户操作 -->
<el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
11.1.4.2 新增请求
①根据前端点击修改按钮,传入的用户用户ID查询用户信息,用于回显在修改对话框中进行修改
// 3.根据用户ID查询用户
// 根据前端点击修改按钮,传入的用户用户ID查询用户信息,用于回显在修改对话框中进行修改
getUserById(id) {
return request({
// url: '/system/user/' + id,
url: `/system/user/${id}`,
method: 'get'
})
},
②修改用户
// 4.修改用户
updateUser(user) {
return request({
url: '/system/user',
method: 'put',
data: user
})
},
③整合添加/修改用户
// 5.整合添加/修改请求后端接口
saveUser(user) {
// eslint-disable-next-line eqeqeq
if (user.id == null && user.id === undefined) {
return this.addUser(user)
} else {
return this.updateUser(user)
}
}
11.1.4.3 发送请求
①根据后端查询是否存在用户ID,判断是添加用户/修改用户操作
<!-- 用户ID为空,判断出该用户不存在,即为添加用户操作 -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
title: '',
openDialog(id) {
if (id == null) {
this.title = '添加用户'
this.dialogFormVisible = true
} else {
this.title = '修改用户'
this.dialogFormVisible = true
userManage.getUserById(id).then(res => {
this.userForm = res.data
})
}
}
②如果是修改用户,密码不需回显到弹出框
<el-form-item v-if="userForm.id == null || userForm.id == undefined" label="密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="userForm.password" type="password" autocomplete="off" />
</el-form-item>
③添加/修改用户请求
// 2.添加/修改用户
saveUser() {
// 触发表单验证
this.$refs.userFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
userManage.saveUser(this.userForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getUserList()
})
} else {
console.log('error submit!!')
return false
}
})
},
11.1.5 删除用户
11.1.5.1 界面布局
<el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteUser(scope.row.id)" />
11.1.5.2 新增请求
// 3.删除用户
deleteUserById(id) {
return request({
url: `/system/user/${id}`,
method: 'delete'
})
}
11.1.5.3 发送请求
deleteUser(user) {
this.$confirm(`您确认要删除用户:${user.username}`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
userManage.deleteUserById(user.id).then(res => {
this.$message({
type: 'success',
message: res.message
})
this.getUserList()
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
}
11.1.5.4 数据回显
删除后页面刷新
12 角色管理
12.1 界面布局
角色管理界面布局复用用户管理界面,修改后的界面
src\views\system\role\index.vue
<template>
<div>
<!-- 搜索栏 -->
<el-card id="search">
<el-row>
<el-col :span="20">
<el-input v-model="searchModel.roleName" placeholder="请输入角色名" />
<el-input v-model="searchModel.roleDesc" placeholder="请输入角色描述" />
<el-button type="primary" round icon="el-icon-search" @click="getRoleList">搜索</el-button>
</el-col>
<el-col :span="3" align="right">
<!-- 角色ID为空,判断出该角色不存在,即为添加角色操作 -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
</el-col>
</el-row>
</el-card>
<!-- 角色列表 -->
<el-card>
<el-table :data="roleList" stripe style="width: 100%">
<el-table-column label="#" width="80" align="center">
<template slot-scope="scope">
{{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="roleName" label="角色名称" align="center" />
<el-table-column prop="status" label="角色状态" align="center">
<template slot-scope="scope">
{{ scope.row.status !== 1 ? '停用' : '启用' }}
</template>
</el-table-column>
<el-table-column prop="roleDesc" label="角色描述" align="center" />
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<!-- 角色ID不为空,判断出该角色已存在,即为修改角色操作 -->
<el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
<el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteRole(scope.row)" />
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加/修改角色 -->
<el-dialog :title="title" :visible.sync="dialogFormVisible" @close="clearForm">
<el-form ref="roleFormRef" :rules="rules" :model="roleForm">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="roleForm.roleName" autocomplete="off" />
</el-form-item>
<el-form-item label="状态" :label-width="formLabelWidth" prop="status">
<el-switch
v-model="roleForm.status"
:active-value="0"
:inactive-value="1"
/>
</el-form-item>
<el-form-item label="角色描述" :label-width="formLabelWidth" prop="roleDesc">
<el-input v-model="roleForm.roleDesc" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveRole">确 定</el-button>
</div>
</el-dialog>
<!-- 分页 -->
<el-pagination
:current-page="searchModel.pageNo"
:page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
:page-size="searchModel.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import roleManage from '@/api/system/roleManage'
export default {
name: 'Index',
data: function() {
return {
rules: {
roleName: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
],
roleDesc: [
{ required: true, message: '请输入角色描述', trigger: 'blur' }
]
},
roleForm: {},
dialogFormVisible: false,
formLabelWidth: '120px',
title: '',
roleList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
roleName: '',
roleDesc: ''
}
}
},
created() {
this.getRoleList()
},
mounted() {
this.getRoleList()
},
methods: {
// 3.删除角色
deleteRole(role) {
this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
roleManage.deleteRoleById(role.id).then(res => {
this.$message({
type: 'success',
message: res.message
})
this.getRoleList()
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
openDialog(id) {
if (id == null) {
this.title = '添加角色'
this.dialogFormVisible = true
} else {
this.title = '修改角色'
this.dialogFormVisible = true
roleManage.getRoleById(id).then(res => {
this.roleForm = res.data
})
}
},
clearForm() {
this.roleForm = {}
this.dialogFormVisible = false
this.$refs.roleFormRef.clearValidate()
},
// 2.添加/修改角色
saveRole() {
// 触发表单验证
this.$refs.roleFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
roleManage.saveRole(this.roleForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getRoleList()
})
} else {
console.log('error submit!!')
return false
}
})
},
// 1.获取角色列表
getRoleList() {
roleManage.getRoleList(this.searchModel).then(res => {
console.log('2.角色列表', res.data.rows)
this.roleList = res.data.rows
this.total = res.data.total
})
},
handleSizeChange(pageSize) {
this.searchModel.pageSize = pageSize
this.getRoleList()
},
handleCurrentChange(pageNo) {
this.searchModel.pageNo = pageNo
this.getRoleList()
}
}
}
</script>
<style scoped lang="scss">
#search .el-input {
width: 160px;
margin-right: 10px;
}
</style>
12.2 新增请求
src\api\system\roleManage.js
import request from '@/utils/request'
export default {
// 1.角色列表
getRoleList(searchModel) {
return request({
url: '/system/role/list',
method: 'get',
params: {
pageNo: searchModel.pageNo,
pageSize: searchModel.pageSize,
roleName: searchModel.roleName,
roleDesc: searchModel.roleDesc
}
})
},
// 添加角色
addRole(role) {
return request({
url: '/system/role',
method: 'post',
data: role
})
},
// 根据角色ID查询角色
getRoleById(roleId) {
return request({
url: `/system/role/${roleId}`,
method: 'get'
})
},
// 修改角色
updateRole(role) {
return request({
url: '/system/role/update',
method: 'put',
data: role
})
},
// 2.添加/修改角色
saveRole(role) {
// eslint-disable-next-line eqeqeq
if (role.id == null && role.id == undefined) {
return this.addRole(role)
} else {
return this.updateRole(role)
}
},
// 3.删除角色
deleteRoleById(id) {
return request({
url: `/system/role/${id}`,
method: 'delete'
})
}
}
12.3 发送请求
// 3.删除角色
deleteRole(role) {
this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
roleManage.deleteRoleById(role.id).then(res => {
this.$message({
type: 'success',
message: res.message
})
this.getRoleList()
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
openDialog(id) {
if (id == null) {
this.title = '添加角色'
this.dialogFormVisible = true
} else {
this.title = '修改角色'
this.dialogFormVisible = true
roleManage.getRoleById(id).then(res => {
this.roleForm = res.data
})
}
},
// 2.添加/修改角色
saveRole() {
// 触发表单验证
this.$refs.roleFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
roleManage.saveRole(this.roleForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getRoleList()
})
} else {
console.log('error submit!!')
return false
}
})
},
// 1.获取角色列表
getRoleList() {
roleManage.getRoleList(this.searchModel).then(res => {
console.log('2.角色列表', res.data.rows)
this.roleList = res.data.rows
this.total = res.data.total
})
},
12.4 数据回显
<template>
<div>
<!-- 搜索栏 -->
<el-card id="search">
<el-row>
<el-col :span="20">
<el-input v-model="searchModel.roleName" placeholder="请输入角色名" />
<el-input v-model="searchModel.roleDesc" placeholder="请输入角色描述" />
<el-button type="primary" round icon="el-icon-search" @click="getRoleList">搜索</el-button>
</el-col>
<el-col :span="3" align="right">
<!-- 角色ID为空,判断出该角色不存在,即为添加角色操作 -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
</el-col>
</el-row>
</el-card>
<!-- 角色列表 -->
<el-card>
<el-table :data="roleList" stripe style="width: 100%">
<el-table-column label="#" width="80" align="center">
<template slot-scope="scope">
{{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="roleName" label="角色名称" align="center" />
<el-table-column prop="status" label="角色状态" align="center">
<template slot-scope="scope">
{{ scope.row.status !== 1 ? '停用' : '启用' }}
</template>
</el-table-column>
<el-table-column prop="roleDesc" label="角色描述" align="center" />
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<!-- 角色ID不为空,判断出该角色已存在,即为修改角色操作 -->
<el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
<el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteRole(scope.row)" />
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加/修改角色 -->
<el-dialog :title="title" :visible.sync="dialogFormVisible" @close="clearForm">
<el-form ref="roleFormRef" :rules="rules" :model="roleForm">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="roleForm.roleName" autocomplete="off" />
</el-form-item>
<el-form-item label="状态" :label-width="formLabelWidth" prop="status">
<el-switch
v-model="roleForm.status"
:active-value="0"
:inactive-value="1"
/>
</el-form-item>
<el-form-item label="角色描述" :label-width="formLabelWidth" prop="roleDesc">
<el-input v-model="roleForm.roleDesc" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveRole">确 定</el-button>
</div>
</el-dialog>
<!-- 分页 -->
<el-pagination
:current-page="searchModel.pageNo"
:page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
:page-size="searchModel.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import roleManage from '@/api/system/roleManage'
export default {
name: 'Index',
data: function() {
return {
rules: {
roleName: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
],
roleDesc: [
{ required: true, message: '请输入角色描述', trigger: 'blur' }
]
},
roleForm: {},
dialogFormVisible: false,
formLabelWidth: '120px',
title: '',
roleList: [],
total: 0,
searchModel: {
pageNo: 1,
pageSize: 5,
roleName: '',
roleDesc: ''
}
}
},
created() {
this.getRoleList()
},
mounted() {
this.getRoleList()
},
methods: {
// 3.删除角色
deleteRole(role) {
this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
roleManage.deleteRoleById(role.id).then(res => {
this.$message({
type: 'success',
message: res.message
})
this.getRoleList()
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
openDialog(id) {
if (id == null) {
this.title = '添加角色'
this.dialogFormVisible = true
} else {
this.title = '修改角色'
this.dialogFormVisible = true
roleManage.getRoleById(id).then(res => {
this.roleForm = res.data
})
}
},
clearForm() {
this.roleForm = {}
this.dialogFormVisible = false
this.$refs.roleFormRef.clearValidate()
},
// 2.添加/修改角色
saveRole() {
// 触发表单验证
this.$refs.roleFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
roleManage.saveRole(this.roleForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getRoleList()
})
} else {
console.log('error submit!!')
return false
}
})
},
// 1.获取角色列表
getRoleList() {
roleManage.getRoleList(this.searchModel).then(res => {
console.log('2.角色列表', res.data.rows)
this.roleList = res.data.rows
this.total = res.data.total
})
},
handleSizeChange(pageSize) {
this.searchModel.pageSize = pageSize
this.getRoleList()
},
handleCurrentChange(pageNo) {
this.searchModel.pageNo = pageNo
this.getRoleList()
}
}
}
</script>
<style scoped lang="scss">
#search .el-input {
width: 160px;
margin-right: 10px;
}
</style>
13 角色菜单
13.1 菜单列表
13.1.1 界面布局
在src\views\system\role\index.vue添加菜单列表树形组件
<el-form-item :label-width="formLabelWidth" prop="menuIdList" label="权限设置">
<el-tree
ref="menuTreeRef"
:data="menuList"
:props="menuProps"
show-checkbox
default-expand-all
node-key="id"
style="width: 85%"
/>
</el-form-item>
在src\views\system\role\index.vue定义接收菜单列表参数
menuList: [],
menuProps: {
label: 'title',
children: 'children'
},
在src\views\system\role\index.vue添加请求菜单列表方法
mounted() {
this.getRoleList()
this.getMenuList()
},
methods: {
// 4.菜单列表
getMenuList() {
menuManage.getMenuList().then(res => {
this.menuList = res.data
console.log('4.菜单列表', res.data)
})
},
13.1.2 新增请求
在src\api\system\menuManage.js创建获取菜单列表的方法
// 获取菜单列表
getMenuList() {
return request({
url: '/system/menu/list',
method: 'get'
})
}
13.1.3 发送请求
在src\views\system\role\index.vue添加请求菜单列表方法
mounted() {
this.getRoleList()
this.getMenuList()
},
methods: {
// 4.菜单列表
getMenuList() {
menuManage.getMenuList().then(res => {
this.menuList = res.data
console.log('4.菜单数据', res.data)
})
},
13.1.4 数据回显
添加/修改弹出框填充自动回显
13.2 添加角色菜单
13.2.1 界面布局
在src\views\system\role\index.vue添加菜单列表树形组件
<el-form-item :label-width="formLabelWidth" prop="menuIdList" label="权限设置">
<el-tree
ref="menuTreeRef"
:data="menuList"
:props="menuProps"
show-checkbox
default-expand-all
node-key="id"
style="width: 85%"
/>
</el-form-item>
注意: node-key的值是menuList中的数据
const checkedKeys = this.$refs.menuTreeRef.getCheckedKeys()
const halfCheckedKeys = this.$refs.menuTreeRef.getHalfCheckedKeys()
this.roleForm.menuIdList = checkedKeys.concat(halfCheckedKeys)
13.2.2 新增请求
复用src\api\system\role\roleManage.js中addRole()
// 2.添加/修改角色
saveRole(role) {
// eslint-disable-next-line eqeqeq
if (role.id == null && role.id == undefined) {
return this.addRole(role)
} else {
return this.updateRole(role)
}
},
13.2.3 发送请求
复用src\views\system\role\index.vue中saveRole()
// 提交请求给后台
roleManage.saveRole(this.roleForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getRoleList()
})
13.2.4 数据回显
在openDialog()方法中添加
this.$refs.menuTreeRef.setCheckedKeys(this.roleForm.menuIdList)
openDialog(id) {
if (id == null) {
this.title = '添加角色'
this.dialogFormVisible = true
} else {
this.title = '修改角色'
this.dialogFormVisible = true
roleManage.getRoleById(id).then(res => {
this.roleForm = res.data
this.$refs.menuTreeRef.setCheckedKeys(this.roleForm.menuIdList)
})
}
},
14 用户角色
14.1 菜单列表
14.1.1 界面布局
在src\views\system\user\index.vue中添加复选框组件
<el-form-item :label-width="formLabelWidth" prop="roleIdList" label="角色">
<el-checkbox-group
v-model="userForm.roleIdList"
style="width: 85%"
:min="1"
:max="10"
>
<el-checkbox v-for="role in roleList" :key="role.id" :label="role.id">{{ role.roleDesc }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
定义接口后端查询用户列表数据参数和页面点选复选框接收参数。
注意:roleList: [] 和 roleIdList: [] 不是同一个接收参数,不能搞混,否则就会出现获取不到页面选中的复选框id,无法传入后端
roleList: [],
userForm: {
roleIdList: []
},
14.1.2 新增请求
在src\api\system\role\roleManage.js中getAllRoleList()
// 4.角色列表
getAllRoleList() {
return request({
url: '/system/role/all',
method: 'get'
})
}
14.1.3 发送请求
发送获取角色列表的请求
import roleManage from '@/api/system/roleManage'
// 4.角色列表
getAllRoleList() {
roleManage.getAllRoleList().then(res => {
this.roleList = res.data
console.log('4.角色列表', this.roleList)
})
},
发送添加用户角色信息的请求
// 2.添加/修改用户
saveUser() {
// 触发表单验证
this.$refs.userFormRef.validate((valid) => {
if (valid) {
// 提交请求给后台
userManage.saveUser(this.userForm).then(res => {
// 成功提示
this.$message({
type: 'success',
message: res.message
})
// 关闭对话框
this.dialogFormVisible = false
// 刷新表格数据
this.getUserList()
})
} else {
console.log('error submit!!')
return false
}
})
},
14.1.4 数据回显
页面发送添加用户角色请求,测试是否异常。
本文来自博客园,作者:screws,转载请注明原文链接:https://www.cnblogs.com/mrlumin/p/18602834