feat(测试计划): 测试计划表补充遗漏&细节
This commit is contained in:
parent
a872b43c9d
commit
4358a82355
|
@ -28,6 +28,8 @@ export default {
|
||||||
'common.updateSuccess': 'Update success',
|
'common.updateSuccess': 'Update success',
|
||||||
'common.updateFailed': 'Update failed',
|
'common.updateFailed': 'Update failed',
|
||||||
'common.deleteConfirm': 'Delete confirm',
|
'common.deleteConfirm': 'Delete confirm',
|
||||||
|
'common.deleteConfirmTitle': 'Delete confirm {name} 吗',
|
||||||
|
'common.archiveConfirmTitle': 'Archive confirm {name} 吗',
|
||||||
'common.deleteSuccess': 'Delete success',
|
'common.deleteSuccess': 'Delete success',
|
||||||
'common.deleteFailed': 'Delete failed',
|
'common.deleteFailed': 'Delete failed',
|
||||||
'common.addSuccess': 'Added successfully',
|
'common.addSuccess': 'Added successfully',
|
||||||
|
@ -121,6 +123,7 @@ export default {
|
||||||
'common.move': 'Move',
|
'common.move': 'Move',
|
||||||
'common.moveSuccess': 'Move successful',
|
'common.moveSuccess': 'Move successful',
|
||||||
'common.batchMove': 'Batch move',
|
'common.batchMove': 'Batch move',
|
||||||
|
'common.batchArchiveSuccess': 'Archive successful',
|
||||||
'common.batchCopy': 'Batch copy',
|
'common.batchCopy': 'Batch copy',
|
||||||
'common.batchCopySuccess': 'Batch copy successful',
|
'common.batchCopySuccess': 'Batch copy successful',
|
||||||
'common.batchMoveSuccess': 'Batch move successful',
|
'common.batchMoveSuccess': 'Batch move successful',
|
||||||
|
|
|
@ -30,6 +30,7 @@ export default {
|
||||||
'common.updateFailed': '更新失败',
|
'common.updateFailed': '更新失败',
|
||||||
'common.deleteConfirm': '确认删除?',
|
'common.deleteConfirm': '确认删除?',
|
||||||
'common.deleteConfirmTitle': '确认删除 {name} 吗',
|
'common.deleteConfirmTitle': '确认删除 {name} 吗',
|
||||||
|
'common.archiveConfirmTitle': '确认归档 {name} 吗',
|
||||||
'common.deleteSuccess': '删除成功',
|
'common.deleteSuccess': '删除成功',
|
||||||
'common.deleteFailed': '删除失败',
|
'common.deleteFailed': '删除失败',
|
||||||
'common.addSuccess': '添加成功',
|
'common.addSuccess': '添加成功',
|
||||||
|
@ -122,6 +123,7 @@ export default {
|
||||||
'common.move': '移动',
|
'common.move': '移动',
|
||||||
'common.moveSuccess': '移动成功',
|
'common.moveSuccess': '移动成功',
|
||||||
'common.batchMove': '批量移动',
|
'common.batchMove': '批量移动',
|
||||||
|
'common.batchArchiveSuccess': '归档成功!',
|
||||||
'common.batchCopy': '批量复制',
|
'common.batchCopy': '批量复制',
|
||||||
'common.batchCopySuccess': '批量复制成功',
|
'common.batchCopySuccess': '批量复制成功',
|
||||||
'common.batchMoveSuccess': '批量移动成功',
|
'common.batchMoveSuccess': '批量移动成功',
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { BatchApiParams } from '../common';
|
import { BatchApiParams } from '../common';
|
||||||
|
|
||||||
|
export type planStatusType = 'PREPARED' | 'UNDERWAY' | 'COMPLETED' | 'ARCHIVED';
|
||||||
|
|
||||||
// 计划分页
|
// 计划分页
|
||||||
export interface TestPlanItem {
|
export interface TestPlanItem {
|
||||||
id?: string;
|
id?: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
num: number;
|
num: number;
|
||||||
name: string;
|
name: string;
|
||||||
status: string;
|
status: planStatusType;
|
||||||
type: string;
|
type: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
schedule: string; // 是否定时
|
schedule: string; // 是否定时
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="showModalVisible"
|
||||||
|
class="ms-modal-form ms-modal-no-padding ms-modal-small"
|
||||||
|
unmount-on-close
|
||||||
|
title-align="start"
|
||||||
|
:mask="true"
|
||||||
|
:mask-closable="false"
|
||||||
|
@close="cancelHandler"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<div class="flex items-center justify-start">
|
||||||
|
<MsIcon type="icon-icon_close_colorful" class="mr-[8px] text-[rgb(var(--danger-6))]" size="16" />
|
||||||
|
<div class="text-[var(--color-text-1)]">
|
||||||
|
{{ t('common.deleteConfirmTitle', { name: characterLimit(record?.name) }) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{ contentTip }}
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<a-button type="secondary" :disabled="confirmLoading" @click="cancelHandler">
|
||||||
|
{{ t('common.cancel') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button class="ml-3" type="primary" status="danger" :loading="confirmLoading" @click="confirmHandler(true)">
|
||||||
|
{{ t('common.confirmDelete') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-if="props.record?.status === 'COMPLETED'"
|
||||||
|
:loading="confirmLoading"
|
||||||
|
class="ml-3"
|
||||||
|
type="primary"
|
||||||
|
@click="confirmHandler(false)"
|
||||||
|
>
|
||||||
|
{{ t('common.archive') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useVModel } from '@vueuse/core';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
|
import type { TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
// isScheduled: boolean; // TODO 这个版本不做有无定时任务区分
|
||||||
|
record: TestPlanItem | undefined; // 表record
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', val: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const showModalVisible = useVModel(props, 'visible', emit);
|
||||||
|
|
||||||
|
function cancelHandler() {
|
||||||
|
showModalVisible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmLoading = ref<boolean>(false);
|
||||||
|
function confirmHandler(isDelete: boolean) {
|
||||||
|
try {
|
||||||
|
Message.success(isDelete ? t('common.deleteSuccess') : t('common.batchArchiveSuccess'));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDeleteTip() {
|
||||||
|
switch (props.record && props.record.status) {
|
||||||
|
case 'ARCHIVED':
|
||||||
|
return t('testPlan.testPlanIndex.deleteArchivedPlan');
|
||||||
|
case 'UNDERWAY':
|
||||||
|
return t('testPlan.testPlanIndex.deleteRunningPlan');
|
||||||
|
case 'COMPLETED':
|
||||||
|
return t('testPlan.testPlanIndex.deleteCompletedPlan');
|
||||||
|
default:
|
||||||
|
return t('testPlan.testPlanIndex.deletePendingPlan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentTip = computed(() => {
|
||||||
|
return getDeleteTip();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
:deep(.ms-modal-form .arco-modal-body) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,180 @@
|
||||||
|
<template>
|
||||||
|
<MsDialog
|
||||||
|
v-model:visible="isVisible"
|
||||||
|
dialog-size="small"
|
||||||
|
:title="t('testPlan.testPlanIndex.batchEdit', { number: props.batchParams.currentSelectCount })"
|
||||||
|
ok-text="common.update"
|
||||||
|
:confirm="confirmHandler"
|
||||||
|
:close="closeHandler"
|
||||||
|
unmount-on-close
|
||||||
|
:switch-props="{
|
||||||
|
switchName: t('caseManagement.featureCase.appendTag'),
|
||||||
|
switchTooltip: t('caseManagement.featureCase.enableTags'),
|
||||||
|
showSwitch: form.selectedAttrsId === 'tags' ? true : false,
|
||||||
|
enable: form.append,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="form">
|
||||||
|
<a-form ref="formRef" class="rounded-[4px]" :model="form" layout="vertical">
|
||||||
|
<a-form-item
|
||||||
|
field="selectedAttrsId"
|
||||||
|
:label="t('apiTestManagement.chooseAttr')"
|
||||||
|
:rules="[{ required: true, message: t('apiTestManagement.attrRequired') }]"
|
||||||
|
asterisk-position="end"
|
||||||
|
>
|
||||||
|
<a-select v-model="form.selectedAttrsId" :placeholder="t('common.pleaseSelect')">
|
||||||
|
<a-option v-for="item of attrOptions" :key="item.value" :value="item.value">
|
||||||
|
{{ t(item.name) }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-if="form.selectedAttrsId === 'tags'"
|
||||||
|
field="values"
|
||||||
|
:label="t('apiTestManagement.batchUpdate')"
|
||||||
|
:validate-trigger="['blur', 'input']"
|
||||||
|
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
||||||
|
asterisk-position="end"
|
||||||
|
class="mb-0"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<MsTagsInput
|
||||||
|
v-model:model-value="form.tags"
|
||||||
|
placeholder="common.tagsInputPlaceholder"
|
||||||
|
allow-clear
|
||||||
|
unique-value
|
||||||
|
retain-input-value
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-else
|
||||||
|
field="value"
|
||||||
|
:label="t('apiTestManagement.batchUpdate')"
|
||||||
|
:rules="[{ required: true, message: t('apiTestManagement.valueRequired') }]"
|
||||||
|
asterisk-position="end"
|
||||||
|
class="mb-0"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="form.value"
|
||||||
|
:placeholder="t('common.pleaseSelect')"
|
||||||
|
:disabled="form.selectedAttrsId === ''"
|
||||||
|
>
|
||||||
|
<a-option v-for="item of valueOptions" :key="item.value" :value="item.value">
|
||||||
|
{{ t(item.label) }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</MsDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import MsDialog from '@/components/pure/ms-dialog/index.vue';
|
||||||
|
import type { BatchActionQueryParams } from '@/components/pure/ms-table/type';
|
||||||
|
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import { TableQueryParams } from '@/models/common';
|
||||||
|
|
||||||
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
|
const isVisible = ref<boolean>(false);
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
batchParams: BatchActionQueryParams;
|
||||||
|
activeFolder: string;
|
||||||
|
offspringIds: string[];
|
||||||
|
condition?: TableQueryParams;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
(e: 'success'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
const initForm = {
|
||||||
|
selectedAttrsId: '',
|
||||||
|
append: false,
|
||||||
|
tags: [],
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
const form = ref({ ...initForm });
|
||||||
|
|
||||||
|
const attrOptions = [
|
||||||
|
{
|
||||||
|
name: 'common.tag',
|
||||||
|
value: 'tags',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance | null>(null);
|
||||||
|
|
||||||
|
function closeHandler() {
|
||||||
|
isVisible.value = false;
|
||||||
|
formRef.value?.resetFields();
|
||||||
|
form.value = { ...initForm };
|
||||||
|
form.value.tags = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function confirmHandler(enable: boolean | undefined) {
|
||||||
|
await formRef.value?.validate().then(async (error) => {
|
||||||
|
if (!error) {
|
||||||
|
try {
|
||||||
|
const customField = {
|
||||||
|
fieldId: '',
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
const { selectedIds, selectAll, excludeIds } = props.batchParams;
|
||||||
|
const params: TableQueryParams = {
|
||||||
|
selectIds: selectedIds || [],
|
||||||
|
selectAll: !!selectAll,
|
||||||
|
excludeIds: excludeIds || [],
|
||||||
|
projectId: currentProjectId.value,
|
||||||
|
append: enable as boolean,
|
||||||
|
tags: form.value.tags,
|
||||||
|
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
|
||||||
|
customField: form.value.selectedAttrsId === 'systemTags' ? {} : customField,
|
||||||
|
condition: {
|
||||||
|
...props.condition,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Message.success(t('caseManagement.featureCase.editSuccess'));
|
||||||
|
closeHandler();
|
||||||
|
emits('success');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueOptions = ref<{ value: string; label: string }[]>([]);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => isVisible.value,
|
||||||
|
(val) => {
|
||||||
|
emits('update:visible', val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(val) => {
|
||||||
|
isVisible.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -10,31 +10,47 @@
|
||||||
@refresh="fetchData"
|
@refresh="fetchData"
|
||||||
>
|
>
|
||||||
<template #left>
|
<template #left>
|
||||||
<a-radio-group v-model="showType" type="button" class="file-show-type mr-2">
|
<!-- TODO 这个版本不上 -->
|
||||||
|
<!-- <a-radio-group v-model="showType" type="button" class="file-show-type mr-2">
|
||||||
<a-radio :value="testPlanTypeEnum.ALL" class="show-type-icon p-[2px]">{{
|
<a-radio :value="testPlanTypeEnum.ALL" class="show-type-icon p-[2px]">{{
|
||||||
t('testPlan.testPlanIndex.all')
|
t('testPlan.testPlanIndex.all')
|
||||||
}}</a-radio>
|
}}</a-radio>
|
||||||
<a-radio :value="testPlanTypeEnum.TEST_PLAN" class="show-type-icon p-[2px]">{{
|
<a-radio :value="testPlanTypeEnum.TEST_PLAN" class="show-type-icon p-[2px]">{{
|
||||||
t('testPlan.testPlanIndex.testPlan')
|
t('testPlan.testPlanIndex.testPlan')
|
||||||
}}</a-radio>
|
}}</a-radio>
|
||||||
<!-- <a-radio value="testPlanGroup" class="show-type-icon p-[2px]">{{
|
<a-radio value="testPlanGroup" class="show-type-icon p-[2px]">{{
|
||||||
t('testPlan.testPlanIndex.testPlanGroup')
|
t('testPlan.testPlanIndex.testPlanGroup')
|
||||||
}}</a-radio> -->
|
}}</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group> -->
|
||||||
|
<a-popover title="" position="bottom">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="one-line-text mr-1 max-h-[32px] max-w-[116px] text-[var(--color-text-1)]">
|
||||||
|
{{ props.activeFolder === 'all' ? t('testPlan.testPlanIndex.allTestPlan') : props.nodeName }}
|
||||||
|
</div>
|
||||||
|
<span class="text-[var(--color-text-4)]"> ({{ props.modulesCount[props.activeFolder] || 0 }})</span>
|
||||||
|
</div>
|
||||||
|
<template #content>
|
||||||
|
<div class="max-w-[400px] text-[14px] font-medium text-[var(--color-text-1)]">
|
||||||
|
{{ props.nodeName }}
|
||||||
|
<span class="text-[var(--color-text-4)]">({{ props.modulesCount[props.activeFolder] || 0 }})</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
</MsAdvanceFilter>
|
</MsAdvanceFilter>
|
||||||
<MsBaseTable
|
<MsBaseTable
|
||||||
v-bind="propsRes"
|
v-bind="propsRes"
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
:action-config="tableBatchActions"
|
:action-config="testPlanBatchActions"
|
||||||
:expanded-keys="expandedKeys"
|
|
||||||
filter-icon-align-left
|
filter-icon-align-left
|
||||||
v-on="propsEvent"
|
v-on="propsEvent"
|
||||||
@batch-action="handleTableBatch"
|
@batch-action="handleTableBatch"
|
||||||
>
|
>
|
||||||
|
<!-- :expanded-keys="expandedKeys" -->
|
||||||
<template #num="{ record }">
|
<template #num="{ record }">
|
||||||
<div class="flex items-center">
|
<!-- TODO 这个版本不做 -->
|
||||||
|
<!-- <div class="flex items-center">
|
||||||
<div v-if="record.childrenCount" class="mr-2 flex items-center" @click="expandHandler(record)">
|
<div v-if="record.childrenCount" class="mr-2 flex items-center" @click="expandHandler(record)">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
type="icon-icon_split-turn-down-left"
|
type="icon-icon_split-turn-down-left"
|
||||||
|
@ -56,17 +72,30 @@
|
||||||
<div>
|
<div>
|
||||||
<div>{{ t('testPlan.testPlanIndex.scheduledTaskOpened') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.scheduledTaskOpened') }}</div>
|
||||||
<div>{{ t('testPlan.testPlanIndex.nextExecutionTime') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.nextExecutionTime') }}</div>
|
||||||
<!-- TODO 缺少字段 -->
|
|
||||||
<div>---</div>
|
<div>---</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- TODO 缺少字段 -->
|
<div> {{ t('testPlan.testPlanIndex.scheduledTaskUnEnable') }} </div>
|
||||||
<!-- <div> {{ t('testPlan.testPlanIndex.scheduledTaskUnEnable') }} </div> -->
|
|
||||||
</template>
|
</template>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
</div> -->
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="one-line-text cursor-pointer text-[rgb(var(--primary-5))]">{{ record.num }}</div>
|
||||||
|
<a-tooltip position="right" :disabled="!record.schedule" :mouse-enter-delay="300">
|
||||||
|
<MsTag v-if="record.schedule" size="small" type="link" theme="outline" class="ml-2">{{
|
||||||
|
t('testPlan.testPlanIndex.timing')
|
||||||
|
}}</MsTag>
|
||||||
|
<template #content>
|
||||||
|
<div>
|
||||||
|
<div>{{ t('testPlan.testPlanIndex.scheduledTaskOpened') }}</div>
|
||||||
|
<div>{{ t('testPlan.testPlanIndex.nextExecutionTime') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div> {{ t('testPlan.testPlanIndex.scheduledTaskUnEnable') }} </div>
|
||||||
|
</template>
|
||||||
|
</a-tooltip></div
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
<template #statusFilter="{ columnConfig }">
|
<template #statusFilter="{ columnConfig }">
|
||||||
<a-trigger v-model:popup-visible="statusFilterVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
<a-trigger v-model:popup-visible="statusFilterVisible" @popup-visible-change="handleFilterHidden">
|
||||||
<a-button type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
|
<a-button type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true">
|
||||||
{{ t(columnConfig.title as string) }}
|
{{ t(columnConfig.title as string) }}
|
||||||
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
@ -75,13 +104,13 @@
|
||||||
<div class="arco-table-filters-content">
|
<div class="arco-table-filters-content">
|
||||||
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
|
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
|
||||||
<a-checkbox v-for="key of Object.keys(reviewStatusMap)" :key="key" :value="key">
|
<a-checkbox v-for="key of Object.keys(planStatusMap)" :key="key" :value="key">
|
||||||
<a-tag
|
<a-tag
|
||||||
:color="reviewStatusMap[key as ReviewStatus].color"
|
:color="planStatusMap[key as planStatusType].color"
|
||||||
:class="[reviewStatusMap[key as ReviewStatus].class, 'px-[4px]']"
|
:class="[planStatusMap[key as planStatusType].class, 'px-[4px]']"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
{{ t(reviewStatusMap[key as ReviewStatus].label) }}
|
{{ t(planStatusMap[key as planStatusType].label) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
|
@ -103,38 +132,33 @@
|
||||||
<statusTag :status="record.status" />
|
<statusTag :status="record.status" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #passRate="{ record }">
|
<!-- <template #passRate="{ record }">
|
||||||
<div class="mr-[8px] w-[100px]">
|
<div class="mr-[8px] w-[100px]">
|
||||||
<StatusProgress :status-detail="record.statusDetail" height="5px" />
|
<StatusProgress :status-detail="record.statusDetail" height="5px" />
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[var(--color-text-1)]">
|
<div class="text-[var(--color-text-1)]">
|
||||||
{{ `${record.passRate || 0}%` }}
|
{{ `${record.passRate || 0}%` }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template> -->
|
||||||
<template #passRateTitleSlot="{ columnConfig }">
|
<template #passRateTitleSlot="{ columnConfig }">
|
||||||
<div class="flex items-center text-[var(--color-text-3)]">
|
<div class="flex items-center text-[var(--color-text-3)]">
|
||||||
{{ t(columnConfig.title as string) }}
|
{{ t(columnConfig.title as string) }}
|
||||||
<a-tooltip position="right">
|
<a-tooltip position="right" :content="t('testPlan.testPlanIndex.passRateTitleTip')">
|
||||||
<icon-question-circle
|
<icon-question-circle
|
||||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||||
size="16"
|
size="16"
|
||||||
/>
|
/>
|
||||||
<template #content>
|
|
||||||
<!-- TODO 需要提供文案 -->
|
|
||||||
<!-- <div>{{ t('apiTestDebug.encodeTip1') }}</div>
|
|
||||||
<div>{{ t('apiTestDebug.encodeTip2') }}</div> -->
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #useCount="{ record }">
|
<!-- <template #useCount="{ record }">
|
||||||
<a-popover position="bottom" content-class="p-[16px]" trigger="click">
|
<a-popover position="bottom" content-class="p-[16px]" trigger="click">
|
||||||
<div>{{ record.useCaseCount.caseCount }}</div>
|
<div>{{ record.useCaseCount.caseCount }}</div>
|
||||||
<template #content>
|
<template #content>
|
||||||
<table class="min-w-[144px]">
|
<table class="min-w-[144px]">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div>{{ t('project.testPlanIndex.TotalCases') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.TotalCases') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ record.useCaseCount.caseCount }}
|
{{ record.useCaseCount.caseCount }}
|
||||||
|
@ -142,7 +166,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('project.testPlanIndex.functionalUseCase') }}</div>
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.functionalUseCase') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ record.useCaseCount.caseCount }}
|
{{ record.useCaseCount.caseCount }}
|
||||||
|
@ -150,7 +174,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('project.testPlanIndex.apiCase') }}</div>
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiCase') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ record.useCaseCount.caseCount }}
|
{{ record.useCaseCount.caseCount }}
|
||||||
|
@ -158,7 +182,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('project.testPlanIndex.apiScenarioCase') }}</div>
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiScenarioCase') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ record.useCaseCount.caseCount }}
|
{{ record.useCaseCount.caseCount }}
|
||||||
|
@ -167,7 +191,7 @@
|
||||||
</table>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template> -->
|
||||||
|
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
@ -218,37 +242,51 @@
|
||||||
@save="handleMoveOrCopy"
|
@save="handleMoveOrCopy"
|
||||||
/>
|
/>
|
||||||
<ScheduledModal v-model:visible="showScheduledTaskModal" />
|
<ScheduledModal v-model:visible="showScheduledTaskModal" />
|
||||||
|
<ActionModal v-model:visible="showStatusDeleteModal" :record="activeRecord" />
|
||||||
|
<BatchEditModal
|
||||||
|
v-model:visible="showEditModel"
|
||||||
|
:batch-params="batchParams"
|
||||||
|
:active-folder="props.activeFolder"
|
||||||
|
:offspring-ids="props.offspringIds"
|
||||||
|
:condition="conditionParams"
|
||||||
|
@success="successHandler"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
||||||
import { FilterFormItem } from '@/components/pure/ms-advance-filter/type';
|
import { FilterFormItem } from '@/components/pure/ms-advance-filter/type';
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/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 MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
import ActionModal from './actionModal.vue';
|
||||||
|
import BatchEditModal from './batchEditModal.vue';
|
||||||
import BatchMoveOrCopy from './batchMoveOrCopy.vue';
|
import BatchMoveOrCopy from './batchMoveOrCopy.vue';
|
||||||
import ScheduledModal from './scheduledModal.vue';
|
import ScheduledModal from './scheduledModal.vue';
|
||||||
import StatusProgress from './statusProgress.vue';
|
import StatusProgress from './statusProgress.vue';
|
||||||
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
||||||
|
|
||||||
import { getTestPlanList, getTestPlanModule } from '@/api/modules/test-plan/testPlan';
|
import { getTestPlanList, getTestPlanModule } from '@/api/modules/test-plan/testPlan';
|
||||||
import { reviewStatusMap } from '@/config/caseManagement';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import { ReviewStatus } from '@/models/caseManagement/caseReview';
|
import { ReviewStatus } from '@/models/caseManagement/caseReview';
|
||||||
|
import type { planStatusType, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||||
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
|
||||||
|
|
||||||
|
import { planStatusMap } from '../config';
|
||||||
|
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -259,6 +297,7 @@
|
||||||
activeFolderType: 'folder' | 'module';
|
activeFolderType: 'folder' | 'module';
|
||||||
offspringIds: string[]; // 当前选中文件夹的所有子孙节点id
|
offspringIds: string[]; // 当前选中文件夹的所有子孙节点id
|
||||||
modulesCount: Record<string, number>; // 模块数量
|
modulesCount: Record<string, number>; // 模块数量
|
||||||
|
nodeName: string; // 选中模块名称
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -413,13 +452,20 @@
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
const statusFilterVisible = ref(false);
|
const statusFilterVisible = ref(false);
|
||||||
const statusFilters = ref<string[]>([]);
|
const statusFilters = ref<string[]>([]);
|
||||||
|
const showType = ref<keyof typeof testPlanTypeEnum>(testPlanTypeEnum.TEST_PLAN);
|
||||||
|
|
||||||
const tableBatchActions = {
|
const testPlanBatchActions = {
|
||||||
baseAction: [
|
baseAction: [
|
||||||
|
// TODO 批量执行不上这个版本
|
||||||
|
// {
|
||||||
|
// label: 'testPlan.testPlanIndex.execute',
|
||||||
|
// eventTag: 'execute',
|
||||||
|
// permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
label: 'testPlan.testPlanIndex.execute',
|
label: 'common.edit',
|
||||||
eventTag: 'execute',
|
eventTag: 'edit',
|
||||||
permission: ['PROJECT_TEST_PLAN:READ+EXECUTE'],
|
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'common.copy',
|
label: 'common.copy',
|
||||||
|
@ -430,23 +476,23 @@
|
||||||
// label: 'common.export',
|
// label: 'common.export',
|
||||||
// eventTag: 'export',
|
// eventTag: 'export',
|
||||||
// },
|
// },
|
||||||
|
],
|
||||||
|
moreAction: [
|
||||||
|
// {
|
||||||
|
// label: 'testPlan.testPlanIndex.openTimingTask',
|
||||||
|
// eventTag: 'openTimingTask',
|
||||||
|
// permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: 'testPlan.testPlanIndex.closeTimingTask',
|
||||||
|
// eventTag: 'closeTimingTask',
|
||||||
|
// permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
label: 'common.move',
|
label: 'common.move',
|
||||||
eventTag: 'move',
|
eventTag: 'move',
|
||||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
||||||
},
|
},
|
||||||
],
|
|
||||||
moreAction: [
|
|
||||||
{
|
|
||||||
label: 'testPlan.testPlanIndex.openTimingTask',
|
|
||||||
eventTag: 'openTimingTask',
|
|
||||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'testPlan.testPlanIndex.closeTimingTask',
|
|
||||||
eventTag: 'closeTimingTask',
|
|
||||||
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'common.archive',
|
label: 'common.archive',
|
||||||
eventTag: 'archive',
|
eventTag: 'archive',
|
||||||
|
@ -469,14 +515,15 @@
|
||||||
label: 'common.copy',
|
label: 'common.copy',
|
||||||
eventTag: 'copy',
|
eventTag: 'copy',
|
||||||
},
|
},
|
||||||
{
|
// TODO 这个版本不上
|
||||||
label: 'testPlan.testPlanIndex.createScheduledTask',
|
// {
|
||||||
eventTag: 'createScheduledTask',
|
// label: 'testPlan.testPlanIndex.createScheduledTask',
|
||||||
},
|
// eventTag: 'createScheduledTask',
|
||||||
{
|
// },
|
||||||
label: 'testPlan.testPlanIndex.configuration',
|
// {
|
||||||
eventTag: 'config',
|
// label: 'testPlan.testPlanIndex.configuration',
|
||||||
},
|
// eventTag: 'config',
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
label: 'common.archive',
|
label: 'common.archive',
|
||||||
eventTag: 'archive',
|
eventTag: 'archive',
|
||||||
|
@ -497,7 +544,7 @@
|
||||||
projectId: 'string',
|
projectId: 'string',
|
||||||
num: '100944',
|
num: '100944',
|
||||||
name: '系统示例',
|
name: '系统示例',
|
||||||
status: 'PREPARED',
|
status: 'COMPLETED',
|
||||||
tags: ['string'],
|
tags: ['string'],
|
||||||
schedule: 'string',
|
schedule: 'string',
|
||||||
createUser: 'string',
|
createUser: 'string',
|
||||||
|
@ -522,74 +569,74 @@
|
||||||
apiCount: 3,
|
apiCount: 3,
|
||||||
scenarioCount: 3,
|
scenarioCount: 3,
|
||||||
},
|
},
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
id: '100945',
|
// id: '100945',
|
||||||
projectId: 'string',
|
// projectId: 'string',
|
||||||
num: '100945',
|
// num: '100945',
|
||||||
name: '系统示例',
|
// name: '系统示例',
|
||||||
status: 'COMPLETED',
|
// status: 'COMPLETED',
|
||||||
tags: ['string'],
|
// tags: ['string'],
|
||||||
schedule: 'string',
|
// schedule: 'string',
|
||||||
createUser: 'string',
|
// createUser: 'string',
|
||||||
createTime: 'string',
|
// createTime: 'string',
|
||||||
moduleName: 'string',
|
// moduleName: 'string',
|
||||||
moduleId: 'string',
|
// moduleId: 'string',
|
||||||
testPlanItem: [],
|
// testPlanItem: [],
|
||||||
testPlanGroupId: 'string',
|
// testPlanGroupId: 'string',
|
||||||
passCount: 0,
|
// passCount: 0,
|
||||||
unPassCount: 0,
|
// unPassCount: 0,
|
||||||
reviewedCount: 0,
|
// reviewedCount: 0,
|
||||||
underReviewedCount: 0,
|
// underReviewedCount: 0,
|
||||||
childrenCount: 0,
|
// childrenCount: 0,
|
||||||
useCaseCount: {
|
// useCaseCount: {
|
||||||
caseCount: 3,
|
// caseCount: 3,
|
||||||
apiCount: 3,
|
// apiCount: 3,
|
||||||
scenarioCount: 3,
|
// scenarioCount: 3,
|
||||||
},
|
// },
|
||||||
statusDetail: {
|
// statusDetail: {
|
||||||
tolerance: 100,
|
// tolerance: 100,
|
||||||
UNPENDING: 100,
|
// UNPENDING: 100,
|
||||||
RUNNING: 30,
|
// RUNNING: 30,
|
||||||
SUCCESS: 30,
|
// SUCCESS: 30,
|
||||||
ERROR: 30,
|
// ERROR: 30,
|
||||||
executionProgress: '100%',
|
// executionProgress: '100%',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
id: '100955',
|
// id: '100955',
|
||||||
projectId: 'string',
|
// projectId: 'string',
|
||||||
num: '100955',
|
// num: '100955',
|
||||||
name: '系统示例',
|
// name: '系统示例',
|
||||||
status: 'COMPLETED',
|
// status: 'COMPLETED',
|
||||||
tags: ['string'],
|
// tags: ['string'],
|
||||||
schedule: 'string',
|
// schedule: 'string',
|
||||||
createUser: 'string',
|
// createUser: 'string',
|
||||||
createTime: 'string',
|
// createTime: 'string',
|
||||||
moduleName: 'string',
|
// moduleName: 'string',
|
||||||
moduleId: 'string',
|
// moduleId: 'string',
|
||||||
testPlanItem: [],
|
// testPlanItem: [],
|
||||||
testPlanGroupId: 'string',
|
// testPlanGroupId: 'string',
|
||||||
passCount: 0,
|
// passCount: 0,
|
||||||
unPassCount: 0,
|
// unPassCount: 0,
|
||||||
reviewedCount: 0,
|
// reviewedCount: 0,
|
||||||
underReviewedCount: 0,
|
// underReviewedCount: 0,
|
||||||
childrenCount: 0,
|
// childrenCount: 0,
|
||||||
useCaseCount: {
|
// useCaseCount: {
|
||||||
caseCount: 3,
|
// caseCount: 3,
|
||||||
apiCount: 3,
|
// apiCount: 3,
|
||||||
scenarioCount: 3,
|
// scenarioCount: 3,
|
||||||
},
|
// },
|
||||||
statusDetail: {
|
// statusDetail: {
|
||||||
tolerance: 100,
|
// tolerance: 100,
|
||||||
UNPENDING: 100,
|
// UNPENDING: 100,
|
||||||
RUNNING: 30,
|
// RUNNING: 30,
|
||||||
SUCCESS: 30,
|
// SUCCESS: 30,
|
||||||
ERROR: 30,
|
// ERROR: 30,
|
||||||
executionProgress: '100%',
|
// executionProgress: '100%',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -623,8 +670,6 @@
|
||||||
combine: {},
|
combine: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const showType = ref<keyof typeof testPlanTypeEnum>('ALL');
|
|
||||||
|
|
||||||
async function initTableParams() {
|
async function initTableParams() {
|
||||||
conditionParams.value = {
|
conditionParams.value = {
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
|
@ -740,7 +785,7 @@
|
||||||
title: t('testPlan.testPlanIndex.confirmBatchArchivePlan', {
|
title: t('testPlan.testPlanIndex.confirmBatchArchivePlan', {
|
||||||
count: batchParams.value.currentSelectCount,
|
count: batchParams.value.currentSelectCount,
|
||||||
}),
|
}),
|
||||||
content: t('testPlan.testPlanIndex.confirmBatchDeletePlanContentTip'),
|
content: t('testPlan.testPlanIndex.confirmBatchArchivePlanContent'),
|
||||||
okText: t('common.archive'),
|
okText: t('common.archive'),
|
||||||
cancelText: t('common.cancel'),
|
cancelText: t('common.cancel'),
|
||||||
okButtonProps: {
|
okButtonProps: {
|
||||||
|
@ -749,7 +794,7 @@
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
const { selectedIds, selectAll, excludeIds } = batchParams.value;
|
const { selectedIds, selectAll, excludeIds } = batchParams.value;
|
||||||
Message.success(t('common.deleteSuccess'));
|
Message.success(t('common.batchArchiveSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -759,7 +804,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 归档
|
* 删除
|
||||||
*/
|
*/
|
||||||
function handleDelete() {
|
function handleDelete() {
|
||||||
openModal({
|
openModal({
|
||||||
|
@ -767,7 +812,7 @@
|
||||||
title: t('testPlan.testPlanIndex.confirmBatchDeletePlan', {
|
title: t('testPlan.testPlanIndex.confirmBatchDeletePlan', {
|
||||||
count: batchParams.value.currentSelectCount,
|
count: batchParams.value.currentSelectCount,
|
||||||
}),
|
}),
|
||||||
content: t('testPlan.testPlanIndex.confirmBatchDeletePlanContentTip'),
|
content: t('testPlan.testPlanIndex.confirmBatchDeletePlanContent'),
|
||||||
okText: t('common.confirmDelete'),
|
okText: t('common.confirmDelete'),
|
||||||
cancelText: t('common.cancel'),
|
cancelText: t('common.cancel'),
|
||||||
okButtonProps: {
|
okButtonProps: {
|
||||||
|
@ -786,6 +831,19 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量编辑
|
||||||
|
*/
|
||||||
|
const showEditModel = ref<boolean>(false);
|
||||||
|
|
||||||
|
function handleEdit() {
|
||||||
|
showEditModel.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function successHandler() {
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量操作
|
* 批量操作
|
||||||
*/
|
*/
|
||||||
|
@ -813,6 +871,9 @@
|
||||||
case 'delete':
|
case 'delete':
|
||||||
handleDelete();
|
handleDelete();
|
||||||
break;
|
break;
|
||||||
|
case 'edit':
|
||||||
|
handleEdit();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -828,7 +889,36 @@
|
||||||
showScheduledTaskModal.value = true;
|
showScheduledTaskModal.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMoreActionSelect(item: ActionsItem, record: any) {
|
const showStatusDeleteModal = ref<boolean>(false);
|
||||||
|
const activeRecord = ref<TestPlanItem>();
|
||||||
|
function deleteStatusHandler(record: TestPlanItem) {
|
||||||
|
activeRecord.value = cloneDeep(record);
|
||||||
|
showStatusDeleteModal.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function archiveHandle(record: TestPlanItem) {
|
||||||
|
openModal({
|
||||||
|
type: 'warning',
|
||||||
|
title: t('common.archiveConfirmTitle', { name: characterLimit(record.name) }),
|
||||||
|
content: t('testPlan.testPlanIndex.confirmArchivePlan'),
|
||||||
|
okText: t('common.archive'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'normal',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
Message.success(t('common.batchArchiveSuccess'));
|
||||||
|
fetchData();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMoreActionSelect(item: ActionsItem, record: TestPlanItem) {
|
||||||
switch (item.eventTag) {
|
switch (item.eventTag) {
|
||||||
case 'copy':
|
case 'copy':
|
||||||
copyHandler();
|
copyHandler();
|
||||||
|
@ -836,6 +926,12 @@
|
||||||
case 'createScheduledTask':
|
case 'createScheduledTask':
|
||||||
handleScheduledTask();
|
handleScheduledTask();
|
||||||
break;
|
break;
|
||||||
|
case 'delete':
|
||||||
|
deleteStatusHandler(record);
|
||||||
|
break;
|
||||||
|
case 'archive':
|
||||||
|
archiveHandle(record);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -843,17 +939,18 @@
|
||||||
|
|
||||||
const expandedKeys = ref<string[]>([]);
|
const expandedKeys = ref<string[]>([]);
|
||||||
|
|
||||||
function expandHandler(record: any) {
|
// TODO先不做展开折叠
|
||||||
if (expandedKeys.value.includes(record.id)) {
|
// function expandHandler(record: any) {
|
||||||
expandedKeys.value = expandedKeys.value.filter((key) => key !== record.id);
|
// if (expandedKeys.value.includes(record.id)) {
|
||||||
} else {
|
// expandedKeys.value = expandedKeys.value.filter((key) => key !== record.id);
|
||||||
expandedKeys.value = [...expandedKeys.value, record.id];
|
// } else {
|
||||||
}
|
// expandedKeys.value = [...expandedKeys.value, record.id];
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
function getIconClass(record: any) {
|
// TODO先不做展开折叠
|
||||||
return expandedKeys.value.includes(record.id) ? 'text-[rgb(var(--primary-5))]' : 'text-[var(--color-text-4)]';
|
// function getIconClass(record: any) {
|
||||||
}
|
// return expandedKeys.value.includes(record.id) ? 'text-[rgb(var(--primary-5))]' : 'text-[var(--color-text-4)]';
|
||||||
|
// }
|
||||||
|
|
||||||
function handleFilterHidden(val: boolean) {
|
function handleFilterHidden(val: boolean) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
|
@ -893,11 +990,6 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO 临时数据模拟
|
|
||||||
// onMounted(() => {
|
|
||||||
// setProps({ data });
|
|
||||||
// });
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
});
|
});
|
||||||
|
@ -906,18 +998,16 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
:deep(.arco-table-cell-expand-icon .arco-table-cell-inline-icon) {
|
// TODO先不做展开折叠
|
||||||
display: none;
|
// :deep(.arco-table-cell-expand-icon .arco-table-cell-inline-icon) {
|
||||||
}
|
// display: none;
|
||||||
:deep(.arco-table-cell-align-left) > span:first-child {
|
// }
|
||||||
padding-left: 0 !important;
|
// :deep(.arco-table-cell-align-left) > span:first-child {
|
||||||
}
|
// padding-left: 0 !important;
|
||||||
.arrowIcon {
|
// }
|
||||||
transform: scaleX(-1);
|
// .arrowIcon {
|
||||||
}
|
// transform: scaleX(-1);
|
||||||
:deep(.ms-modal-form .arco-modal-body) {
|
// }
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.popover-label-td {
|
.popover-label-td {
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="mb-[6px] mt-[4px] p-[3px_8px]">
|
<div class="mb-[6px] mt-[4px] p-[3px_8px]">
|
||||||
<MsButton type="text" class="text-[rgb(var(--primary-5))]" @click="createCustomFrequency">
|
<MsButton type="text" class="text-[rgb(var(--primary-5))]" @click="createCustomFrequency">
|
||||||
{{ t('project.testPlanIndex.customFrequency') }}
|
{{ t('testPlan.testPlanIndex.customFrequency') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,14 +28,14 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-radio-group v-model="form.env" class="mb-4">
|
<a-radio-group v-model="form.env" class="mb-4">
|
||||||
<a-radio value="">
|
<a-radio value="">
|
||||||
{{ t('project.testPlanIndex.defaultEnv') }}
|
{{ t('testPlan.testPlanIndex.defaultEnv') }}
|
||||||
<span class="float-right mx-1 mt-[1px]">
|
<span class="float-right mx-1 mt-[1px]">
|
||||||
<a-tooltip :content="t('testPlan.testPlanIndex.envTip')" position="top">
|
<a-tooltip :content="t('testPlan.testPlanIndex.envTip')" position="top">
|
||||||
<IconQuestionCircle class="h-[16px] w-[16px] text-[--color-text-4] hover:text-[rgb(var(--primary-5))]"
|
<IconQuestionCircle class="h-[16px] w-[16px] text-[--color-text-4] hover:text-[rgb(var(--primary-5))]"
|
||||||
/></a-tooltip>
|
/></a-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</a-radio>
|
</a-radio>
|
||||||
<a-radio value="new"> {{ t('project.testPlanIndex.newEnv') }}</a-radio>
|
<a-radio value="new"> {{ t('testPlan.testPlanIndex.newEnv') }}</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<a-radio-group v-model="form.methods">
|
<a-radio-group v-model="form.methods">
|
||||||
<a-radio value="serial">{{ t('testPlan.testPlanIndex.serial') }}</a-radio>
|
<a-radio value="serial">{{ t('testPlan.testPlanIndex.serial') }}</a-radio>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
<span class="text-[var(--color-text-4)]">CPU</span>
|
<span class="text-[var(--color-text-4)]">CPU</span>
|
||||||
<span class="mx-2"> {{ item.cpuRate }}</span>
|
<span class="mx-2"> {{ item.cpuRate }}</span>
|
||||||
<MsTag theme="outline" :type="item.status ? 'link' : 'success'" size="small">
|
<MsTag theme="outline" :type="item.status ? 'link' : 'success'" size="small">
|
||||||
{{ item.status ? t('project.testPlanIndex.doing') : t('project.testPlanIndex.inFreeTime') }}
|
{{ item.status ? t('testPlan.testPlanIndex.doing') : t('testPlan.testPlanIndex.inFreeTime') }}
|
||||||
</MsTag>
|
</MsTag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<table class="min-w-[144px]">
|
<table class="min-w-[144px]">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div>{{ t('project.testPlanIndex.tolerance') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.tolerance') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ props.statusDetail.tolerance }}
|
{{ props.statusDetail.tolerance }}
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
<div>{{ t('project.testPlanIndex.executionProgress') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.executionProgress') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td">
|
<td class="popover-value-td">
|
||||||
{{ props.statusDetail.executionProgress }}
|
{{ props.statusDetail.executionProgress }}
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
modulesCount?: Record<string, number>; // 模块数量统计对象
|
modulesCount?: Record<string, number>; // 模块数量统计对象
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emits = defineEmits(['update:selectedKeys', 'planTreeNodeSelect', 'init', 'dragUpdate']);
|
const emits = defineEmits(['update:selectedKeys', 'planTreeNodeSelect', 'init', 'dragUpdate', 'getNodeName']);
|
||||||
|
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@
|
||||||
offspringIds.push(e.id);
|
offspringIds.push(e.id);
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
emits('planTreeNodeSelect', selectedKeys, offspringIds);
|
emits('planTreeNodeSelect', selectedKeys, offspringIds, node.name);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 用例树节点更多事件
|
// 用例树节点更多事件
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import type { planStatusType } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
|
export type PlanStatusMap = Record<
|
||||||
|
planStatusType,
|
||||||
|
{
|
||||||
|
label: string;
|
||||||
|
color: string;
|
||||||
|
class: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
export const planStatusMap: PlanStatusMap = {
|
||||||
|
PREPARED: {
|
||||||
|
label: 'caseManagement.caseReview.unStart',
|
||||||
|
color: 'var(--color-text-n8)',
|
||||||
|
class: '!text-[var(--color-text-1)]',
|
||||||
|
},
|
||||||
|
UNDERWAY: {
|
||||||
|
label: 'caseManagement.caseReview.going',
|
||||||
|
color: 'rgb(var(--link-2))',
|
||||||
|
class: '!text-[rgb(var(--link-6))]',
|
||||||
|
},
|
||||||
|
COMPLETED: {
|
||||||
|
label: 'caseManagement.caseReview.finished',
|
||||||
|
color: 'rgb(var(--success-2))',
|
||||||
|
class: '!text-[rgb(var(--success-6))]',
|
||||||
|
},
|
||||||
|
ARCHIVED: {
|
||||||
|
label: 'caseManagement.caseReview.archived',
|
||||||
|
color: 'var(--color-text-n8)',
|
||||||
|
class: '!text-[var(--color-text-4)]',
|
||||||
|
},
|
||||||
|
};
|
|
@ -82,6 +82,7 @@
|
||||||
:offspring-ids="offspringIds"
|
:offspring-ids="offspringIds"
|
||||||
:active-folder-type="activeCaseType"
|
:active-folder-type="activeCaseType"
|
||||||
:modules-count="modulesCount"
|
:modules-count="modulesCount"
|
||||||
|
:node-name="nodeName"
|
||||||
@init="initModulesCount"
|
@init="initModulesCount"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -177,11 +178,14 @@
|
||||||
const activeCaseType = ref<'folder' | 'module'>('folder'); // 激活计划树类型
|
const activeCaseType = ref<'folder' | 'module'>('folder'); // 激活计划树类型
|
||||||
|
|
||||||
const offspringIds = ref<string[]>([]);
|
const offspringIds = ref<string[]>([]);
|
||||||
|
const nodeName = ref<string>('');
|
||||||
|
|
||||||
// 处理计划树节点选中
|
// 处理计划树节点选中
|
||||||
function planNodeSelect(keys: string[], _offspringIds: string[]) {
|
function planNodeSelect(keys: string[], _offspringIds: string[], moduleName: string) {
|
||||||
[activeFolder.value] = keys;
|
[activeFolder.value] = keys;
|
||||||
activeCaseType.value = 'module';
|
activeCaseType.value = 'module';
|
||||||
offspringIds.value = [..._offspringIds];
|
offspringIds.value = [..._offspringIds];
|
||||||
|
nodeName.value = moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,7 +200,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 右侧表格数据刷新后,若当前展示的是模块,则刷新模块树的统计数量
|
* 刷新模块树的统计数量
|
||||||
*/
|
*/
|
||||||
function initModulesCount(params: any) {}
|
function initModulesCount(params: any) {}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ export default {
|
||||||
'testPlan.testPlanIndex.confirmBatchDeletePlan': 'Are you sure to delete {count} test plans?',
|
'testPlan.testPlanIndex.confirmBatchDeletePlan': 'Are you sure to delete {count} test plans?',
|
||||||
'testPlan.testPlanIndex.confirmBatchDeletePlanContentTip':
|
'testPlan.testPlanIndex.confirmBatchDeletePlanContentTip':
|
||||||
'Only sub-plans within the test plan and plan group are deleted',
|
'Only sub-plans within the test plan and plan group are deleted',
|
||||||
|
'testPlan.testPlanIndex.confirmBatchDeletePlanContent': 'After delete, data unrecoverable, please careful operation.',
|
||||||
'testPlan.testPlanIndex.confirmBatchArchivePlan': 'Are you sure to archive {count} test plans?',
|
'testPlan.testPlanIndex.confirmBatchArchivePlan': 'Are you sure to archive {count} test plans?',
|
||||||
'testPlan.testPlanIndex.confirmBatchArchivePlanContent':
|
'testPlan.testPlanIndex.confirmBatchArchivePlanContent':
|
||||||
'Only completed test plans can be archived! \n after filing, implement information no longer update and editing, data unrecoverable, please careful operation.',
|
'Only completed test plans can be archived! \n after filing, implement information no longer update and editing, data unrecoverable, please careful operation.',
|
||||||
|
@ -49,17 +50,28 @@ export default {
|
||||||
'testPlan.testPlanIndex.timingState': 'Timing state',
|
'testPlan.testPlanIndex.timingState': 'Timing state',
|
||||||
'testPlan.testPlanIndex.timingStateEnable': 'Enable: Executes scheduled tasks',
|
'testPlan.testPlanIndex.timingStateEnable': 'Enable: Executes scheduled tasks',
|
||||||
'testPlan.testPlanIndex.timingStateClose': 'Close: Stops a scheduled task',
|
'testPlan.testPlanIndex.timingStateClose': 'Close: Stops a scheduled task',
|
||||||
'project.testPlanIndex.customFrequency': 'Custom frequency',
|
'testPlan.testPlanIndex.customFrequency': 'Custom frequency',
|
||||||
'project.testPlanIndex.doing': 'Doing',
|
'testPlan.testPlanIndex.doing': 'Doing',
|
||||||
'project.testPlanIndex.inFreeTime': 'In free time',
|
'testPlan.testPlanIndex.inFreeTime': 'In free time',
|
||||||
'project.testPlanIndex.defaultEnv': 'Default Environment',
|
'testPlan.testPlanIndex.defaultEnv': 'Default Environment',
|
||||||
'project.testPlanIndex.newEnv': 'New Environment',
|
'testPlan.testPlanIndex.newEnv': 'New Environment',
|
||||||
'project.testPlanIndex.executionProgress': 'Execution progress',
|
'testPlan.testPlanIndex.executionProgress': 'Execution progress',
|
||||||
'project.testPlanIndex.tolerance': 'tolerance',
|
'testPlan.testPlanIndex.tolerance': 'tolerance',
|
||||||
'project.testPlanIndex.TotalCases': 'Total use cases',
|
'testPlan.testPlanIndex.TotalCases': 'Total use cases',
|
||||||
'project.testPlanIndex.functionalUseCase': 'case',
|
'testPlan.testPlanIndex.functionalUseCase': 'case',
|
||||||
'project.testPlanIndex.apiCase': 'Api use case',
|
'testPlan.testPlanIndex.apiCase': 'Api use case',
|
||||||
'project.testPlanIndex.apiScenarioCase': 'Api scenario use cases',
|
'testPlan.testPlanIndex.apiScenarioCase': 'Api scenario use cases',
|
||||||
|
'testPlan.testPlanIndex.deleteArchivedPlan':
|
||||||
|
'After the program has been archived, delete data unrecoverable, please careful operation.',
|
||||||
|
'testPlan.testPlanIndex.deletePendingPlan':
|
||||||
|
'The plan is not executed, the data cannot be recovered after deletion, please operate carefully!',
|
||||||
|
'testPlan.testPlanIndex.deleteRunningPlan':
|
||||||
|
'Scheduled tasks are stopped and deleted. Exercise caution when performing this operation',
|
||||||
|
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||||
|
'The proposed plan is completed, the option is archived, and the use case information and execution results are retained;If you continue to delete, the data will not be restored, please be careful!',
|
||||||
|
'testPlan.testPlanIndex.confirmArchivePlan':
|
||||||
|
'After filing, implement information no longer update and editing, data unrecoverable, please careful operation!',
|
||||||
|
'testPlan.testPlanIndex.passRateTitleTip': 'Passed use cases/all use cases *100%',
|
||||||
'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan',
|
'testPlan.planForm.namePlaceholder': 'Please enter the name of the test plan',
|
||||||
'testPlan.planForm.nameRequired': 'Test plan name cannot be empty',
|
'testPlan.planForm.nameRequired': 'Test plan name cannot be empty',
|
||||||
'testPlan.planForm.planStartAndEndTime': 'Planned start and end time',
|
'testPlan.planForm.planStartAndEndTime': 'Planned start and end time',
|
||||||
|
|
|
@ -36,9 +36,10 @@ export default {
|
||||||
'testPlan.testPlanIndex.parallel': '并行',
|
'testPlan.testPlanIndex.parallel': '并行',
|
||||||
'testPlan.testPlanIndex.confirmBatchDeletePlan': '确认删除 {count} 个测试计划吗?',
|
'testPlan.testPlanIndex.confirmBatchDeletePlan': '确认删除 {count} 个测试计划吗?',
|
||||||
'testPlan.testPlanIndex.confirmBatchDeletePlanContentTip': '仅删除测试计划和计划组内的子计划',
|
'testPlan.testPlanIndex.confirmBatchDeletePlanContentTip': '仅删除测试计划和计划组内的子计划',
|
||||||
|
'testPlan.testPlanIndex.confirmBatchDeletePlanContent': '删除后,数据不可恢复,请谨慎操作!',
|
||||||
'testPlan.testPlanIndex.confirmBatchArchivePlan': '确认归档 {count} 个测试计划吗?',
|
'testPlan.testPlanIndex.confirmBatchArchivePlan': '确认归档 {count} 个测试计划吗?',
|
||||||
'testPlan.testPlanIndex.confirmBatchArchivePlanContent':
|
'testPlan.testPlanIndex.confirmBatchArchivePlanContent':
|
||||||
'仅 已完成 测试计划可归档!\n 归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
'仅 已完成 测试计划可归档!\r\n 归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
||||||
'testPlan.testPlanIndex.selectedCount': '(已选 {count} 项数据)',
|
'testPlan.testPlanIndex.selectedCount': '(已选 {count} 项数据)',
|
||||||
'testPlan.testPlanIndex.createScheduledTask': '创建定时任务',
|
'testPlan.testPlanIndex.createScheduledTask': '创建定时任务',
|
||||||
'testPlan.testPlanIndex.updateScheduledTask': '更新定时任务',
|
'testPlan.testPlanIndex.updateScheduledTask': '更新定时任务',
|
||||||
|
@ -49,17 +50,26 @@ export default {
|
||||||
'testPlan.testPlanIndex.timingState': '定时状态',
|
'testPlan.testPlanIndex.timingState': '定时状态',
|
||||||
'testPlan.testPlanIndex.timingStateEnable': '开启:执行定时任务',
|
'testPlan.testPlanIndex.timingStateEnable': '开启:执行定时任务',
|
||||||
'testPlan.testPlanIndex.timingStateClose': '关闭:停止定时任务',
|
'testPlan.testPlanIndex.timingStateClose': '关闭:停止定时任务',
|
||||||
'project.testPlanIndex.customFrequency': '自定义频率',
|
'testPlan.testPlanIndex.customFrequency': '自定义频率',
|
||||||
'project.testPlanIndex.doing': '进行中',
|
'testPlan.testPlanIndex.doing': '进行中',
|
||||||
'project.testPlanIndex.inFreeTime': '空闲中',
|
'testPlan.testPlanIndex.inFreeTime': '空闲中',
|
||||||
'project.testPlanIndex.defaultEnv': '默认环境',
|
'testPlan.testPlanIndex.defaultEnv': '默认环境',
|
||||||
'project.testPlanIndex.newEnv': '新环境',
|
'testPlan.testPlanIndex.newEnv': '新环境',
|
||||||
'project.testPlanIndex.executionProgress': '执行进度',
|
'testPlan.testPlanIndex.executionProgress': '执行进度',
|
||||||
'project.testPlanIndex.tolerance': '容错率',
|
'testPlan.testPlanIndex.tolerance': '容错率',
|
||||||
'project.testPlanIndex.TotalCases': '用例总数',
|
'testPlan.testPlanIndex.TotalCases': '用例总数',
|
||||||
'project.testPlanIndex.functionalUseCase': '功能用例',
|
'testPlan.testPlanIndex.functionalUseCase': '功能用例',
|
||||||
'project.testPlanIndex.apiCase': '接口用例',
|
'testPlan.testPlanIndex.apiCase': '接口用例',
|
||||||
'project.testPlanIndex.apiScenarioCase': '接口场景用例',
|
'testPlan.testPlanIndex.apiScenarioCase': '接口场景用例',
|
||||||
|
'testPlan.testPlanIndex.deleteArchivedPlan': '计划 已归档,删除后数据不可恢复,请谨慎操作!',
|
||||||
|
'testPlan.testPlanIndex.deletePendingPlan': '计划 未执行,删除后数据不可恢复,请谨慎操作!',
|
||||||
|
'testPlan.testPlanIndex.deleteRunningPlan':
|
||||||
|
'计划 进行中,删除后,终止执行且不可恢复,定时任务停止并删除,请谨慎操作!',
|
||||||
|
'testPlan.testPlanIndex.deleteCompletedPlan':
|
||||||
|
'建议计划 已完成 ,选择归档,用例信息及执行结果都将被保留;若继续删除,数据将不会恢复,请谨慎操作!',
|
||||||
|
'testPlan.testPlanIndex.confirmArchivePlan': '归档后,执行信息不再更新且不可编辑,数据不可恢复,请谨慎操作!',
|
||||||
|
'testPlan.testPlanIndex.passRateTitleTip': '已通过用例/全部用例*100%',
|
||||||
|
'testPlan.testPlanIndex.batchEdit': '批量编辑 (已选 { number } 项数据)',
|
||||||
'testPlan.planForm.namePlaceholder': '请输入测试计划名称',
|
'testPlan.planForm.namePlaceholder': '请输入测试计划名称',
|
||||||
'testPlan.planForm.nameRequired': '测试计划名称不能为空',
|
'testPlan.planForm.nameRequired': '测试计划名称不能为空',
|
||||||
'testPlan.planForm.planStartAndEndTime': '计划起止时间',
|
'testPlan.planForm.planStartAndEndTime': '计划起止时间',
|
||||||
|
|
Loading…
Reference in New Issue