feat_项目设置新增用户组与权限 --story=1003751 --user=王孝刚 项目设置新增用户组与权限配置 https://www.tapd.cn/55049933/s/1063285

This commit is contained in:
wxg0103 2021-11-03 10:20:32 +08:00 committed by 刘瑞斌
parent 8002dc2c4f
commit 862e790509
9 changed files with 395 additions and 2 deletions

View File

@ -12,7 +12,7 @@ import java.util.List;
public interface ExtUserGroupMapper {
List<UserGroupDTO> getUserGroup(@Param("userId") String userId);
List<UserGroupDTO> getUserGroup(@Param("userId") String userId , @Param("projectId") String projectId);
List<Group> getWorkspaceMemberGroups(@Param("workspaceId") String workspaceId, @Param("userId") String userId);

View File

@ -7,6 +7,9 @@
select ug.user_id, ug.group_id, ug.source_id, g.`name`, g.type
from user_group ug join `group` g on ug.group_id = g.id
where ug.user_id = #{userId}
<if test="projectId != null">
and ug.source_id = #{projectId}
</if>
</select>
<select id="getWorkspaceMemberGroups" resultType="io.metersphere.base.domain.Group">

View File

@ -23,6 +23,7 @@ public class EditGroupRequest extends Group {
*/
private Boolean global;
private String projectId;
private List<GroupPermission> permissions;
private String userGroupId;
private List<OrderRequest> orders;

View File

@ -80,7 +80,7 @@ public class GroupService {
public Pager<List<GroupDTO>> getGroupList(EditGroupRequest request) {
SessionUser user = SessionUtils.getUser();
List<UserGroupDTO> userGroup = extUserGroupMapper.getUserGroup(Objects.requireNonNull(user).getId());
List<UserGroupDTO> userGroup = extUserGroupMapper.getUserGroup(Objects.requireNonNull(user).getId() , request.getProjectId());
List<String> groupTypeList = userGroup.stream().map(UserGroupDTO::getType).collect(Collectors.toList());
return getGroups(groupTypeList, request);
}
@ -521,4 +521,5 @@ public class GroupService {
list = workspaceMapper.selectByExample(workspaceExample);
return list;
}
}

View File

@ -11,6 +11,9 @@
<el-menu-item :index="'/project/member'" v-permission="['PROJECT_USER:READ']">
{{ $t('project.member') }}
</el-menu-item>
<el-menu-item :index="'/project/usergroup'" v-permission="['SYSTEM_USER:READ+CREATE']">
{{ $t('project.group_permission') }}
</el-menu-item>
<el-menu-item :index="'/project/env'" v-permission="['PROJECT_ENVIRONMENT:READ']"
popper-class="submenu">
{{ $t('project.env') }}

View File

@ -47,6 +47,19 @@
<span class="desc">{{ $t('project.member_desc') }}</span>
</div>
</div>
<div class="div-item">
<div style="float: left">
<i class="el-icon-user icon-color"
@click="click('/project/usergroup', ['PROJECT_USER:READ'])">
</i>
</div>
<div style="float: left">
<span class="title" @click="click('/project/usergroup', ['PROJECT_USER:READ'])">
{{ $t('project.group_permission') }}
</span><br/>
<span class="desc">{{ $t('project.group_desc') }}</span>
</div>
</div>
<div class="div-item">
<div style="float: left">
<i class="el-icon-s-platform icon-color"

View File

@ -0,0 +1,193 @@
<template>
<el-dialog :close-on-click-modal="false" :visible.sync="dialogVisible" width="50%"
:title="title"
:destroy-on-close="true">
<el-form ref="form" :model="form" label-width="auto" size="small" :rules="rules">
<el-row>
<el-col :span="11">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="11" :offset="2">
<el-form-item :label="$t('group.type')" prop="type">
<el-select v-model="form.type" :placeholder="$t('group.select_type')" style="width: 100%"
@change="changeGroup" disabled>
<el-option :label="$t('group.system')" value="SYSTEM"></el-option>
<el-option :label="$t('group.workspace')" value="WORKSPACE"></el-option>
<el-option :label="$t('group.project')" value="PROJECT"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('group.description')" prop="description">
<el-input type="textarea" v-model="form.description"></el-input>
</el-form-item>
<el-form-item :label="$t('group.global_group')">
<el-switch v-model="form.global" :disabled="dialogType === 'edit' || form.type === 'SYSTEM'"
@change="change(form.global)"></el-switch>
</el-form-item>
<el-form-item :label="$t('project.owning_workspace')" v-if="show" prop="scopeId">
<el-select v-model="form.scopeId" :placeholder="$t('project.please_choose_workspace')" style="width: 100%;" disabled
clearable>
<el-option v-for="item in workspaces" :key="item.id" :label="item.name" :value="item.id"/>
</el-select>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="cancel" size="medium">{{ $t('commons.cancel') }}</el-button>
<el-button type="primary" @click="onSubmit" size="medium">{{ $t('commons.confirm') }}</el-button>
</template>
</el-dialog>
</template>
<script>
import {GROUP_SYSTEM} from "@/common/js/constants";
import {getCurrentUserId, getCurrentWorkspaceId} from "@/common/js/utils";
export default {
name: "EditUserGroup",
data() {
return {
dialogVisible: false,
form: {
global: false,
},
rules: {
name: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'},
],
type: [
{required: true, message: this.$t('group.select_type'), trigger: 'blur'},
],
description: [
{min: 2, max: 90, message: this.$t('commons.input_limit', [2, 90]), trigger: 'blur'},
],
scopeId: [
{required: true, message: this.$t('group.select_belong_organization'), trigger: 'blur'},
]
},
dialogType: '',
isSystem: false,
show: true,
workspaces: [],
title: this.$t('group.create'),
flag: false
}
},
props: {
dialogTitle: {
type: String,
default() {
return this.$t('group.create')
}
}
},
methods: {
onSubmit() {
if (this.dialogType === 'create') {
this.create();
return;
}
if (this.dialogType === 'edit') {
this.edit();
}
if (this.dialogType === 'copy') {
return;
}
},
create() {
this.$refs['form'].validate(valid => {
if (valid) {
this.$post("/user/group/add", this.form, () => {
this.$success(this.$t('commons.save_success'));
this.$emit("refresh")
this.dialogVisible = false;
})
} else {
return false;
}
})
},
edit() {
this.$refs['form'].validate(valid => {
if (valid) {
this.$post("/user/group/edit", this.form, () => {
this.$success(this.$t('commons.modify_success'));
this.$emit("refresh")
this.dialogVisible = false;
})
} else {
return false;
}
})
},
open(row, type, title) {
this.title = title;
this.isSystem = false;
this.show = true;
this.dialogVisible = true;
this.dialogType = type;
this.form = Object.assign({type: 'PROJECT' ,global: false , scopeId: getCurrentWorkspaceId()}, row);
if (type !== 'create') {
if (this.form.type === GROUP_SYSTEM) {
this.form.global = true;
this.show = false;
} else {
this.form.global = true;
this.show = !this.form.global;
}
}
this.getWorkspace();
},
cancel() {
this.dialogVisible = false;
},
change(global) {
this.$get("/user/group/list/ws/" + getCurrentWorkspaceId() + "/" + getCurrentUserId(), res => {
let data = res.data;
if (data) {
data.forEach(row => {
if (row.id === 'ws_admin') {
this.flag = true;
}
})
}
if (this.flag === true) {
this.show = this.isSystem ? false : !global;
} else {
this.form.global = false;
this.$warning(this.$t('group.group_global_warning'))
}
})
},
changeGroup(val) {
if (val === GROUP_SYSTEM) {
this.isSystem = true;
this.$set(this.form, "global", true);
this.change(true);
} else {
this.isSystem = false;
}
},
getWorkspace() {
this.$get("/user/group/ws/" + getCurrentUserId(), res => {
let data = res.data;
if (data) {
this.workspaces = data;
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,174 @@
<template>
<div v-loading="result.loading">
<el-card>
<template v-slot:header>
<ms-table-header :create-permission="['SYSTEM_GROUP:READ+CREATE','ORGANIZATION_GROUP:READ+CREATE']"
:condition.sync="condition" @search="initData" @create="create"
:create-tip="$t('group.create')"/>
</template>
<el-table :data="groups" border class="adjust-table" style="width: 100%"
:height="screenHeight" @sort-change="sort">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
<el-table-column prop="type" :label="$t('group.type')">
<template v-slot="scope">
<span>{{ userGroupType[scope.row.type] ? userGroupType[scope.row.type] : scope.row.type }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('commons.member')" width="100">
<template v-slot:default="scope">
<el-link type="primary" class="member-size" @click="memberClick(scope.row)">
{{ scope.row.memberSize || 0 }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="scopeName" :label="$t('group.scope')"/>
<el-table-column prop="createTime" :label="$t('commons.create_time')" sortable show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime" :label="$t('commons.update_time')" sortable show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column prop="creator" :label="$t('group.operator')"/>
<el-table-column prop="description" :label="$t('group.description')"/>
<el-table-column :label="$t('commons.operating')" min-width="120">
<template v-slot:default="scope">
<div>
<ms-table-operator :edit-permission="['SYSTEM_GROUP:READ+EDIT', 'ORGANIZATION_GROUP:READ+EDIT']"
:delete-permission="['SYSTEM_GROUP:READ+DELETE', 'ORGANIZATION_GROUP:READ+DELETE']"
@editClick="edit(scope.row)" @deleteClick="del(scope.row)">
<template v-slot:middle>
<!-- <ms-table-operator-button tip="复制" icon="el-icon-document-copy" @exec="copy(scope.row)"/>-->
<ms-table-operator-button
v-permission="['SYSTEM_GROUP:READ+SETTING_PERMISSION', 'ORGANIZATION_GROUP:READ+SETTING_PERMISSION']"
:tip="$t('group.set_permission')" icon="el-icon-s-tools" @exec="setPermission(scope.row)"/>
</template>
</ms-table-operator>
</div>
</template>
</el-table-column>
</el-table>
<ms-table-pagination :change="initData" :current-page.sync="currentPage" :page-size.sync="pageSize"
:total="total"/>
</el-card>
<group-member ref="groupMember" @refresh="initData"/>
<edit-user-group ref="editUserGroup" @refresh="initData"/>
<edit-permission ref="editPermission"/>
<ms-delete-confirm :title="$t('group.delete')" @delete="_handleDel" ref="deleteConfirm"/>
</div>
</template>
<script>
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import MsTableOperator from "@/business/components/common/components/MsTableOperator";
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import {USER_GROUP_SCOPE} from "@/common/js/table-constants";
import EditUserGroup from "@/business/components/project/menu/EditUserGroup";
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
import EditPermission from "@/business/components/settings/system/group/EditPermission";
import MsDeleteConfirm from "@/business/components/common/components/MsDeleteConfirm";
import {_sort} from "@/common/js/tableUtils";
import GroupMember from "@/business/components/settings/system/group/GroupMember";
import {getCurrentProjectID} from "@/common/js/utils";
export default {
name: "ProjectUserGroup",
components: {
GroupMember,
EditUserGroup,
MsTableHeader,
MsTableOperator,
MsTablePagination,
MsTableOperatorButton,
EditPermission,
MsDeleteConfirm
},
data() {
return {
result: {},
condition: {},
currentPage: 1,
pageSize: 10,
total: 0,
screenHeight: 'calc(100vh - 200px)',
groups: [],
currentGroup: {}
};
},
activated() {
this.initData();
},
computed: {
userGroupType() {
return USER_GROUP_SCOPE;
},
projectId() {
return getCurrentProjectID();
},
},
methods: {
initData() {
this.condition.projectId = this.projectId;
if(this.projectId) {
this.result = this.$post("/user/group/get/" + this.currentPage + "/" + this.pageSize, this.condition, res => {
let data = res.data;
if (data) {
let {itemCount, listObject} = data;
this.total = itemCount;
this.groups = listObject;
}
});
}
},
create() {
this.$refs.editUserGroup.open({}, 'create', this.$t('group.create'));
},
edit(row) {
if (row.id === "admin") {
this.$warning(this.$t('group.admin_not_allow_edit'));
return;
}
this.$refs.editUserGroup.open(row, 'edit', this.$t('group.edit'));
},
_handleDel(row) {
this.result = this.$get("/user/group/delete/" + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.initData();
});
},
del(row) {
if (row.system) {
this.$warning(this.$t('group.admin_not_allow_delete'));
return;
}
this.$refs.deleteConfirm.open(row);
},
copy(row) {
// console.log(row);
},
setPermission(row) {
this.$refs.editPermission.open(row);
},
sort(column) {
//
if (this.condition.orders) {
this.condition.orders = [];
}
_sort(column, this.condition);
this.initData();
},
memberClick(row) {
this.$refs.groupMember.open(row);
}
}
};
</script>
<style scoped>
</style>

View File

@ -5,6 +5,7 @@ const ProjectEnv = () => import('@/business/components/project/menu/EnvironmentL
const ProjectLog = () => import('@/business/components/project/menu/Log')
const ProjectCodeSegment = () => import('@/business/components/project/menu/function/CustomFunction')
const ProjectFileManage = () => import('@/business/components/project/menu/file/FileManage')
const ProjectUserGroup = () => import('@/business/components/project/menu/UserGroup')
export default {
path: "/project",
@ -23,6 +24,10 @@ export default {
path: 'member',
component: ProjectMember
},
{
path: 'usergroup',
component: ProjectUserGroup
},
{
path: 'env',
component: ProjectEnv