fix(接口测试): 文件 id 问题修复
This commit is contained in:
parent
ab4676b2e2
commit
76adb0d402
|
@ -115,7 +115,7 @@ export interface RequestFileInfo {
|
||||||
export interface ExecuteBinaryBody {
|
export interface ExecuteBinaryBody {
|
||||||
description: string;
|
description: string;
|
||||||
file?: RequestFileInfo;
|
file?: RequestFileInfo;
|
||||||
sendAsBody?: boolean; // 是否作为正文发送,只有 mock 有此字段
|
sendAsBody?: boolean; // 是否作为正文发送,只有 定义/mock 的响应体有此字段
|
||||||
}
|
}
|
||||||
// 接口请求-JsonSchema
|
// 接口请求-JsonSchema
|
||||||
export interface JsonSchema {
|
export interface JsonSchema {
|
||||||
|
|
|
@ -92,6 +92,7 @@ export const defaultResponseItem: ResponseDefinition = {
|
||||||
binaryBody: {
|
binaryBody: {
|
||||||
description: '',
|
description: '',
|
||||||
file: undefined,
|
file: undefined,
|
||||||
|
sendAsBody: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -112,6 +113,7 @@ export const defaultBodyParams: ExecuteBody = {
|
||||||
binaryBody: {
|
binaryBody: {
|
||||||
description: '',
|
description: '',
|
||||||
file: undefined,
|
file: undefined,
|
||||||
|
sendAsBody: false,
|
||||||
},
|
},
|
||||||
rawBody: { value: '' },
|
rawBody: { value: '' },
|
||||||
};
|
};
|
||||||
|
|
|
@ -456,6 +456,7 @@
|
||||||
).validParams;
|
).validParams;
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(
|
parseRequestBodyResult = parseRequestBodyFiles(
|
||||||
requestVModel.value.body,
|
requestVModel.value.body,
|
||||||
|
requestVModel.value.responseDefinition,
|
||||||
requestVModel.value.uploadFileIds, // 外面解析详情的时候传入
|
requestVModel.value.uploadFileIds, // 外面解析详情的时候传入
|
||||||
requestVModel.value.linkFileIds // 外面解析详情的时候传入
|
requestVModel.value.linkFileIds // 外面解析详情的时候传入
|
||||||
);
|
);
|
||||||
|
|
|
@ -1083,6 +1083,7 @@
|
||||||
).validParams;
|
).validParams;
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(
|
parseRequestBodyResult = parseRequestBodyFiles(
|
||||||
requestVModel.value.body,
|
requestVModel.value.body,
|
||||||
|
requestVModel.value.responseDefinition,
|
||||||
requestVModel.value.uploadFileIds, // 外面解析详情的时候传入
|
requestVModel.value.uploadFileIds, // 外面解析详情的时候传入
|
||||||
requestVModel.value.linkFileIds // 外面解析详情的时候传入
|
requestVModel.value.linkFileIds // 外面解析详情的时候传入
|
||||||
);
|
);
|
||||||
|
@ -1292,6 +1293,12 @@
|
||||||
Message.success(t('common.updateSuccess'));
|
Message.success(t('common.updateSuccess'));
|
||||||
requestVModel.value.updateTime = res.updateTime;
|
requestVModel.value.updateTime = res.updateTime;
|
||||||
requestVModel.value.unSaved = false;
|
requestVModel.value.unSaved = false;
|
||||||
|
const parseRequestBodyResult = parseRequestBodyFiles(
|
||||||
|
requestVModel.value.body,
|
||||||
|
requestVModel.value.responseDefinition
|
||||||
|
);
|
||||||
|
requestVModel.value.uploadFileIds = parseRequestBodyResult.uploadFileIds;
|
||||||
|
requestVModel.value.linkFileIds = parseRequestBodyResult.linkFileIds;
|
||||||
emit('addDone');
|
emit('addDone');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
|
@ -380,7 +380,7 @@
|
||||||
|
|
||||||
async function handleFileChange() {
|
async function handleFileChange() {
|
||||||
try {
|
try {
|
||||||
if (fileList.value[0]?.local && fileList.value[0].file && props.uploadTempFileApi) {
|
if (fileList.value[0] && fileList.value[0].local && fileList.value[0].file && props.uploadTempFileApi) {
|
||||||
appStore.showLoading();
|
appStore.showLoading();
|
||||||
const res = await props.uploadTempFileApi(fileList.value[0].file);
|
const res = await props.uploadTempFileApi(fileList.value[0].file);
|
||||||
activeResponse.value.body.binaryBody.file = {
|
activeResponse.value.body.binaryBody.file = {
|
||||||
|
@ -391,7 +391,7 @@
|
||||||
local: true,
|
local: true,
|
||||||
};
|
};
|
||||||
appStore.hideLoading();
|
appStore.hideLoading();
|
||||||
} else {
|
} else if (fileList.value[0]) {
|
||||||
activeResponse.value.body.binaryBody.file = {
|
activeResponse.value.body.binaryBody.file = {
|
||||||
...fileList.value[0],
|
...fileList.value[0],
|
||||||
fileId: fileList.value[0].uid,
|
fileId: fileList.value[0].uid,
|
||||||
|
@ -399,8 +399,7 @@
|
||||||
fileAlias: fileList.value[0]?.name || '',
|
fileAlias: fileList.value[0]?.name || '',
|
||||||
local: false,
|
local: false,
|
||||||
};
|
};
|
||||||
}
|
} else {
|
||||||
if (activeResponse.value.body.binaryBody.file && !activeResponse.value.body.binaryBody.file.fileId) {
|
|
||||||
activeResponse.value.body.binaryBody.file = undefined;
|
activeResponse.value.body.binaryBody.file = undefined;
|
||||||
}
|
}
|
||||||
emit('change');
|
emit('change');
|
||||||
|
|
|
@ -163,6 +163,7 @@
|
||||||
item.body.binaryBody = {
|
item.body.binaryBody = {
|
||||||
description: '',
|
description: '',
|
||||||
file: undefined,
|
file: undefined,
|
||||||
|
sendAsBody: false,
|
||||||
};
|
};
|
||||||
hasInvalid = true;
|
hasInvalid = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import { cloneDeep, isEqual } from 'lodash-es';
|
import { cloneDeep, isEqual } from 'lodash-es';
|
||||||
|
|
||||||
import { type ExecuteAssertionConfig, ExecuteBody, type ExecuteConditionConfig } from '@/models/apiTest/common';
|
import {
|
||||||
import { RequestConditionProcessor, RequestParamsType, ResponseBodyAssertionType } from '@/enums/apiEnum';
|
type ExecuteAssertionConfig,
|
||||||
|
ExecuteBody,
|
||||||
|
type ExecuteConditionConfig,
|
||||||
|
type ResponseDefinition,
|
||||||
|
} from '@/models/apiTest/common';
|
||||||
|
import { RequestConditionProcessor, RequestParamsType } from '@/enums/apiEnum';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assertDefaultParamsItem,
|
assertDefaultParamsItem,
|
||||||
defaultAssertParamsItem,
|
defaultAssertParamsItem,
|
||||||
defaultBodyParamsItem,
|
defaultBodyParamsItem,
|
||||||
defaultExtractParamItem,
|
|
||||||
defaultHeaderParamsItem,
|
defaultHeaderParamsItem,
|
||||||
defaultKeyValueParamItem,
|
defaultKeyValueParamItem,
|
||||||
defaultRequestParamsItem,
|
defaultRequestParamsItem,
|
||||||
|
@ -29,6 +33,7 @@ export interface ParseResult {
|
||||||
*/
|
*/
|
||||||
export function parseRequestBodyFiles(
|
export function parseRequestBodyFiles(
|
||||||
body: ExecuteBody,
|
body: ExecuteBody,
|
||||||
|
response?: ResponseDefinition[],
|
||||||
saveUploadFileIds?: string[],
|
saveUploadFileIds?: string[],
|
||||||
saveLinkFileIds?: string[]
|
saveLinkFileIds?: string[]
|
||||||
): ParseResult {
|
): ParseResult {
|
||||||
|
@ -107,6 +112,40 @@ export function parseRequestBodyFiles(
|
||||||
linkFileIds.add(fileId);
|
linkFileIds.add(fileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (response) {
|
||||||
|
response.forEach((res) => {
|
||||||
|
if (res.body.binaryBody && res.body.binaryBody.file) {
|
||||||
|
const { fileId } = res.body.binaryBody.file;
|
||||||
|
if (res.body.binaryBody.file?.local) {
|
||||||
|
if (saveUploadFileIds) {
|
||||||
|
// 如果有已保存的上传文件id集合
|
||||||
|
if (saveUploadFileIds.includes(fileId)) {
|
||||||
|
// 当前文件是已保存的文件,存入 tempSaveUploadFileIds
|
||||||
|
tempSaveUploadFileIds.add(fileId);
|
||||||
|
} else {
|
||||||
|
// 当前文件不是已保存的文件,存入 uploadFileIds
|
||||||
|
uploadFileIds.add(fileId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有已保存的文件id集合,直接存入 uploadFileIds
|
||||||
|
uploadFileIds.add(fileId);
|
||||||
|
}
|
||||||
|
} else if (saveLinkFileIds) {
|
||||||
|
// 如果有已保存的关联文件id集合
|
||||||
|
if (saveLinkFileIds.includes(fileId)) {
|
||||||
|
// 当前文件是已保存的文件,存入
|
||||||
|
tempSaveLinkFileIds.add(fileId);
|
||||||
|
} else {
|
||||||
|
// 当前文件不是已保存的文件,存入 uploadFileIds
|
||||||
|
linkFileIds.add(fileId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 关联的文件
|
||||||
|
linkFileIds.add(fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
uploadFileIds: Array.from(uploadFileIds),
|
uploadFileIds: Array.from(uploadFileIds),
|
||||||
linkFileIds: Array.from(linkFileIds),
|
linkFileIds: Array.from(linkFileIds),
|
||||||
|
|
|
@ -92,64 +92,6 @@
|
||||||
</MsCodeEditor>
|
</MsCodeEditor>
|
||||||
</div>
|
</div>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
<!-- <a-modal
|
|
||||||
v-model:visible="saveAsApiModalVisible"
|
|
||||||
:title="t('common.save')"
|
|
||||||
:ok-loading="saveLoading"
|
|
||||||
class="ms-modal-form"
|
|
||||||
title-align="start"
|
|
||||||
body-class="!p-0"
|
|
||||||
@before-ok="handleSave"
|
|
||||||
@cancel="handleCancel"
|
|
||||||
>
|
|
||||||
<a-form ref="saveModalFormRef" :model="saveModalForm" layout="vertical">
|
|
||||||
<a-form-item
|
|
||||||
field="name"
|
|
||||||
:label="t('apiTestDebug.requestName')"
|
|
||||||
:rules="[{ required: true, message: t('apiTestDebug.requestNameRequired') }]"
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:model-value="saveModalForm.name"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('apiTestDebug.requestNamePlaceholder')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="isHttpProtocol"
|
|
||||||
field="path"
|
|
||||||
:label="t('apiTestDebug.requestUrl')"
|
|
||||||
:rules="[{ required: true, message: t('apiTestDebug.requestUrlRequired') }]"
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:model-value="saveModalForm.path"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('apiTestDebug.commonPlaceholder')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item :label="t('apiTestDebug.requestModule')" class="mb-0">
|
|
||||||
<a-tree-select
|
|
||||||
v-model:modelValue="saveModalForm.moduleId"
|
|
||||||
:data="apiModules as ModuleTreeNode[]"
|
|
||||||
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
|
||||||
:tree-props="{
|
|
||||||
virtualListProps: {
|
|
||||||
height: 200,
|
|
||||||
threshold: 200,
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
allow-search
|
|
||||||
>
|
|
||||||
<template #tree-slot-title="node">
|
|
||||||
<a-tooltip :content="`${node.name}`" position="tl">
|
|
||||||
<div class="one-line-text w-[300px] text-[var(--color-text-1)]">{{ node.name }}</div>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-tree-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-modal> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -166,7 +108,6 @@
|
||||||
import MsEditableTab from '@/components/pure/ms-editable-tab/index.vue';
|
import MsEditableTab from '@/components/pure/ms-editable-tab/index.vue';
|
||||||
import { TabItem } from '@/components/pure/ms-editable-tab/types';
|
import { TabItem } from '@/components/pure/ms-editable-tab/types';
|
||||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||||
import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
|
|
||||||
import moduleTree from './components/moduleTree.vue';
|
import moduleTree from './components/moduleTree.vue';
|
||||||
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
|
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
|
||||||
import debug, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
import debug, { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
||||||
|
@ -181,10 +122,8 @@
|
||||||
updateDebug,
|
updateDebug,
|
||||||
uploadTempFile,
|
uploadTempFile,
|
||||||
} from '@/api/modules/api-test/debug';
|
} from '@/api/modules/api-test/debug';
|
||||||
import { getModuleTreeOnlyModules } from '@/api/modules/api-test/management';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useLeaveTabUnSaveCheck from '@/hooks/useLeaveTabUnSaveCheck';
|
import useLeaveTabUnSaveCheck from '@/hooks/useLeaveTabUnSaveCheck';
|
||||||
import useAppStore from '@/store/modules/app';
|
|
||||||
import { parseCurlScript } from '@/utils';
|
import { parseCurlScript } from '@/utils';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
@ -200,9 +139,7 @@
|
||||||
|
|
||||||
import { defaultBodyParams, defaultResponse } from '../components/config';
|
import { defaultBodyParams, defaultResponse } from '../components/config';
|
||||||
import { parseRequestBodyFiles } from '../components/utils';
|
import { parseRequestBodyFiles } from '../components/utils';
|
||||||
import type { FormInstance } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -418,25 +355,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveAsApiModalVisible = ref(false);
|
|
||||||
const saveModalForm = ref({
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
path: '',
|
|
||||||
moduleId: 'root',
|
|
||||||
});
|
|
||||||
const saveModalFormRef = ref<FormInstance>();
|
|
||||||
const saveLoading = ref(false);
|
|
||||||
const apiModules = ref<ModuleTreeNode[]>([]);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => saveAsApiModalVisible.value,
|
|
||||||
(val) => {
|
|
||||||
if (!val) {
|
|
||||||
saveModalFormRef.value?.resetFields();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
/**
|
/**
|
||||||
async function openSaveAsApiModal(node: MsTreeNodeData) {
|
async function openSaveAsApiModal(node: MsTreeNodeData) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -334,7 +334,7 @@
|
||||||
}
|
}
|
||||||
let parseRequestBodyResult;
|
let parseRequestBodyResult;
|
||||||
if (res.protocol === 'HTTP') {
|
if (res.protocol === 'HTTP') {
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
parseRequestBodyResult = parseRequestBodyFiles(res.request.body, res.response); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
||||||
}
|
}
|
||||||
addApiTab({
|
addApiTab({
|
||||||
label: name,
|
label: name,
|
||||||
|
|
|
@ -1022,6 +1022,7 @@
|
||||||
).validParams;
|
).validParams;
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(
|
parseRequestBodyResult = parseRequestBodyFiles(
|
||||||
requestVModel.value.body,
|
requestVModel.value.body,
|
||||||
|
undefined,
|
||||||
props.fileParams?.uploadFileIds || requestVModel.value.uploadFileIds, // 外面解析详情的时候传入,或引用 api 在requestVModel内存储
|
props.fileParams?.uploadFileIds || requestVModel.value.uploadFileIds, // 外面解析详情的时候传入,或引用 api 在requestVModel内存储
|
||||||
props.fileParams?.linkFileIds || requestVModel.value.linkFileIds // 外面解析详情的时候传入,或引用 api 在requestVModel内存储
|
props.fileParams?.linkFileIds || requestVModel.value.linkFileIds // 外面解析详情的时候传入,或引用 api 在requestVModel内存储
|
||||||
);
|
);
|
||||||
|
@ -1220,7 +1221,7 @@
|
||||||
const res = await getDefinitionDetail(props.step?.resourceId || '');
|
const res = await getDefinitionDetail(props.step?.resourceId || '');
|
||||||
let parseRequestBodyResult;
|
let parseRequestBodyResult;
|
||||||
if (res.protocol === 'HTTP') {
|
if (res.protocol === 'HTTP') {
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
parseRequestBodyResult = parseRequestBodyFiles(res.request.body, res.response); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
||||||
}
|
}
|
||||||
requestVModel.value = {
|
requestVModel.value = {
|
||||||
executeLoading: false,
|
executeLoading: false,
|
||||||
|
|
|
@ -860,6 +860,7 @@
|
||||||
// 复制 case 才能编辑,才需要计算
|
// 复制 case 才能编辑,才需要计算
|
||||||
parseRequestBodyResult = parseRequestBodyFiles(
|
parseRequestBodyResult = parseRequestBodyFiles(
|
||||||
requestVModel.value.body,
|
requestVModel.value.body,
|
||||||
|
undefined,
|
||||||
props.fileParams?.uploadFileIds || requestVModel.value.uploadFileIds, // 外面解析详情的时候传入,或引用 case 在requestVModel内存储
|
props.fileParams?.uploadFileIds || requestVModel.value.uploadFileIds, // 外面解析详情的时候传入,或引用 case 在requestVModel内存储
|
||||||
props.fileParams?.linkFileIds || requestVModel.value.linkFileIds // 外面解析详情的时候传入,或引用 case 在requestVModel内存储
|
props.fileParams?.linkFileIds || requestVModel.value.linkFileIds // 外面解析详情的时候传入,或引用 case 在requestVModel内存储
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue