diff --git a/frontend/src/config/workbench.ts b/frontend/src/config/workbench.ts
index 07e6b92f87..5a6b6f77e2 100644
--- a/frontend/src/config/workbench.ts
+++ b/frontend/src/config/workbench.ts
@@ -281,6 +281,8 @@ export const commonRatePieOptions = {
color: [],
radius: ['65%', '80%'],
center: [44, '50%'],
+ minAngle: 5,
+ minShowLabelAngle: 10,
avoidLabelOverlap: false,
label: {
show: false,
diff --git a/frontend/src/views/api-test/components/caseAndScenarioReportDrawer.vue b/frontend/src/views/api-test/components/caseAndScenarioReportDrawer.vue
index bdfb554c7d..bea591d7db 100644
--- a/frontend/src/views/api-test/components/caseAndScenarioReportDrawer.vue
+++ b/frontend/src/views/api-test/components/caseAndScenarioReportDrawer.vue
@@ -44,9 +44,19 @@
+
-
@@ -76,6 +86,9 @@
doNotShowShare?: boolean; // 不展示分享按钮
reportDetail?: (...args: any) => Promise; // 获取报告接口
getReportStepDetail?: (...args: any) => Promise; // 获取步骤的详情内容接口
+ caseName?: string; // 用例名称
+ caseId?: string; // 用例id
+ isFilterStep?: boolean;
}>();
const appStore = useAppStore();
diff --git a/frontend/src/views/api-test/management/components/management/case/caseTable.vue b/frontend/src/views/api-test/management/components/management/case/caseTable.vue
index 81b54226f0..d1b392535c 100644
--- a/frontend/src/views/api-test/management/components/management/case/caseTable.vue
+++ b/frontend/src/views/api-test/management/components/management/case/caseTable.vue
@@ -288,7 +288,13 @@
@finished="loadCaseListAndResetSelector"
/>
-
+
('');
+ const currentCaseName = ref('');
const showExecuteResult = ref(false);
async function showResult(record: ApiCaseDetail) {
if (!record.lastReportId) return;
activeReportId.value = record.lastReportId;
+ currentId.value = record.id;
+ currentCaseName.value = record.name;
showExecuteResult.value = true;
}
diff --git a/frontend/src/views/api-test/report/component/caseReportCom.vue b/frontend/src/views/api-test/report/component/caseReportCom.vue
index 5ce37e1e2a..850288e12c 100644
--- a/frontend/src/views/api-test/report/component/caseReportCom.vue
+++ b/frontend/src/views/api-test/report/component/caseReportCom.vue
@@ -175,9 +175,12 @@
v-model:keyword-name="keywordName"
:key-words="cascaderKeywords"
show-type="CASE"
+ :case-id="props.caseId"
+ :case-name="props.caseName"
:active-type="activeTab"
:report-detail="detail || []"
:get-report-step-detail="props.getReportStepDetail"
+ :is-filter-step="props.isFilterStep"
:is-export="props.isExport"
/>
@@ -207,6 +210,9 @@
detailInfo?: ReportDetail;
getReportStepDetail?: (...args: any) => Promise; // 获取步骤的详情内容接口
isExport?: boolean;
+ isFilterStep?: boolean; // 是否打开抽屉之前过滤用例步骤
+ caseName?: string; // 用例名称关键字
+ caseId?: string; // 用例id
}>();
const detail = ref({
@@ -250,7 +256,7 @@
});
const cascaderKeywords = ref('');
- const keywordName = ref('');
+ const keywordName = ref(props.caseName || '');
const getTotalTime = computed(() => {
if (detail.value) {
diff --git a/frontend/src/views/api-test/report/component/scenarioCom.vue b/frontend/src/views/api-test/report/component/scenarioCom.vue
index 81d39ec5bb..02100dc158 100644
--- a/frontend/src/views/api-test/report/component/scenarioCom.vue
+++ b/frontend/src/views/api-test/report/component/scenarioCom.vue
@@ -47,12 +47,15 @@
@@ -84,6 +87,9 @@
detailInfo?: ReportDetail;
getReportStepDetail?: (...args: any) => Promise; // 获取步骤的详情内容接口
isExport?: boolean; // 是否是导出pdf预览
+ isFilterStep?: boolean; // 是否打开抽屉之前过滤用例步骤
+ caseName?: string; // 用例名称关键字
+ caseId?: string; // 用例id
}>();
const detail = ref({
@@ -149,7 +155,7 @@
}
return '';
});
- const keywordName = ref('');
+ const keywordName = ref(props.caseName || '');
const reportAnalysisList = computed(() => [
{
diff --git a/frontend/src/views/api-test/report/component/tiledList.vue b/frontend/src/views/api-test/report/component/tiledList.vue
index 1e0c618073..a5683adbe7 100644
--- a/frontend/src/views/api-test/report/component/tiledList.vue
+++ b/frontend/src/views/api-test/report/component/tiledList.vue
@@ -76,6 +76,9 @@
keyWords: string;
getReportStepDetail?: (...args: any) => Promise; // 获取步骤的详情内容接口
isExport?: boolean; // 是否是导出pdf预览
+ isFilterStep?: boolean; // 是否打开抽屉之前过滤用例步骤
+ caseId?: string; // 用例id
+ caseName?: string; // 用例名称
}>();
const { t } = useI18n();
@@ -106,14 +109,6 @@
const expandedKeys = ref<(string | number)[]>([]);
const originTreeData = ref([]);
- function initStepTree() {
- tiledList.value = cloneDeep(props.reportDetail.children) || [];
- tiledList.value.forEach((item) => {
- addFoldField(item);
- });
- originTreeData.value = cloneDeep(tiledList.value);
- }
-
const controlCurrent = ref(0);
const isFailedRetry = computed(() => {
// 所有步骤 id 相同且带有重试前缀,说明是单个用例的重试结果
@@ -145,15 +140,6 @@
});
});
- watch(
- () => props.reportDetail,
- (val) => {
- if (val && val.children) {
- initStepTree();
- }
- },
- { deep: true, immediate: true }
- );
const showApiType = ref([
ScenarioStepType.API,
ScenarioStepType.API_CASE,
@@ -167,12 +153,14 @@
const stepType =
splitLevel[0] === 'CUSTOM_REQUEST' ? ['API', 'API_CASE', 'CUSTOM_REQUEST'] : Object.values(ScenarioStepType);
const nameSearch = innerKeyword.value?.toLowerCase(); // 传入的 name 检索关键字
-
const search = (_data: ScenarioItemType[]) => {
const result: ScenarioItemType[] = [];
_data.forEach((item) => {
const isStepChildren = item.children && item?.children.length && showApiType.value.includes(item.stepType);
+ const isFilterCaseStep =
+ props.isFilterStep && props.reportDetail.integrated && innerKeyword.value === props.caseName;
+
// 匹配步骤类型
const matchStepType = stepType.includes(item.stepType);
@@ -183,9 +171,16 @@
// 条件匹配逻辑
let matchesStepCondition;
+ // 如果开启用例过滤且为集合报告过滤用例步骤
+ if (isFilterCaseStep) {
+ const caseStepCondition = item.name?.toLowerCase().includes(nameSearch) && item.stepId === props.caseId;
+ matchesStepCondition = stepTypeStatus
+ ? caseStepCondition && matchStepType && matchStepStatus
+ : caseStepCondition;
+ }
// 如果传入了 name 且有状态
- if (nameSearch && stepTypeStatus) {
+ else if (nameSearch && stepTypeStatus) {
matchesStepCondition = matchStepType && matchStepStatus && item.name?.toLowerCase().includes(nameSearch);
}
// 仅传入了 name 没有状态或类型
@@ -235,6 +230,19 @@
}
}, 300);
+ function initStepTree() {
+ tiledList.value = cloneDeep(props.reportDetail.children) || [];
+ tiledList.value.forEach((item) => {
+ addFoldField(item);
+ });
+ originTreeData.value = cloneDeep(tiledList.value);
+
+ // 过滤当前用例步骤
+ if (props.isFilterStep && props.reportDetail.integrated) {
+ updateDebouncedSearch();
+ }
+ }
+
watch(
() => props.keyWords,
(val) => {
@@ -246,6 +254,16 @@
}
);
+ watch(
+ () => props.reportDetail,
+ (val) => {
+ if (val && val.children) {
+ initStepTree();
+ }
+ },
+ { deep: true, immediate: true }
+ );
+
defineExpose({
updateDebouncedSearch,
initStepTree,
diff --git a/frontend/src/views/api-test/scenario/components/scenarioTable.vue b/frontend/src/views/api-test/scenario/components/scenarioTable.vue
index 04b00d5b86..cb7416ebd2 100644
--- a/frontend/src/views/api-test/scenario/components/scenarioTable.vue
+++ b/frontend/src/views/api-test/scenario/components/scenarioTable.vue
@@ -468,6 +468,9 @@
diff --git a/frontend/src/views/workbench/homePage/utils.ts b/frontend/src/views/workbench/homePage/utils.ts
index 04161c074a..e8ffd22870 100644
--- a/frontend/src/views/workbench/homePage/utils.ts
+++ b/frontend/src/views/workbench/homePage/utils.ts
@@ -597,19 +597,20 @@ export function handleUpdateTabPie(
if (hasPermission) {
const pieBorderWidth = countList.slice(1).filter((e) => Number(e.count) > 0).length === 1 ? 0 : 1;
- lastCountList = countList.slice(1).map((item) => {
+ lastCountList = countList.slice(1).map((item, i) => {
return {
value: item.count,
label: item.name,
name: item.name,
itemStyle: {
+ color: defaultValueMap[typeKey][valueKey].color[i],
borderWidth: pieBorderWidth,
borderColor: '#ffffff',
},
};
});
- options.series.data = lastCountList.every((e) => e.value === 0) ? [] : lastCountList;
+ options.series.data = lastCountList.every((e) => e.value === 0) ? [] : lastCountList.filter((e) => e.value !== 0);
options.title.text = countList[0].name ?? '';
options.title.subtext = `${countList[0].count ?? 0}%`;
@@ -625,8 +626,6 @@ export function handleUpdateTabPie(
options.title.subtext = '-%';
}
- options.series.color = defaultValueMap[typeKey][valueKey].color;
-
const lastValueList = lastCountList.map((item, index) => {
return {
...item,