feat(测试计划): 测试计划关联用例_修复完善问题
This commit is contained in:
parent
0e57208f00
commit
2167939d26
|
@ -68,6 +68,7 @@ import {
|
|||
TestPlanAndGroupCopyUrl,
|
||||
TestPlanApiAssociatedPageUrl,
|
||||
TestPlanAssociateBugUrl,
|
||||
TestPlanAssociationUrl,
|
||||
TestPlanCancelBugUrl,
|
||||
TestPlanCaseAssociatedPageUrl,
|
||||
TestPlanCaseDetailUrl,
|
||||
|
@ -85,7 +86,6 @@ import type { CommonList, MoveModules, TableQueryParams } from '@/models/common'
|
|||
import { DragSortParams, ModuleTreeNode } from '@/models/common';
|
||||
import type {
|
||||
AddTestPlanParams,
|
||||
AssociateCaseRequestType,
|
||||
BatchApiCaseParams,
|
||||
BatchExecuteFeatureCaseParams,
|
||||
BatchExecutePlan,
|
||||
|
@ -429,3 +429,7 @@ export function getPlanMinder(testPlanId: string) {
|
|||
export function editPlanMinder(data: PlanMinderEditParams) {
|
||||
return MSR.post({ url: EditPlanMinderUrl, data });
|
||||
}
|
||||
// 测试计划关联模块count
|
||||
export function testPlanAssociateModuleCount(data: TableQueryParams) {
|
||||
return MSR.post({ url: TestPlanAssociationUrl, data });
|
||||
}
|
||||
|
|
|
@ -151,3 +151,5 @@ export const ApiScenarioReportDetailStepUrl = '/test-plan/api/scenario/report/ge
|
|||
export const GetPlanMinderUrl = '/test-plan/mind/data';
|
||||
// 修改测试规划脑图
|
||||
export const EditPlanMinderUrl = '/test-plan/mind/data/edit';
|
||||
// 获取测试计划-关联用例-接口模块数量
|
||||
export const TestPlanAssociationUrl = '/test-plan/association/api/case/module/count';
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
extraTableParams?: TableQueryParams; // 查询表格的额外参数
|
||||
protocols: string[];
|
||||
moduleTree: MsTreeNodeData[];
|
||||
modulesCount: Record<string, any>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -346,16 +347,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleTree } = useModuleSelection(
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleInfo } = useModuleSelection(
|
||||
innerSelectedModulesMaps.value,
|
||||
propsRes.value,
|
||||
props.moduleTree
|
||||
propsRes.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.moduleTree,
|
||||
[() => props.moduleTree, () => props.modulesCount],
|
||||
(val) => {
|
||||
setModuleTree(val);
|
||||
setModuleInfo(val);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
extraTableParams?: TableQueryParams; // 查询表格的额外参数
|
||||
protocols: string[];
|
||||
moduleTree: MsTreeNodeData[];
|
||||
modulesCount: Record<string, any>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -311,16 +312,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleTree } = useModuleSelection(
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleInfo } = useModuleSelection(
|
||||
innerSelectedModulesMaps.value,
|
||||
propsRes.value,
|
||||
props.moduleTree
|
||||
propsRes.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.moduleTree,
|
||||
[() => props.moduleTree, () => props.modulesCount],
|
||||
(val) => {
|
||||
setModuleTree(val);
|
||||
setModuleInfo(val);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
activeSourceType: keyof typeof CaseLinkEnum;
|
||||
keyword: string;
|
||||
moduleTree: MsTreeNodeData[];
|
||||
modulesCount: Record<string, any>;
|
||||
getPageApiType: keyof typeof CasePageApiTypeEnum; // 获取未关联分页Api
|
||||
extraTableParams?: TableQueryParams; // 查询表格的额外参数
|
||||
}>();
|
||||
|
@ -316,16 +317,15 @@
|
|||
return [...propsRes.value.selectedKeys];
|
||||
});
|
||||
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleTree } = useModuleSelection(
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleInfo } = useModuleSelection(
|
||||
innerSelectedModulesMaps.value,
|
||||
propsRes.value,
|
||||
props.moduleTree
|
||||
propsRes.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.moduleTree,
|
||||
[() => props.moduleTree, () => props.modulesCount],
|
||||
(val) => {
|
||||
setModuleTree(val);
|
||||
setModuleInfo(val);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
:extra-table-params="props.extraTableParams"
|
||||
:keyword="keyword"
|
||||
:module-tree="moduleTree"
|
||||
:modules-count="modulesCount"
|
||||
@get-module-count="initModulesCount"
|
||||
@refresh="loadCaseList"
|
||||
>
|
||||
|
@ -215,6 +216,7 @@
|
|||
:show-type="showType"
|
||||
:protocols="selectedProtocols"
|
||||
:module-tree="moduleTree"
|
||||
:modules-count="modulesCount"
|
||||
@get-module-count="initModulesCount"
|
||||
>
|
||||
<TotalCount :total-count="totalCount" />
|
||||
|
@ -237,6 +239,7 @@
|
|||
:show-type="showType"
|
||||
:protocols="selectedProtocols"
|
||||
:module-tree="moduleTree"
|
||||
:modules-count="modulesCount"
|
||||
@get-module-count="initModulesCount"
|
||||
>
|
||||
<TotalCount :total-count="totalCount" />
|
||||
|
@ -496,6 +499,7 @@
|
|||
const isCheckedAll = ref<boolean>(false);
|
||||
const indeterminate = ref<boolean>(false);
|
||||
|
||||
// TODO 需优化、手动触发计算、或者每次增量更新
|
||||
const totalCount = computed(() => {
|
||||
return Object.keys(selectedModulesMaps.value).reduce((total, key) => {
|
||||
const module = selectedModulesMaps.value[key];
|
||||
|
@ -518,6 +522,13 @@
|
|||
const apiCaseCollectionId = ref<string>('');
|
||||
const apiScenarioCollectionId = ref<string>('');
|
||||
|
||||
// 切换项目的时候清空
|
||||
function clearSelector() {
|
||||
Object.keys(selectedModulesMaps.value).forEach((key) => {
|
||||
delete selectedModulesMaps.value[key];
|
||||
});
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleConfirm() {
|
||||
const params = {
|
||||
|
@ -545,6 +556,7 @@
|
|||
keyword.value = '';
|
||||
activeFolder.value = 'all';
|
||||
activeFolderName.value = t('ms.case.associate.allCase');
|
||||
clearSelector();
|
||||
emit('close');
|
||||
}
|
||||
|
||||
|
@ -669,15 +681,6 @@
|
|||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => showType.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
selectedIds.value = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 选中当前节点 && 取消当前节点
|
||||
function selectParent(nodeData: MsTreeNodeData, isSelected: boolean) {
|
||||
selectedModulesMaps.value[nodeData.id] = {
|
||||
|
@ -721,7 +724,7 @@
|
|||
}
|
||||
|
||||
Object.entries(val).forEach(([moduleId, selectedProps]) => {
|
||||
const { selectAll: selectIdsAll, selectIds, count } = selectedProps;
|
||||
const { selectAll: selectIdsAll, selectIds, count, excludeIds } = selectedProps;
|
||||
if (selectedProps) {
|
||||
// 全选和取消全选
|
||||
if (selectIdsAll) {
|
||||
|
@ -731,7 +734,7 @@
|
|||
}
|
||||
|
||||
// 半选状态
|
||||
if (selectIds.size > 0 && selectIds.size < count) {
|
||||
if (excludeIds.size || (selectIds.size > 0 && selectIds.size < count)) {
|
||||
halfCheckedKeysSet.add(moduleId);
|
||||
} else {
|
||||
halfCheckedKeysSet.delete(moduleId);
|
||||
|
@ -753,7 +756,9 @@
|
|||
isCheckedAll.value = false;
|
||||
}
|
||||
|
||||
if (totalCount.value < isAllCheckedModuleProps.count) {
|
||||
if (totalCount.value === 0) {
|
||||
indeterminate.value = false;
|
||||
} else if (totalCount.value < isAllCheckedModuleProps.count) {
|
||||
indeterminate.value = true;
|
||||
} else {
|
||||
indeterminate.value = false;
|
||||
|
@ -781,24 +786,26 @@
|
|||
excludeIds: new Set(),
|
||||
count: modulesCount.value.all,
|
||||
};
|
||||
|
||||
setSelectAll(moduleTree.value, isCheckedAll.value);
|
||||
}
|
||||
|
||||
// 切换项目的时候清空
|
||||
function clearSelector() {
|
||||
Object.keys(selectedModulesMaps.value).forEach((key) => {
|
||||
delete selectedModulesMaps.value[key];
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => innerProject.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
clearSelector();
|
||||
}
|
||||
const lastProps = selectedModulesMaps.value.all;
|
||||
if (lastProps.selectAll) {
|
||||
selectedModulesMaps.value.all.selectAll = true;
|
||||
selectedModulesMaps.value.all.selectIds = new Set([]);
|
||||
selectedModulesMaps.value.all.excludeIds = new Set([]);
|
||||
} else {
|
||||
selectedModulesMaps.value.all.selectAll = false;
|
||||
selectedModulesMaps.value.all.selectIds = new Set([]);
|
||||
selectedModulesMaps.value.all.excludeIds = new Set([]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
watch([() => innerProject.value, () => showType.value, () => props.associatedType], (val) => {
|
||||
if (val) {
|
||||
clearSelector();
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modulesMaps,
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
getPageApiType: keyof typeof CasePageApiTypeEnum; // 获取未关联分页Api
|
||||
extraTableParams?: TableQueryParams; // 查询表格的额外参数
|
||||
moduleTree: MsTreeNodeData[];
|
||||
modulesCount: Record<string, any>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -282,16 +283,15 @@
|
|||
};
|
||||
}
|
||||
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleTree } = useModuleSelection(
|
||||
const { rowSelectChange, selectAllChange, clearSelector, setModuleInfo } = useModuleSelection(
|
||||
innerSelectedModulesMaps.value,
|
||||
propsRes.value,
|
||||
props.moduleTree
|
||||
propsRes.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.moduleTree,
|
||||
[() => props.moduleTree, () => props.modulesCount],
|
||||
(val) => {
|
||||
setModuleTree(val);
|
||||
setModuleInfo(val);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
|
@ -11,12 +11,12 @@ import type { moduleKeysType } from './types';
|
|||
|
||||
export default function useModuleSelections<T>(
|
||||
innerSelectedModulesMaps: Record<string, moduleKeysType>,
|
||||
propsRes: MsTableProps<T>,
|
||||
modulesTree: MsTreeNodeData[]
|
||||
propsRes: MsTableProps<T>
|
||||
) {
|
||||
const moduleSelectedMap = ref<Record<string, string[]>>({});
|
||||
|
||||
const moduleTree = ref<MsTreeNodeData[]>(modulesTree);
|
||||
const moduleTree = ref<MsTreeNodeData[]>([]);
|
||||
const allModuleTotal = ref<Record<string, any>>({});
|
||||
|
||||
// 初始化表格数据的选择
|
||||
function initTableDataSelected() {
|
||||
|
@ -63,12 +63,12 @@ export default function useModuleSelections<T>(
|
|||
function setSelectedAll(moduleId: string) {
|
||||
resetModule(moduleId, true);
|
||||
const selectedProp = innerSelectedModulesMaps[moduleId];
|
||||
if (selectedProp) {
|
||||
if (selectedProp.selectAll && !selectedProp.selectIds.size && !selectedProp.excludeIds.size) {
|
||||
moduleSelectedMap.value[moduleId].forEach((key) => {
|
||||
propsRes.selectedKeys.add(key);
|
||||
});
|
||||
}
|
||||
const isFirstSelectedAll =
|
||||
selectedProp && selectedProp.selectAll && !selectedProp.selectIds.size && !selectedProp.excludeIds.size;
|
||||
if (isFirstSelectedAll) {
|
||||
moduleSelectedMap.value[moduleId].forEach((key) => {
|
||||
propsRes.selectedKeys.add(key);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ export default function useModuleSelections<T>(
|
|||
selectAll: false,
|
||||
selectIds: new Set(),
|
||||
excludeIds: new Set(),
|
||||
count: node?.count || 0,
|
||||
count: moduleId === 'all' ? allModuleTotal.value.all : node?.count ?? 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -91,25 +91,19 @@ export default function useModuleSelections<T>(
|
|||
if (selectedProps) {
|
||||
const { selectIds: selectModuleIds, count, excludeIds } = selectedProps;
|
||||
|
||||
// 处理单个模块的选择状态
|
||||
if (moduleId !== 'all') {
|
||||
if (selectModuleIds.size < count) {
|
||||
selectedProps.selectAll = false;
|
||||
}
|
||||
// 符合选择条数和总数相等,置空模块选择参数
|
||||
if (selectModuleIds.size === count) {
|
||||
setSelectedAll(moduleId);
|
||||
}
|
||||
if (excludeIds.size) {
|
||||
selectedProps.selectAll = false;
|
||||
}
|
||||
|
||||
if (excludeIds.size === count) {
|
||||
resetModule(moduleId, false);
|
||||
}
|
||||
} else if (moduleId === 'all') {
|
||||
// 处理全选选择状态
|
||||
if (excludeIds.size) {
|
||||
selectedProps.selectAll = false;
|
||||
} else {
|
||||
if (excludeIds.size === count) {
|
||||
resetModule(moduleId, false);
|
||||
}
|
||||
|
||||
if (selectModuleIds.size === count) {
|
||||
if (moduleId === 'all') {
|
||||
resetModule(moduleId, true);
|
||||
} else {
|
||||
setSelectedAll(moduleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +149,7 @@ export default function useModuleSelections<T>(
|
|||
function rowSelectChange(record: Record<string, any>) {
|
||||
const { moduleId } = record;
|
||||
setUnSelectNode(moduleId);
|
||||
setUnSelectNode('all');
|
||||
updateSelectModule(moduleId, record.id);
|
||||
updateSelectModule('all', record.id);
|
||||
}
|
||||
|
@ -185,9 +180,9 @@ export default function useModuleSelections<T>(
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setModuleTree(tree: MsTreeNodeData[]) {
|
||||
function setModuleInfo([tree, count]: [MsTreeNodeData[], Record<string, any>]) {
|
||||
moduleTree.value = tree;
|
||||
allModuleTotal.value = count;
|
||||
}
|
||||
|
||||
function clearSelector() {
|
||||
|
@ -229,6 +224,6 @@ export default function useModuleSelections<T>(
|
|||
setSelectedAll,
|
||||
updateSelectModule,
|
||||
clearSelector,
|
||||
setModuleTree,
|
||||
setModuleInfo,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { getModuleCount } from '@/api/modules/api-test/management';
|
||||
import { getModuleCount as getScenarioModuleCount } from '@/api/modules/api-test/scenario';
|
||||
import { getCaseModulesCounts, getPublicLinkCaseModulesCounts } from '@/api/modules/case-management/featureCase';
|
||||
import { testPlanAssociateModuleCount } from '@/api/modules/test-plan/testPlan';
|
||||
|
||||
import { CaseCountApiTypeEnum } from '@/enums/associateCaseEnum';
|
||||
import { CaseLinkEnum } from '@/enums/caseEnum';
|
||||
|
@ -13,7 +13,7 @@ export const getModuleTreeCountApiMap: Record<string, any> = {
|
|||
},
|
||||
[CaseCountApiTypeEnum.TEST_PLAN_CASE_COUNT]: {
|
||||
[CaseLinkEnum.FUNCTIONAL]: getCaseModulesCounts,
|
||||
[CaseLinkEnum.API]: getModuleCount,
|
||||
[CaseLinkEnum.API]: testPlanAssociateModuleCount,
|
||||
[CaseLinkEnum.SCENARIO]: getScenarioModuleCount,
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue