旭锋科技制造信息管理系统-角色管理模块
一、模块功能
该模块主要解决把使用本系统的用户分类,不同类别的用户访问不同的页面。该模块同样完成角色的CRUD,启用、禁用,展示系统支持的角色数据。
二、模块分析
2.1 组件说明
- 角色管理组件:
RoleMngr.vue
- 作用:提供展示角色原始数据UI;提供
查询|新增|更新|删除|启用|禁用
菜单UI;提供查询UI。完成获取菜单原始数据,查询、删除、启用、禁用功能。
- 作用:提供展示角色原始数据UI;提供
- 角色新增或更新组件:
AddOrUpdateRole.vue
- 作用:提供新增|更新UI,完成新增|更新操作。
2.2 UI选择
- 数据展示使用el-table
- 组件内部菜单使用el-button
- 数据获取使用el-form
三、模块初始构建
3.1 构建客户端
3.1.1 构建 RoleMngr.vue
组件
<template>
<div>
<a-card title="角色管理" size="small" style="height: 813px; padding: 0 10px 0 10px ">
<el-row type="flex" justify="space-between" style="margin-top: 10px">
<!--该列提供查询UI-->
<el-col :span="12">
<el-form ref="rlQuery" :model="rlQueryInfo" :rules="rlQueryRule" inline size="small" status-icon >
<el-form-item prop="queryType">
<el-select v-model="rlQueryInfo.queryType" placeholder="请选择查询方式...">
<el-option value="0" label="角色名称"></el-option>
<el-option value="1" label="角色状态"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="queryKey">
<el-input v-model="rlQueryInfo.queryKey" placeholder="请输入查询关键字..." clearable></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" :disabled="menuStatus.query"><i class="fas fa-search"></i> 查询</el-button>
<el-button><i class="fas fa-redo-alt"></i> 重置</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
<!--独立菜单区:新增菜单-->
<el-col :span="2" align="end">
<el-button type="success" size="small" :disabled="menuStatus.add"><i class="fas fa-plus"></i> 新增</el-button>
</el-col>
</el-row>
<el-divider></el-divider>
<!--角色数据展示-->
<el-row type="flex" justify="center">
<el-table :data="roleData" size="small" :header-cell-style="{background:'#7dbcea',color:'#606266'}" max-height="600" :row-key="setRowKey">
<el-table-column label="角色ID"></el-table-column>
<el-table-column label="角色标识"></el-table-column>
<el-table-column label="角色名称"></el-table-column>
<el-table-column label="角色说明"></el-table-column>
<el-table-column label="角色状态"></el-table-column>
<el-table-column label="创建时间"></el-table-column>
<el-table-column label="创建人"></el-table-column>
<el-table-column label="修改时间"></el-table-column>
<el-table-column label="修改人"></el-table-column>
<el-table-column label="操作"></el-table-column>
</el-table>
</el-row>
<el-row type="flex" justify="end" style="margin-top: 15px">
<el-col :span="12" align="end">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :page-sizes="[1, 2, 5, 10, 20]"
:page-size="pagination.pageSize" :current-page.sync="pagination.currentPage" layout="total, sizes, prev, pager, next, jumper" :total="dataTotal"></el-pagination>
</el-col>
</el-row>
</a-card>
</div>
</template>
<script>
export default {
name: "RoleMngr",
inject: ["getChildrenMenuStatus"],
data(){
return{
/*查询UI绑定变量*/
rlQueryInfo: {
queryType: undefined,
queryKey: ""
},
rlQueryRule: {},
/*待展示的角色数据*/
roleData: [],
/*页面菜单状态*/
menuStatus: {
add: true,
update: true,
delete: true,
forbid: true,
enable: true,
query: true,
},
/*分页插件所需变量*/
pagination: {
pageSize: 1,
currentPage: 1
},
dataTotal: 0
}
},
methods: {
/*设置表格的rowKey*/
setRowKey(row) {
return row.id;
},
/*分页处理函数*/
handleSizeChange(value)
{
this.pagination.pageSize=value;
},
handleCurrentChange(value)
{
this.pagination.currentPage=value;
},
}
<style scoped>
.el-divider {
margin-top: 0!important;
}
</style>
3.1.2 构建路由组件在 /home
路由组件的 children
属性中
{
path: "/role",
component: _ => import("../views/role/RoleMngr"),
meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role", roleId: [1]}]
}
3.1.3 构建效果
3.2 构建数据表 sys_role
3.3 服务器端构建
3.3.1 定义封装数据库信息的实体类 SysRolePojo
package org.wjk.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("sys_role")
public class SysRolePojo extends BasePojo
{
private static final long serialVersionUID = -2091659483715729866L;
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String alias;
private String note;
private Boolean enabled = true;
private String createdUser;
private String modifiedUser;
3.3.2 控制层
构建
package org.wjk.controller;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/role")
// 目的:生成一个全参构造,使用构造方式完成依赖注入。
// @AutoWired特性:当一个类的对象由Spring管理时,该类有且只有一个构造函数时,该构造函数默认被@AutroWird标识。
@AllArgsConstructor
public class SysRoleCtrller
{
}
3.3.3 业务层
构建
service
层接口:SysRoleSvs
package org.wjk.service;
public interface SysRoleSvs
{
}
service
层接口的实现类:SysRoleSvsImpl
package org.wjk.service.impl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.wjk.service.SysRoleSvs;
@Service
@AllArgsConstructor
public class SysRoleSvsImpl implements SysRoleSvs
{
}
3.3.4 持久层
构建
package org.wjk.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.wjk.pojo.SysRolePojo;
@Mapper
public interface SysRoleDao extends BaseMapper<SysRolePojo>
{
}
3.3.5 Sql映射文件
构建 SysRole.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.wjk.dao.SysRoleDao">
<!--查询语句的书写顺序:[on Expr][where Expr][group by][having][order by][limit]-->
</mapper>
四、业务实现
4.1 RoleMngr.vue
初始化菜单状态
-
在
RoleMngr.vue
的methods属性中
定义设置页面菜单状态函数,并在created()
属性中调用该方法。/*设置菜单状态方法*/ async setMenuStatus() { let menuStatus = await this.getChildrenMenuStatus(this.$route.path); let currentUser = JSON.parse(sessionStorage.getItem("currentUser")); if (menuStatus && currentUser) { let permissions = currentUser.permissions; for (let item of menuStatus) { switch (item.name) { case "新增": this.menuStatus.add = !(item.enabled && permissions.includes("sys:role:add")); break; case "更新": this.menuStatus.update = !(item.enabled && permissions.includes("sys:role:update")); break; case "删除": this.menuStatus.delete = !(item.enabled && permissions.includes("sys:role:delete")); break; case "查询": this.menuStatus.query = !(item.enabled && permissions.includes("sys:role:query")); break; case "启用": this.menuStatus.enable = !(item.enabled && permissions.includes("sys:role:forbid")); break; case "禁用": this.menuStatus.forbid = !(item.enabled && permissions.includes("sys:role:enable")); break; } } } }
created() { this.setMenuStatus(); }
4.2 角色新增业务
4.2.1RoleMngr
的新增按钮绑定点击事件
<!--独立菜单区:新增菜单-->
<el-col :span="2" align="end">
<el-button type="success" size="small" :disabled="menuStatus.add" @click="handlerAddButtonClickEvent"><i class="fas fa-plus"></i> 新增</el-button>
</el-col>
4.2.2 在 methods
属性中定义点击事件处理函数 handlerAddButtonClickEvent
/*新增按钮点击事件处理函数*/
handlerAddButtonClickEvent()
{
this.$router.push("/role/add");
},
4.2.3在路由 index.js
中的 home
路由组件的 children
属性中定义子路由组件,完成页面跳转
{
path: "/role/add",
component: _ => import("../views/role/AddOrUpdateRole"),
meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role", roleId: [1]},{title: "角色新增", permission: "sys:role:add", roleId: [1]}]
}
4.2.4构建 AddOrUpdateRole.vue
组件
<template>
<a-card :title="pageTitle" size="small" style="height: 813px; padding: 0 10px 0 10px ">
<el-link slot="extra" type="primary" @click="returnToPreviousMenu"><i class="fas fa-fast-backward"></i> 返回</el-link>
<el-form ref="roleForm" :model="roleInfo" :rules="roleRules" label-width="100px" status-icon>
<el-row type="flex" justify="space-between" style="margin-top: 50px">
<el-col :span="12">
<el-form-item label="角色标识" prop="name">
<a-tooltip placement="topLeft" title="角色在系统中的英文标识">
<el-input v-model="roleInfo.name" placeholder="请输入角色标识..." maxlength="8" show-word-limit clearable @blur="roleInfo.name=roleInfo.name.trim()"></el-input>
</a-tooltip>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色名称" prop="alias">
<a-tooltip placement="topLeft" title="角色的中文名称">
<el-input v-model="roleInfo.alias" placeholder="请输入角色名称..." maxlength="16" show-word-limit clearable @blur="roleInfo.alias=roleInfo.alias.trim()"></el-input>
</a-tooltip>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="center">
<el-col :span="24">
<el-form-item label="功能说明" prop="note">
<el-input type="textarea" v-model="roleInfo.note" :rows="3" placeholder="请输入角色功能说明..." maxlength="128" show-word-limit
clearable @blur="roleInfo.note=roleInfo.note.trim()"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!--取消及确定按钮-->
<el-row type="flex" justify="end" style="margin-top: 400px">
<el-col :span="4" align="center">
<el-button>取消</el-button>
<el-button type="primary">确定</el-button>
</el-col>
</el-row>
</a-card>
</template>
<script>
export default {
name: "AddOrUpdateRole",
inject: ["returnToPreviousMenu"],
data(){
return{
pageTitle: "菜单新增",
/*执行操作:更新为1,新增为undefined*/
option: undefined,
/*录入角色信息表单*/
roleInfo: {
id: undefined,
name: "",
alias: "",
note: "",
createdUser: undefined,
enabled: true,
modifiedUser: undefined,
},
roleRules: {
name: [
{required: true, message: "角色标识不能为空,请输入!", trigger: "blur"}
],
alias: [
{required: true, message: "角色名称不能为空,请输入!", trigger: "blur"}
]
}
}
}
}
</script>
4.2.5初始化 AddOrUpdateRole
- 业务逻辑
- 该组件由
角色新增
业务与角色更新
业务共用,由组件变更option
来区分操作。- 当
option
为undefined
时:是新增操作。 - 当
option
为1
时:是更新操作。 - 该变量的值来源于路由组件的
path
属性。
- 当
- 该组件由
- 在
methods
中定义页面初始化方法initComponent
/*初始化组件*/
initThisComponent()
{
/*设置card的title属性。*/
this.pageTitle = this.$route.meta[this.$route.meta.length -1].title;
/*设置当前操作标识。*/
if("/role/update" === this.$route.path)
{
this.option = 1;
}
},
- 在
created()
钩子函数中调用初始化方法
created()
{
this.initThisComponent();
}
- 完成用户输入的二次校验
- 业务逻辑
- 校验成功:发起请求,将用户输入的角色信息发送给服务器端。
- 校验失败:提示用户输入无效,按照提示输入用户信息。
- 为该页面的
确定
及取消
按钮绑定点击事件。<!--取消及确定按钮--> <el-row type="flex" justify="end" style="margin-top: 400px"> <el-col :span="4" align="center"> <el-button @click="cancelHandler">取消</el-button> <el-button type="primary" @click="submitRoleData">确定</el-button> </el-col> </el-row>
- 在组件的
methods
中定义该点击事件处理方法:submitRoleData()
/*确定按钮点击事件*/ submitRoleData() { /*二次校验用户输入信息*/ this.$refs.roleForm.validate(val => { if(!val) { /*校验失败的处理逻辑*/ this.$message.error("您输入的角色信息无效,请重新输入!"); return; } /*校验成功的处理逻辑*/ let that = this; let currentUser = JSON.parse(sessionStorage.getItem("currentUser")).username; this.$confirm({ title: this.title, content: "该操作将永久"+ (that.option ? "修改指定的" : "保存录入的")+"角色信息,是否继续?", okText: "确定", cancelText: "取消", async onOk() { let resStatus, resMessage; /*新增角色处理逻辑*/ if(!that.option) { that.roleInfo.createdUser = currentUser; const {data : res} = await that.$axios.post("/role", that.roleInfo); resStatus = res.status; resMessage = res.message; if(2000 === res.status) { that.cancelHandler(); } } else { /*更新角色处理逻辑*/ } that.resMessage(resStatus, resMessage); }, onCancel() { that.resMessage(2000, "操作终止成功!"); } }) }) }
- 在组件的
methods
中定义该点击事件处理方法:cancelHandler()
/*取消按钮点击事件处理函数*/ cancelHandler() { this.$refs.roleForm.resetFields(); }
- 业务逻辑
4.2.6服务器端处理
-
SysRoleCtrllr
定义处理新增请求方法/*处理新增角色请求*/ @PostMapping public ResPackaging addNewRole(@RequestBody @Validated SysRolePojo rolePojo) { System.out.println(rolePojo); return ResPackaging.success("成功添加该角色信息,请求继续添加下条,退出请按返回键!"); }
-
SysRoleSvs
声明处理新增业务函数并在实现该方法在SysRoleSvsImpl
中void addNewRole(SysRolePojo rolePojo);
/*新增角色功能*/ @Override public void addNewRole(SysRolePojo rolePojo) { /*新增规则,不能新增同名的角色*/ Integer isExist = roleDao.selectExistElementByRoleName(rolePojo.getName()); if(null != isExist) throw new ServiceException(ExcInfo.DATA_NAME_ALREADY_EXISTS); int istCnts = roleDao.insert(rolePojo); if(istCnts != 1) throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT); }
-
SysRoleDao
中声明所需方法Integer selectExistElementByRoleName(String name);
-
SysRole.xml
定义对应的动态Sql<select id="selectExistElementByRoleName" resultType="Integer"> select 1 from sys_role where name=#{name} limit 1; </select>
4.3 角色数据展示
4.3.1 业务说明
通过分页查询的方法,获取数据中角色数据,前在客户端中展示,并实现Redis缓存。
4.3.2 客户端发起获取角色数据请求
-
RoleMngr.vue
的methods
属性中定义获取角色数据函数/*角色数据获取函数*/ async getAllRoleDatas() { const {data: res} = await this.$axios.get("/role", {params: this.pagination}); if (2000 === res.status && res.data.data && res.data.data.length > 0) { this.roleData = res.data.data; this.dataTotal = res.data.totalCounts; } }
-
RoleMngr.vue
的created
生命周期钩子中调用上述方法created() { this.setMenuStatus(); this.getAllRoleDatas(); }
4.3.3服务器端处理请求
-
SysRoleCtrllr
中定义请求处理的方法getAllRolesDataHandler
/*处理获取角色数据请求*/ @GetMapping public ResPackaging getAllRolesDataHandler(@Validated @NotNull Integer pageSize, @Validated @NotNull Integer currentPage) { return ResPackaging.success("OK!", roleSvs.getAllRolesData(pageSize, currentPage)); }
-
SysRoleSvs
中声明获取角色数据的业务处理函数,并在SysRoleSvsImpl
中实现该方法PaginationResPackagin getAllRolesData(Integer pageSize, Integer currentPage);
/*角色数据获取业务*/ @Override @CacheReader("ROLE::") public PaginationResPackagin getAllRolesData(Integer pageSize, Integer currentPage) { /*获取总数据数*/ int totalData = Math.toIntExact(roleDao.selectCount(null)); if(totalData <= 0) throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE); /*计算当前起始索引*/ int index = (currentPage - 1) * pageSize; List<SysRolePojo> res = roleDao.getAllRolesData(index, pageSize); if(res.isEmpty()) throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE); return new PaginationResPackagin(totalData, res); }
-
SysRoleDao
中声明访问持久层方法List<SysRolePojo> getAllRolesData(Integer index, Integer pageSize);
-
SysRole.xml
中定义相关映射Sql<select id="getAllRolesData" resultType="org.wjk.pojo.SysRolePojo"> select id, name, alias, note, enabled, created_time, created_user, modified_time, modified_user from sys_role limit #{index}, #{pageSize} </select>
4.3.4 客户端展示数据及分页处理
-
客户端展示数据:修改
el-table
<el-table :data="roleData" size="small" :header-cell-style="{background:'#7dbcea',color:'#606266'}" max-height="600" :row-key="setRowKey"> <el-table-column type="index" label="序号" align="center" min-width="5%"></el-table-column> <el-table-column prop="name" label="角色标识" align="center" min-width="8%"></el-table-column> <el-table-column prop="alias" label="角色名称" align="center" min-width="10%"></el-table-column> <el-table-column prop="note" label="角色说明" show-overflow-tooltip align="center" min-width="18%"></el-table-column> <el-table-column prop="enabled" label="角色状态" align="center" min-width="7%"> <template v-slot="item"> <el-tag v-if="item.row.enabled" type="seccus" size="small">正常</el-tag> <el-tag v-else type="error" size="small">禁用</el-tag> </template> </el-table-column> <el-table-column prop="createdTime" label="创建时间" align="center" min-width="10%"></el-table-column> <el-table-column prop="createdUser" label="创建人" align="center" min-width="10%"></el-table-column> <el-table-column prop="modifiedTime" label="修改时间" align="center" min-width="10%"> <template v-slot="item"> {{item.row.modifiedTime ? item.row.modifiedTime : "无"}} </template> </el-table-column> <el-table-column prop="modifiedUser" label="修改人" align="center" min-width="10%"> <template v-slot="item"> {{item.row.modifiedUser ? item.row.modifiedUser : "无"}} </template> </el-table-column> <el-table-column label="操作" align="center" min-width="17%"> <template v-slot="item"> <el-link type="warning" :disabled="menuStatus.update"><i class="fas fa-edit"></i> 更新</el-link> <el-divider direction="vertical"/> <el-link type="danger" :disabled="menuStatus.delete"><i class="fas fa-trash-alt"></i> 删除</el-link> <el-divider direction="vertical"/> <el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid"><i class="fas fa-redo-alt"></i> 禁用</el-link> <el-link v-else type="seccuss" :disabled="menuStatus.enable"><i class="fas fa-redo-alt"></i> 启用</el-link> </template> </el-table-column > </el-table>
-
RoleMngr.vue
的methods
属性中定义分页页面更新时处理函数handleSizeChange
handleSizeChange(value) { this.pagination.pageSize=value; this.getAllRoleDatas(); },
-
RoleMngr.vue
的methods
属性中定义分页页面更新时处理函数handleCurrentChange
handleCurrentChange(value) { this.pagination.currentPage=value; this.getAllRoleDatas(); },
4.4 角色更新业务
4.4.1 业务需要
修改已有的角色信息,并修改后的角色标识不能同已有的角色标识同名。
4.4.2 RoleMngr
组件业务实现
更新
按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
<template v-slot="item">
<el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
<el-divider direction="vertical"/>
<el-link type="danger" :disabled="menuStatus.delete"><i class="fas fa-trash-alt"></i> 删除</el-link>
<el-divider direction="vertical"/>
<el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid"><i class="fas fa-redo-alt"></i> 禁用</el-link>
<el-link v-else type="seccuss" :disabled="menuStatus.enable"><i class="fas fa-redo-alt"></i> 启用</el-link>
</template>
</el-table-column >
methods
属性内定义更新点击事件处理函数- 主要功能:手动触发路由,完成页面跳转
AddOrUpdateRole
页面,并将该行的角色数据通过sessionStorage
传递给AddOrUpdateRole
组件。
- 主要功能:手动触发路由,完成页面跳转
/*更新按钮点击事件处理函数*/
updateButtonClickHandler(value)
{
sessionStorage.setItem("role", JSON.stringify(value));
this.$router.push("/role/update")
}
- 在
home
路由组件中定义/role/update
子路由组件
{
path: "/role/update",
component: _ => import("../views/role/AddOrUpdateRole"),
meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role", roleId: [1]},{title: "角色更新", permission: "sys:role:update", roleId: [1]}]
}
4.4.3 AddOrUpdateRole
组件业务实现
- 完成该组件
更新
操作的初始化- 获取
sessionStorage
中参数,copy到form表单绑定的变量中。 - 方法:修改已定义的
initThisComponent()
方法中的更新时业务逻辑
- 获取
/*初始化组件*/
initThisComponent()
{
/*设置card的title属性。*/
this.pageTitle = this.$route.meta[this.$route.meta.length -1].title;
/*设置当前操作标识。*/
if("/role/update" === this.$route.path)
{
this.option = 1;
let role = JSON.parse(sessionStorage.getItem("role"));
if(role)
{
this.roleInfo = {... role};
}
}
},
- 修改组件
methods
属性中submitRoleData()
,发起更新请求,并在处理响应。
/*确定按钮点击事件*/
submitRoleData()
{
/*二次校验用户输入信息*/
this.$refs.roleForm.validate(val => {
if(!val)
{
/*校验失败的处理逻辑*/
this.$message.error("您输入的角色信息无效,请重新输入!");
return;
}
/*校验成功的处理逻辑*/
let that = this;
let currentUser = JSON.parse(sessionStorage.getItem("currentUser")).username;
this.$confirm({
title: this.title, content: "该操作将永久"+ (that.option ? "修改指定的" : "保存录入的")+"角色信息,是否继续?", okText: "确定", cancelText: "取消",
async onOk()
{
let resStatus, resMessage;
/*新增角色处理逻辑*/
if(!that.option)
{
that.roleInfo.createdUser = currentUser;
const {data : res} = await that.$axios.post("/role", that.roleInfo);
resStatus = res.status;
resMessage = res.message;
if(2000 === resStatus)
{
that.cancelHandler();
}
}
else
{
/*更新角色处理逻辑*/
that.roleInfo.modifiedUser = currentUser;
const {data : res} = await that.$axios.put("role", that.roleInfo);
resStatus = res.status;
resMessage = res.message;
if(2000 === resStatus)
{
sessionStorage.removeItem("role");
that.$router.go(-1);
}
}
that.resMessage(resStatus, resMessage);
},
onCancel()
{
that.resMessage(2000, "操作已终止!");
}
})
})
},
4.4.4 服务器端处理请求,完成响应
SysRoleCtrllr
中定义处理更新请求的方法并设置权限
/*处理角色更新请求*/
@PutMapping
@PreAuthorize("hasAuthority('sys:role:update')")
public ResPackaging updateSpecificRoleHanlder(@RequestBody @Validated(SysRolePojo.update.class) SysRolePojo rolePojo)
{
roleSvs.updateSpecificRole(rolePojo);
return ResPackaging.success("角色信息修改成功!");
}
SysRoleSvs
中声明处理更新的业务方法,并在SysRoleSvsImpl
中实现该方法前刷新缓存。
void updateSpecificRole(SysRolePojo rolePojo);
@Override
@CacheWriter("ROLE")
public void updateSpecificRole(SysRolePojo rolePojo)
{
Integer extId = roleDao.selectExistElementByRoleName(rolePojo.getName());
if(null != extId && !extId.equals(rolePojo.getId()))
throw new ServiceException(ExcInfo.DATA_NAME_ALREADY_EXISTS);
//int updtCnts = roleDao.update(rolePojo, new UpdateWrapper<SysRolePojo>().eq("id", rolePojo.getId()));
int updtCnts = roleDao.updateById(rolePojo);
if(1 != updtCnts)
throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
}
4.5 删除角色数据实现
4.5.1 业务需求
当有权限的操作人点击某一角色对应的删除按钮时,如果该角色没有对应的用户时,则服务器删除该角色数据;如果有对应用户,则会提醒操作人该角色不能删除。
4.5.2 RoleMngr
组件业务实现
- 为
删除
按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
<template v-slot="item">
<el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
<el-divider direction="vertical"/>
<el-link type="danger" :disabled="menuStatus.delete" @click="deleteBtnClkHandler(item.row.id)"><i class="fas fa-trash-alt"></i> 删除</el-link>
<el-divider direction="vertical"/>
<el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 禁用</el-link>
<el-link v-else type="seccuss" :disabled="menuStatus.enable" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 启用</el-link>
</template>
</el-table-column >
- 组件
methods
属性中定义删除按钮点击事件处理函数deleteBtnClkHandler(value)
/*删除按钮点击事件处理函数*/
deleteBtnClkHandler(param)
{
let that = this;
this.$confirm({
title: "角色删除", content: "该操作将永久删除此角色信息,是否继续?", okText: "确定", cancelText: "取消",
async onOk()
{
const {data : res} = await that.$axios.delete(`/role/${param}`);
if(2000 === res.status)
{
that.pagination.pageSize = 5;
that.pagination.currentPage = 1;
await that.getAllRoleDatas();
}
that.resMessage(res.status, res.message);
},
onCancel()
{
that.resMessage(2000, "操作已终止!");
}
})
},
4.5.3 服务器端处理请求,返回响应
SysRoleCtrllr
中定义处理删除请求的方法并设置权限
/*处理角色删除请求*/
@DeleteMapping("/{roleId}")
@PreAuthorize("hasAuthority('sys:role:delete')")
public ResPackaging deleteSepcificRoleHandler(@PathVariable @Validated @NotNull Integer roleId)
{
roleSvs.deleteSepcificRole(roleId);
return ResPackaging.success("角色信息删除成功!");
}
SysRoleSvs
中声明处理删除的业务方法,并在SysRoleSvsImpl
中实现该方法前刷新缓存。
void deleteSepcificRole(Integer roleId);
/*删除角色业务*/
@Override
@CacheWriter("ROLE")
public void deleteSepcificRole(Integer roleId)
{
/*查找是否有该角色类型的用户*/
Integer extUsr = roleDao.isExistUserByRoleId(roleId);
/*如果有则提示操作人不能删除该角色*/
if(null != extUsr)
throw new ServiceException(ExcInfo.EXIST_USER_BY_ROLE);
/*如果没有则删除角色*/
int dltCnts = roleDao.deleteById(roleId);
if(1 != dltCnts)
throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
}
SysRoleDao
中声明辅助方法isExistUserByRoleId(roleId)
Integer isExistUserByRoleId(Integer roleId);
SysRole.xml
中定义映射Sql
<select id="isExistUserByRoleId" resultType="Integer">
select id from sys_user where role_id=#{roleId} limit 1;
</select>
4.6 启用|禁用角色实现
4.6.1 业务需求
- 当有权限的操作人点击某一角色对应的
禁用
按钮时,如果该角色没有对应的用户时,则服务器禁用该角色;如果有对应用户,则会提醒操作人该角色不能禁用。 - 当有权限的操作人点击某一角色对应的
启用
按钮时,服务器直接启用该角色。
4.6.2 RoleMngr
组件业务实现
- 为
禁用|启用
按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
<template v-slot="item">
<el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
<el-divider direction="vertical"/>
<el-link type="danger" :disabled="menuStatus.delete" @click="deleteBtnClkHandler(item.row.id)"><i class="fas fa-trash-alt"></i> 删除</el-link>
<el-divider direction="vertical"/>
<el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 禁用</el-link>
<el-link v-else type="seccuss" :disabled="menuStatus.enable" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 启用</el-link>
</template>
</el-table-column >
- 组件
methods
属性中定义禁用|启用
按钮点击事件处理函数fbdOrEablBtnClkHandler(id, enabled)
/*禁用|启用按钮点击事件处理函数*/
fbdOrEablBtnClkHandler(id, enabled)
{
let that = this;
this.$confirm({
title: enabled ? "角色禁用" : "角色启用", content: "该操作将永久"+(enabled ? "禁用" : "启用")+"此角色,是否继续?", okText: "确定", cancelText: "取消",
async onOk()
{
const {data : res} = await that.$axios.put(`/role/enable/${id}/${enabled}`);
if(2000 === res.status)
{
that.pagination.pageSize = 5;
that.pagination.currentPage = 1;
await that.getAllRoleDatas();
}
that.resMessage(res.status, res.message);
},
onCancel()
{
that.resMessage(2000, "操作已终止!");
}
})
}
4.6.3 服务器端处理请求,返回响应
SysRoleCtrllr
中定义处理禁用|启用
请求的方法并设置权限
/*处理角色启用禁用请求*/
@PutMapping("/enable/{id}/{enable}")
@PreAuthorize("hasAnyAuthority('sys:role:enable', 'sys:role:forbid')")
public ResPackaging enOrForSpecificRoleHandler(@PathVariable @Validated @NotNull Integer id, @PathVariable @Validated @NotNull Boolean enable)
{
roleSvs.enOrForSpecificRole(id, enable);
return ResPackaging.success((enable ? "禁用" : "启用") + "该角色成功!");
}
SysRoleSvs
中声明处理禁用|启用
的业务方法,并在SysRoleSvsImpl
中实现该方法前刷新缓存。
void enOrForSpecificRole(Integer id, Boolean enable);
@Override
@CacheWriter("ROLE")
public void enOrForSpecificRole(Integer id, Boolean enable)
{
if(enable)
{
Integer extUsr = roleDao.isExistUserByRoleId(id);
if(null != extUsr)
throw new ServiceException(ExcInfo.EXIST_USER_BY_ROLE);
}
int updtCnts = roleDao.enOrForSpecificRole(id, !enable);
if(updtCnts != 1)
throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
}
SysRoleDao
中声明禁用|启用
方法enOrForSpecificRole(id, enable)
int enOrForSpecificRole(Integer id, boolean b);
SysRole.xml
中定义映射Sql
<update id="enOrForSpecificRole">
update sys_role set enabled=#{b} where id=#{id}
</update>
4.7 角色查询
4.7.1 业务需求
- 根据查询方式及查询关键字构成的查询条件,查询对应的角色数据。并将数据展示在表中。
- 当点击重置时,清空查询信息,并显示原始分页角色数据。
4.7.2 RoleMngr
组件业务实现
- 为
查询
及重置
绑定点击事件
<el-form-item>
<el-button-group>
<el-button type="primary" :disabled="menuStatus.query" @click="queryBtnClckHandler"><i class="fas fa-search"></i> 查询</el-button>
<el-button @click="resetBtnClkHandler"><i class="fas fa-redo-alt"></i> 重置</el-button>
</el-button-group>
</el-form-item>
-
在组件
methods
属性中定义两个点击事件处理函数- 查询按钮点击事件函数
queryBtnClckHandler
/*查询按钮点击事件*/ queryBtnClckHandler() { this.$refs.rlQuery.validate( async value=>{ if(!value) { this.resMessage(0, "您的查询信息无效,请重新输入查询条件!"); return; } const {data : res} = await this.$axios.get(`/role/query/${this.rlQueryInfo.queryType}/${this.rlQueryInfo.queryKey}/5/1`); if(2000 === res.status && res.data.data && res.data.data.length > 0) { this.pagination.pageSize=5; this.pagination.currentPage=1; this.dataTotal = res.data.totalCounts; this.roleData = res.data.data; } else { this.resMessage(res.status, res.message); } }) },
- 重置按钮点击事件处理函数
resetBtnClkHandler
/*重置按钮点击事件*/ resetBtnClkHandler() { this.$refs.rlQuery.resetFields(); this.pagination.pageSize = 5; this.pagination.currentPage = 1; this.getAllRoleDatas(); }
- 查询按钮点击事件函数
4.7.3 服务器端处理请求及响应结果
SysRoleCtrllr
定义处理查询请求方法
@GetMapping("/query/{type}/{key}/{pgSize}/{crrntPg}")
@PreAuthorize("hasAuthority('sys:role:query')")
public ResPackaging queryRoleDataByConditionHandler(@PathVariable @Validated @NotNull Integer type, @PathVariable @Validated @NotEmpty String key,
@PathVariable @Validated @NotNull Integer pgSize, @PathVariable @Validated @NotNull Integer crrntPg)
{
return ResPackaging.success("ok", roleSvs.queryRoleDataByCondition(type, key, pgSize, crrntPg));
}
SysRoleSvs
声明处理角色查询的业务方法并在实现类SysRolesSvsImpl
中实现该方法
PaginationResPackaging queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer crrntPg);
@Override
public PaginationResPackaging queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer crrntPg)
{
int dataTotal = roleDao.getDataTotalCountsValidateCondition(type, key);
if(0 == dataTotal)
throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE);
int index = (crrntPg - 1) * pgSize;
List<SysRolePojo> rs = roleDao.queryRoleDataByCondition(type, key, pgSize, index);
if(rs.isEmpty())
throw new ServiceException(ExcInfo.SYSTEM_INTERNAL_ERROR);
return new PaginationResPackaging(dataTotal, rs);
}
SysRoleDao
声明相关映射方法
int getDataTotalCountsValidateCondition(Integer type, String key);
List<SysRolePojo> queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer index);
SysRole.xml
定义映射Sql
<select id="getDataTotalCountsValidateCondition" resultType="Integer">
select count(*) from sys_role
<where>
<choose>
<when test="type==0">
instr(name, #{key})<!--该方法据资料上说可以优化模糊查询-->
</when>
<when test="type==1">
instr(alias, #{key})
</when>
<when test="type==2">
<choose>
<when test="key=='正常'">
enabled=1
</when>
<when test="key=='正常'">
enabled=0
</when>
<otherwise>
enabled=200
</otherwise>
</choose>
</when>
</choose>
</where>
</select>
<select id="queryRoleDataByCondition" resultType="org.wjk.pojo.SysRolePojo">
select id, name, alias, note, enabled, created_time, created_user, modified_time, modified_user from sys_role
<where>
<choose>
<when test="type==0">
instr(name, #{key})
</when>
<when test="type==1">
instr(alias, #{key})
</when>
<when test="type==2">
<choose>
<when test="key=='正常'">
enabled=1
</when>
<when test="key=='正常'">
enabled=0
</when>
<otherwise>
enabled=200
</otherwise>
</choose>
</when>
</choose>
</where>
limit #{index}, #{pgSize}
</select>
四、业务总结
到此,角色模块已完成,需要思考的是,当项目处于生产环境时,角色的 新增 、 更新、 删除的存在是否合理。