Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
677bdb959a
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.User;
|
||||
import io.metersphere.controller.request.member.QueryMemberRequest;
|
||||
import io.metersphere.dto.UserRoleHelpDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtUserRoleMapper {
|
||||
|
||||
List<UserRoleHelpDTO> getUserRoleHelpList(@Param("userId") String userId);
|
||||
|
||||
List<User> getMemberList(@Param("member") QueryMemberRequest request);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?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="io.metersphere.base.mapper.ext.ExtUserRoleMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.dto.LoadTestDTO"
|
||||
extends="io.metersphere.base.mapper.LoadTestMapper.BaseResultMap">
|
||||
<result column="project_name" property="projectName"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="getUserRoleHelpList" parameterType="java.lang.String"
|
||||
resultType="io.metersphere.dto.UserRoleHelpDTO">
|
||||
SELECT
|
||||
user_role.role_id AS roleId,
|
||||
role.`name` AS roleName,
|
||||
user_role.source_id AS sourceId,
|
||||
|
||||
IF(workspace.id IS NULL,IF(organization.id IS NULL,'',organization.`name`),workspace.name) AS sourceName,
|
||||
|
||||
IF(workspace.id IS NULL,NULL,workspace.organization_id) AS parentId
|
||||
|
||||
FROM user_role LEFT JOIN role ON role.id = user_role.role_id
|
||||
|
||||
LEFT JOIN workspace ON workspace.id = user_role.source_id
|
||||
|
||||
LEFT JOIN organization ON organization.id = user_role.source_id
|
||||
|
||||
WHERE user_role.user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="getMemberList" resultType="io.metersphere.base.domain.User">
|
||||
SELECT `user`.* FROM user_role JOIN `user` ON user_role.user_id = `user`.id
|
||||
WHERE user_role.source_id = #{member.workspaceId} AND user_role.role_id = #{member.roleId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public class RoleConstants {
|
||||
public final static String ADMIN = "admin";
|
||||
public final static String ORG_ADMIN = "org_admin";
|
||||
public final static String TEST_VIEWER = "test_viewer";
|
||||
public final static String TEST_MANAGER = "test_manager";
|
||||
public final static String TEST_USER = "test_user";
|
||||
}
|
|
@ -1,10 +1,19 @@
|
|||
package io.metersphere.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.Role;
|
||||
import io.metersphere.base.domain.User;
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.controller.request.member.AddMemberRequest;
|
||||
import io.metersphere.controller.request.member.QueryMemberRequest;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.dto.UserOperateDTO;
|
||||
import io.metersphere.dto.UserRoleDTO;
|
||||
import io.metersphere.service.UserService;
|
||||
import io.metersphere.user.SessionUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -23,16 +32,67 @@ public class UserController {
|
|||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public List<User> getUserList() { return userService.getUserList(); }
|
||||
public List<User> getUserList() {
|
||||
return userService.getUserList();
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{userId}")
|
||||
public void deleteUser(@PathVariable(value = "userId") String userId) { userService.deleteUser(userId); }
|
||||
public void deleteUser(@PathVariable(value = "userId") String userId) {
|
||||
userService.deleteUser(userId);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public void updateUser(@RequestBody User user) { userService.updateUser(user); }
|
||||
public void updateUser(@RequestBody User user) {
|
||||
userService.updateUser(user);
|
||||
}
|
||||
|
||||
@GetMapping("/role/list/{userId}")
|
||||
public List<Role> getUserRolesList(@PathVariable(value = "userId") String userId) {
|
||||
return userService.getUserRolesList(userId);
|
||||
}
|
||||
|
||||
@GetMapping("/rolelist/{userId}")
|
||||
public List<UserRoleDTO> convertUserRoleDTO(@PathVariable(value = "userId") String userId) {
|
||||
return userService.getUserRoleList(userId);
|
||||
}
|
||||
|
||||
@PostMapping("/switch/source/{sourceId}")
|
||||
public void switchUserRole(@PathVariable(value = "sourceId") String sourceId) {
|
||||
UserDTO user = SessionUtils.getUser();
|
||||
userService.switchUserRole(user, sourceId);
|
||||
}
|
||||
|
||||
@GetMapping("/info/{userId}")
|
||||
public User getUserInfo(@PathVariable(value = "userId") String userId) {
|
||||
return userService.getUserInfo(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取成员用户
|
||||
*/
|
||||
@PostMapping("/member/list/{goPage}/{pageSize}")
|
||||
@RequiresRoles(RoleConstants.TEST_MANAGER)
|
||||
public Pager<List<User>> getMemberList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryMemberRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page, userService.getMemberList(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加成员
|
||||
*/
|
||||
@PostMapping("/member/add")
|
||||
@RequiresRoles(RoleConstants.TEST_MANAGER)
|
||||
public void addMember(@RequestBody AddMemberRequest request) {
|
||||
userService.addMember(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除成员
|
||||
*/
|
||||
@GetMapping("/member/delete/{workspaceId}/{userId}")
|
||||
@RequiresRoles(RoleConstants.TEST_MANAGER)
|
||||
public void deleteMember(@PathVariable String workspaceId, @PathVariable String userId) {
|
||||
userService.deleteMember(workspaceId, userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.controller.request.member;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AddMemberRequest {
|
||||
|
||||
private String workspaceId;
|
||||
|
||||
private List<String> userIds;
|
||||
|
||||
public String getWorkspaceId() {
|
||||
return workspaceId;
|
||||
}
|
||||
|
||||
public void setWorkspaceId(String workspaceId) {
|
||||
this.workspaceId = workspaceId;
|
||||
}
|
||||
|
||||
public List<String> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<String> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.controller.request.member;
|
||||
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
|
||||
public class QueryMemberRequest {
|
||||
private String workspaceId;
|
||||
private String roleId = RoleConstants.TEST_MANAGER;
|
||||
|
||||
public String getWorkspaceId() {
|
||||
return workspaceId;
|
||||
}
|
||||
|
||||
public void setWorkspaceId(String workspaceId) {
|
||||
this.workspaceId = workspaceId;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,16 @@ public class UserDTO {
|
|||
|
||||
private Long updateTime;
|
||||
|
||||
private String lastSourceId;
|
||||
|
||||
public String getLastSourceId() {
|
||||
return lastSourceId;
|
||||
}
|
||||
|
||||
public void setLastSourceId(String lastSourceId) {
|
||||
this.lastSourceId = lastSourceId;
|
||||
}
|
||||
|
||||
private List<Role> roles = new ArrayList<>();
|
||||
|
||||
public List<Role> getRoles() {
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
public class UserRoleDTO {
|
||||
|
||||
private String id;
|
||||
private String roleId;
|
||||
private String type;
|
||||
private String name;
|
||||
private String desc;
|
||||
private String parentId;
|
||||
private Boolean switchable = true;
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(String roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getSwitchable() {
|
||||
return switchable;
|
||||
}
|
||||
|
||||
public void setSwitchable(Boolean switchable) {
|
||||
this.switchable = switchable;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
public class UserRoleHelpDTO {
|
||||
|
||||
private String roleId;
|
||||
private String roleName;
|
||||
private String sourceId;
|
||||
private String sourceName;
|
||||
private String parentId;
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(String roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return sourceId;
|
||||
}
|
||||
|
||||
public void setSourceId(String sourceId) {
|
||||
this.sourceId = sourceId;
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
public void setSourceName(String sourceName) {
|
||||
this.sourceName = sourceName;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,18 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.OrganizationMapper;
|
||||
import io.metersphere.base.mapper.RoleMapper;
|
||||
import io.metersphere.base.mapper.UserMapper;
|
||||
import io.metersphere.base.mapper.UserRoleMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtUserRoleMapper;
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.controller.request.member.AddMemberRequest;
|
||||
import io.metersphere.controller.request.member.QueryMemberRequest;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.dto.UserOperateDTO;
|
||||
import io.metersphere.dto.UserRoleDTO;
|
||||
import io.metersphere.dto.UserRoleHelpDTO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -14,7 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -27,6 +33,10 @@ public class UserService {
|
|||
private RoleMapper roleMapper;
|
||||
@Resource
|
||||
private UserRoleMapper userRoleMapper;
|
||||
@Resource
|
||||
private ExtUserRoleMapper extUserRoleMapper;
|
||||
@Resource
|
||||
private OrganizationMapper organizationMapper;
|
||||
|
||||
public UserDTO insert(User user) {
|
||||
checkUserParam(user);
|
||||
|
@ -113,4 +123,133 @@ public class UserService {
|
|||
roleExample.createCriteria().andIdIn(roleIds);
|
||||
return roleMapper.selectByExample(roleExample);
|
||||
}
|
||||
|
||||
public List<UserRoleDTO> getUserRoleList(String userId) {
|
||||
if (StringUtils.isEmpty(userId)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return convertUserRoleDTO(extUserRoleMapper.getUserRoleHelpList(userId));
|
||||
}
|
||||
|
||||
private List<UserRoleDTO> convertUserRoleDTO(List<UserRoleHelpDTO> helpDTOList) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
Map<String, UserRoleDTO> roleMap = new HashMap<>();
|
||||
|
||||
List<UserRoleDTO> resultList = new ArrayList<>();
|
||||
|
||||
List<UserRoleDTO> otherList = new ArrayList<>();
|
||||
|
||||
Set<String> orgSet = new HashSet<>();
|
||||
|
||||
Set<String> workspaceSet = new HashSet<>();
|
||||
|
||||
for (UserRoleHelpDTO helpDTO : helpDTOList) {
|
||||
UserRoleDTO userRoleDTO = roleMap.get(helpDTO.getSourceId());
|
||||
|
||||
if (userRoleDTO == null) {
|
||||
userRoleDTO = new UserRoleDTO();
|
||||
|
||||
if (!StringUtils.isEmpty(helpDTO.getParentId())) {
|
||||
workspaceSet.add(helpDTO.getParentId());
|
||||
userRoleDTO.setType("workspace");
|
||||
} else {
|
||||
orgSet.add(helpDTO.getSourceId());
|
||||
userRoleDTO.setType("organization");
|
||||
}
|
||||
|
||||
userRoleDTO.setId(helpDTO.getSourceId());
|
||||
userRoleDTO.setRoleId(helpDTO.getRoleId());
|
||||
userRoleDTO.setName(helpDTO.getSourceName());
|
||||
userRoleDTO.setParentId(helpDTO.getParentId());
|
||||
userRoleDTO.setDesc(helpDTO.getRoleName());
|
||||
|
||||
} else {
|
||||
userRoleDTO.setDesc(userRoleDTO.getDesc() + "," + helpDTO.getRoleName());
|
||||
}
|
||||
roleMap.put(helpDTO.getSourceId(), userRoleDTO);
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(buffer.toString())) {
|
||||
UserRoleDTO dto = new UserRoleDTO();
|
||||
dto.setId("admin");
|
||||
dto.setType("admin");
|
||||
dto.setDesc(buffer.toString());
|
||||
resultList.add(dto);
|
||||
}
|
||||
|
||||
for (String org : orgSet) {
|
||||
workspaceSet.remove(org);
|
||||
}
|
||||
|
||||
List<UserRoleDTO> orgWorkSpace = new ArrayList<>(roleMap.values());
|
||||
|
||||
if (!CollectionUtils.isEmpty(workspaceSet)) {
|
||||
for (String orgId : workspaceSet) {
|
||||
Organization organization = organizationMapper.selectByPrimaryKey(orgId);
|
||||
if (organization != null) {
|
||||
UserRoleDTO dto = new UserRoleDTO();
|
||||
dto.setId(orgId);
|
||||
dto.setName(organization.getName());
|
||||
dto.setSwitchable(false);
|
||||
dto.setType("organization");
|
||||
orgWorkSpace.add(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
orgWorkSpace.sort((o1, o2) -> {
|
||||
if (o1.getParentId() == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (o2.getParentId() == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return o1.getParentId().compareTo(o2.getParentId());
|
||||
});
|
||||
resultList.addAll(orgWorkSpace);
|
||||
resultList.addAll(otherList);
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void switchUserRole(UserDTO user, String sourceId) {
|
||||
User newUser = new User();
|
||||
BeanUtils.copyProperties(user, newUser);
|
||||
newUser.setLastSourceId(sourceId);
|
||||
userMapper.updateByPrimaryKeySelective(newUser);
|
||||
}
|
||||
|
||||
public User getUserInfo(String userId) {
|
||||
return userMapper.selectByPrimaryKey(userId);
|
||||
}
|
||||
|
||||
public List<User> getMemberList(QueryMemberRequest request) {
|
||||
return extUserRoleMapper.getMemberList(request);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addMember(AddMemberRequest request) {
|
||||
if (!CollectionUtils.isEmpty(request.getUserIds())) {
|
||||
for (String userId : request.getUserIds()) {
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setRoleId(RoleConstants.TEST_MANAGER);
|
||||
userRole.setSourceId(request.getWorkspaceId());
|
||||
userRole.setUserId(userId);
|
||||
userRole.setId(UUID.randomUUID().toString());
|
||||
userRole.setUpdateTime(System.currentTimeMillis());
|
||||
userRole.setCreateTime(System.currentTimeMillis());
|
||||
userRoleMapper.insertSelective(userRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteMember(String workspaceId, String userId) {
|
||||
UserRoleExample example = new UserRoleExample();
|
||||
example.createCriteria().andRoleIdEqualTo(RoleConstants.TEST_MANAGER)
|
||||
.andUserIdEqualTo(userId).andSourceIdEqualTo(workspaceId);
|
||||
userRoleMapper.deleteByExample(example);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,8 @@
|
|||
this.$post("signin", this.form, (response) => {
|
||||
// 登录信息保存 cookie
|
||||
Cookies.set(TokenKey, response.data);
|
||||
// 保存上次角色
|
||||
localStorage.setItem("lastSourceId", JSON.parse(Cookies.get(TokenKey)).lastSourceId);
|
||||
window.location.href = "/"
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<el-col v-if="auth">
|
||||
<el-row id="header-top" type="flex" justify="space-between" align="middle">
|
||||
<a class="logo"/>
|
||||
<ms-switch-user/>
|
||||
<ms-user/>
|
||||
</el-row>
|
||||
<el-row id="header-bottom" type="flex" justify="space-between" align="middle">
|
||||
|
@ -29,6 +30,7 @@
|
|||
import MsSetting from "./components/HeaderSetting";
|
||||
import MsView from "./components/router/View";
|
||||
import MsUser from "./components/HeaderUser";
|
||||
import MsSwitchUser from "./components/HeaderSwitchUser";
|
||||
import MsWebSocket from "./components/websocket/WebSocket";
|
||||
|
||||
export default {
|
||||
|
@ -49,7 +51,7 @@
|
|||
window.location.href = "/login"
|
||||
});
|
||||
},
|
||||
components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView},
|
||||
components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView, MsSwitchUser},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<el-row>
|
||||
<el-button type="text" @click="open">切换角色-{{ currentUserRole }}</el-button>
|
||||
<el-dialog title="角色列表" :visible.sync="createVisible" width="30%">
|
||||
<el-tree :data="userRoleList"
|
||||
@node-click="handleNodeClick"
|
||||
:props="defaultProps"
|
||||
></el-tree>
|
||||
<div style="text-align: center; margin-top: 20px;">
|
||||
<el-button type="info" size="mini" class="ms-button" @click="closeDialog">取消</el-button>
|
||||
<el-button type="primary" size="mini" style="margin-left: 50px;" @click="changeSubmit">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from "js-cookie"
|
||||
import {TokenKey} from "../../common/constants"
|
||||
|
||||
export default {
|
||||
name: "MsSwitchUser",
|
||||
computed: {
|
||||
currentUserRole() {
|
||||
return this.userInfo.lastSourceId;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getUserRoleList();
|
||||
this.getUserInfo();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createVisible: false,
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'switchInfo'
|
||||
},
|
||||
switchInfo: '',
|
||||
userRoleList: [],
|
||||
selectNode:[],
|
||||
userInfo: {},
|
||||
userId: JSON.parse(Cookies.get(TokenKey)).id
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.createVisible = true;
|
||||
},
|
||||
getUserRoleList() {
|
||||
this.$get('user/rolelist/' + this.userId).then(response => {
|
||||
let roleList = response.data.data;
|
||||
let newRoleList = [];
|
||||
roleList.forEach(item => {
|
||||
// item.current = item.id === this.userInfo.lastSourceId;
|
||||
item.current = item.roleId;
|
||||
if (item.current) {
|
||||
if (item.name) {
|
||||
item.switchInfo = item.name + " [" + item.desc + "]";
|
||||
} else {
|
||||
item.switchInfo = "MeterSphere[系统管理员]";
|
||||
}
|
||||
}
|
||||
if (!item.parentId) {
|
||||
item.hasChild = false;
|
||||
item.children = [];
|
||||
newRoleList.push(item);
|
||||
} else {
|
||||
newRoleList.forEach(userRole => {
|
||||
if (userRole.id === item.parentId) {
|
||||
userRole.children.push(item);
|
||||
userRole.hasChild = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
this.userRoleList = newRoleList;
|
||||
})
|
||||
},
|
||||
closeDialog() {
|
||||
this.createVisible = false;
|
||||
},
|
||||
switchRole(selectNode) {
|
||||
if (!selectNode.switchable) {
|
||||
return;
|
||||
}
|
||||
this.$post("user/switch/source/" + selectNode.roleId).then(() => {
|
||||
this.getUserInfo();
|
||||
// localStorage.setItem("lastSourceId", "bbbbb");
|
||||
this.closeDialog();
|
||||
});
|
||||
localStorage.setItem("lastSourceId", selectNode.roleId);
|
||||
window.location.reload();
|
||||
},
|
||||
changeSubmit() {
|
||||
this.switchRole(this.selectNode);
|
||||
},
|
||||
handleNodeClick(data) {
|
||||
this.selectNode = data;
|
||||
window.console.log(data)
|
||||
},
|
||||
getUserInfo() {
|
||||
this.$get("/user/info/" + this.userId).then(response => {
|
||||
this.userInfo = response.data.data;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -7,7 +7,7 @@ import User from "../settings/User";
|
|||
import CreateTestPlan from "../testPlan/CreateTestPlan";
|
||||
import AllTestPlan from "../testPlan/AllTestPlan";
|
||||
import Organization from "../settings/Organization";
|
||||
import WorkspaceUser from "../settings/WorkSpcaeUser";
|
||||
import Member from "../settings/Member";
|
||||
import TestResourcePool from "../settings/TestResourcePool";
|
||||
import MsProject from "../project/MsProject";
|
||||
|
||||
|
@ -49,8 +49,8 @@ const router = new VueRouter({
|
|||
}
|
||||
},
|
||||
{
|
||||
path: 'workspace/user',
|
||||
component: WorkspaceUser
|
||||
path: 'member',
|
||||
component: Member
|
||||
},
|
||||
{
|
||||
path: 'testresourcepool',
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="create-box">
|
||||
<el-tooltip class="item" effect="dark" :content="tips" placement="left">
|
||||
<el-button @click="exec()" type="primary" size="mini" circle>
|
||||
<font-awesome-icon :icon="['fas', 'plus']"/>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<span class="box">
|
||||
<el-tooltip class="item" effect="dark" :content="tips" placement="right">
|
||||
<el-button @click="exec()" type="primary" size="mini" circle>
|
||||
<font-awesome-icon :icon="['fas', 'plus']"/>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -19,18 +19,8 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.create-box {
|
||||
width: 100%;
|
||||
background: #FCFCFC;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
box-shadow: 0 5px 20px 0 rgba(0, 0, 0, .1);
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.create-box .el-button--mini.is-circle {
|
||||
width: 28.5px;
|
||||
.box {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<el-row type="flex" justify="space-between" align="middle">
|
||||
<span class="title">成员
|
||||
<ms-create-box :tips="btnTips" :exec="create"/>
|
||||
</span>
|
||||
<span class="search">
|
||||
<el-input type="text" size="small" placeholder="根据名称搜索" prefix-icon="el-icon-search"
|
||||
maxlength="60" v-model="condition" @change="search" clearable/>
|
||||
</span>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="name" label="用户名"/>
|
||||
<el-table-column prop="email" label="邮箱"/>
|
||||
<el-table-column prop="phone" label="电话"/>
|
||||
<el-table-column>
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="del(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="22" :offset="1">
|
||||
<div class="table-page">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page.sync="currentPage"
|
||||
:page-sizes="[5, 10, 20, 50, 100]"
|
||||
:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog title="添加成员" :visible.sync="createVisible" width="30%">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-position="left" label-width="100px" size="small">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input type="textarea" v-model="form.description"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submit('form')" size="medium">创建</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCreateBox from "./CreateBox";
|
||||
// import {Message} from "element-ui";
|
||||
|
||||
export default {
|
||||
name: "Member",
|
||||
components: {MsCreateBox},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: {},
|
||||
btnTips: "添加成员",
|
||||
createVisible: false,
|
||||
queryPath: "/user/member/list",
|
||||
condition: "",
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
currentWorkspaceId: "0a2430b1-a818-4b9b-bc04-c1229c472896",
|
||||
currentPage: 1,
|
||||
pageSize: 5,
|
||||
total: 0,
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.initTableData();
|
||||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
let param = {
|
||||
name: this.condition,
|
||||
workspaceId: this.currentWorkspaceId
|
||||
};
|
||||
|
||||
this.$post(this.buildPagePath(this.queryPath), param).then(response => {
|
||||
if (response.data.success) {
|
||||
let data = response.data.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
} else {
|
||||
this.$message.error(response.message);
|
||||
}
|
||||
})
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
search() {
|
||||
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size;
|
||||
},
|
||||
handleCurrentChange(current) {
|
||||
this.currentPage = current;
|
||||
},
|
||||
del(row) {
|
||||
this.$confirm('移除该成员, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$get('/user/member/delete/' + this.currentWorkspaceId + '/' + row.id).then(() => {
|
||||
this.initTableData();
|
||||
});
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
});
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
});
|
||||
});
|
||||
},
|
||||
create() {
|
||||
this.createVisible = true;
|
||||
this.form = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.edit {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.el-table__row:hover .edit {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.table-page {
|
||||
padding-top: 20px;
|
||||
margin-right: -9px;
|
||||
float: right;
|
||||
}
|
||||
</style>
|
|
@ -5,9 +5,9 @@
|
|||
<font-awesome-icon class="icon account" :icon="['far', 'address-card']" size="lg"/>
|
||||
<span>账号</span>
|
||||
</template>
|
||||
<el-menu-item index="/setting/user" v-permission="['admin']">用户</el-menu-item>
|
||||
<el-menu-item index="/setting/testresourcepool" v-permission="['admin','org_admin']">测试资源池</el-menu-item>
|
||||
<el-menu-item index="/setting/organization" v-permission="['test_user']">组织</el-menu-item>
|
||||
<el-menu-item index="/setting/user" v-permission="['admin','test_user']">用户</el-menu-item>
|
||||
<el-menu-item index="/setting/testresourcepool" v-permission="['test_user']">测试资源池</el-menu-item>
|
||||
<el-menu-item index="/setting/organization" v-permission="['org_admin']">组织</el-menu-item>
|
||||
<el-menu-item index="/setting/workspace">工作空间</el-menu-item>
|
||||
<el-menu-item>API Keys</el-menu-item>
|
||||
</el-submenu>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<font-awesome-icon class="icon workspace" :icon="['far', 'clone']" size="lg"/>
|
||||
<span>工作空间</span>
|
||||
</template>
|
||||
<el-menu-item index="/setting/workspace/user">成员</el-menu-item>
|
||||
<el-menu-item index="/setting/member">成员</el-menu-item>
|
||||
<el-menu-item>证书</el-menu-item>
|
||||
<el-menu-item>测试计划</el-menu-item>
|
||||
<el-menu-item>警告</el-menu-item>
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<el-row type="flex" justify="space-between" align="middle">
|
||||
<span class="title">工作空间</span>
|
||||
<span class="search">
|
||||
<el-input type="text" size="small" placeholder="根据名称搜索" prefix-icon="el-icon-search"
|
||||
maxlength="60" v-model="condition" clearable/>
|
||||
</span>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-table :data="items" style="width: 100%">
|
||||
<el-table-column prop="name" label="名称"/>
|
||||
<el-table-column prop="description" label="描述"/>
|
||||
<el-table-column width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="edit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle
|
||||
class="edit"/>
|
||||
<el-popconfirm title="这个工作空间确定要删除吗?" @onConfirm="del(scope.row)">
|
||||
<el-button slot="reference" type="primary" icon="el-icon-delete" size="mini"
|
||||
circle
|
||||
class="edit"/>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<ms-create-box :tips="btnTips" :exec="create"/>
|
||||
<el-dialog title="创建工作空间" :visible.sync="createVisible" width="30%">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-position="left" label-width="100px" size="small">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input type="textarea" v-model="form.description"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submit('form')" size="medium">创建</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCreateBox from "./CreateBox";
|
||||
import {Message} from "element-ui";
|
||||
|
||||
export default {
|
||||
name: "MsWorkspace",
|
||||
components: {MsCreateBox},
|
||||
mounted() {
|
||||
this.list();
|
||||
},
|
||||
methods: {
|
||||
create() {
|
||||
this.createVisible = true;
|
||||
this.form = {};
|
||||
},
|
||||
submit(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
this.$post("/workspace/save", this.form, () => {
|
||||
this.createVisible = false;
|
||||
this.loading = false;
|
||||
this.list();
|
||||
Message.success('保存成功');
|
||||
})
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
edit(row) {
|
||||
this.createVisible = true;
|
||||
window.console.log(row);
|
||||
this.loading = true;
|
||||
this.form = row;
|
||||
|
||||
// let self = this;
|
||||
// let getUser1 = this.$get("/test/user");
|
||||
// let getUser2 = this.$get("/test/sleep");
|
||||
// this.$all([getUser1, getUser2], function (r1, r2) {
|
||||
// window.console.log(r1.data.data, r2.data.data);
|
||||
// self.loading = false;
|
||||
// });
|
||||
},
|
||||
del(row) {
|
||||
this.$get('/workspace/delete/' + row.id, () => {
|
||||
Message.success('删除成功');
|
||||
this.list();
|
||||
});
|
||||
window.console.log(row);
|
||||
},
|
||||
list() {
|
||||
this.$post('/workspace/list', {}, response => {
|
||||
this.items = response.data;
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
createVisible: false,
|
||||
btnTips: "添加工作空间",
|
||||
condition: "",
|
||||
items: [],
|
||||
form: {
|
||||
// name: "",
|
||||
// description: ""
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{required: true, message: '请输入工作空间名称', trigger: 'blur'},
|
||||
{min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur'}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.edit {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.el-table__row:hover .edit {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
|
@ -1,20 +1,16 @@
|
|||
import router from './components/router/router'
|
||||
import Cookies from 'js-cookie' // get token from cookie
|
||||
import {TokenKey} from '../common/constants';
|
||||
import store from "./store";
|
||||
|
||||
const whiteList = ['/login']; // no redirect whitelist
|
||||
|
||||
export const permission = {
|
||||
inserted(el, binding) {
|
||||
const { value } = binding
|
||||
// user role list
|
||||
const roles = store.state.roles
|
||||
const { value } = binding;
|
||||
const roles = localStorage.getItem("lastSourceId");
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const permissionRoles = value
|
||||
const hasPermission = roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
})
|
||||
const permissionRoles = value;
|
||||
const hasPermission = permissionRoles.includes(roles);
|
||||
if (!hasPermission) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
|
@ -29,13 +25,12 @@ router.beforeEach(async (to, from, next) => {
|
|||
// determine whether the user has logged in
|
||||
const user = JSON.parse(Cookies.get(TokenKey));
|
||||
|
||||
if (user && user.roles.length > 0) {
|
||||
if (user) {
|
||||
if (to.path === '/login') {
|
||||
next({path: '/'});
|
||||
} else {
|
||||
// const roles = user.roles.filter(r => r.id);
|
||||
// TODO 设置路由的权限
|
||||
store.commit("setRoles", user.roles.map(r => r.id))
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -3,17 +3,7 @@ import Vuex from 'vuex'
|
|||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
roles: []
|
||||
},
|
||||
mutations: {
|
||||
setRoles(state, data) {
|
||||
state.roles = data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default store
|
||||
export default new Vuex.Store({})
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue