fix(测试跟踪): 优化测试计划内批量编辑接口和场景用例的环境,增加已选环境的反显

--bug=1024643 --user=宋天阳 【测试跟踪】测试计划-接口用例tab-批量编辑接口case页面显示运行环境信息优化
https://www.tapd.cn/55049933/s/1354319
This commit is contained in:
song-tianyang 2023-03-22 13:10:00 +08:00 committed by 建国
parent 1dda504ebb
commit 091c41cccd
3 changed files with 380 additions and 198 deletions

View File

@ -9,43 +9,115 @@
@close="handleClose" @close="handleClose"
append-to-body append-to-body
:close-on-click-modal="false" :close-on-click-modal="false"
v-loading="loading"> v-loading="loading"
<span class="select-row">{{$t('test_track.batch_operate_select_row_count', [size])}}</span> >
<span class="select-row">{{
$t("test_track.batch_operate_select_row_count", [size])
}}</span>
<el-form :model="form" label-position="top" label-width="180px" size="small" ref="form" :rules="rules" style="margin-top: 24px" class="batchEditForm"> <el-form
:model="form"
label-position="top"
label-width="180px"
size="small"
ref="form"
:rules="rules"
style="margin-top: 24px"
class="batchEditForm"
>
<el-form-item :label="$t('test_track.case.select_attr')" prop="type"> <el-form-item :label="$t('test_track.case.select_attr')" prop="type">
<el-select v-model="form.type" style="width: 100%" @change="changeType"> <el-select
<el-option v-for="(type, index) in typeArr" :key="index" :value="type.custom ? type.custom : type.id" v-model="form.type"
:label="type.name"/> style="width: 100%"
@change="changeType"
>
<el-option
v-for="(type, index) in typeArr"
:key="index"
:value="type.custom ? type.custom : type.id"
:label="type.name"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="form.type === 'projectEnv'" :label="$t('test_track.case.batch_update_to')"> <el-form-item
<env-popover :env-map="projectEnvMap" v-if="form.type === 'projectEnv'"
:project-ids="projectIds" :label="$t('test_track.case.batch_update_to')"
@setProjectEnvMap="setProjectEnvMap" >
:show-config-button-with-out-permission="showConfigButtonWithOutPermission" <env-popover
:project-list="projectList" :env-map="projectEnvMap"
:environment-type.sync="environmentType" :project-ids="projectIds"
:group-id="envGroupId" @setProjectEnvMap="setProjectEnvMap"
:is-scenario="false" :show-config-button-with-out-permission="
@setEnvGroup="setEnvGroup" showConfigButtonWithOutPermission
ref="envPopover"/> "
:project-list="projectList"
:environment-type.sync="environmentType"
:group-id="envGroupId"
:is-scenario="false"
@setEnvGroup="setEnvGroup"
ref="envPopover"
/>
<div v-if="showProjectEnv" type="flex" style="margin-top: 5px">
<div
v-for="(values, key) in projectEnvDescMap"
:key="key"
style="margin-right: 10px"
>
<el-row>
{{ key + ":" }}
<ms-tag
:key="values"
type="success"
:content="values"
style="margin-left: 2px"
/>
</el-row>
</div>
</div>
</el-form-item> </el-form-item>
<el-form-item v-else-if="form.type === 'tags'" :label="$t('test_track.case.batch_update_to')"> <el-form-item
<ms-input-tag :currentScenario="form" v-if="showInputTag" ref="tag" class="ms-case-input"></ms-input-tag> v-else-if="form.type === 'tags'"
:label="$t('test_track.case.batch_update_to')"
>
<ms-input-tag
:currentScenario="form"
v-if="showInputTag"
ref="tag"
class="ms-case-input"
></ms-input-tag>
<el-checkbox v-model="form.appendTag"> <el-checkbox v-model="form.appendTag">
{{ $t('commons.append_tag') }} {{ $t("commons.append_tag") }}
<el-tooltip class="item" effect="dark" :content="$t('commons.append_tag_tip')" placement="top"> <el-tooltip
class="item"
effect="dark"
:content="$t('commons.append_tag_tip')"
placement="top"
>
<i class="el-icon-question"></i> <i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
</el-checkbox> </el-checkbox>
</el-form-item> </el-form-item>
<el-form-item v-else-if="form.type === 'reviewers'" :label="$t('test_track.case.batch_update_to')" prop="value"> <el-form-item
<el-select multiple v-model="form.value" style="width: 100%" :filterable="filterable" :disabled="!form.type"> v-else-if="form.type === 'reviewers'"
<el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name"> :label="$t('test_track.case.batch_update_to')"
prop="value"
>
<el-select
multiple
v-model="form.value"
style="width: 100%"
:filterable="filterable"
:disabled="!form.type"
>
<el-option
v-for="(option, index) in options"
:key="index"
:value="option.id"
:label="option.name"
>
<div v-if="option.email"> <div v-if="option.email">
<span>{{ option.id }}({{ option.name }})</span> <span>{{ option.id }}({{ option.name }})</span>
</div> </div>
@ -53,17 +125,40 @@
</el-select> </el-select>
<el-checkbox v-model="form.appendTag"> <el-checkbox v-model="form.appendTag">
{{ $t('commons.append_reviewer') }} {{ $t("commons.append_reviewer") }}
</el-checkbox> </el-checkbox>
</el-form-item> </el-form-item>
<el-form-item v-else-if="fieldType === 'custom'" prop="customFieldValue" :label="$t('test_track.case.batch_update_to')"> <el-form-item
<custom-filed-component v-if="customField" :data="customField" prop="defaultValue"/> v-else-if="fieldType === 'custom'"
prop="customFieldValue"
:label="$t('test_track.case.batch_update_to')"
>
<custom-filed-component
v-if="customField"
:data="customField"
prop="defaultValue"
/>
</el-form-item> </el-form-item>
<el-form-item v-else prop="value" :label="$t('test_track.case.batch_update_to')"> <el-form-item
<el-select v-model="form.value" style="width: 100%" :filterable="filterable" :disabled="!form.type" @change="changeValue"> v-else
<el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name"> prop="value"
:label="$t('test_track.case.batch_update_to')"
>
<el-select
v-model="form.value"
style="width: 100%"
:filterable="filterable"
:disabled="!form.type"
@change="changeValue"
>
<el-option
v-for="(option, index) in options"
:key="index"
:value="option.id"
:label="option.name"
>
<div v-if="option.email"> <div v-if="option.email">
<span>{{ option.id }}({{ option.name }})</span> <span>{{ option.id }}({{ option.name }})</span>
</div> </div>
@ -71,25 +166,48 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="form.type === 'status' && this.showDescription" <el-form-item
:label="$t('commons.description')" :label-width="formLabelWidth" prop="description"> v-if="form.type === 'status' && this.showDescription"
<el-input v-model="form.description" :label="$t('commons.description')"
type="textarea" :label-width="formLabelWidth"
:autosize="{ minRows: 2, maxRows: 4}" prop="description"
:rows="2" >
:placeholder="$t('commons.input_un_pass_reason')"/> <el-input
v-model="form.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
:rows="2"
:placeholder="$t('commons.input_un_pass_reason')"
/>
</el-form-item> </el-form-item>
<el-form-item v-if="form.type === 'reviewStatus'" <el-form-item
:label="$t('原因')" :label-width="formLabelWidth" prop="description"> v-if="form.type === 'reviewStatus'"
<comment-edit-input :placeholder="'请输入原因'" :data="form" ref="commentEditInput"/> :label="$t('原因')"
:label-width="formLabelWidth"
prop="description"
>
<comment-edit-input
:placeholder="'请输入原因'"
:data="form"
ref="commentEditInput"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button @click="dialogVisible = false" size="small">{{ $t('commons.cancel') }}</el-button> <el-button @click="dialogVisible = false" size="small">{{
<el-button v-prevent-re-click :type="!form.type ? 'info' : 'primary'" @click="submit('form')" $t("commons.cancel")
@keydown.enter.native.prevent size="small" :disabled="!form.type" style="margin-left: 12px">{{ $t('commons.confirm') }}</el-button> }}</el-button>
<el-button
v-prevent-re-click
:type="!form.type ? 'info' : 'primary'"
@click="submit('form')"
@keydown.enter.native.prevent
size="small"
:disabled="!form.type"
style="margin-left: 12px"
>{{ $t("commons.confirm") }}</el-button
>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
@ -97,14 +215,18 @@
<script> <script>
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter"; 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 EnvPopover from "@/business/plan/env/EnvPopover"; import EnvPopover from "@/business/plan/env/EnvPopover";
import {ENV_TYPE} from "metersphere-frontend/src/utils/constants"; import MsTag from "metersphere-frontend/src/components/MsTag";
import { ENV_TYPE } from "metersphere-frontend/src/utils/constants";
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent"; import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
import MsInputTag from "metersphere-frontend/src/components/MsInputTag"; import MsInputTag from "metersphere-frontend/src/components/MsInputTag";
import {getOwnerProjects} from "@/business/utils/sdk-utils"; import { getOwnerProjects } from "@/business/utils/sdk-utils";
import {getApiScenarioEnvByProjectId} from "@/api/remote/api/api-automation"; import { getApiScenarioEnvByProjectId } from "@/api/remote/api/api-automation";
import {getCustomField} from "@/api/custom-field"; import { getCustomField } from "@/api/custom-field";
import CommentEditInput from "@/business/review/view/components/commnet/CommentEditInput"; import CommentEditInput from "@/business/review/view/components/commnet/CommentEditInput";
export default { export default {
@ -114,7 +236,8 @@ export default {
CustomFiledComponent, CustomFiledComponent,
EnvPopover, EnvPopover,
MsDialogFooter, MsDialogFooter,
MsInputTag MsInputTag,
MsTag,
}, },
props: { props: {
typeArr: Array, typeArr: Array,
@ -122,8 +245,8 @@ export default {
dialogTitle: { dialogTitle: {
type: String, type: String,
default() { default() {
return this.$t('test_track.case.batch_operate') return this.$t("test_track.case.batch_operate");
} },
}, },
}, },
data() { data() {
@ -134,32 +257,36 @@ export default {
appendTag: true, appendTag: true,
customFieldValue: null, customFieldValue: null,
tags: null, tags: null,
value: null value: null,
}, },
formLabelWidth: "100px", formLabelWidth: "100px",
size: 0, size: 0,
rules: { rules: {
type: {required: true, message: this.$t('test_track.case.please_select_attr'), trigger: ['blur', 'change']}, type: {
required: true,
message: this.$t("test_track.case.please_select_attr"),
trigger: ["blur", "change"],
},
value: { value: {
required: true, required: true,
message: this.$t('test_track.case.please_select_required_value'), message: this.$t("test_track.case.please_select_required_value"),
trigger: ['blur', 'change'] trigger: ["blur", "change"],
}, },
tags: { tags: {
required: true, required: true,
message: this.$t('test_track.case.please_select_required_value'), message: this.$t("test_track.case.please_select_required_value"),
trigger: ['blur', 'change'] trigger: ["blur", "change"],
}, },
customFieldValue: { customFieldValue: {
required: true, required: true,
message: this.$t('test_track.case.please_select_required_value'), message: this.$t("test_track.case.please_select_required_value"),
trigger: ['blur', 'change'] trigger: ["blur", "change"],
}, },
description: { description: {
required: true, required: true,
message: this.$t('test_track.case.please_select_required_value'), message: this.$t("test_track.case.please_select_required_value"),
trigger: ['blur'] trigger: ["blur"],
} },
}, },
options: [], options: [],
filterable: false, filterable: false,
@ -168,26 +295,33 @@ export default {
selectRows: new Set(), selectRows: new Set(),
allDataRows: new Set(), allDataRows: new Set(),
projectEnvMap: new Map(), projectEnvMap: new Map(),
projectEnvDescMap: {},
map: new Map(), map: new Map(),
isScenario: '', isScenario: "",
showDescription: false, showDescription: false,
loading: false, loading: false,
environmentType: ENV_TYPE.JSON, environmentType: ENV_TYPE.JSON,
envGroupId: "", envGroupId: "",
customField: null, customField: null,
fieldType: "", fieldType: "",
showInputTag: true showInputTag: true,
} };
}, },
computed: { computed: {
ENV_TYPE() { ENV_TYPE() {
return ENV_TYPE; return ENV_TYPE;
} },
showProjectEnv() {
return (
this.projectEnvDescMap &&
JSON.stringify(this.projectEnvDescMap) !== "{}"
);
},
}, },
watch: { watch: {
'customField.defaultValue'() { "customField.defaultValue"() {
this.$set(this.form, 'customFieldValue', this.customField.defaultValue); this.$set(this.form, "customFieldValue", this.customField.defaultValue);
} },
}, },
methods: { methods: {
submit(form) { submit(form) {
@ -198,8 +332,8 @@ export default {
this.$refs[form].validate(async (valid) => { this.$refs[form].validate(async (valid) => {
if (valid) { if (valid) {
this.form.projectEnvMap = this.projectEnvMap; this.form.projectEnvMap = this.projectEnvMap;
if (this.form.type === 'projectEnv') { if (this.form.type === "projectEnv") {
if (!await this.$refs.envPopover.checkEnv()) { if (!(await this.$refs.envPopover.checkEnv())) {
return false; return false;
} }
this.form.map = this.map; this.form.map = this.map;
@ -218,14 +352,19 @@ export default {
}); });
}, },
validateReviewStatus() { validateReviewStatus() {
if (this.form.type === 'reviewStatus' && this.form.value === 'UnPass' && !this.form.description) { if (
this.form.type === "reviewStatus" &&
this.form.value === "UnPass" &&
!this.form.description
) {
this.$refs.commentEditInput.inputLight(); this.$refs.commentEditInput.inputLight();
return false; return false;
} }
return true; return true;
}, },
setProjectEnvMap(projectEnvMap) { setProjectEnvMap(projectEnvMap, projectEnvDescMap) {
this.projectEnvMap = projectEnvMap; this.projectEnvMap = projectEnvMap;
this.projectEnvDescMap = projectEnvDescMap;
}, },
setEnvGroup(id) { setEnvGroup(id) {
this.envGroupId = id; this.envGroupId = id;
@ -234,8 +373,8 @@ export default {
this.dialogVisible = true; this.dialogVisible = true;
this.projectEnvMap.clear(); this.projectEnvMap.clear();
this.form = { this.form = {
appendTag: true appendTag: true,
} };
if (size) { if (size) {
this.size = size; this.size = size;
} else { } else {
@ -247,9 +386,9 @@ export default {
setSelectRows(rows) { setSelectRows(rows) {
this.selectRows = rows; this.selectRows = rows;
this.projectIds.clear(); this.projectIds.clear();
this.selectRows.forEach(row => { this.selectRows.forEach((row) => {
this.projectIds.add(row.projectId) this.projectIds.add(row.projectId);
}) });
}, },
setScenarioSelectRows(rows, sign) { setScenarioSelectRows(rows, sign) {
this.selectRows = rows; this.selectRows = rows;
@ -269,27 +408,29 @@ export default {
let id = val.slice(6); let id = val.slice(6);
this.fieldType = "custom"; this.fieldType = "custom";
this.loading = true; this.loading = true;
getCustomField(id) getCustomField(id).then((res) => {
.then(res => { this.loading = false;
this.loading = false; if (res) {
if (res) { res.data.defaultValue = null;
res.data.defaultValue = null; this.customField = res.data;
this.customField = res.data; } else {
} else { this.customField = { defaultValue: null };
this.customField = {defaultValue: null}; }
} this.customField.options = JSON.parse(this.customField.options);
this.customField.options = JSON.parse(this.customField.options); if (
if (this.customField.type === 'checkbox' || this.customField.type === 'multipleMember') { this.customField.type === "checkbox" ||
this.customField.defaultValue = []; this.customField.type === "multipleMember"
} ) {
}); this.customField.defaultValue = [];
}
});
}, },
changeType(val) { changeType(val) {
this.showDescription = false; this.showDescription = false;
if (val && val.startsWith("custom")) { if (val && val.startsWith("custom")) {
this._handleCustomField(val); this._handleCustomField(val);
} }
if (val === 'tags') { if (val === "tags") {
// form rules // form rules
this.$set(this.form, "value", "tags"); this.$set(this.form, "value", "tags");
} else { } else {
@ -298,7 +439,7 @@ export default {
this.filterable = val === "maintainer" || val === "executor"; this.filterable = val === "maintainer" || val === "executor";
this.options = this.valueArr[val]; this.options = this.valueArr[val];
this.typeArr.forEach(item => { this.typeArr.forEach((item) => {
if (item.id === val) { if (item.id === val) {
if (item.optionMethod) { if (item.optionMethod) {
this.options = []; this.options = [];
@ -307,35 +448,35 @@ export default {
return; return;
} }
}); });
this.typeArr.forEach(item => { this.typeArr.forEach((item) => {
if (item.id === val && item.uuid) { if (item.id === val && item.uuid) {
this.$set(this.form, "id", item.uuid); this.$set(this.form, "id", item.uuid);
} }
}); });
if (val === 'projectEnv' && this.isScenario !== '') { if (val === "projectEnv" && this.isScenario !== "") {
this.projectIds.clear(); this.projectIds.clear();
this.map.clear(); this.map.clear();
if (this.allDataRows != null && this.allDataRows.length > 0) { if (this.allDataRows != null && this.allDataRows.length > 0) {
this.allDataRows.forEach(row => { this.allDataRows.forEach((row) => {
this.getApiScenarioProjectId(row); this.getApiScenarioProjectId(row);
}); });
} else { } else {
this.selectRows.forEach(row => { this.selectRows.forEach((row) => {
this.getApiScenarioProjectId(row); this.getApiScenarioProjectId(row);
}) });
} }
} }
}, },
changeValue(val) { changeValue(val) {
if (val === 'UnPass') { if (val === "UnPass") {
this.showDescription = true; this.showDescription = true;
} else { } else {
this.showDescription = false; this.showDescription = false;
} }
if (this.form.type === 'reviewStatus') { if (this.form.type === "reviewStatus") {
if (val === 'UnPass') { if (val === "UnPass") {
this.rules.description.required = true; this.rules.description.required = true;
} else { } else {
this.rules.description.required = false; this.rules.description.required = false;
@ -343,34 +484,32 @@ export default {
} }
}, },
getApiScenarioProjectId(row) { getApiScenarioProjectId(row) {
let id = this.isScenario === 'scenario' ? row.id : row.caseId; let id = this.isScenario === "scenario" ? row.id : row.caseId;
this.loading = true; this.loading = true;
getApiScenarioEnvByProjectId(id) getApiScenarioEnvByProjectId(id).then((res) => {
.then(res => { this.loading = false;
this.loading = false; let data = res.data;
let data = res.data; data.projectIds.forEach((d) => this.projectIds.add(d));
data.projectIds.forEach(d => this.projectIds.add(d)); this.map.set(row.id, data.projectIds);
this.map.set(row.id, data.projectIds); });
});
}, },
getWsProjects() { getWsProjects() {
getOwnerProjects() getOwnerProjects().then((res) => {
.then(res => { this.projectList = res.data;
this.projectList = res.data; });
});
}, },
} },
} };
</script> </script>
<style scoped> <style scoped>
.select-row { .select-row {
font-family: 'PingFang SC'; font-family: "PingFang SC";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
color: #646A73; color: #646a73;
flex: none; flex: none;
order: 1; order: 1;
align-self: center; align-self: center;
@ -378,12 +517,12 @@ export default {
} }
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
font-family: 'PingFang SC'; font-family: "PingFang SC";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
color: #1F2329; color: #1f2329;
flex: none; flex: none;
order: 0; order: 0;
flex-grow: 0; flex-grow: 0;
@ -391,7 +530,7 @@ export default {
} }
:deep(.el-button--small span) { :deep(.el-button--small span) {
font-family: 'PingFang SC'; font-family: "PingFang SC";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-size: 14px; font-size: 14px;
@ -416,19 +555,19 @@ export default {
.batchEditForm :deep(.el-form-item.is-required > .el-form-item__label:after) { .batchEditForm :deep(.el-form-item.is-required > .el-form-item__label:after) {
content: "*"; content: "*";
color: #F56C6C; color: #f56c6c;
margin-right: 4px; margin-right: 4px;
} }
.ms-case-input :deep(.el-tag.el-tag--info) { .ms-case-input :deep(.el-tag.el-tag--info) {
background-color: rgba(31, 35, 41, 0.1); background-color: rgba(31, 35, 41, 0.1);
font-family: 'PingFang SC'; font-family: "PingFang SC";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
align-items: center; align-items: center;
color: #1F2329; color: #1f2329;
flex: none; flex: none;
order: 1; order: 1;
flex-grow: 0; flex-grow: 0;
@ -442,7 +581,7 @@ export default {
} }
.ms-case-input :deep(.el-tag.el-tag--info .el-icon-close:hover) { .ms-case-input :deep(.el-tag.el-tag--info .el-icon-close:hover) {
color: #783887;; color: #783887;
background-color: transparent; background-color: transparent;
} }
</style> </style>

View File

@ -5,60 +5,70 @@
width="400" width="400"
:disabled="isReadOnly" :disabled="isReadOnly"
@show="showPopover" @show="showPopover"
trigger="click"> trigger="click"
<env-select :project-ids="projectIds" :env-map="envMap" @close="visible = false" >
:show-config-button-with-out-permission="showConfigButtonWithOutPermission" <env-select
ref="envSelect" @setProjectEnvMap="setProjectEnvMap" :project-list="projectList"/> :project-ids="projectIds"
<el-button type="primary" slot="reference" size="mini" style="margin-top: 2px;"> :env-map="envMap"
{{ $t('api_test.definition.request.run_env') }} @close="visible = false"
:show-config-button-with-out-permission="
showConfigButtonWithOutPermission
"
ref="envSelect"
@setProjectEnvMap="setProjectEnvMap"
:project-list="projectList"
/>
<el-button
type="primary"
slot="reference"
size="mini"
style="margin-top: 2px"
>
{{ $t("api_test.definition.request.run_env") }}
<i class="el-icon-caret-bottom el-icon--right"></i> <i class="el-icon-caret-bottom el-icon--right"></i>
</el-button> </el-button>
</el-popover> </el-popover>
</template> </template>
<script> <script>
import EnvSelect from "@/business/plan/env/EnvSelect"; import EnvSelect from "@/business/plan/env/EnvSelect";
export default { export default {
name: "EnvPopover", name: "EnvPopover",
components: {EnvSelect}, components: { EnvSelect },
props: { props: {
envMap: Map, envMap: Map,
projectIds: Set, projectIds: Set,
projectList: Array, projectList: Array,
showConfigButtonWithOutPermission:{ showConfigButtonWithOutPermission: {
type: Boolean, type: Boolean,
default() { default() {
return true; return true;
} },
}, },
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default() { default() {
return false; return false;
} },
} },
}, },
data() { data() {
return { return {
visible: false visible: false,
}; };
}, },
methods: { methods: {
showPopover() { showPopover() {
this.$refs.envSelect.open(); this.$refs.envSelect.open();
}, },
setProjectEnvMap(map) { setProjectEnvMap(map, groupDescMap) {
this.$emit("setProjectEnvMap", map); this.$emit("setProjectEnvMap", map, groupDescMap);
}, },
checkEnv() { checkEnv() {
return this.$refs.envSelect.checkEnv(); return this.$refs.envSelect.checkEnv();
} },
} },
}; };
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@ -1,20 +1,41 @@
<template> <template>
<div v-loading="result.loading"> <div v-loading="result.loading">
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;"> <div v-for="pe in data" :key="pe.id" style="margin-left: 20px">
<el-select v-model="pe['selectEnv']" filterable :placeholder="$t('api_test.environment.select_environment')" <el-select
style="margin-top: 8px;width: 200px;" size="small"> v-model="pe['selectEnv']"
<el-option v-for="(environment, index) in pe.envs" :key="index" filterable
:label="environment.name" :placeholder="$t('api_test.environment.select_environment')"
:value="environment.id"/> style="margin-top: 8px; width: 200px"
<el-button class="ms-scenario-button" v-if="isShowConfirmButton(pe.id)" size="mini" type="primary" size="small"
@click="openEnvironmentConfig(pe.id)"> >
{{ $t('api_test.environment.environment_config') }} <el-option
v-for="(environment, index) in pe.envs"
:key="index"
:label="environment.name"
:value="environment.id"
/>
<el-button
class="ms-scenario-button"
v-if="isShowConfirmButton(pe.id)"
size="mini"
type="primary"
@click="openEnvironmentConfig(pe.id)"
>
{{ $t("api_test.environment.environment_config") }}
</el-button> </el-button>
<template v-slot:empty> <template v-slot:empty>
<!--这里只做没有可搜索内容时使用否则如果没有符合搜索条件的也会显示该项与上面的btn重复显示 --> <!--这里只做没有可搜索内容时使用否则如果没有符合搜索条件的也会显示该项与上面的btn重复显示 -->
<div v-if="isShowConfirmButton(pe.id) && pe.envs.length===0" class="empty-environment"> <div
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)"> v-if="isShowConfirmButton(pe.id) && pe.envs.length === 0"
{{ $t('api_test.environment.environment_config') }} class="empty-environment"
>
<el-button
class="ms-scenario-button"
size="mini"
type="primary"
@click="openEnvironmentConfig(pe.id)"
>
{{ $t("api_test.environment.environment_config") }}
</el-button> </el-button>
</div> </div>
</template> </template>
@ -24,24 +45,32 @@
</span> </span>
</div> </div>
<el-button type="primary" @click="handleConfirm" size="small" class="env-confirm">{{ $t('commons.confirm') }} <el-button
type="primary"
@click="handleConfirm"
size="small"
class="env-confirm"
>{{ $t("commons.confirm") }}
</el-button> </el-button>
<!-- 环境配置 --> <!-- 环境配置 -->
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/> <api-environment-config
ref="environmentConfig"
@close="environmentConfigClose"
/>
</div> </div>
</template> </template>
<script> <script>
import {parseEnvironment} from "metersphere-frontend/src/model/EnvironmentModel"; import { parseEnvironment } from "metersphere-frontend/src/model/EnvironmentModel";
import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig"; import ApiEnvironmentConfig from "metersphere-frontend/src/components/environment/ApiEnvironmentConfig";
import {getOwnerProjectIds} from "@/api/project"; import { getOwnerProjectIds } from "@/api/project";
import {getEnvironmentByProjectId} from "@/api/remote/api/api-environment"; import { getEnvironmentByProjectId } from "@/api/remote/api/api-environment";
export default { export default {
name: "EnvSelect", name: "EnvSelect",
components: { components: {
ApiEnvironmentConfig ApiEnvironmentConfig,
}, },
props: { props: {
envMap: Map, envMap: Map,
@ -50,14 +79,14 @@ export default {
type: Boolean, type: Boolean,
default() { default() {
return true; return true;
} },
}, },
projectList: Array projectList: Array,
}, },
data() { data() {
return { return {
data: [], data: [],
result: {loading: false}, result: { loading: false },
projects: [], projects: [],
environments: [], environments: [],
permissionProjectIds: [], permissionProjectIds: [],
@ -87,28 +116,28 @@ export default {
this.getUserPermissionProjectIds(); this.getUserPermissionProjectIds();
} }
this.projectIds.forEach(id => { this.projectIds.forEach((id) => {
const project = this.projectList.find(p => p.id === id); const project = this.projectList.find((p) => p.id === id);
if (project) { if (project) {
let item = {id: id, envs: [], selectEnv: ""}; let item = { id: id, envs: [], selectEnv: "" };
this.data.push(item); this.data.push(item);
this.result.loading = true; this.result.loading = true;
getEnvironmentByProjectId(id) getEnvironmentByProjectId(id).then((res) => {
.then(res => { this.result.loading = false;
this.result.loading = false; let envs = res.data;
let envs = res.data; envs.forEach((environment) => {
envs.forEach(environment => { parseEnvironment(environment);
parseEnvironment(environment);
});
//
let temp = this.data.find(dt => dt.id === id);
temp.envs = envs;
if (this.envMap && this.envMap.size > 0) {
let envId = this.envMap.get(id);
//
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
}
}); });
//
let temp = this.data.find((dt) => dt.id === id);
temp.envs = envs;
if (this.envMap && this.envMap.size > 0) {
let envId = this.envMap.get(id);
//
temp.selectEnv =
envs.filter((e) => e.id === envId).length === 0 ? null : envId;
}
});
} }
}); });
}, },
@ -119,12 +148,12 @@ export default {
} }
}, },
getProjectName(id) { getProjectName(id) {
const project = this.projectList.find(p => p.id === id); const project = this.projectList.find((p) => p.id === id);
return project ? project.name : ""; return project ? project.name : "";
}, },
openEnvironmentConfig(projectId) { openEnvironmentConfig(projectId) {
if (!projectId) { if (!projectId) {
this.$error(this.$t('api_test.select_project')); this.$error(this.$t("api_test.select_project"));
return; return;
} }
this.$refs.environmentConfig.open(projectId); this.$refs.environmentConfig.open(projectId);
@ -132,25 +161,30 @@ export default {
handleConfirm() { handleConfirm() {
let map = new Map(); let map = new Map();
let sign = true; let sign = true;
this.data.forEach(dt => { let projectEnvDesc = {};
this.data.forEach((dt) => {
if (!dt.selectEnv) { if (!dt.selectEnv) {
sign = false; sign = false;
return; return;
} }
map.set(dt.id, dt.selectEnv); map.set(dt.id, dt.selectEnv);
let filteredEnv = dt.envs.filter((e) => e.id === dt.selectEnv);
if (filteredEnv.length > 0) {
projectEnvDesc[this.getProjectName(dt.id)] = filteredEnv[0].name;
}
}); });
if (!sign) { if (!sign) {
this.$warning("请为当前场景选择一个运行环境!"); this.$warning("请为当前场景选择一个运行环境!");
return; return;
} }
this.$emit('setProjectEnvMap', map); this.$emit("setProjectEnvMap", map, projectEnvDesc);
this.$emit('close'); this.$emit("close");
}, },
checkEnv() { checkEnv() {
let sign = true; let sign = true;
this.isFullUrl = true; this.isFullUrl = true;
if (this.data.length > 0) { if (this.data.length > 0) {
this.data.forEach(dt => { this.data.forEach((dt) => {
if (!dt.selectEnv) { if (!dt.selectEnv) {
sign = false; sign = false;
return false; return false;
@ -159,7 +193,7 @@ export default {
} else { } else {
// //
if (this.envMap && this.envMap.size > 0) { if (this.envMap && this.envMap.size > 0) {
this.projectIds.forEach(id => { this.projectIds.forEach((id) => {
if (!this.envMap.get(id)) { if (!this.envMap.get(id)) {
sign = false; sign = false;
return false; return false;
@ -180,12 +214,11 @@ export default {
// todo // todo
}, },
getUserPermissionProjectIds() { getUserPermissionProjectIds() {
getOwnerProjectIds() getOwnerProjectIds().then((res) => {
.then(res => { this.permissionProjectIds = res.data;
this.permissionProjectIds = res.data; });
});
}, },
} },
}; };
</script> </script>