diff --git a/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue b/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue index 57d07fc6bd..162697d0df 100644 --- a/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue +++ b/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue @@ -12,7 +12,7 @@ diff --git a/frontend/src/components/business/ms-assertion/comp/VariableTab.vue b/frontend/src/components/business/ms-assertion/comp/VariableTab.vue index dd75a40bfc..be210b18e9 100644 --- a/frontend/src/components/business/ms-assertion/comp/VariableTab.vue +++ b/frontend/src/components/business/ms-assertion/comp/VariableTab.vue @@ -5,6 +5,7 @@ :columns="columns" :scroll="{ minWidth: '700px' }" :default-param-item="defaultParamItem" + :disabled-except-param="props.disabled" @change="handleParamTableChange" /> @@ -24,6 +25,7 @@ const props = defineProps<{ data: Param; + disabled?: boolean; }>(); const emit = defineEmits<{ diff --git a/frontend/src/components/business/ms-assertion/index.vue b/frontend/src/components/business/ms-assertion/index.vue index 06cb13ef4c..f1431ee73e 100644 --- a/frontend/src/components/business/ms-assertion/index.vue +++ b/frontend/src/components/business/ms-assertion/index.vue @@ -49,7 +49,7 @@ {{ item.name }}
-
+
{{ t('common.desc') }}
- + {{ t('apiTestDebug.introduceSource') }}
@@ -297,6 +303,7 @@ @@ -313,6 +320,7 @@
{{ t('apiTestDebug.storageByResult') }} @@ -394,7 +405,9 @@ type="icon-icon_flashlamp" :size="15" :class=" - disabledExpressionSuffix ? 'ms-params-input-suffix-icon--disabled' : 'ms-params-input-suffix-icon' + disabledExpressionSuffix || props.disabled + ? 'ms-params-input-suffix-icon--disabled' + : 'ms-params-input-suffix-icon' " @click.stop="() => showFastExtraction(record)" /> @@ -828,6 +841,7 @@ if (!result){ const activeRecord = ref({ ...defaultExtractParamItem }); // 用于暂存当前操作的提取参数表格项 function showFastExtraction(record: ExpressionConfig) { + if (props.disabled) return; activeRecord.value = { ...record }; fastExtractionVisible.value = true; } diff --git a/frontend/src/views/api-test/components/requestAndResponse.vue b/frontend/src/views/api-test/components/requestAndResponse.vue index 88c3d8a1ff..992030d97e 100644 --- a/frontend/src/views/api-test/components/requestAndResponse.vue +++ b/frontend/src/views/api-test/components/requestAndResponse.vue @@ -237,42 +237,80 @@ label: t('apiTestDebug.setting'), }, ]; + const headerNum = computed( + () => filterKeyValParams(requestVModel.value?.headers ?? [], defaultHeaderParamsItem).validParams?.length + ); + const restNum = computed( + () => filterKeyValParams(requestVModel.value?.rest ?? [], defaultRequestParamsItem).validParams?.length + ); + const queryNum = computed( + () => filterKeyValParams(requestVModel.value?.query ?? [], defaultRequestParamsItem).validParams?.length + ); + const preProcessorNum = computed(() => requestVModel.value.children[0].preProcessorConfig.processors.length); + const postProcessorNum = computed(() => requestVModel.value.children[0].postProcessorConfig.processors.length); + const assertionsNum = computed(() => requestVModel.value.children[0].assertionConfig.assertions.length); // 根据协议类型获取请求内容tab const contentTabList = computed(() => { // HTTP 协议 tabs if (isHttpProtocol.value) { + // 引用CASE:如果[请求头、query、rest、前后置、断言]没有数据则直接隐藏tab + if (props.disabledExceptParam) { + return httpContentTabList.filter( + (item) => + !(!restNum.value && item.value === RequestComposition.REST) && + !(!queryNum.value && item.value === RequestComposition.QUERY) && + !(!headerNum.value && item.value === RequestComposition.HEADER) && + !(!preProcessorNum.value && item.value === RequestComposition.PRECONDITION) && + !(!postProcessorNum.value && item.value === RequestComposition.POST_CONDITION) && + !(!assertionsNum.value && item.value === RequestComposition.ASSERTION) + ); + } return props.isShowCommonContentTabKey ? httpContentTabList : httpContentTabList.filter((e) => !commonContentTabKey.includes(e.value)); } + if (props.disabledExceptParam) { + 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))]; }); // 获取 tab 的参数数量徽标 function getTabBadge(tabKey: RequestComposition) { switch (tabKey) { case RequestComposition.HEADER: - const headerNum = filterKeyValParams(requestVModel.value.headers, defaultHeaderParamsItem).validParams.length; - return `${headerNum > 0 ? headerNum : ''}`; + return `${headerNum.value > 0 ? headerNum.value : ''}`; case RequestComposition.BODY: return requestVModel.value.body?.bodyType !== RequestBodyFormat.NONE ? '1' : ''; case RequestComposition.QUERY: - const queryNum = filterKeyValParams(requestVModel.value.query, defaultRequestParamsItem).validParams.length; - return `${queryNum > 0 ? queryNum : ''}`; + return `${queryNum.value > 0 ? queryNum.value : ''}`; case RequestComposition.REST: - const restNum = filterKeyValParams(requestVModel.value.rest, defaultRequestParamsItem).validParams.length; - return `${restNum > 0 ? restNum : ''}`; + return `${restNum.value > 0 ? restNum.value : ''}`; case RequestComposition.PRECONDITION: - return `${requestVModel.value.children[0].preProcessorConfig.processors.length || ''}`; + return `${preProcessorNum.value > 99 ? '99+' : preProcessorNum.value || ''}`; case RequestComposition.POST_CONDITION: - return `${requestVModel.value.children[0].postProcessorConfig.processors.length || ''}`; + return `${postProcessorNum.value > 99 ? '99+' : postProcessorNum.value || ''}`; case RequestComposition.ASSERTION: - return `${requestVModel.value.children[0].assertionConfig.assertions.length || ''}`; + return `${assertionsNum.value > 99 ? '99+' : assertionsNum.value || ''}`; case RequestComposition.AUTH: return requestVModel.value.authConfig.authType !== RequestAuthType.NONE ? '1' : ''; default: return ''; } } + // 设置第一个tab为当前tab + function setActiveTabByFirst() { + requestVModel.value.activeTab = contentTabList.value[0].value; + } const protocolLoading = ref(false); const protocolOptions = ref([]); @@ -492,6 +530,7 @@ initPluginScript, handleActiveDebugChange, makeRequestParams, + setActiveTabByFirst, }); diff --git a/frontend/src/views/api-test/components/requestComposition/body.vue b/frontend/src/views/api-test/components/requestComposition/body.vue index e2c6e9e4ba..9cf6821f8e 100644 --- a/frontend/src/views/api-test/components/requestComposition/body.vue +++ b/frontend/src/views/api-test/components/requestComposition/body.vue @@ -64,7 +64,7 @@ /> @@ -67,7 +67,7 @@ :disabled-param-value="isQuote" :request="requestVModel" :is-priority-local-exec="isPriorityLocalExec" - :file-save-as-source-id="requestVModel.id" + :file-save-as-source-id="requestVModel.resourceId" :file-module-options-api="getTransferOptionsCase" :file-save-as-api="transferFileCase" :upload-temp-file="uploadTempFileCase" @@ -133,6 +133,7 @@ const defaultCaseParams: RequestParam = { id: `case-${Date.now()}`, + resourceId: '', type: 'case', moduleId: 'root', protocol: 'HTTP', @@ -203,7 +204,7 @@ () => activeStep.value?.stepType === ScenarioStepType.API_CASE && activeStep.value?.refType === ScenarioStepRefType.COPY ); - const isCopyNeedInit = computed(() => isCopyCase.value && props.request?.request === null); + const isCopyNeedInit = computed(() => isCopyCase.value && props.request === undefined); const isQuote = computed( () => activeStep.value?.stepType === ScenarioStepType.API_CASE && activeStep.value?.refType === ScenarioStepRefType.REF @@ -280,10 +281,11 @@ debugSocket(executeType); // 开启websocket let res; const params = { + apiDefinitionId: requestVModel.value.apiDefinitionId, ...makeRequestParams, reportId: reportId.value, }; - if (!(requestVModel.value.id as string).startsWith('c') && executeType === 'serverExec') { + if (!(requestVModel.value.resourceId as string).startsWith('c') && executeType === 'serverExec') { // 已创建的服务端 res = await runCase(params); } else { @@ -317,7 +319,7 @@ async function initQuoteCaseDetail() { try { loading.value = true; - const res = await getCaseDetail(props.request?.id as string); + const res = await getCaseDetail(activeStep.value?.resourceId || ''); let parseRequestBodyResult; if (res.protocol === 'HTTP') { parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件 @@ -334,10 +336,11 @@ response: cloneDeep(defaultResponse), url: res.path, name: res.name, // request里面还有个name但是是null - id: res.id, + resourceId: res.id, ...parseRequestBodyResult, }; nextTick(() => { + requestAndResponseRef.value?.setActiveTabByFirst(); // 等待内容渲染出来再隐藏loading loading.value = false; }); @@ -352,12 +355,10 @@ () => visible.value, async (val) => { if (val) { - if (props.request) { - requestVModel.value = { ...cloneDeep(defaultCaseParams), ...props.request }; - if (isQuote.value || isCopyNeedInit.value) { - // 引用时,需要初始化引用的详情;复制只在第一次初始化的时候需要加载后台数据(request.request是复制请求时列表参数字段request会为 null,以此判断释放第一次初始化) - initQuoteCaseDetail(); - } + requestVModel.value = { ...cloneDeep(defaultCaseParams), ...props.request }; + if (isQuote.value || isCopyNeedInit.value) { + // 引用时,需要初始化引用的详情;复制只在第一次初始化的时候需要加载后台数据(request.request是复制请求时列表参数字段request会为 null,以此判断释放第一次初始化) + initQuoteCaseDetail(); } await initLocalConfig(); }