style(接口测试): 编辑场景模块选项样式调整
【【接口测试】github#30574,接口场景模块展示-在修改场景时无法直接定位到当前场景所在模块,需要一层一层打开并且当有多层级目录时无法展示完整】https://www.tapd.cn/55049933/bugtrace/bugs/view?bug_id=1155049933001040224 Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
parent
b42f7311a7
commit
0911a02805
|
@ -24,6 +24,7 @@
|
|||
<ms-select-tree
|
||||
size="small"
|
||||
:data="moduleOptions"
|
||||
:default-expand-all="true"
|
||||
:defaultKey="currentScenario.apiScenarioModuleId"
|
||||
@getValue="setModule"
|
||||
:obj="moduleObj"
|
||||
|
@ -1209,7 +1210,7 @@ export default {
|
|||
if (node.parent && node.parent.data && node.parent.data.id) {
|
||||
this.evaluationParent(node.parent, status);
|
||||
}
|
||||
if (node.data.code === 'ERROR') {
|
||||
if (node.data.code === 'ERROR') {
|
||||
return;
|
||||
}
|
||||
if (node.data.code === 'FAKE_ERROR') {
|
||||
|
@ -2409,7 +2410,7 @@ export default {
|
|||
let currentEnvironment = {};
|
||||
this.environments.forEach((environment) => {
|
||||
// 找到原始环境和数据源名称
|
||||
if (environment.id === request.originalEnvironmentId !== envId) {
|
||||
if ((environment.id === request.originalEnvironmentId) !== envId) {
|
||||
parseEnvironment(environment);
|
||||
if (environment.config && environment.config.databaseConfigs) {
|
||||
environment.config.databaseConfigs.forEach((item) => {
|
||||
|
|
|
@ -1,39 +1,51 @@
|
|||
<template>
|
||||
<div v-loading="loading" ref="projectButton">
|
||||
<div class="mask" v-show="isShowSelect"></div>
|
||||
<el-popover placement="bottom-start" :width="popoverWidth" trigger="manual" v-model="isShowSelect"
|
||||
@hide="popoverHide" @show="show">
|
||||
<el-input
|
||||
size="mini"
|
||||
prefix-icon="el-icon-search"
|
||||
v-model="filterText">
|
||||
</el-input>
|
||||
<el-tree class="common-tree" :width="width" ref="tree" :data="treeData" :props="obj"
|
||||
:show-checkbox="multiple"
|
||||
:node-key="obj.id"
|
||||
:check-strictly="checkStrictly"
|
||||
:expand-on-click-node="multiple&&expandClickNode"
|
||||
:check-on-click-node="checkClickNode"
|
||||
:highlight-current="true"
|
||||
@check="clickDeal"
|
||||
:default-checked-keys="checkedId"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="nodeClick"/>
|
||||
<el-select slot="reference" ref="select" :size="size"
|
||||
v-model="returnDataKeys"
|
||||
:multiple="multiple"
|
||||
:clearable="clearable"
|
||||
:collapse-tags="collapseTags"
|
||||
:disabled="disabled"
|
||||
@click.native="selectClick"
|
||||
@remove-tag="removeTag"
|
||||
@clear="clean"
|
||||
:placeholder="placeholder"
|
||||
class="ms-tree-select">
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
trigger="manual"
|
||||
v-model="isShowSelect"
|
||||
:style="{ minWidth: `${popoverWidth}px !important` }"
|
||||
style="min-width: 200px !important; max-height: 400px; overflow: auto"
|
||||
@hide="popoverHide"
|
||||
@show="show">
|
||||
<el-input size="mini" prefix-icon="el-icon-search" v-model="filterText"> </el-input>
|
||||
<el-tree
|
||||
class="common-tree"
|
||||
:style="{ minWidth: `${popoverWidth}px !important` }"
|
||||
:width="width"
|
||||
ref="tree"
|
||||
:data="treeData"
|
||||
:props="obj"
|
||||
:show-checkbox="multiple"
|
||||
:node-key="obj.id"
|
||||
:check-strictly="checkStrictly"
|
||||
:expand-on-click-node="multiple && expandClickNode"
|
||||
:check-on-click-node="checkClickNode"
|
||||
:default-expand-all="defaultExpandAll"
|
||||
:highlight-current="true"
|
||||
@check="clickDeal"
|
||||
:default-checked-keys="checkedId"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="nodeClick" />
|
||||
<el-select
|
||||
slot="reference"
|
||||
ref="select"
|
||||
:size="size"
|
||||
v-model="returnDataKeys"
|
||||
:multiple="multiple"
|
||||
:clearable="clearable"
|
||||
:collapse-tags="collapseTags"
|
||||
:disabled="disabled"
|
||||
@click.native="selectClick"
|
||||
@remove-tag="removeTag"
|
||||
@clear="clean"
|
||||
:placeholder="placeholder"
|
||||
class="ms-tree-select">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-row>
|
||||
<el-button v-if="multiple" class="ok" @click="isShowSelect=false" size="mini" type="text">
|
||||
<el-button v-if="multiple" class="ok" @click="isShowSelect = false" size="mini" type="text">
|
||||
{{ $t('commons.confirm') }}
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
@ -42,7 +54,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'SelectTree',
|
||||
props: {
|
||||
|
@ -51,22 +62,22 @@ export default {
|
|||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
},
|
||||
obj: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => {
|
||||
return {
|
||||
id: 'id',// ID
|
||||
label: 'name',// 显示名称
|
||||
id: 'id', // ID
|
||||
label: 'name', // 显示名称
|
||||
children: 'children', //子级字段名
|
||||
path: 'path',//路径
|
||||
content: 'content',//描述
|
||||
pid: 'pid',//父id
|
||||
disabled: this.isDisabled
|
||||
}
|
||||
}
|
||||
path: 'path', //路径
|
||||
content: 'content', //描述
|
||||
pid: 'pid', //父id
|
||||
disabled: this.isDisabled,
|
||||
};
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
|
@ -77,91 +88,99 @@ export default {
|
|||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
// 配置是否可清空选择
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
// 配置多选时是否将选中值按文字的形式展示
|
||||
collapseTags: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
// 显示复选框情况下,是否严格遵循父子不互相关联
|
||||
checkStrictly: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
defaultExpandAll: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
//多选是设置点击节点是否可以选中
|
||||
checkClickNode: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
//多选时:点击节点展开还是点三角标
|
||||
expandClickNode: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
// 默认选中的节点key
|
||||
defaultKey: {
|
||||
type: [Number, String, Array, Object],
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default() {
|
||||
return 'small';
|
||||
}
|
||||
},
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default() {
|
||||
return '100%';
|
||||
}
|
||||
},
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default() {
|
||||
return '300px';
|
||||
}
|
||||
},
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default() {
|
||||
return this.$t('el.select.placeholder');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
//上面是父组件可传入参数
|
||||
data() {
|
||||
return {
|
||||
popoverWidth: "0px",//下拉框大小
|
||||
popoverWidth: '200px', //下拉框大小
|
||||
isShowSelect: false, // 是否显示树状选择器
|
||||
options: [],//select option选项
|
||||
returnDatas: [],//返回给父组件数组对象
|
||||
returnDataKeys: [],//返回父组件数组主键值
|
||||
filterText: "",
|
||||
options: [], //select option选项
|
||||
returnDatas: [], //返回给父组件数组对象
|
||||
returnDataKeys: [], //返回父组件数组主键值
|
||||
filterText: '',
|
||||
loading: false,
|
||||
checkedId: [],
|
||||
selectNodeIds: []
|
||||
selectNodeIds: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
treeData() { // 若非树状结构,则转化为树状结构数据
|
||||
treeData() {
|
||||
// 若非树状结构,则转化为树状结构数据
|
||||
return JSON.stringify(this.data).indexOf(this.obj.children) !== -1 ? this.data : this.switchTree();
|
||||
},
|
||||
},
|
||||
|
@ -171,54 +190,57 @@ export default {
|
|||
methods: {
|
||||
updated() {
|
||||
// 给多选树设置默认值
|
||||
this.$refs.tree.setCheckedKeys(this.checkedId)
|
||||
this.$refs.tree.setCheckedKeys(this.checkedId);
|
||||
},
|
||||
clickDeal(currentObj, treeStatus) {
|
||||
// 用于:父子节点严格互不关联时,父节点勾选变化时通知子节点同步变化,实现单向关联。
|
||||
let selected = treeStatus.checkedKeys.indexOf(currentObj.id) // -1未选中
|
||||
let selected = treeStatus.checkedKeys.indexOf(currentObj.id); // -1未选中
|
||||
// 选中
|
||||
if (selected !== -1) {
|
||||
// 子节点只要被选中父节点就被选中
|
||||
// this.selectedParent(currentObj)
|
||||
// 统一处理子节点为相同的勾选状态
|
||||
this.uniteChildSame(currentObj, true)
|
||||
this.uniteChildSame(currentObj, true);
|
||||
} else {
|
||||
// 未选中 处理子节点全部未选中
|
||||
if (currentObj.children && currentObj.children.length !== 0) {
|
||||
this.uniteChildSame(currentObj, false)
|
||||
this.uniteChildSame(currentObj, false);
|
||||
}
|
||||
}
|
||||
this.nodeClick(currentObj, treeStatus)
|
||||
this.nodeClick(currentObj, treeStatus);
|
||||
},
|
||||
// 统一处理子节点为相同的勾选状态
|
||||
uniteChildSame(treeList, isSelected) {
|
||||
this.$refs.tree.setChecked(treeList.id, isSelected)
|
||||
this.$refs.tree.setChecked(treeList.id, isSelected);
|
||||
if (treeList.children) {
|
||||
for (let i = 0; i < treeList.children.length; i++) {
|
||||
this.uniteChildSame(treeList.children[i], isSelected)
|
||||
this.uniteChildSame(treeList.children[i], isSelected);
|
||||
}
|
||||
}
|
||||
},
|
||||
// 统一处理父节点为选中
|
||||
selectedParent(currentObj) {
|
||||
let currentNode = this.$refs.tree.getNode(currentObj)
|
||||
let currentNode = this.$refs.tree.getNode(currentObj);
|
||||
if (currentNode.parent.key !== undefined) {
|
||||
this.$refs.tree.setChecked(currentNode.parent, true)
|
||||
this.selectedParent(currentNode.parent)
|
||||
this.$refs.tree.setChecked(currentNode.parent, true);
|
||||
this.selectedParent(currentNode.parent);
|
||||
}
|
||||
},
|
||||
outsideClick() {
|
||||
this.isShowSelect = false;
|
||||
},
|
||||
init() {
|
||||
if (this.defaultKey != undefined && this.defaultKey.length > 0) {
|
||||
if (this.defaultKey !== undefined && this.defaultKey.length > 0) {
|
||||
if (this.multiple) {
|
||||
// 多选
|
||||
if (Object.prototype.toString.call(this.defaultKey).indexOf("Array") != -1) {
|
||||
if (Object.prototype.toString.call(this.defaultKey[0]).indexOf("Object") != -1) {//对象
|
||||
if (Object.prototype.toString.call(this.defaultKey).indexOf('Array') !== -1) {
|
||||
if (Object.prototype.toString.call(this.defaultKey[0]).indexOf('Object') !== -1) {
|
||||
//对象
|
||||
this.setDatas(this.defaultKey);
|
||||
} else if (Object.prototype.toString.call(this.defaultKey[0]).indexOf("Number") != -1
|
||||
|| Object.prototype.toString.call(this.defaultKey[0]).indexOf("String") != -1) {
|
||||
} else if (
|
||||
Object.prototype.toString.call(this.defaultKey[0]).indexOf('Number') !== -1 ||
|
||||
Object.prototype.toString.call(this.defaultKey[0]).indexOf('String') !== -1
|
||||
) {
|
||||
this.setKeys(this.defaultKey);
|
||||
} else {
|
||||
return;
|
||||
|
@ -226,12 +248,13 @@ export default {
|
|||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// 单选
|
||||
if (Object.prototype.toString.call(this.defaultKey).indexOf("Number") != -1
|
||||
|| Object.prototype.toString.call(this.defaultKey).indexOf("String") != -1
|
||||
|| Object.prototype.toString.call(this.defaultKey).indexOf("Object") != -1) {
|
||||
if (
|
||||
Object.prototype.toString.call(this.defaultKey).indexOf('Number') !== -1 ||
|
||||
Object.prototype.toString.call(this.defaultKey).indexOf('String') !== -1 ||
|
||||
Object.prototype.toString.call(this.defaultKey).indexOf('Object') !== -1
|
||||
) {
|
||||
this.setKey(this.defaultKey);
|
||||
} else {
|
||||
return;
|
||||
|
@ -244,28 +267,32 @@ export default {
|
|||
},
|
||||
//下拉框select点击[入口]
|
||||
selectClick() {
|
||||
this.$emit("selectClick")
|
||||
this.$emit('selectClick');
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
this.$nextTick(function () {//设置下拉框自适应宽度
|
||||
this.$nextTick(function () {
|
||||
//设置下拉框自适应宽度
|
||||
this.popoverWidth = this.$refs.select.$el.clientWidth - 26;
|
||||
})
|
||||
});
|
||||
//显示下拉框
|
||||
return this.isShowSelect = !this.isShowSelect
|
||||
return (this.isShowSelect = !this.isShowSelect);
|
||||
},
|
||||
//单选: 树点击方法
|
||||
nodeClick(data, node) {
|
||||
if (!this.multiple) {//单选
|
||||
if (!this.multiple) {
|
||||
//单选
|
||||
this.isShowSelect = false;
|
||||
this.setKey(node.key);
|
||||
} else {//多选
|
||||
} else {
|
||||
//多选
|
||||
let checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
|
||||
let t = [];
|
||||
this.options = checkedKeys.map((item) => {//设置option选项
|
||||
this.options = checkedKeys.map((item) => {
|
||||
//设置option选项
|
||||
let node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
|
||||
t.push(node.data);
|
||||
return {label: node.label, value: node.key};
|
||||
return { label: node.label, value: node.key };
|
||||
});
|
||||
this.returnDataKeys = this.options.map((item) => {
|
||||
return item.value;
|
||||
|
@ -289,7 +316,7 @@ export default {
|
|||
},
|
||||
//单选:清空选中
|
||||
clean() {
|
||||
this.$refs.tree.setCurrentKey(null);//清除树选中key
|
||||
this.$refs.tree.setCurrentKey(null); //清除树选中key
|
||||
this.returnDatas = null;
|
||||
this.returnDataKeys = '';
|
||||
this.selectNodeIds = [];
|
||||
|
@ -308,9 +335,9 @@ export default {
|
|||
//单选:设置、初始化对象
|
||||
setData(data) {
|
||||
this.options = [];
|
||||
this.options.push({label: data[this.obj.label], value: data[this.obj.id]});
|
||||
this.options.push({ label: data[this.obj.label], value: data[this.obj.id] });
|
||||
this.returnDatas = data;
|
||||
this.returnDataKeys = data[this.obj.id]
|
||||
this.returnDataKeys = data[this.obj.id];
|
||||
this.selectNodeIds = [];
|
||||
this.getChildNodeId(data, this.selectNodeIds);
|
||||
},
|
||||
|
@ -320,34 +347,36 @@ export default {
|
|||
this.returnDataKeys = thisKeys;
|
||||
let t = [];
|
||||
this.options = [];
|
||||
thisKeys.map((item) => {//设置option选项
|
||||
thisKeys.map((item) => {
|
||||
//设置option选项
|
||||
let node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
|
||||
if (node) {
|
||||
t.push(node.data);
|
||||
this.options.push({label: node.label, value: node.key});
|
||||
return {label: node.label, value: node.key};
|
||||
this.options.push({ label: node.label, value: node.key });
|
||||
return { label: node.label, value: node.key };
|
||||
}
|
||||
});
|
||||
this.returnDatas = t;
|
||||
this.popoverHide()
|
||||
this.popoverHide();
|
||||
},
|
||||
//多选:设置、初始化对象
|
||||
setDatas(data) {
|
||||
this.$refs.tree.setCheckedNodes(data);
|
||||
this.returnDatas = data;
|
||||
let t = [];
|
||||
data.map((item) => {//设置option选项
|
||||
data.map((item) => {
|
||||
//设置option选项
|
||||
t.push(item[this.obj.id]);
|
||||
});
|
||||
this.returnDataKeys = t;
|
||||
this.popoverHide()
|
||||
this.popoverHide();
|
||||
},
|
||||
// 多选,删除任一select选项的回调
|
||||
removeTag(val) {
|
||||
this.$refs.tree.setChecked(val, false);//设置为未选中
|
||||
let node = this.$refs.tree.getNode(val);//获取节点
|
||||
this.$refs.tree.setChecked(val, false); //设置为未选中
|
||||
let node = this.$refs.tree.getNode(val); //获取节点
|
||||
if (!this.checkStrictly && node.childNodes.length > 0) {
|
||||
this.treeToList(node).map(item => {
|
||||
this.treeToList(node).map((item) => {
|
||||
if (item.childNodes.length <= 0) {
|
||||
this.$refs.tree.setChecked(item, false);
|
||||
}
|
||||
|
@ -355,21 +384,20 @@ export default {
|
|||
}
|
||||
this.nodeClick();
|
||||
this.popoverHide();
|
||||
|
||||
},
|
||||
show(){
|
||||
document.addEventListener('click', this.hidePanel, false)
|
||||
show() {
|
||||
document.addEventListener('click', this.hidePanel, false);
|
||||
},
|
||||
//下拉框关闭执行
|
||||
popoverHide() {
|
||||
this.$emit('setSelectNodeIds', this.selectNodeIds);
|
||||
this.$emit('getValue', this.returnDataKeys, this.returnDatas ? this.returnDatas : {});
|
||||
document.removeEventListener('click', this.hidePanel, false)
|
||||
document.removeEventListener('click', this.hidePanel, false);
|
||||
},
|
||||
hidePanel (e) {
|
||||
hidePanel(e) {
|
||||
if (!this.$refs.projectButton.contains(e.target)) {
|
||||
this.isShowSelect = false
|
||||
this.popoverHide()
|
||||
this.isShowSelect = false;
|
||||
this.popoverHide();
|
||||
}
|
||||
},
|
||||
// 多选,清空所有勾选
|
||||
|
@ -422,9 +450,9 @@ export default {
|
|||
return false;
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
|
@ -435,13 +463,14 @@ export default {
|
|||
// 隐藏select自带的下拉框
|
||||
this.$refs.select.blur();
|
||||
},
|
||||
treeData: {//监听tree数据
|
||||
treeData: {
|
||||
//监听tree数据
|
||||
handler: function () {
|
||||
this.$nextTick(() => {
|
||||
this.init();
|
||||
})
|
||||
});
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
},
|
||||
defaultKey: {
|
||||
handler: function () {
|
||||
|
@ -452,7 +481,7 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
},
|
||||
data: {
|
||||
handler: function () {
|
||||
|
@ -462,7 +491,7 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
},
|
||||
filterText(val) {
|
||||
this.$nextTick(() => {
|
||||
|
@ -474,10 +503,9 @@ export default {
|
|||
this.$refs.tree.filter(val);
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mask {
|
||||
height: 100%;
|
||||
|
@ -499,16 +527,13 @@ export default {
|
|||
z-index: 111;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__children ) {
|
||||
:deep(.el-tree-node__children) {
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
.ok {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.el-row {
|
||||
padding-top: 0px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -2,38 +2,61 @@
|
|||
<div>
|
||||
<el-card class="table-card" v-loading="loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :create-permission="['SYSTEM_TEST_POOL:READ+CREATE']" :condition.sync="condition"
|
||||
@search="search" @create="create"
|
||||
:create-tip="$t('test_resource_pool.create_resource_pool')"
|
||||
:title="$t('commons.test_resource_pool')"/>
|
||||
<ms-table-header
|
||||
:create-permission="['SYSTEM_TEST_POOL:READ+CREATE']"
|
||||
:condition.sync="condition"
|
||||
@search="search"
|
||||
@create="create"
|
||||
:create-tip="$t('test_resource_pool.create_resource_pool')"
|
||||
:title="$t('commons.test_resource_pool')"
|
||||
/>
|
||||
</template>
|
||||
<el-table border class="adjust-table" :data="items" style="width: 100%"
|
||||
:height="screenHeight"
|
||||
<el-table
|
||||
border
|
||||
class="adjust-table"
|
||||
:data="items"
|
||||
style="width: 100%"
|
||||
:height="screenHeight"
|
||||
>
|
||||
<el-table-column prop="name" :label="$t('commons.name')"/>
|
||||
<el-table-column prop="description" :label="$t('commons.description')"/>
|
||||
<el-table-column prop="name" :label="$t('commons.name')" />
|
||||
<el-table-column
|
||||
prop="description"
|
||||
:label="$t('commons.description')"
|
||||
/>
|
||||
<el-table-column prop="type" :label="$t('test_resource_pool.type')">
|
||||
<template v-slot:default="scope">
|
||||
<span v-if="scope.row.type === 'NODE'">Node</span>
|
||||
<span v-if="scope.row.type === 'K8S'" v-xpack>Kubernetes</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" :label="$t('test_resource_pool.enable_disable')">
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:label="$t('test_resource_pool.enable_disable')"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<el-switch v-model="scope.row.status"
|
||||
inactive-color="#DCDFE6"
|
||||
active-value="VALID"
|
||||
inactive-value="INVALID"
|
||||
@change="changeSwitch(scope.row)"
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
inactive-color="#DCDFE6"
|
||||
active-value="VALID"
|
||||
inactive-value="INVALID"
|
||||
@change="changeSwitch(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" :label="$t('commons.create_time')" width="180">
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
width="180"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="updateTime" :label="$t('commons.update_time')" width="180">
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
width="180"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | datetimeFormat }}</span>
|
||||
</template>
|
||||
|
@ -41,74 +64,122 @@
|
|||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<div>
|
||||
<ms-table-operator :edit-permission="['SYSTEM_TEST_POOL:READ+EDIT']"
|
||||
:delete-permission="['SYSTEM_TEST_POOL:READ+DELETE']"
|
||||
@editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||
<ms-table-operator
|
||||
:edit-permission="['SYSTEM_TEST_POOL:READ+EDIT']"
|
||||
:delete-permission="['SYSTEM_TEST_POOL:READ+DELETE']"
|
||||
@editClick="edit(scope.row)"
|
||||
@deleteClick="del(scope.row)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
<ms-table-pagination
|
||||
:change="initTableData"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:total="total"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="form.id ? $t('test_resource_pool.update_resource_pool') : $t('test_resource_pool.create_resource_pool')"
|
||||
:visible.sync="dialogVisible" width="80%"
|
||||
:title="
|
||||
form.id
|
||||
? $t('test_resource_pool.update_resource_pool')
|
||||
: $t('test_resource_pool.create_resource_pool')
|
||||
"
|
||||
:visible.sync="dialogVisible"
|
||||
width="80%"
|
||||
top="5%"
|
||||
@closed="closeFunc"
|
||||
:destroy-on-close="true"
|
||||
v-loading="dialogLoading"
|
||||
>
|
||||
<div style="height: 60vh;overflow: auto;">
|
||||
<el-form :model="form" label-position="right" label-width="140px" size="small" :rules="rule"
|
||||
ref="testResourcePoolForm">
|
||||
<div style="height: 60vh; overflow: auto">
|
||||
<el-form
|
||||
:model="form"
|
||||
label-position="right"
|
||||
label-width="140px"
|
||||
size="small"
|
||||
:rules="rule"
|
||||
ref="testResourcePoolForm"
|
||||
>
|
||||
<el-form-item :label="$t('commons.name')" prop="name">
|
||||
<el-input v-model="form.name" autocomplete="off"/>
|
||||
<el-input v-model="form.name" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.description')" prop="description">
|
||||
<el-input v-model="form.description" autocomplete="off"/>
|
||||
<el-input v-model="form.description" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.image')" prop="image">
|
||||
<el-input v-model="form.image"/>
|
||||
<el-input v-model="form.image" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('test_resource_pool.backend_listener')" prop="backendListener" v-xpack>
|
||||
<el-switch v-model="form.backendListener"/>
|
||||
<el-form-item
|
||||
:label="$t('test_resource_pool.backend_listener')"
|
||||
prop="backendListener"
|
||||
v-xpack
|
||||
>
|
||||
<el-switch v-model="form.backendListener" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('test_resource_pool.usage')" prop="usage">
|
||||
<el-checkbox :label="$t('commons.api')" v-model="form.api"></el-checkbox>
|
||||
<el-checkbox :label="$t('commons.performance')" v-model="form.performance"></el-checkbox>
|
||||
<el-checkbox
|
||||
:label="$t('commons.api')"
|
||||
v-model="form.api"
|
||||
></el-checkbox>
|
||||
<el-checkbox
|
||||
:label="$t('commons.performance')"
|
||||
v-model="form.performance"
|
||||
></el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="JMeter HEAP" prop="HEAP">
|
||||
<el-input v-model="form.heap" placeholder="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" maxlength="200" show-word-limit/>
|
||||
<el-input
|
||||
v-model="form.heap"
|
||||
placeholder="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="JMeter GC_ALGO" prop="GC_ALGO">
|
||||
<el-input v-model="form.gcAlgo"
|
||||
placeholder="-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20" maxlength="200" show-word-limit/>
|
||||
<el-input
|
||||
v-model="form.gcAlgo"
|
||||
placeholder="-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="type" :label="$t('test_resource_pool.type')">
|
||||
<el-select v-model="form.type" :placeholder="$t('test_resource_pool.select_pool_type')"
|
||||
@change="changeResourceType(form.type)">
|
||||
<el-select
|
||||
v-model="form.type"
|
||||
:placeholder="$t('test_resource_pool.select_pool_type')"
|
||||
@change="changeResourceType(form.type)"
|
||||
>
|
||||
<el-option key="NODE" value="NODE" label="Node">Node</el-option>
|
||||
<el-option key="K8S" value="K8S" label="Kubernetes" v-xpack>Kubernetes</el-option>
|
||||
<el-option key="K8S" value="K8S" label="Kubernetes" v-xpack
|
||||
>Kubernetes</el-option
|
||||
>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div class="node-line" v-if="form.type === 'K8S'" v-xpack>
|
||||
<div v-for="(item,index) in infoList " :key="index">
|
||||
<div v-for="(item, index) in infoList" :key="index">
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form-item label="Master URL"
|
||||
:rules="requiredRules">
|
||||
<el-input v-model="item.masterUrl" autocomplete="new-password"/>
|
||||
<el-form-item label="Master URL" :rules="requiredRules">
|
||||
<el-input
|
||||
v-model="item.masterUrl"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form-item label="Token"
|
||||
:rules="requiredRules">
|
||||
<el-input v-model="item.token" type="password" show-password autocomplete="new-password"/>
|
||||
<el-form-item label="Token" :rules="requiredRules">
|
||||
<el-input
|
||||
v-model="item.token"
|
||||
type="password"
|
||||
show-password
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -120,64 +191,96 @@
|
|||
<el-popover
|
||||
placement="bottom"
|
||||
width="450"
|
||||
trigger="hover">
|
||||
trigger="hover"
|
||||
>
|
||||
<div>
|
||||
<strong>{{ $t('test_resource_pool.k8s_sa_tips') }}</strong><br>
|
||||
<el-link type="primary" @click="downloadYaml(item, 'role')">role.yaml</el-link>
|
||||
<strong>{{
|
||||
$t("test_resource_pool.k8s_sa_tips")
|
||||
}}</strong
|
||||
><br />
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="downloadYaml(item, 'role')"
|
||||
>role.yaml</el-link
|
||||
>
|
||||
</div>
|
||||
|
||||
<div style="padding-top: 20px">
|
||||
<strong>{{ $t('test_resource_pool.k8s_deploy_type_tips') }}</strong><br>
|
||||
<el-link type="primary" @click="downloadYaml(item, 'DaemonSet')">daemonset.yaml</el-link>
|
||||
<strong>{{
|
||||
$t("test_resource_pool.k8s_deploy_type_tips")
|
||||
}}</strong
|
||||
><br />
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="downloadYaml(item, 'DaemonSet')"
|
||||
>daemonset.yaml</el-link
|
||||
>
|
||||
|
||||
<el-link type="primary" @click="downloadYaml(item, 'Deployment')">deployment.yaml</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="downloadYaml(item, 'Deployment')"
|
||||
>deployment.yaml</el-link
|
||||
>
|
||||
</div>
|
||||
<i class="el-icon-info" slot="reference"></i>
|
||||
</el-popover>
|
||||
</template>
|
||||
<el-input v-model="item.namespace" type="text"/>
|
||||
<el-input v-model="item.namespace" type="text" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form-item label="Deploy Name" :rules="requiredRules">
|
||||
<el-input v-model="item.deployName"/>
|
||||
<el-input v-model="item.deployName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form-item label="API Image">
|
||||
<el-input v-model="item.apiImage" type="text"/>
|
||||
<el-input v-model="item.apiImage" type="text" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('test_resource_pool.max_threads')"
|
||||
:rules="requiredRules">
|
||||
<el-input-number v-model="item.maxConcurrency" :min="1" :max="1000000000"/>
|
||||
<el-form-item
|
||||
:label="$t('test_resource_pool.max_threads')"
|
||||
:rules="requiredRules"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="item.maxConcurrency"
|
||||
:min="1"
|
||||
:max="1000000000"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('test_resource_pool.pod_thread_limit')"
|
||||
:rules="requiredRules">
|
||||
<el-input-number v-model="item.podThreadLimit" :min="1" :max="1000000"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('test_resource_pool.sync_jar')">
|
||||
<el-checkbox v-model="item.enable"/>
|
||||
<el-form-item
|
||||
:label="$t('test_resource_pool.pod_thread_limit')"
|
||||
:rules="requiredRules"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="item.podThreadLimit"
|
||||
:min="1"
|
||||
:max="1000000"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item>
|
||||
<template v-slot:label>
|
||||
<el-link type="primary" @click="jobTemplate">{{ $t('system.test_resource_pool.edit_job_template') }}</el-link>
|
||||
<el-tooltip :content="$t('system.test_resource_pool.edit_job_template_tip')"
|
||||
effect="light"
|
||||
trigger="hover">
|
||||
<el-link type="primary" @click="jobTemplate">{{
|
||||
$t("system.test_resource_pool.edit_job_template")
|
||||
}}</el-link>
|
||||
<el-tooltip
|
||||
:content="
|
||||
$t('system.test_resource_pool.edit_job_template_tip')
|
||||
"
|
||||
effect="light"
|
||||
trigger="hover"
|
||||
>
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
@ -185,90 +288,122 @@
|
|||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<job-template ref="jobTemplate" @saveJobTemplate="saveJobTemplate"/>
|
||||
<job-template
|
||||
ref="jobTemplate"
|
||||
@saveJobTemplate="saveJobTemplate"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="node-line" v-if="form.type === 'NODE'">
|
||||
<el-row>
|
||||
<el-col :span="22" :offset="2">
|
||||
<el-row style="margin-bottom: 10px;">
|
||||
<el-row style="margin-bottom: 10px">
|
||||
<el-col :span="8">
|
||||
<el-button icon="el-icon-circle-plus-outline" plain size="mini"
|
||||
@click="addResourceInfo()">
|
||||
{{ $t('commons.add') }}
|
||||
<el-button
|
||||
icon="el-icon-circle-plus-outline"
|
||||
plain
|
||||
size="mini"
|
||||
@click="addResourceInfo()"
|
||||
>
|
||||
{{ $t("commons.add") }}
|
||||
</el-button>
|
||||
<el-button icon="el-icon-circle-plus-outline" plain size="mini"
|
||||
@click="batchAddResource">
|
||||
{{ $t('commons.batch_add') }}
|
||||
<el-button
|
||||
icon="el-icon-circle-plus-outline"
|
||||
plain
|
||||
size="mini"
|
||||
@click="batchAddResource"
|
||||
>
|
||||
{{ $t("commons.batch_add") }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table :data="infoList" class="tb-edit" align="center" border highlight-current-row>
|
||||
<el-table-column type="index" width="50"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="ip"
|
||||
label="IP">
|
||||
<template v-slot:default="{row}">
|
||||
<el-input size="small" v-model="row.ip" autocomplete="off"/>
|
||||
<el-table
|
||||
:data="infoList"
|
||||
class="tb-edit"
|
||||
align="center"
|
||||
border
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column align="center" prop="ip" label="IP">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
size="small"
|
||||
v-model="row.ip"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="port"
|
||||
label="Port">
|
||||
<template v-slot:default="{row}">
|
||||
<el-input-number size="small" v-model="row.port" :min="1" :max="65535"></el-input-number>
|
||||
<el-table-column align="center" prop="port" label="Port">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input-number
|
||||
size="small"
|
||||
v-model="row.port"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="monitorPort"
|
||||
label="Monitor">
|
||||
<template v-slot:default="{row}">
|
||||
<el-input-number size="small" v-model="row.monitorPort" :min="1" :max="65535"></el-input-number>
|
||||
label="Monitor"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input-number
|
||||
size="small"
|
||||
v-model="row.monitorPort"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="maxConcurrency"
|
||||
:label="$t('test_resource_pool.max_threads')">
|
||||
<template v-slot:default="{row}">
|
||||
<el-input-number size="small" v-model="row.maxConcurrency" :min="1"
|
||||
:max="1000000000"></el-input-number>
|
||||
:label="$t('test_resource_pool.max_threads')"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input-number
|
||||
size="small"
|
||||
v-model="row.maxConcurrency"
|
||||
:min="1"
|
||||
:max="1000000000"
|
||||
></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="enable"
|
||||
:label="$t('test_resource_pool.sync_jar')">
|
||||
<template v-slot:default="{row}">
|
||||
<el-checkbox size="small" v-model="row.enable"/>
|
||||
:label="$t('commons.operating')"
|
||||
>
|
||||
<template v-slot:default="{ $index }">
|
||||
<el-button
|
||||
@click="removeResourceInfo($index)"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
circle
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" :label="$t('commons.operating')">
|
||||
<template v-slot:default="{$index}">
|
||||
<el-button @click="removeResourceInfo($index)" type="danger" icon="el-icon-delete" size="mini"
|
||||
circle/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<batch-add-resource ref="batchAddResource" @batchSave="batchSave"/>
|
||||
<batch-add-resource ref="batchAddResource" @batchSave="batchSave" />
|
||||
</el-form>
|
||||
</div>
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
v-if="form.id"
|
||||
@cancel="dialogVisible = false"
|
||||
@confirm="updateTestResourcePool()"/>
|
||||
@confirm="updateTestResourcePool()"
|
||||
/>
|
||||
<ms-dialog-footer
|
||||
v-else
|
||||
@cancel="dialogVisible = false"
|
||||
@confirm="createTestResourcePool()"/>
|
||||
@confirm="createTestResourcePool()"
|
||||
/>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
@ -279,24 +414,34 @@ import MsTablePagination from "metersphere-frontend/src/components/pagination/Ta
|
|||
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
||||
import MsTableOperator from "metersphere-frontend/src/components/MsTableOperator";
|
||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||
import {listenGoBack, removeGoBackListener} from "metersphere-frontend/src/utils";
|
||||
import {
|
||||
listenGoBack,
|
||||
removeGoBackListener,
|
||||
} from "metersphere-frontend/src/utils";
|
||||
import BatchAddResource from "../components/BatchAddResource";
|
||||
import {getYaml} from "./test-resource-pool";
|
||||
import { getYaml } from "./test-resource-pool";
|
||||
import {
|
||||
checkResourcePoolUse,
|
||||
createResourcePool,
|
||||
delResourcePoolById,
|
||||
getResourcePoolPages,
|
||||
modifyResourcePool,
|
||||
modifyResourcePoolStatus
|
||||
modifyResourcePoolStatus,
|
||||
} from "../../../api/resource-pool";
|
||||
import {getSystemVersion} from "../../../api/system";
|
||||
import {operationConfirm} from "metersphere-frontend/src/utils";
|
||||
import { getSystemVersion } from "../../../api/system";
|
||||
import { operationConfirm } from "metersphere-frontend/src/utils";
|
||||
import JobTemplate from "@/business/system/components/JobTemplate";
|
||||
|
||||
export default {
|
||||
name: "MsTestResourcePool",
|
||||
components: {JobTemplate, BatchAddResource, MsTablePagination, MsTableHeader, MsTableOperator, MsDialogFooter},
|
||||
components: {
|
||||
JobTemplate,
|
||||
BatchAddResource,
|
||||
MsTablePagination,
|
||||
MsTableHeader,
|
||||
MsTableOperator,
|
||||
MsDialogFooter,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
@ -310,36 +455,59 @@ export default {
|
|||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
form: {performance: true, api: true, backendListener: true},
|
||||
screenHeight: 'calc(100vh - 155px)',
|
||||
requiredRules: [{required: true, message: this.$t('test_resource_pool.fill_the_data'), trigger: 'blur'}],
|
||||
form: { performance: true, api: true, backendListener: true },
|
||||
screenHeight: "calc(100vh - 155px)",
|
||||
requiredRules: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("test_resource_pool.fill_the_data"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_resource_pool.input_pool_name'), trigger: 'blur'},
|
||||
{min: 2, max: 20, message: this.$t('commons.input_limit', [2, 20]), trigger: 'blur'},
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("test_resource_pool.input_pool_name"),
|
||||
trigger: "blur",
|
||||
},
|
||||
{
|
||||
min: 2,
|
||||
max: 20,
|
||||
message: this.$t("commons.input_limit", [2, 20]),
|
||||
trigger: "blur",
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9.·-]+$/,
|
||||
message: this.$t('test_resource_pool.pool_name_valid'),
|
||||
trigger: 'blur'
|
||||
}
|
||||
message: this.$t("test_resource_pool.pool_name_valid"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
image: [
|
||||
{max: 100, message: this.$t('commons.input_limit', [0, 100])}
|
||||
{ max: 100, message: this.$t("commons.input_limit", [0, 100]) },
|
||||
],
|
||||
description: [
|
||||
{max: 60, message: this.$t('commons.input_limit', [0, 60]), trigger: 'blur'}
|
||||
{
|
||||
max: 60,
|
||||
message: this.$t("commons.input_limit", [0, 60]),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
type: [
|
||||
{required: true, message: this.$t('test_resource_pool.select_pool_type'), trigger: 'blur'}
|
||||
]
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("test_resource_pool.select_pool_type"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
updatePool: {
|
||||
testName: '',
|
||||
haveTestUsePool: false
|
||||
testName: "",
|
||||
haveTestUsePool: false,
|
||||
},
|
||||
apiImage: '',
|
||||
apiImageTag: '',
|
||||
apiImage: "",
|
||||
apiImageTag: "",
|
||||
};
|
||||
},
|
||||
activated() {
|
||||
|
@ -348,28 +516,31 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
this.loading = getResourcePoolPages(this.currentPage, this.pageSize, this.condition)
|
||||
.then(res => {
|
||||
let {listObject, itemCount} = res.data;
|
||||
this.items = listObject;
|
||||
this.total = itemCount;
|
||||
});
|
||||
this.loading = getResourcePoolPages(
|
||||
this.currentPage,
|
||||
this.pageSize,
|
||||
this.condition
|
||||
).then((res) => {
|
||||
let { listObject, itemCount } = res.data;
|
||||
this.items = listObject;
|
||||
this.total = itemCount;
|
||||
});
|
||||
},
|
||||
changeResourceType(type) {
|
||||
this.infoList = [];
|
||||
let info = {};
|
||||
if (type === 'NODE') {
|
||||
info.ip = '';
|
||||
info.port = '8082';
|
||||
info.monitorPort = '9100';
|
||||
if (type === "NODE") {
|
||||
info.ip = "";
|
||||
info.port = "8082";
|
||||
info.monitorPort = "9100";
|
||||
}
|
||||
if (type === 'K8S') {
|
||||
info.masterUrl = '';
|
||||
info.token = '';
|
||||
info.namespace = '';
|
||||
if (type === "K8S") {
|
||||
info.masterUrl = "";
|
||||
info.token = "";
|
||||
info.namespace = "";
|
||||
info.podThreadLimit = 5000;
|
||||
info.deployType = 'DaemonSet';
|
||||
info.deployName = 'ms-node-controller';
|
||||
info.deployType = "DaemonSet";
|
||||
info.deployName = "ms-node-controller";
|
||||
}
|
||||
info.maxConcurrency = 100;
|
||||
this.infoList.push(info);
|
||||
|
@ -377,16 +548,16 @@ export default {
|
|||
|
||||
addResourceInfo() {
|
||||
this.infoList.push({
|
||||
port: '8082',
|
||||
monitorPort: '9100',
|
||||
maxConcurrency: 100
|
||||
port: "8082",
|
||||
monitorPort: "9100",
|
||||
maxConcurrency: 100,
|
||||
});
|
||||
},
|
||||
removeResourceInfo(index) {
|
||||
if (this.infoList.length > 1) {
|
||||
this.infoList.splice(index, 1);
|
||||
} else {
|
||||
this.$warning(this.$t('test_resource_pool.cannot_remove_all_node'));
|
||||
this.$warning(this.$t("test_resource_pool.cannot_remove_all_node"));
|
||||
}
|
||||
},
|
||||
batchAddResource() {
|
||||
|
@ -397,14 +568,14 @@ export default {
|
|||
},
|
||||
batchSave(resources) {
|
||||
let targets = this._handleBatchVars(resources);
|
||||
targets.forEach(row => {
|
||||
targets.forEach((row) => {
|
||||
this.infoList.push(row);
|
||||
});
|
||||
},
|
||||
_handleBatchVars(data) {
|
||||
let params = data.split("\n");
|
||||
let keyValues = [];
|
||||
params.forEach(item => {
|
||||
params.forEach((item) => {
|
||||
let line = item.split(/,|,/);
|
||||
if (line.length < 3) {
|
||||
return;
|
||||
|
@ -419,23 +590,29 @@ export default {
|
|||
return keyValues;
|
||||
},
|
||||
saveJobTemplate(template) {
|
||||
this.infoList.forEach(item => {
|
||||
this.infoList.forEach((item) => {
|
||||
item.jobTemplate = template;
|
||||
});
|
||||
},
|
||||
validateResourceInfo() {
|
||||
if (this.infoList.length <= 0) {
|
||||
return {validate: false, msg: this.$t('test_resource_pool.cannot_empty')};
|
||||
return {
|
||||
validate: false,
|
||||
msg: this.$t("test_resource_pool.cannot_empty"),
|
||||
};
|
||||
}
|
||||
let resourcePoolType = this.form.type;
|
||||
let resultValidate = {validate: true, msg: this.$t('test_resource_pool.fill_the_data')};
|
||||
this.infoList.forEach(info => {
|
||||
let resultValidate = {
|
||||
validate: true,
|
||||
msg: this.$t("test_resource_pool.fill_the_data"),
|
||||
};
|
||||
this.infoList.forEach((info) => {
|
||||
for (let key in info) {
|
||||
// 排除非必填项
|
||||
if (key === 'nodeSelector' || key === 'apiImage') {
|
||||
if (key === "nodeSelector" || key === "apiImage") {
|
||||
continue;
|
||||
}
|
||||
if (info[key] != '0' && !info[key]) {
|
||||
if (info[key] != "0" && !info[key]) {
|
||||
resultValidate.validate = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -446,11 +623,13 @@ export default {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (resourcePoolType === 'K8S' && info.nodeSelector) {
|
||||
if (resourcePoolType === "K8S" && info.nodeSelector) {
|
||||
let validate = this.isJsonString(info.nodeSelector);
|
||||
if (!validate) {
|
||||
resultValidate.validate = false;
|
||||
resultValidate.msg = this.$t('test_resource_pool.node_selector_invalid');
|
||||
resultValidate.msg = this.$t(
|
||||
"test_resource_pool.node_selector_invalid"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -475,26 +654,32 @@ export default {
|
|||
this.form.resources.forEach(function (resource) {
|
||||
let configuration = JSON.parse(resource.configuration);
|
||||
configuration.id = resource.id;
|
||||
configuration.monitorPort = configuration.monitorPort || '9100';
|
||||
configuration.deployType = configuration.deployType || 'DaemonSet';
|
||||
configuration.deployName = configuration.deployName || 'ms-node-controller';
|
||||
configuration.monitorPort = configuration.monitorPort || "9100";
|
||||
configuration.deployType = configuration.deployType || "DaemonSet";
|
||||
configuration.deployName =
|
||||
configuration.deployName || "ms-node-controller";
|
||||
resources.push(configuration);
|
||||
});
|
||||
}
|
||||
this.infoList = resources;
|
||||
},
|
||||
del(row) {
|
||||
operationConfirm(this, this.$t('test_resource_pool.delete_prompt'), () => {
|
||||
this.loading = delResourcePoolById(row.id).then(() => {
|
||||
this.initTableData();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
})
|
||||
}, () => {
|
||||
this.$info(this.$t('commons.delete_cancel'));
|
||||
})
|
||||
operationConfirm(
|
||||
this,
|
||||
this.$t("test_resource_pool.delete_prompt"),
|
||||
() => {
|
||||
this.loading = delResourcePoolById(row.id).then(() => {
|
||||
this.initTableData();
|
||||
this.$success(this.$t("commons.delete_success"));
|
||||
});
|
||||
},
|
||||
() => {
|
||||
this.$info(this.$t("commons.delete_cancel"));
|
||||
}
|
||||
);
|
||||
},
|
||||
createTestResourcePool() {
|
||||
this.$refs.testResourcePoolForm.validate(valid => {
|
||||
this.$refs.testResourcePoolForm.validate((valid) => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
@ -505,7 +690,7 @@ export default {
|
|||
}
|
||||
this.convertSubmitResources();
|
||||
this.dialogLoading = createResourcePool(this.form).then(() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$success(this.$t("commons.save_success"));
|
||||
this.dialogVisible = false;
|
||||
this.initTableData();
|
||||
});
|
||||
|
@ -516,7 +701,7 @@ export default {
|
|||
let poolId = this.form.id;
|
||||
this.infoList.forEach(function (info) {
|
||||
let configuration = JSON.stringify(info);
|
||||
let resource = {"configuration": configuration, id: info.id};
|
||||
let resource = { configuration: configuration, id: info.id };
|
||||
if (poolId) {
|
||||
resource.testResourcePoolId = poolId;
|
||||
}
|
||||
|
@ -525,7 +710,7 @@ export default {
|
|||
this.form.resources = resources;
|
||||
},
|
||||
updateTestResourcePool() {
|
||||
this.$refs.testResourcePoolForm.validate(valid => {
|
||||
this.$refs.testResourcePoolForm.validate((valid) => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
@ -535,41 +720,47 @@ export default {
|
|||
}
|
||||
this.convertSubmitResources();
|
||||
this.dialogLoading = modifyResourcePool(this.form).then(() => {
|
||||
this.$success(this.$t('commons.modify_success'));
|
||||
this.$success(this.$t("commons.modify_success"));
|
||||
this.dialogVisible = false;
|
||||
this.initTableData();
|
||||
});
|
||||
});
|
||||
},
|
||||
closeFunc() {
|
||||
this.form = {performance: true, api: true, backendListener: true};
|
||||
this.form = { performance: true, api: true, backendListener: true };
|
||||
this.dialogVisible = false;
|
||||
removeGoBackListener(this.closeFunc);
|
||||
},
|
||||
changeSwitch(row) {
|
||||
this.result.loading = true;
|
||||
this.$info(this.$t('test_resource_pool.check_in'), 1000);
|
||||
if (row.status === 'VALID') {
|
||||
this.$info(this.$t("test_resource_pool.check_in"), 1000);
|
||||
if (row.status === "VALID") {
|
||||
this.updatePoolStatus(row);
|
||||
return false;
|
||||
}
|
||||
// 禁用时检查是否有正在使用该资源池的性能测试
|
||||
if (row.status === 'INVALID') {
|
||||
if (row.status === "INVALID") {
|
||||
this.checkHaveTestUsePool(row).then(() => {
|
||||
if (this.updatePool && this.updatePool.haveTestUsePool) {
|
||||
let testIndex = this.updatePool.testName.indexOf(";")
|
||||
let testIndex = this.updatePool.testName.indexOf(";");
|
||||
let subPrompt = this.updatePool.testName.substring(0, testIndex);
|
||||
this.$confirm(this.$t('test_resource_pool.update_prompt', [subPrompt]), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.updatePoolStatus(row);
|
||||
}).catch(() => {
|
||||
row.status = 'VALID';
|
||||
this.result.loading = false;
|
||||
this.$info(this.$t('commons.cancel'));
|
||||
});
|
||||
this.$confirm(
|
||||
this.$t("test_resource_pool.update_prompt", [subPrompt]),
|
||||
this.$t("commons.prompt"),
|
||||
{
|
||||
confirmButtonText: this.$t("commons.confirm"),
|
||||
cancelButtonText: this.$t("commons.cancel"),
|
||||
type: "warning",
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.updatePoolStatus(row);
|
||||
})
|
||||
.catch(() => {
|
||||
row.status = "VALID";
|
||||
this.result.loading = false;
|
||||
this.$info(this.$t("commons.cancel"));
|
||||
});
|
||||
} else {
|
||||
this.updatePoolStatus(row);
|
||||
}
|
||||
|
@ -577,50 +768,62 @@ export default {
|
|||
}
|
||||
},
|
||||
checkHaveTestUsePool(row) {
|
||||
return checkResourcePoolUse(row.id).then(res => {
|
||||
return checkResourcePoolUse(row.id).then((res) => {
|
||||
this.updatePool = res.data;
|
||||
})
|
||||
});
|
||||
},
|
||||
updatePoolStatus(row) {
|
||||
modifyResourcePoolStatus(row.id, row.status).then(() => {
|
||||
this.$success(row.status === 'VALID' ? this.$t('commons.enable_success') : this.$t('commons.disable_success'));
|
||||
}).catch(() => {
|
||||
this.$error(this.$t('test_resource_pool.status_change_failed'));
|
||||
row.status = 'INVALID';
|
||||
})
|
||||
modifyResourcePoolStatus(row.id, row.status)
|
||||
.then(() => {
|
||||
this.$success(
|
||||
row.status === "VALID"
|
||||
? this.$t("commons.enable_success")
|
||||
: this.$t("commons.disable_success")
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.$error(this.$t("test_resource_pool.status_change_failed"));
|
||||
row.status = "INVALID";
|
||||
});
|
||||
},
|
||||
downloadYaml(item, deployType) {
|
||||
if (!item.namespace) {
|
||||
this.$error(this.$t('test_resource_pool.fill_the_data'));
|
||||
this.$error(this.$t("test_resource_pool.fill_the_data"));
|
||||
return;
|
||||
}
|
||||
if (!item.deployName) {
|
||||
this.$error(this.$t('test_resource_pool.fill_the_data'));
|
||||
this.$error(this.$t("test_resource_pool.fill_the_data"));
|
||||
return;
|
||||
}
|
||||
let apiImage = 'registry.cn-qingdao.aliyuncs.com/metersphere/node-controller:' + this.apiImageTag;
|
||||
let apiImage =
|
||||
"registry.cn-qingdao.aliyuncs.com/metersphere/node-controller:" +
|
||||
this.apiImageTag;
|
||||
if (item.apiImage) {
|
||||
apiImage = item.apiImage;
|
||||
}
|
||||
let yaml = getYaml(deployType, item.deployName, item.namespace, apiImage);
|
||||
let blob = new Blob([yaml], {type: 'application/yaml'});
|
||||
let blob = new Blob([yaml], { type: "application/yaml" });
|
||||
let url = URL.createObjectURL(blob);
|
||||
let downloadAnchorNode = document.createElement('a')
|
||||
let downloadAnchorNode = document.createElement("a");
|
||||
downloadAnchorNode.setAttribute("href", url);
|
||||
downloadAnchorNode.setAttribute("download", deployType.toLowerCase() + ".yaml")
|
||||
downloadAnchorNode.setAttribute(
|
||||
"download",
|
||||
deployType.toLowerCase() + ".yaml"
|
||||
);
|
||||
downloadAnchorNode.click();
|
||||
downloadAnchorNode.remove();
|
||||
},
|
||||
getApiImageTag() {
|
||||
getSystemVersion().then(res => {
|
||||
if (!res.data) {
|
||||
this.apiImageTag = 'dev';
|
||||
return;
|
||||
}
|
||||
let i = res.data.lastIndexOf('-');
|
||||
this.apiImageTag = res.data.substring(0, i);
|
||||
}).catch(err => {
|
||||
})
|
||||
getSystemVersion()
|
||||
.then((res) => {
|
||||
if (!res.data) {
|
||||
this.apiImageTag = "dev";
|
||||
return;
|
||||
}
|
||||
let i = res.data.lastIndexOf("-");
|
||||
this.apiImageTag = res.data.substring(0, i);
|
||||
})
|
||||
.catch((err) => {});
|
||||
},
|
||||
isJsonString(str) {
|
||||
try {
|
||||
|
@ -631,15 +834,13 @@ export default {
|
|||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.box {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue