feat(接口管理): 新增接口用例回收站页面
This commit is contained in:
parent
c5602b2033
commit
045092b13b
|
@ -7,9 +7,11 @@ import {
|
||||||
BatchCleanOutApiUrl,
|
BatchCleanOutApiUrl,
|
||||||
BatchDeleteCaseUrl,
|
BatchDeleteCaseUrl,
|
||||||
BatchDeleteDefinitionUrl,
|
BatchDeleteDefinitionUrl,
|
||||||
|
BatchDeleteRecycleCaseUrl,
|
||||||
BatchEditCaseUrl,
|
BatchEditCaseUrl,
|
||||||
BatchMoveDefinitionUrl,
|
BatchMoveDefinitionUrl,
|
||||||
BatchRecoverApiUrl,
|
BatchRecoverApiUrl,
|
||||||
|
BatchRecoverCaseUrl,
|
||||||
BatchUpdateDefinitionUrl,
|
BatchUpdateDefinitionUrl,
|
||||||
CasePageUrl,
|
CasePageUrl,
|
||||||
CheckDefinitionScheduleUrl,
|
CheckDefinitionScheduleUrl,
|
||||||
|
@ -23,6 +25,7 @@ import {
|
||||||
DeleteMockUrl,
|
DeleteMockUrl,
|
||||||
DeleteModuleUrl,
|
DeleteModuleUrl,
|
||||||
DeleteRecycleApiUrl,
|
DeleteRecycleApiUrl,
|
||||||
|
DeleteRecycleCaseUrl,
|
||||||
GetDefinitionDetailUrl,
|
GetDefinitionDetailUrl,
|
||||||
GetDefinitionScheduleUrl,
|
GetDefinitionScheduleUrl,
|
||||||
GetEnvModuleUrl,
|
GetEnvModuleUrl,
|
||||||
|
@ -34,8 +37,10 @@ import {
|
||||||
ImportDefinitionUrl,
|
ImportDefinitionUrl,
|
||||||
MoveModuleUrl,
|
MoveModuleUrl,
|
||||||
OperationHistoryUrl,
|
OperationHistoryUrl,
|
||||||
|
RecoverCaseUrl,
|
||||||
RecoverDefinitionUrl,
|
RecoverDefinitionUrl,
|
||||||
RecoverOperationHistoryUrl,
|
RecoverOperationHistoryUrl,
|
||||||
|
RecycleCasePageUrl,
|
||||||
SaveOperationHistoryUrl,
|
SaveOperationHistoryUrl,
|
||||||
SortCaseUrl,
|
SortCaseUrl,
|
||||||
SortDefinitionUrl,
|
SortDefinitionUrl,
|
||||||
|
@ -345,6 +350,34 @@ export function dragSort(data: DragSortParams) {
|
||||||
return MSR.post({ url: SortCaseUrl, data });
|
return MSR.post({ url: SortCaseUrl, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口用例回收站
|
||||||
|
*/
|
||||||
|
// 获取回收站接口用例列表
|
||||||
|
export function getRecycleCasePage(data: ApiCasePageParams) {
|
||||||
|
return MSR.post<CommonList<ApiCaseDetail>>({ url: RecycleCasePageUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复接口用例
|
||||||
|
export function recoverCase(id: string) {
|
||||||
|
return MSR.get({ url: RecoverCaseUrl, params: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量恢复接口用例
|
||||||
|
export function batchRecoverCase(data: ApiCaseBatchParams) {
|
||||||
|
return MSR.post({ url: BatchRecoverCaseUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 彻底删除接口用例
|
||||||
|
export function deleteRecycleCase(id: string) {
|
||||||
|
return MSR.get({ url: DeleteRecycleCaseUrl, params: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量彻底删除接口用例
|
||||||
|
export function batchDeleteRecycleCase(data: ApiCaseBatchParams) {
|
||||||
|
return MSR.post({ url: BatchDeleteRecycleCaseUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
// 添加接口用例
|
// 添加接口用例
|
||||||
export function addCase(data: AddApiCaseParams) {
|
export function addCase(data: AddApiCaseParams) {
|
||||||
return MSR.post({ url: AddCaseUrl, data });
|
return MSR.post({ url: AddCaseUrl, data });
|
||||||
|
|
|
@ -57,8 +57,17 @@ export const GetTrashModuleCountUrl = '/api/definition/module/trash/count'; //
|
||||||
export const CasePageUrl = '/api/case/page'; // 接口用例列表
|
export const CasePageUrl = '/api/case/page'; // 接口用例列表
|
||||||
export const UpdateCaseStatusUrl = '/api/case/update-status'; // 接口用例更新状态
|
export const UpdateCaseStatusUrl = '/api/case/update-status'; // 接口用例更新状态
|
||||||
export const UpdateCasePriorityUrl = '/api/case/update-priority'; // 接口用例更新等级
|
export const UpdateCasePriorityUrl = '/api/case/update-priority'; // 接口用例更新等级
|
||||||
export const DeleteCaseUrl = '/api/case/delete'; // 删除接口用例
|
export const DeleteCaseUrl = '/api/case/delete-to-gc'; // 删除接口用例
|
||||||
export const BatchDeleteCaseUrl = '/api/case/batch/delete'; // 批量删除接口用例
|
export const BatchDeleteCaseUrl = '/api/case/batch/delete-to-gc'; // 批量删除接口用例
|
||||||
export const BatchEditCaseUrl = '/api/case/batch/edit'; // 批量编辑接口用例
|
export const BatchEditCaseUrl = '/api/case/batch/edit'; // 批量编辑接口用例
|
||||||
export const SortCaseUrl = '/api/case/edit/pos'; // 接口用例拖拽
|
export const SortCaseUrl = '/api/case/edit/pos'; // 接口用例拖拽
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口用例回收站
|
||||||
|
*/
|
||||||
|
export const RecycleCasePageUrl = '/api/case/trash/page'; // 接口用例回收站列表
|
||||||
|
export const RecoverCaseUrl = '/api/case/recover'; // 接口用例恢复
|
||||||
|
export const BatchRecoverCaseUrl = '/api/case/batch/recover'; // 接口用例批量恢复
|
||||||
|
export const DeleteRecycleCaseUrl = '/api/case/delete'; // 接口用例彻底删除
|
||||||
|
export const BatchDeleteRecycleCaseUrl = '/api/case/batch/delete'; // 接口用例批量彻底删除
|
||||||
export const AddCaseUrl = '/api/case/add'; // 添加用例
|
export const AddCaseUrl = '/api/case/add'; // 添加用例
|
||||||
|
|
|
@ -0,0 +1,582 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-[16px_22px]">
|
||||||
|
<div class="mb-[16px] flex items-center justify-end">
|
||||||
|
<div class="flex items-center gap-[8px]">
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('apiTestManagement.searchPlaceholder')"
|
||||||
|
allow-clear
|
||||||
|
class="mr-[8px] w-[240px]"
|
||||||
|
@search="loadCaseList"
|
||||||
|
@press-enter="loadCaseList"
|
||||||
|
/>
|
||||||
|
<a-button type="outline" class="arco-btn-outline--secondary !p-[8px]" @click="loadCaseList">
|
||||||
|
<template #icon>
|
||||||
|
<icon-refresh class="text-[var(--color-text-4)]" />
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ms-base-table
|
||||||
|
v-bind="propsRes"
|
||||||
|
:action-config="batchActions"
|
||||||
|
:first-column-width="44"
|
||||||
|
no-disable
|
||||||
|
filter-icon-align-left
|
||||||
|
v-on="propsEvent"
|
||||||
|
@selected-change="handleTableSelect"
|
||||||
|
@batch-action="handleTableBatch"
|
||||||
|
>
|
||||||
|
<template #caseLevelFilter="{ columnConfig }">
|
||||||
|
<a-trigger v-model:popup-visible="caseFilterVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
||||||
|
<MsButton type="text" class="arco-btn-text--secondary ml-[10px]" @click="caseFilterVisible = true">
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
<icon-down :class="caseFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</MsButton>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group v-model:model-value="caseFilters" direction="vertical" size="small">
|
||||||
|
<a-checkbox v-for="item of caseLevelList" :key="item.text" :value="item.text">
|
||||||
|
<caseLevel :case-level="item.text" />
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<template #deleteTime="{ record }">
|
||||||
|
{{ dayjs(record.deleteTime).format('YYYY-MM-DD HH:mm:ss') || '-' }}
|
||||||
|
</template>
|
||||||
|
<template #status="{ record }">
|
||||||
|
<apiStatus :status="record.status" />
|
||||||
|
</template>
|
||||||
|
<template #statusFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="statusFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<MsButton type="text" class="arco-btn-text--secondary ml-[10px]" @click="statusFilterVisible = true">
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</MsButton>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<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 v-for="val of Object.values(RequestDefinitionStatus)" :key="val" :value="val">
|
||||||
|
<apiStatus :status="val" />
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<template #lastReportStatusFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="lastReportStatusFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<MsButton
|
||||||
|
type="text"
|
||||||
|
class="arco-btn-text--secondary ml-[10px]"
|
||||||
|
@click="lastReportStatusFilterVisible = true"
|
||||||
|
>
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
<icon-down :class="lastReportStatusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</MsButton>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group v-model:model-value="lastReportStatusFilters" direction="vertical" size="small">
|
||||||
|
<a-checkbox v-for="val of lastReportStatusList" :key="val" :value="val">
|
||||||
|
<span>{{ val }}</span>
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<template #passRateColumn>
|
||||||
|
<div class="flex items-center text-[var(--color-text-3)]">
|
||||||
|
{{ t('case.passRate') }}
|
||||||
|
<a-tooltip :content="t('case.passRateTip')" position="right">
|
||||||
|
<icon-question-circle
|
||||||
|
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #action="{ record }">
|
||||||
|
<MsButton
|
||||||
|
v-permission="['PROJECT_API_DEFINITION_CASE:READ+DELETE']"
|
||||||
|
type="text"
|
||||||
|
class="!mr-0"
|
||||||
|
@click="recover(record)"
|
||||||
|
>
|
||||||
|
{{ t('apiTestManagement.recycle.batchRecover') }}
|
||||||
|
</MsButton>
|
||||||
|
<a-divider
|
||||||
|
v-permission="['PROJECT_API_DEFINITION_CASE:READ+DELETE']"
|
||||||
|
direction="vertical"
|
||||||
|
:margin="8"
|
||||||
|
></a-divider>
|
||||||
|
<MsButton
|
||||||
|
v-permission="['PROJECT_API_DEFINITION_CASE:READ+DELETE']"
|
||||||
|
type="text"
|
||||||
|
class="!mr-0"
|
||||||
|
@click="cleanOut(record)"
|
||||||
|
>
|
||||||
|
{{ t('apiTestManagement.recycle.batchCleanOut') }}
|
||||||
|
</MsButton>
|
||||||
|
</template>
|
||||||
|
</ms-base-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
|
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
batchDeleteRecycleCase,
|
||||||
|
batchRecoverCase,
|
||||||
|
deleteRecycleCase,
|
||||||
|
getRecycleCasePage,
|
||||||
|
recoverCase,
|
||||||
|
} from '@/api/modules/api-test/management';
|
||||||
|
import { getCaseDefaultFields } from '@/api/modules/case-management/featureCase';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useModal from '@/hooks/useModal';
|
||||||
|
import useTableStore from '@/hooks/useTableStore';
|
||||||
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import { ApiCaseBatchParams, ApiCaseDetail } from '@/models/apiTest/management';
|
||||||
|
import { RequestDefinitionStatus } from '@/enums/apiEnum';
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
activeModule: string;
|
||||||
|
offspringIds: string[];
|
||||||
|
protocol: string; // 查看的协议类型
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const tableStore = useTableStore();
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const keyword = ref('');
|
||||||
|
const refreshModuleTree: (() => Promise<any>) | undefined = inject('refreshModuleTree');
|
||||||
|
|
||||||
|
const columns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'num',
|
||||||
|
slotName: 'num',
|
||||||
|
sortIndex: 1,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
fixed: 'left',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.caseName',
|
||||||
|
dataIndex: 'name',
|
||||||
|
showTooltip: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.caseLevel',
|
||||||
|
dataIndex: 'priority',
|
||||||
|
slotName: 'caseLevel',
|
||||||
|
titleSlotName: 'caseLevelFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'apiTestManagement.apiStatus',
|
||||||
|
dataIndex: 'status',
|
||||||
|
slotName: 'status',
|
||||||
|
titleSlotName: 'statusFilter',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'apiTestManagement.path',
|
||||||
|
dataIndex: 'path',
|
||||||
|
showTooltip: true,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.tag',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
isTag: true,
|
||||||
|
isStringTag: true,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.lastReportStatus',
|
||||||
|
dataIndex: 'lastReportStatus',
|
||||||
|
titleSlotName: 'lastReportStatusFilter',
|
||||||
|
showInTable: false,
|
||||||
|
showTooltip: true,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.passRate',
|
||||||
|
dataIndex: 'passRate',
|
||||||
|
titleSlotName: 'passRateColumn',
|
||||||
|
showInTable: false,
|
||||||
|
showTooltip: true,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.caseEnvironment',
|
||||||
|
dataIndex: 'environmentName',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: false,
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.tableColumnUpdateUser',
|
||||||
|
dataIndex: 'updateUser',
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.tableColumnUpdateTime',
|
||||||
|
dataIndex: 'updateTime',
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.tableColumnCreateUser',
|
||||||
|
dataIndex: 'createName',
|
||||||
|
showTooltip: true,
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'case.tableColumnCreateTime',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'apiTestManagement.deleteUser',
|
||||||
|
dataIndex: 'deleteName',
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'apiTestManagement.deleteTime',
|
||||||
|
slotName: 'deleteTime',
|
||||||
|
dataIndex: 'deleteTime',
|
||||||
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.operation',
|
||||||
|
slotName: 'action',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await tableStore.initColumn(TableKeyEnum.API_TEST_MANAGEMENT_CASE, columns, 'drawer');
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getRecycleCasePage, {
|
||||||
|
columns,
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
tableKey: TableKeyEnum.API_TEST_MANAGEMENT_CASE,
|
||||||
|
showSetting: true,
|
||||||
|
selectable: true,
|
||||||
|
showSelectAll: true,
|
||||||
|
draggable: { type: 'handle', width: 32 },
|
||||||
|
});
|
||||||
|
const batchActions = {
|
||||||
|
baseAction: [
|
||||||
|
{
|
||||||
|
label: 'apiTestManagement.recycle.batchRecover',
|
||||||
|
eventTag: 'batchRecover',
|
||||||
|
permission: ['PROJECT_API_DEFINITION_CASE:READ+DELETE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'apiTestManagement.recycle.batchCleanOut',
|
||||||
|
eventTag: 'batchCleanOut',
|
||||||
|
danger: true,
|
||||||
|
permission: ['PROJECT_API_DEFINITION_CASE:READ+DELETE'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const statusFilterVisible = ref(false);
|
||||||
|
const statusFilters = ref(Object.keys(RequestDefinitionStatus));
|
||||||
|
const caseLevelFields = ref<Record<string, any>>({});
|
||||||
|
const caseFilterVisible = ref(false);
|
||||||
|
const caseFilters = ref<string[]>([]);
|
||||||
|
const caseLevelList = computed(() => {
|
||||||
|
return caseLevelFields.value?.options || [];
|
||||||
|
});
|
||||||
|
const lastReportStatusFilterVisible = ref(false);
|
||||||
|
const lastReportStatusList = ['error', 'FakeError', 'success'];
|
||||||
|
const lastReportStatusFilters = ref<string[]>([...lastReportStatusList]);
|
||||||
|
|
||||||
|
const moduleIds = computed(() => {
|
||||||
|
return props.activeModule === 'all' ? [] : [props.activeModule];
|
||||||
|
});
|
||||||
|
function loadCaseList() {
|
||||||
|
const params = {
|
||||||
|
keyword: keyword.value,
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
moduleIds: moduleIds.value,
|
||||||
|
protocol: props.protocol,
|
||||||
|
filter: {
|
||||||
|
status: statusFilters.value,
|
||||||
|
priority: caseFilters.value,
|
||||||
|
lastReportStatus: lastReportStatusFilters.value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
setLoadListParams(params);
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
function loadCaseListAndResetSelector() {
|
||||||
|
resetSelector();
|
||||||
|
loadCaseList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用例等级数据
|
||||||
|
async function getCaseLevelFields() {
|
||||||
|
const result = await getCaseDefaultFields(appStore.currentProjectId);
|
||||||
|
caseLevelFields.value = result.customFields.find((item: any) => item.internal && item.fieldName === '用例等级');
|
||||||
|
caseFilters.value = caseLevelFields.value?.options.map((item: any) => item.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getCaseLevelFields();
|
||||||
|
loadCaseList();
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleFilterHidden(val: boolean) {
|
||||||
|
if (!val) {
|
||||||
|
loadCaseList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.activeModule,
|
||||||
|
() => {
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.protocol,
|
||||||
|
() => {
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const tableSelected = ref<(string | number)[]>([]); // 表格选中的
|
||||||
|
const batchParams = ref<BatchActionQueryParams>({
|
||||||
|
selectedIds: [],
|
||||||
|
selectAll: false,
|
||||||
|
excludeIds: [],
|
||||||
|
currentSelectCount: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 列表彻底删除
|
||||||
|
async function cleanOut(record: ApiCaseDetail) {
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title: t('case.batchDeleteCaseTipTitle', { name: record?.name }),
|
||||||
|
content: t('case.recycle.cleanOutDeleteOnRecycleTip'),
|
||||||
|
okText: t('common.confirmDelete'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await deleteRecycleCase(record.id);
|
||||||
|
Message.success(t('common.deleteSuccess'));
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function recover(record: ApiCaseDetail) {
|
||||||
|
openModal({
|
||||||
|
type: 'info',
|
||||||
|
title: t('case.batchRecoverCaseTipTitle', { name: record?.name }),
|
||||||
|
content: t('case.recycle.recoverCaseTip'),
|
||||||
|
okText: t('case.recycle.confirmRecovery'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'normal',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await recoverCase(record.id);
|
||||||
|
Message.success(t('apiTestManagement.recycle.recoveredSuccessfully'));
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作参数
|
||||||
|
function getBatchParams(): ApiCaseBatchParams {
|
||||||
|
return {
|
||||||
|
excludeIds: batchParams.value.excludeIds,
|
||||||
|
selectAll: batchParams.value.selectAll,
|
||||||
|
selectIds: batchParams.value.selectedIds as string[],
|
||||||
|
moduleIds: moduleIds.value,
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
protocol: props.protocol,
|
||||||
|
condition: {
|
||||||
|
keyword: keyword.value,
|
||||||
|
filter: propsRes.value.filter,
|
||||||
|
combine: batchParams.value.condition,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量恢复
|
||||||
|
async function batchRecover() {
|
||||||
|
openModal({
|
||||||
|
type: 'info',
|
||||||
|
title: t('case.batchRecoverCaseTip', {
|
||||||
|
count: batchParams.value.currentSelectCount || tableSelected.value.length,
|
||||||
|
}),
|
||||||
|
content: t('case.recycle.recoverCaseTip'),
|
||||||
|
okText: t('case.recycle.confirmRecovery'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'normal',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await batchRecoverCase(getBatchParams());
|
||||||
|
Message.success(t('apiTestManagement.recycle.recoveredSuccessfully'));
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量彻底删除
|
||||||
|
async function batchCleanOut() {
|
||||||
|
const title = t('case.batchDeleteCaseTip', {
|
||||||
|
count: batchParams.value.currentSelectCount || tableSelected.value.length,
|
||||||
|
});
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title,
|
||||||
|
content: t('case.recycle.cleanOutDeleteOnRecycleTip'),
|
||||||
|
okText: t('common.confirmDelete'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await batchDeleteRecycleCase(getBatchParams());
|
||||||
|
Message.success(t('common.deleteSuccess'));
|
||||||
|
loadCaseListAndResetSelector();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTableSelect(arr: (string | number)[]) {
|
||||||
|
tableSelected.value = arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理表格选中后批量操作
|
||||||
|
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||||
|
tableSelected.value = params?.selectedIds || [];
|
||||||
|
batchParams.value = params;
|
||||||
|
switch (event.eventTag) {
|
||||||
|
case 'batchRecover':
|
||||||
|
batchRecover();
|
||||||
|
break;
|
||||||
|
case 'batchCleanOut':
|
||||||
|
batchCleanOut();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
:deep(.param-input:not(.arco-input-focus, .arco-select-view-focus)) {
|
||||||
|
&:not(:hover) {
|
||||||
|
border-color: transparent !important;
|
||||||
|
.arco-input::placeholder {
|
||||||
|
@apply invisible;
|
||||||
|
}
|
||||||
|
.arco-select-view-icon {
|
||||||
|
@apply invisible;
|
||||||
|
}
|
||||||
|
.arco-select-view-value {
|
||||||
|
color: var(--color-text-brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -9,12 +9,15 @@
|
||||||
:protocol="protocol"
|
:protocol="protocol"
|
||||||
/>
|
/>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="case" title="CASE" class="ms-api-tab-pane"></a-tab-pane>
|
<a-tab-pane key="case" title="CASE" class="ms-api-tab-pane">
|
||||||
|
<api-case :active-module="props.activeModule" :offspring-ids="props.offspringIds" :protocol="protocol"></api-case>
|
||||||
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import api from './api/apiTable.vue';
|
import api from './api/apiTable.vue';
|
||||||
|
import apiCase from './case/caseTable.vue';
|
||||||
|
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
|
|
@ -165,9 +165,16 @@ export default {
|
||||||
'case.passRate': 'Pass Rate',
|
'case.passRate': 'Pass Rate',
|
||||||
'case.passRateTip': 'Number of success case executions/Total number of case executions *%',
|
'case.passRateTip': 'Number of success case executions/Total number of case executions *%',
|
||||||
'case.batchModalSubTitle': '({count} cases selected)',
|
'case.batchModalSubTitle': '({count} cases selected)',
|
||||||
|
'case.batchDeleteCaseTipTitle': 'Are you sure you want to delete {name} ?',
|
||||||
|
'case.batchRecoverCaseTipTitle': 'Are you sure you want to recover {name} ?',
|
||||||
'case.batchDeleteCaseTip': 'Are you sure you want to delete {count} selected cases?',
|
'case.batchDeleteCaseTip': 'Are you sure you want to delete {count} selected cases?',
|
||||||
|
'case.recycle.cleanOutDeleteOnRecycleTip':
|
||||||
|
'After deletion, the case cannot be restored. Please operate with caution!',
|
||||||
'case.deleteCaseTip':
|
'case.deleteCaseTip':
|
||||||
'Deleting an case will result in the execution failure of the test task that references the use case. Please be cautious!',
|
'Deleting an case will result in the execution failure of the test task that references the use case. Please be cautious!',
|
||||||
'apiTestManagement.click': 'Click',
|
'apiTestManagement.click': 'Click',
|
||||||
'apiTestManagement.getResponse': 'Get response content',
|
'apiTestManagement.getResponse': 'Get response content',
|
||||||
|
'case.batchRecoverCaseTip': 'Are you sure you want to recover {count} selected cases?',
|
||||||
|
'case.recycle.recoverCaseTip': 'When restoring the case, the deleted API will be restored simultaneously.',
|
||||||
|
'case.recycle.confirmRecovery': 'Confirm recovery',
|
||||||
};
|
};
|
||||||
|
|
|
@ -162,5 +162,11 @@ export default {
|
||||||
'case.passRateTip': '用例执行success数/用例执行总数*%',
|
'case.passRateTip': '用例执行success数/用例执行总数*%',
|
||||||
'case.batchModalSubTitle': '(已选 {count} 个用例)',
|
'case.batchModalSubTitle': '(已选 {count} 个用例)',
|
||||||
'case.batchDeleteCaseTip': '确认删除已选中的 {count} 个用例吗?',
|
'case.batchDeleteCaseTip': '确认删除已选中的 {count} 个用例吗?',
|
||||||
|
'case.batchDeleteCaseTipTitle': '确认删除 {name} 吗?',
|
||||||
|
'case.batchRecoverCaseTipTitle': '确认恢复 {name} 吗?',
|
||||||
|
'case.recycle.cleanOutDeleteOnRecycleTip': '删除后,用例无法恢复,请谨慎操作!',
|
||||||
'case.deleteCaseTip': '删除用例会导致引用了该用例的测试任务执行失败,请谨慎操作!',
|
'case.deleteCaseTip': '删除用例会导致引用了该用例的测试任务执行失败,请谨慎操作!',
|
||||||
|
'case.batchRecoverCaseTip': '确认恢复已选中的 {count} 个用例吗?',
|
||||||
|
'case.recycle.recoverCaseTip': '恢复case时会同步恢复被删除的api',
|
||||||
|
'case.recycle.confirmRecovery': '确认恢复',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue