feat(任务中心): 任务中心接口联调
This commit is contained in:
parent
c1a59f4cc0
commit
e7ea9f975e
|
@ -1,7 +1,7 @@
|
||||||
import MSR from '@/api/http';
|
import MSR from '@/api/http';
|
||||||
import * as reportUrl from '@/api/requrls/api-test/report';
|
import * as reportUrl from '@/api/requrls/api-test/report';
|
||||||
|
|
||||||
import type { GetShareId, ReportDetail, ReportStepDetail } from '@/models/apiTest/report';
|
import type { GetShareId, ReportDetail, ReportStepDetail, ReportStepDetailItem } from '@/models/apiTest/report';
|
||||||
import type { TableQueryParams } from '@/models/common';
|
import type { TableQueryParams } from '@/models/common';
|
||||||
import { ReportEnum } from '@/enums/reportEnum';
|
import { ReportEnum } from '@/enums/reportEnum';
|
||||||
|
|
||||||
|
@ -111,4 +111,17 @@ export function downloadFile(data: string | undefined) {
|
||||||
return MSR.post({ url: reportUrl.DownloadFileUrl, data, responseType: 'blob' }, { isTransformResponse: false });
|
return MSR.post({ url: reportUrl.DownloadFileUrl, data, responseType: 'blob' }, { isTransformResponse: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {};
|
// 获取用例任务报告
|
||||||
|
export function getCaseTaskReport(taskId: string) {
|
||||||
|
return MSR.get<ReportStepDetailItem[]>({ url: `${reportUrl.caseTaskReportUrl}/${taskId}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取场景任务报告
|
||||||
|
export function getScenarioTaskReport(taskId: string) {
|
||||||
|
return MSR.get<ReportDetail>({ url: `${reportUrl.scenarioTaskReportUrl}/${taskId}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取场景任务报告-步骤
|
||||||
|
export function getScenarioTaskReportStep(taskId: string, stepId: string) {
|
||||||
|
return MSR.get<ReportStepDetailItem>({ url: `${reportUrl.scenarioTaskReportStepUrl}/${taskId}/${stepId}` });
|
||||||
|
}
|
||||||
|
|
|
@ -47,3 +47,12 @@ export const getShareReportInfoUrl = '/api/report/share/get';
|
||||||
export const getShareTimeUrl = '/api/report/share/get-share-time';
|
export const getShareTimeUrl = '/api/report/share/get-share-time';
|
||||||
// 下载文件地址
|
// 下载文件地址
|
||||||
export const DownloadFileUrl = '/api/test/download';
|
export const DownloadFileUrl = '/api/test/download';
|
||||||
|
|
||||||
|
// 用例任务报告
|
||||||
|
export const caseTaskReportUrl = '/api/report/case/task-report';
|
||||||
|
|
||||||
|
// 场景任务报告
|
||||||
|
export const scenarioTaskReportUrl = '/api/report/scenario/task-step';
|
||||||
|
|
||||||
|
// 场景任务报告-步骤
|
||||||
|
export const scenarioTaskReportStepUrl = '/api/report/scenario/task-report';
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
multiple
|
multiple
|
||||||
allow-clear
|
allow-clear
|
||||||
check-strictly
|
check-strictly
|
||||||
:max-tag-count="maxTagCount"
|
:max-tag-count="props.shouldCalculateMaxTag ? maxTagCount : 1"
|
||||||
:virtual-list-props="props.virtualListProps"
|
:virtual-list-props="props.virtualListProps"
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
:loading="props.loading"
|
:loading="props.loading"
|
||||||
|
@ -51,11 +51,11 @@
|
||||||
v-model:model-value="innerValue"
|
v-model:model-value="innerValue"
|
||||||
class="ms-cascader"
|
class="ms-cascader"
|
||||||
:options="props.options"
|
:options="props.options"
|
||||||
:trigger-props="{ contentClass: `ms-cascader-popper ms-cascader-popper--${props.optionSize}` }"
|
:trigger-props="{ contentClass: `ms-cascader-popper-native ms-cascader-popper--${props.optionSize}` }"
|
||||||
:multiple="props.multiple"
|
:multiple="props.multiple"
|
||||||
allow-clear
|
allow-clear
|
||||||
:check-strictly="props.strictly"
|
:check-strictly="props.strictly"
|
||||||
:max-tag-count="maxTagCount"
|
:max-tag-count="props.shouldCalculateMaxTag ? maxTagCount : 1"
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
:virtual-list-props="props.virtualListProps"
|
:virtual-list-props="props.virtualListProps"
|
||||||
:loading="props.loading"
|
:loading="props.loading"
|
||||||
|
@ -121,6 +121,7 @@
|
||||||
labelPathMode?: boolean; // 是否开启回显的 label 是路径模式
|
labelPathMode?: boolean; // 是否开启回显的 label 是路径模式
|
||||||
valueKey?: string;
|
valueKey?: string;
|
||||||
labelKey?: string; // 传入自定义的 labelKey
|
labelKey?: string; // 传入自定义的 labelKey
|
||||||
|
shouldCalculateMaxTag?: boolean; // 是否需要计算最大标签数
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<MsCascaderProps>(), {
|
const props = withDefaults(defineProps<MsCascaderProps>(), {
|
||||||
|
@ -129,6 +130,7 @@
|
||||||
pathMode: false,
|
pathMode: false,
|
||||||
valueKey: 'value',
|
valueKey: 'value',
|
||||||
labelKey: 'label',
|
labelKey: 'label',
|
||||||
|
shouldCalculateMaxTag: true,
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['update:modelValue', 'update:level', 'change']);
|
const emit = defineEmits(['update:modelValue', 'update:level', 'change']);
|
||||||
|
|
||||||
|
@ -161,6 +163,9 @@
|
||||||
// 顶级选项,该级别为单选选项
|
// 顶级选项,该级别为单选选项
|
||||||
innerLevel.value = val[0] as string;
|
innerLevel.value = val[0] as string;
|
||||||
}
|
}
|
||||||
|
if (props.shouldCalculateMaxTag !== false && props.multiple) {
|
||||||
|
calculateMaxTag();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
@ -175,11 +180,11 @@
|
||||||
selectedLabelObj = {};
|
selectedLabelObj = {};
|
||||||
for (let i = 0; i < val.length; i++) {
|
for (let i = 0; i < val.length; i++) {
|
||||||
const item = val[i];
|
const item = val[i];
|
||||||
const value = typeof item === 'object' ? item.value : item;
|
const value = typeof item === 'object' ? item[props.valueKey] : item;
|
||||||
if (!props.labelPathMode) {
|
if (!props.labelPathMode) {
|
||||||
selectedLabelObj[value] = t((item.label || '').split('/').pop() || '');
|
selectedLabelObj[value] = t((item[props.labelKey] || '').split('/').pop() || '');
|
||||||
} else {
|
} else {
|
||||||
selectedLabelObj[value] = t(item.label || '');
|
selectedLabelObj[value] = t(item[props.labelKey] || '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,8 +223,10 @@
|
||||||
innerLevel.value = '';
|
innerLevel.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (props.shouldCalculateMaxTag) {
|
||||||
calculateMaxTag();
|
calculateMaxTag();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 临时解决 arco-design 的 cascader 组件已选项的label只能是带路径‘/’的 path-mode 的问题
|
// TODO: 临时解决 arco-design 的 cascader 组件已选项的label只能是带路径‘/’的 path-mode 的问题
|
||||||
function getInputLabel(data: CascaderOption) {
|
function getInputLabel(data: CascaderOption) {
|
||||||
|
@ -258,7 +265,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ms-cascader-popper {
|
.ms-cascader-popper,
|
||||||
|
.ms-cascader-popper-native {
|
||||||
.arco-cascader-panel {
|
.arco-cascader-panel {
|
||||||
.arco-cascader-panel-column {
|
.arco-cascader-panel-column {
|
||||||
.arco-cascader-column-content {
|
.arco-cascader-column-content {
|
||||||
|
@ -275,6 +283,10 @@
|
||||||
background-color: rgb(var(--primary-1));
|
background-color: rgb(var(--primary-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-cascader-popper {
|
||||||
|
.arco-cascader-panel {
|
||||||
.arco-cascader-panel-column:first-child {
|
.arco-cascader-panel-column:first-child {
|
||||||
.arco-checkbox {
|
.arco-checkbox {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
|
|
|
@ -76,6 +76,7 @@ export enum TableKeyEnum {
|
||||||
TASK_CENTER_CASE_TASK = 'taskCenterCaseTask',
|
TASK_CENTER_CASE_TASK = 'taskCenterCaseTask',
|
||||||
TASK_CENTER_CASE_TASK_DETAIL = 'taskCenterCaseTaskDetail',
|
TASK_CENTER_CASE_TASK_DETAIL = 'taskCenterCaseTaskDetail',
|
||||||
TASK_CENTER_SYSTEM_TASK = 'taskCenterSystemTask',
|
TASK_CENTER_SYSTEM_TASK = 'taskCenterSystemTask',
|
||||||
|
TASK_CENTER_BATCH_TASK = 'taskCenterBatchTask',
|
||||||
TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM = 'taskCenterScheduleApiImportSystem',
|
TASK_SCHEDULE_TASK_API_IMPORT_SYSTEM = 'taskCenterScheduleApiImportSystem',
|
||||||
TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM = 'taskCenterScheduleApiScenarioSystem',
|
TASK_SCHEDULE_TASK_API_SCENARIO_SYSTEM = 'taskCenterScheduleApiScenarioSystem',
|
||||||
TASK_SCHEDULE_TASK_API_IMPORT_ORGANIZATION = 'taskCenterScheduleApiImportOrganization',
|
TASK_SCHEDULE_TASK_API_IMPORT_ORGANIZATION = 'taskCenterScheduleApiImportOrganization',
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { RequestResult } from '@/models/apiTest/common';
|
import { RequestResult } from '@/models/apiTest/common';
|
||||||
import type { RequestMethods } from '@/enums/apiEnum';
|
import type { RequestMethods } from '@/enums/apiEnum';
|
||||||
|
import type { ExecuteStatusEnum } from '@/enums/taskCenter';
|
||||||
|
|
||||||
export interface LegendData {
|
export interface LegendData {
|
||||||
label: string;
|
label: string;
|
||||||
|
@ -73,7 +74,7 @@ export interface ReportStepDetailItem {
|
||||||
id: string;
|
id: string;
|
||||||
reportId: string;
|
reportId: string;
|
||||||
stepId: string;
|
stepId: string;
|
||||||
status: string;
|
status: ExecuteStatusEnum;
|
||||||
fakeCode: string;
|
fakeCode: string;
|
||||||
requestName: string;
|
requestName: string;
|
||||||
requestTime: number;
|
requestTime: number;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ExecuteTaskType, ExecuteTriggerMode } from '@/enums/taskCenter';
|
import type { ExecuteStatusEnum, ExecuteTaskType, ExecuteTriggerMode } from '@/enums/taskCenter';
|
||||||
|
|
||||||
import type { TableQueryParams } from './common';
|
import type { TableQueryParams } from './common';
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ export interface TaskCenterTaskDetailItem {
|
||||||
resourceId: string;
|
resourceId: string;
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
taskOrigin: string; // 任务来源
|
taskOrigin: string; // 任务来源
|
||||||
status: string; // 执行状态
|
status: ExecuteStatusEnum; // 执行状态
|
||||||
result: string; // 执行结果
|
result: string; // 执行结果
|
||||||
resourcePoolId: string; // 资源池ID
|
resourcePoolId: string; // 资源池ID
|
||||||
resourcePoolNode: string; // 资源池节点
|
resourcePoolNode: string; // 资源池节点
|
||||||
|
|
|
@ -151,6 +151,8 @@
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
mode: 'tiled' | 'tab'; // 平铺 | tab形式
|
mode: 'tiled' | 'tab'; // 平铺 | tab形式
|
||||||
hideResponseTime?: boolean; // 是否隐藏响应时间栏
|
hideResponseTime?: boolean; // 是否隐藏响应时间栏
|
||||||
|
static?: boolean; // 是否静态展示
|
||||||
|
staticInfo?: ReportStepDetailItem; // 静态展示数据
|
||||||
stepItem?: ScenarioItemType; // 步骤详情
|
stepItem?: ScenarioItemType; // 步骤详情
|
||||||
console?: string;
|
console?: string;
|
||||||
isPriorityLocalExec?: boolean;
|
isPriorityLocalExec?: boolean;
|
||||||
|
@ -386,7 +388,10 @@
|
||||||
const originStepId = ref<string | undefined>('');
|
const originStepId = ref<string | undefined>('');
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (props.stepItem?.stepId && props.mode === 'tiled') {
|
if (props.static && props.staticInfo) {
|
||||||
|
activeStepDetail.value = props.staticInfo;
|
||||||
|
activeStepDetailCopy.value = cloneDeep(props.staticInfo);
|
||||||
|
} else if (props.stepItem?.stepId && props.mode === 'tiled') {
|
||||||
const stepIds = props.stepItem?.stepChildren || [];
|
const stepIds = props.stepItem?.stepChildren || [];
|
||||||
getStepDetail(isShowLoopControl.value ? stepIds[controlCurrent.value - 1].stepId : props.stepItem.stepId);
|
getStepDetail(isShowLoopControl.value ? stepIds[controlCurrent.value - 1].stepId : props.stepItem.stepId);
|
||||||
}
|
}
|
||||||
|
@ -394,7 +399,10 @@
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
originStepId.value = props.stepItem?.stepId;
|
originStepId.value = props.stepItem?.stepId;
|
||||||
if (props.stepItem?.stepId && !props.stepItem.fold) {
|
if (props.static && props.staticInfo) {
|
||||||
|
activeStepDetail.value = props.staticInfo;
|
||||||
|
activeStepDetailCopy.value = cloneDeep(props.staticInfo);
|
||||||
|
} else if (props.stepItem?.stepId && !props.stepItem.fold) {
|
||||||
const stepIds = props.stepItem?.stepChildren || [];
|
const stepIds = props.stepItem?.stepChildren || [];
|
||||||
getStepDetail(isShowLoopControl.value ? stepIds[controlCurrent.value - 1].stepId : props.stepItem.stepId);
|
getStepDetail(isShowLoopControl.value ? stepIds[controlCurrent.value - 1].stepId : props.stepItem.stepId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<a-button type="text" class="max-w-full justify-start px-0" @click="showReportDetail(record)">
|
<a-button type="text" class="max-w-full justify-start px-0" @click="showReportDetail(record)">
|
||||||
<div class="one-line-text">
|
<div class="one-line-text">
|
||||||
{{ record.num }}
|
{{ record.name }}
|
||||||
</div>
|
</div>
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -25,7 +25,8 @@
|
||||||
<ExecutionStatus :module-type="props.moduleType" :status="filterContent.value" />
|
<ExecutionStatus :module-type="props.moduleType" :status="filterContent.value" />
|
||||||
</template>
|
</template>
|
||||||
<template #execStatus="{ record }">
|
<template #execStatus="{ record }">
|
||||||
<ExecStatus :status="record.execStatus" />
|
<ExecStatus v-if="record.execStatus" :status="record.execStatus" />
|
||||||
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
<template #[FilterSlotNameEnum.API_TEST_CASE_API_REPORT_EXECUTE_RESULT]="{ filterContent }">
|
<template #[FilterSlotNameEnum.API_TEST_CASE_API_REPORT_EXECUTE_RESULT]="{ filterContent }">
|
||||||
<ExecStatus :status="filterContent.value" />
|
<ExecStatus :status="filterContent.value" />
|
||||||
|
@ -38,12 +39,37 @@
|
||||||
<template #triggerMode="{ record }">
|
<template #triggerMode="{ record }">
|
||||||
<span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span>
|
<span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #operationTime="{ record }">
|
<template #createTime="{ record }">
|
||||||
<span>{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
|
<span>{{ dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
<ReportDrawer v-model:visible="reportVisible" :report-id="independentReportId" />
|
<CaseReportDrawer
|
||||||
|
v-model:visible="showCaseDetailDrawer"
|
||||||
|
:report-id="activeDetailId"
|
||||||
|
:active-report-index="activeReportIndex"
|
||||||
|
:table-data="propsRes.data"
|
||||||
|
:page-change="propsEvent.pageChange"
|
||||||
|
:pagination="{
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 1,
|
||||||
|
}"
|
||||||
|
:share-time="shareTime"
|
||||||
|
/>
|
||||||
|
<ReportDetailDrawer
|
||||||
|
v-model:visible="showDetailDrawer"
|
||||||
|
:report-id="activeDetailId"
|
||||||
|
:active-report-index="activeReportIndex"
|
||||||
|
:table-data="propsRes.data"
|
||||||
|
:page-change="propsEvent.pageChange"
|
||||||
|
:pagination="{
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 1,
|
||||||
|
}"
|
||||||
|
:share-time="shareTime"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -54,31 +80,35 @@
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
||||||
|
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
||||||
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
||||||
import ExecStatus from '@/views/test-plan/report/component/execStatus.vue';
|
import ExecStatus from '@/views/test-plan/report/component/execStatus.vue';
|
||||||
import ReportDrawer from '@/views/test-plan/testPlan/detail/reportDrawer.vue';
|
|
||||||
|
|
||||||
|
import { getShareTime } from '@/api/modules/api-test/report';
|
||||||
import { organizationBatchTaskReportList } from '@/api/modules/taskCenter/organization';
|
import { organizationBatchTaskReportList } from '@/api/modules/taskCenter/organization';
|
||||||
import { projectBatchTaskReportList } from '@/api/modules/taskCenter/project';
|
import { projectBatchTaskReportList } from '@/api/modules/taskCenter/project';
|
||||||
import { systemBatchTaskReportList } from '@/api/modules/taskCenter/system';
|
import { systemBatchTaskReportList } from '@/api/modules/taskCenter/system';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useTableStore from '@/hooks/useTableStore';
|
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import { TaskCenterBatchTaskReportItem } from '@/models/taskCenter';
|
import { TaskCenterTaskItem } from '@/models/taskCenter';
|
||||||
import { ReportExecStatus } from '@/enums/apiEnum';
|
import { ReportExecStatus } from '@/enums/apiEnum';
|
||||||
import { ReportEnum, ReportStatus, TriggerModeLabel } from '@/enums/reportEnum';
|
import { ReportEnum, ReportStatus, TriggerModeLabel } from '@/enums/reportEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
|
||||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||||
|
import { ExecuteTaskType } from '@/enums/taskCenter';
|
||||||
|
|
||||||
|
import { executeMethodMap } from './config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
range: 'system' | 'project' | 'org';
|
range: 'system' | 'project' | 'org';
|
||||||
type: 'CASE' | 'SCENARIO';
|
type: 'CASE' | 'SCENARIO';
|
||||||
moduleType: keyof typeof ReportEnum;
|
moduleType: keyof typeof ReportEnum;
|
||||||
|
taskId: string;
|
||||||
|
batchType: ExecuteTaskType;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableStore = useTableStore();
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible', { required: true });
|
const visible = defineModel<boolean>('visible', { required: true });
|
||||||
|
@ -125,13 +155,13 @@
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
ellipsis: true,
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.type',
|
title: 'report.type',
|
||||||
slotName: 'integrated',
|
slotName: 'integrated',
|
||||||
dataIndex: 'integrated',
|
dataIndex: 'integrated',
|
||||||
width: 150,
|
width: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.result',
|
title: 'report.result',
|
||||||
|
@ -146,7 +176,7 @@
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
width: 200,
|
width: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.status',
|
title: 'report.status',
|
||||||
|
@ -161,27 +191,34 @@
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
width: 200,
|
width: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.trigger.mode',
|
title: 'report.trigger.mode',
|
||||||
dataIndex: 'triggerMode',
|
dataIndex: 'triggerMode',
|
||||||
slotName: 'triggerMode',
|
slotName: 'triggerMode',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
width: 150,
|
filterConfig: {
|
||||||
|
options: Object.keys(executeMethodMap).map((key) => ({
|
||||||
|
label: t(executeMethodMap[key]),
|
||||||
|
value: key,
|
||||||
|
})),
|
||||||
|
filterSlotName: FilterSlotNameEnum.GLOBAL_TASK_CENTER_EXEC_METHOD,
|
||||||
|
},
|
||||||
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.operator',
|
title: 'report.operator',
|
||||||
slotName: 'createUserName',
|
slotName: 'createUserName',
|
||||||
dataIndex: 'createUserName',
|
dataIndex: 'createUserName',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
width: 300,
|
width: 150,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'report.operating',
|
title: 'report.operating',
|
||||||
dataIndex: 'startTime',
|
dataIndex: 'createTime',
|
||||||
slotName: 'startTime',
|
slotName: 'createTime',
|
||||||
width: 180,
|
width: 180,
|
||||||
sortable: {
|
sortable: {
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
@ -190,8 +227,6 @@
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
await tableStore.initColumn(TableKeyEnum.API_TEST_REPORT, columns, 'drawer');
|
|
||||||
|
|
||||||
const currentList = {
|
const currentList = {
|
||||||
system: systemBatchTaskReportList,
|
system: systemBatchTaskReportList,
|
||||||
org: organizationBatchTaskReportList,
|
org: organizationBatchTaskReportList,
|
||||||
|
@ -200,7 +235,7 @@
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
|
||||||
currentList,
|
currentList,
|
||||||
{
|
{
|
||||||
tableKey: TableKeyEnum.API_TEST_REPORT,
|
columns,
|
||||||
scroll: {
|
scroll: {
|
||||||
x: '100%',
|
x: '100%',
|
||||||
},
|
},
|
||||||
|
@ -224,6 +259,8 @@
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
moduleType: props.moduleType,
|
moduleType: props.moduleType,
|
||||||
|
taskId: props.taskId,
|
||||||
|
batchType: props.batchType,
|
||||||
filter: {
|
filter: {
|
||||||
integrated: typeFilter.value,
|
integrated: typeFilter.value,
|
||||||
...filterParams,
|
...filterParams,
|
||||||
|
@ -236,13 +273,55 @@
|
||||||
initData(dataIndex, value);
|
initData(dataIndex, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const reportVisible = ref(false);
|
/**
|
||||||
const independentReportId = ref<string>('');
|
* 报告详情 showReportDetail
|
||||||
|
*/
|
||||||
|
const activeDetailId = ref<string>('');
|
||||||
|
const activeReportIndex = ref<number>(0);
|
||||||
|
const showDetailDrawer = ref<boolean>(false);
|
||||||
|
const showCaseDetailDrawer = ref<boolean>(false);
|
||||||
|
|
||||||
function showReportDetail(record: TaskCenterBatchTaskReportItem) {
|
function showReportDetail(record: TaskCenterTaskItem) {
|
||||||
independentReportId.value = record.id;
|
activeDetailId.value = record.id;
|
||||||
reportVisible.value = true;
|
if ([ExecuteTaskType.API_SCENARIO_BATCH, ExecuteTaskType.TEST_PLAN_API_SCENARIO_BATCH].includes(props.batchType)) {
|
||||||
|
showDetailDrawer.value = true;
|
||||||
|
} else {
|
||||||
|
showCaseDetailDrawer.value = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const shareTime = ref<string>('');
|
||||||
|
async function getTime() {
|
||||||
|
try {
|
||||||
|
const res = await getShareTime(appStore.currentProjectId);
|
||||||
|
const match = res.match(/^(\d+)([MYHD])$/);
|
||||||
|
if (match) {
|
||||||
|
const value = parseInt(match[1], 10);
|
||||||
|
const type = match[2];
|
||||||
|
const translations: Record<string, string> = {
|
||||||
|
M: t('msTimeSelector.month'),
|
||||||
|
Y: t('msTimeSelector.year'),
|
||||||
|
H: t('msTimeSelector.hour'),
|
||||||
|
D: t('msTimeSelector.day'),
|
||||||
|
};
|
||||||
|
shareTime.value = value + (translations[type] || translations.D);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
initData();
|
||||||
|
getTime();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -2,21 +2,22 @@
|
||||||
<MsDrawer v-model:visible="visible" :width="800" :footer="false">
|
<MsDrawer v-model:visible="visible" :width="800" :footer="false">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex items-center gap-[8px]">
|
||||||
<a-tag :color="executeResultMap[detail.executeResult]?.color">
|
<a-tag :color="executeResultMap[props.record.result]?.color">
|
||||||
{{ t(executeResultMap[detail.executeResult]?.label) }}
|
{{ t(executeResultMap[props.record.result]?.label) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<div>{{ detail.name }}</div>
|
<div>{{ detail.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 justify-end">
|
<div class="flex flex-1 justify-end">
|
||||||
<MsButton type="icon" status="secondary" class="!rounded-[var(--border-radius-small)]" @click="refresh">
|
<MsButton type="icon" status="secondary" class="!rounded-[var(--border-radius-small)]" @click="init">
|
||||||
<MsIcon type="icon-icon_reset_outlined" class="mr-[8px]" size="14" />
|
<MsIcon type="icon-icon_reset_outlined" class="mr-[8px]" size="14" />
|
||||||
{{ t('common.refresh') }}
|
{{ t('common.refresh') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<a-spin :loading="loading" class="block">
|
||||||
<MsDescription :descriptions="detail.description" :column="3" :line-gap="8" one-line-value>
|
<MsDescription :descriptions="detail.description" :column="3" :line-gap="8" one-line-value>
|
||||||
<template #value="{ item }">
|
<template #value="{ item }">
|
||||||
<execStatus v-if="item.key === 'status'" :status="item.value as ReportExecStatus" size="small" />
|
<execStatus v-if="item.key === 'status'" :status="props.record.status" size="small" />
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-else
|
v-else
|
||||||
:content="`${item.value}`"
|
:content="`${item.value}`"
|
||||||
|
@ -31,15 +32,17 @@
|
||||||
</MsDescription>
|
</MsDescription>
|
||||||
<div class="mt-[8px]">
|
<div class="mt-[8px]">
|
||||||
<StepDetailContent
|
<StepDetailContent
|
||||||
|
v-if="visible && detail.content"
|
||||||
mode="tiled"
|
mode="tiled"
|
||||||
show-type="CASE"
|
show-type="CASE"
|
||||||
:step-item="detail.scenarioDetail"
|
static
|
||||||
:console="detail.console"
|
:static-info="detail"
|
||||||
:is-definition="true"
|
:is-definition="true"
|
||||||
:get-report-step-detail="props.getReportStepDetail"
|
:get-report-step-detail="getCaseTaskReport"
|
||||||
:report-id="detail.scenarioDetail?.reportId"
|
:report-id="detail.reportId"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</a-spin>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -53,55 +56,55 @@
|
||||||
import execStatus from './execStatus.vue';
|
import execStatus from './execStatus.vue';
|
||||||
import StepDetailContent from '@/views/api-test/components/requestComposition/response/result/index.vue';
|
import StepDetailContent from '@/views/api-test/components/requestComposition/response/result/index.vue';
|
||||||
|
|
||||||
|
import { getCaseTaskReport } from '@/api/modules/api-test/report';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { ReportExecStatus } from '@/enums/apiEnum';
|
import { TaskCenterTaskDetailItem } from '@/models/taskCenter';
|
||||||
|
|
||||||
import { executeResultMap } from './config';
|
import { executeResultMap, executeStatusMap } from './config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: string;
|
record: TaskCenterTaskDetailItem;
|
||||||
getReportStepDetail?: (...args: any) => Promise<any>; // 获取步骤的详情内容接口
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible', { required: true });
|
const visible = defineModel<boolean>('visible', { required: true });
|
||||||
|
const loading = ref(false);
|
||||||
const detail = ref<any>({ description: [] });
|
const detail = ref<any>({ description: [] });
|
||||||
|
|
||||||
watch(
|
async function init() {
|
||||||
() => props.id,
|
try {
|
||||||
async () => {
|
loading.value = true;
|
||||||
if (props.id) {
|
const res = await getCaseTaskReport(props.record.id);
|
||||||
|
const [caseDetail] = res;
|
||||||
detail.value = {
|
detail.value = {
|
||||||
id: props.id,
|
name: caseDetail.requestName,
|
||||||
name: '测试用例名称',
|
|
||||||
executeResult: 'SUCCESS',
|
|
||||||
description: [
|
description: [
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.executeStatus'),
|
label: t('ms.taskCenter.executeStatus'),
|
||||||
key: 'status',
|
key: 'status',
|
||||||
value: 'COMPLETED',
|
value: t(executeStatusMap[props.record.status].label),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.operationUser'),
|
label: t('ms.taskCenter.operationUser'),
|
||||||
value: 'admin',
|
value: props.record.executor,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskCreateTime'),
|
label: t('ms.taskCenter.taskCreateTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: dayjs(props.record.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskResource'),
|
label: t('ms.taskCenter.taskResource'),
|
||||||
value: '测试计划',
|
value: props.record.resourceName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.threadID'),
|
label: t('ms.taskCenter.threadID'),
|
||||||
value: '1231231231',
|
value: props.record.threadId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskStartTime'),
|
label: t('ms.taskCenter.taskStartTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: dayjs(props.record.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.executeEnvInfo'),
|
label: t('ms.taskCenter.executeEnvInfo'),
|
||||||
|
@ -110,18 +113,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskEndTime'),
|
label: t('ms.taskCenter.taskEndTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: dayjs(props.record.endTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
] as Description[],
|
] as Description[],
|
||||||
|
...caseDetail,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
if (props.record.id && val) {
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
function refresh() {
|
|
||||||
console.log('refresh');
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -12,15 +12,18 @@
|
||||||
<MsCascader
|
<MsCascader
|
||||||
v-model:model-value="resourcePool"
|
v-model:model-value="resourcePool"
|
||||||
mode="native"
|
mode="native"
|
||||||
|
multiple
|
||||||
:options="resourcePoolOptions"
|
:options="resourcePoolOptions"
|
||||||
:placeholder="t('common.pleaseSelect')"
|
:placeholder="t('common.pleaseSelect')"
|
||||||
option-size="small"
|
option-size="small"
|
||||||
label-key="name"
|
|
||||||
value-key="id"
|
|
||||||
class="w-[240px]"
|
class="w-[240px]"
|
||||||
:prefix="t('ms.taskCenter.resourcePool')"
|
:prefix="t('ms.taskCenter.resourcePool')"
|
||||||
|
:virtual-list-props="{ height: 200 }"
|
||||||
|
strictly
|
||||||
label-path-mode
|
label-path-mode
|
||||||
@change="searchTask"
|
@clear="searchTask"
|
||||||
|
@popup-visible-change="handleResourcePoolVisibleChange"
|
||||||
|
@change="handleResourcePoolChange"
|
||||||
>
|
>
|
||||||
</MsCascader>
|
</MsCascader>
|
||||||
<MsTag no-margin size="large" :tooltip-disabled="true" class="cursor-pointer" theme="outline" @click="searchTask">
|
<MsTag no-margin size="large" :tooltip-disabled="true" class="cursor-pointer" theme="outline" @click="searchTask">
|
||||||
|
@ -69,13 +72,13 @@
|
||||||
>
|
>
|
||||||
{{ t('ms.taskCenter.rerun') }}
|
{{ t('ms.taskCenter.rerun') }}
|
||||||
</MsButton> -->
|
</MsButton> -->
|
||||||
<MsButton v-if="record.status === ExecuteStatusEnum.COMPLETED" @click="checkExecuteResult(record)">
|
<MsButton v-if="record.status !== ExecuteStatusEnum.PENDING" @click="checkExecuteResult(record)">
|
||||||
{{ t('ms.taskCenter.executeResult') }}
|
{{ t('ms.taskCenter.executeResult') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
<caseExecuteResultDrawer :id="executeResultId" v-model:visible="caseExecuteResultDrawerVisible" />
|
<caseExecuteResultDrawer v-model:visible="caseExecuteResultDrawerVisible" :record="activeRecord" />
|
||||||
<scenarioExecuteResultDrawer :id="executeResultId" v-model:visible="scenarioExecuteResultDrawerVisible" />
|
<scenarioExecuteResultDrawer v-model:visible="scenarioExecuteResultDrawerVisible" :record="activeRecord" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -119,7 +122,8 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useTableStore from '@/hooks/useTableStore';
|
import useTableStore from '@/hooks/useTableStore';
|
||||||
import { characterLimit } from '@/utils';
|
import { useAppStore } from '@/store';
|
||||||
|
import { characterLimit, mapTree } from '@/utils';
|
||||||
|
|
||||||
import { TaskCenterTaskDetailItem } from '@/models/taskCenter';
|
import { TaskCenterTaskDetailItem } from '@/models/taskCenter';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
@ -135,10 +139,11 @@
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
|
const appStore = useAppStore();
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
|
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
const resourcePool = ref([]);
|
const resourcePool = ref<string[]>([]);
|
||||||
const resourcePoolOptions = ref<CascaderOption[]>([]);
|
const resourcePoolOptions = ref<CascaderOption[]>([]);
|
||||||
const tableSelected = ref<string[]>([]);
|
const tableSelected = ref<string[]>([]);
|
||||||
const batchModalParams = ref();
|
const batchModalParams = ref();
|
||||||
|
@ -334,11 +339,57 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const resourcePoolIds = ref<Set<string>>(new Set([]));
|
||||||
|
const resourcePoolNodes = ref<Set<string>>(new Set([]));
|
||||||
function searchTask() {
|
function searchTask() {
|
||||||
setLoadListParams({ keyword: keyword.value, resourcePools: resourcePool.value });
|
setLoadListParams({
|
||||||
|
keyword: keyword.value,
|
||||||
|
resourcePoolIds: Array.from(resourcePoolIds.value),
|
||||||
|
resourcePoolNodes: Array.from(resourcePoolNodes.value),
|
||||||
|
});
|
||||||
loadList();
|
loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleResourcePoolVisibleChange(val: boolean) {
|
||||||
|
if (!val) {
|
||||||
|
searchTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResourcePoolChange(value: string[]) {
|
||||||
|
if (resourcePool.value.length < value.length) {
|
||||||
|
// 添加选中节点
|
||||||
|
const lastValue = value[value.length - 1];
|
||||||
|
const resourceClass = resourcePoolOptions.value.find((e) => e.value === lastValue);
|
||||||
|
if (resourceClass && resourceClass.children && resourceClass.children.length > 0) {
|
||||||
|
const childIds = resourceClass.children.map((e) => e.value as string);
|
||||||
|
resourcePool.value.push(...value, ...childIds);
|
||||||
|
resourcePool.value = Array.from(new Set(resourcePool.value));
|
||||||
|
childIds.forEach((e) => {
|
||||||
|
resourcePoolNodes.value.add(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (resourceClass) {
|
||||||
|
// 是资源池分类
|
||||||
|
resourcePoolIds.value.add(resourceClass.value as string);
|
||||||
|
} else {
|
||||||
|
// 是资源池节点
|
||||||
|
resourcePoolNodes.value.add(lastValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 移除选中节点
|
||||||
|
const lastValue = value[value.length - 1];
|
||||||
|
const resourceClass = resourcePoolOptions.value.find((e) => e.value === lastValue);
|
||||||
|
if (resourceClass) {
|
||||||
|
// 是资源池分类
|
||||||
|
resourcePoolIds.value.delete(resourceClass.value as string);
|
||||||
|
} else {
|
||||||
|
// 是资源池节点
|
||||||
|
resourcePoolNodes.value.delete(lastValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const currentStopTask = {
|
const currentStopTask = {
|
||||||
system: systemStopTaskDetail,
|
system: systemStopTaskDetail,
|
||||||
project: projectStopTaskDetail,
|
project: projectStopTaskDetail,
|
||||||
|
@ -409,11 +460,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const executeResultId = ref('');
|
const activeRecord = ref<TaskCenterTaskDetailItem>({} as TaskCenterTaskDetailItem);
|
||||||
const caseExecuteResultDrawerVisible = ref(false);
|
const caseExecuteResultDrawerVisible = ref(false);
|
||||||
const scenarioExecuteResultDrawerVisible = ref(false);
|
const scenarioExecuteResultDrawerVisible = ref(false);
|
||||||
function checkExecuteResult(record: TaskCenterTaskDetailItem) {
|
function checkExecuteResult(record: TaskCenterTaskDetailItem) {
|
||||||
executeResultId.value = record.id;
|
activeRecord.value = record;
|
||||||
if (record.resourceType === 'API_SCENARIO') {
|
if (record.resourceType === 'API_SCENARIO') {
|
||||||
scenarioExecuteResultDrawerVisible.value = true;
|
scenarioExecuteResultDrawerVisible.value = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -422,15 +473,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentResourcePoolRequest = {
|
const currentResourcePoolRequest = {
|
||||||
system: getProjectTaskCenterResourcePools,
|
system: getSystemTaskCenterResourcePools,
|
||||||
project: getOrgTaskCenterResourcePools,
|
project: getProjectTaskCenterResourcePools,
|
||||||
org: getSystemTaskCenterResourcePools,
|
org: getOrgTaskCenterResourcePools,
|
||||||
}[props.type];
|
}[props.type];
|
||||||
|
|
||||||
async function initResourcePools() {
|
async function initResourcePools() {
|
||||||
try {
|
try {
|
||||||
const res = await currentResourcePoolRequest();
|
const res = await currentResourcePoolRequest();
|
||||||
resourcePoolOptions.value = res;
|
resourcePoolOptions.value = mapTree(res, (node) => ({
|
||||||
|
label: node.name,
|
||||||
|
value: node.id,
|
||||||
|
children: node.children,
|
||||||
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -518,6 +573,13 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => appStore.currentProjectId,
|
||||||
|
() => {
|
||||||
|
searchTask();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (props.id) {
|
if (props.id) {
|
||||||
keyword.value = props.id;
|
keyword.value = props.id;
|
||||||
|
|
|
@ -131,9 +131,11 @@
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
<batchTaskReportDrawer
|
<batchTaskReportDrawer
|
||||||
v-model:visible="taskReportDrawerVisible"
|
v-model:visible="taskReportDrawerVisible"
|
||||||
:range="reportModuleType"
|
:range="props.type"
|
||||||
:type="reportModuleType"
|
:type="reportType"
|
||||||
:module-type="reportModuleType"
|
:module-type="reportModuleType"
|
||||||
|
:task-id="reportBatchTaskId"
|
||||||
|
:batch-type="reportBatchType"
|
||||||
/>
|
/>
|
||||||
<CaseReportDrawer
|
<CaseReportDrawer
|
||||||
v-model:visible="showCaseDetailDrawer"
|
v-model:visible="showCaseDetailDrawer"
|
||||||
|
@ -257,7 +259,7 @@
|
||||||
title: 'ms.taskCenter.executeStatus',
|
title: 'ms.taskCenter.executeStatus',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
slotName: 'status',
|
slotName: 'status',
|
||||||
width: 90,
|
width: 100,
|
||||||
filterConfig: {
|
filterConfig: {
|
||||||
options: Object.keys(executeStatusMap).map((key) => ({
|
options: Object.keys(executeStatusMap).map((key) => ({
|
||||||
label: t(executeStatusMap[key as ExecuteStatusEnum].label),
|
label: t(executeStatusMap[key as ExecuteStatusEnum].label),
|
||||||
|
@ -270,7 +272,7 @@
|
||||||
title: 'ms.taskCenter.executeMethod',
|
title: 'ms.taskCenter.executeMethod',
|
||||||
dataIndex: 'triggerMode',
|
dataIndex: 'triggerMode',
|
||||||
slotName: 'triggerMode',
|
slotName: 'triggerMode',
|
||||||
width: 90,
|
width: 100,
|
||||||
filterConfig: {
|
filterConfig: {
|
||||||
options: Object.keys(executeMethodMap).map((key) => ({
|
options: Object.keys(executeMethodMap).map((key) => ({
|
||||||
label: t(executeMethodMap[key]),
|
label: t(executeMethodMap[key]),
|
||||||
|
@ -283,7 +285,7 @@
|
||||||
title: 'ms.taskCenter.executeResult',
|
title: 'ms.taskCenter.executeResult',
|
||||||
dataIndex: 'result',
|
dataIndex: 'result',
|
||||||
slotName: 'result',
|
slotName: 'result',
|
||||||
width: 90,
|
width: 100,
|
||||||
filterConfig: {
|
filterConfig: {
|
||||||
options: Object.keys(executeResultMap).map((key) => ({
|
options: Object.keys(executeResultMap).map((key) => ({
|
||||||
label: t(executeResultMap[key].label),
|
label: t(executeResultMap[key].label),
|
||||||
|
@ -686,13 +688,17 @@
|
||||||
|
|
||||||
const taskReportDrawerVisible = ref(false);
|
const taskReportDrawerVisible = ref(false);
|
||||||
const reportModuleType = ref();
|
const reportModuleType = ref();
|
||||||
const reportBatchType = ref();
|
const reportType = ref<'CASE' | 'SCENARIO'>('CASE');
|
||||||
|
const reportBatchType = ref<ExecuteTaskType>(ExecuteTaskType.API_CASE);
|
||||||
|
const reportBatchTaskId = ref('');
|
||||||
function checkReport(record: TaskCenterTaskItem) {
|
function checkReport(record: TaskCenterTaskItem) {
|
||||||
if (record.taskType.includes('BATCH')) {
|
if (record.taskType.includes('BATCH')) {
|
||||||
reportModuleType.value = record.taskType.includes('CASE')
|
reportModuleType.value = record.taskType.includes('CASE')
|
||||||
? ReportEnum.API_REPORT
|
? ReportEnum.API_REPORT
|
||||||
: ReportEnum.API_SCENARIO_REPORT;
|
: ReportEnum.API_SCENARIO_REPORT;
|
||||||
reportBatchType.value = record.taskType.includes('CASE') ? 'CASE' : 'SCENARIO';
|
reportType.value = record.taskType.includes('CASE') ? 'CASE' : 'SCENARIO';
|
||||||
|
reportBatchType.value = record.taskType;
|
||||||
|
reportBatchTaskId.value = record.id;
|
||||||
taskReportDrawerVisible.value = true;
|
taskReportDrawerVisible.value = true;
|
||||||
} else if (
|
} else if (
|
||||||
[
|
[
|
||||||
|
@ -726,6 +732,13 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => appStore.currentProjectId,
|
||||||
|
() => {
|
||||||
|
searchTask();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await tableStore.initColumn(TableKeyEnum.TASK_CENTER_CASE_TASK, columns, 'drawer');
|
await tableStore.initColumn(TableKeyEnum.TASK_CENTER_CASE_TASK, columns, 'drawer');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { ReportExecStatus } from '@/enums/apiEnum';
|
import { ReportExecStatus } from '@/enums/apiEnum';
|
||||||
|
import { ExecuteStatusEnum } from '@/enums/taskCenter';
|
||||||
|
|
||||||
import { executeStatusMap } from './config';
|
import { executeStatusMap } from './config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
status: ReportExecStatus;
|
status: ReportExecStatus | ExecuteStatusEnum;
|
||||||
size?: 'small' | 'medium' | 'large';
|
size?: 'small' | 'medium' | 'large';
|
||||||
}>();
|
}>();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
|
@ -2,18 +2,19 @@
|
||||||
<MsDrawer v-model:visible="visible" :width="800" :footer="false">
|
<MsDrawer v-model:visible="visible" :width="800" :footer="false">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex items-center gap-[8px]">
|
||||||
<a-tag :color="executeResultMap[detail.executeResult]?.color">
|
<a-tag :color="executeResultMap[props.record.result]?.color">
|
||||||
{{ t(executeResultMap[detail.executeResult]?.label) }}
|
{{ t(executeResultMap[props.record.result]?.label) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<div>{{ detail.name }}</div>
|
<div>{{ detail.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 justify-end">
|
<div class="flex flex-1 justify-end">
|
||||||
<MsButton type="icon" status="secondary" class="!rounded-[var(--border-radius-small)]" @click="refresh">
|
<MsButton type="icon" status="secondary" class="!rounded-[var(--border-radius-small)]" @click="init">
|
||||||
<MsIcon type="icon-icon_reset_outlined" class="mr-[8px]" size="14" />
|
<MsIcon type="icon-icon_reset_outlined" class="mr-[8px]" size="14" />
|
||||||
{{ t('common.refresh') }}
|
{{ t('common.refresh') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<a-spin :loading="loading" class="block">
|
||||||
<MsDescription :descriptions="detail.description" :column="3" :line-gap="8" one-line-value>
|
<MsDescription :descriptions="detail.description" :column="3" :line-gap="8" one-line-value>
|
||||||
<template #value="{ item }">
|
<template #value="{ item }">
|
||||||
<execStatus v-if="item.key === 'status'" :status="item.value as ReportExecStatus" size="small" />
|
<execStatus v-if="item.key === 'status'" :status="item.value as ReportExecStatus" size="small" />
|
||||||
|
@ -43,12 +44,13 @@
|
||||||
v-model:keyword-name="keywordName"
|
v-model:keyword-name="keywordName"
|
||||||
:key-words="cascaderKeywords"
|
:key-words="cascaderKeywords"
|
||||||
show-type="API"
|
show-type="API"
|
||||||
:get-report-step-detail="props.getReportStepDetail"
|
:get-report-step-detail="getScenarioTaskReportStep"
|
||||||
:active-type="activeTab"
|
:active-type="activeTab"
|
||||||
:report-detail="detail || []"
|
:report-detail="detail || []"
|
||||||
class="p-[16px]"
|
class="p-[16px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</a-spin>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -63,55 +65,54 @@
|
||||||
import reportInfoHeader from '@/views/api-test/report/component/step/reportInfoHeaders.vue';
|
import reportInfoHeader from '@/views/api-test/report/component/step/reportInfoHeaders.vue';
|
||||||
import TiledList from '@/views/api-test/report/component/tiledList.vue';
|
import TiledList from '@/views/api-test/report/component/tiledList.vue';
|
||||||
|
|
||||||
|
import { getScenarioTaskReport, getScenarioTaskReportStep } from '@/api/modules/api-test/report';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { TaskCenterTaskDetailItem } from '@/models/taskCenter';
|
||||||
import { ReportExecStatus } from '@/enums/apiEnum';
|
import { ReportExecStatus } from '@/enums/apiEnum';
|
||||||
|
|
||||||
import { executeResultMap } from './config';
|
import { executeResultMap, executeStatusMap } from './config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: string;
|
record: TaskCenterTaskDetailItem;
|
||||||
getReportStepDetail?: (...args: any) => Promise<any>; // 获取步骤的详情内容接口
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible', { required: true });
|
const visible = defineModel<boolean>('visible', { required: true });
|
||||||
|
const loading = ref(false);
|
||||||
const detail = ref<any>({ description: [], children: [] });
|
const detail = ref<any>({ description: [], children: [] });
|
||||||
|
|
||||||
watch(
|
async function init() {
|
||||||
() => props.id,
|
try {
|
||||||
async () => {
|
loading.value = true;
|
||||||
if (props.id) {
|
const res = await getScenarioTaskReport(props.record.id);
|
||||||
detail.value = {
|
detail.value = {
|
||||||
id: props.id,
|
|
||||||
name: '测试用例名称',
|
|
||||||
executeResult: 'SUCCESS',
|
|
||||||
description: [
|
description: [
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.executeStatus'),
|
label: t('ms.taskCenter.executeStatus'),
|
||||||
key: 'status',
|
key: 'status',
|
||||||
value: 'COMPLETED',
|
value: t(executeStatusMap[props.record.status].label),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.operationUser'),
|
label: t('ms.taskCenter.operationUser'),
|
||||||
value: 'admin',
|
value: res.creatUserName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskCreateTime'),
|
label: t('ms.taskCenter.taskCreateTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: dayjs(res.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskResource'),
|
label: t('ms.taskCenter.taskResource'),
|
||||||
value: '测试计划',
|
value: props.record.resourceName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.threadID'),
|
label: t('ms.taskCenter.threadID'),
|
||||||
value: '1231231231',
|
value: props.record.threadId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskStartTime'),
|
label: t('ms.taskCenter.taskStartTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: dayjs(res.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.executeEnvInfo'),
|
label: t('ms.taskCenter.executeEnvInfo'),
|
||||||
|
@ -120,11 +121,24 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.taskCenter.taskEndTime'),
|
label: t('ms.taskCenter.taskEndTime'),
|
||||||
value: dayjs(1626844800000).format('YYYY-MM-DD HH:mm:ss'),
|
value: res.endTime ? dayjs(res.endTime).format('YYYY-MM-DD HH:mm:ss') : '-',
|
||||||
},
|
},
|
||||||
] as Description[],
|
] as Description[],
|
||||||
children: [],
|
...res,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.record.id,
|
||||||
|
() => {
|
||||||
|
if (props.record.id) {
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
|
@ -146,10 +160,6 @@
|
||||||
function resetHandler() {
|
function resetHandler() {
|
||||||
tiledListRef.value?.initStepTree();
|
tiledListRef.value?.initStepTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
|
||||||
console.log('refresh');
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -104,6 +104,7 @@
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||||
import useTableStore from '@/hooks/useTableStore';
|
import useTableStore from '@/hooks/useTableStore';
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
@ -123,6 +124,7 @@
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const { openNewPage } = useOpenNewPage();
|
const { openNewPage } = useOpenNewPage();
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
const batchModalParams = ref();
|
const batchModalParams = ref();
|
||||||
|
@ -464,6 +466,13 @@
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadList();
|
loadList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => appStore.currentProjectId,
|
||||||
|
() => {
|
||||||
|
searchTask();
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
Loading…
Reference in New Issue