Merge branch 'dev' of https://github.com/fit2cloudrd/metersphere-server into dev
This commit is contained in:
commit
d60dc5ec3c
|
@ -230,6 +230,19 @@ public class WorkspaceService {
|
|||
}
|
||||
|
||||
public void addWorkspaceByAdmin(Workspace workspace) {
|
||||
if (StringUtils.isBlank(workspace.getName())) {
|
||||
MSException.throwException(Translator.get("workspace_name_is_null"));
|
||||
}
|
||||
if (StringUtils.isBlank(workspace.getOrganizationId())) {
|
||||
MSException.throwException(Translator.get("organization_id_is_null"));
|
||||
}
|
||||
WorkspaceExample example = new WorkspaceExample();
|
||||
example.createCriteria()
|
||||
.andOrganizationIdEqualTo(workspace.getOrganizationId())
|
||||
.andNameEqualTo(workspace.getName());
|
||||
if (workspaceMapper.countByExample(example) > 0) {
|
||||
MSException.throwException(Translator.get("workspace_name_already_exists"));
|
||||
}
|
||||
workspace.setId(UUID.randomUUID().toString());
|
||||
workspace.setCreateTime(System.currentTimeMillis());
|
||||
workspace.setUpdateTime(System.currentTimeMillis());
|
||||
|
|
|
@ -17,5 +17,6 @@
|
|||
"node_deep_limit": "The node depth does not exceed 5 layers!",
|
||||
"no_nodes_message": "No node message",
|
||||
"duplicate_node_ip": "Duplicate IPs",
|
||||
"only_one_k8s": "Only one K8s can be added"
|
||||
"only_one_k8s": "Only one K8s can be added",
|
||||
"organization_id_is_null": "Organization ID cannot be null"
|
||||
}
|
|
@ -17,5 +17,6 @@
|
|||
"node_deep_limit": "节点深度不超过5层!",
|
||||
"no_nodes_message": "没有节点信息",
|
||||
"duplicate_node_ip": "节点 IP 重复",
|
||||
"only_one_k8s": "只能添加一个 K8s"
|
||||
"only_one_k8s": "只能添加一个 K8s",
|
||||
"organization_id_is_null": "组织 ID 不能为空"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-col>
|
||||
<api-header-menus/>
|
||||
<ms-api-header-menus/>
|
||||
<div>
|
||||
<transition>
|
||||
<keep-alive>
|
||||
|
@ -12,11 +12,11 @@
|
|||
</template>
|
||||
<script>
|
||||
|
||||
import ApiHeaderMenus from "./head/ApiHeaderMenus";
|
||||
import MsApiHeaderMenus from "./head/ApiHeaderMenus";
|
||||
|
||||
export default {
|
||||
name: "ApiTest",
|
||||
components: {ApiHeaderMenus},
|
||||
name: "MsApiTest",
|
||||
components: {MsApiHeaderMenus},
|
||||
data() {
|
||||
return {
|
||||
beaseUrl: "api"
|
||||
|
|
|
@ -1,96 +1,111 @@
|
|||
<template>
|
||||
|
||||
<div id="menu-bar" v-if="isRouterAlive">
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
||||
:default-active='$route.path'>
|
||||
<el-menu-item :index="'/api/home'">
|
||||
{{ $t("i18n.home") }}
|
||||
</el-menu-item>
|
||||
<el-row type="flex">
|
||||
<el-col :span="8">
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||
<el-menu-item :index="'/api/home'">
|
||||
{{ $t("i18n.home") }}
|
||||
</el-menu-item>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="3" popper-class="submenu" v-permission="['test_manager']" >
|
||||
<template v-slot:title>{{$t('commons.project')}}</template>
|
||||
<api-recent-project/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/api/project/all'">
|
||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'/api/project/create'">
|
||||
<el-button type="text">{{$t('project.create')}}</el-button>
|
||||
</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="3" popper-class="submenu" v-permission="['test_manager']">
|
||||
<template v-slot:title>{{$t('commons.project')}}</template>
|
||||
<ms-recent-list :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<ms-show-all :index="'/api/project/all'"/>
|
||||
<ms-create-button :index="'/api/project/create'" :title="$t('project.create')"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="4" popper-class="submenu" v-permission="['test_manager', 'test_user']">
|
||||
<template v-slot:title>{{$t('commons.test')}}</template>
|
||||
<api-recent-test/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/api/test/all'">
|
||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="'/api/test/create'">
|
||||
<el-button type="text">{{$t('load_test.create')}}</el-button>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
|
||||
<el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="4" popper-class="submenu" v-permission="['test_manager', 'test_user']">
|
||||
<template v-slot:title>{{$t('commons.test')}}</template>
|
||||
<ms-recent-list :options="testRecent"/>
|
||||
<el-divider/>
|
||||
<ms-show-all :index="'/api/test/all'"/>
|
||||
<ms-create-button :index="'/api/test/create'" :title="$t('load_test.create')"/>
|
||||
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
|
||||
<el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="5" popper-class="submenu" v-permission="['test_manager', 'test_user', 'test_viewer']">
|
||||
<template v-slot:title>{{$t('commons.report')}}</template>
|
||||
<api-recent-report/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/api/report/all'">
|
||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>
|
||||
</el-submenu>
|
||||
|
||||
<router-link v-if="isCurrentWorkspaceUser"
|
||||
class="header-bottom" :to="'/api/test/create'" v-permission="['test_user','test_manager']">
|
||||
<el-button type="primary" size="small">{{$t('load_test.create')}}</el-button>
|
||||
</router-link>
|
||||
|
||||
</el-menu>
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="5" popper-class="submenu" v-permission="['test_manager', 'test_user', 'test_viewer']">
|
||||
<template v-slot:title>{{$t('commons.report')}}</template>
|
||||
<ms-recent-list :options="reportRecent"/>
|
||||
<el-divider/>
|
||||
<ms-show-all :index="'/api/report/all'"/>
|
||||
<el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-row type="flex" justify="center">
|
||||
<ms-create-test :show="isCurrentWorkspaceUser" :to="'/api/test/create'"/>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="8"/>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ApiRecentTest from "../../api/test/ApiRecentTest";
|
||||
import ApiRecentProject from "../../api/project/ApiRecentProject";
|
||||
import ApiRecentReport from "../../api/report/ApiRecentReport";
|
||||
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
||||
import MsRecentList from "../../common/head/RecentList";
|
||||
import MsShowAll from "../../common/head/ShowAll";
|
||||
import MsCreateButton from "../../common/head/CreateButton";
|
||||
import MsCreateTest from "../../common/head/CreateTest";
|
||||
|
||||
export default {
|
||||
name: "ApiHeaderMenus",
|
||||
components: {ApiRecentTest, ApiRecentReport, ApiRecentProject},
|
||||
name: "MsApiHeaderMenus",
|
||||
components: {MsCreateTest, MsCreateButton, MsShowAll, MsRecentList},
|
||||
data() {
|
||||
return {
|
||||
isCurrentWorkspaceUser: false,
|
||||
testCaseProjectPath: '',
|
||||
testEditPath: '',
|
||||
reportViewPath: '',
|
||||
isRouterAlive: true
|
||||
isRouterAlive: true,
|
||||
projectRecent: {
|
||||
title: this.$t('project.recent'),
|
||||
url: "/project/recent/5",
|
||||
index: function (item) {
|
||||
return '/api/' + item.id;
|
||||
},
|
||||
router: function (item) {
|
||||
return {name: 'fucPlan', params: {projectId: item.id, projectName: item.name}}
|
||||
}
|
||||
},
|
||||
testRecent: {
|
||||
title: this.$t('load_test.recent'),
|
||||
url: "/api/recent/5",
|
||||
index: function (item) {
|
||||
return '/api/test/edit/' + item.id;
|
||||
}
|
||||
},
|
||||
reportRecent: {
|
||||
title: this.$t('report.recent'),
|
||||
url: "/api/report/recent/5",
|
||||
index: function (item) {
|
||||
return '/api/report/view/' + item.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
let path = to.path;
|
||||
//激活菜单栏
|
||||
if (path.indexOf("/api/test/") >= 0){
|
||||
if (path.indexOf("/api/test/") >= 0) {
|
||||
this.testCaseProjectPath = '/api/test/' + this.$route.params.projectId;
|
||||
this.reload();
|
||||
}
|
||||
if (path.indexOf("/api/test/edit/") >= 0){
|
||||
if (path.indexOf("/api/test/edit/") >= 0) {
|
||||
this.testEditPath = '/api/test/edit/' + this.$route.params.testId;
|
||||
this.reload();
|
||||
}
|
||||
if (path.indexOf("/api/report/view/") >= 0){
|
||||
if (path.indexOf("/api/report/view/") >= 0) {
|
||||
this.reportViewPath = '/api/report/view/' + this.$route.params.reportId;
|
||||
this.reload();
|
||||
}
|
||||
|
@ -100,7 +115,7 @@
|
|||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||
},
|
||||
methods: {
|
||||
reload () {
|
||||
reload() {
|
||||
this.isRouterAlive = false;
|
||||
this.$nextTick(function () {
|
||||
this.isRouterAlive = true;
|
||||
|
@ -112,7 +127,6 @@
|
|||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.header-menu.el-menu--horizontal > li {
|
||||
height: 39px;
|
||||
line-height: 40px;
|
||||
|
@ -125,10 +139,6 @@
|
|||
color: dimgray;
|
||||
}
|
||||
|
||||
.header-bottom {
|
||||
line-height: 40px;
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
@ -136,8 +146,14 @@
|
|||
.el-divider--horizontal {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-menu.el-menu--horizontal {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#menu-bar {
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.blank_item {
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
<template>
|
||||
<el-menu router menu-trigger="click" :default-active="$route.path">
|
||||
<div>
|
||||
<div class="recent-text">
|
||||
<i class="el-icon-time"/>
|
||||
{{$t('project.recent')}}
|
||||
<span>{{$t('project.recent')}}</span>
|
||||
</div>
|
||||
|
||||
<el-menu-item :key="p.id" v-for="p in recentProjects"
|
||||
:index="'/api/' + p.id" :route="{name:'fucPlan', params:{projectId:p.id, projectName:p.name}}">
|
||||
{{ p.name }}
|
||||
<span class="title">{{ p.name }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -20,7 +19,6 @@
|
|||
export default {
|
||||
name: "ApiRecentProject",
|
||||
mounted() {
|
||||
|
||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
this.$get('/project/recent/5', (response) => {
|
||||
this.recentProjects = response.data;
|
||||
|
@ -38,7 +36,18 @@
|
|||
|
||||
<style scoped>
|
||||
.recent-text {
|
||||
padding-left: 10%;
|
||||
padding: 0 10px;
|
||||
margin-top: -5px;
|
||||
line-height: 36px;
|
||||
color: #777777;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.recent-text span {
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<el-menu router menu-trigger="click" :default-active="$route.path">
|
||||
<div>
|
||||
<div class="recent-text">
|
||||
<i class="el-icon-time"/>
|
||||
{{$t('load_test.recent')}}
|
||||
<span>{{$t('load_test.recent')}}</span>
|
||||
</div>
|
||||
<el-menu-item :key="p.id" v-for="p in recentReports"
|
||||
:index="'/api/report/view/' + p.id" :route="{path: '/api/report/view/' + p.id}">
|
||||
{{ p.name }}
|
||||
<span class="title">{{ p.name }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -37,7 +37,18 @@
|
|||
|
||||
<style scoped>
|
||||
.recent-text {
|
||||
padding-left: 10%;
|
||||
padding: 0 10px;
|
||||
margin-top: -5px;
|
||||
line-height: 36px;
|
||||
color: #777777;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.recent-text span {
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<el-menu-item :index="this.index">
|
||||
<el-button type="text" class="create-button">{{this.title}}</el-button>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsCreateButton",
|
||||
props: {
|
||||
index: String,
|
||||
title: String,
|
||||
click: Function
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.create-button {
|
||||
padding-left: 18px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,33 @@
|
|||
<template>
|
||||
<router-link v-if="this.show" class="create-test" :to="this.to" v-permission="this.permission">
|
||||
<el-button type="primary" size="small">{{this.title}}</el-button>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsCreateTest",
|
||||
props: {
|
||||
show: Boolean,
|
||||
to: String,
|
||||
title: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return this.$t('load_test.create');
|
||||
}
|
||||
},
|
||||
permission: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return ['test_user', 'test_manager'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.create-test {
|
||||
line-height: 38px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="recent-text">
|
||||
<i class="el-icon-time"/>
|
||||
<span>{{options.title}}</span>
|
||||
</div>
|
||||
<el-menu-item :key="i.id" v-for="i in items"
|
||||
:index="getIndex(i)" :route="getRouter(i)">
|
||||
<span class="title">{{ i.name }}</span>
|
||||
</el-menu-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasRoles} from "../../../../common/utils";
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER} from "../../../../common/constants";
|
||||
|
||||
export default {
|
||||
name: "MsRecentList",
|
||||
props: {
|
||||
options: Object
|
||||
},
|
||||
mounted() {
|
||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
this.$get(this.options.url, (response) => {
|
||||
this.items = response.data;
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getIndex: function () {
|
||||
return function (item) {
|
||||
return this.options.index(item);
|
||||
}
|
||||
},
|
||||
getRouter: function () {
|
||||
return function (item) {
|
||||
return this.options.router(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.recent-text {
|
||||
padding: 0 10px;
|
||||
margin-top: -5px;
|
||||
line-height: 36px;
|
||||
color: #777777;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.recent-text span {
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<el-menu-item :index="this.index">
|
||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||
<span>{{$t('commons.show_all')}}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MsShowAll",
|
||||
props: {
|
||||
index: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
svg + span {
|
||||
padding-left: 5px;
|
||||
}
|
||||
</style>
|
|
@ -244,7 +244,6 @@
|
|||
data() {
|
||||
return {
|
||||
result: {},
|
||||
testLoading: false,
|
||||
createVisible: false,
|
||||
infoList: [],
|
||||
updateVisible: false,
|
||||
|
@ -386,11 +385,13 @@
|
|||
});
|
||||
},
|
||||
createTestResourcePool(createTestResourcePoolForm) {
|
||||
if (this.result.loading) {
|
||||
return;
|
||||
}
|
||||
this.$refs[createTestResourcePoolForm].validate(valide => {
|
||||
if (valide) {
|
||||
let vri = this.validateResourceInfo();
|
||||
if (vri.validate) {
|
||||
this.testLoading = true;
|
||||
this.convertSubmitResources();
|
||||
this.result = this.$post("/testresourcepool/add", this.form, () => {
|
||||
this.$message({
|
||||
|
@ -399,14 +400,12 @@
|
|||
},
|
||||
this.createVisible = false,
|
||||
this.initTableData());
|
||||
this.testLoading = false;
|
||||
});
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'warning',
|
||||
message: vri.msg
|
||||
});
|
||||
this.testLoading = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -428,9 +427,11 @@
|
|||
this.form.resources = resources;
|
||||
},
|
||||
updateTestResourcePool(updateTestResourcePoolForm) {
|
||||
if (this.result.loading) {
|
||||
return;
|
||||
}
|
||||
this.$refs[updateTestResourcePoolForm].validate(valide => {
|
||||
if (valide) {
|
||||
this.testLoading = true;
|
||||
let vri = this.validateResourceInfo();
|
||||
if (vri.validate) {
|
||||
this.convertSubmitResources();
|
||||
|
@ -442,20 +443,18 @@
|
|||
this.updateVisible = false,
|
||||
this.initTableData(),
|
||||
self.loading = false);
|
||||
this.testLoading = false;
|
||||
});
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'warning',
|
||||
message: vri.msg
|
||||
});
|
||||
this.testLoading = false;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
closeFunc() {
|
||||
this.form = {};
|
||||
|
|
Loading…
Reference in New Issue