feat(任务中心): 测试计划执行结果
This commit is contained in:
parent
81ff2a8f9b
commit
7956aa5b42
|
@ -209,4 +209,7 @@ export function getCollectScenarioPage(data: TableQueryParams) {
|
||||||
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getCollectScenarioUrl}`, data });
|
return MSR.post<CommonList<testPlanSetItem>>({ url: `${reportUrl.getCollectScenarioUrl}`, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {};
|
// 测试计划-获取执行结果
|
||||||
|
export function getTestPlanResult(id: string) {
|
||||||
|
return MSR.get({ url: `${reportUrl.GetTestPlanResultUrl}/${id}` });
|
||||||
|
}
|
||||||
|
|
|
@ -86,3 +86,5 @@ export const getShareCollectFunctionalUrl = '/test-plan/report/share/detail/func
|
||||||
export const getShareCollectionApiUrl = '/test-plan/report/share/detail/api/collection/page';
|
export const getShareCollectionApiUrl = '/test-plan/report/share/detail/api/collection/page';
|
||||||
// 测试计划-报告-详情-分享-报告-场景明细-测试点
|
// 测试计划-报告-详情-分享-报告-场景明细-测试点
|
||||||
export const getShareCollectScenarioUrl = '/test-plan/report/share/detail/scenario/collection/page';
|
export const getShareCollectScenarioUrl = '/test-plan/report/share/detail/scenario/collection/page';
|
||||||
|
// 任务中心-测试计划执行结果
|
||||||
|
export const GetTestPlanResultUrl = '/test-plan/report/get-result';
|
||||||
|
|
|
@ -40,12 +40,14 @@
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<a-spin :loading="loading" class="block">
|
||||||
<CaseReportCom
|
<CaseReportCom
|
||||||
v-if="!props.isScenario"
|
v-if="!props.isScenario"
|
||||||
:detail-info="reportStepDetail"
|
:detail-info="reportStepDetail"
|
||||||
:get-report-step-detail="props.getReportStepDetail"
|
:get-report-step-detail="props.getReportStepDetail"
|
||||||
/>
|
/>
|
||||||
<ScenarioCom v-else :detail-info="reportStepDetail" :get-report-step-detail="props.getReportStepDetail" />
|
<ScenarioCom v-else :detail-info="reportStepDetail" :get-report-step-detail="props.getReportStepDetail" />
|
||||||
|
</a-spin>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -128,8 +130,11 @@
|
||||||
const reportStepDetail = ref<ReportDetail>({
|
const reportStepDetail = ref<ReportDetail>({
|
||||||
...initReportStepDetail,
|
...initReportStepDetail,
|
||||||
});
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
async function getReportDetail() {
|
async function getReportDetail() {
|
||||||
try {
|
try {
|
||||||
|
loading.value = true;
|
||||||
if (props.reportDetail) {
|
if (props.reportDetail) {
|
||||||
reportStepDetail.value = await props.reportDetail(props.reportId, route.query.shareId as string | undefined);
|
reportStepDetail.value = await props.reportDetail(props.reportId, route.query.shareId as string | undefined);
|
||||||
return;
|
return;
|
||||||
|
@ -142,6 +147,8 @@
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +159,9 @@
|
||||||
reportStepDetail.value = { ...initReportStepDetail };
|
reportStepDetail.value = { ...initReportStepDetail };
|
||||||
await getReportDetail();
|
await getReportDetail();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
{{ t('ms.taskCenter.rerun') }}
|
{{ t('ms.taskCenter.rerun') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
<MsButton v-if="record.status === ExecuteStatusEnum.COMPLETED" @click="checkReport(record)">
|
<MsButton v-if="record.status === ExecuteStatusEnum.COMPLETED" @click="checkReport(record)">
|
||||||
{{ t('ms.taskCenter.checkReport') }}
|
{{ t('ms.taskCenter.executeResult') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
|
@ -108,6 +108,11 @@
|
||||||
}"
|
}"
|
||||||
:share-time="shareTime"
|
:share-time="shareTime"
|
||||||
/>
|
/>
|
||||||
|
<TestPlanExecuteResultDrawer
|
||||||
|
:id="activeDetailId"
|
||||||
|
v-model:visible="showTestPlanDetailDrawer"
|
||||||
|
:is-group="isTestPlanGroup"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -124,6 +129,7 @@
|
||||||
import execStatus from './execStatus.vue';
|
import execStatus from './execStatus.vue';
|
||||||
import executeRatePopper from './executeRatePopper.vue';
|
import executeRatePopper from './executeRatePopper.vue';
|
||||||
import executeResultStatus from './executeResultStatus.vue';
|
import executeResultStatus from './executeResultStatus.vue';
|
||||||
|
import TestPlanExecuteResultDrawer from './testPlanExecuteResultDrawer.vue';
|
||||||
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
||||||
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
||||||
|
|
||||||
|
@ -160,7 +166,6 @@
|
||||||
} from '@/api/modules/taskCenter/system';
|
} from '@/api/modules/taskCenter/system';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
|
||||||
import useTableStore from '@/hooks/useTableStore';
|
import useTableStore from '@/hooks/useTableStore';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
@ -168,7 +173,6 @@
|
||||||
|
|
||||||
import { TaskCenterTaskItem } from '@/models/taskCenter';
|
import { TaskCenterTaskItem } from '@/models/taskCenter';
|
||||||
import { ReportEnum } from '@/enums/reportEnum';
|
import { ReportEnum } from '@/enums/reportEnum';
|
||||||
import { TestPlanRouteEnum } from '@/enums/routeEnum';
|
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||||
import { ExecuteResultEnum, ExecuteStatusEnum, ExecuteTaskType } from '@/enums/taskCenter';
|
import { ExecuteResultEnum, ExecuteStatusEnum, ExecuteTaskType } from '@/enums/taskCenter';
|
||||||
|
@ -185,7 +189,6 @@
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const { openNewPage } = useOpenNewPage();
|
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
@ -657,6 +660,8 @@
|
||||||
const activeReportIndex = ref<number>(0);
|
const activeReportIndex = ref<number>(0);
|
||||||
const showDetailDrawer = ref<boolean>(false);
|
const showDetailDrawer = ref<boolean>(false);
|
||||||
const showCaseDetailDrawer = ref<boolean>(false);
|
const showCaseDetailDrawer = ref<boolean>(false);
|
||||||
|
const showTestPlanDetailDrawer = ref<boolean>(false);
|
||||||
|
const isTestPlanGroup = ref(false);
|
||||||
|
|
||||||
function showReportDetail(record: TaskCenterTaskItem) {
|
function showReportDetail(record: TaskCenterTaskItem) {
|
||||||
activeDetailId.value = record.reportId;
|
activeDetailId.value = record.reportId;
|
||||||
|
@ -718,12 +723,9 @@
|
||||||
) {
|
) {
|
||||||
showReportDetail(record);
|
showReportDetail(record);
|
||||||
} else if ([ExecuteTaskType.TEST_PLAN_GROUP, ExecuteTaskType.TEST_PLAN].includes(record.taskType)) {
|
} else if ([ExecuteTaskType.TEST_PLAN_GROUP, ExecuteTaskType.TEST_PLAN].includes(record.taskType)) {
|
||||||
openNewPage(TestPlanRouteEnum.TEST_PLAN_REPORT, {
|
showTestPlanDetailDrawer.value = true;
|
||||||
orgId: record.organizationId,
|
activeDetailId.value = record.reportId;
|
||||||
pId: record.projectId,
|
isTestPlanGroup.value = record.taskType === ExecuteTaskType.TEST_PLAN_GROUP;
|
||||||
id: record.reportId,
|
|
||||||
type: record.taskType === ExecuteTaskType.TEST_PLAN_GROUP ? 'GROUP' : '',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,417 @@
|
||||||
|
<template>
|
||||||
|
<MsDrawer v-model:visible="visible" :width="1200" :footer="false" no-content-padding>
|
||||||
|
<template #title>
|
||||||
|
<div class="flex flex-1 items-center gap-[8px] overflow-hidden">
|
||||||
|
<a-tag :color="executeResultMap[detail.resultStatus]?.color">
|
||||||
|
{{ t(executeResultMap[detail.resultStatus]?.label || '-') }}
|
||||||
|
</a-tag>
|
||||||
|
<div class="one-line-text flex-1">{{ detail.name }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<MsButton type="icon" status="secondary" class="!rounded-[var(--border-radius-small)]" @click="init">
|
||||||
|
<MsIcon type="icon-icon_reset_outlined" class="mr-[8px]" size="14" />
|
||||||
|
{{ t('common.refresh') }}
|
||||||
|
</MsButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<a-spin :loading="loading" class="block">
|
||||||
|
<div class="analysis-wrapper">
|
||||||
|
<SystemTrigger :is-preview="true">
|
||||||
|
<div class="analysis min-w-[330px]">
|
||||||
|
<ReportMetricsItem
|
||||||
|
v-for="analysisItem in reportAnalysisList"
|
||||||
|
:key="analysisItem.name"
|
||||||
|
:item-info="analysisItem"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SystemTrigger>
|
||||||
|
<SystemTrigger :is-preview="true">
|
||||||
|
<div class="analysis min-w-[330px]">
|
||||||
|
<ExecuteAnalysis :detail="detail" hide-title />
|
||||||
|
</div>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content px-[8px] py-[4px]">
|
||||||
|
{{ t('report.detail.systemInternalTooltip') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</SystemTrigger>
|
||||||
|
</div>
|
||||||
|
<div class="px-[24px]">
|
||||||
|
<a-select
|
||||||
|
v-if="testPlanGroups.length > 0"
|
||||||
|
v-model:model-value="activePlan"
|
||||||
|
:options="testPlanGroups"
|
||||||
|
class="w-[240px]"
|
||||||
|
@change="searchList"
|
||||||
|
></a-select>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<MsTab
|
||||||
|
v-model:active-key="activeTable"
|
||||||
|
:content-tab-list="contentTabList"
|
||||||
|
:show-badge="false"
|
||||||
|
class="testPlan-execute-tab no-content"
|
||||||
|
@change="searchList"
|
||||||
|
/>
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('report.detail.caseDetailSearchPlaceholder')"
|
||||||
|
allow-clear
|
||||||
|
class="w-[240px]"
|
||||||
|
@search="searchList"
|
||||||
|
@press-enter="searchList"
|
||||||
|
@clear="searchList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-[8px]">
|
||||||
|
<MsBaseTable
|
||||||
|
v-bind="currentCaseTable.propsRes.value"
|
||||||
|
:row-class="getRowClass"
|
||||||
|
v-on="currentCaseTable.propsEvent.value"
|
||||||
|
>
|
||||||
|
<template #num="{ record }">
|
||||||
|
<MsButton type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
|
||||||
|
</template>
|
||||||
|
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL]="{ filterContent }">
|
||||||
|
<caseLevel :case-level="filterContent.value" />
|
||||||
|
</template>
|
||||||
|
<template #priority="{ record }">
|
||||||
|
<caseLevel :case-level="record.priority" />
|
||||||
|
</template>
|
||||||
|
<template #[FilterSlotNameEnum.API_TEST_CASE_API_LAST_EXECUTE_STATUS]="{ filterContent }">
|
||||||
|
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="filterContent.value" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #lastExecResult="{ record }">
|
||||||
|
<ExecutionStatus
|
||||||
|
:module-type="ReportEnum.API_REPORT"
|
||||||
|
:status="record.executeResult"
|
||||||
|
:class="[!record.executeResult ? '' : 'cursor-pointer']"
|
||||||
|
@click="showReport(record)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</MsDrawer>
|
||||||
|
<CaseAndScenarioReportDrawer
|
||||||
|
v-if="reportVisible"
|
||||||
|
v-model:visible="reportVisible"
|
||||||
|
:report-id="apiReportId"
|
||||||
|
do-not-show-share
|
||||||
|
:is-scenario="activeTable === 'scenario'"
|
||||||
|
:report-detail="activeTable === 'scenario' ? reportScenarioDetail : reportCaseDetail"
|
||||||
|
:get-report-step-detail="activeTable === 'scenario' ? reportStepDetail : reportCaseStepDetail"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
import MsTab from '@/components/pure/ms-tab/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
|
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
||||||
|
import ExecuteAnalysis from '@/views/test-plan/report/detail/component/system-card/executeAnalysis.vue';
|
||||||
|
import ReportMetricsItem from '@/views/test-plan/report/detail/component/system-card/ReportMetricsItem.vue';
|
||||||
|
import SystemTrigger from '@/views/test-plan/report/detail/component/system-card/systemTrigger.vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getApiPage,
|
||||||
|
getScenarioPage,
|
||||||
|
getTestPlanResult,
|
||||||
|
reportCaseDetail,
|
||||||
|
reportCaseStepDetail,
|
||||||
|
reportScenarioDetail,
|
||||||
|
reportStepDetail,
|
||||||
|
} from '@/api/modules/test-plan/report';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||||
|
import { addCommasToNumber } from '@/utils';
|
||||||
|
|
||||||
|
import { ApiOrScenarioCaseItem } from '@/models/testPlan/report';
|
||||||
|
import { ReportMetricsItemModel } from '@/models/testPlan/testPlanReport';
|
||||||
|
import { ReportEnum } from '@/enums/reportEnum';
|
||||||
|
import { ApiTestRouteEnum } from '@/enums/routeEnum';
|
||||||
|
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||||
|
|
||||||
|
import { casePriorityOptions, lastReportStatusListOptions } from '@/views/api-test/components/config';
|
||||||
|
import { executeResultMap } from '@/views/taskCenter/component/config';
|
||||||
|
|
||||||
|
const CaseAndScenarioReportDrawer = defineAsyncComponent(
|
||||||
|
() => import('@/views/api-test/components/caseAndScenarioReportDrawer.vue')
|
||||||
|
);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: string;
|
||||||
|
isGroup: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { openNewPage } = useOpenNewPage();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', { required: true });
|
||||||
|
const loading = ref(false);
|
||||||
|
const detail = ref<any>({});
|
||||||
|
const testPlanGroups = ref<SelectOptionData[]>([]);
|
||||||
|
const activePlan = ref('');
|
||||||
|
|
||||||
|
const reportAnalysisList = computed<ReportMetricsItemModel[]>(() => {
|
||||||
|
if (props.isGroup) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: t('report.detail.testPlanTotal'),
|
||||||
|
value: detail.value.planCount,
|
||||||
|
unit: t('report.detail.number'),
|
||||||
|
icon: 'plan_total',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.detail.testPlanCaseTotal'),
|
||||||
|
value: detail.value.caseTotal,
|
||||||
|
unit: t('report.detail.number'),
|
||||||
|
icon: 'case_total',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.passRate'),
|
||||||
|
value: detail.value.passRate,
|
||||||
|
unit: '%',
|
||||||
|
icon: 'passRate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.detail.totalDefects'),
|
||||||
|
value: addCommasToNumber(detail.value.bugCount),
|
||||||
|
unit: t('report.detail.number'),
|
||||||
|
icon: 'bugTotal',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: t('report.detail.threshold'),
|
||||||
|
value: detail.value.passThreshold,
|
||||||
|
unit: '%',
|
||||||
|
icon: 'threshold',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.passRate'),
|
||||||
|
value: detail.value.passRate,
|
||||||
|
unit: '%',
|
||||||
|
icon: 'passRate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.detail.performCompletion'),
|
||||||
|
value: detail.value.executeRate,
|
||||||
|
unit: '%',
|
||||||
|
icon: 'passRate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('report.detail.totalDefects'),
|
||||||
|
value: addCommasToNumber(detail.value.bugCount),
|
||||||
|
unit: t('report.detail.number'),
|
||||||
|
icon: 'bugTotal',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'num',
|
||||||
|
slotName: 'num',
|
||||||
|
sortIndex: 1,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 150,
|
||||||
|
showTooltip: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.detail.level',
|
||||||
|
dataIndex: 'priority',
|
||||||
|
slotName: 'priority',
|
||||||
|
filterConfig: {
|
||||||
|
options: casePriorityOptions,
|
||||||
|
filterSlotName: FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL,
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.belongModule',
|
||||||
|
dataIndex: 'moduleName',
|
||||||
|
showTooltip: true,
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'testPlan.featureCase.executor',
|
||||||
|
dataIndex: 'executeUser',
|
||||||
|
showTooltip: true,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.executionResult',
|
||||||
|
dataIndex: 'executeResult',
|
||||||
|
slotName: 'lastExecResult',
|
||||||
|
filterConfig: {
|
||||||
|
options: lastReportStatusListOptions.value,
|
||||||
|
filterSlotName: FilterSlotNameEnum.API_TEST_CASE_API_LAST_EXECUTE_STATUS,
|
||||||
|
emptyFilter: true,
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const activeTable = ref<'case' | 'scenario'>('case');
|
||||||
|
const contentTabList = [
|
||||||
|
{ value: 'case', label: t('report.detail.apiCaseDetails') },
|
||||||
|
{ value: 'scenario', label: t('report.detail.scenarioCaseDetails') },
|
||||||
|
];
|
||||||
|
const keyword = ref('');
|
||||||
|
|
||||||
|
const useApiTable = useTable(getApiPage, {
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
columns,
|
||||||
|
showSelectorAll: false,
|
||||||
|
heightUsed: 236,
|
||||||
|
showSetting: false,
|
||||||
|
paginationSize: 'mini',
|
||||||
|
});
|
||||||
|
|
||||||
|
const useScenarioTable = useTable(getScenarioPage, {
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
columns,
|
||||||
|
showSelectorAll: false,
|
||||||
|
showSetting: false,
|
||||||
|
heightUsed: 236,
|
||||||
|
paginationSize: 'mini',
|
||||||
|
});
|
||||||
|
const currentCaseTable = computed(() => (activeTable.value === 'case' ? useApiTable : useScenarioTable));
|
||||||
|
|
||||||
|
// 显示执行报告
|
||||||
|
const reportVisible = ref(false);
|
||||||
|
|
||||||
|
const apiReportId = ref<string>('');
|
||||||
|
const selectedReportId = ref<string>('');
|
||||||
|
|
||||||
|
function showReport(record: ApiOrScenarioCaseItem) {
|
||||||
|
if (!record.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!record.executeResult || record.executeResult === 'STOPPED') return;
|
||||||
|
reportVisible.value = true;
|
||||||
|
apiReportId.value = record.reportId;
|
||||||
|
selectedReportId.value = record.reportId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRowClass(record: ApiOrScenarioCaseItem) {
|
||||||
|
return record.reportId === selectedReportId.value ? 'selected-row-class' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchList() {
|
||||||
|
currentCaseTable.value.setLoadListParams({
|
||||||
|
keyword: keyword.value,
|
||||||
|
reportId: activePlan.value || detail.value.id,
|
||||||
|
});
|
||||||
|
currentCaseTable.value.loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去用例详情页面
|
||||||
|
function toDetail(record: ApiOrScenarioCaseItem) {
|
||||||
|
if (activeTable.value === 'scenario') {
|
||||||
|
openNewPage(ApiTestRouteEnum.API_TEST_SCENARIO, {
|
||||||
|
id: record.id,
|
||||||
|
pId: record.projectId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openNewPage(ApiTestRouteEnum.API_TEST_MANAGEMENT, {
|
||||||
|
cId: record.id,
|
||||||
|
pId: record.projectId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getTestPlanResult(props.id);
|
||||||
|
detail.value = res;
|
||||||
|
if (res.children?.length) {
|
||||||
|
testPlanGroups.value = res.children.map((item: any) => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.name,
|
||||||
|
}));
|
||||||
|
activePlan.value = res.children[0]?.id;
|
||||||
|
}
|
||||||
|
searchList();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
if (props.id && val) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.testPlan-execute-tab {
|
||||||
|
.arco-tabs-tab:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
:deep(.ms-description-item) {
|
||||||
|
@apply items-center;
|
||||||
|
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
.analysis-wrapper {
|
||||||
|
@apply mb-4 grid items-center gap-4;
|
||||||
|
|
||||||
|
padding: 16px 16px 16px 24px;
|
||||||
|
background-color: var(--color-bg-3);
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
.analysis {
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
box-shadow: 0 0 10px rgba(120 56 135/ 5%);
|
||||||
|
@apply h-full rounded-xl bg-white;
|
||||||
|
.charts {
|
||||||
|
@apply absolute text-center;
|
||||||
|
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
z-index: 99;
|
||||||
|
width: 70px;
|
||||||
|
height: 42px;
|
||||||
|
transform: translateY(-50%) translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover-analysis {
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid rgb(var(--primary-5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -46,7 +46,10 @@
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
@apply mb-3 flex items-center justify-between;
|
@apply flex items-center justify-between;
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
.report-analysis-item-icon {
|
.report-analysis-item-icon {
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mb-[16px] font-medium">{{ t('report.detail.executionAnalysis') }}</div>
|
<div v-if="!props.hideTitle" class="mb-[16px] font-medium">{{ t('report.detail.executionAnalysis') }}</div>
|
||||||
<SetReportChart
|
<SetReportChart
|
||||||
size="130px"
|
size="130px"
|
||||||
:legend-data="legendData"
|
:legend-data="legendData"
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
detail: PlanReportDetail;
|
detail: PlanReportDetail;
|
||||||
|
hideTitle?: boolean;
|
||||||
animation?: boolean; // 是否开启动画
|
animation?: boolean; // 是否开启动画
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@ -108,12 +109,15 @@
|
||||||
|
|
||||||
const getTotal = computed(() => {
|
const getTotal = computed(() => {
|
||||||
const { executeCount } = props.detail;
|
const { executeCount } = props.detail;
|
||||||
|
if (executeCount) {
|
||||||
const { success, error, fakeError, pending, block } = executeCount;
|
const { success, error, fakeError, pending, block } = executeCount;
|
||||||
return success + error + fakeError + pending + block;
|
return success + error + fakeError + pending + block;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (props.detail) {
|
if (Object.keys(props.detail).length > 0) {
|
||||||
initExecuteOptions();
|
initExecuteOptions();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue