feat(测试计划): 测试计划详情-功能用例-测试点支持脑图

This commit is contained in:
teukkk 2024-09-30 13:12:12 +08:00 committed by Craftsman
parent e357048091
commit 1c0583fe21
8 changed files with 60 additions and 51 deletions

View File

@ -15,6 +15,7 @@ import {
EditReviewUrl, EditReviewUrl,
FollowReviewUrl, FollowReviewUrl,
GetAssociatedIdsUrl, GetAssociatedIdsUrl,
GetCasePlanCollectionMinderUrl,
GetCasePlanMinderUrl, GetCasePlanMinderUrl,
getCaseReviewerListUrl, getCaseReviewerListUrl,
GetCaseReviewHistoryListUrl, GetCaseReviewHistoryListUrl,
@ -219,7 +220,10 @@ export function getCaseReviewMinder(data: CaseReviewMinderParams) {
} }
// 获取测试计划用例脑图 // 获取测试计划用例脑图
export function getCasePlanMinder(data: CasePlanMinderParams) { export function getCasePlanMinder(treeType: 'MODULE' | 'COLLECTION', data: CasePlanMinderParams) {
if (treeType === 'COLLECTION') {
return MSR.post<CommonList<MinderJsonNode>>({ url: `${GetCasePlanCollectionMinderUrl}`, data });
}
return MSR.post<CommonList<MinderJsonNode>>({ url: `${GetCasePlanMinderUrl}`, data }); return MSR.post<CommonList<MinderJsonNode>>({ url: `${GetCasePlanMinderUrl}`, data });
} }

View File

@ -31,3 +31,4 @@ export const getCaseReviewerListUrl = '/case/review/detail/reviewer/list'; //
export const GetCaseReviewMinderUrl = '/functional/mind/case/review/list'; // 获取评审脑图数据 export const GetCaseReviewMinderUrl = '/functional/mind/case/review/list'; // 获取评审脑图数据
export const GetReviewerAndStatusUrl = '/case/review/detail/reviewer/status/total'; // 脑图-获取用例评审最终结果和每个评审人最终的评审结果 export const GetReviewerAndStatusUrl = '/case/review/detail/reviewer/status/total'; // 脑图-获取用例评审最终结果和每个评审人最终的评审结果
export const GetCasePlanMinderUrl = '/functional/mind/case/plan/list'; // 获取测试计划用例脑图 export const GetCasePlanMinderUrl = '/functional/mind/case/plan/list'; // 获取测试计划用例脑图
export const GetCasePlanCollectionMinderUrl = '/functional/mind/case/collection/list'; // 获取测试计划用例脑图-测试点

View File

@ -1,4 +1,4 @@
import type { MinderJsonNode } from '@/components/pure/ms-minder-editor/props'; import type { MinderJsonNode, MinderJsonNodeData } from '@/components/pure/ms-minder-editor/props';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { mapTree } from '@/utils'; import { mapTree } from '@/utils';
@ -18,17 +18,24 @@ export function getMinderOffspringIds(node: MinderJsonNode): string[] {
return offspringIds; return offspringIds;
} }
// 模块或测试点
export function isModuleOrCollection(data?: MinderJsonNodeData) {
return data?.isModuleOrCollection || data?.resource?.includes(t('common.module'));
}
/** /**
* *
* @param node * @param node
*/ */
export function getMinderOperationParams(node: MinderJsonNode): BatchApiParams { export function getMinderOperationParams(node: MinderJsonNode, isCollection = false): BatchApiParams {
if (node.data?.resource?.includes(t('common.module'))) { if (isModuleOrCollection(node.data)) {
return { return {
selectIds: [], selectIds: [],
selectAll: true, selectAll: true,
condition: {}, condition: {},
moduleIds: node.data?.id === 'NONE' ? [] : [node.data?.id, ...getMinderOffspringIds(node)], ...(isCollection
? { collectionId: node.data?.id === 'NONE' ? '' : node.data?.id }
: { moduleIds: (node.data?.id === 'NONE' ? [] : [node.data?.id, ...getMinderOffspringIds(node)]) as string[] }),
}; };
} }
return { return {

View File

@ -64,6 +64,7 @@
<div class="w-[440px] rounded bg-white p-[16px] shadow-[0_0_10px_rgba(0,0,0,0.05)]"> <div class="w-[440px] rounded bg-white p-[16px] shadow-[0_0_10px_rgba(0,0,0,0.05)]">
<ExecuteSubmit <ExecuteSubmit
:select-node="selectNode" :select-node="selectNode"
:tree-type="props.treeType"
:test-plan-id="props.planId" :test-plan-id="props.planId"
is-default-activate is-default-activate
@done="handleExecuteDone" @done="handleExecuteDone"
@ -175,7 +176,8 @@
testPlanCaseId: selectNode?.data?.id, testPlanCaseId: selectNode?.data?.id,
caseId: selectNode?.data?.caseId, caseId: selectNode?.data?.caseId,
testPlanId: props.planId, testPlanId: props.planId,
selectAll: batchMinderParams.minderModuleIds.includes('NONE'), selectAll:
batchMinderParams.minderModuleIds.includes('NONE') || batchMinderParams.minderCollectionIds.includes('NONE'),
...batchMinderParams, ...batchMinderParams,
}" }"
:is-minder-batch="isMinderOperation" :is-minder-batch="isMinderOperation"
@ -225,7 +227,10 @@
setPriorityView, setPriorityView,
} from '@/components/pure/ms-minder-editor/script/tool/utils'; } from '@/components/pure/ms-minder-editor/script/tool/utils';
import { MsFileItem } from '@/components/pure/ms-upload/types'; import { MsFileItem } from '@/components/pure/ms-upload/types';
import { getMinderOperationParams } from '@/components/business/ms-minders/caseReviewMinder/utils'; import {
getMinderOperationParams,
isModuleOrCollection,
} from '@/components/business/ms-minders/caseReviewMinder/utils';
import Attachment from '@/components/business/ms-minders/featureCaseMinder/attachment.vue'; import Attachment from '@/components/business/ms-minders/featureCaseMinder/attachment.vue';
import useMinderBaseApi from '@/components/business/ms-minders/featureCaseMinder/useMinderBaseApi'; import useMinderBaseApi from '@/components/business/ms-minders/featureCaseMinder/useMinderBaseApi';
import BugList from './bugList.vue'; import BugList from './bugList.vue';
@ -276,6 +281,7 @@
moduleTree: ModuleTreeNode[]; moduleTree: ModuleTreeNode[];
planId: string; planId: string;
canEdit: boolean; // canEdit: boolean; //
treeType: 'MODULE' | 'COLLECTION';
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -319,11 +325,13 @@
type: e.type || e.data?.type, type: e.type || e.data?.type,
id: e.id || e.data?.id || '', id: e.id || e.data?.id || '',
text: e.name || e.data?.text.replace(/<\/?p\b[^>]*>/gi, '') || '', text: e.name || e.data?.text.replace(/<\/?p\b[^>]*>/gi, '') || '',
resource: modulesCount.value[e.id] !== undefined ? [moduleTag] : e.data?.resource, resource:
modulesCount.value[e.id] !== undefined && props.treeType === 'MODULE' ? [moduleTag] : e.data?.resource,
expandState: e.level === 0 ? 'expand' : 'collapse', expandState: e.level === 0 ? 'expand' : 'collapse',
count: modulesCount.value[e.id], count: modulesCount.value[e.id],
disabled: true, disabled: true,
projectId: getMinderNodeParentId(e), projectId: props.treeType === 'MODULE' ? getMinderNodeParentId(e) : appStore.currentProjectId,
isModuleOrCollection: true, //
}, },
children: children:
modulesCount.value[e.id] > 0 && !e.children?.length modulesCount.value[e.id] > 0 && !e.children?.length
@ -343,9 +351,10 @@
data: { data: {
id: 'NONE', id: 'NONE',
text: t('testPlan.testPlanIndex.functionalUseCase'), text: t('testPlan.testPlanIndex.functionalUseCase'),
resource: [moduleTag], resource: props.treeType === 'MODULE' ? [moduleTag] : [],
disabled: true, disabled: true,
count: modulesCount.value.all, count: modulesCount.value.all,
isModuleOrCollection: true, //
}, },
}; };
importJson.value.treePath = []; importJson.value.treePath = [];
@ -365,12 +374,9 @@
} }
} }
watch( watch([() => props.activeModule, () => props.treeType], () => {
() => props.activeModule, initCaseTree();
() => { });
initCaseTree();
}
);
function isCaseTag(data?: MinderJsonNodeData) { function isCaseTag(data?: MinderJsonNodeData) {
return data?.caseId?.length; return data?.caseId?.length;
@ -385,9 +391,9 @@
try { try {
loading.value = true; loading.value = true;
if (!node?.data) return; if (!node?.data) return;
const { list, total } = await getCasePlanMinder({ const { list, total } = await getCasePlanMinder(props.treeType, {
current: (loadMoreCurrent ?? 0) + 1, current: (loadMoreCurrent ?? 0) + 1,
moduleId: node.data?.id, ...(props.treeType === 'COLLECTION' ? { collectionId: node.data?.id } : { moduleId: node.data?.id }),
projectId: node.data?.projectId, projectId: node.data?.projectId,
planId: props.planId, planId: props.planId,
}); });
@ -577,6 +583,7 @@
const batchMinderParams = ref({ const batchMinderParams = ref({
minderModuleIds: [] as string[], minderModuleIds: [] as string[],
minderCaseIds: [] as string[], minderCaseIds: [] as string[],
minderCollectionIds: [] as string[],
minderProjectIds: [] as string[], minderProjectIds: [] as string[],
}); });
const isMinderOperation = ref(false); const isMinderOperation = ref(false);
@ -598,7 +605,9 @@
caseId: '', caseId: '',
testPlanId: props.planId, testPlanId: props.planId,
bugIds: params.selectIds, bugIds: params.selectIds,
selectAll: batchMinderParams.value.minderModuleIds.includes('NONE'), selectAll:
batchMinderParams.value.minderModuleIds.includes('NONE') ||
batchMinderParams.value.minderCollectionIds.includes('NONE'),
...batchMinderParams.value, ...batchMinderParams.value,
}); });
} else { } else {
@ -656,7 +665,6 @@
const curSelectNode = window.minder.getSelectedNode(); const curSelectNode = window.minder.getSelectedNode();
const node = isActualResultNode(curSelectNode) ? curSelectNode.parent : curSelectNode; const node = isActualResultNode(curSelectNode) ? curSelectNode.parent : curSelectNode;
executeVisible.value = false; executeVisible.value = false;
const resource = node.data?.resource;
if (isCaseTag(node.data)) { if (isCaseTag(node.data)) {
// //
node.setData('resource', [executionResultMap[status].statusText]).render(); node.setData('resource', [executionResultMap[status].statusText]).render();
@ -666,7 +674,7 @@
if (extraVisible.value && activeExtraKey.value === 'history') { if (extraVisible.value && activeExtraKey.value === 'history') {
initExecuteHistory(node.data); initExecuteHistory(node.data);
} }
} else if (resource?.includes(moduleTag)) { } else if (isModuleOrCollection(node.data)) {
// //
for (let i = node.children.length - 1; i >= 0; i--) { for (let i = node.children.length - 1; i >= 0; i--) {
window.minder.removeNode(node.children[i]); window.minder.removeNode(node.children[i]);
@ -686,7 +694,7 @@
testPlanId: props.planId, testPlanId: props.planId,
lastExecResult: status, lastExecResult: status,
content: '', content: '',
...getMinderOperationParams(selectedNodes), ...getMinderOperationParams(selectedNodes, props.treeType === 'COLLECTION'),
} as BatchExecuteFeatureCaseParams); } as BatchExecuteFeatureCaseParams);
// //
handleExecuteDone(status, ''); handleExecuteDone(status, '');
@ -860,6 +868,7 @@
function setBatchMinderParams() { function setBatchMinderParams() {
batchMinderParams.value = { batchMinderParams.value = {
minderCollectionIds: [],
minderModuleIds: [], minderModuleIds: [],
minderCaseIds: [], minderCaseIds: [],
minderProjectIds: [], minderProjectIds: [],
@ -870,8 +879,12 @@
batchMinderParams.value.minderCaseIds.push(node.data?.id || ''); batchMinderParams.value.minderCaseIds.push(node.data?.id || '');
} else if (node.data?.type === 'PROJECT') { } else if (node.data?.type === 'PROJECT') {
batchMinderParams.value.minderProjectIds.push(node.data?.id || ''); batchMinderParams.value.minderProjectIds.push(node.data?.id || '');
} else if (node.data?.resource?.includes(moduleTag)) { } else if (isModuleOrCollection(node.data)) {
batchMinderParams.value.minderModuleIds.push(node.data?.id || ''); if (props.treeType === 'COLLECTION') {
batchMinderParams.value.minderCollectionIds.push(node.data?.id || '');
} else {
batchMinderParams.value.minderModuleIds.push(node.data?.id || '');
}
} }
}); });
} }
@ -879,14 +892,14 @@
// //
async function handleNodeSelect(node: MinderJsonNode) { async function handleNodeSelect(node: MinderJsonNode) {
const { data } = node; const { data } = node;
if (node.data?.resource?.includes(moduleTag)) { if (isModuleOrCollection(node.data)) {
isMinderOperation.value = true; // / isMinderOperation.value = true; // /
setBatchMinderParams(); setBatchMinderParams();
} else { } else {
isMinderOperation.value = false; isMinderOperation.value = false;
} }
// //
if (data?.type === 'tmp' && node.parent?.data?.resource?.includes(moduleTag)) { if (data?.type === 'tmp' && node.parent && isModuleOrCollection(node.parent?.data)) {
canShowFloatMenu.value = false; canShowFloatMenu.value = false;
await initNodeCases(node.parent, data.current); await initNodeCases(node.parent, data.current);
setPriorityView(true, 'P'); setPriorityView(true, 'P');
@ -897,7 +910,7 @@
// : // :
if ( if (
isCaseTag(node?.data) || isCaseTag(node?.data) ||
(node.data?.resource?.includes(moduleTag) && (isModuleOrCollection(node.data) &&
(node.children || []).length > 0 && (node.children || []).length > 0 &&
!(!hasOperationPermission.value && node.type === 'root')) !(!hasOperationPermission.value && node.type === 'root'))
) { ) {
@ -931,7 +944,7 @@
} }
// : // :
if (data?.resource?.includes(moduleTag) && (node.children || []).length > 0 && node.type !== 'root') { if (isModuleOrCollection(data) && (node.children || []).length > 0 && node.type !== 'root') {
canShowEnterNode.value = true; canShowEnterNode.value = true;
} else { } else {
canShowEnterNode.value = false; canShowEnterNode.value = false;
@ -948,7 +961,7 @@
// //
expendNodeAndChildren(node); expendNodeAndChildren(node);
node.layout(); node.layout();
} else if (data?.resource?.includes(moduleTag)) { } else if (data && isModuleOrCollection(data)) {
// //
if (data.id !== 'NONE' && data.count > 0 && data.isLoaded !== true) { if (data.id !== 'NONE' && data.count > 0 && data.isLoaded !== true) {
await initNodeCases(node); await initNodeCases(node);

View File

@ -277,7 +277,8 @@ export interface CaseReviewMinderParams {
// 测试计划用例脑图 // 测试计划用例脑图
export interface CasePlanMinderParams { export interface CasePlanMinderParams {
projectId: string; projectId: string;
moduleId: string; moduleId?: string;
collectionId?: string;
current?: number; current?: number;
planId: string; planId: string;
} }

View File

@ -126,6 +126,7 @@
ref="msTestPlanFeatureCaseMinderRef" ref="msTestPlanFeatureCaseMinderRef"
:active-module="props.activeModule" :active-module="props.activeModule"
:module-tree="moduleTree" :module-tree="moduleTree"
:tree-type="props.treeType"
:plan-id="props.planId" :plan-id="props.planId"
:can-edit="props.canEdit" :can-edit="props.canEdit"
@operation="handleMinderOperation" @operation="handleMinderOperation"
@ -271,7 +272,6 @@
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'refresh'): void; (e: 'refresh'): void;
(e: 'setTreeTypeToModule'): void; // TODO lmy v3.4
(e: 'selectParentNode', tree: ModuleTreeNode[]): void; (e: 'selectParentNode', tree: ModuleTreeNode[]): void;
}>(); }>();
@ -567,16 +567,6 @@
} }
); );
// TODO lmy v3.4
watch(
() => props.treeType,
(val) => {
if (val === 'COLLECTION') {
showType.value = 'list';
}
}
);
async function loadCaseList(refreshTreeCount = true) { async function loadCaseList(refreshTreeCount = true) {
const tableParams = await getTableParams(false); const tableParams = await getTableParams(false);
setLoadListParams({ setLoadListParams({
@ -655,10 +645,6 @@
function handleShowTypeChange(val: string | number | boolean) { function handleShowTypeChange(val: string | number | boolean) {
if (val === 'minder') { if (val === 'minder') {
if (props.treeType === 'COLLECTION') {
emit('setTreeTypeToModule'); // TODO lmy v3.4
return;
}
getModuleCount(); // getModuleCount(); //
} else { } else {
loadCaseList(); loadCaseList();
@ -925,7 +911,7 @@
function handleMinderOperation(type: string, node: MinderJsonNode) { function handleMinderOperation(type: string, node: MinderJsonNode) {
minderSelectData.value = node.data; minderSelectData.value = node.data;
batchUpdateParams.value = { batchUpdateParams.value = {
...getMinderOperationParams(node), ...getMinderOperationParams(node, props.treeType === 'COLLECTION'),
testPlanId: props.planId, testPlanId: props.planId,
projectId: node.data?.id !== 'NONE' ? node.data?.projectId : '', projectId: node.data?.id !== 'NONE' ? node.data?.projectId : '',
}; };

View File

@ -59,6 +59,7 @@
selectNode?: MinderJsonNode; selectNode?: MinderJsonNode;
stepExecutionResult?: StepExecutionResult[]; stepExecutionResult?: StepExecutionResult[];
isDefaultActivate?: boolean; // isDefaultActivate?: boolean; //
treeType?: 'MODULE' | 'COLLECTION';
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -132,7 +133,7 @@
if (props.selectNode) { if (props.selectNode) {
await batchExecuteCase({ await batchExecuteCase({
...params, ...params,
...getMinderOperationParams(props.selectNode), ...getMinderOperationParams(props.selectNode, props.treeType === 'COLLECTION'),
} as BatchExecuteFeatureCaseParams); } as BatchExecuteFeatureCaseParams);
} else { } else {
await runFeatureCase({ await runFeatureCase({

View File

@ -28,7 +28,6 @@
:can-edit="props.canEdit" :can-edit="props.canEdit"
@select-parent-node="selectParentNode" @select-parent-node="selectParentNode"
@refresh="emit('refresh')" @refresh="emit('refresh')"
@set-tree-type-to-module="setTreeTypeToModule"
></CaseTable> ></CaseTable>
</template> </template>
</MsSplitBox> </MsSplitBox>
@ -86,9 +85,6 @@
} }
const treeType = ref<'MODULE' | 'COLLECTION'>('COLLECTION'); const treeType = ref<'MODULE' | 'COLLECTION'>('COLLECTION');
function setTreeTypeToModule() {
treeType.value = 'MODULE'; // TODO lmy v3.4
}
function getCaseTableList() { function getCaseTableList() {
nextTick(async () => { nextTick(async () => {
await caseTreeRef.value?.initModules(); await caseTreeRef.value?.initModules();