fix(项目设置): 修复环境设置历史数据不能编辑备注的缺陷

--bug=1020201 --user=王孝刚 【接口测试】
github#20027【升级数据兼容问题】从1.19.2版本升到2.2.1后,环境中的变量备注不能编辑
https://www.tapd.cn/55049933/s/1306342
This commit is contained in:
wxg0103 2022-11-28 15:25:11 +08:00 committed by wxg0103
parent d2c357b094
commit 7e3b069dfc
1 changed files with 263 additions and 139 deletions

View File

@ -1,24 +1,49 @@
<template> <template>
<div> <div>
<div> <div>
<div style="padding-bottom: 10px;float: left"> <div style="padding-bottom: 10px; float: left">
<el-input :placeholder="$t('api_test.search_by_variables')" size="mini" v-model="selectVariable" <el-input
@change="filter" :placeholder="$t('api_test.search_by_variables')"
@keyup.enter="filter"> size="mini"
v-model="selectVariable"
@change="filter"
@keyup.enter="filter"
>
</el-input> </el-input>
</div> </div>
<div style="padding-bottom: 10px; float: right;"> <div style="padding-bottom: 10px; float: right">
<ms-table-button v-permission="['PROJECT_ENVIRONMENT:READ+IMPORT']" icon="el-icon-box" <ms-table-button
:content="$t('commons.import')" @click="importJSON"/> v-permission="['PROJECT_ENVIRONMENT:READ+IMPORT']"
<ms-table-button v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']" icon="el-icon-box" icon="el-icon-box"
:content="$t('commons.export')" @click="exportJSON"/> :content="$t('commons.import')"
<el-link style="margin-left: 10px" @click="batchAdd" type="primary" :disabled="isReadOnly"> @click="importJSON"
/>
<ms-table-button
v-permission="['PROJECT_ENVIRONMENT:READ+EXPORT']"
icon="el-icon-box"
:content="$t('commons.export')"
@click="exportJSON"
/>
<el-link
style="margin-left: 10px"
@click="batchAdd"
type="primary"
:disabled="isReadOnly"
>
{{ $t("commons.batch_add") }} {{ $t("commons.batch_add") }}
</el-link> </el-link>
</div> </div>
</div> </div>
<div <div
style="border:1px #DCDFE6 solid; min-height: 300px;border-radius: 4px ;width: 99% ;margin-top: 10px; clear: both"> style="
border: 1px #dcdfe6 solid;
min-height: 300px;
border-radius: 4px;
width: 99%;
margin-top: 10px;
clear: both;
"
>
<ms-table <ms-table
v-loading="loading" v-loading="loading"
row-key="id" row-key="id"
@ -29,73 +54,134 @@
:remember-order="true" :remember-order="true"
:highlightCurrentRow="true" :highlightCurrentRow="true"
@refresh="onChange" @refresh="onChange"
ref="variableTable"> ref="variableTable"
>
<ms-table-column <ms-table-column prop="num" sortable label="ID" min-width="60">
prop="num"
sortable
label="ID"
min-width="60">
</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" size="mini" v-model="scope.row.name"
maxlength="200" :placeholder="$t('api_test.variable_name')" show-word-limit size="mini"
@change="change"/> maxlength="200"
:placeholder="$t('api_test.variable_name')"
show-word-limit
@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 v-model="scope.row.type" :placeholder="$t('commons.please_select')" size="mini" <el-select
@change="changeType(scope.row)"> v-model="scope.row.type"
<el-option v-for="item in typeSelectOptions " :key="item.value" :label="item.label" :value="item.value"/> :placeholder="$t('commons.please_select')"
size="mini"
@change="changeType(scope.row)"
>
<el-option
v-for="item in typeSelectOptions"
:key="item.value"
:label="item.label"
: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')" <el-table-column
min-width="200px" sortable show-overflow-tooltip> prop="value"
:label="$t('api_test.value')"
min-width="200px"
sortable
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.value" size="mini" v-if="scope.row.type !=='CSV'" <el-input
:placeholder="valueText(scope.row)" v-model="scope.row.value"
:disabled="scope.row.type === 'COUNTER' || scope.row.type === 'RANDOM'"/> size="mini"
<csv-file-upload :parameter="scope.row" v-if="scope.row.type ==='CSV'"/> v-if="scope.row.type !== 'CSV'"
:placeholder="valueText(scope.row)"
:disabled="
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> </el-table-column>
<ms-table-column prop="description" :label="$t('commons.remark')" <ms-table-column
min-width="160" sortable> 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" 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" />
<el-tooltip effect="dark" :content="$t('commons.remove')" placement="top-start"> <el-tooltip
<el-button icon="el-icon-delete" type="danger" circle size="mini" style="margin-left: 10px" effect="dark"
@click="remove(scope.row)" v-if="isDisable(scope.row)"/> :content="$t('commons.remove')"
</el-tooltip> placement="top-start"
<el-tooltip effect="dark" :content="$t('schema.adv_setting')" placement="top-start"> >
<el-button icon="el-icon-setting" circle size="mini" style="margin-left: 10px" <el-button
@click="openSetting(scope.row)" v-if="scope.row.type !=='LIST'" @change="change"/> icon="el-icon-delete"
</el-tooltip> type="danger"
circle
</span> size="mini"
style="margin-left: 10px"
@click="remove(scope.row)"
v-if="isDisable(scope.row)"
/>
</el-tooltip>
<el-tooltip
effect="dark"
:content="$t('schema.adv_setting')"
placement="top-start"
>
<el-button
icon="el-icon-setting"
circle
size="mini"
style="margin-left: 10px"
@click="openSetting(scope.row)"
v-if="scope.row.type !== 'LIST'"
@change="change"
/>
</el-tooltip>
</span>
</template> </template>
</ms-table-column> </ms-table-column>
</ms-table> </ms-table>
</div> </div>
<batch-add-parameter @batchSave="batchSave" ref="batchAdd"/> <batch-add-parameter @batchSave="batchSave" ref="batchAdd" />
<api-variable-setting ref="apiVariableSetting"></api-variable-setting> <api-variable-setting ref="apiVariableSetting"></api-variable-setting>
<variable-import ref="variableImport" @mergeData="mergeData"></variable-import> <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";
@ -103,7 +189,7 @@ 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";
export default { export default {
@ -116,45 +202,44 @@ export default {
MsTableColumn, MsTableColumn,
ApiVariableSetting, ApiVariableSetting,
CsvFileUpload, CsvFileUpload,
VariableImport VariableImport,
}, },
props: { props: {
description: String,
items: Array, items: Array,
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
showVariable: { showVariable: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
showCopy: { showCopy: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
screenHeight: '400px', screenHeight: "400px",
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") },
], ],
variables: {}, variables: {},
selectVariable: '', selectVariable: "",
editData: {}, editData: {},
} };
}, },
watch: { watch: {
items: { items: {
@ -163,14 +248,14 @@ export default {
this.sortParameters(); this.sortParameters();
}, },
immediate: true, immediate: true,
deep: true deep: true,
} },
}, },
methods: { methods: {
remove: function (index) { remove: function (index) {
const dataIndex = this.variables.findIndex(d => d.name === index.name); const dataIndex = this.variables.findIndex((d) => d.name === index.name);
this.variables.splice(dataIndex, 1); this.variables.splice(dataIndex, 1);
this.$emit('change', this.variables); this.$emit("change", this.variables);
}, },
change: function () { change: function () {
let isNeedCreate = true; let isNeedCreate = true;
@ -192,79 +277,107 @@ export default {
} }
}); });
if (repeatKey !== "") { if (repeatKey !== "") {
this.$warning(this.$t('api_test.environment.common_config') + "【" + repeatKey + "】" + this.$t('load_test.param_is_duplicate')); this.$warning(
this.$t("api_test.environment.common_config") +
"【" +
repeatKey +
"】" +
this.$t("load_test.param_is_duplicate")
);
} }
if (isNeedCreate) { if (isNeedCreate) {
this.variables.push(new KeyValue({enable: true, id: getUUID(), type: 'CONSTANT'})); this.variables.push(
new KeyValue({ enable: true, id: getUUID(), type: "CONSTANT" })
);
} }
this.$emit('change', this.variables); this.$emit("change", this.variables);
// TODO key // TODO key
}, },
changeType(data) { changeType(data) {
data.value = ''; data.value = "";
if (!data.delimiter || (!data.files && data.files.length === 0) || !data.quotedData) { if (
data.delimiter = ','; !data.delimiter ||
(!data.files && data.files.length === 0) ||
!data.quotedData
) {
data.delimiter = ",";
data.files = []; data.files = [];
data.quotedData = 'false'; data.quotedData = "false";
} }
}, },
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 = [{value: "UTF-8"}, {value: "UTF-16"}, {value: "GB2312"}, {value: "ISO-8859-15"}, {value: "US-ASCll"}]; let restaurants = [
let results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants; { value: "UTF-8" },
{ value: "UTF-16" },
{ value: "GB2312" },
{ value: "ISO-8859-15" },
{ value: "US-ASCll" },
];
let results = queryString
? restaurants.filter(this.createFilter(queryString))
: restaurants;
// callback // callback
cb(results); cb(results);
}, },
sortParameters() { sortParameters() {
let index = 1; let index = 1;
this.variables.forEach(item => { this.variables.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) {
item.description = item.remark; this.$set(item, "description", item.remark);
item.remark = undefined;
} }
index++; index++;
}); });
}, },
handleDeleteBatch() { handleDeleteBatch() {
operationConfirm(this, this.$t('api_test.environment.variables_delete_info') + " ", () => { operationConfirm(
let ids = this.$refs.variableTable.selectRows; this,
ids.forEach(row => { this.$t("api_test.environment.variables_delete_info") + " ",
if (row.id) { () => {
const index = this.variables.findIndex(d => d.id === row.id); let ids = this.$refs.variableTable.selectRows;
if (index !== this.variables.length - 1) { ids.forEach((row) => {
this.variables.splice(index, 1); if (row.id) {
const index = this.variables.findIndex((d) => d.id === row.id);
if (index !== this.variables.length - 1) {
this.variables.splice(index, 1);
}
} }
} });
}); this.sortParameters();
this.sortParameters(); this.$refs.variableTable.cancelCurrentRow();
this.$refs.variableTable.cancelCurrentRow(); this.$refs.variableTable.clear();
this.$refs.variableTable.clear(); }
}); );
}, },
filter() { filter() {
let datas = []; let datas = [];
this.variables.forEach(item => { this.variables.forEach((item) => {
if (this.selectVariable && this.selectVariable != "" && item.name) { if (this.selectVariable && this.selectVariable != "" && item.name) {
if (item.name.toLowerCase().indexOf(this.selectVariable.toLowerCase()) == -1) { if (
item.name
.toLowerCase()
.indexOf(this.selectVariable.toLowerCase()) == -1
) {
item.hidden = true; item.hidden = true;
} else { } else {
item.hidden = undefined; item.hidden = undefined;
@ -280,28 +393,30 @@ export default {
this.$refs.apiVariableSetting.open(data); this.$refs.apiVariableSetting.open(data);
}, },
isDisable: function (row) { isDisable: function (row) {
const index = this.variables.findIndex(d => d.name === row.name); const index = this.variables.findIndex((d) => d.name === row.name);
return this.variables.length - 1 !== index; return this.variables.length - 1 !== index;
}, },
_handleBatchVars(data) { _handleBatchVars(data) {
let params = data.split("\n"); let params = data.split("\n");
let keyValues = []; let keyValues = [];
params.forEach(item => { params.forEach((item) => {
if (item) { if (item) {
let line = item.split(/|:/); let line = item.split(/|:/);
let values = item.split(line[0] + ":"); let values = item.split(line[0] + ":");
let required = false; let required = false;
keyValues.push(new KeyValue({ keyValues.push(
name: line[0], new KeyValue({
required: required, name: line[0],
value: values[1], required: required,
type: 'CONSTANT', value: values[1],
valid: false, type: "CONSTANT",
file: false, valid: false,
encode: true, file: false,
enable: true, encode: true,
description: undefined enable: true,
})); description: undefined,
})
);
} }
}); });
return keyValues; return keyValues;
@ -312,18 +427,22 @@ export default {
batchSave(data) { batchSave(data) {
if (data) { if (data) {
let keyValues = this._handleBatchVars(data); let keyValues = this._handleBatchVars(data);
keyValues.forEach(keyValue => { keyValues.forEach((keyValue) => {
let isAdd = true; let isAdd = true;
this.variables.forEach(item => { this.variables.forEach((item) => {
if (item.name === keyValue.name) { if (item.name === keyValue.name) {
item.value = keyValue.value; item.value = keyValue.value;
isAdd = false; isAdd = false;
} }
}) });
if (isAdd) { if (isAdd) {
this.variables.splice(this.variables.indexOf(i => !i.name), 0, keyValue); this.variables.splice(
this.variables.indexOf((i) => !i.name),
0,
keyValue
);
} }
}) });
} }
}, },
onChange() { onChange() {
@ -331,50 +450,55 @@ export default {
}, },
exportJSON() { exportJSON() {
if (this.$refs.variableTable.selectIds.length < 1) { if (this.$refs.variableTable.selectIds.length < 1) {
this.$warning(this.$t('api_test.environment.select_variable')); this.$warning(this.$t("api_test.environment.select_variable"));
return; return;
} }
let variablesJson = []; let variablesJson = [];
let messages = ''; let messages = "";
let rows = this.$refs.variableTable.selectRows; let rows = this.$refs.variableTable.selectRows;
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) { if (row.name) {
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();
}, },
mergeData(data, modeId) { mergeData(data, modeId) {
JSON.parse(data).map(importData => { JSON.parse(data).map((importData) => {
importData.id = getUUID(); importData.id = getUUID();
importData.enable = true; importData.enable = true;
importData.showMore = false; importData.showMore = false;
let sameNameIndex = this.variables.findIndex(d => d.name === importData.name); let sameNameIndex = this.variables.findIndex(
(d) => d.name === importData.name
);
if (sameNameIndex !== -1) { if (sameNameIndex !== -1) {
if (modeId === 'fullCoverage') { if (modeId === "fullCoverage") {
this.variables.splice(sameNameIndex, 1, importData); this.variables.splice(sameNameIndex, 1, importData);
} }
} else { } else {
this.variables.splice(this.variables.length - 1, 0, importData); this.variables.splice(this.variables.length - 1, 0, importData);
} }
}) });
} },
}, },
created() { created() {
if (this.items.length === 0) { if (this.items.length === 0) {
this.items.push(new KeyValue({enable: true})); this.items.push(new KeyValue({ enable: true }));
} }
} },
}; };
</script> </script>