feat(测试计划): 测试计划详情-执行历史联调&调整新建测试计划

This commit is contained in:
teukkk 2024-06-14 17:36:19 +08:00 committed by Craftsman
parent 7703a79d03
commit 8965678a2c
11 changed files with 53 additions and 35 deletions

View File

@ -392,7 +392,7 @@ export function getApiScenarioReport(reportId: string) {
export function getApiScenarioReportStep(reportId: string, stepId: string) { export function getApiScenarioReportStep(reportId: string, stepId: string) {
return MSR.get<ReportStepDetail[]>({ url: `${ApiScenarioReportDetailStepUrl}/${reportId}/${stepId}` }); return MSR.get<ReportStepDetail[]>({ url: `${ApiScenarioReportDetailStepUrl}/${reportId}/${stepId}` });
} }
// 计划详情-执行历史 TODO 联调 // 计划详情-执行历史
export function getPlanDetailExecuteHistory(data: PlanDetailFeatureCaseListQueryParams) { export function getPlanDetailExecuteHistory(data: PlanDetailFeatureCaseListQueryParams) {
return MSR.post<CommonList<PlanDetailExecuteHistoryItem>>({ url: PlanDetailExecuteHistoryUrl, data }); return MSR.post<CommonList<PlanDetailExecuteHistoryItem>>({ url: PlanDetailExecuteHistoryUrl, data });
} }

View File

@ -80,8 +80,8 @@ export const GetTestPlanUsersUrl = '/test-plan/functional/case/user-option';
export const BatchUpdateCaseExecutorUrl = '/test-plan/functional/case/batch/update/executor'; export const BatchUpdateCaseExecutorUrl = '/test-plan/functional/case/batch/update/executor';
// 计划详情-功能用例-执行历史 // 计划详情-功能用例-执行历史
export const ExecuteHistoryUrl = '/test-plan/functional/case/exec/history'; export const ExecuteHistoryUrl = '/test-plan/functional/case/exec/history';
// 计划详情-执行历史 TODO 联调 // 计划详情-执行历史
export const PlanDetailExecuteHistoryUrl = '/api/scenario/execute/page'; export const PlanDetailExecuteHistoryUrl = '/his/page';
// 功能用例-关联用例-接口用例-API // 功能用例-关联用例-接口用例-API
export const TestPlanApiAssociatedPageUrl = '/test-plan/association/api/page'; export const TestPlanApiAssociatedPageUrl = '/test-plan/association/api/page';
// 功能用例-关联用例-接口用例-CASE // 功能用例-关联用例-接口用例-CASE

View File

@ -98,7 +98,7 @@ body {
} }
/* 白色背景的tooltip */ /* 白色背景的tooltip */
.tooltip-white { .ms-tooltip-white {
.arco-tooltip-content { .arco-tooltip-content {
background-color: var(--color-bg-1); background-color: var(--color-bg-1);
box-shadow: 0 4px 10px -1px rgb(100 100 102 / 15%); box-shadow: 0 4px 10px -1px rgb(100 100 102 / 15%);
@ -108,3 +108,16 @@ body {
background-color: var(--color-bg-1); background-color: var(--color-bg-1);
} }
} }
/* 红色背景的tooltip */
.ms-tooltip-red {
.arco-tooltip-content {
color: rgb(var(--danger-6));
background-color: rgb(var(--danger-1));
box-shadow: 0 4px 10px -1px rgb(100 100 102 / 15%);
}
.arco-tooltip-popup-arrow {
z-index: 1;
background-color: rgb(var(--danger-1));
}
}

View File

@ -61,6 +61,7 @@ export interface AddTestPlanParams {
projectId?: string; projectId?: string;
testPlanId?: string; testPlanId?: string;
functionalCaseCount?: number; functionalCaseCount?: number;
isGroup?: boolean;
} }
export interface TestPlanDetail extends AddTestPlanParams { export interface TestPlanDetail extends AddTestPlanParams {
@ -144,7 +145,7 @@ export interface FollowPlanParams {
} }
export interface TestPlanBaseParams { export interface TestPlanBaseParams {
projectId: string; projectId?: string;
testPlanId: string; testPlanId: string;
} }
@ -348,17 +349,16 @@ export interface PlanDetailApiScenarioItem {
testPlanCollectionId: string; // 测试集id testPlanCollectionId: string; // 测试集id
} }
// 执行历史 TODO 联调 // 执行历史
export interface PlanDetailExecuteHistoryItem { export interface PlanDetailExecuteHistoryItem {
id: string; id: string;
num: string; num: string;
name: string; triggerMode: string; // 执行方式
execStatus: string; // 执行结果
operationUser: string; operationUser: string;
createUser: string;
startTime: number; startTime: number;
endTime: number; endTime: number;
lastExecResult: LastExecuteResults; deleted: boolean;
triggerMode: string;
} }
export interface CreateTask { export interface CreateTask {

View File

@ -19,7 +19,7 @@
</div> </div>
<MsBaseTable v-bind="propsRes" v-on="propsEvent"> <MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #revokeDelete="{ record }"> <template #revokeDelete="{ record }">
<a-tooltip class="tooltip-white"> <a-tooltip class="ms-tooltip-white">
<template #content> <template #content>
<div class="flex flex-row"> <div class="flex flex-row">
<span class="text-[var(--color-text-1)]"> <span class="text-[var(--color-text-1)]">

View File

@ -1,7 +1,7 @@
<template> <template>
<MsBaseTable v-bind="propsRes" v-on="propsEvent"> <MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #revokeDelete="{ record }"> <template #revokeDelete="{ record }">
<a-tooltip class="tooltip-white"> <a-tooltip class="ms-tooltip-white">
<template #content> <template #content>
<div class="flex flex-row"> <div class="flex flex-row">
<span class="text-[var(--color-text-1)]">{{ <span class="text-[var(--color-text-1)]">{{

View File

@ -1,7 +1,7 @@
<template> <template>
<MsBaseTable v-bind="propsRes" v-on="propsEvent"> <MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #revokeDelete="{ record }"> <template #revokeDelete="{ record }">
<a-tooltip class="tooltip-white"> <a-tooltip class="ms-tooltip-white">
<template #content> <template #content>
<div class="flex flex-row"> <div class="flex flex-row">
<span class="text-[var(--color-text-1)]">{{ <span class="text-[var(--color-text-1)]">{{

View File

@ -28,28 +28,25 @@
field="type" field="type"
:label="props.planId?.length ? t('caseManagement.featureCase.moveTo') : t('testPlan.planForm.createTo')" :label="props.planId?.length ? t('caseManagement.featureCase.moveTo') : t('testPlan.planForm.createTo')"
> >
<a-radio-group v-model:model-value="form.type"> <a-radio-group v-model:model-value="form.isGroup">
<a-radio :value="testPlanTypeEnum.TEST_PLAN">{{ t('testPlan.testPlanGroup.module') }}</a-radio> <a-radio :value="false">{{ t('testPlan.testPlanGroup.module') }}</a-radio>
<a-radio :value="testPlanTypeEnum.GROUP">{{ t('testPlan.testPlanIndex.testPlanGroup') }}</a-radio> <a-radio :value="true">{{ t('testPlan.testPlanIndex.testPlanGroup') }}</a-radio>
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
v-show="form.type === testPlanTypeEnum.GROUP" v-if="form.isGroup"
field="groupId" field="groupId"
:rules="[{ required: true, message: t('testPlan.planForm.testPlanGroupRequired') }]"
:label="t('testPlan.testPlanIndex.testPlanGroup')" :label="t('testPlan.testPlanIndex.testPlanGroup')"
class="w-[436px]" class="w-[436px]"
> >
<a-select v-model="form.groupId" :placeholder="t('common.pleaseSelect')"> <a-select v-model="form.groupId" allow-search :placeholder="t('common.pleaseSelect')">
<a-option v-for="item of groupList" :key="item.id" :value="item.id"> <a-option v-for="item of groupList" :key="item.id" :value="item.id">
{{ item.name }} {{ item.name }}
</a-option> </a-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item <a-form-item v-else field="moduleId" :label="t('common.belongModule')" class="w-[436px]">
v-show="form.type === testPlanTypeEnum.TEST_PLAN"
:label="t('common.belongModule')"
class="w-[436px]"
>
<a-tree-select <a-tree-select
v-model:modelValue="form.moduleId" v-model:modelValue="form.moduleId"
:data="props.moduleTree" :data="props.moduleTree"
@ -178,7 +175,7 @@
const drawerLoading = ref(false); const drawerLoading = ref(false);
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const initForm: AddTestPlanParams = { const initForm: AddTestPlanParams = {
groupId: 'NONE', isGroup: false,
name: '', name: '',
projectId: '', projectId: '',
moduleId: 'root', moduleId: 'root',
@ -310,6 +307,7 @@
form.value.cycle = [result.plannedStartTime as number, result.plannedEndTime as number]; form.value.cycle = [result.plannedStartTime as number, result.plannedEndTime as number];
form.value.passThreshold = parseFloat(result.passThreshold.toString()); form.value.passThreshold = parseFloat(result.passThreshold.toString());
form.value.isGroup = result.groupId !== 'none';
} }
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -8,16 +8,20 @@
<span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span> <span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span>
</template> </template>
<template #lastExecResult="{ record }"> <template #lastExecResult="{ record }">
<ExecutionStatus :status="record.status" :module-type="ReportEnum.API_REPORT" /> <ExecutionStatus :status="record.execStatus" :module-type="ReportEnum.API_REPORT" />
</template> </template>
<template #executionStartAndEndTime="{ record }"> <template #executionStartAndEndTime="{ record }">
<!-- TODO 样式 --> <div> {{ record.startTime }} {{ record.endTime ?? '-' }} </div>
<div>{{ record.startTime }} {{ record.endTime ?? '-' }}</div>
</template> </template>
<template #operation="{ record }"> <template #operation="{ record }">
<MsButton class="!mr-0" @click="toReport(record)"> <a-tooltip :content="t('project.executionHistory.cleared')" :disabled="!record.deleted">
{{ t('apiScenario.executeHistory.execution.operation') }} <MsButton
</MsButton> :disabled="record.deleted || !hasAnyPermission(['PROJECT_TEST_PLAN_REPORT:READ'])"
class="!mr-0"
@click="toReport(record)"
>{{ t('apiScenario.executeHistory.execution.operation') }}
</MsButton>
</a-tooltip>
</template> </template>
</ms-base-table> </ms-base-table>
</div> </div>
@ -37,9 +41,10 @@
import { getPlanDetailExecuteHistory } from '@/api/modules/test-plan/testPlan'; import { getPlanDetailExecuteHistory } from '@/api/modules/test-plan/testPlan';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useOpenNewPage from '@/hooks/useOpenNewPage'; import useOpenNewPage from '@/hooks/useOpenNewPage';
import useAppStore from '@/store/modules/app'; import { hasAnyPermission } from '@/utils/permission';
import type { PlanDetailExecuteHistoryItem } from '@/models/testPlan/testPlan'; import type { PlanDetailExecuteHistoryItem } from '@/models/testPlan/testPlan';
import { LastExecuteResults } from '@/enums/caseEnum';
import { ReportEnum, TriggerModeLabel } from '@/enums/reportEnum'; import { ReportEnum, TriggerModeLabel } from '@/enums/reportEnum';
import { TestPlanRouteEnum } from '@/enums/routeEnum'; import { TestPlanRouteEnum } from '@/enums/routeEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum'; import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
@ -49,7 +54,6 @@
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const appStore = useAppStore();
const { openNewPage } = useOpenNewPage(); const { openNewPage } = useOpenNewPage();
const planId = ref(route.query.id as string); const planId = ref(route.query.id as string);
@ -73,7 +77,7 @@
}, },
{ {
title: 'common.executionResult', title: 'common.executionResult',
dataIndex: 'lastExecResult', dataIndex: 'execStatus',
slotName: 'lastExecResult', slotName: 'lastExecResult',
filterConfig: { filterConfig: {
valueKey: 'key', valueKey: 'key',
@ -121,8 +125,7 @@
function loadExecuteList() { function loadExecuteList() {
setLoadListParams({ setLoadListParams({
projectId: appStore.currentProjectId, testPlanId: planId.value,
id: planId.value,
}); });
loadList(); loadList();
} }

View File

@ -80,6 +80,7 @@ export default {
'testPlan.testPlanIndex.passRateTitleTip': 'Passed use cases/all use cases *100%', 'testPlan.testPlanIndex.passRateTitleTip': 'Passed use cases/all use cases *100%',
'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan', 'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan',
'testPlan.planForm.nameRequired': 'Test plan name cannot be empty', 'testPlan.planForm.nameRequired': 'Test plan name cannot be empty',
'testPlan.planForm.testPlanGroupRequired': 'Plan group cannot be empty',
'testPlan.planForm.planStartAndEndTime': 'Planned start and end time', 'testPlan.planForm.planStartAndEndTime': 'Planned start and end time',
'testPlan.planForm.associateRepeatCase': 'Allow associated duplicate cases', 'testPlan.planForm.associateRepeatCase': 'Allow associated duplicate cases',
'testPlan.planForm.passThreshold': 'Pass threshold', 'testPlan.planForm.passThreshold': 'Pass threshold',
@ -116,6 +117,7 @@ export default {
'testPlan.featureCase.autoNextTip2': 'Close: After submitting the results, it is still in the current state', 'testPlan.featureCase.autoNextTip2': 'Close: After submitting the results, it is still in the current state',
'testPlan.api.testSetRequired': 'The test set cannot be empty', 'testPlan.api.testSetRequired': 'The test set cannot be empty',
'testPlan.executeHistory.executionStartAndEndTime': 'Execution start and end time', 'testPlan.executeHistory.executionStartAndEndTime': 'Execution start and end time',
'testPlan.executeHistory.testPlanHasTimedOut': 'Test plan has timed out',
'testPlan.testPlanGroup.seeArchived': 'Only see archived', 'testPlan.testPlanGroup.seeArchived': 'Only see archived',
'testPlan.testPlanGroup.planNamePlaceholder': 'Please enter the name of the test plan group', 'testPlan.testPlanGroup.planNamePlaceholder': 'Please enter the name of the test plan group',
'testPlan.testPlanGroup.name': 'Group Name', 'testPlan.testPlanGroup.name': 'Group Name',

View File

@ -75,6 +75,7 @@ export default {
'testPlan.testPlanIndex.batchEdit': '批量编辑 (已选 { number } 项数据)', 'testPlan.testPlanIndex.batchEdit': '批量编辑 (已选 { number } 项数据)',
'testPlan.planForm.namePlaceholder': '请输入测试计划名称', 'testPlan.planForm.namePlaceholder': '请输入测试计划名称',
'testPlan.planForm.nameRequired': '测试计划名称不能为空', 'testPlan.planForm.nameRequired': '测试计划名称不能为空',
'testPlan.planForm.testPlanGroupRequired': '计划组不能为空',
'testPlan.planForm.planStartAndEndTime': '计划起止时间', 'testPlan.planForm.planStartAndEndTime': '计划起止时间',
'testPlan.planForm.associateRepeatCase': '允许关联重复用例', 'testPlan.planForm.associateRepeatCase': '允许关联重复用例',
'testPlan.planForm.passThreshold': '通过阀值', 'testPlan.planForm.passThreshold': '通过阀值',
@ -110,6 +111,7 @@ export default {
'testPlan.featureCase.autoNextTip2': '关闭:提交结果后,还在当前', 'testPlan.featureCase.autoNextTip2': '关闭:提交结果后,还在当前',
'testPlan.api.testSetRequired': '测试集不能为空', 'testPlan.api.testSetRequired': '测试集不能为空',
'testPlan.executeHistory.executionStartAndEndTime': '执行起止时间', 'testPlan.executeHistory.executionStartAndEndTime': '执行起止时间',
'testPlan.executeHistory.testPlanHasTimedOut': '测试计划已超时',
'testPlan.testPlanGroup.seeArchived': '只看已归档', 'testPlan.testPlanGroup.seeArchived': '只看已归档',
'testPlan.testPlanGroup.planNamePlaceholder': '请输入测试计划组名称', 'testPlan.testPlanGroup.planNamePlaceholder': '请输入测试计划组名称',
'testPlan.testPlanGroup.name': '计划组名称', 'testPlan.testPlanGroup.name': '计划组名称',