refactor(权限管理): 权限设置
This commit is contained in:
parent
a10099da54
commit
db96d93cf4
|
@ -66,6 +66,9 @@
|
||||||
<if test="proRequest.workspaceId != null">
|
<if test="proRequest.workspaceId != null">
|
||||||
and w.id = #{proRequest.workspaceId}
|
and w.id = #{proRequest.workspaceId}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="proRequest.projectId != null">
|
||||||
|
and p.id = #{proRequest.projectId}
|
||||||
|
</if>
|
||||||
</where>
|
</where>
|
||||||
<if test="proRequest.orders != null and proRequest.orders.size() > 0">
|
<if test="proRequest.orders != null and proRequest.orders.size() > 0">
|
||||||
order by
|
order by
|
||||||
|
|
|
@ -68,8 +68,12 @@ public class PermissionConstants {
|
||||||
public static final String WORKSPACE_TEMPLATE_READ_ISSUE_TEMPLATE = "WORKSPACE_TEMPLATE:READ+ISSUE_TEMPLATE";
|
public static final String WORKSPACE_TEMPLATE_READ_ISSUE_TEMPLATE = "WORKSPACE_TEMPLATE:READ+ISSUE_TEMPLATE";
|
||||||
public static final String WORKSPACE_TEMPLATE_READ_CUSTOM = "WORKSPACE_TEMPLATE:READ+CUSTOM";
|
public static final String WORKSPACE_TEMPLATE_READ_CUSTOM = "WORKSPACE_TEMPLATE:READ+CUSTOM";
|
||||||
public static final String WORKSPACE_TEMPLATE_READ_REPORT_TEMPLATE = "WORKSPACE_TEMPLATE:READ+REPORT_TEMPLATE";
|
public static final String WORKSPACE_TEMPLATE_READ_REPORT_TEMPLATE = "WORKSPACE_TEMPLATE:READ+REPORT_TEMPLATE";
|
||||||
|
public static final String WORKSPACE_PROJECT_MANAGER_READ = "WORKSPACE_PROJECT_MANAGER:READ";
|
||||||
|
public static final String WORKSPACE_PROJECT_MANAGER_READ_CREATE = "WORKSPACE_PROJECT_MANAGER:READ+CREATE";
|
||||||
|
public static final String WORKSPACE_PROJECT_MANAGER_READ_EDIT = "WORKSPACE_PROJECT_MANAGER:READ+EDIT";
|
||||||
|
public static final String WORKSPACE_PROJECT_MANAGER_READ_DELETE = "WORKSPACE_PROJECT_MANAGER:READ+DELETE";
|
||||||
|
|
||||||
|
|
||||||
public static final String PROJECT_USER_READ = "PROJECT_USER:READ";
|
public static final String PROJECT_USER_READ = "PROJECT_USER:READ";
|
||||||
public static final String PROJECT_USER_READ_CREATE = "PROJECT_USER:READ+CREATE";
|
public static final String PROJECT_USER_READ_CREATE = "PROJECT_USER:READ+CREATE";
|
||||||
public static final String PROJECT_USER_READ_EDIT = "PROJECT_USER:READ+EDIT";
|
public static final String PROJECT_USER_READ_EDIT = "PROJECT_USER:READ+EDIT";
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.Map;
|
||||||
@Setter
|
@Setter
|
||||||
public class ProjectRequest {
|
public class ProjectRequest {
|
||||||
private String workspaceId;
|
private String workspaceId;
|
||||||
|
private String projectId;
|
||||||
private String name;
|
private String name;
|
||||||
private List<OrderRequest> orders;
|
private List<OrderRequest> orders;
|
||||||
private Map<String, List<String>> filters;
|
private Map<String, List<String>> filters;
|
||||||
|
|
|
@ -470,9 +470,7 @@ public class UserService {
|
||||||
List<Workspace> workspaces = workspaceService.getWorkspaceListByOrgIdAndUserId(sourceId);
|
List<Workspace> workspaces = workspaceService.getWorkspaceListByOrgIdAndUserId(sourceId);
|
||||||
if (workspaces.size() > 0) {
|
if (workspaces.size() > 0) {
|
||||||
user.setLastWorkspaceId(workspaces.get(0).getId());
|
user.setLastWorkspaceId(workspaces.get(0).getId());
|
||||||
ProjectExample projectExample = new ProjectExample();
|
List<Project> projects = getProjectListByWsAndUserId(workspaces.get(0).getId());
|
||||||
projectExample.createCriteria().andWorkspaceIdEqualTo(workspaces.get(0).getId());
|
|
||||||
List<Project> projects = projectMapper.selectByExample(projectExample);
|
|
||||||
if (projects.size() > 0) {
|
if (projects.size() > 0) {
|
||||||
user.setLastProjectId(projects.get(0).getId());
|
user.setLastProjectId(projects.get(0).getId());
|
||||||
} else {
|
} else {
|
||||||
|
@ -484,12 +482,10 @@ public class UserService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.equals("workspace", sign)) {
|
if (StringUtils.equals("workspace", sign)) {
|
||||||
ProjectExample projectExample = new ProjectExample();
|
|
||||||
projectExample.createCriteria().andWorkspaceIdEqualTo(sourceId);
|
|
||||||
List<Project> projects = projectMapper.selectByExample(projectExample);
|
|
||||||
Workspace workspace = workspaceMapper.selectByPrimaryKey(sourceId);
|
Workspace workspace = workspaceMapper.selectByPrimaryKey(sourceId);
|
||||||
user.setLastOrganizationId(workspace.getOrganizationId());
|
user.setLastOrganizationId(workspace.getOrganizationId());
|
||||||
user.setLastWorkspaceId(sourceId);
|
user.setLastWorkspaceId(sourceId);
|
||||||
|
getProjectListByWsAndUserId(sourceId)
|
||||||
if (projects.size() > 0) {
|
if (projects.size() > 0) {
|
||||||
user.setLastProjectId(projects.get(0).getId());
|
user.setLastProjectId(projects.get(0).getId());
|
||||||
} else {
|
} else {
|
||||||
|
@ -502,6 +498,28 @@ public class UserService {
|
||||||
userMapper.updateByPrimaryKeySelective(newUser);
|
userMapper.updateByPrimaryKeySelective(newUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Project> getProjectListByWsAndUserId(String workspaceId) {
|
||||||
|
String useId = SessionUtils.getUser().getId();
|
||||||
|
ProjectExample projectExample = new ProjectExample();
|
||||||
|
projectExample.createCriteria().andWorkspaceIdEqualTo(workspaceId);
|
||||||
|
List<Project> projects = projectMapper.selectByExample(projectExample);
|
||||||
|
|
||||||
|
UserGroupExample userGroupExample = new UserGroupExample();
|
||||||
|
userGroupExample.createCriteria().andUserIdEqualTo(useId);
|
||||||
|
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
|
||||||
|
List<Project> projectList = new ArrayList<>();
|
||||||
|
userGroups.forEach(userGroup -> {
|
||||||
|
projects.forEach(project -> {
|
||||||
|
if (StringUtils.equals(userGroup.getSourceId(), project.getId())) {
|
||||||
|
if (!projectList.contains(project)) {
|
||||||
|
projectList.add(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return projectList;
|
||||||
|
}
|
||||||
|
|
||||||
public UserDTO getUserInfo(String userId) {
|
public UserDTO getUserInfo(String userId) {
|
||||||
return getUserDTO(userId);
|
return getUserDTO(userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,14 @@ INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
|
||||||
VALUES (uuid(), 'ws_admin', 'WORKSPACE_TEMPLATE:READ+ISSUE_TEMPLATE', 'WORKSPACE_TEMPLATE');
|
VALUES (uuid(), 'ws_admin', 'WORKSPACE_TEMPLATE:READ+ISSUE_TEMPLATE', 'WORKSPACE_TEMPLATE');
|
||||||
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
|
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
|
||||||
VALUES (uuid(), 'ws_admin', 'WORKSPACE_TEMPLATE:READ+CASE_TEMPLATE', 'WORKSPACE_TEMPLATE');
|
VALUES (uuid(), 'ws_admin', 'WORKSPACE_TEMPLATE:READ+CASE_TEMPLATE', 'WORKSPACE_TEMPLATE');
|
||||||
|
insert into metersphere_dev.user_group_permission (id, group_id, permission_id, module_id)
|
||||||
|
values (uuid(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ', 'WORKSPACE_PROJECT_MANAGER');
|
||||||
|
insert into metersphere_dev.user_group_permission (id, group_id, permission_id, module_id)
|
||||||
|
values (uuid(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ+CREATE','WORKSPACE_PROJECT_MANAGER');
|
||||||
|
insert into metersphere_dev.user_group_permission (id, group_id, permission_id, module_id)
|
||||||
|
values (uuid(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ+DELETE', 'WORKSPACE_PROJECT_MANAGER');
|
||||||
|
insert into metersphere_dev.user_group_permission (id, group_id, permission_id, module_id)
|
||||||
|
values (uuid(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ+EDIT', 'WORKSPACE_PROJECT_MANAGER');
|
||||||
|
|
||||||
-- 工作空间成员
|
-- 工作空间成员
|
||||||
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
|
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
|
|
@ -254,6 +254,31 @@
|
||||||
"name": "删除成员",
|
"name": "删除成员",
|
||||||
"resourceId": "WORKSPACE_USER"
|
"resourceId": "WORKSPACE_USER"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_MANAGER:READ",
|
||||||
|
"name": "查询项目",
|
||||||
|
"resourceId": "WORKSPACE_PROJECT_MANAGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_MANAGER:READ+CREATE",
|
||||||
|
"name": "创建项目",
|
||||||
|
"resourceId": "WORKSPACE_PROJECT_MANAGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_MANAGER:READ+EDIT",
|
||||||
|
"name": "创建项目",
|
||||||
|
"resourceId": "WORKSPACE_PROJECT_MANAGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_MANAGER:READ+DELETE",
|
||||||
|
"name": "删除项目",
|
||||||
|
"resourceId": "WORKSPACE_PROJECT_MANAGER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_ENVIRONMENT:READ",
|
||||||
|
"name": "查询环境",
|
||||||
|
"resourceId": "WORKSPACE_PROJECT_MANAGER"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "WORKSPACE_TEMPLATE:READ",
|
"id": "WORKSPACE_TEMPLATE:READ",
|
||||||
"name": "查询",
|
"name": "查询",
|
||||||
|
@ -701,6 +726,14 @@
|
||||||
"id": "WORKSPACE_TEMPLATE",
|
"id": "WORKSPACE_TEMPLATE",
|
||||||
"name": "模版设置"
|
"name": "模版设置"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_MANAGER",
|
||||||
|
"name": "项目管理"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WORKSPACE_PROJECT_ENVIRONMENT",
|
||||||
|
"name": "环境设置"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "PROJECT_USER",
|
"id": "PROJECT_USER",
|
||||||
"name": "成员"
|
"name": "成员"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import MsProject from "@/business/components/settings/project/MsProject";
|
import MsProject from "@/business/components/settings/workspace/MsProject";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: "/api",
|
path: "/api",
|
||||||
|
|
|
@ -113,36 +113,32 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initMenuData() {
|
initMenuData() {
|
||||||
if (hasRoles(ROLE_ORG_ADMIN, ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
this.$get("/organization/list/userorg/" + encodeURIComponent(this.currentUserId), response => {
|
||||||
this.$get("/organization/list/userorg/" + encodeURIComponent(this.currentUserId), response => {
|
let data = response.data;
|
||||||
let data = response.data;
|
this.organizationList = data;
|
||||||
this.organizationList = data;
|
this.orgListCopy = data;
|
||||||
this.orgListCopy = data;
|
let org = data.filter(r => r.id === this.currentUser.lastOrganizationId);
|
||||||
let org = data.filter(r => r.id === this.currentUser.lastOrganizationId);
|
if (org.length > 0) {
|
||||||
if (org.length > 0) {
|
this.currentOrganizationName = org[0].name;
|
||||||
this.currentOrganizationName = org[0].name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
|
||||||
if (!this.currentUser.lastOrganizationId) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
this.$get("/workspace/list/orgworkspace/", response => {
|
});
|
||||||
let data = response.data;
|
if (!this.currentUser.lastOrganizationId) {
|
||||||
if (data.length === 0) {
|
return false;
|
||||||
this.workspaceList = [{name: this.$t('workspace.none')}];
|
|
||||||
} else {
|
|
||||||
this.workspaceList = data;
|
|
||||||
this.wsListCopy = data;
|
|
||||||
let workspace = data.filter(r => r.id === this.currentUser.lastWorkspaceId);
|
|
||||||
if (workspace.length > 0) {
|
|
||||||
this.currentWorkspaceName = workspace[0].name;
|
|
||||||
localStorage.setItem(WORKSPACE_ID, workspace[0].id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.$get("/workspace/list/orgworkspace/", response => {
|
||||||
|
let data = response.data;
|
||||||
|
if (data.length === 0) {
|
||||||
|
this.workspaceList = [{name: this.$t('workspace.none')}];
|
||||||
|
} else {
|
||||||
|
this.workspaceList = data;
|
||||||
|
this.wsListCopy = data;
|
||||||
|
let workspace = data.filter(r => r.id === this.currentUser.lastWorkspaceId);
|
||||||
|
if (workspace.length > 0) {
|
||||||
|
this.currentWorkspaceName = workspace[0].name;
|
||||||
|
localStorage.setItem(WORKSPACE_ID, workspace[0].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getCurrentUserInfo() {
|
getCurrentUserInfo() {
|
||||||
this.$get("/user/info/" + encodeURIComponent(this.currentUserId), response => {
|
this.$get("/user/info/" + encodeURIComponent(this.currentUserId), response => {
|
||||||
|
@ -159,11 +155,11 @@ export default {
|
||||||
if (response.data.workspaceId) {
|
if (response.data.workspaceId) {
|
||||||
localStorage.setItem("workspace_id", response.data.workspaceId);
|
localStorage.setItem("workspace_id", response.data.workspaceId);
|
||||||
}
|
}
|
||||||
if (response.data.lastProjectId) {
|
// if (response.data.lastProjectId) {
|
||||||
localStorage.setItem(PROJECT_ID, response.data.lastProjectId);
|
// localStorage.setItem(PROJECT_ID, response.data.lastProjectId);
|
||||||
} else {
|
// } else {
|
||||||
localStorage.removeItem(PROJECT_ID);
|
// localStorage.removeItem(PROJECT_ID);
|
||||||
}
|
// }
|
||||||
this.$router.push('/').then(() => {
|
this.$router.push('/').then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}).catch(err => err);
|
}).catch(err => err);
|
||||||
|
@ -177,11 +173,11 @@ export default {
|
||||||
this.$post("/user/switch/source/ws/" + workspaceId, {}, response => {
|
this.$post("/user/switch/source/ws/" + workspaceId, {}, response => {
|
||||||
saveLocalStorage(response);
|
saveLocalStorage(response);
|
||||||
localStorage.setItem("workspace_id", workspaceId);
|
localStorage.setItem("workspace_id", workspaceId);
|
||||||
if (response.data.lastProjectId) {
|
// if (response.data.lastProjectId) {
|
||||||
localStorage.setItem(PROJECT_ID, response.data.lastProjectId);
|
// localStorage.setItem(PROJECT_ID, response.data.lastProjectId);
|
||||||
} else {
|
// } else {
|
||||||
localStorage.removeItem(PROJECT_ID);
|
// localStorage.removeItem(PROJECT_ID);
|
||||||
}
|
// }
|
||||||
this.$router.push('/').then(() => {
|
this.$router.push('/').then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}).catch(err => err);
|
}).catch(err => err);
|
||||||
|
|
|
@ -120,7 +120,7 @@ export default {
|
||||||
initTableData() {
|
initTableData() {
|
||||||
let param = {};
|
let param = {};
|
||||||
param.projectId = this.projectId;
|
param.projectId = this.projectId;
|
||||||
this.$post('/user/project/member/list/' + this.currentPage + "/" + this.pageSize, param, response => {
|
this.result = this.$post('/user/project/member/list/' + this.currentPage + "/" + this.pageSize, param, response => {
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
let url = "/user/group/list/project/" + this.projectId;
|
let url = "/user/group/list/project/" + this.projectId;
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
<template>
|
||||||
|
<div v-loading="result.loading">
|
||||||
|
<el-card class="table-card">
|
||||||
|
<template v-slot:header>
|
||||||
|
<ms-table-header :show-create="false" :condition.sync="condition"
|
||||||
|
@search="search" @create="create"
|
||||||
|
:create-tip="btnTips" :title="$t('commons.project')">
|
||||||
|
<template v-slot:button>
|
||||||
|
<ms-table-button icon="el-icon-box"
|
||||||
|
:content="$t('api_test.jar_config.title')" @click="openJarConfig"/>
|
||||||
|
</template>
|
||||||
|
</ms-table-header>
|
||||||
|
</template>
|
||||||
|
<el-table border class="adjust-table" :data="items" style="width: 100%"
|
||||||
|
@sort-change="sort"
|
||||||
|
@filter-change="filter"
|
||||||
|
:height="screenHeight"
|
||||||
|
>
|
||||||
|
<el-table-column prop="name" :label="$t('commons.name')" min-width="100" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<pre>{{ scope.row.description }}</pre>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||||
|
<el-table-column
|
||||||
|
prop="createUser"
|
||||||
|
:label="$t('commons.create_user')"
|
||||||
|
:filters="userFilters"
|
||||||
|
column-key="create_user"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createUserName }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column min-width="100"
|
||||||
|
sortable
|
||||||
|
prop="createTime"
|
||||||
|
:label="$t('commons.create_time')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column min-width="100"
|
||||||
|
sortable
|
||||||
|
prop="updateTime"
|
||||||
|
:label="$t('commons.update_time')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('commons.operating')" width="180">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<ms-table-operator
|
||||||
|
:edit-permission="['PROJECT_MANAGER:READ+EDIT']"
|
||||||
|
:delete-permission="['PROJECT_MANAGER:READ+DELETE']"
|
||||||
|
@editClick="edit(scope.row)"
|
||||||
|
@deleteClick="handleDelete(scope.row)">
|
||||||
|
<template v-slot:behind>
|
||||||
|
<ms-table-operator-button
|
||||||
|
v-permission="['PROJECT_MANAGER:READ+EDIT']"
|
||||||
|
:tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||||
|
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||||
|
<ms-table-operator-button
|
||||||
|
v-permission="['PROJECT_MANAGER:READ+EDIT']"
|
||||||
|
:tip="$t('load_test.other_resource')"
|
||||||
|
icon="el-icon-files"
|
||||||
|
type="success" @exec="openFiles(scope.row)"/>
|
||||||
|
</template>
|
||||||
|
</ms-table-operator>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close
|
||||||
|
@close="handleClose">
|
||||||
|
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="140px" size="small">
|
||||||
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
|
<el-input v-model="form.name" autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
|
||||||
|
<el-form-item :label="$t('用例模板')" prop="caseTemplateId">
|
||||||
|
<template-select :data="form" scene="API_CASE" prop="caseTemplateId" ref="caseTemplate"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('缺陷模板')" prop="issueTemplateId">
|
||||||
|
<template-select :data="form" scene="ISSUE" prop="issueTemplateId" ref="issueTemplate"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
|
||||||
|
<el-form-item :label="$t('commons.description')" prop="description">
|
||||||
|
<el-input :autosize="{ minRows: 2, maxRows: 4}" type="textarea" v-model="form.description"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('project.tapd_id')" v-if="tapd">
|
||||||
|
<el-input v-model="form.tapdId" autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('project.jira_key')" v-if="jira">
|
||||||
|
<el-input v-model="form.jiraKey" autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('project.zentao_id')" v-if="zentao">
|
||||||
|
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('project.repeatable')" prop="repeatable">
|
||||||
|
<el-switch v-model="form.repeatable"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="测试用例自定义ID" prop="customNum">
|
||||||
|
<el-switch v-model="form.customNum"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="场景自定义ID" prop="scenarioCustomNum">
|
||||||
|
<el-switch v-model="form.scenarioCustomNum"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template v-slot:footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<ms-dialog-footer
|
||||||
|
@cancel="createVisible = false"
|
||||||
|
@confirm="submit('form')"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<ms-delete-confirm :title="$t('project.delete')" @delete="_handleDelete" ref="deleteConfirm"/>
|
||||||
|
|
||||||
|
<api-environment-config ref="environmentConfig"/>
|
||||||
|
|
||||||
|
<ms-jar-config ref="jarConfig"/>
|
||||||
|
|
||||||
|
<ms-resource-files ref="resourceFiles"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsCreateBox from "../CreateBox";
|
||||||
|
import {Message} from "element-ui";
|
||||||
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
import MsDialogFooter from "../../common/components/MsDialogFooter";
|
||||||
|
import {
|
||||||
|
getCurrentProjectID,
|
||||||
|
getCurrentUser,
|
||||||
|
getCurrentWorkspaceId,
|
||||||
|
listenGoBack,
|
||||||
|
removeGoBackListener
|
||||||
|
} from "@/common/js/utils";
|
||||||
|
import MsContainer from "../../common/components/MsContainer";
|
||||||
|
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||||
|
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
|
||||||
|
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
|
||||||
|
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
|
||||||
|
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||||
|
import {PROJECT_ID} from "@/common/js/constants";
|
||||||
|
import MsJarConfig from "../../api/test/components/jar/JarConfig";
|
||||||
|
import MsTableButton from "../../common/components/MsTableButton";
|
||||||
|
import {_filter, _sort} from "@/common/js/tableUtils";
|
||||||
|
import MsResourceFiles from "@/business/components/performance/test/components/ResourceFiles";
|
||||||
|
import TemplateSelect from "@/business/components/settings/workspace/template/TemplateSelect";
|
||||||
|
import {PROJECT_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsProject",
|
||||||
|
components: {
|
||||||
|
TemplateSelect,
|
||||||
|
MsResourceFiles,
|
||||||
|
MsTableButton,
|
||||||
|
MsJarConfig,
|
||||||
|
TemplateComponent,
|
||||||
|
ApiEnvironmentConfig,
|
||||||
|
MsTableOperatorButton,
|
||||||
|
MsDeleteConfirm,
|
||||||
|
MsMainContainer,
|
||||||
|
MsContainer, MsTableOperator, MsCreateBox, MsTablePagination, MsTableHeader, MsDialogFooter
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
createVisible: false,
|
||||||
|
result: {},
|
||||||
|
btnTips: this.$t('project.create'),
|
||||||
|
title: this.$t('project.create'),
|
||||||
|
condition: {components: PROJECT_CONFIGS},
|
||||||
|
items: [],
|
||||||
|
tapd: false,
|
||||||
|
jira: false,
|
||||||
|
zentao: false,
|
||||||
|
form: {},
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
userFilters: [],
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{required: true, message: this.$t('project.input_name'), trigger: 'blur'},
|
||||||
|
{min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'}
|
||||||
|
],
|
||||||
|
description: [
|
||||||
|
{max: 250, message: this.$t('commons.input_limit', [0, 250]), trigger: 'blur'}
|
||||||
|
],
|
||||||
|
// caseTemplateId: [{required: true}],
|
||||||
|
// issueTemplateId: [{required: true}],
|
||||||
|
},
|
||||||
|
screenHeight: 'calc(100vh - 255px)',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
baseUrl: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.$route.path.split('/')[2] === 'project' &&
|
||||||
|
this.$route.path.split('/')[3] === 'create') {
|
||||||
|
this.create();
|
||||||
|
this.$router.replace('/setting/project/all');
|
||||||
|
}
|
||||||
|
this.list();
|
||||||
|
this.getMaintainerOptions();
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentUser: () => {
|
||||||
|
return getCurrentUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.createVisible = false;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getMaintainerOptions() {
|
||||||
|
let workspaceId = getCurrentWorkspaceId();
|
||||||
|
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||||
|
this.userFilters = response.data.map(u => {
|
||||||
|
return {text: u.name, value: u.id};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
create() {
|
||||||
|
let workspaceId = this.currentUser.lastWorkspaceId;
|
||||||
|
this.getOptions();
|
||||||
|
if (!workspaceId) {
|
||||||
|
this.$warning(this.$t('project.please_choose_workspace'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.title = this.$t('project.create');
|
||||||
|
// listenGoBack(this.handleClose);
|
||||||
|
this.createVisible = true;
|
||||||
|
this.form = {};
|
||||||
|
},
|
||||||
|
getOptions() {
|
||||||
|
|
||||||
|
if (this.$refs.issueTemplate) {
|
||||||
|
this.$refs.issueTemplate.getTemplateOptions();
|
||||||
|
}
|
||||||
|
if (this.$refs.caseTemplate) {
|
||||||
|
this.$refs.caseTemplate.getTemplateOptions();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
edit(row) {
|
||||||
|
this.title = this.$t('project.edit');
|
||||||
|
this.getOptions();
|
||||||
|
this.createVisible = true;
|
||||||
|
listenGoBack(this.handleClose);
|
||||||
|
this.form = Object.assign({}, row);
|
||||||
|
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
|
||||||
|
let data = response.data;
|
||||||
|
let platforms = data.map(d => d.platform);
|
||||||
|
if (platforms.indexOf("Tapd") !== -1) {
|
||||||
|
this.tapd = true;
|
||||||
|
}
|
||||||
|
if (platforms.indexOf("Jira") !== -1) {
|
||||||
|
this.jira = true;
|
||||||
|
}
|
||||||
|
if (platforms.indexOf("Zentao") !== -1) {
|
||||||
|
this.zentao = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submit(formName) {
|
||||||
|
this.$refs[formName].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
let saveType = "add";
|
||||||
|
if (this.form.id) {
|
||||||
|
saveType = "update";
|
||||||
|
}
|
||||||
|
var protocol = document.location.protocol;
|
||||||
|
protocol = protocol.substring(0, protocol.indexOf(":"));
|
||||||
|
this.form.protocal = protocol;
|
||||||
|
this.result = this.$post("/project/" + saveType, this.form, () => {
|
||||||
|
this.createVisible = false;
|
||||||
|
this.list();
|
||||||
|
Message.success(this.$t('commons.save_success'));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openJarConfig() {
|
||||||
|
this.$refs.jarConfig.open();
|
||||||
|
},
|
||||||
|
openFiles(project) {
|
||||||
|
this.$refs.resourceFiles.open(project);
|
||||||
|
},
|
||||||
|
handleDelete(project) {
|
||||||
|
this.$refs.deleteConfirm.open(project);
|
||||||
|
},
|
||||||
|
_handleDelete(project) {
|
||||||
|
this.$confirm(this.$t('project.delete_tip'), '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.$get('/project/delete/' + project.id, () => {
|
||||||
|
if (project.id === getCurrentProjectID()) {
|
||||||
|
localStorage.removeItem(PROJECT_ID);
|
||||||
|
this.$post("/user/update/current", {id: getCurrentUser().id, lastProjectId: ''});
|
||||||
|
}
|
||||||
|
Message.success(this.$t('commons.delete_success'));
|
||||||
|
this.list();
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
this.$message({
|
||||||
|
type: 'info',
|
||||||
|
message: this.$t('commons.delete_cancelled')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
removeGoBackListener(this.handleClose);
|
||||||
|
this.createVisible = false;
|
||||||
|
this.tapd = false;
|
||||||
|
this.jira = false;
|
||||||
|
this.zentao = false;
|
||||||
|
},
|
||||||
|
search() {
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
this.condition.projectId = getCurrentProjectID();
|
||||||
|
let url = "/project/list/" + this.currentPage + '/' + this.pageSize;
|
||||||
|
this.result = this.$post(url, this.condition, (response) => {
|
||||||
|
let data = response.data;
|
||||||
|
this.items = data.listObject;
|
||||||
|
this.total = data.itemCount;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
sort(column) {
|
||||||
|
_sort(column, this.condition);
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
filter(filters) {
|
||||||
|
_filter(filters, this.condition);
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
openEnvironmentConfig(project) {
|
||||||
|
this.$refs.environmentConfig.open(project.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
document.addEventListener('keydown', this.handleEvent);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
document.removeEventListener('keydown', this.handleEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
pre {
|
||||||
|
margin: 0 0;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -109,10 +109,20 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'project/:type',
|
path: 'project/list/:type',
|
||||||
component: () => import('@/business/components/settings/project/MsProject'),
|
component: () => import('@/business/components/settings/project/ProjectList'),
|
||||||
meta: {project: true, title: 'project.manager', permissions: ['PROJECT_MANAGER:READ']}
|
meta: {project: true, title: 'project.manager', permissions: ['PROJECT_MANAGER:READ']}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'project/:type',
|
||||||
|
component: () => import('@/business/components/settings/workspace/MsProject'),
|
||||||
|
meta: {workspace: true, title: 'project.manager', permissions: ['WORKSPACE_PROJECT_MANAGER:READ']}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'wsenvlist',
|
||||||
|
component: () => import('@/business/components/settings/workspace/WsEnvironmentList'),
|
||||||
|
meta: {workspace: true, title: 'api_test.environment.environment_config', permissions: ['PROJECT_ENVIRONMENT:READ']}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'envlist',
|
path: 'envlist',
|
||||||
component: () => import('@/business/components/settings/project/EnvironmentList'),
|
component: () => import('@/business/components/settings/project/EnvironmentList'),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div v-loading="result.loading">
|
<div v-loading="result.loading">
|
||||||
<el-card class="table-card">
|
<el-card class="table-card">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :create-permission="['PROJECT_MANAGER:READ+CREATE']" :condition.sync="condition"
|
<ms-table-header :create-permission="['WORKSPACE_PROJECT_MANAGER:READ+CREATE']" :condition.sync="condition"
|
||||||
@search="search" @create="create"
|
@search="search" @create="create"
|
||||||
:create-tip="btnTips" :title="$t('commons.project')">
|
:create-tip="btnTips" :title="$t('commons.project')">
|
||||||
<template v-slot:button>
|
<template v-slot:button>
|
||||||
|
@ -54,17 +54,20 @@
|
||||||
<el-table-column :label="$t('commons.operating')" width="180">
|
<el-table-column :label="$t('commons.operating')" width="180">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-table-operator
|
<ms-table-operator
|
||||||
:edit-permission="['PROJECT_MANAGER:READ+EDIT']"
|
:edit-permission="['WORKSPACE_PROJECT_MANAGER:READ+EDIT']"
|
||||||
:delete-permission="['PROJECT_MANAGER:READ+DELETE']"
|
:delete-permission="['WORKSPACE_PROJECT_MANAGER:READ+DELETE']"
|
||||||
@editClick="edit(scope.row)"
|
@editClick="edit(scope.row)"
|
||||||
@deleteClick="handleDelete(scope.row)">
|
@deleteClick="handleDelete(scope.row)">
|
||||||
<template v-slot:behind>
|
<template v-slot:behind>
|
||||||
<ms-table-operator-button
|
<ms-table-operator-button
|
||||||
|
v-permission="['WORKSPACE_PROJECT_MANAGER:READ+EDIT']"
|
||||||
:tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
:tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||||
<ms-table-operator-button :tip="$t('load_test.other_resource')"
|
<ms-table-operator-button
|
||||||
icon="el-icon-files"
|
v-permission="['WORKSPACE_PROJECT_MANAGER:READ+EDIT']"
|
||||||
type="success" @exec="openFiles(scope.row)"/>
|
:tip="$t('load_test.other_resource')"
|
||||||
|
icon="el-icon-files"
|
||||||
|
type="success" @exec="openFiles(scope.row)"/>
|
||||||
</template>
|
</template>
|
||||||
</ms-table-operator>
|
</ms-table-operator>
|
||||||
</template>
|
</template>
|
|
@ -0,0 +1,140 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :visible="dialogVisible" :title="dialogTitle"
|
||||||
|
@close="close" :close-on-click-modal="false"
|
||||||
|
width="50%">
|
||||||
|
<el-form>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="project-item">
|
||||||
|
<div style="margin-bottom: 10px">
|
||||||
|
{{$t('project.select')}}
|
||||||
|
</div>
|
||||||
|
<el-select v-model="currentProjectId" filterable clearable >
|
||||||
|
<el-option v-for="item in projectList" :key="item.id"
|
||||||
|
:label="item.name" :value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="16" :offset="1">
|
||||||
|
<el-upload
|
||||||
|
class="api-upload" drag action="alert"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:limit="1" :file-list="uploadFiles"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:auto-upload="false" accept=".json">
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
|
||||||
|
<div class="el-upload__tip" slot="tip">
|
||||||
|
{{ $t('api_test.api_import.file_size_limit') }} {{',' + $t('api_test.api_import.ms_env_import_file_limit') }}
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template v-slot:footer>
|
||||||
|
<el-button type="primary" @click="save">
|
||||||
|
{{ $t('commons.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "EnvironmentImport",
|
||||||
|
props: {
|
||||||
|
projectList: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentProjectId: '', //所选中环境的id
|
||||||
|
uploadFiles: [],
|
||||||
|
dialogTitle: this.$t('api_test.environment.import'),
|
||||||
|
dialogVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
//导入框激活时重置选中的项目和文件
|
||||||
|
dialogVisible(val, oldVal) {
|
||||||
|
if (oldVal === false) {
|
||||||
|
this.currentProjectId = '';
|
||||||
|
this.uploadFiles = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleFileChange(file, uploadFiles) {
|
||||||
|
this.uploadFiles = uploadFiles;
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
if (this.uploadFiles.length > 0) {
|
||||||
|
for (let i = 0; i < this.uploadFiles.length; i++) {
|
||||||
|
this.uploadValidate(this.uploadFiles[i]);
|
||||||
|
let file = this.uploadFiles[i];
|
||||||
|
if (!file) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let reader = new FileReader();
|
||||||
|
|
||||||
|
reader.readAsText(file.raw)
|
||||||
|
reader.onload = (e) => {
|
||||||
|
let fileString = e.target.result;
|
||||||
|
try {
|
||||||
|
JSON.parse(fileString).map(env => {
|
||||||
|
//projectId为空字符串要转换为null,空字符串会被认为有projectId
|
||||||
|
env.projectId = this.currentProjectId === '' ? null : this.currentProjectId;
|
||||||
|
this.$fileUpload('/api/environment/add', null,[], env, response => {
|
||||||
|
this.$emit('refresh');
|
||||||
|
this.$success(this.$t('commons.save_success'));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (exception) {
|
||||||
|
this.$warning(this.$t('api_test.api_import.ms_env_import_file_limit'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleExceed() {
|
||||||
|
this.$warning(this.$t('api_test.api_import.file_exceed_limit'));
|
||||||
|
},
|
||||||
|
handleRemove() {
|
||||||
|
|
||||||
|
},
|
||||||
|
uploadValidate(file) { //判断文件扩展名是不是.json,以及文件大小是否超过20M
|
||||||
|
const extension = file.name.substring(file.name.lastIndexOf('.') + 1);
|
||||||
|
if (!(extension === 'json')) {
|
||||||
|
this.$warning(this.$t('api_test.api_import.ms_env_import_file_limit'));
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 20) {
|
||||||
|
this.$warning(this.$t('api_test.api_import.file_size_limit'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
this.dialogVisible = true;
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.dialogVisible = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.project-item {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,409 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card class="table-card" v-loading="result.loading">
|
||||||
|
<!-- 表头 -->
|
||||||
|
<template v-slot:header>
|
||||||
|
<ms-table-header :create-permission="['PROJECT_ENVIRONMENT:READ+CREATE']" :title="$t('api_test.environment.environment_list')" :create-tip="btnTips"
|
||||||
|
:condition.sync="condition" :is-tester-permission="isTesterPermission" @search="search" @create="createEnv">
|
||||||
|
<template v-slot:button>
|
||||||
|
<ms-table-button v-permission="['PROJECT_ENVIRONMENT:READ+IMPORT']" :is-tester-permission="isTesterPermission" icon="el-icon-box"
|
||||||
|
:content="$t('commons.import')" @click="importJSON"/>
|
||||||
|
<ms-table-button v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']" :is-tester-permission="isTesterPermission" icon="el-icon-box"
|
||||||
|
:content="$t('commons.export')" @click="exportJSON"/>
|
||||||
|
</template>
|
||||||
|
</ms-table-header>
|
||||||
|
</template>
|
||||||
|
<!-- 环境列表内容 -->
|
||||||
|
<el-table border :data="environments" @filter-change="filter"
|
||||||
|
@selection-change="handleSelectionChange" class="adjust-table" style="width: 100%" ref="table"
|
||||||
|
:height="screenHeight"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection"></el-table-column>
|
||||||
|
<el-table-column :label="$t('commons.project')" width="250" :filters="projectFilters" column-key="projectId"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>{{ idNameMap.get(scope.row.projectId) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('api_test.environment.name')" prop="name" show-overflow-tooltip>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('api_test.environment.socket')" show-overflow-tooltip>
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span v-if="parseDomainName(scope.row)!='SHOW_INFO'">{{ parseDomainName(scope.row) }}</span>
|
||||||
|
<el-button size="mini" icon="el-icon-s-data" @click="showInfo(scope.row)" v-else>查看域名详情</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('commons.operating')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<ms-table-operator :edit-permission="['PROJECT_ENVIRONMENT:READ+EDIT']"
|
||||||
|
:delete-permission="['PROJECT_ENVIRONMENT:READ+DELETE']"
|
||||||
|
@editClick="editEnv(scope.row)" @deleteClick="deleteEnv(scope.row)">
|
||||||
|
<template v-slot:middle>
|
||||||
|
<ms-table-operator-button v-permission="['PROJECT_ENVIRONMENT:READ+COPY']" :tip="$t('commons.copy')" @exec="copyEnv(scope.row)" :is-tester-permission="isTesterPermission"
|
||||||
|
icon="el-icon-document-copy" type="info"/>
|
||||||
|
</template>
|
||||||
|
</ms-table-operator>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 创建、编辑、复制环境时的对话框 -->
|
||||||
|
<el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" :title="dialogTitle" width="66%">
|
||||||
|
<div class="project-item">
|
||||||
|
<div>
|
||||||
|
{{$t('project.select')}}
|
||||||
|
</div>
|
||||||
|
<el-select @change="handleProjectChange" v-model="currentProjectId" filterable clearable>
|
||||||
|
<el-option v-for="item in projectList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<environment-edit :environment="currentEnvironment" ref="environmentEdit" @close="close"
|
||||||
|
:project-id="currentProjectId" @refreshAfterSave="refresh">
|
||||||
|
</environment-edit>
|
||||||
|
</el-dialog>
|
||||||
|
<environment-import :project-list="projectList" @refresh="refresh" ref="envImport"></environment-import>
|
||||||
|
|
||||||
|
<el-dialog title="域名列表" :visible.sync="domainVisible">
|
||||||
|
<el-table :data="conditions">
|
||||||
|
<el-table-column prop="socket" :label="$t('load_test.domain')" show-overflow-tooltip width="180">
|
||||||
|
<template v-slot:default="{row}">
|
||||||
|
{{getUrl(row)}}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="type" :label="$t('api_test.environment.condition_enable')" show-overflow-tooltip min-width="100px">
|
||||||
|
<template v-slot:default="{row}">
|
||||||
|
{{getName(row)}}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="details" show-overflow-tooltip min-width="120px" :label="$t('api_test.value')">
|
||||||
|
<template v-slot:default="{row}">
|
||||||
|
{{getDetails(row)}}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="createTime" show-overflow-tooltip min-width="120px" :label="$t('commons.create_time')">
|
||||||
|
<template v-slot:default="{row}">
|
||||||
|
<span>{{ row.time | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="domainVisible = false" size="mini">{{$t('commons.cancel')}}</el-button>
|
||||||
|
<el-button type="primary" @click="domainVisible = false" size="mini">{{$t('commons.confirm')}}</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
|
||||||
|
import MsTableButton from "@/business/components/common/components/MsTableButton";
|
||||||
|
import MsTableOperator from "@/business/components/common/components/MsTableOperator";
|
||||||
|
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
|
||||||
|
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
|
||||||
|
import ApiEnvironmentConfig from "@/business/components/api/test/components/ApiEnvironmentConfig";
|
||||||
|
import {Environment, parseEnvironment} from "@/business/components/api/test/model/EnvironmentModel";
|
||||||
|
import EnvironmentEdit from "@/business/components/api/test/components/environment/EnvironmentEdit";
|
||||||
|
import MsAsideItem from "@/business/components/common/components/MsAsideItem";
|
||||||
|
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
|
||||||
|
import ProjectSwitch from "@/business/components/common/head/ProjectSwitch";
|
||||||
|
import SearchList from "@/business/components/common/head/SearchList";
|
||||||
|
import {checkoutTestManagerOrTestUser, downloadFile} from "@/common/js/utils";
|
||||||
|
import EnvironmentImport from "@/business/components/settings/project/EnvironmentImport";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "EnvironmentList",
|
||||||
|
components: {
|
||||||
|
EnvironmentImport,
|
||||||
|
SearchList,
|
||||||
|
ProjectSwitch,
|
||||||
|
MsAsideContainer,
|
||||||
|
MsAsideItem,
|
||||||
|
EnvironmentEdit,
|
||||||
|
ApiEnvironmentConfig,
|
||||||
|
MsTablePagination, MsTableOperatorButton, MsTableOperator, MsTableButton, MsTableHeader
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
btnTips: this.$t('api_test.environment.create'),
|
||||||
|
projectList: [],
|
||||||
|
condition: {}, //封装传递给后端的查询条件
|
||||||
|
environments: [],
|
||||||
|
currentEnvironment: new Environment(),
|
||||||
|
result: {},
|
||||||
|
dialogVisible: false,
|
||||||
|
idNameMap: new Map(),
|
||||||
|
dialogTitle: '',
|
||||||
|
currentProjectId: '', //复制、创建、编辑环境时所选择项目的id
|
||||||
|
selectRows: [],
|
||||||
|
isTesterPermission: false,
|
||||||
|
domainVisible: false,
|
||||||
|
conditions: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
projectIds: [], //当前工作空间所拥有的所有项目id
|
||||||
|
projectFilters: [],
|
||||||
|
screenHeight: 'calc(100vh - 255px)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.isTesterPermission = checkoutTestManagerOrTestUser();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
activated() {
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
//当创建及复制环境所选择的项目变化时,改变当前环境对应的projectId
|
||||||
|
currentProjectId() {
|
||||||
|
// el-select什么都不选时值为'',为''的话也会被当成有效的projectId传给后端,转化使其无效
|
||||||
|
if (this.currentProjectId === '') {
|
||||||
|
this.currentEnvironment.projectId = null;
|
||||||
|
} else {
|
||||||
|
this.currentEnvironment.projectId = this.currentProjectId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
showInfo(row) {
|
||||||
|
const config = JSON.parse(row.config);
|
||||||
|
this.conditions = config.httpConfig.conditions;
|
||||||
|
this.domainVisible = true;
|
||||||
|
},
|
||||||
|
getName(row) {
|
||||||
|
switch (row.type) {
|
||||||
|
case "NONE":
|
||||||
|
return this.$t("api_test.definition.document.data_set.none");
|
||||||
|
case "MODULE":
|
||||||
|
return this.$t("test_track.module.module");
|
||||||
|
case "PATH":
|
||||||
|
return this.$t("api_test.definition.api_path");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getUrl(row) {
|
||||||
|
return row.protocol + "://" + row.socket;
|
||||||
|
},
|
||||||
|
getDetails(row) {
|
||||||
|
if (row && row.type === "MODULE") {
|
||||||
|
if (row.details && row.details instanceof Array) {
|
||||||
|
let value = "";
|
||||||
|
row.details.forEach((item) => {
|
||||||
|
value += item.name + ",";
|
||||||
|
});
|
||||||
|
if (value.endsWith(",")) {
|
||||||
|
value = value.substr(0, value.length - 1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} else if (row && row.type === "PATH" && row.details.length > 0 && row.details[0].name) {
|
||||||
|
return row.details[0].value === "equals" ? this.$t("commons.adv_search.operators.equals") + row.details[0].name : this.$t("api_test.request.assertions.contains") + row.details[0].name;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
if (!this.projectList || this.projectList.length === 0) { //没有项目数据的话请求项目数据
|
||||||
|
this.$get("/project/listAll", (response) => {
|
||||||
|
this.projectList = response.data; //获取当前工作空间所拥有的项目,
|
||||||
|
this.projectList.forEach(project => {
|
||||||
|
this.idNameMap.set(project.id, project.name);
|
||||||
|
this.projectIds.push(project.id);
|
||||||
|
this.projectFilters.push({
|
||||||
|
text: project.name,
|
||||||
|
value: project.id,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
this.getEnvironments();
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.getEnvironments()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getEnvironments(projectIds){
|
||||||
|
this.environments = [];
|
||||||
|
if (projectIds && projectIds.length > 0) {
|
||||||
|
this.condition.projectIds = projectIds;
|
||||||
|
} else {
|
||||||
|
this.condition.projectIds = this.projectIds;
|
||||||
|
}
|
||||||
|
let url = '/api/environment/list/' + this.currentPage + '/' + this.pageSize;
|
||||||
|
this.result = this.$post(url, this.condition, response => {
|
||||||
|
this.environments = response.data.listObject;
|
||||||
|
this.total = response.data.itemCount;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
createEnv() {
|
||||||
|
this.currentProjectId = '';
|
||||||
|
this.dialogTitle = this.$t('api_test.environment.create');
|
||||||
|
this.dialogVisible = true;
|
||||||
|
this.currentEnvironment = new Environment();
|
||||||
|
},
|
||||||
|
search() {
|
||||||
|
this.list()
|
||||||
|
},
|
||||||
|
editEnv(environment) {
|
||||||
|
this.dialogTitle = this.$t('api_test.environment.config_environment');
|
||||||
|
this.currentProjectId = environment.projectId;
|
||||||
|
const temEnv = {};
|
||||||
|
Object.assign(temEnv, environment);
|
||||||
|
parseEnvironment(temEnv); //parseEnvironment会改变环境对象的内部结构,从而影响前端列表的显示,所以复制一个环境对象作为代替
|
||||||
|
this.currentEnvironment = temEnv;
|
||||||
|
this.dialogVisible = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
copyEnv(environment) {
|
||||||
|
this.currentProjectId = environment.projectId; //复制时默认选择所要复制环境对应的项目
|
||||||
|
this.dialogTitle = this.$t('api_test.environment.copy_environment');
|
||||||
|
const temEnv = {};
|
||||||
|
Object.assign(temEnv, environment);
|
||||||
|
parseEnvironment(temEnv); //parseEnvironment会改变环境对象的内部结构,从而影响前端列表的显示,所以复制一个环境对象作为代替
|
||||||
|
let newEnvironment = new Environment(temEnv);
|
||||||
|
newEnvironment.id = null;
|
||||||
|
newEnvironment.name = this.getNoRepeatName(newEnvironment.name);
|
||||||
|
this.dialogVisible = true;
|
||||||
|
this.currentEnvironment = newEnvironment;
|
||||||
|
|
||||||
|
},
|
||||||
|
deleteEnv(environment) {
|
||||||
|
if (environment.id) {
|
||||||
|
this.$confirm(this.$t('commons.confirm_delete') + environment.name, {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.result = this.$get('/api/environment/delete/' + environment.id, () => {
|
||||||
|
this.$success(this.$t('commons.delete_success'));
|
||||||
|
this.list();
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
this.$info(this.$t('commons.delete_cancelled'));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNoRepeatName(name) {
|
||||||
|
for (let i in this.environments) {
|
||||||
|
if (this.environments[i].name === name) {
|
||||||
|
return this.getNoRepeatName(name + ' copy');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
},
|
||||||
|
|
||||||
|
//筛选指定项目下的环境
|
||||||
|
filter(filters) {
|
||||||
|
this.getEnvironments(filters.projectId)
|
||||||
|
},
|
||||||
|
|
||||||
|
//对话框取消按钮
|
||||||
|
close() {
|
||||||
|
this.dialogVisible = false;
|
||||||
|
this.$refs.environmentEdit.clearValidate();
|
||||||
|
},
|
||||||
|
refresh() {
|
||||||
|
this.list();
|
||||||
|
},
|
||||||
|
handleSelectionChange(value) {
|
||||||
|
this.selectRows = value;
|
||||||
|
},
|
||||||
|
importJSON() {
|
||||||
|
this.$refs.envImport.open();
|
||||||
|
},
|
||||||
|
exportJSON() {
|
||||||
|
if (this.selectRows.length < 1) {
|
||||||
|
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//拷贝一份选中的数据,不然下面删除id和projectId的时候会影响原数据
|
||||||
|
const envs = JSON.parse(JSON.stringify(this.selectRows));
|
||||||
|
envs.map(env => { //不导出id和projectId和模块启用条件
|
||||||
|
if (env.config){ //旧环境可能没有config数据
|
||||||
|
let tempConfig = JSON.parse(env.config);
|
||||||
|
if (tempConfig.httpConfig.conditions && tempConfig.httpConfig.conditions.length > 0) {
|
||||||
|
tempConfig.httpConfig.conditions = tempConfig.httpConfig.conditions.filter(condition => { //删除”模块启用条件“,因为导入导出环境对应的项目不同,模块也就不同,
|
||||||
|
return condition.type !== 'MODULE';
|
||||||
|
});
|
||||||
|
env.config = JSON.stringify(tempConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete env.id;
|
||||||
|
delete env.projectId;
|
||||||
|
})
|
||||||
|
downloadFile('MS_' + envs.length + '_Environments.json', JSON.stringify(envs));
|
||||||
|
},
|
||||||
|
|
||||||
|
handleProjectChange() { //项目选择下拉框选择其他项目后清空“启用条件”,因为项目变了模块也就变了。
|
||||||
|
this.currentEnvironment.config.httpConfig.conditions = [];
|
||||||
|
},
|
||||||
|
parseDomainName(environment) { //解析出环境域名用于前端展示
|
||||||
|
if (environment.config) {
|
||||||
|
const config = JSON.parse(environment.config);
|
||||||
|
if (config.httpConfig && !config.httpConfig.conditions) {
|
||||||
|
if (config.httpConfig.protocol && config.httpConfig.domain) {
|
||||||
|
return config.httpConfig.protocol + "://" + config.httpConfig.domain;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
if (config.httpConfig.conditions.length === 1) {
|
||||||
|
let obj = config.httpConfig.conditions[0];
|
||||||
|
if (obj.protocol && obj.domain) {
|
||||||
|
return obj.protocol + "://" + obj.domain;
|
||||||
|
}
|
||||||
|
} else if (config.httpConfig.conditions.length > 1) {
|
||||||
|
return "SHOW_INFO";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { //旧版本没有对应的config数据,其域名保存在protocol和domain中
|
||||||
|
return environment.protocol + '://' + environment.domain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.item-bar {
|
||||||
|
width: 100%;
|
||||||
|
background: #F9F9F9;
|
||||||
|
padding: 5px 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: solid 1px #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-selected {
|
||||||
|
background: #ECF5FF;
|
||||||
|
border-left: solid #409EFF 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-selected .item-right {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.environment-edit {
|
||||||
|
margin-left: 0;
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item .el-select {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue