fix(接口测试): csv文件类型限制&场景步骤调整
This commit is contained in:
parent
586417e1bf
commit
b84a874aa9
|
@ -8,7 +8,7 @@
|
|||
<template #content>
|
||||
<MsUpload
|
||||
v-model:file-list="innerFileList"
|
||||
accept="none"
|
||||
:accept="props.accept || 'none'"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:limit="50"
|
||||
|
@ -38,12 +38,13 @@
|
|||
<script setup lang="ts">
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsUpload from '@/components/pure/ms-upload/index.vue';
|
||||
import { MsFileItem } from '@/components/pure/ms-upload/types';
|
||||
import { MsFileItem, UploadType } from '@/components/pure/ms-upload/types';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const props = defineProps<{
|
||||
disabled?: boolean;
|
||||
accept?: UploadType;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<dropdownMenu
|
||||
:file-list="fileList"
|
||||
:disabled="props.disabled"
|
||||
:accept="props.accept"
|
||||
@link-file="associatedFile"
|
||||
@change="handleChange"
|
||||
/>
|
||||
|
@ -186,7 +187,12 @@
|
|||
</a-popover>
|
||||
</div>
|
||||
<div v-else class="flex w-full items-center gap-[4px]">
|
||||
<dropdownMenu :disabled="props.disabled" @link-file="associatedFile" @change="handleChange" />
|
||||
<dropdownMenu
|
||||
:accept="props.accept"
|
||||
:disabled="props.disabled"
|
||||
@link-file="associatedFile"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<a-input
|
||||
v-model:model-value="inputFileName"
|
||||
:disabled="props.disabled"
|
||||
|
@ -206,6 +212,7 @@
|
|||
:get-list-request="getAssociatedFileListUrl"
|
||||
:get-list-fun-params="getListFunParams"
|
||||
:selector-type="props.multiple ? 'checkbox' : 'radio'"
|
||||
:filetype="props.accept"
|
||||
@save="saveSelectAssociatedFile"
|
||||
/>
|
||||
</template>
|
||||
|
@ -218,7 +225,7 @@
|
|||
import MsTag, { Size } from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||
import MsUpload from '@/components/pure/ms-upload/index.vue';
|
||||
import type { MsFileItem } from '@/components/pure/ms-upload/types';
|
||||
import type { MsFileItem, UploadType } from '@/components/pure/ms-upload/types';
|
||||
import LinkFileDrawer from '@/components/business/ms-link-file/associatedFileDrawer.vue';
|
||||
import dropdownMenu from './dropdownMenu.vue';
|
||||
import saveAsFilePopover from './saveAsFilePopover.vue';
|
||||
|
@ -237,6 +244,7 @@
|
|||
defineProps<{
|
||||
disabled?: boolean;
|
||||
mode?: 'button' | 'input';
|
||||
accept?: UploadType;
|
||||
multiple?: boolean;
|
||||
inputClass?: string;
|
||||
inputSize?: 'small' | 'medium' | 'large' | 'mini';
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
:get-list-fun-params="props.getListFunParams"
|
||||
:selector-type="props.selectorType"
|
||||
:file-all-count-by-storage="fileAllCountByStorage"
|
||||
:filetype="props.filetype"
|
||||
@init="handleModuleTableInit"
|
||||
/>
|
||||
</template>
|
||||
|
@ -105,6 +106,7 @@
|
|||
getListRequest: (params: TableQueryParams) => Promise<CommonList<AssociatedList>>; // 获取表格请求
|
||||
getListFunParams: TableQueryParams; // 关联表去重id
|
||||
selectorType?: 'none' | 'checkbox' | 'radio';
|
||||
filetype?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
><span class="ml-[4px] text-[var(--color-text-4)]">({{ moduleInfo.count }})</span></div
|
||||
>
|
||||
<div class="header-right">
|
||||
<a-select v-model="tableFileType" class="w-[240px]" :loading="fileTypeLoading" @change="searchList">
|
||||
<a-select
|
||||
v-model="tableFileType"
|
||||
class="w-[240px]"
|
||||
:loading="fileTypeLoading"
|
||||
:disabled="!!props.filetype"
|
||||
@change="searchList"
|
||||
>
|
||||
<a-option key="" value="">{{ t('common.all') }}</a-option>
|
||||
<a-option v-for="item of tableFileTypeOptions" :key="item" :value="item">
|
||||
{{ item }}
|
||||
|
@ -91,6 +97,7 @@
|
|||
getListFunParams: TableQueryParams; // 表格额外去重参数
|
||||
selectorType?: 'none' | 'checkbox' | 'radio';
|
||||
fileAllCountByStorage: number;
|
||||
filetype?: string;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'init', params: FileListQueryParams): void;
|
||||
|
@ -98,7 +105,7 @@
|
|||
}>();
|
||||
|
||||
const tableFileTypeOptions = ref<string[]>([]);
|
||||
const tableFileType = ref(''); // 文件格式筛选
|
||||
const tableFileType = ref(props.filetype || ''); // 文件格式筛选
|
||||
const keyword = ref('');
|
||||
const fileTypeLoading = ref(false);
|
||||
const fileType = ref('module'); // 当前查看的文件类型,模块/存储库
|
||||
|
@ -249,7 +256,7 @@
|
|||
} else {
|
||||
res = await getFileTypes(appStore.currentProjectId);
|
||||
}
|
||||
tableFileType.value = '';
|
||||
tableFileType.value = props.filetype || '';
|
||||
tableFileTypeOptions.value = res;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -260,6 +260,7 @@
|
|||
id: 'fileId',
|
||||
name: 'fileAlias',
|
||||
}"
|
||||
:accept="columnConfig.accept"
|
||||
:file-save-as-source-id="props.fileSaveAsSourceId"
|
||||
:file-save-as-api="props.fileSaveAsApi"
|
||||
:file-module-options-api="props.fileModuleOptionsApi"
|
||||
|
@ -280,7 +281,7 @@
|
|||
/>
|
||||
</template>
|
||||
<!-- 文件 -->
|
||||
<template #file="{ record, rowIndex }">
|
||||
<template #file="{ record, rowIndex, columnConfig }">
|
||||
<MsAddAttachment
|
||||
:file-list="[record.file]"
|
||||
:disabled="props.disabledParamValue"
|
||||
|
@ -290,6 +291,7 @@
|
|||
id: 'fileId',
|
||||
name: 'fileAlias',
|
||||
}"
|
||||
:accept="columnConfig.accept"
|
||||
:file-save-as-source-id="props.fileSaveAsSourceId"
|
||||
:file-save-as-api="props.fileSaveAsApi"
|
||||
:file-module-options-api="props.fileModuleOptionsApi"
|
||||
|
@ -619,7 +621,7 @@
|
|||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
import MsTagsGroup from '@/components/pure/ms-tag/ms-tag-group.vue';
|
||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||
import { MsFileItem } from '@/components/pure/ms-upload/types';
|
||||
import { MsFileItem, UploadType } from '@/components/pure/ms-upload/types';
|
||||
import MsSelect from '@/components/business/ms-select/index';
|
||||
import paramDescInput from './paramDescInput.vue';
|
||||
import DomainModal from '@/views/project-management/environmental/components/envParams/popUp/domain.vue';
|
||||
|
@ -656,6 +658,7 @@
|
|||
format?: RequestBodyFormat; // 用于 operation 列区分是否有请求体格式选择器
|
||||
addLineDisabled?: boolean; // 用于 是否禁用添加新行
|
||||
disabledColumn?: boolean; // 用于禁用某一列不能编辑
|
||||
accept?: UploadType; // 用于文件上传列的 accept 属性
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
|
|
|
@ -169,6 +169,7 @@
|
|||
title: 'apiScenario.params.file',
|
||||
dataIndex: 'file',
|
||||
slotName: 'file',
|
||||
accept: 'csv',
|
||||
},
|
||||
{
|
||||
title: 'apiScenario.table.columns.status',
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
{{ title }}
|
||||
</div>
|
||||
<MsIcon
|
||||
v-if="!props.step || !props.step.isQuoteScenarioStep"
|
||||
type="icon-icon_edit_outlined"
|
||||
class="cursor-pointer hover:text-[rgb(var(--primary-5))]"
|
||||
@click="isShowEditStepNameInput = true"
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
>
|
||||
</a-tooltip>
|
||||
<MsIcon
|
||||
v-if="!activeStep || !activeStep.isQuoteScenarioStep"
|
||||
type="icon-icon_edit_outlined"
|
||||
class="cursor-pointer hover:text-[rgb(var(--primary-5))]"
|
||||
@click="showEditScriptNameInput"
|
||||
|
|
|
@ -480,7 +480,6 @@
|
|||
import saveAsApiModal from '@/views/api-test/components/saveAsApiModal.vue';
|
||||
|
||||
import { addCase, getDefinitionDetail } from '@/api/modules/api-test/management';
|
||||
import { getScenarioDetail, getScenarioStep } from '@/api/modules/api-test/scenario';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
|
@ -495,7 +494,6 @@
|
|||
import {
|
||||
CreateStepAction,
|
||||
Scenario,
|
||||
ScenarioStepConfig,
|
||||
ScenarioStepDetails,
|
||||
ScenarioStepFileParams,
|
||||
ScenarioStepItem,
|
||||
|
@ -514,7 +512,6 @@
|
|||
import useStepNodeEdit from './useStepNodeEdit';
|
||||
import useStepOperation from './useStepOperation';
|
||||
import { casePriorityOptions, caseStatusOptions } from '@/views/api-test/components/config';
|
||||
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||
import getStepType from '@/views/api-test/scenario/components/common/stepType/utils';
|
||||
import { defaultStepItemCommon } from '@/views/api-test/scenario/components/config';
|
||||
|
||||
|
@ -728,151 +725,68 @@
|
|||
return stepMoreActions;
|
||||
}
|
||||
|
||||
const scenarioConfigForm = ref<
|
||||
ScenarioStepConfig & {
|
||||
refType: ScenarioStepRefType;
|
||||
}
|
||||
>({
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
});
|
||||
const showScenarioConfig = ref(false);
|
||||
// const scenarioConfigParamTip = computed(() => {
|
||||
// if (!scenarioConfigForm.value.useOriginScenarioParam && !scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// // 非使用原场景参数-非选择源场景环境
|
||||
// return t('apiScenario.notSource');
|
||||
// }
|
||||
// if (!scenarioConfigForm.value.useOriginScenarioParam && scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// // 非使用原场景参数-选择源场景环境
|
||||
// return t('apiScenario.notSourceParamAndSourceEnv');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// !scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用原场景参数
|
||||
// return t('apiScenario.sourceParamAndSource');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用原场景参数-选择源场景环境
|
||||
// return t('apiScenario.sourceParamAndSourceEnv');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// !scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// !scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用当前场景参数
|
||||
// return t('apiScenario.currentParamAndSource');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// !scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用当前场景参数-选择源场景环境
|
||||
// return t('apiScenario.currentParamAndSourceEnv');
|
||||
// }
|
||||
// });
|
||||
|
||||
// 关闭场景配置弹窗
|
||||
function cancelScenarioConfig() {
|
||||
showScenarioConfig.value = false;
|
||||
scenarioConfigForm.value = {
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新引用场景的步骤数据
|
||||
* 处理api、case、场景步骤名称编辑
|
||||
*/
|
||||
async function refreshScenarioStepInfo(step: ScenarioStepItem, id: string | number) {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await getScenarioDetail(id);
|
||||
if (step.children) {
|
||||
step.children = mapTree(res.steps || [], (child) => {
|
||||
child.uniqueId = getGenerateId();
|
||||
child.isQuoteScenarioStep = true; // 标记为引用场景下的子步骤
|
||||
child.isRefScenarioStep = true; // 标记为完全引用场景
|
||||
child.draggable = false; // 引用场景下的任何步骤不可拖拽
|
||||
if (selectedKeys.value.includes(step.uniqueId) && !selectedKeys.value.includes(child.uniqueId)) {
|
||||
// 如果有新增的子步骤,且当前步骤被选中,则这个新增的子步骤也要选中
|
||||
selectedKeys.value.push(child.uniqueId);
|
||||
}
|
||||
return child;
|
||||
}) as ScenarioStepItem[];
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
const showStepNameEditInputStepId = ref<string | number>('');
|
||||
const tempStepName = ref('');
|
||||
/**
|
||||
* 处理非 api、case、场景步骤名称编辑
|
||||
*/
|
||||
const showStepDescEditInputStepId = ref<string | number>('');
|
||||
const tempStepDesc = ref('');
|
||||
const importApiDrawerVisible = ref(false);
|
||||
const customCaseDrawerVisible = ref(false);
|
||||
const customApiDrawerVisible = ref(false);
|
||||
const scriptOperationDrawerVisible = ref(false);
|
||||
|
||||
// 应用场景配置
|
||||
async function saveScenarioConfig() {
|
||||
if (activeStep.value) {
|
||||
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, activeStep.value.uniqueId, 'uniqueId');
|
||||
if (realStep) {
|
||||
realStep.refType = scenarioConfigForm.value.refType; // 更新场景引用类型
|
||||
realStep.config = {
|
||||
...realStep.config,
|
||||
...scenarioConfigForm.value,
|
||||
};
|
||||
if (scenarioConfigForm.value.refType === ScenarioStepRefType.REF) {
|
||||
// 更新子孙步骤完全引用
|
||||
await refreshScenarioStepInfo(realStep as ScenarioStepItem, realStep.resourceId);
|
||||
} else {
|
||||
realStep.children = mapTree<ScenarioStepItem>(realStep.children || [], (child) => {
|
||||
// 更新子孙步骤-步骤引用
|
||||
child.isRefScenarioStep = false;
|
||||
return child;
|
||||
const { handleStepExpand, handleStepSelect, deleteStep, handleDrop, getStepDetail } = useStepOperation({
|
||||
scenario,
|
||||
steps,
|
||||
stepDetails,
|
||||
activeStep,
|
||||
selectedKeys,
|
||||
customApiDrawerVisible,
|
||||
customCaseDrawerVisible,
|
||||
scriptOperationDrawerVisible,
|
||||
loading,
|
||||
});
|
||||
}
|
||||
Message.success(t('apiScenario.setSuccess'));
|
||||
scenario.value.unSaved = true;
|
||||
cancelScenarioConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getStepDetail(step: ScenarioStepItem) {
|
||||
try {
|
||||
appStore.showLoading();
|
||||
const res = await getScenarioStep(step.copyFromStepId || step.id);
|
||||
let parseRequestBodyResult;
|
||||
if (step.config.protocol === 'HTTP' && res.body) {
|
||||
parseRequestBodyResult = parseRequestBodyFiles(res.body); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
||||
}
|
||||
stepDetails.value[step.id] = {
|
||||
...res,
|
||||
stepId: step.id,
|
||||
protocol: step.config.protocol || '',
|
||||
method: step.config.method || '',
|
||||
...parseRequestBodyResult,
|
||||
};
|
||||
scenario.value.stepFileParam[step.id] = {
|
||||
...parseRequestBodyResult,
|
||||
};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
appStore.hideLoading();
|
||||
}
|
||||
}
|
||||
const showQuickInput = ref(false);
|
||||
const quickInputParamValue = ref<any>('');
|
||||
const quickInputDataKey = ref('');
|
||||
|
||||
const {
|
||||
setQuickInput,
|
||||
clearQuickInput,
|
||||
applyQuickInput,
|
||||
handleStepDescClick,
|
||||
applyStepDescChange,
|
||||
handleStepContentChange,
|
||||
handleStepToggleEnable,
|
||||
handleStepNameClick,
|
||||
applyStepNameChange,
|
||||
saveScenarioConfig,
|
||||
cancelScenarioConfig,
|
||||
scenarioConfigForm,
|
||||
} = useStepNodeEdit({
|
||||
steps,
|
||||
scenario,
|
||||
activeStep,
|
||||
quickInputDataKey,
|
||||
quickInputParamValue,
|
||||
showQuickInput,
|
||||
treeRef,
|
||||
tempStepDesc,
|
||||
showStepDescEditInputStepId,
|
||||
tempStepName,
|
||||
showStepNameEditInputStepId,
|
||||
loading,
|
||||
selectedKeys,
|
||||
showScenarioConfig,
|
||||
});
|
||||
|
||||
const saveNewApiModalVisible = ref(false);
|
||||
const tempApiDetail = ref<RequestParam>();
|
||||
|
@ -1109,20 +1023,6 @@
|
|||
treeRef.value?.checkAll(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理api、case、场景步骤名称编辑
|
||||
*/
|
||||
const showStepNameEditInputStepId = ref<string | number>('');
|
||||
const tempStepName = ref('');
|
||||
/**
|
||||
* 处理非 api、case、场景步骤名称编辑
|
||||
*/
|
||||
const showStepDescEditInputStepId = ref<string | number>('');
|
||||
const tempStepDesc = ref('');
|
||||
const importApiDrawerVisible = ref(false);
|
||||
const customCaseDrawerVisible = ref(false);
|
||||
const customApiDrawerVisible = ref(false);
|
||||
const scriptOperationDrawerVisible = ref(false);
|
||||
const activeCreateAction = ref<CreateStepAction>(); // 用于抽屉操作创建步骤时记录当前插入类型
|
||||
const currentStepDetail = computed<ScenarioStepDetails | undefined>(() => {
|
||||
if (activeStep.value) {
|
||||
|
@ -1143,18 +1043,6 @@
|
|||
scenario.value.unSaved = true;
|
||||
}
|
||||
|
||||
const { handleStepExpand, handleStepSelect, deleteStep, handleDrop } = useStepOperation({
|
||||
scenario,
|
||||
steps,
|
||||
stepDetails,
|
||||
activeStep,
|
||||
selectedKeys,
|
||||
customApiDrawerVisible,
|
||||
customCaseDrawerVisible,
|
||||
scriptOperationDrawerVisible,
|
||||
loading,
|
||||
});
|
||||
|
||||
function handleReplaceStep(newStep: ScenarioStepItem) {
|
||||
if (activeStep.value) {
|
||||
// 替换步骤,删除原本的详情数据
|
||||
|
@ -1343,14 +1231,13 @@
|
|||
}
|
||||
if (activeStep.value) {
|
||||
const _stepType = getStepType(activeStep.value);
|
||||
if (_stepType.isQuoteCase || activeStep.value.isQuoteScenarioStep) {
|
||||
// 引用的 case 和引用的场景步骤都不可更改(除了步骤名)
|
||||
if (_stepType.isQuoteCase && !activeStep.value.isQuoteScenarioStep) {
|
||||
activeStep.value.name = request.stepName || request.name;
|
||||
stepDetails.value[activeStep.value.id] = request; // 为了设置一次正确的polymorphicName
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (activeStep.value) {
|
||||
if (activeStep.value && !activeStep.value.isQuoteScenarioStep) {
|
||||
request.isNew = false;
|
||||
stepDetails.value[activeStep.value.id] = request;
|
||||
scenario.value.stepFileParam[activeStep.value?.id] = {
|
||||
|
@ -1363,10 +1250,9 @@
|
|||
...activeStep.value.config,
|
||||
method: request.method,
|
||||
};
|
||||
activeStep.value.name = request.stepName || request.name;
|
||||
emit('updateResource', request.uploadFileIds, request.linkFileIds);
|
||||
activeStep.value = undefined;
|
||||
}
|
||||
activeStep.value = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1408,7 +1294,8 @@
|
|||
}
|
||||
|
||||
function saveScriptStep(name: string, scriptProcessor: ExecuteConditionProcessor, unSaved = false) {
|
||||
if (activeStep.value) {
|
||||
if (activeStep.value && !activeStep.value.isQuoteScenarioStep) {
|
||||
// 引用的场景步骤不需要存储详情
|
||||
stepDetails.value[activeStep.value.id] = cloneDeep(scriptProcessor);
|
||||
activeStep.value.name = name;
|
||||
activeStep.value = undefined;
|
||||
|
@ -1418,34 +1305,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
const showQuickInput = ref(false);
|
||||
const quickInputParamValue = ref<any>('');
|
||||
const quickInputDataKey = ref('');
|
||||
|
||||
const {
|
||||
setQuickInput,
|
||||
clearQuickInput,
|
||||
applyQuickInput,
|
||||
handleStepDescClick,
|
||||
applyStepDescChange,
|
||||
handleStepContentChange,
|
||||
handleStepToggleEnable,
|
||||
handleStepNameClick,
|
||||
applyStepNameChange,
|
||||
} = useStepNodeEdit({
|
||||
steps,
|
||||
scenario,
|
||||
activeStep,
|
||||
quickInputDataKey,
|
||||
quickInputParamValue,
|
||||
showQuickInput,
|
||||
treeRef,
|
||||
tempStepDesc,
|
||||
showStepDescEditInputStepId,
|
||||
tempStepName,
|
||||
showStepNameEditInputStepId,
|
||||
});
|
||||
|
||||
const dbClick = ref({
|
||||
e: null as MouseEvent | null,
|
||||
timeStamp: 0,
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import MsTree from '@/components/business/ms-tree/index.vue';
|
||||
|
||||
import { findNodeByKey } from '@/utils';
|
||||
import { getScenarioDetail } from '@/api/modules/api-test/scenario';
|
||||
import { t } from '@/hooks/useI18n';
|
||||
import { findNodeByKey, getGenerateId, mapTree } from '@/utils';
|
||||
|
||||
import type { Scenario, ScenarioStepDetail, ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||
import type { Scenario, ScenarioStepConfig, ScenarioStepDetail, ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||
import { ScenarioStepRefType } from '@/enums/apiEnum';
|
||||
|
||||
/**
|
||||
* 处理步骤节点信息更改
|
||||
|
@ -19,6 +24,9 @@ export default function useStepNodeEdit({
|
|||
showStepDescEditInputStepId,
|
||||
tempStepName,
|
||||
showStepNameEditInputStepId,
|
||||
loading,
|
||||
selectedKeys,
|
||||
showScenarioConfig,
|
||||
}: {
|
||||
steps: Ref<ScenarioStepItem[]>;
|
||||
scenario: Ref<Scenario>;
|
||||
|
@ -31,6 +39,9 @@ export default function useStepNodeEdit({
|
|||
showStepDescEditInputStepId: Ref<string | number>;
|
||||
tempStepName: Ref<string>;
|
||||
showStepNameEditInputStepId: Ref<string | number>;
|
||||
loading: Ref<boolean>;
|
||||
selectedKeys: Ref<Array<string | number>>;
|
||||
showScenarioConfig: Ref<boolean>;
|
||||
}) {
|
||||
/**
|
||||
* 打开快速输入
|
||||
|
@ -162,6 +173,125 @@ export default function useStepNodeEdit({
|
|||
scenario.value.unSaved = !!tempStepName.value;
|
||||
}
|
||||
|
||||
const scenarioConfigForm = ref<
|
||||
ScenarioStepConfig & {
|
||||
refType: ScenarioStepRefType;
|
||||
}
|
||||
>({
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
});
|
||||
// const scenarioConfigParamTip = computed(() => {
|
||||
// if (!scenarioConfigForm.value.useOriginScenarioParam && !scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// // 非使用原场景参数-非选择源场景环境
|
||||
// return t('apiScenario.notSource');
|
||||
// }
|
||||
// if (!scenarioConfigForm.value.useOriginScenarioParam && scenarioConfigForm.value.enableScenarioEnv) {
|
||||
// // 非使用原场景参数-选择源场景环境
|
||||
// return t('apiScenario.notSourceParamAndSourceEnv');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// !scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用原场景参数
|
||||
// return t('apiScenario.sourceParamAndSource');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用原场景参数-选择源场景环境
|
||||
// return t('apiScenario.sourceParamAndSourceEnv');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// !scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// !scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用当前场景参数
|
||||
// return t('apiScenario.currentParamAndSource');
|
||||
// }
|
||||
// if (
|
||||
// scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
// !scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
// scenarioConfigForm.value.enableScenarioEnv
|
||||
// ) {
|
||||
// // 使用原场景参数-优先使用当前场景参数-选择源场景环境
|
||||
// return t('apiScenario.currentParamAndSourceEnv');
|
||||
// }
|
||||
// });
|
||||
|
||||
// 关闭场景配置弹窗
|
||||
function cancelScenarioConfig() {
|
||||
showScenarioConfig.value = false;
|
||||
scenarioConfigForm.value = {
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新引用场景的步骤数据
|
||||
*/
|
||||
async function refreshScenarioStepInfo(step: ScenarioStepItem, id: string | number) {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await getScenarioDetail(id);
|
||||
if (step.children) {
|
||||
step.children = mapTree(res.steps || [], (child) => {
|
||||
child.uniqueId = getGenerateId();
|
||||
child.isQuoteScenarioStep = true; // 标记为引用场景下的子步骤
|
||||
child.isRefScenarioStep = true; // 标记为完全引用场景
|
||||
child.draggable = false; // 引用场景下的任何步骤不可拖拽
|
||||
if (selectedKeys.value.includes(step.uniqueId) && !selectedKeys.value.includes(child.uniqueId)) {
|
||||
// 如果有新增的子步骤,且当前步骤被选中,则这个新增的子步骤也要选中
|
||||
selectedKeys.value.push(child.uniqueId);
|
||||
}
|
||||
return child;
|
||||
}) as ScenarioStepItem[];
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 应用场景配置
|
||||
async function saveScenarioConfig() {
|
||||
if (activeStep.value) {
|
||||
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, activeStep.value.uniqueId, 'uniqueId');
|
||||
if (realStep) {
|
||||
realStep.refType = scenarioConfigForm.value.refType; // 更新场景引用类型
|
||||
realStep.config = {
|
||||
...realStep.config,
|
||||
...scenarioConfigForm.value,
|
||||
};
|
||||
if (scenarioConfigForm.value.refType === ScenarioStepRefType.REF) {
|
||||
// 更新子孙步骤完全引用
|
||||
await refreshScenarioStepInfo(realStep as ScenarioStepItem, realStep.resourceId);
|
||||
} else {
|
||||
realStep.children = mapTree<ScenarioStepItem>(realStep.children || [], (child) => {
|
||||
// 更新子孙步骤-步骤引用
|
||||
child.isRefScenarioStep = false;
|
||||
return child;
|
||||
});
|
||||
}
|
||||
Message.success(t('apiScenario.setSuccess'));
|
||||
scenario.value.unSaved = true;
|
||||
cancelScenarioConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
setQuickInput,
|
||||
clearQuickInput,
|
||||
|
@ -172,5 +302,8 @@ export default function useStepNodeEdit({
|
|||
handleStepToggleEnable,
|
||||
handleStepNameClick,
|
||||
applyStepNameChange,
|
||||
saveScenarioConfig,
|
||||
cancelScenarioConfig,
|
||||
scenarioConfigForm,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ export default function useStepOperation({
|
|||
}
|
||||
|
||||
return {
|
||||
getStepDetail,
|
||||
handleStepExpand,
|
||||
handleStepSelect,
|
||||
deleteStep,
|
||||
|
|
|
@ -317,7 +317,10 @@
|
|||
const waitTingDebugSteps = filterTree(activeScenarioTab.value.steps, (node) => {
|
||||
if (node.enable) {
|
||||
node.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||
if (!node.isQuoteScenarioStep) {
|
||||
// 引用场景的步骤详情不传
|
||||
waitingDebugStepDetails[node.id] = activeScenarioTab.value.stepDetails[node.id];
|
||||
}
|
||||
} else {
|
||||
node.executeStatus = undefined;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue