fix(接口测试): 环境配置-通用配置相关问题修复

This commit is contained in:
RubyLiu 2023-12-19 17:57:25 +08:00 committed by 刘瑞斌
parent ab8607555f
commit d065f461f3
1 changed files with 306 additions and 163 deletions

View File

@ -7,7 +7,8 @@
size="mini" size="mini"
v-model="selectVariable" v-model="selectVariable"
@change="filter" @change="filter"
@keyup.enter="filter"> @keyup.enter="filter"
>
</el-input> </el-input>
</div> </div>
<div style="padding-bottom: 10px; float: right"> <div style="padding-bottom: 10px; float: right">
@ -15,20 +16,33 @@
v-permission="['PROJECT_ENVIRONMENT:READ+IMPORT']" v-permission="['PROJECT_ENVIRONMENT:READ+IMPORT']"
icon="el-icon-box" icon="el-icon-box"
:content="$t('commons.import')" :content="$t('commons.import')"
@click="importJSON"/> @click="importJSON"
/>
<el-dropdown <el-dropdown
@command="handleExportCommand" @command="handleExportCommand"
class="scenario-ext-btn" class="scenario-ext-btn"
trigger="hover" trigger="hover"
v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']"> v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']"
<ms-table-button style="margin-left: 10px" icon="el-icon-box" :content="$t('commons.export')"/> >
<ms-table-button
style="margin-left: 10px"
icon="el-icon-box"
:content="$t('commons.export')"
/>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="exportApi">{{ $t('envrionment.export_variable_tip') }}</el-dropdown-item> <el-dropdown-item command="exportApi">{{
$t("envrionment.export_variable_tip")
}}</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<el-link style="margin-left: 10px" @click="batchAdd" type="primary" :disabled="isReadOnly"> <el-link
{{ $t('commons.batch_add') }} style="margin-left: 10px"
@click="batchAdd"
type="primary"
:disabled="isReadOnly"
>
{{ $t("commons.batch_add") }}
</el-link> </el-link>
</div> </div>
</div> </div>
@ -40,7 +54,8 @@
width: 99%; width: 99%;
margin-top: 10px; margin-top: 10px;
clear: both; clear: both;
"> "
>
<ms-table <ms-table
v-loading="loading" v-loading="loading"
row-key="id" row-key="id"
@ -55,26 +70,39 @@
:condition="condition" :condition="condition"
@filter="filter" @filter="filter"
@refresh="onChange" @refresh="onChange"
ref="variableTable"> ref="variableTable"
>
<ms-table-column prop="num" sortable label="ID" min-width="60" /> <ms-table-column prop="num" sortable label="ID" min-width="60" />
<ms-table-column <ms-table-column
prop="scope" prop="scope"
sortable sortable
:label="$t('commons.scope')" :label="$t('commons.scope')"
:filters="scopeTypeFilters" :filters="scopeTypeFilters"
min-width="120"> min-width="120"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-select <el-select
v-model="scope.row.scope" v-model="scope.row.scope"
:placeholder="$t('commons.please_select')" :placeholder="$t('commons.please_select')"
size="mini" size="mini"
@change="changeType(scope.row)"> @change="changeType($event, scope.row)"
<el-option v-for="item in scopeTypeFilters" :key="item.value" :label="item.text" :value="item.value"/> >
<el-option
v-for="item in scopeTypeFilters"
:key="item.value"
:label="item.text"
:value="item.value"
/>
</el-select> </el-select>
</template> </template>
</ms-table-column> </ms-table-column>
<ms-table-column prop="name" :label="$t('api_test.variable_name')" min-width="200" sortable> <ms-table-column
prop="name"
:label="$t('api_test.variable_name')"
min-width="200"
sortable
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-model="scope.row.name" v-model="scope.row.name"
@ -82,31 +110,55 @@
maxlength="200" maxlength="200"
:placeholder="$t('api_test.variable_name')" :placeholder="$t('api_test.variable_name')"
show-word-limit show-word-limit
@change="change"/> @change="change"
/>
</template> </template>
</ms-table-column> </ms-table-column>
<ms-table-column prop="type" :label="$t('test_track.case.type')" min-width="140" sortable> <ms-table-column
prop="type"
:label="$t('test_track.case.type')"
min-width="140"
sortable
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-select <el-select
v-model="scope.row.type" v-model="scope.row.type"
v-if="!scope.row.scope || scope.row.scope == 'api'" v-if="!scope.row.scope || scope.row.scope == 'api'"
:placeholder="$t('commons.please_select')" :placeholder="$t('commons.please_select')"
size="mini" size="mini"
@change="changeType(scope.row)"> @change="changeType($event, scope.row)"
<el-option v-for="item in typeSelectOptions" :key="item.value" :label="item.label" :value="item.value"/> >
<el-option
v-for="item in typeSelectOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<el-select v-else v-model="scope.row.type" :placeholder="$t('commons.please_select')" size="mini"> <el-select
v-else
v-model="scope.row.type"
:placeholder="$t('commons.please_select')"
size="mini"
>
<el-option <el-option
v-for="item in uiTypeSelectOptions" v-for="item in uiTypeSelectOptions"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value"/> :value="item.value"
/>
</el-select> </el-select>
</template> </template>
</ms-table-column> </ms-table-column>
<el-table-column prop="value" :label="$t('api_test.value')" min-width="200px" sortable show-overflow-tooltip> <ms-table-column
prop="value"
:label="$t('api_test.value')"
min-width="200px"
sortable
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-model="scope.row.value" v-model="scope.row.value"
@ -114,20 +166,39 @@
v-if="scope.row.type !== 'CSV'" v-if="scope.row.type !== 'CSV'"
:placeholder="valueText(scope.row)" :placeholder="valueText(scope.row)"
@change="changeVariableVal(scope.row)" @change="changeVariableVal(scope.row)"
:disabled="scope.row.type === 'COUNTER' || scope.row.type === 'RANDOM'"/> :disabled="
<csv-file-upload :parameter="scope.row" v-if="scope.row.type === 'CSV'"/> scope.row.type === 'COUNTER' || scope.row.type === 'RANDOM'
"
/>
<csv-file-upload
:parameter="scope.row"
v-if="scope.row.type === 'CSV'"
/>
</template> </template>
</el-table-column> </ms-table-column>
<ms-table-column prop="description" :label="$t('commons.remark')" min-width="160" sortable> <ms-table-column
prop="description"
:label="$t('commons.remark')"
min-width="160"
sortable
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.description" size="mini"/> <el-input
v-model="scope.row.description"
@change="descriptionChange(scope.row)"
size="mini"
/>
</template> </template>
</ms-table-column> </ms-table-column>
<ms-table-column :label="$t('commons.operating')" width="150"> <ms-table-column :label="$t('commons.operating')" width="150">
<template v-slot:default="scope"> <template v-slot:default="scope">
<span> <span>
<el-switch v-model="scope.row.enable" size="mini"/> <el-switch
v-model="scope.row.enable"
size="mini"
@change="enableChange(scope.row)"
/>
<el-button <el-button
icon="el-icon-delete" icon="el-icon-delete"
type="danger" type="danger"
@ -135,15 +206,20 @@
size="mini" size="mini"
style="margin-left: 10px" style="margin-left: 10px"
@click="remove(scope.row)" @click="remove(scope.row)"
v-if="isDisable(scope.row)"/> v-if="isDisable(scope.row)"
/>
<el-button <el-button
v-if="(!scope.row.scope || scope.row.scope == 'api') && scope.row.type !== 'LIST'" v-if="
(!scope.row.scope || scope.row.scope == 'api') &&
scope.row.type !== 'LIST'
"
icon="el-icon-setting" icon="el-icon-setting"
circle circle
size="mini" size="mini"
style="margin-left: 10px" style="margin-left: 10px"
@click="openSetting(scope.row)" @click="openSetting(scope.row)"
@blur="change"/> @blur="change"
/>
</span> </span>
</template> </template>
</ms-table-column> </ms-table-column>
@ -152,30 +228,37 @@
:change="queryPage" :change="queryPage"
:current-page.sync="currentPage" :current-page.sync="currentPage"
:page-size.sync="pageSize" :page-size.sync="pageSize"
:total="total"/> :total="total"
/>
</div> </div>
<batch-add-parameter @batchSave="batchSave" ref="batchAdd" /> <batch-add-parameter @batchSave="batchSave" ref="batchAdd" />
<api-variable-setting ref="apiVariableSetting" @changeData="change"></api-variable-setting> <api-variable-setting
<variable-import ref="variableImport" @mergeData="mergeData"></variable-import> ref="apiVariableSetting"
@changeData="change"
></api-variable-setting>
<variable-import
ref="variableImport"
@mergeData="mergeData"
></variable-import>
</div> </div>
</template> </template>
<script> <script>
import {KeyValue} from '../../../model/EnvTestModel'; import { KeyValue } from "../../../model/EnvTestModel";
import MsApiVariableInput from './ApiVariableInput'; import MsApiVariableInput from "./ApiVariableInput";
import BatchAddParameter from './BatchAddParameter'; import BatchAddParameter from "./BatchAddParameter";
import MsTableButton from '../../MsTableButton'; import MsTableButton from "../../MsTableButton";
import MsTable from '../../table/MsTable'; import MsTable from "../../table/MsTable";
import MsTableColumn from '../../table/MsTableColumn'; import MsTableColumn from "../../table/MsTableColumn";
import ApiVariableSetting from './ApiVariableSetting'; import ApiVariableSetting from "./ApiVariableSetting";
import CsvFileUpload from './variable/CsvFileUpload'; import CsvFileUpload from "./variable/CsvFileUpload";
import {downloadFile, getUUID, operationConfirm} from '../../../utils'; import { downloadFile, getUUID, operationConfirm } from "../../../utils";
import VariableImport from './variable/VariableImport'; import VariableImport from "./variable/VariableImport";
import {forEach} from 'lodash-es'; import { forEach } from "lodash-es";
import MsTablePagination from '../../pagination/TablePagination'; import MsTablePagination from "../../pagination/TablePagination";
export default { export default {
name: 'MsApiScenarioVariables', name: "MsApiScenarioVariables",
components: { components: {
BatchAddParameter, BatchAddParameter,
MsApiVariableInput, MsApiVariableInput,
@ -209,34 +292,34 @@ export default {
total: 0, total: 0,
loading: false, loading: false,
refreshOver: true, refreshOver: true,
screenHeight: '460px', screenHeight: "460px",
batchButtons: [ batchButtons: [
{ {
name: this.$t('api_test.definition.request.batch_delete'), name: this.$t("api_test.definition.request.batch_delete"),
handleClick: this.handleDeleteBatch, handleClick: this.handleDeleteBatch,
}, },
], ],
typeSelectOptions: [ typeSelectOptions: [
{value: 'CONSTANT', label: this.$t('api_test.automation.constant')}, { value: "CONSTANT", label: this.$t("api_test.automation.constant") },
{value: 'LIST', label: this.$t('test_track.case.list')}, { value: "LIST", label: this.$t("test_track.case.list") },
{value: 'CSV', label: 'CSV'}, { value: "CSV", label: "CSV" },
{value: 'COUNTER', label: this.$t('api_test.automation.counter')}, { value: "COUNTER", label: this.$t("api_test.automation.counter") },
{value: 'RANDOM', label: this.$t('api_test.automation.random')}, { value: "RANDOM", label: this.$t("api_test.automation.random") },
], ],
uiTypeSelectOptions: [ uiTypeSelectOptions: [
{value: 'STRING', label: this.$t('api_test.automation.string')}, { value: "STRING", label: this.$t("api_test.automation.string") },
{value: 'ARRAY', label: this.$t('api_test.automation.array')}, { value: "ARRAY", label: this.$t("api_test.automation.array") },
{value: 'JSON', label: this.$t('api_test.automation.json')}, { value: "JSON", label: this.$t("api_test.automation.json") },
{value: 'NUMBER', label: this.$t('api_test.automation.number')}, { value: "NUMBER", label: this.$t("api_test.automation.number") },
], ],
pageData: [], pageData: [],
selectVariable: '', selectVariable: "",
editData: {}, editData: {},
allData: [], allData: [],
lastPage: 1, lastPage: 1,
scopeTypeFilters: [ scopeTypeFilters: [
{text: this.$t('commons.api'), value: 'api'}, { text: this.$t("commons.api"), value: "api" },
{text: this.$t('commons.ui_test'), value: 'ui'}, { text: this.$t("commons.ui_test"), value: "ui" },
], ],
condition: { condition: {
selectAll: false, selectAll: false,
@ -281,85 +364,133 @@ export default {
delete item.hashTree; delete item.hashTree;
}); });
}, },
// change
change: function () { change: function () {
let isNeedCreate = true; let isNeedCreate = true;
let removeIndex = -1; let removeIndex = -1;
let repeatKey = ''; let repeatKey = "";
const itemNames = new Set();
this.items.forEach((item, index) => { this.items.forEach((item, index) => {
this.items.forEach((row, rowIndex) => { // name
if (item.name === row.name && index !== rowIndex) { if (itemNames.has(item.name)) {
repeatKey = item.name; repeatKey = item.name;
} else {
itemNames.add(item.name);
} }
});
//
if (!item.name && !item.value) { if (!item.name && !item.value) {
// removeIndex = index !== this.items.length - 1 ? index : removeIndex;
if (index !== this.items.length - 1) {
removeIndex = index;
}
//
isNeedCreate = false; isNeedCreate = false;
} }
}); });
if (repeatKey !== '') {
// name
if (repeatKey !== "") {
this.$warning( this.$warning(
this.$t('api_test.environment.common_config') + `${this.$t(
'【' + "api_test.environment.common_config"
repeatKey + )}${repeatKey}${this.$t("load_test.param_is_duplicate")}`
'】' +
this.$t('load_test.param_is_duplicate')
); );
} }
//
if (removeIndex !== -1) {
this.items.splice(removeIndex, 1);
}
//
if (isNeedCreate) { if (isNeedCreate) {
this.items.push(new KeyValue({enable: true, id: getUUID(), type: 'CONSTANT', scope: 'api'})); this.items.push(
new KeyValue({
enable: true,
id: getUUID(),
type: "CONSTANT",
scope: "api",
})
);
this.currentPage = Math.ceil(this.allData.length / this.pageSize); this.currentPage = Math.ceil(this.allData.length / this.pageSize);
} }
//
//
this.allData = []; this.allData = [];
this._filter(); this._filter();
this.queryPage(); this.queryPage();
this.$emit('change', this.items);
},
changeType(data) {
data.value = '';
if (!data.delimiter || (!data.files && data.files.length === 0) || !data.quotedData) {
data.delimiter = ',';
data.files = [];
data.quotedData = 'false';
}
if (!data.scope || data.scope == 'ui') { //
data.type = 'STRING'; this.$emit("change", this.items);
},
changeType(value, data) {
data.value = "";
if (
!data.delimiter ||
(!data.files && data.files.length === 0) ||
!data.quotedData
) {
data.delimiter = ",";
data.files = [];
data.quotedData = "false";
} }
if (!data.scope || data.scope == "ui") {
data.type = "STRING";
}
this.items.forEach((item) => {
if (item.name === data.name) {
item.scope = value;
item.type = data.type;
item.value = data.value;
}
});
}, },
changeVariableVal(data) { changeVariableVal(data) {
this.items.forEach(item => { this.items.forEach((item) => {
if (item.name === data.name) { if (item.name === data.name) {
item.value = data.value; item.value = data.value;
} }
}) });
},
//
descriptionChange(data) {
this.items.forEach((item) => {
if (item.name === data.name) {
item.description = data.description;
}
});
},
//
enableChange(data) {
this.items.forEach((item) => {
if (item.name === data.name) {
item.enable = data.enable;
}
});
}, },
valueText(data) { valueText(data) {
switch (data.type) { switch (data.type) {
case 'LIST': case "LIST":
return this.$t('api_test.environment.list_info'); return this.$t("api_test.environment.list_info");
case 'CONSTANT': case "CONSTANT":
return this.$t('api_test.value'); return this.$t("api_test.value");
case 'COUNTER': case "COUNTER":
case 'RANDOM': case "RANDOM":
return this.$t('api_test.environment.advanced_setting'); return this.$t("api_test.environment.advanced_setting");
default: default:
return this.$t('api_test.value'); return this.$t("api_test.value");
} }
}, },
querySearch(queryString, cb) { querySearch(queryString, cb) {
let restaurants = [ let restaurants = [
{value: 'UTF-8'}, { value: "UTF-8" },
{value: 'UTF-16'}, { value: "UTF-16" },
{value: 'GB2312'}, { value: "GB2312" },
{value: 'ISO-8859-15'}, { value: "ISO-8859-15" },
{value: 'US-ASCll'}, { value: "US-ASCll" },
]; ];
let results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants; let results = queryString
? restaurants.filter(this.createFilter(queryString))
: restaurants;
// callback // callback
cb(results); cb(results);
}, },
@ -367,33 +498,35 @@ export default {
let index = 1; let index = 1;
this.allData.forEach((item) => { this.allData.forEach((item) => {
item.num = index; item.num = index;
if (!item.type || item.type === 'text') { if (!item.type || item.type === "text") {
item.type = 'CONSTANT'; item.type = "CONSTANT";
} }
if (!item.id) { if (!item.id) {
item.id = getUUID(); item.id = getUUID();
} }
if (item.remark) { if (item.remark) {
this.$set(item, 'description', item.remark); this.$set(item, "description", item.remark);
item.remark = undefined; item.remark = undefined;
} }
if (!item.scope) { if (!item.scope) {
this.$set(item, 'scope', 'api'); this.$set(item, "scope", "api");
} }
index++; index++;
}); });
}, },
handleDeleteBatch() { handleDeleteBatch() {
operationConfirm(this, this.$t('api_test.environment.variables_delete_info') + ' ', () => { operationConfirm(
this,
this.$t("api_test.environment.variables_delete_info") + " ",
() => {
if (this.condition.selectAll) { if (this.condition.selectAll) {
let deleteIndex = 0;
let deleteRows = this.items.filter((item) => { let deleteRows = this.items.filter((item) => {
return this.condition.unSelectIds.indexOf(item.id) < 0; return this.condition.unSelectIds.indexOf(item.id) < 0;
}); });
deleteRows.forEach(deleteRow => { deleteRows.forEach((deleteRow) => {
const index = this.items.findIndex((d) => d.id === deleteRow.id); const index = this.items.findIndex((d) => d.id === deleteRow.id);
this.items.splice(index, 1); this.items.splice(index, 1);
}) });
this.allData = this.items; this.allData = this.items;
this.currentPage = 1; this.currentPage = 1;
this.queryPage(); this.queryPage();
@ -418,8 +551,8 @@ export default {
this.pageData.forEach((item) => { this.pageData.forEach((item) => {
item.showMore = false; item.showMore = false;
}); });
}
}); );
}, },
filter() { filter() {
// //
@ -432,12 +565,16 @@ export default {
_filter() { _filter() {
// filter by scope // filter by scope
let scopeFilterData = []; let scopeFilterData = [];
if (!this.condition.filters || !this.condition.filters.scope || this.condition.filters.scope.length === 0) { if (
!this.condition.filters ||
!this.condition.filters.scope ||
this.condition.filters.scope.length === 0
) {
// //
forEach(this.items, (item) => { forEach(this.items, (item) => {
delete item.hidden; delete item.hidden;
if (!item.scope) { if (!item.scope) {
this.$set(item, 'scope', 'api'); this.$set(item, "scope", "api");
} }
}); });
scopeFilterData = this.items; scopeFilterData = this.items;
@ -460,8 +597,10 @@ export default {
} }
let keyword = this.selectVariable; let keyword = this.selectVariable;
scopeFilterData.forEach((filterData) => { scopeFilterData.forEach((filterData) => {
if (keyword && keyword !== '' && filterData.name) { if (keyword && keyword !== "" && filterData.name) {
if (filterData.name.toLowerCase().indexOf(keyword.toLowerCase()) === -1) { if (
filterData.name.toLowerCase().indexOf(keyword.toLowerCase()) === -1
) {
filterData.hidden = true; filterData.hidden = true;
} else { } else {
filterData.hidden = undefined; filterData.hidden = undefined;
@ -492,11 +631,11 @@ export default {
let required = false; let required = false;
keyValues.push( keyValues.push(
new KeyValue({ new KeyValue({
scope: 'api', scope: "api",
name: line[0], name: line[0],
required: required, required: required,
value: values, value: values,
type: 'CONSTANT', type: "CONSTANT",
valid: false, valid: false,
file: false, file: false,
encode: true, encode: true,
@ -541,34 +680,37 @@ export default {
exportJSON() { exportJSON() {
let apiVariable = []; let apiVariable = [];
this.$refs.variableTable.selectRows.forEach((r) => { this.$refs.variableTable.selectRows.forEach((r) => {
if (!r.scope || r.scope != 'ui') { if (!r.scope || r.scope != "ui") {
apiVariable.push(r); apiVariable.push(r);
} }
}); });
if (apiVariable.length < 1) { if (apiVariable.length < 1) {
this.$warning(this.$t('api_test.environment.select_api_variable')); this.$warning(this.$t("api_test.environment.select_api_variable"));
return; return;
} }
let variablesJson = []; let variablesJson = [];
let messages = ''; let messages = "";
let rows = this.$refs.variableTable.selectRows; let rows = this.$refs.variableTable.selectRows;
if (this.condition.selectAll) { if (this.condition.selectAll) {
rows = this.allData; rows = this.allData;
} }
rows.forEach((row) => { rows.forEach((row) => {
if (row.type === 'CSV') { if (row.type === "CSV") {
messages = this.$t('variables.csv_download'); messages = this.$t("variables.csv_download");
} }
if (row.name && (!row.scope || row.scope == 'api')) { if (row.name && (!row.scope || row.scope == "api")) {
variablesJson.push(row); variablesJson.push(row);
} }
}); });
if (messages !== '') { if (messages !== "") {
this.$warning(messages); this.$warning(messages);
return; return;
} }
downloadFile('MS_' + variablesJson.length + '_Environments_variables.json', JSON.stringify(variablesJson)); downloadFile(
"MS_" + variablesJson.length + "_Environments_variables.json",
JSON.stringify(variablesJson)
);
}, },
importJSON() { importJSON() {
this.$refs.variableImport.open(); this.$refs.variableImport.open();
@ -578,9 +720,11 @@ export default {
importData.id = getUUID(); importData.id = getUUID();
importData.enable = true; importData.enable = true;
importData.showMore = false; importData.showMore = false;
let sameNameIndex = this.items.findIndex((d) => d.name === importData.name); let sameNameIndex = this.items.findIndex(
(d) => d.name === importData.name
);
if (sameNameIndex !== -1) { if (sameNameIndex !== -1) {
if (modeId === 'fullCoverage') { if (modeId === "fullCoverage") {
this.items.splice(sameNameIndex, 1, importData); this.items.splice(sameNameIndex, 1, importData);
} }
} else { } else {
@ -599,13 +743,13 @@ export default {
}, },
created() { created() {
if (this.items.length === 0) { if (this.items.length === 0) {
this.items.push(new KeyValue({enable: true, scope: 'api'})); this.items.push(new KeyValue({ enable: true, scope: "api" }));
} else { } else {
// api // api
forEach(this.items, (item) => { forEach(this.items, (item) => {
delete item.hidden; delete item.hidden;
if (!item.scope) { if (!item.scope) {
this.$set(item, 'scope', 'api'); this.$set(item, "scope", "api");
} }
}); });
this.allData = this.items; this.allData = this.items;
@ -633,5 +777,4 @@ export default {
.kv-delete { .kv-delete {
width: 60px; width: 60px;
} }
</style> </style>