fix(接口场景): 调整引用case&删除冗余代码

This commit is contained in:
teukkk 2024-03-29 15:10:38 +08:00 committed by Craftsman
parent d7135d57f7
commit 8bb7b0c86c
7 changed files with 89 additions and 151 deletions

View File

@ -712,7 +712,6 @@
// HTTP tabs
if (isHttpProtocol.value) {
if (props.isCase) {
// BODY/QUERY/RESTtab
return httpContentTabList;
}
if (props.isDefinition) {

View File

@ -455,7 +455,7 @@
slotName: 'action',
dataIndex: 'operation',
fixed: 'right',
width: hasOperationPermission.value ? 200 : 50,
width: hasOperationPermission.value ? 220 : 50,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(

View File

@ -54,8 +54,8 @@
<template #label>
<span class="text-[var(--color-text-2)]"> <caseLevel :case-level="record.priority" /></span>
</template>
<a-option v-for="item of caseLevelList" :key="item.value" :value="item.value">
<caseLevel :case-level="item.text" />
<a-option v-for="item of casePriorityOptions" :key="item.value" :value="item.value">
<caseLevel :case-level="item.label as CaseLevel" />
</a-option>
</a-select>
<span v-else class="text-[var(--color-text-2)]"> <caseLevel :case-level="record.priority" /></span>
@ -70,8 +70,8 @@
<div class="arco-table-filters-content">
<div class="ml-[6px] flex items-center justify-start px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="caseFilters" direction="vertical" size="small">
<a-checkbox v-for="item of caseLevelList" :key="item.text" :value="item.text">
<caseLevel :case-level="item.text" />
<a-checkbox v-for="item of casePriorityOptions" :key="item.value" :value="item.value">
<caseLevel :case-level="item.label as CaseLevel" />
</a-checkbox>
</a-checkbox-group>
</div>
@ -287,7 +287,7 @@
>
<a-select v-model="batchForm.value" :placeholder="t('common.pleaseSelect')" :disabled="batchForm.attr === ''">
<a-option v-for="item of valueOptions" :key="item.value" :value="item.value">
{{ t(item.text) }}
{{ t(item.label) }}
</a-option>
</a-select>
</a-form-item>
@ -359,6 +359,7 @@
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
import caseDetailDrawer from './caseDetailDrawer.vue';
import caseReportDrawer from './caseReportDrawer.vue';
import createAndEditCaseDrawer from './createAndEditCaseDrawer.vue';
@ -377,7 +378,6 @@
updateCasePriority,
updateCaseStatus,
} from '@/api/modules/api-test/management';
import { getCaseDefaultFields } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
@ -390,6 +390,7 @@
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { casePriorityOptions } from '@/views/api-test/components/config';
import type { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
@ -552,7 +553,7 @@
slotName: 'operation',
dataIndex: 'operation',
fixed: 'right',
width: hasOperationPermission.value ? 200 : 50,
width: hasOperationPermission.value ? 220 : 50,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getCasePage, {
@ -597,12 +598,8 @@
const statusFilterVisible = ref(false);
const statusFilters = ref<string[]>([]);
const caseLevelFields = ref<Record<string, any>>({});
const caseFilterVisible = ref(false);
const caseFilters = ref<string[]>([]);
const caseLevelList = computed(() => {
return caseLevelFields.value?.options || [];
});
const lastReportStatusFilterVisible = ref(false);
const lastReportStatusList = computed(() => {
return Object.keys(ReportStatus[ReportEnum.API_REPORT]);
@ -643,15 +640,8 @@
loadCaseList();
}
//
async function getCaseLevelFields() {
const result = await getCaseDefaultFields(appStore.currentProjectId);
caseLevelFields.value = result.customFields.find((item: any) => item.internal && item.fieldName === '用例等级');
}
onBeforeMount(() => {
loadCaseList();
getCaseLevelFields();
});
function handleFilterHidden(val: boolean) {
@ -842,23 +832,23 @@
batchForm.value.value = '';
switch (batchForm.value.attr) {
case 'priority':
return caseLevelList.value;
return casePriorityOptions;
case 'status':
return [
{
text: 'apiTestManagement.processing',
label: 'apiTestManagement.processing',
value: RequestDefinitionStatus.PROCESSING,
},
{
text: 'apiTestManagement.done',
label: 'apiTestManagement.done',
value: RequestDefinitionStatus.DONE,
},
{
text: 'apiTestManagement.deprecate',
label: 'apiTestManagement.deprecate',
value: RequestDefinitionStatus.DEPRECATED,
},
{
text: 'apiTestManagement.debugging',
label: 'apiTestManagement.debugging',
value: RequestDefinitionStatus.DEBUGGING,
},
];

View File

@ -599,17 +599,12 @@
return httpContentTabList;
}
if (!isEditableApi.value) {
return [
...pluginContentTab,
...httpContentTabList
.filter((e) => commonContentTabKey.includes(e.value))
.filter(
(item) =>
!(!preProcessorNum.value && item.value === RequestComposition.PRECONDITION) &&
!(!postProcessorNum.value && item.value === RequestComposition.POST_CONDITION) &&
!(!assertionsNum.value && item.value === RequestComposition.ASSERTION)
),
];
return [...pluginContentTab, ...httpContentTabList.filter((e) => commonContentTabKey.includes(e.value))].filter(
(item) =>
!(!preProcessorNum.value && item.value === RequestComposition.PRECONDITION) &&
!(!postProcessorNum.value && item.value === RequestComposition.POST_CONDITION) &&
!(!assertionsNum.value && item.value === RequestComposition.ASSERTION)
);
}
return [...pluginContentTab, ...httpContentTabList.filter((e) => commonContentTabKey.includes(e.value))];
});
@ -634,7 +629,7 @@
case RequestComposition.ASSERTION:
return `${assertionsNum.value > 99 ? '99+' : assertionsNum.value || ''}`;
case RequestComposition.AUTH:
return requestVModel.value.authConfig.authType !== RequestAuthType.NONE ? '1' : '';
return requestVModel.value.authConfig?.authType !== RequestAuthType.NONE ? '1' : '';
default:
return '';
}
@ -1045,11 +1040,8 @@
props.request?.[type]?.forEach((item) => {
if (!item.key.length) return;
const index = requestVModel.value[type]?.findIndex((itemReq) => itemReq.key === item.key);
// key;key
if (index > -1) {
requestVModel.value[type][index].value = item.value;
} else {
requestVModel.value[type].push(item);
}
});
});
@ -1059,8 +1051,6 @@
const index = requestVModel.value.body[type].formValues.findIndex((itemReq) => itemReq.key === item.key);
if (index > -1) {
requestVModel.value.body[type].formValues[index].value = item.value;
} else {
requestVModel.value.body[type].formValues.push(item);
}
});
});

