Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
haifeng414 2020-02-18 13:41:31 +08:00
commit 677bdb959a
20 changed files with 737 additions and 192 deletions

View File

@ -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);
}

View File

@ -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>

View File

@ -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";
}

View File

@ -1,10 +1,19 @@
package io.metersphere.controller; 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.Role;
import io.metersphere.base.domain.User; 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.UserDTO;
import io.metersphere.dto.UserOperateDTO; import io.metersphere.dto.UserRoleDTO;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import io.metersphere.user.SessionUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -23,16 +32,67 @@ public class UserController {
} }
@GetMapping("/list") @GetMapping("/list")
public List<User> getUserList() { return userService.getUserList(); } public List<User> getUserList() {
return userService.getUserList();
}
@GetMapping("/delete/{userId}") @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") @PostMapping("/update")
public void updateUser(@RequestBody User user) { userService.updateUser(user); } public void updateUser(@RequestBody User user) {
userService.updateUser(user);
}
@GetMapping("/role/list/{userId}") @GetMapping("/role/list/{userId}")
public List<Role> getUserRolesList(@PathVariable(value = "userId") String userId) { public List<Role> getUserRolesList(@PathVariable(value = "userId") String userId) {
return userService.getUserRolesList(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);
}
} }

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -20,6 +20,16 @@ public class UserDTO {
private Long updateTime; 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<>(); private List<Role> roles = new ArrayList<>();
public List<Role> getRoles() { public List<Role> getRoles() {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -1,12 +1,18 @@
package io.metersphere.service; package io.metersphere.service;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.OrganizationMapper;
import io.metersphere.base.mapper.RoleMapper; import io.metersphere.base.mapper.RoleMapper;
import io.metersphere.base.mapper.UserMapper; import io.metersphere.base.mapper.UserMapper;
import io.metersphere.base.mapper.UserRoleMapper; 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.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.UserDTO;
import io.metersphere.dto.UserOperateDTO; import io.metersphere.dto.UserRoleDTO;
import io.metersphere.dto.UserRoleHelpDTO;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -14,7 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -27,6 +33,10 @@ public class UserService {
private RoleMapper roleMapper; private RoleMapper roleMapper;
@Resource @Resource
private UserRoleMapper userRoleMapper; private UserRoleMapper userRoleMapper;
@Resource
private ExtUserRoleMapper extUserRoleMapper;
@Resource
private OrganizationMapper organizationMapper;
public UserDTO insert(User user) { public UserDTO insert(User user) {
checkUserParam(user); checkUserParam(user);
@ -113,4 +123,133 @@ public class UserService {
roleExample.createCriteria().andIdIn(roleIds); roleExample.createCriteria().andIdIn(roleIds);
return roleMapper.selectByExample(roleExample); 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);
}
} }

View File

@ -109,6 +109,8 @@
this.$post("signin", this.form, (response) => { this.$post("signin", this.form, (response) => {
// cookie // cookie
Cookies.set(TokenKey, response.data); Cookies.set(TokenKey, response.data);
//
localStorage.setItem("lastSourceId", JSON.parse(Cookies.get(TokenKey)).lastSourceId);
window.location.href = "/" window.location.href = "/"
}); });
} else { } else {

View File

@ -2,6 +2,7 @@
<el-col v-if="auth"> <el-col v-if="auth">
<el-row id="header-top" type="flex" justify="space-between" align="middle"> <el-row id="header-top" type="flex" justify="space-between" align="middle">
<a class="logo"/> <a class="logo"/>
<ms-switch-user/>
<ms-user/> <ms-user/>
</el-row> </el-row>
<el-row id="header-bottom" type="flex" justify="space-between" align="middle"> <el-row id="header-bottom" type="flex" justify="space-between" align="middle">
@ -29,6 +30,7 @@
import MsSetting from "./components/HeaderSetting"; import MsSetting from "./components/HeaderSetting";
import MsView from "./components/router/View"; import MsView from "./components/router/View";
import MsUser from "./components/HeaderUser"; import MsUser from "./components/HeaderUser";
import MsSwitchUser from "./components/HeaderSwitchUser";
import MsWebSocket from "./components/websocket/WebSocket"; import MsWebSocket from "./components/websocket/WebSocket";
export default { export default {
@ -49,7 +51,7 @@
window.location.href = "/login" window.location.href = "/login"
}); });
}, },
components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView}, components: {MsWebSocket, MsUser, MsMenus, MsSetting, MsView, MsSwitchUser},
methods: { methods: {
} }
} }

View File

@ -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>

View File

