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 });
|
||||
}
|
||||
|
||||
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 getShareCollectScenarioUrl = '/test-plan/report/share/detail/scenario/collection/page';
|
||||
// 任务中心-测试计划执行结果
|
||||
export const GetTestPlanResultUrl = '/test-plan/report/get-result';
|
||||
|
|
|
@ -40,12 +40,14 @@
|
|||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
<CaseReportCom
|
||||
v-if="!props.isScenario"
|
||||
:detail-info="reportStepDetail"
|
||||
:get-report-step-detail="props.getReportStepDetail"
|
||||
/>
|
||||
<ScenarioCom v-else :detail-info="reportStepDetail" :get-report-step-detail="props.getReportStepDetail" />
|
||||
<a-spin :loading="loading" class="block">
|
||||
<CaseReportCom
|
||||
v-if="!props.isScenario"
|
||||
:detail-info="reportStepDetail"
|
||||
:get-report-step-detail="props.getReportStepDetail"
|
||||
/>
|
||||
<ScenarioCom v-else :detail-info="reportStepDetail" :get-report-step-detail="props.getReportStepDetail" />
|
||||
</a-spin>
|
||||
</MsDrawer>
|
||||
</template>
|
||||
|
||||
|
@ -128,8 +130,11 @@
|
|||
const reportStepDetail = ref<ReportDetail>({
|
||||
...initReportStepDetail,
|
||||
});
|
||||
const loading = ref(false);
|
||||
|
||||
async function getReportDetail() {
|
||||
try {
|
||||
loading.value = true;
|
||||
if (props.reportDetail) {
|
||||
reportStepDetail.value = await props.reportDetail(props.reportId, route.query.shareId as string | undefined);
|
||||
return;
|
||||
|
@ -142,6 +147,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +159,9 @@
|
|||
reportStepDetail.value = { ...initReportStepDetail };
|
||||
await getReportDetail();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
{{ t('ms.taskCenter.rerun') }}
|
||||
</MsButton>
|
||||
<MsButton v-if="record.status === ExecuteStatusEnum.COMPLETED" @click="checkReport(record)">
|
||||
{{ t('ms.taskCenter.checkReport') }}
|
||||
{{ t('ms.taskCenter.executeResult') }}
|
||||
</MsButton>
|
||||
</template>
|
||||
</ms-base-table>
|
||||
|
@ -108,6 +108,11 @@
|
|||
}"
|
||||
:share-time="shareTime"
|
||||
/>
|
||||
<TestPlanExecuteResultDrawer
|
||||
:id="activeDetailId"
|
||||
v-model:visible="showTestPlanDetailDrawer"
|
||||
:is-group="isTestPlanGroup"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -124,6 +129,7 @@
|
|||
import execStatus from './execStatus.vue';
|
||||
import executeRatePopper from './executeRatePopper.vue';
|
||||
import executeResultStatus from './executeResultStatus.vue';
|
||||
import TestPlanExecuteResultDrawer from './testPlanExecuteResultDrawer.vue';
|
||||
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
||||
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
||||
|
||||
|
@ -160,7 +166,6 @@
|
|||
} from '@/api/modules/taskCenter/system';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||
import useTableStore from '@/hooks/useTableStore';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import { characterLimit } from '@/utils';
|
||||
|
@ -168,7 +173,6 @@
|
|||
|
||||
import { TaskCenterTaskItem } from '@/models/taskCenter';
|
||||
import { ReportEnum } from '@/enums/reportEnum';
|
||||
import { TestPlanRouteEnum } from '@/enums/routeEnum';
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||
import { ExecuteResultEnum, ExecuteStatusEnum, ExecuteTaskType } from '@/enums/taskCenter';
|
||||
|
@ -185,7 +189,6 @@
|
|||
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
const { openNewPage } = useOpenNewPage();
|
||||
const tableStore = useTableStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
|
@ -657,6 +660,8 @@
|
|||
const activeReportIndex = ref<number>(0);
|
||||
const showDetailDrawer = ref<boolean>(false);
|
||||
const showCaseDetailDrawer = ref<boolean>(false);
|
||||
const showTestPlanDetailDrawer = ref<boolean>(false);
|
||||
const isTestPlanGroup = ref(false);
|
||||
|
||||
function showReportDetail(record: TaskCenterTaskItem) {
|
||||
activeDetailId.value = record.reportId;
|
||||
|
@ -718,12 +723,9 @@
|
|||
) {
|
||||
showReportDetail(record);
|
||||
} else if ([ExecuteTaskType.TEST_PLAN_GROUP, ExecuteTaskType.TEST_PLAN].includes(record.taskType)) {
|
||||
openNewPage(TestPlanRouteEnum.TEST_PLAN_REPORT, {
|
||||
orgId: record.organizationId,
|
||||
pId: record.projectId,
|
||||
id: record.reportId,
|
||||
type: record.taskType === ExecuteTaskType.TEST_PLAN_GROUP ? 'GROUP' : '',
|
||||
});
|
||||
showTestPlanDetailDrawer.value = true;
|
||||
activeDetailId.value = record.reportId;
|
||||
isTestPlanGroup.value = record.taskType === ExecuteTaskType.TEST_PLAN_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;
|
||||
border-radius: 4px;
|
||||
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 {
|
||||
@apply flex items-center;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<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
|
||||
size="130px"
|
||||
:legend-data="legendData"
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
const props = defineProps<{
|
||||
detail: PlanReportDetail;
|
||||
hideTitle?: boolean;
|
||||
animation?: boolean; // 是否开启动画
|
||||
}>();
|
||||
|
||||
|
@ -108,12 +109,15 @@
|
|||
|
||||
const getTotal = computed(() => {
|
||||
const { executeCount } = props.detail;
|
||||
const { success, error, fakeError, pending, block } = executeCount;
|
||||
return success + error + fakeError + pending + block;
|
||||
if (executeCount) {
|
||||
const { success, error, fakeError, pending, block } = executeCount;
|
||||
return success + error + fakeError + pending + block;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.detail) {
|
||||
if (Object.keys(props.detail).length > 0) {
|
||||
initExecuteOptions();
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue