feat(测试计划): 测试计划脑图批量关联缺陷

This commit is contained in:
baiqi 2024-09-04 14:01:29 +08:00 committed by Craftsman
parent 32b27a95d7
commit 63c7dfdaf6
8 changed files with 159 additions and 44 deletions

View File

@ -11,9 +11,11 @@ import {
AssociatedBugToScenarioCaseUrl,
BatchAddBugToApiCaseUrl,
BatchAddBugToFunctionalCaseUrl,
BatchAddBugToMinderCaseUrl,
BatchAddBugToScenarioCaseUrl,
batchArchivedPlanUrl,
BatchAssociatedBugToCaseUrl,
BatchAssociatedBugToMinderCaseUrl,
batchCopyPlanUrl,
batchDeletePlanUrl,
BatchDisassociateApiCaseUrl,
@ -504,3 +506,11 @@ export function batchLinkBugToApiCase(data: TableQueryParams) {
export function batchLinkBugToScenarioCase(data: TableQueryParams) {
return MSR.post({ url: BatchLinkBugToScenarioCaseUrl, data });
}
// 测试计划-详情-脑图批量关联缺陷
export function batchAssociatedBugToMinderCase(data: TableQueryParams) {
return MSR.post({ url: BatchAssociatedBugToMinderCaseUrl, data });
}
// 测试计划-详情-脑图批量新建缺陷
export function batchAddBugToMinderCase(data: { request: BugEditFormObject; fileList: File[] }) {
return MSR.uploadFile({ url: BatchAddBugToMinderCaseUrl }, data, '', true);
}

View File

@ -181,3 +181,8 @@ export const BatchAddBugToScenarioCaseUrl = '/test-plan/api/scenario/batch/add-b
export const BatchLinkBugToApiCaseUrl = '/test-plan/api/case/batch/associate-bug';
// 测试计划-详情-场景用例列表-批量关联缺陷
export const BatchLinkBugToScenarioCaseUrl = '/test-plan/api/scenario/batch/associate-bug';
export const BatchAddBugToCaseUrl = '/test-plan/functional/case/batch/add-bug';
// 测试计划-详情-用例列表-脑图批量关联缺陷
export const BatchAssociatedBugToMinderCaseUrl = '/test-plan/functional/case/minder/batch/associate-bug';
// 测试计划-详情-用例列表-脑图批量新建缺陷
export const BatchAddBugToMinderCaseUrl = '/test-plan/functional/case/minder/batch/add-bug';

View File

@ -14,24 +14,24 @@
:can-show-more-menu-node-operation="false"
:more-menu-other-operation-list="canShowFloatMenu && hasOperationPermission ? moreMenuOtherOperationList : []"
disabled
@node-batch-select="handleNodeBatchSelect"
@node-select="handleNodeSelect"
@node-unselect="handleNodeUnselect"
>
<template #extractMenu>
<!-- 缺陷 -->
<a-dropdown trigger="hover" position="bl">
<a-tooltip
<MsButton
v-if="
props.canEdit &&
showAssociateBugMenu &&
hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])
"
:content="t('common.add')"
type="icon"
class="ms-minder-node-float-menu-icon-button"
>
<MsButton type="icon" class="ms-minder-node-float-menu-icon-button">
<MsIcon type="icon-icon_bug" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
<MsIcon type="icon-icon_bug" class="text-[var(--color-text-4)]" />
</MsButton>
<template #content>
<a-doption v-permission="['PROJECT_BUG:READ+ADD']" value="new" @click="showAddDefectDrawer = true">
{{ t('testPlan.featureCase.noBugDataNewBug') }}
@ -49,20 +49,16 @@
:click-outside-to-close="false"
popup-container="body"
>
<a-tooltip
<MsButton
v-if="props.canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
:content="t('common.execute')"
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${executeVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
>
<MsButton
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${executeVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
>
<MsIcon type="icon-icon_play-round_filled" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
<MsIcon type="icon-icon_play-round_filled" class="text-[var(--color-text-4)]" />
</MsButton>
<template #content>
<div class="w-[440px] rounded bg-white p-[16px] shadow-[0_0_10px_rgba(0,0,0,0.05)]">
<ExecuteSubmit
@ -75,20 +71,18 @@
</template>
</a-trigger>
<!-- 查看详情 -->
<a-tooltip v-if="canShowDetail" :content="t('common.detail')">
<MsButton
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${extraVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
@click="toggleDetail"
>
<MsIcon type="icon-icon_describe_outlined" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
<MsButton
v-if="canShowDetail"
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${extraVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
@click="toggleDetail"
>
<MsIcon type="icon-icon_describe_outlined" class="text-[var(--color-text-4)]" />
</MsButton>
</template>
<template #extractTabContent>
<MsDescription
v-if="activeExtraKey === 'baseInfo'"
@ -121,8 +115,37 @@
show-step-detail-trigger
/>
</template>
<template #batchMenu>
<a-dropdown trigger="hover" position="bl">
<MsButton
v-if="props.canEdit && hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])"
type="icon"
class="ms-minder-node-float-menu-icon-button"
>
<MsIcon type="icon-icon_bug" class="text-[var(--color-text-4)]" />
</MsButton>
<template #content>
<a-doption v-permission="['PROJECT_BUG:READ+ADD']" value="new" @click="showBatchAddDefect">
{{ t('testPlan.featureCase.noBugDataNewBug') }}
</a-doption>
<a-doption v-permission="['PROJECT_BUG:READ']" value="link" @click="showBatchLinkDefect">
{{ t('caseManagement.featureCase.linkDefect') }}
</a-doption>
</template>
</a-dropdown>
</template>
</MsMinderEditor>
<LinkDefectDrawer
v-if="isMinderOperation"
v-model:visible="showLinkDefectDrawer"
:case-id="selectNode?.data?.caseId ?? ''"
:drawer-loading="linkDrawerLoading"
:load-api="AssociatedBugApiTypeEnum.BUG_TOTAL_LIST"
:show-selector-all="false"
@save="associateSuccessHandler"
/>
<LinkDefectDrawer
v-else
v-model:visible="showLinkDefectDrawer"
:case-id="selectNode?.data?.caseId ?? ''"
:drawer-loading="linkDrawerLoading"
@ -137,7 +160,9 @@
testPlanCaseId: selectNode?.data?.id,
caseId: selectNode?.data?.caseId,
testPlanId: props.planId,
...batchMinderParams,
}"
:is-minder-batch="isMinderOperation"
@success="handleAddBugDone"
/>
<a-modal
@ -198,6 +223,7 @@
import { getCasePlanMinder } from '@/api/modules/case-management/caseReview';
import {
associateBugToPlan,
batchAssociatedBugToMinderCase,
batchExecuteCase,
executeHistory,
getCaseDetail,
@ -274,6 +300,7 @@
...e,
data: {
...e.data,
type: e.type || e.data?.type,
id: e.id || e.data?.id || '',
text: e.name || e.data?.text || '',
resource: modulesCount.value[e.id] !== undefined ? [moduleTag] : e.data?.resource,
@ -526,21 +553,41 @@
const showAddDefectDrawer = ref(false);
const linkDrawerLoading = ref(false);
const bugListRef = ref<InstanceType<typeof BugList>>();
const batchMinderParams = ref({
minderModuleIds: [] as string[],
minderCaseIds: [] as string[],
minderProjectIds: [] as string[],
});
const isMinderOperation = ref(false);
function handleAddBugDone() {
if (extraVisible.value && activeExtraKey.value === 'bug') {
bugListRef.value?.loadBugList();
}
emit('refreshPlan');
}
async function associateSuccessHandler(params: TableQueryParams) {
try {
linkDrawerLoading.value = true;
await associateBugToPlan({
...params,
testPlanCaseId: selectNode.value.data?.id,
caseId: selectNode.value.data?.caseId,
testPlanId: props.planId,
});
if (isMinderOperation.value) {
await batchAssociatedBugToMinderCase({
...params,
testPlanCaseId: '',
caseId: '',
testPlanId: props.planId,
bugIds: params.selectIds,
selectAll: batchMinderParams.value.minderModuleIds.includes('NONE'),
...batchMinderParams.value,
});
} else {
await associateBugToPlan({
...params,
testPlanCaseId: selectNode.value.data?.id,
caseId: selectNode.value.data?.caseId,
testPlanId: props.planId,
});
}
Message.success(t('caseManagement.featureCase.associatedSuccess'));
linkDrawerLoading.value = false;
handleAddBugDone();
@ -574,9 +621,11 @@
handleRenderNode(node, [actualResultNode]);
}
}
function isActualResultNode(node: MinderJsonNode) {
return node.data?.resource?.includes(actualResultTag) && node.parent?.data?.resource?.includes(caseTag);
}
// //
function handleExecuteDone(status: LastExecuteResults, content: string) {
const curSelectNode = window.minder.getSelectedNode();
@ -602,6 +651,7 @@
}
emit('refreshPlan');
}
async function handleShortCutExecute(status: LastExecuteResults) {
const selectedNodes: MinderJsonNode = window.minder.getSelectedNode();
if (!selectedNodes?.data?.resource?.includes(caseTag)) return;
@ -783,9 +833,33 @@
return null;
}
function setBatchMinderParams() {
batchMinderParams.value = {
minderModuleIds: [],
minderCaseIds: [],
minderProjectIds: [],
};
const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes();
selectedNodes.forEach((node) => {
if (node.data?.resource?.includes(caseTag)) {
batchMinderParams.value.minderCaseIds.push(node.data?.id || '');
} else if (node.data?.type === 'PROJECT') {
batchMinderParams.value.minderProjectIds.push(node.data?.id || '');
} else if (node.data?.resource?.includes(moduleTag)) {
batchMinderParams.value.minderModuleIds.push(node.data?.id || '');
}
});
}
//
async function handleNodeSelect(node: MinderJsonNode) {
const { data } = node;
if (node.data?.resource?.includes(moduleTag)) {
isMinderOperation.value = true; // /
setBatchMinderParams();
} else {
isMinderOperation.value = false;
}
//
if (data?.type === 'tmp' && node.parent?.data?.resource?.includes(moduleTag)) {
canShowFloatMenu.value = false;
@ -849,14 +923,14 @@
//
expendNodeAndChildren(node);
node.layout();
} else if (data?.resource?.includes(moduleTag) && data.count > 0 && data.isLoaded !== true) {
} else if (data?.resource?.includes(moduleTag)) {
//
if (data.id !== 'NONE') {
if (data.id !== 'NONE' && data.count > 0 && data.isLoaded !== true) {
await initNodeCases(node);
}
extraVisible.value = false;
canShowDetail.value = false;
showAssociateBugMenu.value = false;
showAssociateBugMenu.value = true;
} else {
extraVisible.value = false;
canShowDetail.value = false;
@ -867,8 +941,23 @@
setPriorityView(true, 'P');
}
function handleNodeBatchSelect() {
isMinderOperation.value = true;
}
function showBatchAddDefect() {
showAddDefectDrawer.value = true;
setBatchMinderParams();
}
function showBatchLinkDefect() {
showLinkDefectDrawer.value = true;
setBatchMinderParams();
}
function handleNodeUnselect() {
extraVisible.value = false;
isMinderOperation.value = false;
}
const { unbindShortcuts } = useShortCut(

View File

@ -30,7 +30,11 @@
</template>
</nodeFloatMenu>
<nodeDropdown v-if="props.canShowDropdown" :dropdown-list="props.dropdownList" :checked-val="props.checkedVal" />
<batchMenu v-bind="props" />
<batchMenu v-bind="props">
<template #batchMenu>
<slot name="batchMenu"></slot>
</template>
</batchMenu>
</div>
</template>

View File

@ -52,7 +52,7 @@
class="ms-minder-dropdown"
:popup-translate="[0, -4]"
position="tl"
trigger="click"
trigger="hover"
@select="(val) => handleMinderMenuSelect(val)"
>
<a-tooltip :content="t('common.more')">

View File

@ -11,6 +11,9 @@
<template #extractMenu>
<slot name="extractMenu"></slot>
</template>
<template #batchMenu>
<slot name="batchMenu"></slot>
</template>
</mainEditor>
</div>
<div class="ms-minder-editor-extra" :class="[extraVisible ? 'ms-minder-editor-extra--visible' : '']">

View File

@ -54,6 +54,7 @@
import {
batchAddBugToApiCase,
batchAddBugToFunctionCase,
batchAddBugToMinderCase,
batchAddBugToScenarioCase,
} from '@/api/modules/test-plan/testPlan';
import { useI18n } from '@/hooks/useI18n';
@ -80,6 +81,7 @@
detailId: string; // id idid
name: string; //
};
isMinderBatch?: boolean;
}>();
const emit = defineEmits<{
@ -139,6 +141,8 @@
props.extraParams && typeof props.extraParams === 'function' ? await props.extraParams() : props.extraParams;
if (props.isBatch && props.caseType) {
await batchAddApiMap[props.caseType]({ request: { ...request, ...extraParam }, fileList });
} else if (props.isMinderBatch) {
await batchAddBugToMinderCase({ request: { ...request, ...props.extraParams }, fileList });
} else {
await createOrUpdateBug({ request: { ...request, ...extraParam }, fileList });
}

View File

@ -230,7 +230,7 @@
keyword: keyword.value,
searchMode: 'AND',
combine: {},
caseId: props.caseId,
caseId: props.caseId || '',
condition: { keyword: keyword.value },
};
showDrawer.value = false;
@ -245,7 +245,7 @@
currentCaseTable.value.setLoadListParams({
keyword: keyword.value,
projectId: currentProjectId.value,
sourceId: props.caseId,
sourceId: props.caseId || '',
});
currentCaseTable.value.loadList();
}