feat(测试计划): 测试计划详情-功能用例取消关联用例联调
This commit is contained in:
parent
7110f47191
commit
0c3ed10966
|
@ -5,9 +5,11 @@ import {
|
||||||
archivedPlanUrl,
|
archivedPlanUrl,
|
||||||
batchCopyPlanUrl,
|
batchCopyPlanUrl,
|
||||||
batchDeletePlanUrl,
|
batchDeletePlanUrl,
|
||||||
|
BatchDisassociateCaseUrl,
|
||||||
batchMovePlanUrl,
|
batchMovePlanUrl,
|
||||||
deletePlanUrl,
|
deletePlanUrl,
|
||||||
DeleteTestPlanModuleUrl,
|
DeleteTestPlanModuleUrl,
|
||||||
|
DisassociateCaseUrl,
|
||||||
GetFeatureCaseModuleCountUrl,
|
GetFeatureCaseModuleCountUrl,
|
||||||
GetFeatureCaseModuleUrl,
|
GetFeatureCaseModuleUrl,
|
||||||
GetPlanDetailFeatureCaseListUrl,
|
GetPlanDetailFeatureCaseListUrl,
|
||||||
|
@ -27,6 +29,8 @@ import type { CommonList, MoveModules, TableQueryParams } from '@/models/common'
|
||||||
import { ModuleTreeNode } from '@/models/common';
|
import { ModuleTreeNode } from '@/models/common';
|
||||||
import type {
|
import type {
|
||||||
AddTestPlanParams,
|
AddTestPlanParams,
|
||||||
|
BatchFeatureCaseParams,
|
||||||
|
DisassociateCaseParams,
|
||||||
PlanDetailBugItem,
|
PlanDetailBugItem,
|
||||||
PlanDetailFeatureCaseItem,
|
PlanDetailFeatureCaseItem,
|
||||||
PlanDetailFeatureCaseListQueryParams,
|
PlanDetailFeatureCaseListQueryParams,
|
||||||
|
@ -124,3 +128,11 @@ export function getFeatureCaseModuleCount(data: PlanDetailFeatureCaseListQueryPa
|
||||||
export function getFeatureCaseModule(planId: string) {
|
export function getFeatureCaseModule(planId: string) {
|
||||||
return MSR.get<ModuleTreeNode[]>({ url: `${GetFeatureCaseModuleUrl}/${planId}` });
|
return MSR.get<ModuleTreeNode[]>({ url: `${GetFeatureCaseModuleUrl}/${planId}` });
|
||||||
}
|
}
|
||||||
|
// 计划详情-功能用例列表-取消关联用例
|
||||||
|
export function disassociateCase(data: DisassociateCaseParams) {
|
||||||
|
return MSR.post({ url: DisassociateCaseUrl, data });
|
||||||
|
}
|
||||||
|
// 计划详情-功能用例列表-批量取消关联用例
|
||||||
|
export function batchDisassociateCase(data: BatchFeatureCaseParams) {
|
||||||
|
return MSR.post({ url: BatchDisassociateCaseUrl, data });
|
||||||
|
}
|
||||||
|
|
|
@ -38,3 +38,7 @@ export const GetPlanDetailFeatureCaseListUrl = '/test-plan/functional/case/page'
|
||||||
export const GetFeatureCaseModuleCountUrl = '/test-plan/functional/case/module/count';
|
export const GetFeatureCaseModuleCountUrl = '/test-plan/functional/case/module/count';
|
||||||
// 计划详情-功能用例模块树
|
// 计划详情-功能用例模块树
|
||||||
export const GetFeatureCaseModuleUrl = '/test-plan/functional/case/tree';
|
export const GetFeatureCaseModuleUrl = '/test-plan/functional/case/tree';
|
||||||
|
// 计划详情-功能用例-取消关联用例
|
||||||
|
export const DisassociateCaseUrl = '/test-plan/functional/case/disassociate';
|
||||||
|
// 计划详情-功能用例-批量取消关联用例
|
||||||
|
export const BatchDisassociateCaseUrl = '/test-plan/functional/case/batch/disassociate';
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { BatchActionQueryParams } from '@/components/pure/ms-table/type';
|
||||||
|
|
||||||
import type { customFieldsItem } from '@/models/caseManagement/featureCase';
|
import type { customFieldsItem } from '@/models/caseManagement/featureCase';
|
||||||
import type { TableQueryParams } from '@/models/common';
|
import type { TableQueryParams } from '@/models/common';
|
||||||
import { LastExecuteResults } from '@/enums/caseEnum';
|
import { LastExecuteResults } from '@/enums/caseEnum';
|
||||||
|
@ -148,5 +150,14 @@ export interface PlanDetailFeatureCaseListQueryParams extends TableQueryParams {
|
||||||
testPlanId: string;
|
testPlanId: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
export interface DisassociateCaseParams {
|
||||||
|
testPlanId: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BatchFeatureCaseParams extends BatchActionQueryParams {
|
||||||
|
testPlanId: string;
|
||||||
|
moduleIds?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -46,14 +46,23 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
<span v-else class="text-[var(--color-text-2)]"><ExecuteResult :execute-result="record.lastExecResult" /></span>
|
<span v-else class="text-[var(--color-text-2)]"><ExecuteResult :execute-result="record.lastExecResult" /></span>
|
||||||
</template>
|
</template>
|
||||||
<template #operation>
|
<template #operation="{ record }">
|
||||||
<MsButton v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']" type="text" class="!mr-0">
|
<MsButton v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']" type="text" class="!mr-0">
|
||||||
{{ t('common.execute') }}
|
{{ t('common.execute') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
<a-divider v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" direction="vertical" :margin="8"></a-divider>
|
<a-divider v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" direction="vertical" :margin="8"></a-divider>
|
||||||
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" type="text" class="!mr-0">
|
<MsPopconfirm
|
||||||
{{ t('common.cancelLink') }}
|
:title="t('testPlan.featureCase.disassociateTip', { name: record.name })"
|
||||||
</MsButton>
|
:sub-title-tip="t('testPlan.featureCase.disassociateTipContent')"
|
||||||
|
:ok-text="t('common.confirm')"
|
||||||
|
:loading="disassociateLoading"
|
||||||
|
type="error"
|
||||||
|
@confirm="(val, done) => handleDisassociateCase(record, done)"
|
||||||
|
>
|
||||||
|
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+ASSOCIATION']" type="text" class="!mr-0">
|
||||||
|
{{ t('common.cancelLink') }}
|
||||||
|
</MsButton>
|
||||||
|
</MsPopconfirm>
|
||||||
<!-- TODO: 修改permission -->
|
<!-- TODO: 修改permission -->
|
||||||
<a-divider
|
<a-divider
|
||||||
v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']"
|
v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']"
|
||||||
|
@ -71,16 +80,23 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeMount, ref } from 'vue';
|
import { computed, onBeforeMount, ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsPopconfirm from '@/components/pure/ms-popconfirm/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import CaseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
import CaseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
|
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
|
||||||
|
|
||||||
import { getPlanDetailFeatureCaseList } from '@/api/modules/test-plan/testPlan';
|
import {
|
||||||
|
batchDisassociateCase,
|
||||||
|
disassociateCase,
|
||||||
|
getPlanDetailFeatureCaseList,
|
||||||
|
} from '@/api/modules/test-plan/testPlan';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useModal from '@/hooks/useModal';
|
||||||
import useTableStore from '@/hooks/useTableStore';
|
import useTableStore from '@/hooks/useTableStore';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
@ -106,7 +122,7 @@
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'init', params: PlanDetailFeatureCaseListQueryParams): void;
|
(e: 'getModuleCount', params: PlanDetailFeatureCaseListQueryParams): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -114,8 +130,13 @@
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
|
const tableParams = ref<PlanDetailFeatureCaseListQueryParams>({
|
||||||
|
testPlanId: props.planId,
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: 复制的Permission
|
// TODO: 复制的Permission
|
||||||
const hasOperationPermission = computed(() =>
|
const hasOperationPermission = computed(() =>
|
||||||
|
@ -235,10 +256,6 @@
|
||||||
eventTag: 'execute',
|
eventTag: 'execute',
|
||||||
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'testPlan.featureCase.sort',
|
|
||||||
eventTag: 'sort',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'testPlan.featureCase.changeExecutor',
|
label: 'testPlan.featureCase.changeExecutor',
|
||||||
eventTag: 'changeExecutor',
|
eventTag: 'changeExecutor',
|
||||||
|
@ -261,25 +278,6 @@
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const tableSelected = ref<(string | number)[]>([]); // 表格选中的
|
|
||||||
const batchParams = ref<BatchActionQueryParams>({
|
|
||||||
selectedIds: [],
|
|
||||||
selectAll: false,
|
|
||||||
excludeIds: [],
|
|
||||||
currentSelectCount: 0,
|
|
||||||
});
|
|
||||||
// 处理表格选中后批量操作
|
|
||||||
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
|
||||||
tableSelected.value = params?.selectedIds || [];
|
|
||||||
batchParams.value = params;
|
|
||||||
switch (event.eventTag) {
|
|
||||||
case 'execute':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModuleIds() {
|
async function getModuleIds() {
|
||||||
let moduleIds: string[] = [];
|
let moduleIds: string[] = [];
|
||||||
if (props.activeModule !== 'all') {
|
if (props.activeModule !== 'all') {
|
||||||
|
@ -293,16 +291,16 @@
|
||||||
}
|
}
|
||||||
async function loadCaseList() {
|
async function loadCaseList() {
|
||||||
const selectModules = await getModuleIds();
|
const selectModules = await getModuleIds();
|
||||||
const params: PlanDetailFeatureCaseListQueryParams = {
|
tableParams.value = {
|
||||||
testPlanId: props.planId,
|
testPlanId: props.planId,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
moduleIds: selectModules,
|
moduleIds: selectModules,
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
};
|
};
|
||||||
setLoadListParams(params);
|
setLoadListParams(tableParams.value);
|
||||||
loadList();
|
loadList();
|
||||||
emit('init', {
|
emit('getModuleCount', {
|
||||||
...params,
|
...tableParams.value,
|
||||||
current: propsRes.value.msPagination?.current,
|
current: propsRes.value.msPagination?.current,
|
||||||
pageSize: propsRes.value.msPagination?.pageSize,
|
pageSize: propsRes.value.msPagination?.pageSize,
|
||||||
});
|
});
|
||||||
|
@ -310,6 +308,90 @@
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
loadCaseList();
|
loadCaseList();
|
||||||
});
|
});
|
||||||
|
watch(
|
||||||
|
() => props.activeModule,
|
||||||
|
() => {
|
||||||
|
loadCaseList();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const tableSelected = ref<(string | number)[]>([]); // 表格选中的
|
||||||
|
const batchParams = ref<BatchActionQueryParams>({
|
||||||
|
selectIds: [],
|
||||||
|
selectAll: false,
|
||||||
|
excludeIds: [],
|
||||||
|
condition: {},
|
||||||
|
currentSelectCount: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
function resetCaseList() {
|
||||||
|
resetSelector();
|
||||||
|
emit('getModuleCount', {
|
||||||
|
...tableParams.value,
|
||||||
|
current: propsRes.value.msPagination?.current,
|
||||||
|
pageSize: propsRes.value.msPagination?.pageSize,
|
||||||
|
});
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量取消关联用例
|
||||||
|
function handleBatchDisassociateCase() {
|
||||||
|
openModal({
|
||||||
|
type: 'warning',
|
||||||
|
title: t('caseManagement.caseReview.disassociateConfirmTitle', { count: batchParams.value.currentSelectCount }),
|
||||||
|
content: t('testPlan.featureCase.batchDisassociateTipContent'),
|
||||||
|
okText: t('common.cancelLink'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await batchDisassociateCase({
|
||||||
|
...batchParams.value,
|
||||||
|
...tableParams.value,
|
||||||
|
});
|
||||||
|
Message.success(t('common.updateSuccess'));
|
||||||
|
resetCaseList();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理表格选中后批量操作
|
||||||
|
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||||
|
tableSelected.value = params?.selectedIds || [];
|
||||||
|
batchParams.value = params;
|
||||||
|
switch (event.eventTag) {
|
||||||
|
case 'execute':
|
||||||
|
break;
|
||||||
|
case 'disassociate':
|
||||||
|
handleBatchDisassociateCase();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消关联
|
||||||
|
const disassociateLoading = ref(false);
|
||||||
|
async function handleDisassociateCase(record: PlanDetailFeatureCaseItem, done?: () => void) {
|
||||||
|
try {
|
||||||
|
disassociateLoading.value = true;
|
||||||
|
await disassociateCase({ testPlanId: props.planId, id: record.id });
|
||||||
|
if (done) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
Message.success(t('common.unLinkSuccess'));
|
||||||
|
resetCaseList();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
disassociateLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 去用例详情页面
|
// 去用例详情页面
|
||||||
function toCaseDetail(record: PlanDetailFeatureCaseItem) {
|
function toCaseDetail(record: PlanDetailFeatureCaseItem) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
:active-module="activeFolderId"
|
:active-module="activeFolderId"
|
||||||
:offspring-ids="offspringIds"
|
:offspring-ids="offspringIds"
|
||||||
:module-tree="moduleTree"
|
:module-tree="moduleTree"
|
||||||
@init="getModuleCount"
|
@get-module-count="getModuleCount"
|
||||||
></CaseTable>
|
></CaseTable>
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
|
|
|
@ -89,4 +89,9 @@ export default {
|
||||||
'testPlan.featureCase.executor': 'Executor',
|
'testPlan.featureCase.executor': 'Executor',
|
||||||
'testPlan.featureCase.changeExecutor': 'Change executor',
|
'testPlan.featureCase.changeExecutor': 'Change executor',
|
||||||
'testPlan.featureCase.sort': 'sort',
|
'testPlan.featureCase.sort': 'sort',
|
||||||
|
'testPlan.featureCase.disassociateTip': 'Are you sure to cancel the association {name}? ',
|
||||||
|
'testPlan.featureCase.disassociateTipContent':
|
||||||
|
'After cancellation, it will affect the statistics related to the test plan',
|
||||||
|
'testPlan.featureCase.batchDisassociateTipContent':
|
||||||
|
' After cancellation, associate again, and the execution result is unexecuted',
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,4 +87,7 @@ export default {
|
||||||
'testPlan.featureCase.executor': '执行人',
|
'testPlan.featureCase.executor': '执行人',
|
||||||
'testPlan.featureCase.changeExecutor': '修改执行人',
|
'testPlan.featureCase.changeExecutor': '修改执行人',
|
||||||
'testPlan.featureCase.sort': '排序',
|
'testPlan.featureCase.sort': '排序',
|
||||||
|
'testPlan.featureCase.disassociateTip': '确认取消关联 { name } 吗?',
|
||||||
|
'testPlan.featureCase.disassociateTipContent': '取消后,影响测试计划相关统计',
|
||||||
|
'testPlan.featureCase.batchDisassociateTipContent': '取消后,再次关联,执行结果为:未执行',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue