fix(测试计划): 修复测试计划&测试计划组&报告部分优先级较高bug

This commit is contained in:
xinxin.wu 2024-06-19 13:02:29 +08:00 committed by 刘瑞斌
parent 9d6f5bd1b0
commit e62149ae10
18 changed files with 135 additions and 30 deletions

View File

@ -90,6 +90,7 @@
(e: 'getModuleCount', params: TableQueryParams): void;
(e: 'refresh'): void;
(e: 'initModules'): void;
(e: 'update:selectedIds'): void;
}>();
const lastReportStatusListOptions = computed(() => {
@ -268,7 +269,17 @@
loadCaseList();
}
);
const innerSelectedIds = defineModel<string[]>('selectedIds', { required: true });
const selectIds = computed(() => {
return [...propsRes.value.selectedKeys];
});
watch(
() => selectIds.value,
(val) => {
innerSelectedIds.value = val;
}
);
watch(
() => props.activeModule,
(val) => {

View File

@ -70,6 +70,7 @@
(e: 'getModuleCount', params: TableQueryParams): void;
(e: 'refresh'): void;
(e: 'initModules'): void;
(e: 'update:selectedIds'): void;
}>();
const requestMethodsOptions = computed(() => {
@ -215,6 +216,18 @@
}
);
const innerSelectedIds = defineModel<string[]>('selectedIds', { required: true });
const selectIds = computed(() => {
return [...propsRes.value.selectedKeys];
});
watch(
() => selectIds.value,
(val) => {
innerSelectedIds.value = val;
}
);
watch(
() => props.showType,
(val) => {

View File

@ -80,6 +80,7 @@
(e: 'getModuleCount', params: TableQueryParams): void;
(e: 'refresh'): void;
(e: 'initModules'): void;
(e: 'update:selectedIds'): void;
}>();
const reviewResultOptions = computed(() => {
@ -277,6 +278,19 @@
}
);
const innerSelectedIds = defineModel<string[]>('selectedIds', { required: true });
const selectIds = computed(() => {
return [...propsRes.value.selectedKeys];
});
watch(
() => selectIds.value,
(val) => {
innerSelectedIds.value = val;
}
);
watch(
() => props.activeModule,
() => {

View File

@ -184,6 +184,7 @@
<CaseTable
v-if="associationType === CaseLinkEnum.FUNCTIONAL"
ref="functionalTableRef"
v-model:selectedIds="selectedIds"
:association-type="associateType"
:get-page-api-type="getPageApiType"
:active-module="activeFolder"
@ -200,6 +201,7 @@
<ApiTable
v-if="associationType === CaseLinkEnum.API && showType === 'API'"
ref="apiTableRef"
v-model:selectedIds="selectedIds"
:get-page-api-type="getPageApiType"
:extra-table-params="props.extraTableParams"
:association-type="associateType"
@ -217,6 +219,7 @@
<ApiCaseTable
v-if="associationType === CaseLinkEnum.API && showType === 'CASE'"
ref="caseTableRef"
v-model:selectedIds="selectedIds"
:get-page-api-type="getPageApiType"
:extra-table-params="props.extraTableParams"
:association-type="associateType"
@ -234,6 +237,7 @@
<ScenarioCaseTable
v-if="associationType === CaseLinkEnum.SCENARIO"
ref="scenarioTableRef"
v-model:selectedIds="selectedIds"
:association-type="associateType"
:modules-count="modulesCount"
:active-module="activeFolder"
@ -257,7 +261,12 @@
<a-button type="secondary" :disabled="props.confirmLoading" class="mr-[12px]" @click="cancel">
{{ t('common.cancel') }}
</a-button>
<a-button :loading="props.confirmLoading" type="primary" @click="handleConfirm">
<a-button
:loading="props.confirmLoading"
type="primary"
:disabled="!selectedIds.length"
@click="handleConfirm"
>
{{ t('ms.case.associate.associate') }}
</a-button>
</slot>
@ -339,6 +348,7 @@
const associationType = ref<keyof typeof CaseLinkEnum>('FUNCTIONAL');
const activeFolder = ref('all');
const selectedIds = ref<string[]>([]);
const selectedKeys = computed({
get: () => [activeFolder.value],
@ -501,6 +511,16 @@
}
selectPopVisible.value = false;
keyword.value = '';
selectedIds.value = [];
}
);
watch(
() => showType.value,
(val) => {
if (val) {
selectedIds.value = [];
}
}
);

View File

@ -77,6 +77,7 @@
(e: 'getModuleCount', params: TableQueryParams): void;
(e: 'refresh'): void;
(e: 'initModules'): void;
(e: 'update:selectedIds'): void;
}>();
const appStore = useAppStore();
@ -225,6 +226,18 @@
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
const innerSelectedIds = defineModel<string[]>('selectedIds', { required: true });
const selectIds = computed(() => {
return [...propsRes.value.selectedKeys];
});
watch(
() => selectIds.value,
(val) => {
innerSelectedIds.value = val;
}
);
watch(
() => props.currentProject,
() => {

View File

@ -25,7 +25,7 @@
>
<template #tree-slot-title="node">
<a-tooltip :content="`${node.name}`" position="tl">
<div class="one-line-text w-[300px] text-[var(--color-text-1)]">{{ node.name }}</div>
<div class="one-line-text w-[300px]">{{ node.name }}</div>
</a-tooltip>
</template>
</a-tree-select>

View File

@ -41,6 +41,15 @@
{{ characterLimit(record.name) }}
</div>
</template>
<template #integrated="{ record }">
<MsTag theme="light" :type="record.integrated ? 'primary' : undefined">
{{
record.integrated
? t('report.detail.testPlanGroup.testGroupReport')
: t('report.detail.testPlanGroup.testReport')
}}
</MsTag>
</template>
<!-- 通过率 -->
<template #passRateColumn>
@ -101,6 +110,7 @@
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 ExecStatus from '@/views/test-plan/report/component/execStatus.vue';
import ExecutionStatus from '@/views/test-plan/report/component/reportStatus.vue';
@ -181,10 +191,16 @@
sortDirections: ['ascend', 'descend'],
sorter: true,
},
ellipsis: true,
showDrag: false,
columnSelectorDisabled: true,
},
{
title: 'report.type',
slotName: 'integrated',
dataIndex: 'integrated',
width: 150,
showDrag: true,
},
{
title: 'report.plan.name',
slotName: 'planName',
@ -192,7 +208,6 @@
width: 200,
showInTable: true,
showTooltip: true,
ellipsis: true,
showDrag: true,
columnSelectorDisabled: true,
},

View File

@ -9,20 +9,12 @@
<template #priority="{ record }">
<caseLevel :case-level="record.priority" />
</template>
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_EXECUTE_RESULT]="{ filterContent }">
<ExecuteResult :execute-result="filterContent.key" />
<template #[FilterSlotNameEnum.API_TEST_CASE_API_LAST_EXECUTE_STATUS]="{ filterContent }">
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="filterContent.value" />
</template>
<template #lastExecResult="{ record }">
<ExecuteResult v-if="record.executeResult" :execute-result="record.executeResult" />
<span v-else>-</span>
<!-- TOTO 暂时不上 -->
<!-- <MsIcon
v-show="record.lastExecResult !== LastExecuteResults.PENDING"
type="icon-icon_take-action_outlined"
class="ml-[8px] cursor-pointer text-[rgb(var(--primary-5))]"
size="16"
@click="showReport(record)"
/> -->
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="record.executeResult" />
</template>
</MsBaseTable>
<CaseAndScenarioReportDrawer
@ -39,15 +31,16 @@
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
import CaseAndScenarioReportDrawer from '@/views/api-test/components/caseAndScenarioReportDrawer.vue';
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
import { getApiPage, getScenarioPage } from '@/api/modules/test-plan/report';
import { ApiOrScenarioCaseItem } from '@/models/testPlan/report';
import { ReportEnum } from '@/enums/reportEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { casePriorityOptions } from '@/views/api-test/components/config';
import { casePriorityOptions, lastReportStatusListOptions } from '@/views/api-test/components/config';
import { executionResultMap } from '@/views/case-management/caseManagementFeature/components/utils';
const props = defineProps<{
@ -88,10 +81,8 @@
dataIndex: 'executeResult',
slotName: 'lastExecResult',
filterConfig: {
valueKey: 'key',
labelKey: 'statusText',
options: Object.values(executionResultMap),
filterSlotName: FilterSlotNameEnum.CASE_MANAGEMENT_EXECUTE_RESULT,
options: lastReportStatusListOptions.value,
filterSlotName: FilterSlotNameEnum.API_TEST_CASE_API_LAST_EXECUTE_STATUS,
},
width: 150,
showDrag: true,

View File

@ -1,5 +1,5 @@
<template>
<ReportHeader v-if="!props.isDrawer" :detail="detail" :share-id="shareId" />
<ReportHeader v-if="!props.isDrawer" :detail="detail" :share-id="shareId" :is-group="false" />
<div class="analysis-wrapper">
<div class="analysis min-w-[238px]">
<div class="block-title">{{ t('report.detail.api.reportAnalysis') }}</div>

View File

@ -48,6 +48,7 @@
const props = defineProps<{
detail: PlanReportDetail;
shareId?: string;
isGroup?: boolean;
}>();
const appStore = useAppStore();
@ -63,7 +64,9 @@
projectId: appStore.currentProjectId,
});
const { origin } = window.location;
shareLink.value = `${origin}/#/${RouteEnum.SHARE}/${RouteEnum.SHARE_REPORT_TEST_PLAN}${res.shareUrl}`;
shareLink.value = `${origin}/#/${RouteEnum.SHARE}/${RouteEnum.SHARE_REPORT_TEST_PLAN}${res.shareUrl}&type=${
props.isGroup ? 'GROUP' : 'TEST_PLAN'
}`;
if (isSupported) {
copy(shareLink.value);
Message.info(t('bugManagement.detail.shareTip'));

View File

@ -1,5 +1,5 @@
<template>
<ReportHeader v-if="!props.isDrawer" :detail="detail" :share-id="shareId" />
<ReportHeader v-if="!props.isDrawer" :detail="detail" :share-id="shareId" is-group />
<div class="analysis-wrapper">
<div class="analysis min-w-[238px]">
<div class="block-title">{{ t('report.detail.api.reportAnalysis') }}</div>

View File

@ -8,7 +8,7 @@
</div>
</template>
<template #headerRight>
<PlanDetailHeaderRight :share-id="shareId" :detail="detail" />
<PlanDetailHeaderRight :is-group="props.isGroup" :share-id="shareId" :detail="detail" />
</template>
</MsCard>
</template>
@ -25,6 +25,7 @@
detail: PlanReportDetail;
shareId?: string;
isDrawer?: boolean;
isGroup: boolean;
}>();
</script>

View File

@ -1,5 +1,6 @@
<template>
<PlanDetail :detail-info="detail" />
<PlanGroupDetail v-if="isGroup" :detail-info="detail" />
<PlanDetail v-else :detail-info="detail" />
</template>
<script setup lang="ts">
@ -8,6 +9,7 @@
import { cloneDeep } from 'lodash-es';
import PlanDetail from '@/views/test-plan/report/detail/component/planDetail.vue';
import PlanGroupDetail from '@/views/test-plan/report/detail/component/planGroupDetail.vue';
import { getReportDetail, planGetShareHref } from '@/api/modules/test-plan/report';
import { defaultReportDetail } from '@/config/testPlan';
@ -18,7 +20,7 @@
const route = useRoute();
const router = useRouter();
const reportId = ref<string>(route.query.id as string);
const isGroup = computed(() => route.query.type === 'GROUP');
const detail = ref<PlanReportDetail>(cloneDeep(defaultReportDetail));
async function getShareDetail() {

View File

@ -47,4 +47,6 @@ export default {
'report.detail.testPlanGroup.result': '结果',
'report.detail.testPlanGroup.useCasesCount': '用例数',
'report.detail.testPlanGroup.viewReport': '查看报告',
'report.detail.testPlanGroup.testGroupReport': '测试组报告',
'report.detail.testPlanGroup.testReport': '测试报告',
};

View File

@ -122,6 +122,7 @@
theme="outline"
class="ml-2"
:tooltip-disabled="true"
@click="handleScheduledTask(record)"
>{{ t('testPlan.testPlanIndex.timing') }}</MsTag
>
<template #content>
@ -1005,6 +1006,7 @@
name: TestPlanRouteEnum.TEST_PLAN_INDEX_DETAIL,
query: {
id,
type: 'featureCase',
},
});
} else {
@ -1251,6 +1253,9 @@
const planSourceId = ref<string>();
const planType = ref<keyof typeof testPlanTypeEnum>(testPlanTypeEnum.TEST_PLAN);
function handleScheduledTask(record: TestPlanItem) {
if (!hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])) {
return;
}
planType.value = record.type;
planSourceId.value = record.id;
taskForm.value = defaultCountDetailMap.value[record.id]?.scheduleConfig;

