From c170455ed57d504cc8a56db1943c85f6737f94ff Mon Sep 17 00:00:00 2001 From: teukkk Date: Thu, 16 May 2024 16:58:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92):=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E8=AF=A6=E6=83=85-?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B=E5=88=97=E8=A1=A8-?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E5=92=8C=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/modules/test-plan/testPlan.ts | 6 ++ .../src/api/requrls/test-plan/testPlan.ts | 2 + frontend/src/locale/en-US/common.ts | 1 + frontend/src/locale/zh-CN/common.ts | 1 + frontend/src/models/testPlan/testPlan.ts | 7 +- .../featureCase/components/caseTable.vue | 102 +++++++++++++----- .../testPlan/detail/featureCase/index.vue | 9 +- .../views/test-plan/testPlan/detail/index.vue | 2 +- 8 files changed, 101 insertions(+), 29 deletions(-) diff --git a/frontend/src/api/modules/test-plan/testPlan.ts b/frontend/src/api/modules/test-plan/testPlan.ts index 8aff4f15b2..b8743734c5 100644 --- a/frontend/src/api/modules/test-plan/testPlan.ts +++ b/frontend/src/api/modules/test-plan/testPlan.ts @@ -28,6 +28,7 @@ import { planDetailBugPageUrl, planPassRateUrl, RunFeatureCaseUrl, + SortFeatureCaseUrl, updateTestPlanModuleUrl, UpdateTestPlanUrl, } from '@/api/requrls/test-plan/testPlan'; @@ -48,6 +49,7 @@ import type { PlanDetailFeatureCaseItem, PlanDetailFeatureCaseListQueryParams, RunFeatureCaseParams, + SortFeatureCaseParams, TestPlanDetail, TestPlanItem, UseCountType, @@ -166,6 +168,10 @@ export function getFeatureCaseModule(planId: string) { export function disassociateCase(data: DisassociateCaseParams) { return MSR.post({ url: DisassociateCaseUrl, data }); } +// 计划详情-功能用例列表-拖拽排序 +export const sortFeatureCase = (data: SortFeatureCaseParams) => { + return MSR.post({ url: SortFeatureCaseUrl, data }); +}; // 计划详情-功能用例列表-批量取消关联用例 export function batchDisassociateCase(data: BatchFeatureCaseParams) { return MSR.post({ url: BatchDisassociateCaseUrl, data }); diff --git a/frontend/src/api/requrls/test-plan/testPlan.ts b/frontend/src/api/requrls/test-plan/testPlan.ts index 8b0ab3140b..03f8ca9dc3 100644 --- a/frontend/src/api/requrls/test-plan/testPlan.ts +++ b/frontend/src/api/requrls/test-plan/testPlan.ts @@ -48,6 +48,8 @@ export const GetPlanDetailFeatureCaseListUrl = '/test-plan/functional/case/page' export const GetFeatureCaseModuleCountUrl = '/test-plan/functional/case/module/count'; // 计划详情-功能用例模块树 export const GetFeatureCaseModuleUrl = '/test-plan/functional/case/tree'; +// 计划详情-功能用例列表-拖拽排序 +export const SortFeatureCaseUrl = '/test-plan/functional/case/sort'; // 计划详情-功能用例-取消关联用例 export const DisassociateCaseUrl = '/test-plan/functional/case/disassociate'; // 计划详情-功能用例-批量取消关联用例 diff --git a/frontend/src/locale/en-US/common.ts b/frontend/src/locale/en-US/common.ts index 9f21cab2a6..79fb7f5f48 100644 --- a/frontend/src/locale/en-US/common.ts +++ b/frontend/src/locale/en-US/common.ts @@ -180,4 +180,5 @@ export default { 'common.responsiblePerson': 'Responsible person', 'common.updateUserName': 'Update user name', 'common.updateTime': 'Update time', + 'common.belongProject': 'Belong to Project', }; diff --git a/frontend/src/locale/zh-CN/common.ts b/frontend/src/locale/zh-CN/common.ts index 21ae4e6cdf..6222b9a099 100644 --- a/frontend/src/locale/zh-CN/common.ts +++ b/frontend/src/locale/zh-CN/common.ts @@ -183,4 +183,5 @@ export default { 'common.responsiblePerson': '责任人', 'common.updateUserName': '更新人', 'common.updateTime': '更新时间', + 'common.belongProject': '所属项目', }; diff --git a/frontend/src/models/testPlan/testPlan.ts b/frontend/src/models/testPlan/testPlan.ts index 3a837e2bea..a664645e6e 100644 --- a/frontend/src/models/testPlan/testPlan.ts +++ b/frontend/src/models/testPlan/testPlan.ts @@ -2,10 +2,9 @@ import type { BatchActionQueryParams } from '@/components/pure/ms-table/type'; import type { customFieldsItem } from '@/models/caseManagement/featureCase'; import type { TableQueryParams } from '@/models/common'; +import { BatchApiParams, DragSortParams } from '@/models/common'; import { LastExecuteResults } from '@/enums/caseEnum'; -import { BatchApiParams } from '../common'; - export type planStatusType = 'PREPARED' | 'UNDERWAY' | 'COMPLETED' | 'ARCHIVED'; export interface AssociateFunctionalCaseItem { @@ -188,6 +187,10 @@ export interface BatchUpdateCaseExecutorParams extends BatchFeatureCaseParams { userId: string; } +export interface SortFeatureCaseParams extends DragSortParams { + testPlanId: string; +} + export interface PassRateCountDetail { id: string; passThreshold: number; diff --git a/frontend/src/views/test-plan/testPlan/detail/featureCase/components/caseTable.vue b/frontend/src/views/test-plan/testPlan/detail/featureCase/components/caseTable.vue index 1e5f9cdab8..629d7e3fb9 100644 --- a/frontend/src/views/test-plan/testPlan/detail/featureCase/components/caseTable.vue +++ b/frontend/src/views/test-plan/testPlan/detail/featureCase/components/caseTable.vue @@ -16,7 +16,13 @@ - + @@ -70,11 +76,18 @@ - + {{ t('common.copy') }} @@ -164,11 +177,13 @@ import ExecuteForm from '@/views/test-plan/testPlan/detail/featureCase/components/executeForm.vue'; import { + associationCaseToPlan, batchDisassociateCase, batchExecuteCase, batchUpdateCaseExecutor, disassociateCase, getPlanDetailFeatureCaseList, + sortFeatureCase, } from '@/api/modules/test-plan/testPlan'; import { defaultExecuteForm } from '@/config/testPlan'; import { useI18n } from '@/hooks/useI18n'; @@ -177,7 +192,7 @@ import useAppStore from '@/store/modules/app'; import { hasAnyPermission } from '@/utils/permission'; - import { ModuleTreeNode } from '@/models/common'; + import { DragSortParams, ModuleTreeNode } from '@/models/common'; import type { ExecuteFeatureCaseFormParams, PlanDetailFeatureCaseItem, @@ -200,11 +215,12 @@ offspringIds: string[]; planId: string; moduleTree: ModuleTreeNode[]; + repeatCase: boolean; }>(); const emit = defineEmits<{ (e: 'getModuleCount', params: PlanDetailFeatureCaseListQueryParams): void; - (e: 'executeDone'): void; + (e: 'refresh'): void; }>(); const { t } = useI18n(); @@ -283,6 +299,14 @@ width: 200, showDrag: true, }, + { + title: 'common.belongProject', + dataIndex: 'projectName', + showTooltip: true, + showInTable: false, + showDrag: true, + width: 150, + }, { title: 'testPlan.featureCase.bugCount', dataIndex: 'bugCount', @@ -410,6 +434,54 @@ loadList(); } + // 拖拽排序 + async function handleDragChange(params: DragSortParams) { + try { + await sortFeatureCase({ ...params, testPlanId: props.planId }); + Message.success(t('caseManagement.featureCase.sortSuccess')); + loadCaseList(); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + } + } + + // 复制用例 + async function handleCopyCase(record: PlanDetailFeatureCaseItem) { + try { + await associationCaseToPlan({ + functionalSelectIds: [record.caseId], + testPlanId: props.planId, + }); + Message.success(t('ms.case.associate.associateSuccess')); + resetCaseList(); + emit('refresh'); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + } + } + + // 取消关联 + 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(); + emit('refresh'); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + } finally { + disassociateLoading.value = false; + } + } + // 批量取消关联用例 function handleBatchDisassociateCase() { openModal({ @@ -426,6 +498,7 @@ }); Message.success(t('common.updateSuccess')); resetCaseList(); + emit('refresh'); } catch (error) { // eslint-disable-next-line no-console console.log(error); @@ -451,7 +524,7 @@ Message.success(t('common.updateSuccess')); resetSelector(); loadList(); - emit('executeDone'); + emit('refresh'); } catch (error) { // eslint-disable-next-line no-console console.log(error); @@ -513,25 +586,6 @@ } } - // 取消关联 - 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) { router.push({ diff --git a/frontend/src/views/test-plan/testPlan/detail/featureCase/index.vue b/frontend/src/views/test-plan/testPlan/detail/featureCase/index.vue index 7dab9635c0..18a20071e3 100644 --- a/frontend/src/views/test-plan/testPlan/detail/featureCase/index.vue +++ b/frontend/src/views/test-plan/testPlan/detail/featureCase/index.vue @@ -14,11 +14,12 @@ @@ -37,8 +38,12 @@ import { ModuleTreeNode } from '@/models/common'; import type { PlanDetailFeatureCaseListQueryParams } from '@/models/testPlan/testPlan'; + const props = defineProps<{ + repeatCase: boolean; + }>(); + const emit = defineEmits<{ - (e: 'executeDone'): void; + (e: 'refresh'): void; }>(); const route = useRoute(); diff --git a/frontend/src/views/test-plan/testPlan/detail/index.vue b/frontend/src/views/test-plan/testPlan/detail/index.vue index 07f0742e8b..761884fd1f 100644 --- a/frontend/src/views/test-plan/testPlan/detail/index.vue +++ b/frontend/src/views/test-plan/testPlan/detail/index.vue @@ -88,7 +88,7 @@ - +