feat: 角色管理完善

This commit is contained in:
fit2cloud-chenyw 2021-02-24 13:41:04 +08:00
parent 7056db3b53
commit 2ba005db3d
10 changed files with 288 additions and 26 deletions

View File

@ -1,6 +1,8 @@
package io.dataease.base.domain;
import java.io.Serializable;
import java.util.Objects;
import lombok.Data;
@Data
@ -42,4 +44,30 @@ public class SysMenu implements Serializable {
private Long updateTime;
private static final long serialVersionUID = 1L;
/**
* 由于该类型作为HashSet key所以必须重写以下方法
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SysMenu menu = (SysMenu) o;
return Objects.equals(menuId, menu.menuId);
}
@Override
public int hashCode() {
return Objects.hash(menuId);
}
}

View File

@ -5,10 +5,15 @@ import io.dataease.controller.sys.response.RoleNodeResponse;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface ExtSysRoleMapper {
List<RoleNodeResponse> query(@Param("request")RoleGridRequest request);
int deleteRoleMenu(@Param("roleId") Long roleId);
int batchInsertRoleMenu(@Param("maps") List<Map<String, Long>> maps);
}

View File

@ -23,4 +23,16 @@
</select>
<delete id="deleteRoleMenu">
delete from sys_roles_menus where role_id = #{roleId}
</delete>
<insert id="batchInsertRoleMenu">
insert into sys_roles_menus (role_id, menu_id) values
<foreach collection="maps" item="map" separator=",">
(#{map.roleId},#{map.menuId})
</foreach>
</insert>
</mapper>

View File

@ -14,6 +14,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@ -29,15 +30,11 @@ public class SysMenuController {
@PostMapping("/childNodes/{pid}")
public List<MenuNodeResponse> childNodes(@PathVariable("pid") Long pid){
List<SysMenu> nodes = menuService.nodesByPid(pid);
List<MenuNodeResponse> nodeResponses = nodes.stream().map(node -> {
MenuNodeResponse menuNodeResponse = BeanUtils.copyBean(new MenuNodeResponse(), node);
menuNodeResponse.setHasChildren(node.getSubCount() > 0);
menuNodeResponse.setTop(node.getPid() == menuService.MENU_ROOT_PID);
return menuNodeResponse;
}).collect(Collectors.toList());
return nodeResponses;
return menuService.convert(nodes);
}
@ApiOperation("新增菜单")
@PostMapping("/create")
public void create(@RequestBody MenuCreateRequest request){
@ -49,6 +46,7 @@ public class SysMenuController {
public void delete(@RequestBody MenuDeleteRequest request){
menuService.delete(request);
}
@ApiOperation("更新菜单")
@PostMapping("/update")
public void update(@RequestBody MenuCreateRequest menu){
@ -56,4 +54,14 @@ public class SysMenuController {
}
@PostMapping("/childMenus/{pid}")
public Set<Long> childMenus(@PathVariable Long pid){
List<MenuNodeResponse> childs = menuService.childs(pid);
Set<Long> sets = childs.stream().map(MenuNodeResponse::getMenuId).collect(Collectors.toSet());
sets.add(pid);
return sets;
}
}

View File

@ -7,6 +7,7 @@ import io.dataease.base.domain.SysRole;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
import io.dataease.controller.sys.request.RoleGridRequest;
import io.dataease.controller.sys.request.RoleMenusRequest;
import io.dataease.controller.sys.response.RoleNodeResponse;
import io.dataease.service.sys.SysRoleService;
import io.swagger.annotations.Api;
@ -34,8 +35,8 @@ public class SysRoleController {
@ApiOperation("删除角色")
@PostMapping("/delete")
public void delete(Long roleId){
@PostMapping("/delete/{roleId}")
public void delete(@PathVariable("roleId") Long roleId){
sysRoleService.delete(roleId);
}
@ -52,4 +53,10 @@ public class SysRoleController {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, sysRoleService.query(request));
}
@PostMapping("/saveRolesMenus")
public void saveRolesMenus(@RequestBody RoleMenusRequest request){
sysRoleService.batchSaveRolesMenus(request);
}
}

View File

@ -0,0 +1,13 @@
package io.dataease.controller.sys.request;
import lombok.Data;
import java.util.List;
@Data
public class RoleMenusRequest {
private Long roleId;
private List<Long> menuIds;
}

View File

@ -7,11 +7,16 @@ import io.dataease.base.mapper.ext.ExtMenuMapper;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.sys.request.MenuCreateRequest;
import io.dataease.controller.sys.request.MenuDeleteRequest;
import io.dataease.controller.sys.response.MenuNodeResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class MenuService {
@ -108,5 +113,32 @@ public class MenuService {
return sysMenuMapper.updateByPrimaryKeySelective(sysMenu);
}
public List<MenuNodeResponse> childs(Long pid){
Set<SysMenu> childs = getChilds(nodesByPid(pid), new HashSet());
List<SysMenu> menus = childs.stream().collect(Collectors.toList());
List<MenuNodeResponse> responses = convert(menus);
return responses;
}
private Set<SysMenu> getChilds(List<SysMenu> lists, Set<SysMenu> sets){
lists.forEach(menu -> {
sets.add(menu);
List<SysMenu> kidMenus = nodesByPid(menu.getMenuId());
if (CollectionUtils.isNotEmpty(kidMenus)){
getChilds(kidMenus, sets);
}
});
return sets;
}
public List<MenuNodeResponse> convert(List<SysMenu> menus){
return menus.stream().map(node -> {
MenuNodeResponse menuNodeResponse = BeanUtils.copyBean(new MenuNodeResponse(), node);
menuNodeResponse.setHasChildren(node.getSubCount() > 0);
menuNodeResponse.setTop(node.getPid() == MENU_ROOT_PID);
return menuNodeResponse;
}).collect(Collectors.toList());
}
}

View File

@ -5,11 +5,16 @@ import io.dataease.base.domain.SysRole;
import io.dataease.base.mapper.SysRoleMapper;
import io.dataease.base.mapper.ext.ExtSysRoleMapper;
import io.dataease.controller.sys.request.RoleGridRequest;
import io.dataease.controller.sys.request.RoleMenusRequest;
import io.dataease.controller.sys.response.RoleNodeResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class SysRoleService {
@ -45,4 +50,19 @@ public class SysRoleService {
return result;
}
@Transactional
public int batchSaveRolesMenus(RoleMenusRequest request){
extSysRoleMapper.deleteRoleMenu(request.getRoleId());
List<Map<String, Long>> maps = request.getMenuIds().stream().map(menuId -> {
Map<String, Long> map = new HashMap<>();
map.put("roleId", request.getRoleId());
map.put("menuId", menuId);
return map;
}).collect(Collectors.toList());
return extSysRoleMapper.batchInsertRoleMenu(maps);
}
}

View File

@ -4,12 +4,12 @@
<el-aside width="70%" style="border: 1px solid #eee">
<el-card class="table-card">
<template v-slot:header>
<ms-table-header :condition.sync="condition" @search="search" @create="create" :create-tip="$t('user.create')" :title="$t('commons.user')"/>
<ms-table-header :condition.sync="condition" @search="search" @create="create" :create-tip="$t('role.add')" :title="$t('commons.role')"/>
</template>
<el-table border class="adjust-table" :data="tableData" style="width: 100%;">
<el-table border highlight-current-row class="adjust-table" :data="tableData" style="width: 100%;" @row-click="rowClick">
<el-table-column prop="name" label="名称" />
<el-table-column :show-overflow-tooltip="true" width="135px" prop="createTime" label="创建日期">
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
@ -35,9 +35,8 @@
:load="getMenuDatas"
:props="defaultProps"
check-strictly
accordion
show-checkbox
node-key="menuId"
node-key="id"
@check="menuChange"
/>
</el-tab-pane>
@ -45,6 +44,26 @@
</el-tabs>
</el-main>
</el-container>
<el-dialog :close-on-click-modal="false" :title="formType=='add' ? $t('role.add') : $t('role.modify')" :visible.sync="dialogVisible" width="580px" @closed="closeFunc"
:destroy-on-close="true">
<el-form ref="roleForm" inline :model="form" :rules="rule" size="small" label-width="80px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="form.name" style="width: 380px;" />
</el-form-item>
<el-form-item label="描述信息" prop="description">
<el-input v-model="form.description" style="width: 380px;" rows="5" type="textarea" />
</el-form-item>
</el-form>
<template v-slot:footer>
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="saveRole('roleForm')"/>
</template>
</el-dialog>
</div>
</template>
@ -55,7 +74,10 @@ import MsTableHeader from "../../common/components/MsTableHeader";
import MsTableOperator from "../../common/components/MsTableOperator";
import MsDialogFooter from "../../common/components/MsDialogFooter";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import {
listenGoBack,
removeGoBackListener
} from "@/common/js/utils";
export default {
name: 'role',
components: {
@ -70,9 +92,12 @@ export default {
return {
result: {},
queryPath: '/api/role/roleGrid',
deletePath: '/user/special/delete/',
createPath: '/user/special/add',
updatePath: '/user/special/update',
deletePath: '/api/role/delete/',
createPath: '/api/role/create',
updatePath: '/api/role/update',
queryMenusPath: '/api/menu/childNodes/',
childMenusPath: '/api/menu/childMenus/',
saveRoleMenusPath: '/api/role/saveRolesMenus',
currentPage: 1,
pageSize: 10,
total: 0,
@ -80,37 +105,147 @@ export default {
tableData: [],
menus: [],
menuIds: [],
defaultProps: {},
activeName: 'second'
defaultProps: { children: 'children', label: 'label' ,isLeaf: 'isLeaf'},
activeName: 'first',
dialogVisible: false,
formType: 'add',
form: {},
rule: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
]
},
currentRow: null
};
},
activated() {
this.search();
},
watch: {
currentRow: 'currentRowChange'
},
methods: {
handleClick(tab, event) {
console.log(tab, event);
},
create(){},
create(){
this.form = {}
this.formType = "add";
this.dialogVisible = true
listenGoBack(this.closeFunc)
},
search(){
this.result = this.$post(this.queryPath+ "/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
let data = response.data
this.total = data.itemCount
this.tableData = data.listObject
})
},
edit(row){
this.formType = 'modify'
this.dialogVisible = true
this.form = Object.assign({}, row)
listenGoBack(this.closeFunc)
},
getMenuDatas(node, resolve){
saveRole(roleForm){
this.$refs[roleForm].validate(valid => {
if (valid) {
const url = this.formType=='add' ? this.createPath : this.updatePath
this.result = this.$post(url, this.form, () => {
this.$success(this.$t('commons.save_success'))
this.search();
this.dialogVisible = false
});
} else {
return false;
}
})
},
closeFunc() {
this.dialogVisible = false
removeGoBackListener(this.closeFunc);
},
getMenuDatas(node, resolve){
this.$post(this.queryMenusPath+(node.data.id ? node.data.id : 0), null, (res) => {
const datas = res.data
const nodes = datas.map(data => this.formatNode(data))
resolve && resolve(nodes)
})
},
formatNode(node) {
const result = {
id: node.menuId,
label: node.title,
isLeaf: !node.hasChildren,
children: node.children
}
return result
},
menuChange(menu){
this.$post(this.childMenusPath + menu.id, null, res => {
const childIds = res.data
if (this.menuIds.indexOf(menu.id) !== -1) {
for (let i = 0; i < childIds.length; i++) {
const index = this.menuIds.indexOf(childIds[i])
if (index !== -1) {
this.menuIds.splice(index, 1)
}
}
} else {
for (let i = 0; i < childIds.length; i++) {
const index = this.menuIds.indexOf(childIds[i])
if (index === -1) {
this.menuIds.push(childIds[i])
}
}
}
console.log(this.menuIds)
this.$refs.menu.setCheckedKeys(this.menuIds)
this.saveMenus()
})
},
saveMenus(){
if (!this.currentRow) {
return
}
const param = {roleId: this.currentRow.roleId, menuIds: this.menuIds}
this.$post(this.saveRoleMenusPath, param, res => {
this.search()
})
},
rowClick(row,column, event){
this.currentRow = row
},
currentRowChange(newVal, oldVal){
if (newVal == oldVal) {
return
}
if (!newVal) {
this.menuIds = []
return
}
this.menuIds = newVal.menuIds;
this.$refs.menu.setCheckedKeys(this.menuIds)
},
handleDelete(row){
this.$confirm('确认删除角色['+row.name+']', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const url = this.deletePath+row.roleId
this.$post(url, null, () => {
this.$success(this.$t('commons.modify_success'))
this.search()
});
}).catch(() => {
})
}
}
}

View File

@ -385,6 +385,8 @@ export default {
test_user: '测试人员',
test_viewer: '只读用户',
add: '添加角色',
delete: '删除角色',
modify: '修改角色',
},
report: {
api_test_report: '接口测试报告',