View File

@ -4,6 +4,7 @@
class="ms-modal-form ms-modal-small"
title-align="start"
:mask-closable="false"
@close="handleCancel"
>
<template #title>
{{

View File

@ -481,6 +481,9 @@
}
onBeforeMount(() => {
if (route.query.type === 'featureCase') {
activeTab.value = 'featureCase';
}
initDetail();
initPlanTree();
});

View File

@ -36,7 +36,14 @@
},
}"
allow-search
/>
:filter-tree-node="filterTreeNode"
>
<template #tree-slot-title="node">
<a-tooltip :content="`${node.name}`" position="tl">
<div class="one-line-text w-[300px]">{{ node.name }}</div>
</a-tooltip>
</template>
</a-tree-select>
</a-form-item>
<a-form-item field="tags" :label="t('common.tag')">
<MsTagsInput v-model:modelValue="form.tags"></MsTagsInput>
@ -54,7 +61,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { FormInstance, Message } from '@arco-design/web-vue';
import { FormInstance, Message, TreeNodeData } from '@arco-design/web-vue';
import { cloneDeep } from 'lodash-es';
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
@ -160,6 +167,10 @@
}
}
function filterTreeNode(searchValue: string, nodeData: TreeNodeData) {
return (nodeData as ModuleTreeNode).name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
}
const okText = computed(() => {
return props.planGroupId ? t('common.update') : t('common.create');
});