diff --git a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue index ed52ad6c06..b4e87a8441 100644 --- a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue +++ b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue @@ -183,7 +183,11 @@ - + {{ t('ms.minders.failRetry') }} @@ -201,6 +205,7 @@ :step="1" :min="1" :precision="0" + :disabled="configForm.level === 2 && configForm.extended" size="small" class="w-[120px]" > @@ -218,6 +223,7 @@ :step="100" :min="0" :precision="0" + :disabled="configForm.level === 2 && configForm.extended" size="small" class="w-[120px]" > diff --git a/frontend/src/components/pure/ms-tab/index.vue b/frontend/src/components/pure/ms-tab/index.vue index 3f8c31caa3..83e058bab2 100644 --- a/frontend/src/components/pure/ms-tab/index.vue +++ b/frontend/src/components/pure/ms-tab/index.vue @@ -5,7 +5,7 @@ :class="[props.class, props.noContent ? 'no-content' : '']" @change="(val) => handleTabClick(val as string)" > - + {{ item.label }} @@ -40,23 +43,28 @@ const props = withDefaults( defineProps<{ mode?: 'origin' | 'button'; - contentTabList: { label: string; value: string }[]; + contentTabList: { label: string | number; value: string | number }[]; class?: string; getTextFunc?: (value: any) => string; noContent?: boolean; showBadge?: boolean; - changeInterceptor?: (newVal: string, oldVal: string, done: () => void) => void; + changeInterceptor?: (newVal: string | number, oldVal: string | number, done: () => void) => void; + buttonSize?: 'small' | 'default'; }>(), { mode: 'origin', showBadge: true, getTextFunc: (value: any) => value, class: '', + buttonSize: 'default', } ); + const emit = defineEmits<{ + (e: 'change', value: string | number): void; + }>(); // 实际值,用于最终确认修改的 tab 值 - const activeKey = defineModel('activeKey', { + const activeKey = defineModel('activeKey', { default: '', }); // 临时值,用于组件内部变更,但未影响到实际值 @@ -69,7 +77,7 @@ } ); - function handleTabClick(value: string) { + function handleTabClick(value: string | number) { if (value === activeKey.value) { return; } @@ -85,6 +93,7 @@ // 不存在拦截器,直接修改实际值 activeKey.value = value; } + emit('change', activeKey.value); } @@ -107,7 +116,7 @@ @apply flex; border-radius: var(--border-radius-small); - .ms-tab--button-item { + .ms-tab-button-item { @apply cursor-pointer; padding: 4px 12px; @@ -128,7 +137,12 @@ color: rgb(var(--primary-5)); } } - .ms-tab--button-item--active { + .ms-tab--button-item--small { + padding: 1px 12px; + font-size: 12px; + line-height: 20px; + } + .ms-tab-button-item--active { z-index: 2; border: 1px solid rgb(var(--primary-5)) !important; color: rgb(var(--primary-5)); diff --git a/frontend/src/views/api-test/components/requestComposition/response/result/index.vue b/frontend/src/views/api-test/components/requestComposition/response/result/index.vue index 017900a1c3..de279c6d97 100644 --- a/frontend/src/views/api-test/components/requestComposition/response/result/index.vue +++ b/frontend/src/views/api-test/components/requestComposition/response/result/index.vue @@ -1,33 +1,43 @@ {}"> - {}"> - {}" + > + + - {{ t('report.detail.api.resContent') }} + {{ t('report.detail.api.resContent') }} + - {{ t('report.detail.api.subRequest') }} + {{ t('report.detail.api.subRequest') }} + @@ -121,7 +131,9 @@ import { useRoute } from 'vue-router'; import { cloneDeep } from 'lodash-es'; + import MsTab from '@/components/pure/ms-tab/index.vue'; import result from '@/views/api-test/components/requestComposition/response/result.vue'; + import loopPagination from '@/views/api-test/scenario/components/common/loopPagination.vue'; import { reportCaseStepDetail, reportStepDetail } from '@/api/modules/api-test/report'; import { useI18n } from '@/hooks/useI18n'; @@ -337,7 +349,24 @@ } return 0; }); - const controlPageSize = ref(1); + const controlTotalList = computed(() => { + return Array.from({ length: controlTotal.value }, (v, k) => { + if (k === 0) { + return { + value: k + 1, + label: t('apiTestDebug.first'), + }; + } + return { + value: k + 1, + label: `${t('apiTestDebug.retry')} ${k}`, + }; + }); + }); + const isFailedRetry = computed(() => { + return !!props.stepItem?.stepChildren?.some((item) => item.requestName.includes('MsRetry_')); // 是否包含重试前缀 + }); + /** * 循环次数控制器 */ diff --git a/frontend/src/views/api-test/debug/locale/en-US.ts b/frontend/src/views/api-test/debug/locale/en-US.ts index 73c8c7eeeb..a881655e2d 100644 --- a/frontend/src/views/api-test/debug/locale/en-US.ts +++ b/frontend/src/views/api-test/debug/locale/en-US.ts @@ -213,4 +213,6 @@ export default { 'apiTestDebug.standardAdditionsTip': 'Writing format: parameter name, type, required, parameter value; multiple records separated by newlines', 'apiTestDebug.quickAdditions': 'Quick', + 'apiTestDebug.first': 'First', + 'apiTestDebug.retry': 'Retry', }; diff --git a/frontend/src/views/api-test/debug/locale/zh-CN.ts b/frontend/src/views/api-test/debug/locale/zh-CN.ts index 78dcc34841..35ae0f7a6f 100644 --- a/frontend/src/views/api-test/debug/locale/zh-CN.ts +++ b/frontend/src/views/api-test/debug/locale/zh-CN.ts @@ -199,4 +199,6 @@ export default { 'apiTestDebug.standardAdditions': '标准添加', 'apiTestDebug.standardAdditionsTip': '书写格式:参数名,类型,必填,参数值;多条记录换行分隔', 'apiTestDebug.quickAdditions': '快捷添加', + 'apiTestDebug.first': '首次', + 'apiTestDebug.retry': '重试', }; diff --git a/frontend/src/views/api-test/report/component/step/reportInfoHeaders.vue b/frontend/src/views/api-test/report/component/step/reportInfoHeaders.vue index ce0ef23b36..46fc9c9121 100644 --- a/frontend/src/views/api-test/report/component/step/reportInfoHeaders.vue +++ b/frontend/src/views/api-test/report/component/step/reportInfoHeaders.vue @@ -1,5 +1,5 @@ - + {{ t('report.detail.api.reportDetail') }} diff --git a/frontend/src/views/api-test/report/component/step/stepTree.vue b/frontend/src/views/api-test/report/component/step/stepTree.vue index 04b5c3ec53..6f31163a45 100644 --- a/frontend/src/views/api-test/report/component/step/stepTree.vue +++ b/frontend/src/views/api-test/report/component/step/stepTree.vue @@ -128,25 +128,21 @@ {{ t('report.detail.api.responseTime') }} - {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[0] : '-' - }}{{ - step.requestTime !== null ? formatDuration(step.requestTime).split('-')[1] : 'ms' - }} + + {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[0] : '-' }} + {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[1] : 'ms' }} + {{ t('report.detail.api.responseTime') }} - {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[0] : '-' - }}{{ - step.requestTime !== null ? formatDuration(step.requestTime).split('-')[1] : 'ms' - }} + + {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[0] : '-' }} + {{ step.requestTime !== null ? formatDuration(step.requestTime).split('-')[1] : 'ms' }} + + - + + {{ t('report.detail.api.responseSize') }} @@ -157,8 +153,8 @@ {{ step.responseSize || 0 }} bytes - + + diff --git a/frontend/src/views/api-test/report/component/tiledList.vue b/frontend/src/views/api-test/report/component/tiledList.vue index 79cffb812c..e547295c2b 100644 --- a/frontend/src/views/api-test/report/component/tiledList.vue +++ b/frontend/src/views/api-test/report/component/tiledList.vue @@ -5,10 +5,18 @@ 'border border-solid border-[var(--color-text-n8)]': props.showType === 'API', }" > + + + Promise; // 获取步骤的详情内容接口 }>(); + const { t } = useI18n(); + const tiledList = ref([]); const isExpandAll = ref(false); // 是否展开全部 @@ -82,6 +95,37 @@ originTreeData.value = cloneDeep(tiledList.value); } + const controlCurrent = ref(0); + const isFailedRetry = computed(() => { + // 所有步骤 id 相同且带有重试前缀,说明是单个用例的重试结果 + return ( + props.reportDetail.children.every((item) => item.stepId === props.reportDetail.children[0].stepId) && + props.reportDetail.children.some((item) => item.requestName?.includes('MsRetry_')) + ); + }); + const currentTiledList = computed(() => { + if (isFailedRetry.value === false) { + // 不是失败重试结果 + return tiledList.value; + } + // 失败重试的结果 + return [tiledList.value[controlCurrent.value]]; + }); + const controlTotalList = computed(() => { + return Array.from({ length: props.reportDetail.children.length }, (v, k) => { + if (k === 0) { + return { + value: k, + label: t('apiTestDebug.first'), + }; + } + return { + value: k, + label: `${t('apiTestDebug.retry')} ${k}`, + }; + }); + }); + watch( () => props.reportDetail, (val) => { diff --git a/frontend/src/views/api-test/scenario/components/common/loopPagination.vue b/frontend/src/views/api-test/scenario/components/common/loopPagination.vue index e4c4f884df..ca55414650 100644 --- a/frontend/src/views/api-test/scenario/components/common/loopPagination.vue +++ b/frontend/src/views/api-test/scenario/components/common/loopPagination.vue @@ -9,6 +9,7 @@ show-total size="mini" class="loop-pagination" + @change="() => emit('change', currentLoop)" > (); + const emit = defineEmits<{ + (e: 'change', value: number): void; + }>(); const { t } = useI18n(); diff --git a/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue b/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue index 46cd875cb1..277eed6300 100644 --- a/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue +++ b/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue @@ -90,18 +90,18 @@ - + - - {{ - t('caseManagement.featureCase.detailDisplaySetting') - }} + /> + + + {{ t('caseManagement.featureCase.detailDisplaySetting') }} + commentInputRef.value?.isActive); const tabSetting = ref([]); - const activeTab = ref('detail'); + const activeTab = ref('detail'); - function clickMenu(key: string) { + function clickMenu(key: string | number) { activeTab.value = key; featureCaseStore.setActiveTab(key); switch (activeTab.value) { diff --git a/frontend/src/views/test-plan/testPlan/detail/index.vue b/frontend/src/views/test-plan/testPlan/detail/index.vue index 2a83062761..907a0ea87e 100644 --- a/frontend/src/views/test-plan/testPlan/detail/index.vue +++ b/frontend/src/views/test-plan/testPlan/detail/index.vue @@ -509,7 +509,7 @@ } } - function changeTabInterceptor(newVal: string, oldVal: string, done: () => void) { + function changeTabInterceptor(newVal: string | number, oldVal: string | number, done: () => void) { if (oldVal === 'plan' && minderStore.minderUnsaved) { openModal({ type: 'warning',