@ -7,7 +7,7 @@ import User from "../settings/User";
import CreateTestPlan from "../testPlan/CreateTestPlan"; import CreateTestPlan from "../testPlan/CreateTestPlan";
import AllTestPlan from "../testPlan/AllTestPlan"; import AllTestPlan from "../testPlan/AllTestPlan";
import Organization from "../settings/Organization"; import Organization from "../settings/Organization";
import WorkspaceUser from "../settings/WorkSpcaeUser"; import Member from "../settings/Member";
import TestResourcePool from "../settings/TestResourcePool"; import TestResourcePool from "../settings/TestResourcePool";
import MsProject from "../project/MsProject"; import MsProject from "../project/MsProject";
@ -49,8 +49,8 @@ const router = new VueRouter({
} }
}, },
{ {
path: 'workspace/user', path: 'member',
component: WorkspaceUser component: Member
}, },
{ {
path: 'testresourcepool', path: 'testresourcepool',

View File

@ -1,11 +1,11 @@
<template> <template>
<div class="create-box"> <span class="box">
<el-tooltip class="item" effect="dark" :content="tips" placement="left"> <el-tooltip class="item" effect="dark" :content="tips" placement="right">
<el-button @click="exec()" type="primary" size="mini" circle> <el-button @click="exec()" type="primary" size="mini" circle>
<font-awesome-icon :icon="['fas', 'plus']"/> <font-awesome-icon :icon="['fas', 'plus']"/>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
</div> </span>
</template> </template>
<script> <script>
@ -19,18 +19,8 @@
</script> </script>
<style scoped> <style scoped>
.create-box { .box {
width: 100%; margin-left: 5px;
background: #FCFCFC; margin-right: 5px;
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;
} }
</style> </style>

View File

@ -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>

View File

@ -5,9 +5,9 @@
<font-awesome-icon class="icon account" :icon="['far', 'address-card']" size="lg"/> <font-awesome-icon class="icon account" :icon="['far', 'address-card']" size="lg"/>
<span>账号</span> <span>账号</span>
</template> </template>
<el-menu-item index="/setting/user" v-permission="['admin']">用户</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="['admin','org_admin']">测试资源池</el-menu-item> <el-menu-item index="/setting/testresourcepool" v-permission="['test_user']">测试资源池</el-menu-item>
<el-menu-item index="/setting/organization" 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 index="/setting/workspace">工作空间</el-menu-item>
<el-menu-item>API Keys</el-menu-item> <el-menu-item>API Keys</el-menu-item>
</el-submenu> </el-submenu>
@ -16,7 +16,7 @@
<font-awesome-icon class="icon workspace" :icon="['far', 'clone']" size="lg"/> <font-awesome-icon class="icon workspace" :icon="['far', 'clone']" size="lg"/>
<span>工作空间</span> <span>工作空间</span>
</template> </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> <el-menu-item>测试计划</el-menu-item>
<el-menu-item>警告</el-menu-item> <el-menu-item>警告</el-menu-item>

View File

@ -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>

View File

@ -1,20 +1,16 @@
import router from './components/router/router' import router from './components/router/router'
import Cookies from 'js-cookie' // get token from cookie import Cookies from 'js-cookie' // get token from cookie
import {TokenKey} from '../common/constants'; import {TokenKey} from '../common/constants';
import store from "./store";
const whiteList = ['/login']; // no redirect whitelist const whiteList = ['/login']; // no redirect whitelist
export const permission = { export const permission = {
inserted(el, binding) { inserted(el, binding) {
const { value } = binding const { value } = binding;
// user role list const roles = localStorage.getItem("lastSourceId");
const roles = store.state.roles
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const permissionRoles = value const permissionRoles = value;
const hasPermission = roles.some(role => { const hasPermission = permissionRoles.includes(roles);
return permissionRoles.includes(role)
})
if (!hasPermission) { if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el) el.parentNode && el.parentNode.removeChild(el)
} }
@ -29,13 +25,12 @@ router.beforeEach(async (to, from, next) => {
// determine whether the user has logged in // determine whether the user has logged in
const user = JSON.parse(Cookies.get(TokenKey)); const user = JSON.parse(Cookies.get(TokenKey));
if (user && user.roles.length > 0) { if (user) {
if (to.path === '/login') { if (to.path === '/login') {
next({path: '/'}); next({path: '/'});
} else { } else {
// const roles = user.roles.filter(r => r.id); // const roles = user.roles.filter(r => r.id);
// TODO 设置路由的权限 // TODO 设置路由的权限
store.commit("setRoles", user.roles.map(r => r.id))
next() next()
} }
} else { } else {

View File

@ -3,17 +3,7 @@ import Vuex from 'vuex'
Vue.use(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({})