fix(测试计划): 修复测试计划以及用例管理bugs

This commit is contained in:
xinxin.wu 2024-06-24 19:38:50 +08:00 committed by 刘瑞斌
parent b47d8c60ed
commit 4165947b4a
21 changed files with 173 additions and 92 deletions

View File

@ -134,7 +134,6 @@
width: 200,
showDrag: true,
},
{
title: 'common.tag',
dataIndex: 'tags',

View File

@ -169,6 +169,14 @@
width: 150,
showDrag: true,
},
{
title: 'common.tag',
dataIndex: 'tags',
isTag: true,
isStringTag: true,
width: 400,
showDrag: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateUser',
slotName: 'createUserName',
@ -227,12 +235,6 @@
return {
...record,
caseLevel: getCaseLevel(record),
tags: (record.tags || []).map((item: string, i: number) => {
return {
id: `${record.id}-${i}`,
name: item,
};
}),
};
}
);

View File

@ -374,7 +374,7 @@
case CaseLinkEnum.FUNCTIONAL:
return t('common.searchByIdName');
case CaseLinkEnum.API:
return t('apiTestManagement.searchPlaceholder');
return t('ms.case.associate.apiSearchPlaceholder');
case CaseLinkEnum.SCENARIO:
return t('common.searchByIdName');
default:

View File

@ -21,4 +21,5 @@ export default {
'ms.case.associate.gotIt': 'I got it',
'ms.case.associate.switchProject': 'Switch project?',
'ms.case.associate.switchProjectPopTip': 'After switching, the selected data will be cleared',
'ms.case.associate.apiSearchPlaceholder': 'Support ID/ name/tag/ path search',
};

View File

@ -21,4 +21,5 @@ export default {
'ms.case.associate.gotIt': '知道了',
'ms.case.associate.switchProject': '切换项目?',
'ms.case.associate.switchProjectPopTip': '切换后,已选数据将清空',
'ms.case.associate.apiSearchPlaceholder': '支持 ID/名称/标签/路径搜索',
};

View File

@ -285,24 +285,25 @@
return customFieldToColumns(res);
};
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps } = useTable(
getRecycleList,
{
tableKey: TableKeyEnum.BUG_MANAGEMENT_RECYCLE,
selectable: true,
noDisable: true,
showSetting: true,
scroll: { x: '1900px' },
heightUsed: 256,
},
(record: TableData) => ({
...record,
handleUser: record.handleUserName,
createUser: record.createUserName,
updateUser: record.updateUserName,
...customFieldDataToTableData(record.customFields, customFields.value),
})
);
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps, resetSelector, resetFilterParams } =
useTable(
getRecycleList,
{
tableKey: TableKeyEnum.BUG_MANAGEMENT_RECYCLE,
selectable: true,
noDisable: true,
showSetting: true,
scroll: { x: '1900px' },
heightUsed: 256,
},
(record: TableData) => ({
...record,
handleUser: record.handleUserName,
createUser: record.createUserName,
updateUser: record.updateUserName,
...customFieldDataToTableData(record.customFields, customFields.value),
})
);
const tableAction = {
baseAction: [
@ -354,6 +355,8 @@
try {
await recoverSingleByRecycle(record.id);
Message.success(t('bugManagement.recycle.recoverSuccess'));
resetSelector();
resetFilterParams();
fetchData();
} catch (error) {
// eslint-disable-next-line no-console
@ -370,6 +373,8 @@
appStore.hideLoading();
Message.success(t('bugManagement.recycle.recoverSuccess'));
keyword.value = '';
resetSelector();
resetFilterParams();
fetchData();
} catch (error) {
// eslint-disable-next-line no-console
@ -386,6 +391,8 @@
try {
await deleteSingleByRecycle(record.id);
Message.success(t('common.deleteSuccess'));
resetSelector();
resetFilterParams();
fetchData();
} catch (error) {
// eslint-disable-next-line no-console
@ -405,6 +412,8 @@
await deleteBatchByRecycle(tmpObj);
Message.success(t('common.deleteSuccess'));
keyword.value = '';
resetSelector();
resetFilterParams();
fetchData();
} catch (error) {
// eslint-disable-next-line no-console

View File

@ -2,7 +2,7 @@
<MsDetailDrawer
ref="detailDrawerRef"
v-model:visible="showDrawerVisible"
:width="880"
:width="860"
:footer="false"
:mask="false"
:title="t('caseManagement.featureCase.caseDetailTitle', { id: detailInfo?.num, name: detailInfo?.name })"
@ -89,14 +89,16 @@
</template>
<template #default="{ detail, loading }">
<div ref="wrapperRef" class="bg-white">
<div class="header relative h-[48px] pl-2">
<MsTab
v-model:active-key="activeTab"
:content-tab-list="tabSetting"
:get-text-func="getTotal"
class="no-content relative border-b"
@change="clickMenu"
/>
<div class="header relative h-[48px] border-b pl-2">
<div class="max-w-[calc(100%-72px)]"
><MsTab
v-model:active-key="activeTab"
:content-tab-list="tabSetting"
:get-text-func="getTotal"
class="no-content relative"
@change="clickMenu"
/></div>
<span class="display-setting h-full text-[var(--color-text-2)]" @click="showMenuSetting">{{
t('caseManagement.featureCase.detailDisplaySetting')
}}</span>

View File

@ -331,7 +331,7 @@
]);
const featureCaseStore = useFeatureCaseStore();
const modelId = computed(() => featureCaseStore.moduleId[0]);
const modelId = computed(() => featureCaseStore.moduleId[0] || 'root');
const initForm: DetailCase = {
id: '',

View File

@ -14,6 +14,11 @@
<div class="one-line-text max-w-[200px]">{{ characterLimit(record.handleUserName) || '-' }}</div>
</a-tooltip>
</template>
<template #createUserName="{ record }">
<a-tooltip :content="record.handleUserName">
<div class="one-line-text">{{ record.createUserName || '-' }}</div>
</a-tooltip>
</template>
<template #operation="{ record }">
<MsButton v-permission="['FUNCTIONAL_CASE:READ+UPDATE']" @click="cancelLink(record.id)">{{

View File

@ -27,21 +27,19 @@
></a-input-search>
</div>
</div>
<div>
<ms-base-table
ref="tableRef"
v-bind="propsRes"
:action-config="{
baseAction: [],
moreAction: [],
}"
v-on="propsEvent"
>
<template #name="{ record }">
<BugNamePopover :name="record.name" :content="record.content" />
</template>
</ms-base-table>
</div>
<ms-base-table
ref="tableRef"
v-bind="propsRes"
:action-config="{
baseAction: [],
moreAction: [],
}"
v-on="propsEvent"
>
<template #name="{ record }">
<BugNamePopover :name="record.name" :content="record.content" />
</template>
</ms-base-table>
</MsDrawer>
</template>
@ -87,7 +85,6 @@
width: 150,
showInTable: true,
showTooltip: true,
ellipsis: true,
showDrag: false,
},
{
@ -105,7 +102,6 @@
showInTable: true,
showTooltip: true,
width: 200,
ellipsis: true,
showDrag: false,
},
{
@ -124,7 +120,6 @@
showInTable: true,
showTooltip: true,
width: 200,
ellipsis: true,
showDrag: false,
},
{
@ -134,7 +129,6 @@
showInTable: true,
showTooltip: true,
width: 200,
ellipsis: true,
},
{
title: 'caseManagement.featureCase.tableColumnCreateTime',

View File

@ -78,7 +78,12 @@
</template>
<template #handleUserName="{ record }">
<a-tooltip :content="record.handleUserName">
<div class="one-line-text max-w-[200px]">{{ characterLimit(record.handleUserName) || '-' }}</div>
<div class="one-line-text">{{ record.handleUserName || '-' }}</div>
</a-tooltip>
</template>
<template #createUserName="{ record }">
<a-tooltip :content="record.handleUserName">
<div class="one-line-text">{{ record.createUserName || '-' }}</div>
</a-tooltip>
</template>
<template #testPlanName="{ record }">

View File

@ -12,7 +12,7 @@
:max-length="255"
/>
<a-dropdown-button
v-if="hasAllPermission(['FUNCTIONAL_CASE:READ+ADD', 'FUNCTIONAL_CASE:READ+IMPORT'])"
v-if="hasAllPermission(['FUNCTIONAL_CASE:READ+IMPORT', 'FUNCTIONAL_CASE:READ+ADD'])"
class="ml-2"
type="primary"
@click="handleSelect('newCase')"
@ -31,14 +31,33 @@
</a-doption>
</template>
</a-dropdown-button>
<a-button
v-else-if="
!hasAnyPermission(['FUNCTIONAL_CASE:READ+ADD']) && hasAnyPermission(['FUNCTIONAL_CASE:READ+IMPORT'])
"
class="ml-2"
type="primary"
@click="handleSelect('import', 'Excel')"
>
{{ t('caseManagement.featureCase.importExcel') }}
</a-button>
<a-button
v-else
v-permission="['FUNCTIONAL_CASE:READ+ADD']"
class="ml-2"
type="primary"
@click="handleSelect('newCase')"
>
{{ t('common.newCreate') }}
</a-button>
</div>
<div class="case h-[38px]">
<div class="flex items-center" :class="getActiveClass('all')" @click="setActiveFolder('all')">
<MsIcon type="icon-icon_folder_filled1" class="folder-icon" />
<div class="folder-name mx-[4px]">{{ t('caseManagement.featureCase.allCase') }}</div>
<div class="folder-count">({{ modulesCount.all || 0 }})</div></div
>
<div class="folder-count">({{ modulesCount.all || 0 }})</div>
</div>
<div class="ml-auto flex items-center">
<a-tooltip :content="isExpandAll ? t('common.expandAllSubModule') : t('common.collapseAllSubModule')">
<MsButton type="icon" status="secondary" class="!mr-0 p-[4px]" @click="expandHandler">
@ -82,7 +101,7 @@
@case-node-select="caseNodeSelect"
@init="setRootModules"
@drag-update="dragUpdate"
></FeatureCaseTree>
/>
</div>
</div>
<div class="flex-1">
@ -110,7 +129,7 @@
:module-name="activeFolderName"
@init="initModulesCount"
@import="importCase"
></CaseTable>
/>
</div>
</template>
</MsSplitBox>
@ -435,7 +454,7 @@
.case {
padding: 8px 4px;
border-radius: var(--border-radius-small);
@apply flex cursor-pointer items-center justify-between;
@apply flex cursor-pointer items-center justify-between;
&:hover {
background-color: rgb(var(--primary-1));
}
@ -471,7 +490,7 @@
}
}
.recycle {
@apply absolute bottom-0 bg-white pb-4;
@apply absolute bottom-0 bg-white pb-4;
:deep(.arco-divider-horizontal) {
margin: 8px 0;
}

View File

@ -135,7 +135,7 @@ export default {
'caseManagement.featureCase.tabShowSetting': 'tab display setting',
'caseManagement.featureCase.closeModuleTab': 'Close: in the drawer not show related modules',
'caseManagement.featureCase.enableModuleTab': 'Open: Display the relevant modules in the drawer',
'caseManagement.featureCase.recoverDefault': 'Restore default',
'caseManagement.featureCase.recoverDefault': 'Undo modify',
'caseManagement.featureCase.detail': 'details',
'caseManagement.featureCase.nonClosableTab': 'These attributes cannot be turned off',
'caseManagement.featureCase.case': 'case',

View File

@ -134,7 +134,7 @@ export default {
'caseManagement.featureCase.tabShowSetting': 'tab 显示设置',
'caseManagement.featureCase.closeModuleTab': '关闭: 在抽屉内不展示相关模块',
'caseManagement.featureCase.enableModuleTab': '开启: 在抽屉内展示相关模块',
'caseManagement.featureCase.recoverDefault': '恢复默认',
'caseManagement.featureCase.recoverDefault': '撤销修改',
'caseManagement.featureCase.detail': '详情',
'caseManagement.featureCase.nonClosableTab': '以上属性不可关闭',
'caseManagement.featureCase.case': '用例',

View File

@ -1,7 +1,7 @@
<template>
<MsBaseTable v-bind="currentCaseTable.propsRes.value" v-on="currentCaseTable.propsEvent.value">
<template #num="{ record }">
<MsButton type="text" @click="showReport(record)">{{ record.num }}</MsButton>
<MsButton type="text" @click="toDetail(record)">{{ record.num }}</MsButton>
</template>
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL]="{ filterContent }">
<caseLevel :case-level="filterContent.value" />
@ -14,7 +14,12 @@
</template>
<template #lastExecResult="{ record }">
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="record.executeResult" />
<ExecutionStatus
:module-type="ReportEnum.API_REPORT"
:status="record.executeResult"
:class="[!record.executeResult ? '' : 'cursor-pointer']"
@click="showReport(record)"
/>
</template>
</MsBaseTable>
<CaseAndScenarioReportDrawer
@ -44,13 +49,18 @@
reportScenarioDetail,
reportStepDetail,
} from '@/api/modules/test-plan/report';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import { ApiOrScenarioCaseItem } from '@/models/testPlan/report';
import type { PlanDetailApiCaseItem } from '@/models/testPlan/testPlan';
import { ReportEnum } from '@/enums/reportEnum';
import { ApiTestRouteEnum } from '@/enums/routeEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { casePriorityOptions, lastReportStatusListOptions } from '@/views/api-test/components/config';
const { openNewPage } = useOpenNewPage();
const props = defineProps<{
reportId: string;
shareId?: string;
@ -153,10 +163,26 @@
const apiReportId = ref<string>('');
function showReport(record: ApiOrScenarioCaseItem) {
if (!record.executeResult || record.executeResult === 'STOPPED') return;
reportVisible.value = true;
apiReportId.value = record.reportId;
}
//
function toDetail(record: PlanDetailApiCaseItem) {
if (props.activeTab === 'scenarioCase') {
openNewPage(ApiTestRouteEnum.API_TEST_SCENARIO, {
id: record.id,
pId: record.projectId,
});
} else {
openNewPage(ApiTestRouteEnum.API_TEST_MANAGEMENT, {
cId: record.id,
pId: record.projectId,
});
}
}
watch(
() => props.activeTab,
() => {

View File

@ -79,6 +79,13 @@
return data;
}
function getResultText(isPass: boolean, text: string) {
const successColor = 'rgb(76, 217, 100)';
const errorColor = 'rgb(255, 59, 48)';
const color = isPass ? successColor : errorColor;
return `<strong><span style="color: ${color}" color="${color}" fontsize="">${text}</span></strong>`;
}
const summaryContent = computed(() => {
const { functionalCount, apiCaseCount, apiScenarioCount } = props.detail;
const functionalCaseDetail = getSummaryDetail(functionalCount);
@ -91,17 +98,30 @@
//
const allSuccessCount = (allSuccessCase / allCaseTotal) * 100;
const allSuccessRate = `${Number.isNaN(allSuccessCount) ? 0 : allSuccessCount.toFixed(2)}%`;
// TODO
const allSuccessRate = `${Number.isNaN(allSuccessCount) ? 0 : allSuccessCount.toFixed(2)}`;
if (props.isPlanGroup) {
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong>包含 ${props.detail.planCount}个子计划。
其中 ${props.detail.passCountOfPlan} 个子计划通过 ${props.detail.failCountOfPlan} 个子计划不通过</span></p>`;
}
const functionalCasText = `1本次测试包含${functionalCaseDetail.caseTotal}条功能测试用例,执行了${functionalCaseDetail.hasExecutedCase}条,未执行${functionalCaseDetail.pending}条,执行率为${functionalCaseDetail.apiExecutedRate},通过用例${functionalCaseDetail.success}条,通过率为${functionalCaseDetail.successRate}。共发现缺陷${props.detail.functionalBugCount}个。<br>`;
const functionCaseDesc = functionalCaseDetail.caseTotal ? `${functionalCasText}` : ``;
const apiCaseText = `2本次测试包含${apiCaseDetail.caseTotal}条接口测试用例,执行了${apiCaseDetail.hasExecutedCase}条,未执行${apiCaseDetail.pending}条,执行率为${apiCaseDetail.apiExecutedRate},通过用例${apiCaseDetail.success}条,通过率为${apiCaseDetail.successRate}。共发现缺陷 ${props.detail.apiBugCount} 个。<br>`;
const apiCaseDesc = apiCaseDetail.caseTotal ? `${apiCaseText}` : ``;
const scenarioCaseText = `3本次测试包含${apiScenarioDetail.caseTotal}条场景测试用例,执行了${apiScenarioDetail.hasExecutedCase}条,未执行${apiScenarioDetail.pending}条,执行率为${apiScenarioDetail.apiExecutedRate}%,通过用例${apiScenarioDetail.success}条,通过率为${apiScenarioDetail.successRate}。共发现缺陷${props.detail.scenarioBugCount}`;
const scenarioCaseDesc = apiScenarioDetail.caseTotal ? `${scenarioCaseText}` : ``;
const isPass = Number(allSuccessRate) >= Number(props.detail.passThreshold);
const isAchieveText = getResultText(isPass, isPass ? '达到' : '未达到');
const isMeetText = getResultText(isPass, isPass ? '满足' : '不满足');
//
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong> 包含功能测试、接口用例、场景用例, 共 ${allCaseTotal}条用例,已执行 ${allHasExecutedCase} 条,通过用例 ${allSuccessCase} 条,通过率为 ${allSuccessRate},达到/未达到通过阈值(通过阈值为${props.detail.passThreshold}%<strong>${props.detail.testPlanName}</strong> 计划满足/不满足发布要求。<br>
1本次测试包含${functionalCaseDetail.caseTotal}条功能测试用例执行了${functionalCaseDetail.hasExecutedCase}未执行${functionalCaseDetail.pending}执行率为${functionalCaseDetail.apiExecutedRate}通过用例${functionalCaseDetail.success}通过率为${functionalCaseDetail.successRate}共发现缺陷${props.detail.functionalBugCount}<br>
2本次测试包含${apiCaseDetail.caseTotal}条接口测试用例执行了${apiCaseDetail.hasExecutedCase}未执行${apiCaseDetail.pending}执行率为${apiCaseDetail.apiExecutedRate}通过用例${apiCaseDetail.success}通过率为${apiCaseDetail.successRate}共发现缺陷 ${props.detail.apiBugCount} <br>
3本次测试包含${apiScenarioDetail.caseTotal}条场景测试用例执行了${apiScenarioDetail.hasExecutedCase}未执行${apiScenarioDetail.pending}执行率为${apiScenarioDetail.apiExecutedRate}%通过用例${apiScenarioDetail.success}通过率为${apiScenarioDetail.successRate}共发现缺陷${props.detail.scenarioBugCount}</span></p>
return `<p style=""><span color="" fontsize=""> <strong>${props.detail.testPlanName}</strong> 包含功能测试、接口用例、场景用例, 共 ${allCaseTotal}条用例,已执行 ${allHasExecutedCase} 条,通过用例 ${allSuccessCase} 条,通过率为 ${allSuccessRate}%${isAchieveText}通过阈值(通过阈值为${props.detail.passThreshold}%<strong>${props.detail.testPlanName}</strong> 计划${isMeetText}发布要求。<br>
${functionCaseDesc}
${apiCaseDesc}
${scenarioCaseDesc}</span></p>
`;
});

View File

@ -92,10 +92,12 @@
}
const contentTip = computed(() => {
if (props.record?.type === testPlanTypeEnum.GROUP) {
return t('testPlan.testPlanGroup.planGroupDeleteContent');
}
let deleteMessage;
const planType =
props.record?.type === testPlanTypeEnum.GROUP
? `${t('testPlan.testPlanIndex.testPlanGroup')}`
: `${t('testPlan.testPlanIndex.plan')}`;
switch (props.record && props.record.status) {
case 'ARCHIVED':
deleteMessage = t('testPlan.testPlanIndex.deleteArchivedPlan');
@ -104,13 +106,13 @@
deleteMessage = t('testPlan.testPlanIndex.deleteRunningPlan');
break;
case 'COMPLETED':
deleteMessage = t('testPlan.testPlanIndex.deleteCompletedPlan');
deleteMessage = t('testPlan.testPlanGroup.planGroupDeleteContent');
break;
default:
deleteMessage = t('testPlan.testPlanIndex.deletePendingPlan');
}
const scheduledMessage = props.scheduleConfig ? t('testPlan.testPlanIndex.scheduledTask') : '';
return `${deleteMessage}${scheduledMessage}${t('testPlan.testPlanIndex.operateWithCaution')}`;
return `${planType}${deleteMessage}${scheduledMessage}${t('testPlan.testPlanIndex.operateWithCaution')}`;
});
const showArchive = computed(() => {

View File

@ -36,7 +36,7 @@
ref="tableRef"
class="mt-4"
:action-config="testPlanBatchActions"
:selectable="hasOperationPermission && showType !== testPlanTypeEnum.ALL"
:selectable="hasOperationPermission && showType !== testPlanTypeEnum.ALL && !isArchived"
filter-icon-align-left
:expanded-keys="expandedKeys"
:disabled-config="{
@ -1287,7 +1287,7 @@
}
planType.value = record.type;
planSourceId.value = record.id;
taskForm.value = defaultCountDetailMap.value[record.id]?.scheduleConfig;
taskForm.value = cloneDeep(defaultCountDetailMap.value[record.id]?.scheduleConfig);
showScheduledTaskModal.value = true;
}

View File

@ -49,8 +49,4 @@ export const planStatusOptions: { value: planStatusType; label: string }[] = [
value: 'COMPLETED',
label: t('caseManagement.caseReview.unStart'),
},
{
value: 'ARCHIVED',
label: t('caseManagement.caseReview.going'),
},
];

View File

@ -66,10 +66,10 @@ export default {
'testPlan.testPlanIndex.apiScenarioCase': 'Scenario use cases',
'testPlan.testPlanIndex.scheduledTask': 'stop and delete scheduled tasks, ',
'testPlan.testPlanIndex.operateWithCaution': 'please operate with caution!',
'testPlan.testPlanIndex.deleteArchivedPlan': 'After the program has been archived, delete data unrecoverable,',
'testPlan.testPlanIndex.deletePendingPlan': 'The plan is not executed, the data cannot be recovered after deletion,',
'testPlan.testPlanIndex.deleteArchivedPlan': 'Archived. Data cannot be recovered after deletion.',
'testPlan.testPlanIndex.deletePendingPlan': 'Not executed. Data cannot be recovered after deletion.',
'testPlan.testPlanIndex.deleteRunningPlan':
'The plan is in progress. After deletion, the execution will be terminated and cannot be restored,',
'In progress. After deletion, execution terminates and cannot be recovered.',
'testPlan.testPlanIndex.deleteCompletedPlan':
'Suggest that completed plans, choose archiving, and retain use case information and execution results; If the deletion continues, the data will not be restored,',
'testPlan.testPlanIndex.confirmArchivePlan':
@ -134,7 +134,7 @@ export default {
'testPlan.testPlanGroup.planGroupArchiveContent':
'After archived, plan and carry out information no longer update and edit data unrecoverable, please careful operation.',
'testPlan.testPlanGroup.planGroupDeleteContent':
'Planning groups choose file has been completed and the case information, and the results will be retained, If you continue to delete, the data will not be recovered, please be careful!',
'It is recommended to select the archive, and the use case information and execution results will be retained;The data will not be restored if continue to delete,',
'testPlan.testPlanGroup.selectTestPlanGroupPlaceHolder': 'Please select the Plan group',
'testPlan.testPlanGroup.batchArchivedGroup': 'Confirm archive: {count} test plan groups',
'testPlan.testPlanGroup.confirmBatchDeletePlanGroup': 'Are you sure to delete {count} test plan groups?',

View File

@ -64,9 +64,9 @@ export default {
'testPlan.testPlanIndex.apiScenarioCase': '场景用例',
'testPlan.testPlanIndex.scheduledTask': '定时任务停止并删除,',
'testPlan.testPlanIndex.operateWithCaution': '请谨慎操作!',
'testPlan.testPlanIndex.deleteArchivedPlan': '计划 已归档,删除后数据不可恢复,',
'testPlan.testPlanIndex.deletePendingPlan': '计划 未执行,删除后数据不可恢复,',
'testPlan.testPlanIndex.deleteRunningPlan': '计划 进行中,删除后,终止执行且不可恢复,',
'testPlan.testPlanIndex.deleteArchivedPlan': ' 已归档,删除后数据不可恢复,',
'testPlan.testPlanIndex.deletePendingPlan': ' 未执行,删除后数据不可恢复,',
'testPlan.testPlanIndex.deleteRunningPlan': ' 进行中,删除后,终止执行且不可恢复,',
'testPlan.testPlanIndex.deleteCompletedPlan':
'建议计划 已完成 ,选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,',
'testPlan.testPlanIndex.confirmArchivePlan': '归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
@ -124,7 +124,7 @@ export default {
'testPlan.testPlanGroup.planGroupArchiveContent':
'归档后,计划执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
'testPlan.testPlanGroup.planGroupDeleteContent':
'计划组 已完成 选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,请谨慎操作!',
' 已完成 建议选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,',
'testPlan.testPlanGroup.module': '模块',
'testPlan.testPlanGroup.selectTestPlanGroupPlaceHolder': '请选择计划组',
'testPlan.testPlanGroup.batchArchivedGroup': '确认归档:{count} 个测试计划组吗',