feat(接口测试): csv部分页面
This commit is contained in:
parent
1c1d52f45f
commit
472e7ae5eb
|
@ -403,7 +403,7 @@
|
|||
function handleOpenSaveAs(item: TagData) {
|
||||
inputFilesPopoverVisible.value = false;
|
||||
// 这里先判定 uid 是否存在,存在则是刚上传的文件;否则是已保存过后的详情文件
|
||||
savingFile.value = fileList.value.find((file) => (file.uid || file[props.fields.id]) === item.value);
|
||||
savingFile.value = fileList.value.find((file) => file.uid === item.value || file[props.fields.id] === item.value);
|
||||
saveFilePopoverVisible.value = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
(visible) => {
|
||||
if (visible) {
|
||||
initModuleOptions();
|
||||
saveFileForm.value.name = props.savingFile?.name?.split('.').shift() || '';
|
||||
saveFileForm.value.name = (props.savingFile?.name || props.savingFile?.fileName)?.split('.').shift() || '';
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-form ref="formRef" :model="propsRes">
|
||||
<a-form ref="formRef" :model="propsRes" layout="vertical">
|
||||
<MsBaseTable
|
||||
v-bind="propsRes"
|
||||
:hoverable="false"
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
ResponseDefinition,
|
||||
} from '@/models/apiTest/common';
|
||||
import type { MockParams } from '@/models/apiTest/mock';
|
||||
import type { CsvVariable } from '@/models/apiTest/scenario';
|
||||
import {
|
||||
FullResponseAssertionType,
|
||||
RequestAssertionCondition,
|
||||
|
@ -242,16 +243,13 @@ export const regexDefaultParamItem = {
|
|||
moreSettingPopoverVisible: false,
|
||||
};
|
||||
// 响应断言类型映射
|
||||
export const responseAssertionTypeMap: Record<FullResponseAssertionType, string> = {
|
||||
export const responseAssertionTypeMap: Record<string, string> = {
|
||||
[FullResponseAssertionType.DOCUMENT]: 'apiTestManagement.document',
|
||||
[FullResponseAssertionType.RESPONSE_CODE]: 'apiTestManagement.responseCode',
|
||||
[FullResponseAssertionType.RESPONSE_HEADER]: 'apiTestManagement.responseHeader',
|
||||
[FullResponseAssertionType.RESPONSE_TIME]: 'apiTestManagement.responseTime',
|
||||
[FullResponseAssertionType.SCRIPT]: 'apiTestManagement.script',
|
||||
[FullResponseAssertionType.VARIABLE]: 'apiTestManagement.variable',
|
||||
[FullResponseAssertionType.JSON_PATH]: 'jsonPath',
|
||||
[FullResponseAssertionType.XPATH]: 'xPath',
|
||||
[FullResponseAssertionType.REGEX]: 'apiTestManagement.regex',
|
||||
};
|
||||
// 提取类型选项
|
||||
export const extractTypeOptions = [
|
||||
|
@ -415,3 +413,32 @@ export const matchRuleOptions = [
|
|||
];
|
||||
// mock 参数为文件类型的匹配规则选项
|
||||
export const mockFileMatchRules = ['EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY'];
|
||||
|
||||
// 场景-常规参数默认值
|
||||
export const defaultNormalParamItem = {
|
||||
key: '',
|
||||
paramType: 'CONSTANT',
|
||||
value: '',
|
||||
description: '',
|
||||
tags: [],
|
||||
enable: true,
|
||||
};
|
||||
// 场景-csv参数默认值
|
||||
export const defaultCsvParamItem: CsvVariable = {
|
||||
id: '',
|
||||
fileId: '',
|
||||
scenarioId: '',
|
||||
name: '',
|
||||
fileName: '',
|
||||
scope: 'SCENARIO',
|
||||
enable: true,
|
||||
association: false,
|
||||
encoding: 'UTF-8',
|
||||
random: false,
|
||||
variableNames: '',
|
||||
ignoreFirstLine: false,
|
||||
delimiter: ',',
|
||||
allowQuotedData: false,
|
||||
recycleOnEof: false,
|
||||
stopThreadOnEof: false,
|
||||
};
|
||||
|
|
|
@ -26,7 +26,13 @@
|
|||
<template #typeTitle="{ columnConfig }">
|
||||
<div class="flex items-center text-[var(--color-text-3)]">
|
||||
{{ t('apiTestDebug.paramType') }}
|
||||
<a-tooltip :content="columnConfig.typeTitleTooltip" :disabled="!columnConfig.typeTitleTooltip" position="right">
|
||||
<a-tooltip :disabled="!columnConfig.typeTitleTooltip" position="right">
|
||||
<template #content>
|
||||
<template v-if="Array.isArray(columnConfig.typeTitleTooltip)">
|
||||
<div v-for="tip of columnConfig.typeTitleTooltip" :key="tip">{{ tip }}</div>
|
||||
</template>
|
||||
<div v-else>{{ columnConfig.typeTitleTooltip }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
|
@ -184,6 +190,17 @@
|
|||
<template #expression="{ record, rowIndex, columnConfig }">
|
||||
<slot name="expression" :record="record" :row-index="rowIndex" :column-config="columnConfig"></slot>
|
||||
</template>
|
||||
<!-- 作用域 -->
|
||||
<template #scope="{ record, columnConfig, rowIndex }">
|
||||
<a-select
|
||||
v-model:model-value="record.scope"
|
||||
:disabled="props.disabledExceptParam"
|
||||
:options="columnConfig.typeOptions || []"
|
||||
class="ms-form-table-input w-[180px]"
|
||||
size="mini"
|
||||
@change="() => addTableLine(rowIndex)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 参数值 -->
|
||||
<template #value="{ record, columnConfig, rowIndex }">
|
||||
<a-popover
|
||||
|
@ -238,6 +255,27 @@
|
|||
@apply="() => addTableLine(rowIndex, columnConfig.addLineDisabled)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 文件 -->
|
||||
<template #file="{ record, rowIndex }">
|
||||
<MsAddAttachment
|
||||
v-model:file-list="record.files"
|
||||
:disabled="props.disabledParamValue"
|
||||
:multiple="false"
|
||||
mode="input"
|
||||
:fields="{
|
||||
id: 'fileId',
|
||||
name: 'fileAlias',
|
||||
}"
|
||||
:file-save-as-source-id="props.fileSaveAsSourceId"
|
||||
:file-save-as-api="props.fileSaveAsApi"
|
||||
:file-module-options-api="props.fileModuleOptionsApi"
|
||||
input-class="ms-form-table-input h-[24px]"
|
||||
input-size="small"
|
||||
tag-size="small"
|
||||
@change="(files, file) => handleFileChange(files, record, rowIndex, file)"
|
||||
@delete-file="() => emitChange('deleteFile')"
|
||||
/>
|
||||
</template>
|
||||
<!-- 长度范围 -->
|
||||
<template #lengthRange="{ record, rowIndex }">
|
||||
<div class="flex items-center justify-between">
|
||||
|
@ -430,9 +468,20 @@
|
|||
/>
|
||||
<div v-else class="text-[var(--color-text-1)]">{{ '-' }}</div>
|
||||
</template>
|
||||
<!-- 单独启用/禁用列 -->
|
||||
<template #enable="{ record, rowIndex }">
|
||||
<a-switch
|
||||
v-model="record.enable"
|
||||
:disabled="props.disabledExceptParam"
|
||||
size="small"
|
||||
type="line"
|
||||
class="ml-[8px]"
|
||||
@change="() => addTableLine(rowIndex)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template v-if="!props.disabledExceptParam" #operation="{ record, rowIndex, columnConfig }">
|
||||
<div class="flex flex-row items-center" :class="{ 'justify-end': columnConfig.align === 'right' }">
|
||||
<div class="flex w-full flex-row items-center" :class="{ 'justify-end': columnConfig.align === 'right' }">
|
||||
<a-switch
|
||||
v-if="columnConfig.hasDisable"
|
||||
v-model="record.enable"
|
||||
|
@ -573,7 +622,7 @@
|
|||
isNormal?: boolean; // 用于 value 列区分是普通输入框还是 MsParamsInput
|
||||
hasRequired?: boolean; // 用于 type 列区分是否有 required 星号
|
||||
typeOptions?: { label: string; value: string }[]; // 用于 type 列选择器选项
|
||||
typeTitleTooltip?: string; // 用于 type 表头列展示的 tooltip
|
||||
typeTitleTooltip?: string | string[]; // 用于 type 表头列展示的 tooltip
|
||||
hasDisable?: boolean; // 用于 operation 列区分是否有 enable 开关
|
||||
moreAction?: ActionsItem[]; // 用于 operation 列更多操作按钮配置
|
||||
format?: RequestBodyFormat; // 用于 operation 列区分是否有请求体格式选择器
|
||||
|
|
|
@ -8,7 +8,12 @@
|
|||
>
|
||||
<template #assertionItem="{ record }">
|
||||
<div class="flex items-center gap-[4px]">
|
||||
【{{ t(responseAssertionTypeMap[(record as ResponseAssertionTableItem).assertionType]) }}】
|
||||
【{{
|
||||
t(
|
||||
responseAssertionTypeMap[(record as ResponseAssertionTableItem).assertionType] ||
|
||||
'apiTestDebug.responseBody'
|
||||
)
|
||||
}}】
|
||||
{{ record.name }}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -16,7 +21,7 @@
|
|||
{{
|
||||
record.assertionType === FullResponseAssertionType.RESPONSE_TIME
|
||||
? t('advanceFilter.operator.le')
|
||||
: t(statusCodeOptions.find((item) => item.value === record.condition)?.label || '')
|
||||
: t(statusCodeOptions.find((item) => item.value === record.condition)?.label || '-')
|
||||
}}
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div class="history-container">
|
||||
<a-alert v-if="isShowTip" :show-icon="true" class="mb-[8px]" type="info">
|
||||
<a-alert :show-icon="true" class="mb-[8px]" type="info">
|
||||
{{ t('apiScenario.params.priority') }}
|
||||
</a-alert>
|
||||
</div>
|
||||
<!-- <div class="mb-[16px]">
|
||||
<div class="mb-[8px] flex items-center justify-between">
|
||||
<a-radio-group v-model="activeRadio" type="button" size="medium">
|
||||
<a-radio value="convention">{{ t('apiScenario.params.convention') }}</a-radio>
|
||||
<a-radio value="csv">{{ t('apiScenario.params.csv') }}</a-radio>
|
||||
</a-radio-group>
|
||||
</div>-->
|
||||
<div class="mb-[8px] flex items-center justify-between">
|
||||
<a-input-search
|
||||
v-if="activeRadio === 'convention'"
|
||||
v-model="searchValue"
|
||||
:placeholder="t('apiScenario.params.searchPlaceholder')"
|
||||
allow-clear
|
||||
|
@ -21,58 +21,146 @@
|
|||
/>
|
||||
</div>
|
||||
<paramTable
|
||||
v-model:params="innerParams"
|
||||
v-if="activeRadio === 'convention'"
|
||||
v-model:params="commonVariables"
|
||||
:columns="columns"
|
||||
:default-param-item="defaultParamItem"
|
||||
draggable
|
||||
:default-param-item="defaultNormalParamItem"
|
||||
:draggable="false"
|
||||
:selectable="false"
|
||||
@change="handleParamTableChange"
|
||||
@batch-add="batchAddKeyValVisible = true"
|
||||
/>
|
||||
<paramTable
|
||||
v-else
|
||||
v-model:params="csvVariables"
|
||||
:columns="csvColumns"
|
||||
:default-param-item="defaultCsvParamItem"
|
||||
:draggable="false"
|
||||
:selectable="false"
|
||||
@change="handleParamTableChange"
|
||||
@batch-add="batchAddKeyValVisible = true"
|
||||
>
|
||||
<template #operationPre="{ record }">
|
||||
<a-trigger trigger="click" position="br" class="scenario-csv-trigger">
|
||||
<MsButton type="text" class="!mr-0">{{ t('apiScenario.params.config') }}</MsButton>
|
||||
<template #content>
|
||||
<div class="scenario-csv-trigger-content">
|
||||
<div class="mb-[16px] flex items-center">
|
||||
<div class="font-semibold text-[var(--color-text-1)]">{{ t('apiScenario.params.csvConfig') }}</div>
|
||||
<!-- <div class="text-[var(--color-text-4)]">({{ record.key }})</div> -->
|
||||
</div>
|
||||
<div class="scenario-csv-trigger-content-scroll">
|
||||
<a-form ref="paramFormRef" :model="record" layout="vertical">
|
||||
<a-form-item
|
||||
field="key"
|
||||
:label="t('apiScenario.params.csvName')"
|
||||
:rules="[{ required: true, message: t('apiScenario.params.csvNameNotNull') }]"
|
||||
asterisk-position="end"
|
||||
class="mb-[16px]"
|
||||
>
|
||||
<a-input v-model:model-value="record.key" :max-length="255"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="variableNames" :label="t('apiScenario.params.csvParamName')" class="mb-[16px]">
|
||||
<a-input
|
||||
v-model:model-value="record.variableNames"
|
||||
:placeholder="t('apiScenario.params.csvParamNamePlaceholder')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="encoding" :label="t('apiScenario.params.csvFileCode')" class="mb-[16px]">
|
||||
<a-select
|
||||
v-model:model-value="record.encoding"
|
||||
:options="encodingOptions"
|
||||
class="w-[120px]"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="delimiter" :label="t('apiScenario.params.csvSplitChar')" class="mb-[16px]">
|
||||
<a-input
|
||||
v-model:model-value="record.delimiter"
|
||||
:placeholder="t('common.pleaseInput')"
|
||||
:max-length="64"
|
||||
class="w-[120px]"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="ignoreFirstLine"
|
||||
:label="t('apiScenario.params.csvIgnoreFirstLine')"
|
||||
class="mb-[16px]"
|
||||
>
|
||||
<a-radio-group v-model:model-value="record.ignoreFirstLine">
|
||||
<a-radio :value="false">False</a-radio>
|
||||
<a-radio :value="true">True</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item field="random" :label="t('apiScenario.params.csvIsRandom')" class="mb-[16px]">
|
||||
<a-radio-group v-model:model-value="record.random">
|
||||
<a-radio :value="false">False</a-radio>
|
||||
<a-radio :value="true">True</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item field="allowQuotedData" :label="t('apiScenario.params.csvQuoteAllow')" class="mb-[16px]">
|
||||
<a-radio-group v-model:model-value="record.allowQuotedData">
|
||||
<a-radio :value="false">False</a-radio>
|
||||
<a-radio :value="true">True</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item field="recycleOnEof" :label="t('apiScenario.params.csvRecycle')" class="mb-[16px]">
|
||||
<a-radio-group v-model:model-value="record.recycleOnEof">
|
||||
<a-radio :value="false">False</a-radio>
|
||||
<a-radio :value="true">True</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item field="stopThreadOnEof" :label="t('apiScenario.params.csvStop')" class="mb-[16px]">
|
||||
<a-radio-group v-model:model-value="record.stopThreadOnEof">
|
||||
<a-radio :value="false">False</a-radio>
|
||||
<a-radio :value="true">True</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-trigger>
|
||||
</template>
|
||||
</paramTable>
|
||||
<batchAddKeyVal
|
||||
v-model:visible="batchAddKeyValVisible"
|
||||
:params="innerParams"
|
||||
:default-param-item="defaultParamItem"
|
||||
:params="commonVariables"
|
||||
:default-param-item="defaultNormalParamItem"
|
||||
no-param-type
|
||||
@apply="handleBatchParamApply"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { FormInstance } from '@arco-design/web-vue';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import batchAddKeyVal from '@/views/api-test/components/batchAddKeyVal.vue';
|
||||
import paramTable, { ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
|
||||
|
||||
import { CommonVariable } from '@/models/apiTest/scenario';
|
||||
import { CommonVariable, CsvVariable } from '@/models/apiTest/scenario';
|
||||
|
||||
import { defaultCsvParamItem, defaultNormalParamItem } from '@/views/api-test/components/config';
|
||||
import { filterKeyValParams } from '@/views/api-test/components/utils';
|
||||
|
||||
const props = defineProps<{
|
||||
activeKey?: string;
|
||||
params: CommonVariable[];
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:params', value: CommonVariable[]): void;
|
||||
(e: 'change'): void; // 数据发生变化
|
||||
}>();
|
||||
const innerParams = useVModel(props, 'params', emit);
|
||||
const isShowTip = ref<boolean>(true);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const commonVariables = defineModel<CommonVariable[]>('commonVariables', {
|
||||
required: true,
|
||||
});
|
||||
const csvVariables = defineModel<CsvVariable[]>('csvVariables', {
|
||||
required: true,
|
||||
});
|
||||
const searchValue = ref('');
|
||||
const firstSearch = ref(true);
|
||||
const backupParams = ref(props.params);
|
||||
const backupParams = ref(commonVariables.value);
|
||||
const batchAddKeyValVisible = ref(false);
|
||||
|
||||
const defaultParamItem = {
|
||||
key: '',
|
||||
paramType: 'CONSTANT',
|
||||
value: '',
|
||||
description: '',
|
||||
tags: [],
|
||||
enable: true,
|
||||
};
|
||||
const activeRadio = ref('convention');
|
||||
|
||||
const columns: ParamTableColumn[] = [
|
||||
{
|
||||
|
@ -104,6 +192,11 @@
|
|||
dataIndex: 'value',
|
||||
slotName: 'value',
|
||||
},
|
||||
{
|
||||
title: 'apiScenario.table.columns.status',
|
||||
dataIndex: 'enable',
|
||||
slotName: 'enable',
|
||||
},
|
||||
{
|
||||
title: 'apiScenario.params.tag',
|
||||
dataIndex: 'tags',
|
||||
|
@ -120,12 +213,12 @@
|
|||
slotName: 'operation',
|
||||
titleSlotName: 'batchAddTitle',
|
||||
dataIndex: 'operation',
|
||||
width: 70,
|
||||
width: 90,
|
||||
},
|
||||
];
|
||||
|
||||
function handleParamTableChange(resultArr: any[], isInit?: boolean) {
|
||||
innerParams.value = [...resultArr];
|
||||
commonVariables.value = [...resultArr];
|
||||
if (!isInit) {
|
||||
emit('change');
|
||||
firstSearch.value = true;
|
||||
|
@ -135,16 +228,16 @@
|
|||
// 搜索
|
||||
function handleSearch() {
|
||||
if (firstSearch.value) {
|
||||
backupParams.value = [...innerParams.value];
|
||||
backupParams.value = [...commonVariables.value];
|
||||
firstSearch.value = false;
|
||||
}
|
||||
if (!searchValue.value) {
|
||||
innerParams.value = [...backupParams.value];
|
||||
commonVariables.value = [...backupParams.value];
|
||||
} else {
|
||||
const result = backupParams.value.filter(
|
||||
(item) => item.key.includes(searchValue.value) || item.tags.includes(searchValue.value)
|
||||
);
|
||||
innerParams.value = [...result];
|
||||
commonVariables.value = [...result];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,14 +245,113 @@
|
|||
* 批量参数代码转换为参数表格数据
|
||||
*/
|
||||
function handleBatchParamApply(resultArr: any[]) {
|
||||
const filterResult = filterKeyValParams(innerParams.value, defaultParamItem);
|
||||
const filterResult = filterKeyValParams(commonVariables.value, defaultNormalParamItem);
|
||||
if (filterResult.lastDataIsDefault) {
|
||||
innerParams.value = [...resultArr, innerParams.value[innerParams.value.length - 1]].filter(Boolean);
|
||||
commonVariables.value = [...resultArr, commonVariables.value[commonVariables.value.length - 1]].filter(Boolean);
|
||||
} else {
|
||||
innerParams.value = resultArr.filter(Boolean);
|
||||
commonVariables.value = resultArr.filter(Boolean);
|
||||
}
|
||||
emit('change');
|
||||
}
|
||||
|
||||
const csvColumns: ParamTableColumn[] = [
|
||||
{
|
||||
title: 'apiScenario.params.csvName',
|
||||
dataIndex: 'key',
|
||||
slotName: 'key',
|
||||
needValidRepeat: true,
|
||||
},
|
||||
{
|
||||
title: 'apiScenario.params.csvScoped',
|
||||
dataIndex: 'scope',
|
||||
slotName: 'scope',
|
||||
typeOptions: [
|
||||
{
|
||||
label: t('apiScenario.scenario'),
|
||||
value: 'SCENARIO',
|
||||
},
|
||||
{
|
||||
label: t('apiScenario.step'),
|
||||
value: 'STEP',
|
||||
},
|
||||
],
|
||||
width: 80,
|
||||
titleSlotName: 'typeTitle',
|
||||
typeTitleTooltip: [t('apiScenario.params.csvScopedTip1'), t('apiScenario.params.csvScopedTip2')],
|
||||
},
|
||||
// {
|
||||
// title: 'apiScenario.params.file',
|
||||
// dataIndex: 'file',
|
||||
// slotName: 'file',
|
||||
// },
|
||||
{
|
||||
title: 'apiScenario.table.columns.status',
|
||||
dataIndex: 'enable',
|
||||
slotName: 'enable',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
slotName: 'operation',
|
||||
dataIndex: 'operation',
|
||||
width: 90,
|
||||
},
|
||||
];
|
||||
|
||||
const configFormRef = ref<FormInstance>();
|
||||
const encodingOptions = [
|
||||
{
|
||||
label: 'UTF-8',
|
||||
value: 'UTF-8',
|
||||
},
|
||||
{
|
||||
label: 'UTF-16',
|
||||
value: 'UTF-16',
|
||||
},
|
||||
{
|
||||
label: 'ISO-8859-15',
|
||||
value: 'ISO-8859-15',
|
||||
},
|
||||
{
|
||||
label: 'US-ASCII',
|
||||
value: 'US-ASCII',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less">
|
||||
.scenario-csv-trigger {
|
||||
@apply bg-white;
|
||||
.scenario-csv-trigger-content {
|
||||
padding: 16px;
|
||||
width: 400px;
|
||||
border-radius: var(--border-radius-medium);
|
||||
box-shadow: 0 5px 5px -3px rgb(0 0 0 / 10%), 0 8px 10px 1px rgb(0 0 0 / 6%), 0 3px 14px 2px rgb(0 0 0 / 5%);
|
||||
&::before {
|
||||
@apply absolute left-0 top-0;
|
||||
|
||||
content: '';
|
||||
z-index: -1;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
border: 1px solid var(--color-text-input-border);
|
||||
border-radius: 12px;
|
||||
transform-origin: 0 0;
|
||||
transform: scale(0.5, 0.5);
|
||||
}
|
||||
.scenario-csv-trigger-content-scroll {
|
||||
.ms-scroll-bar();
|
||||
|
||||
overflow-y: auto;
|
||||
margin-right: -6px;
|
||||
max-height: 400px;
|
||||
.scenario-csv-trigger-content-scroll-preview {
|
||||
@apply w-full overflow-y-auto overflow-x-hidden break-all;
|
||||
.ms-scroll-bar();
|
||||
|
||||
max-height: 100px;
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
>
|
||||
<params
|
||||
v-if="activeKey === ScenarioCreateComposition.PARAMS"
|
||||
v-model:params="scenario.scenarioConfig.variable.commonVariables"
|
||||
v-model:commonVariables="scenario.scenarioConfig.variable.commonVariables"
|
||||
v-model:csvVariables="scenario.scenarioConfig.variable.csvVariables"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
|
|
|
@ -62,7 +62,8 @@
|
|||
>
|
||||
<params
|
||||
v-if="activeKey === ScenarioDetailComposition.PARAMS"
|
||||
v-model:params="scenario.scenarioConfig.variable.commonVariables"
|
||||
v-model:commonVariables="scenario.scenarioConfig.variable.commonVariables"
|
||||
v-model:csvVariables="scenario.scenarioConfig.variable.csvVariables"
|
||||
@change="scenario.unSaved = true"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
|
|
|
@ -515,6 +515,7 @@
|
|||
environmentId: appStore.getCurrentEnvId || '',
|
||||
});
|
||||
const scenarioDetail = await getScenarioDetail(res.id);
|
||||
// 添加后获取后台组装的场景信息
|
||||
scenarioDetail.stepDetails = {};
|
||||
scenarioDetail.isNew = false;
|
||||
scenarioDetail.id = res.id;
|
||||
|
|
|
@ -24,6 +24,14 @@ export default {
|
|||
'apiScenario.dependency': 'Dependency',
|
||||
'apiScenario.quote': 'Quote',
|
||||
'apiScenario.params.convention': 'Conventional Parameters',
|
||||
'apiScenario.params.csv': 'CSV Parameters',
|
||||
'apiScenario.params.csvName': 'CSV name',
|
||||
'apiScenario.params.csvScoped': 'Scope',
|
||||
'apiScenario.params.file': 'File',
|
||||
'apiScenario.params.csvScopedTip1':
|
||||
'Scenario level: Load CSV before executing the scenario. Data can be read from CSV in any step of the current scenario.',
|
||||
'apiScenario.params.csvScopedTip2':
|
||||
'Step level: The CSV needs to be added to the scenario step. The CSV is loaded when executing this step, and the scope is the request within the step.',
|
||||
'apiScenario.params.searchPlaceholder': 'Search by name or tag',
|
||||
'apiScenario.params.priority':
|
||||
'Variable Priority: Temporary Parameters > Scenario Parameters > Environment Parameters > Global Parameters; Note: Avoid using variables with the same name. In case of same name variables, scenario-level CSV has the highest priority.',
|
||||
|
|
|
@ -23,6 +23,24 @@ export default {
|
|||
'apiScenario.dependency': '依赖关系',
|
||||
'apiScenario.quote': '引用关系',
|
||||
'apiScenario.params.convention': '常规参数',
|
||||
'apiScenario.params.csv': 'CSV 参数',
|
||||
'apiScenario.params.csvName': 'CSV 名称',
|
||||
'apiScenario.params.csvNameNotNull': 'CSV 名称不能为空',
|
||||
'apiScenario.params.csvScoped': '作用域',
|
||||
'apiScenario.params.file': '文件',
|
||||
'apiScenario.params.csvScopedTip1': '场景级:执行场景前加载CSV,当前场景任意步骤均可从CSV中读取到数据',
|
||||
'apiScenario.params.csvScopedTip2': '步骤级:需在场景步骤中添加该CSV,执行该步骤时加载CSV,作用域为步骤内的请求',
|
||||
'apiScenario.params.config': '配置',
|
||||
'apiScenario.params.csvConfig': 'CSV 配置',
|
||||
'apiScenario.params.csvParamName': '参数名称',
|
||||
'apiScenario.params.csvParamNamePlaceholder': '多个参数名以 , 隔开',
|
||||
'apiScenario.params.csvFileCode': '文件编码',
|
||||
'apiScenario.params.csvSplitChar': '分隔符',
|
||||
'apiScenario.params.csvIgnoreFirstLine': '忽略首行',
|
||||
'apiScenario.params.csvIsRandom': '是否随机',
|
||||
'apiScenario.params.csvQuoteAllow': '允许带引号',
|
||||
'apiScenario.params.csvRecycle': '遇到文件结束符再次循环',
|
||||
'apiScenario.params.csvStop': '遇到文件结束符停止线程',
|
||||
'apiScenario.params.searchPlaceholder': '通过名称或标签搜索',
|
||||
'apiScenario.params.priority':
|
||||
'变量优先级:临时参数>场景参数 >环境参数>全局参数;注: 避免使用同名变量,同名变量时场景级 CSV 优先级最高',
|
||||
|
|
Loading…
Reference in New Issue