feat_项目设置新增用户组与权限 --story=1003751 --user=王孝刚 项目设置新增用户组与权限配置 https://www.tapd.cn/55049933/s/1063285
This commit is contained in:
parent
8002dc2c4f
commit
862e790509
|
@ -12,7 +12,7 @@ import java.util.List;
|
||||||
|
|
||||||
public interface ExtUserGroupMapper {
|
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);
|
List<Group> getWorkspaceMemberGroups(@Param("workspaceId") String workspaceId, @Param("userId") String userId);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
select ug.user_id, ug.group_id, ug.source_id, g.`name`, g.type
|
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
|
from user_group ug join `group` g on ug.group_id = g.id
|
||||||
where ug.user_id = #{userId}
|
where ug.user_id = #{userId}
|
||||||
|
<if test="projectId != null">
|
||||||
|
and ug.source_id = #{projectId}
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getWorkspaceMemberGroups" resultType="io.metersphere.base.domain.Group">
|
<select id="getWorkspaceMemberGroups" resultType="io.metersphere.base.domain.Group">
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class EditGroupRequest extends Group {
|
||||||
*/
|
*/
|
||||||
private Boolean global;
|
private Boolean global;
|
||||||
|
|
||||||
|
private String projectId;
|
||||||
private List<GroupPermission> permissions;
|
private List<GroupPermission> permissions;
|
||||||
private String userGroupId;
|
private String userGroupId;
|
||||||
private List<OrderRequest> orders;
|
private List<OrderRequest> orders;
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class GroupService {
|
||||||
|
|
||||||
public Pager<List<GroupDTO>> getGroupList(EditGroupRequest request) {
|
public Pager<List<GroupDTO>> getGroupList(EditGroupRequest request) {
|
||||||
SessionUser user = SessionUtils.getUser();
|
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());
|
List<String> groupTypeList = userGroup.stream().map(UserGroupDTO::getType).collect(Collectors.toList());
|
||||||
return getGroups(groupTypeList, request);
|
return getGroups(groupTypeList, request);
|
||||||
}
|
}
|
||||||
|
@ -521,4 +521,5 @@ public class GroupService {
|
||||||
list = workspaceMapper.selectByExample(workspaceExample);
|
list = workspaceMapper.selectByExample(workspaceExample);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
<el-menu-item :index="'/project/member'" v-permission="['PROJECT_USER:READ']">
|
<el-menu-item :index="'/project/member'" v-permission="['PROJECT_USER:READ']">
|
||||||
{{ $t('project.member') }}
|
{{ $t('project.member') }}
|
||||||
</el-menu-item>
|
</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']"
|
<el-menu-item :index="'/project/env'" v-permission="['PROJECT_ENVIRONMENT:READ']"
|
||||||
popper-class="submenu">
|
popper-class="submenu">
|
||||||
{{ $t('project.env') }}
|
{{ $t('project.env') }}
|
||||||
|
|
|
@ -47,6 +47,19 @@
|
||||||
<span class="desc">{{ $t('project.member_desc') }}</span>
|
<span class="desc">{{ $t('project.member_desc') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</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 class="div-item">
|
||||||
<div style="float: left">
|
<div style="float: left">
|
||||||
<i class="el-icon-s-platform icon-color"
|
<i class="el-icon-s-platform icon-color"
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -5,6 +5,7 @@ const ProjectEnv = () => import('@/business/components/project/menu/EnvironmentL
|
||||||
const ProjectLog = () => import('@/business/components/project/menu/Log')
|
const ProjectLog = () => import('@/business/components/project/menu/Log')
|
||||||
const ProjectCodeSegment = () => import('@/business/components/project/menu/function/CustomFunction')
|
const ProjectCodeSegment = () => import('@/business/components/project/menu/function/CustomFunction')
|
||||||
const ProjectFileManage = () => import('@/business/components/project/menu/file/FileManage')
|
const ProjectFileManage = () => import('@/business/components/project/menu/file/FileManage')
|
||||||
|
const ProjectUserGroup = () => import('@/business/components/project/menu/UserGroup')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: "/project",
|
path: "/project",
|
||||||
|
@ -23,6 +24,10 @@ export default {
|
||||||
path: 'member',
|
path: 'member',
|
||||||
component: ProjectMember
|
component: ProjectMember
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'usergroup',
|
||||||
|
component: ProjectUserGroup
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'env',
|
path: 'env',
|
||||||
component: ProjectEnv
|
component: ProjectEnv
|
||||||
|
|
Loading…
Reference in New Issue