feat(测试计划): 计划报告列表页面
This commit is contained in:
parent
e8c29ee662
commit
c2d3ee2a81
|
@ -0,0 +1,26 @@
|
||||||
|
import MSR from '@/api/http';
|
||||||
|
import * as reportUrl from '@/api/requrls/test-plan/report';
|
||||||
|
|
||||||
|
import type { TableQueryParams } from '@/models/common';
|
||||||
|
|
||||||
|
// 报告列表
|
||||||
|
export function reportList(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: reportUrl.PlanReportListUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除报告
|
||||||
|
export function reportDelete(moduleType: string, id: string) {
|
||||||
|
return MSR.get({ url: `${reportUrl.PlanDeleteUrl}/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重命名
|
||||||
|
export function reportRename(moduleType: string, id: string, data: string) {
|
||||||
|
return MSR.post({ url: `${reportUrl.PlanReportRenameUrl}/${id}`, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
export function reportBathDelete(moduleType: string, data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: reportUrl.PlanBatchDeleteUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {};
|
|
@ -0,0 +1,8 @@
|
||||||
|
// 报告列表
|
||||||
|
export const PlanReportListUrl = '/api/report/scenario/page';
|
||||||
|
// 报告重命名
|
||||||
|
export const PlanReportRenameUrl = '/api/report/scenario/rename';
|
||||||
|
// 删除报告
|
||||||
|
export const PlanDeleteUrl = '/api/report/scenario/delete';
|
||||||
|
// 批量删除报告
|
||||||
|
export const PlanBatchDeleteUrl = '/api/report/scenario/batch/delete';
|
|
@ -958,6 +958,13 @@ export const pathMap: PathMapItem[] = [
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[2],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'TEST_PLAN_REPORT', // 测试计划报告
|
||||||
|
locale: 'menu.apiTest.report',
|
||||||
|
route: RouteEnum.TEST_PLAN_REPORT,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'TEST_PLAN_INDEX_DETAIL', // 测试计划-测试计划-测试计划详情
|
key: 'TEST_PLAN_INDEX_DETAIL', // 测试计划-测试计划-测试计划详情
|
||||||
locale: 'menu.testPlan.testPlanDetail',
|
locale: 'menu.testPlan.testPlanDetail',
|
||||||
|
|
|
@ -4,13 +4,17 @@ export enum ReportEnum {
|
||||||
API_REPORT = 'API_REPORT',
|
API_REPORT = 'API_REPORT',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ReportStatusEnum {
|
||||||
|
EXEC_STATUS = 'EXEC_STATUS',
|
||||||
|
REPORT_STATUS = 'REPORT_STATUS',
|
||||||
|
}
|
||||||
|
|
||||||
export enum TriggerModeLabel {
|
export enum TriggerModeLabel {
|
||||||
MANUAL = 'report.trigger.manual', // 手动执行
|
MANUAL = 'report.trigger.manual', // 手动执行
|
||||||
SCHEDULE = 'report.trigger.scheduled', // 定时任务
|
SCHEDULE = 'report.trigger.scheduled', // 定时任务
|
||||||
BATCH = 'report.trigger.batch.execution', // 批量执行
|
BATCH = 'report.trigger.batch.execution', // 批量执行
|
||||||
API = 'report.trigger.interface', // 接口调用
|
API = 'report.trigger.interface', // 接口调用
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReportStatus = {
|
export const ReportStatus = {
|
||||||
[ReportEnum.API_REPORT]: {
|
[ReportEnum.API_REPORT]: {
|
||||||
SUCCESS: {
|
SUCCESS: {
|
||||||
|
@ -81,4 +85,38 @@ export const ReportStatus = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PlanReportStatus = {
|
||||||
|
[ReportStatusEnum.EXEC_STATUS]: {
|
||||||
|
STOPPED: {
|
||||||
|
icon: 'icon-icon_block_filled',
|
||||||
|
label: 'report.stop',
|
||||||
|
color: '!var(--color-text-input-border)',
|
||||||
|
},
|
||||||
|
RUNNING: {
|
||||||
|
icon: 'icon-icon_testing',
|
||||||
|
label: 'report.inExecution',
|
||||||
|
color: '!text-[rgb(var(--link-6))]',
|
||||||
|
},
|
||||||
|
PENDING: {
|
||||||
|
icon: 'icon-icon_wait',
|
||||||
|
label: 'report.queuing',
|
||||||
|
color: '!text-[rgb(var(--link-6))]',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[ReportStatusEnum.REPORT_STATUS]: {
|
||||||
|
SUCCESS: {
|
||||||
|
icon: 'icon-icon_succeed_colorful',
|
||||||
|
label: 'report.successful',
|
||||||
|
},
|
||||||
|
ERROR: {
|
||||||
|
icon: 'icon-icon_close_colorful',
|
||||||
|
label: 'report.failure',
|
||||||
|
},
|
||||||
|
FAKE_ERROR: {
|
||||||
|
icon: 'icon-icon_warning_colorful',
|
||||||
|
label: 'report.falseAlarm',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -63,6 +63,7 @@ export enum TestPlanRouteEnum {
|
||||||
TEST_PLAN_INDEX = 'testPlanIndex',
|
TEST_PLAN_INDEX = 'testPlanIndex',
|
||||||
TEST_PLAN_INDEX_DETAIL = 'testPlanIndexDetail',
|
TEST_PLAN_INDEX_DETAIL = 'testPlanIndexDetail',
|
||||||
TEST_PLAN_INDEX_DETAIL_FEATURE_CASE_DETAIL = 'testPlanIndexDetailFeatureCaseDetail',
|
TEST_PLAN_INDEX_DETAIL_FEATURE_CASE_DETAIL = 'testPlanIndexDetailFeatureCaseDetail',
|
||||||
|
TEST_PLAN_REPORT = 'testPlanReport',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum UITestRouteEnum {
|
export enum UITestRouteEnum {
|
||||||
|
|
|
@ -66,6 +66,7 @@ export enum TableKeyEnum {
|
||||||
TEST_PLAN_DETAIL_BUG_TABLE = 'testPlanDetailBug',
|
TEST_PLAN_DETAIL_BUG_TABLE = 'testPlanDetailBug',
|
||||||
TEST_PLAN_DETAIL_FEATURE_CASE_TABLE = 'testPlanDetailFeatureCaseTable',
|
TEST_PLAN_DETAIL_FEATURE_CASE_TABLE = 'testPlanDetailFeatureCaseTable',
|
||||||
TEST_PLAN_DETAIL_BUG_TABLE_CASE_COUNT = 'testPlanDetailBugCaseCount',
|
TEST_PLAN_DETAIL_BUG_TABLE_CASE_COUNT = 'testPlanDetailBugCaseCount',
|
||||||
|
TEST_PLAN_REPORT_TABLE = 'testPlanReportTable',
|
||||||
TASK_API_CASE_SYSTEM = 'taskCenterApiCaseSystem',
|
TASK_API_CASE_SYSTEM = 'taskCenterApiCaseSystem',
|
||||||
TASK_API_CASE_ORGANIZATION = 'taskCenterApiCaseOrganization',
|
TASK_API_CASE_ORGANIZATION = 'taskCenterApiCaseOrganization',
|
||||||
TASK_API_CASE_PROJECT = 'taskCenterApiCaseProject',
|
TASK_API_CASE_PROJECT = 'taskCenterApiCaseProject',
|
||||||
|
|
|
@ -27,6 +27,16 @@ const TestPlan: AppRouteRecordRaw = {
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'testPlanReport',
|
||||||
|
name: TestPlanRouteEnum.TEST_PLAN_REPORT,
|
||||||
|
component: () => import('@/views/test-plan/report/index.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.apiTest.report',
|
||||||
|
roles: ['*'],
|
||||||
|
isTopMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
// 测试计划详情
|
// 测试计划详情
|
||||||
{
|
{
|
||||||
path: 'testPlanIndexDetail',
|
path: 'testPlanIndexDetail',
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<template>
|
||||||
|
<div class="condition-status" :style="getClass"> {{ t(scenarioStepMap[props.status].label) }} </div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { ScenarioStepType } from '@/enums/apiEnum';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<{
|
||||||
|
status: string;
|
||||||
|
}>();
|
||||||
|
// 场景步骤类型映射
|
||||||
|
const scenarioStepMap: Record<string, any> = {
|
||||||
|
[ScenarioStepType.LOOP_CONTROLLER]: { label: 'apiScenario.loopControl', color: 'rgba(167, 98, 191, 1)' },
|
||||||
|
[ScenarioStepType.IF_CONTROLLER]: { label: 'apiScenario.conditionControl', color: 'rgba(238, 80, 163, 1)' },
|
||||||
|
[ScenarioStepType.ONCE_ONLY_CONTROLLER]: { label: 'apiScenario.onlyOnceControl', color: 'rgba(211, 68, 0, 1)' },
|
||||||
|
[ScenarioStepType.SCRIPT]: { label: 'apiScenario.scriptOperation', color: 'rgba(20, 225, 198, 1)' },
|
||||||
|
[ScenarioStepType.API_CASE]: { label: 'report.detail.api.apiCase', color: 'rgb(var(--link-4))' },
|
||||||
|
[ScenarioStepType.CUSTOM_REQUEST]: { label: 'report.detail.api.customRequest', color: 'rgb(var(--link-4))' },
|
||||||
|
[ScenarioStepType.API]: { label: 'report.detail.api', color: 'rgb(var(--link-4))' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const getClass = computed(() => {
|
||||||
|
if (props.status) {
|
||||||
|
return {
|
||||||
|
color: scenarioStepMap[props.status]?.color,
|
||||||
|
border: `1px solid ${scenarioStepMap[props.status]?.color}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.condition-status {
|
||||||
|
padding: 0 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
border-radius: 0 12px 12px 0; /* 设置左半边为正常边框 */
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,119 @@
|
||||||
|
<template>
|
||||||
|
<MsColorLine :color-data="colorData" :height="props.height" :radius="props.radius">
|
||||||
|
<!-- TODO 这个页面还得根据实际业务调整-->
|
||||||
|
<template #popoverContent>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="pr-[8px] text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.progress') }}</td>
|
||||||
|
<td class="font-medium text-[var(--color-text-1)]">
|
||||||
|
{{ progress }}
|
||||||
|
<span> ({{ `${props.detail.passCount + props.detail.unPassCount}/${props.detail.caseCount}` }}) </span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--success-6))]"></div>
|
||||||
|
<div>{{ t('caseManagement.caseReview.pass') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ props.detail.passCount }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--danger-6))]"></div>
|
||||||
|
<div>{{ t('caseManagement.caseReview.fail') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ props.detail.unPassCount }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--warning-6))]"></div>
|
||||||
|
<div>{{ t('caseManagement.caseReview.reReview') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ props.detail.reReviewedCount }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--link-6))]"></div>
|
||||||
|
<div>{{ t('caseManagement.caseReview.reviewing') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ props.detail.underReviewedCount }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
</MsColorLine>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MsColorLine from '@/components/pure/ms-color-line/index.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
detail: {
|
||||||
|
passCount: number;
|
||||||
|
unPassCount: number;
|
||||||
|
reReviewedCount: number;
|
||||||
|
underReviewedCount: number;
|
||||||
|
caseCount: number;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
height: string;
|
||||||
|
radius?: string;
|
||||||
|
}>();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const colorData = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
percentage: 100,
|
||||||
|
color: 'var(--color-text-n8)',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
// TODO 实际业务调整
|
||||||
|
// return [
|
||||||
|
// {
|
||||||
|
// percentage: (props.detail.passCount / props.detail.caseCount) * 100,
|
||||||
|
// color: 'rgb(var(--success-6))',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// percentage: (props.detail.unPassCount / props.detail.caseCount) * 100,
|
||||||
|
// color: 'rgb(var(--danger-6))',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// percentage: (props.detail.reReviewedCount / props.detail.caseCount) * 100,
|
||||||
|
// color: 'rgb(var(--warning-6))',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// percentage: (props.detail.underReviewedCount / props.detail.caseCount) * 100,
|
||||||
|
// color: 'rgb(var(--link-6))',
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
});
|
||||||
|
const progress = computed(() => {
|
||||||
|
const result = ((props.detail.passCount + props.detail.unPassCount) / props.detail.caseCount) * 100;
|
||||||
|
return `${Number.isNaN(result) ? 0 : result.toFixed(2)}%`;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.popover-label-td {
|
||||||
|
@apply flex items-center;
|
||||||
|
|
||||||
|
padding: 8px 8px 0 0;
|
||||||
|
color: var(--color-text-4);
|
||||||
|
}
|
||||||
|
.popover-value-td {
|
||||||
|
@apply font-medium;
|
||||||
|
|
||||||
|
padding-top: 8px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,633 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-[16px]">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type" @change="changeShowType">
|
||||||
|
<a-radio value="All">{{ t('report.all') }}</a-radio>
|
||||||
|
<a-radio value="INDEPENDENT">{{ t('report.independent') }}</a-radio>
|
||||||
|
<a-radio value="INTEGRATED">{{ t('report.collection') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('project.menu.nameSearch')"
|
||||||
|
allow-clear
|
||||||
|
class="mx-[8px] w-[240px]"
|
||||||
|
@search="searchList"
|
||||||
|
@press-enter="searchList"
|
||||||
|
@clear="searchList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- 报告列表 -->
|
||||||
|
<ms-base-table
|
||||||
|
v-bind="propsRes"
|
||||||
|
ref="tableRef"
|
||||||
|
:action-config="tableBatchActions"
|
||||||
|
v-on="propsEvent"
|
||||||
|
@batch-action="handleTableBatch"
|
||||||
|
>
|
||||||
|
<template #name="{ record, rowIndex }">
|
||||||
|
<div
|
||||||
|
type="text"
|
||||||
|
class="one-line-text flex w-full text-[rgb(var(--primary-5))]"
|
||||||
|
@click="showReportDetail(record.id, rowIndex)"
|
||||||
|
>{{ characterLimit(record.name) }}</div
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<!-- 报告类型 -->
|
||||||
|
<template #integrated="{ record }">
|
||||||
|
<MsTag theme="light" :type="record.integrated ? 'primary' : undefined">
|
||||||
|
{{ record.integrated ? t('report.collection') : t('report.independent') }}
|
||||||
|
</MsTag>
|
||||||
|
</template>
|
||||||
|
<template #integratedFilter="{ columnConfig }">
|
||||||
|
<TableFilter
|
||||||
|
v-model:visible="reportTypeVisible"
|
||||||
|
v-model:status-filters="integratedFiltersMap[showType]"
|
||||||
|
:title="(columnConfig.title as string)"
|
||||||
|
:list="reportTypeList"
|
||||||
|
@search="initData()"
|
||||||
|
>
|
||||||
|
<template #item="{ item }">
|
||||||
|
<MsTag theme="light" :type="item.value === 'INTEGRATED' ? 'primary' : undefined">
|
||||||
|
{{ item.value === 'INTEGRATED' ? t('report.collection') : t('report.independent') }}
|
||||||
|
</MsTag>
|
||||||
|
</template>
|
||||||
|
</TableFilter>
|
||||||
|
</template>
|
||||||
|
<!-- 报告触发方式筛选 -->
|
||||||
|
<template #triggerModeFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="triggerModeFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
class="arco-btn-text--secondary p-[8px_4px]"
|
||||||
|
@click.stop="triggerModeFilterVisible = true"
|
||||||
|
>
|
||||||
|
<div class="font-medium">
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
</div>
|
||||||
|
<icon-down :class="triggerModeFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</a-button>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="ml-[6px] flex items-center justify-start px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group
|
||||||
|
v-model:model-value="triggerModeListFiltersMaps[showType]"
|
||||||
|
direction="vertical"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<a-checkbox v-for="(key, value) of TriggerModeLabel" :key="key" :value="value">
|
||||||
|
<div class="font-medium">{{ t(key) }}</div>
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="filter-button">
|
||||||
|
<a-button size="mini" class="mr-[8px]" @click="resetTriggerModeFilter">
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||||
|
{{ t('system.orgTemplate.confirm') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<!-- 通过率 -->
|
||||||
|
<template #passRateColumn>
|
||||||
|
<div class="flex items-center text-[var(--color-text-3)]">
|
||||||
|
{{ t('report.passRate') }}
|
||||||
|
<a-tooltip :content="t('report.passRateTip')" position="right">
|
||||||
|
<icon-question-circle
|
||||||
|
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #passRate="{ record }">
|
||||||
|
<div class="mr-[8px] w-[100px]">
|
||||||
|
<passRateLine :detail="record" height="5px" />
|
||||||
|
</div>
|
||||||
|
<div class="text-[var(--color-text-1)]">
|
||||||
|
{{ `${record.passRate | 0}%` }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 报告结果筛选 -->
|
||||||
|
<template #statusFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="statusFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click.stop="statusFilterVisible = true">
|
||||||
|
<div class="font-medium">
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
</div>
|
||||||
|
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</a-button>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group
|
||||||
|
v-model:model-value="statusListFiltersMap[showType]"
|
||||||
|
direction="vertical"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<a-checkbox v-for="key of statusFilters" :key="key" :value="key">
|
||||||
|
<ExecutionStatus :module-type="moduleType" :status="key" />
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="filter-button">
|
||||||
|
<a-button size="mini" class="mr-[8px]" @click="resetStatusFilter">
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||||
|
{{ t('system.orgTemplate.confirm') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<!-- 执行状态筛选 -->
|
||||||
|
<template #execStatusFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="execStatusFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleExecStatusFilterHidden"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
class="arco-btn-text--secondary p-[8px_4px]"
|
||||||
|
@click.stop="execStatusFilterVisible = true"
|
||||||
|
>
|
||||||
|
<div class="font-medium">
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
</div>
|
||||||
|
<icon-down :class="execStatusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</a-button>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group
|
||||||
|
v-model:model-value="statusListFiltersMap[showType]"
|
||||||
|
direction="vertical"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<a-checkbox v-for="key of execStatusFilters" :key="key" :value="key">
|
||||||
|
<ExecutionStatus :module-type="moduleType" :status="key" />
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="filter-button">
|
||||||
|
<a-button size="mini" class="mr-[8px]" @click="resetExecStatusFilter">
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" size="mini" @click="handleExecStatusFilterHidden(false)">
|
||||||
|
{{ t('system.orgTemplate.confirm') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<template #status="{ record }">
|
||||||
|
<ExecutionStatus :module-type="moduleType" :status="record.status" />
|
||||||
|
</template>
|
||||||
|
<template #triggerMode="{ record }">
|
||||||
|
<span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span>
|
||||||
|
</template>
|
||||||
|
<template #operationTime="{ record }">
|
||||||
|
<span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<MsButton
|
||||||
|
v-permission="['PROJECT_TEST_PLAN_REPORT:READ+DELETE']"
|
||||||
|
class="!mr-0"
|
||||||
|
@click="handleDelete(record.id, record.name)"
|
||||||
|
>{{ t('ms.comment.delete') }}</MsButton
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</ms-base-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
|
||||||
|
import passRateLine from '@/views/test-plan/report/component/passRateLine.vue';
|
||||||
|
import ExecutionStatus from '@/views/test-plan/report/component/reportStatus.vue';
|
||||||
|
|
||||||
|
import { reportBathDelete, reportDelete, reportList, reportRename } from '@/api/modules/test-plan/report';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useModal from '@/hooks/useModal';
|
||||||
|
import { useTableStore } from '@/store';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
import { characterLimit } from '@/utils';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
import { BatchApiParams } from '@/models/common';
|
||||||
|
import { PlanReportStatus, ReportStatusEnum, TriggerModeLabel } from '@/enums/reportEnum';
|
||||||
|
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const tableStore = useTableStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const moduleType = ReportStatusEnum.REPORT_STATUS;
|
||||||
|
const keyword = ref<string>('');
|
||||||
|
const statusFilterVisible = ref(false);
|
||||||
|
const execStatusFilterVisible = ref(false);
|
||||||
|
|
||||||
|
const triggerModeFilterVisible = ref(false);
|
||||||
|
|
||||||
|
const triggerModeListFilters = ref<string[]>([]);
|
||||||
|
|
||||||
|
type ReportShowType = 'All' | 'INDEPENDENT' | 'INTEGRATED';
|
||||||
|
const showType = ref<ReportShowType>('All');
|
||||||
|
|
||||||
|
const columns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'report.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
width: 200,
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
editType: hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
ellipsis: true,
|
||||||
|
showDrag: false,
|
||||||
|
columnSelectorDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.plan.name',
|
||||||
|
slotName: 'planName',
|
||||||
|
dataIndex: 'planName',
|
||||||
|
width: 200,
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
ellipsis: true,
|
||||||
|
showDrag: true,
|
||||||
|
columnSelectorDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.type',
|
||||||
|
slotName: 'integrated',
|
||||||
|
dataIndex: 'integrated',
|
||||||
|
titleSlotName: 'integratedFilter',
|
||||||
|
width: 150,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.execStatus',
|
||||||
|
dataIndex: 'execStatus',
|
||||||
|
slotName: 'execStatus',
|
||||||
|
titleSlotName: 'execStatusFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
|
width: 200,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: 'report.result',
|
||||||
|
dataIndex: 'status',
|
||||||
|
slotName: 'status',
|
||||||
|
titleSlotName: 'statusFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showInTable: true,
|
||||||
|
width: 200,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.passRate',
|
||||||
|
slotName: 'passRate',
|
||||||
|
titleSlotName: 'passRateColumn',
|
||||||
|
showDrag: true,
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.trigger.mode',
|
||||||
|
dataIndex: 'triggerMode',
|
||||||
|
slotName: 'triggerMode',
|
||||||
|
showInTable: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
showDrag: true,
|
||||||
|
titleSlotName: 'triggerModeFilter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.operator',
|
||||||
|
slotName: 'createUserName',
|
||||||
|
dataIndex: 'createUserName',
|
||||||
|
showInTable: true,
|
||||||
|
width: 300,
|
||||||
|
showDrag: true,
|
||||||
|
showTooltip: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'report.operating',
|
||||||
|
dataIndex: 'startTime',
|
||||||
|
slotName: 'startTime',
|
||||||
|
width: 180,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
title: hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+DELETE']) ? 'common.operation' : '',
|
||||||
|
width: hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+DELETE']) ? 130 : 50,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await tableStore.initColumn(TableKeyEnum.TEST_PLAN_REPORT_TABLE, columns, 'drawer');
|
||||||
|
|
||||||
|
const rename = async (record: any) => {
|
||||||
|
try {
|
||||||
|
await reportRename(moduleType, record.id, record.name);
|
||||||
|
Message.success(t('common.updateSuccess'));
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
|
||||||
|
reportList,
|
||||||
|
{
|
||||||
|
tableKey: TableKeyEnum.TEST_PLAN_REPORT_TABLE,
|
||||||
|
scroll: {
|
||||||
|
x: '100%',
|
||||||
|
},
|
||||||
|
showSetting: true,
|
||||||
|
selectable: hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ+DELETE']),
|
||||||
|
heightUsed: 230,
|
||||||
|
paginationSize: 'mini',
|
||||||
|
showSelectorAll: true,
|
||||||
|
},
|
||||||
|
(item) => ({
|
||||||
|
...item,
|
||||||
|
startTime: dayjs(item.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
}),
|
||||||
|
rename
|
||||||
|
);
|
||||||
|
// 全部过滤条件
|
||||||
|
const allListFilters = ref<string[]>([]);
|
||||||
|
const independentListFilters = ref<string[]>([]);
|
||||||
|
const integratedListFilters = ref<string[]>([]);
|
||||||
|
|
||||||
|
const statusListFiltersMap = ref<Record<string, string[]>>({
|
||||||
|
All: allListFilters.value,
|
||||||
|
INDEPENDENT: independentListFilters.value,
|
||||||
|
INTEGRATED: integratedListFilters.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
const allTriggerModeFilters = ref<string[]>([]);
|
||||||
|
const independentTriggerModeFilters = ref<string[]>([]);
|
||||||
|
const integratedTriggerModeFilters = ref<string[]>([]);
|
||||||
|
const triggerModeListFiltersMaps = ref<Record<string, string[]>>({
|
||||||
|
All: allTriggerModeFilters.value,
|
||||||
|
INDEPENDENT: independentTriggerModeFilters.value,
|
||||||
|
INTEGRATED: integratedTriggerModeFilters.value,
|
||||||
|
});
|
||||||
|
// 全部过滤条件
|
||||||
|
const allIntegratedFilters = ref<string[]>([]);
|
||||||
|
const independentIntegratedFilters = ref<string[]>([]);
|
||||||
|
const integratedIntegratedFilters = ref<string[]>([]);
|
||||||
|
|
||||||
|
const reportTypeVisible = ref<boolean>(false);
|
||||||
|
|
||||||
|
const integratedFiltersMap = ref<Record<string, string[]>>({
|
||||||
|
All: allIntegratedFilters.value,
|
||||||
|
INDEPENDENT: independentIntegratedFilters.value,
|
||||||
|
INTEGRATED: integratedIntegratedFilters.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
const reportTypeList = ref([
|
||||||
|
{
|
||||||
|
value: 'INDEPENDENT',
|
||||||
|
label: t('report.independent'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'INTEGRATED',
|
||||||
|
label: t('report.collection'),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const integratedFilters = computed(() => {
|
||||||
|
if (showType.value === 'All') {
|
||||||
|
if (integratedFiltersMap.value[showType.value].length === 1) {
|
||||||
|
return integratedFiltersMap.value[showType.value].includes('INDEPENDENT') ? [false] : [true];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (showType.value === 'INTEGRATED') {
|
||||||
|
return [true];
|
||||||
|
}
|
||||||
|
return [false];
|
||||||
|
});
|
||||||
|
|
||||||
|
function initData() {
|
||||||
|
setLoadListParams({
|
||||||
|
keyword: keyword.value,
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
moduleType,
|
||||||
|
filter: {
|
||||||
|
status: statusListFiltersMap.value[showType.value],
|
||||||
|
integrated: integratedFilters.value,
|
||||||
|
triggerMode: triggerModeListFiltersMaps.value[showType.value],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableBatchActions = {
|
||||||
|
baseAction: [
|
||||||
|
{
|
||||||
|
label: 'common.delete',
|
||||||
|
eventTag: 'batchStop',
|
||||||
|
permission: ['PROJECT_TEST_PLAN_REPORT:READ+DELETE'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const batchParams = ref<BatchApiParams>({
|
||||||
|
selectIds: [],
|
||||||
|
selectAll: false,
|
||||||
|
excludeIds: [] as string[],
|
||||||
|
condition: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
const handleTableBatch = async (event: BatchActionParams, params: BatchActionQueryParams) => {
|
||||||
|
batchParams.value = {
|
||||||
|
...params,
|
||||||
|
selectIds: params?.selectedIds || [],
|
||||||
|
condition: {
|
||||||
|
filter: {
|
||||||
|
status: statusListFiltersMap.value[showType.value],
|
||||||
|
integrated: integratedFilters.value,
|
||||||
|
triggerMode: triggerModeListFilters.value,
|
||||||
|
},
|
||||||
|
keyword: keyword.value,
|
||||||
|
},
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
};
|
||||||
|
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title: t('report.delete.tip', {
|
||||||
|
count: params?.currentSelectCount || params?.selectedIds?.length,
|
||||||
|
}),
|
||||||
|
content: '',
|
||||||
|
okText: t('common.confirmDelete'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await reportBathDelete(moduleType, batchParams.value);
|
||||||
|
Message.success(t('apiTestDebug.deleteSuccess'));
|
||||||
|
resetSelector();
|
||||||
|
initData();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function searchList() {
|
||||||
|
resetSelector();
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
const handleDelete = async (id: string, currentName: string) => {
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title: t('apiTestManagement.deleteApiTipTitle', { name: characterLimit(currentName) }),
|
||||||
|
content: '',
|
||||||
|
okText: t('common.confirmDelete'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await reportDelete(moduleType, id);
|
||||||
|
Message.success(t('apiTestDebug.deleteSuccess'));
|
||||||
|
initData();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
initData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const statusFilters = computed(() => {
|
||||||
|
return Object.keys(PlanReportStatus[ReportStatusEnum.REPORT_STATUS]) || [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const execStatusFilters = computed(() => {
|
||||||
|
return Object.keys(PlanReportStatus[ReportStatusEnum.EXEC_STATUS]) || [];
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleFilterHidden(val: boolean) {
|
||||||
|
if (!val) {
|
||||||
|
triggerModeFilterVisible.value = false;
|
||||||
|
statusFilterVisible.value = false;
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleExecStatusFilterHidden(val: boolean) {
|
||||||
|
if (!val) {
|
||||||
|
triggerModeFilterVisible.value = false;
|
||||||
|
execStatusFilterVisible.value = false;
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTriggerModeFilter() {
|
||||||
|
triggerModeFilterVisible.value = false;
|
||||||
|
triggerModeListFilters.value = [];
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetStatusFilter() {
|
||||||
|
statusFilterVisible.value = false;
|
||||||
|
statusListFiltersMap.value[showType.value] = [];
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetExecStatusFilter() {
|
||||||
|
execStatusFilterVisible.value = false;
|
||||||
|
statusListFiltersMap.value[showType.value] = [];
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeShowType(val: string | number | boolean) {
|
||||||
|
showType.value = val as ReportShowType;
|
||||||
|
resetSelector();
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报告详情 showReportDetail
|
||||||
|
*/
|
||||||
|
function showReportDetail(id: string, rowIndex: number) {
|
||||||
|
// 待处理
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => moduleType,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
resetSelector();
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.ms-table--special-small();
|
||||||
|
</style>
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center justify-start">
|
||||||
|
<MsIcon :type="getExecutionResult().icon" :class="getExecutionResult()?.color" size="14" />
|
||||||
|
<span class="ml-1">{{ t(getExecutionResult().label) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { ReportStatusEnum } from '@/enums/reportEnum';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<{
|
||||||
|
status: string;
|
||||||
|
moduleType: keyof typeof ReportStatusEnum;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
export interface IconType {
|
||||||
|
icon: string;
|
||||||
|
label: string;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconTypeStatus: Record<string, any> = {
|
||||||
|
[ReportStatusEnum.REPORT_STATUS]: {
|
||||||
|
RUNNING: {
|
||||||
|
icon: 'icon-icon_testing',
|
||||||
|
label: 'report.status.running',
|
||||||
|
color: '!text-[rgb(var(--link-6))]',
|
||||||
|
},
|
||||||
|
PENDING: {
|
||||||
|
icon: 'icon-icon_block_filled',
|
||||||
|
label: 'report.status.pending',
|
||||||
|
color: '!text-[var(--color-text-input-border)]',
|
||||||
|
},
|
||||||
|
DEFAULT: {
|
||||||
|
icon: 'icon-icon_block_filled',
|
||||||
|
label: 'report.status.pending',
|
||||||
|
color: '!text-[var(--color-text-input-border)]',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[ReportStatusEnum.EXEC_STATUS]: {
|
||||||
|
STOPPED: {
|
||||||
|
icon: 'icon-icon_block_filled',
|
||||||
|
label: 'report.stopped',
|
||||||
|
color: '!text-[var(--color-text-input-border)]',
|
||||||
|
},
|
||||||
|
RUNNING: {
|
||||||
|
icon: 'icon-icon_testing',
|
||||||
|
label: 'report.status.running',
|
||||||
|
color: '!text-[rgb(var(--link-6))]',
|
||||||
|
},
|
||||||
|
PENDING: {
|
||||||
|
icon: 'icon-icon_wait',
|
||||||
|
label: 'report.status.pending',
|
||||||
|
color: '!text-[var(--color-text-input-border)]',
|
||||||
|
},
|
||||||
|
DEFAULT: {
|
||||||
|
icon: 'icon-icon_wait',
|
||||||
|
label: 'report.status.pending',
|
||||||
|
color: '!text-[var(--color-text-input-border)]',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getExecutionResult(): IconType {
|
||||||
|
if (props.status in iconTypeStatus[props.moduleType]) {
|
||||||
|
return iconTypeStatus[props.moduleType][props.status];
|
||||||
|
}
|
||||||
|
return iconTypeStatus[props.moduleType].DEFAULT;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<template>
|
||||||
|
<MsCard simple no-content-padding>
|
||||||
|
<!-- 报告列表-->
|
||||||
|
<ReportList />
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import ReportList from './component/reportList.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
:deep(.arco-tabs-content) {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,34 @@
|
||||||
|
export default {
|
||||||
|
'report.api.case': 'Case report',
|
||||||
|
'report.api.scenario': 'Scenario report',
|
||||||
|
'report.all': 'All',
|
||||||
|
'report.independent': 'Independent report',
|
||||||
|
'report.collection': 'Collection report',
|
||||||
|
'report.name': 'Report name',
|
||||||
|
'report.type': 'Report type',
|
||||||
|
'report.result': 'Report result',
|
||||||
|
'report.trigger.mode': 'Trigger mode',
|
||||||
|
'report.operator': 'Create User',
|
||||||
|
'report.operating': 'Create time',
|
||||||
|
'report.batch.delete': 'Batch delete',
|
||||||
|
'report.successful': 'Successful',
|
||||||
|
'report.failure': 'failure',
|
||||||
|
'report.fake.error': 'Fake error',
|
||||||
|
'report.status.running': 'Running',
|
||||||
|
'report.status.rerunning': 'Rerunning',
|
||||||
|
'report.status.pending': 'Pending',
|
||||||
|
'report.stopped': 'Stopped',
|
||||||
|
'report.trigger.scheduled': 'Schedule',
|
||||||
|
'report.trigger.manual': 'Manual execution',
|
||||||
|
'report.trigger.interface': 'API',
|
||||||
|
'report.trigger.batch.execution': 'Batch',
|
||||||
|
'report.delete.tip': 'Are you sure you want to delete {count} selected reports?',
|
||||||
|
'report.detail.successCount': 'pass',
|
||||||
|
'report.detail.errorCount': 'Failure',
|
||||||
|
'report.detail.fakeErrorCount': 'False alarm',
|
||||||
|
'report.detail.pendingCount': 'Not executed',
|
||||||
|
'report.detail.stepTotal': 'total',
|
||||||
|
'report.execStatus': 'Execution status',
|
||||||
|
'report.plan.name': 'Plan Name',
|
||||||
|
'report.passRate': 'Pass rate',
|
||||||
|
};
|
|
@ -0,0 +1,35 @@
|
||||||
|
export default {
|
||||||
|
'report.api.case': '用例报告',
|
||||||
|
'report.api.scenario': '场景报告',
|
||||||
|
'report.all': '全部',
|
||||||
|
'report.independent': '独立报告',
|
||||||
|
'report.collection': '集合报告',
|
||||||
|
'report.name': '报告名称',
|
||||||
|
'report.type': '报告类型',
|
||||||
|
'report.result': '执行结果',
|
||||||
|
'report.trigger.mode': '触发方式',
|
||||||
|
'report.operator': '创建人',
|
||||||
|
'report.operating': '创建时间',
|
||||||
|
'report.batch.delete': '批量删除',
|
||||||
|
'report.successful': '成功',
|
||||||
|
'report.failure': '失败',
|
||||||
|
'report.fake.error': '误报',
|
||||||
|
'report.status.running': '执行中',
|
||||||
|
'report.status.rerunning': '重跑中',
|
||||||
|
'report.status.pending': '未执行',
|
||||||
|
'report.stopped': '停止',
|
||||||
|
'report.trigger.scheduled': '定时执行',
|
||||||
|
'report.trigger.manual': '手动执行',
|
||||||
|
'report.trigger.interface': 'API 执行',
|
||||||
|
'report.trigger.batch.execution': '批量执行',
|
||||||
|
'report.delete.tip': '确认删除已选中的 {count} 个报告吗?',
|
||||||
|
'report.detail.successCount': '通过',
|
||||||
|
'report.detail.errorCount': '失败',
|
||||||
|
'report.detail.fakeErrorCount': '误报',
|
||||||
|
'report.detail.pendingCount': '未执行',
|
||||||
|
'report.detail.stepTotal': '总数',
|
||||||
|
'report.execStatus': '执行状态',
|
||||||
|
'report.plan.name': '计划名称',
|
||||||
|
'report.passRate': '通过率',
|
||||||
|
'report.passRateTip': 'TODO待补充文案',
|
||||||
|
};
|
Loading…
Reference in New Issue