View File

@ -50,90 +50,45 @@
</template>
</a-empty>
<div v-show="!pluginError || isHttpProtocol" class="flex h-full flex-col">
<div class="px-[18px] pt-[8px]">
<div class="flex flex-wrap items-center justify-between gap-[12px]">
<div class="flex flex-1 items-center gap-[16px]">
<a-select
v-if="requestVModel.isNew"
v-model:model-value="requestVModel.protocol"
:options="protocolOptions"
:loading="protocolLoading"
:disabled="_stepType.isQuoteCase"
class="w-[90px]"
@change="(val) => handleActiveDebugProtocolChange(val as string)"
/>
<div v-else class="flex items-center gap-[4px]">
<apiMethodName
:method="(requestVModel.protocol as RequestMethods)"
tag-background-color="rgb(var(--link-7))"
tag-text-color="white"
is-tag
class="flex items-center"
/>
<a-tooltip v-if="!isHttpProtocol" :content="requestVModel.name" :mouse-enter-delay="500">
<div class="one-line-text max-w-[350px]"> {{ requestVModel.name }}</div>
</a-tooltip>
</div>
<a-input-group v-if="isHttpProtocol" class="flex-1">
<apiMethodSelect
v-model:model-value="requestVModel.method"
class="w-[140px]"
:disabled="_stepType.isQuoteCase"
@change="handleActiveDebugChange"
/>
<a-input
v-model:model-value="requestVModel.url"
:max-length="255"
:placeholder="t('apiTestDebug.urlPlaceholder')"
allow-clear
class="hover:z-10"
:style="isUrlError ? 'border: 1px solid rgb(var(--danger-6);z-index: 10' : ''"
:disabled="_stepType.isQuoteCase"
@input="() => (isUrlError = false)"
@change="handleUrlChange"
/>
</a-input-group>
</div>
<div>
<a-dropdown-button
v-if="hasLocalExec"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
class="exec-btn"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
@select="execute"
>
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
<template #icon>
<icon-down />
</template>
<template #content>
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
</template>
</a-dropdown-button>
<a-button v-else-if="!requestVModel.executeLoading" type="primary" @click="() => execute('serverExec')">
{{ t('apiTestDebug.serverExec') }}
</a-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">{{ t('common.stop') }}</a-button>
</div>
</div>
<div class="flex items-center gap-[16px] p-[16px] pb-[8px]">
<a-input
v-if="activeStep?.stepType && (_stepType.isCopyCase || _stepType.isQuoteCase) && isHttpProtocol"
v-if="activeStep?.stepType && (_stepType.isCopyCase || _stepType.isQuoteCase)"
v-model:model-value="requestVModel.name"
:max-length="255"
:show-word-limit="isEditableApi"
:placeholder="t('apiTestManagement.apiNamePlaceholder')"
:disabled="!isEditableApi"
allow-clear
class="mt-[8px]"
/>
<a-dropdown-button
v-if="hasLocalExec"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
class="exec-btn"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
@select="execute"
>
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
<template #icon>
<icon-down />
</template>
<template #content>
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
</template>
</a-dropdown-button>
<a-button v-else-if="!requestVModel.executeLoading" type="primary" @click="() => execute('serverExec')">
{{ t('apiTestDebug.serverExec') }}
</a-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">{{ t('common.stop') }}</a-button>
</div>
<div class="px-[16px]">
<MsTab
v-model:active-key="requestVModel.activeTab"
:content-tab-list="contentTabList"
:get-text-func="getTabBadge"
class="no-content relative mt-[8px] border-b"
no-content
class="relative mt-[8px] border-b"
/>
</div>
<div ref="splitContainerRef" class="h-[calc(100%-87px)]">
@ -176,6 +131,7 @@
<httpHeader
v-if="requestVModel.activeTab === RequestComposition.HEADER"
v-model:params="requestVModel.headers"
:disabled-param-value="!isEditableApi"
:disabled-except-param="!isEditableApi"
:layout="activeLayout"
:second-box-height="secondBoxHeight"
@ -185,6 +141,7 @@
v-else-if="requestVModel.activeTab === RequestComposition.BODY"
v-model:params="requestVModel.body"
:layout="activeLayout"
:disabled-param-value="!isEditableApi"
:disabled-except-param="!isEditableApi"
:second-box-height="secondBoxHeight"
:upload-temp-file-api="uploadTempFileCase"
@ -197,6 +154,7 @@
v-else-if="requestVModel.activeTab === RequestComposition.QUERY"
v-model:params="requestVModel.query"
:layout="activeLayout"
:disabled-param-value="!isEditableApi"
:disabled-except-param="!isEditableApi"
:second-box-height="secondBoxHeight"
@change="handleActiveDebugChange"
@ -205,6 +163,7 @@
v-else-if="requestVModel.activeTab === RequestComposition.REST"
v-model:params="requestVModel.rest"
:layout="activeLayout"
:disabled-param-value="!isEditableApi"
:disabled-except-param="!isEditableApi"
:second-box-height="secondBoxHeight"
@change="handleActiveDebugChange"
@ -288,8 +247,6 @@
import MsTab from '@/components/pure/ms-tab/index.vue';
import assertion from '@/components/business/ms-assertion/index.vue';
import stepType from './stepType/stepType.vue';
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
import apiMethodSelect from '@/views/api-test/components/apiMethodSelect.vue';
import auth from '@/views/api-test/components/requestComposition/auth.vue';
import postcondition from '@/views/api-test/components/requestComposition/postcondition.vue';
import precondition from '@/views/api-test/components/requestComposition/precondition.vue';
@ -305,7 +262,7 @@
uploadTempFileCase,
} from '@/api/modules/api-test/management';
import { useAppStore } from '@/store';
import { characterLimit, parseQueryParams } from '@/utils';
import { characterLimit } from '@/utils';
import { scrollIntoView } from '@/utils/dom';
import { ExecuteConditionConfig, PluginConfig, RequestResult } from '@/models/apiTest/common';
@ -559,17 +516,12 @@
return httpContentTabList;
}
if (!isEditableApi.value) {
return [
...pluginContentTab,
...httpContentTabList
.filter((e) => commonContentTabKey.includes(e.value))
.filter(
(item) =>
!(!preProcessorNum.value && item.value === RequestComposition.PRECONDITION) &&
!(!postProcessorNum.value && item.value === RequestComposition.POST_CONDITION) &&
!(!assertionsNum.value && item.value === RequestComposition.ASSERTION)
),
];
return [...pluginContentTab, ...httpContentTabList.filter((e) => commonContentTabKey.includes(e.value))].filter(
(item) =>
!(!preProcessorNum.value && item.value === RequestComposition.PRECONDITION) &&
!(!postProcessorNum.value && item.value === RequestComposition.POST_CONDITION) &&
!(!assertionsNum.value && item.value === RequestComposition.ASSERTION)
);
}
return [...pluginContentTab, ...httpContentTabList.filter((e) => commonContentTabKey.includes(e.value))];
});
@ -594,7 +546,7 @@
case RequestComposition.ASSERTION:
return `${assertionsNum.value > 99 ? '99+' : assertionsNum.value || ''}`;
case RequestComposition.AUTH:
return requestVModel.value.authConfig.authType !== RequestAuthType.NONE ? '1' : '';
return requestVModel.value.authConfig?.authType !== RequestAuthType.NONE ? '1' : '';
default:
return '';
}
@ -744,26 +696,6 @@
handleActiveDebugChange();
}
/**
* 处理url输入框变化解析成参数表格
*/
function handleUrlChange(val: string) {
const params = parseQueryParams(val.trim());
if (params.length > 0) {
requestVModel.value.query = [
...params.map((e, i) => ({
id: (new Date().getTime() + i).toString(),
...defaultRequestParamsItem,
...e,
})),
cloneDeep(defaultRequestParamsItem),
];
requestVModel.value.activeTab = RequestComposition.QUERY;
[requestVModel.value.url] = val.split('?');
}
handleActiveDebugChange();
}
const showResponse = computed(
() => isHttpProtocol.value || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode
);
@ -952,7 +884,6 @@
}
}
const isUrlError = ref(false);
// const showAddDependencyDrawer = ref(false);
// const addDependencyMode = ref<'pre' | 'post'>('pre');
@ -985,6 +916,7 @@
...parseRequestBodyResult,
};
nextTick(() => {
requestVModel.value.activeTab = contentTabList.value[0].value;
// loading
loading.value = false;
});
@ -1010,9 +942,32 @@
});
if (isQuote.value || isCopyNeedInit.value) {
// (request.requestrequest null)
initQuoteCaseDetail();
await initQuoteCaseDetail();
}
handleActiveDebugProtocolChange(requestVModel.value.protocol);
}
}
);
</script>
<style lang="less" scoped>
.exec-btn {
:deep(.arco-btn) {
color: white !important;
background-color: rgb(var(--primary-5)) !important;
.btn-base-primary-hover();
.btn-base-primary-active();
.btn-base-primary-disabled();
}
}
.tab-pane-container {
@apply flex-1 overflow-y-auto;
.ms-scroll-bar();
}
:deep(.arco-tabs-tab:first-child) {
margin-left: 0;
}
:deep(.arco-tabs-tab) {
@apply leading-none;
}
</style>

View File

@ -547,7 +547,7 @@
slotName: 'operation',
dataIndex: 'operation',
fixed: 'right',
width: 200,
width: 220,
},
];
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(

View File

@ -210,6 +210,10 @@
const baseInfoRef = ref<InstanceType<typeof baseInfo>>();
function validScenarioForm(cb: () => Promise<void>) {
if (!baseInfoRef.value) {
cb();
return;
}
baseInfoRef.value?.createFormRef?.validate(async (errors) => {
if (errors) {
activeKey.value = ScenarioDetailComposition.BASE_INFO;