feat(测试计划): 高级筛选-计划详情页-功能用例/接口用例/场景用例的关联抽屉

This commit is contained in:
teukkk 2024-10-15 16:30:34 +08:00 committed by Craftsman
parent ec7112f400
commit 5bcc5caa5d
19 changed files with 802 additions and 94 deletions

View File

@ -7,6 +7,7 @@
baseAction: [],
moreAction: [],
}"
:not-show-table-filter="props.isAdvancedSearchMode"
always-show-selected-count
v-on="propsEvent"
@row-select-change="rowSelectChange"
@ -55,6 +56,7 @@
import { ref } from 'vue';
import { TableData } from '@arco-design/web-vue';
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
@ -67,10 +69,12 @@
import { useI18n } from '@/hooks/useI18n';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import { characterLimit } from '@/utils';
import { ApiCaseDetail } from '@/models/apiTest/management';
import type { TableQueryParams } from '@/models/common';
import { FilterType } from '@/enums/advancedFilterEnum';
import { CasePageApiTypeEnum } from '@/enums/associateCaseEnum';
import { CaseLinkEnum } from '@/enums/caseEnum';
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
@ -81,10 +85,11 @@
import type { moduleKeysType } from './types';
import useModuleSelection from './useModuleSelection';
import { getPublicLinkCaseListMap } from './utils/page';
import { casePriorityOptions } from '@/views/api-test/components/config';
import { casePriorityOptions, caseStatusOptions } from '@/views/api-test/components/config';
const { openNewPage } = useOpenNewPage();
const { t } = useI18n();
const appStore = useAppStore();
const props = defineProps<{
associationType: string; // | |
@ -99,6 +104,8 @@
getPageApiType: keyof typeof CasePageApiTypeEnum; // Api
extraTableParams?: TableQueryParams; //
protocols: string[];
allProtocolList: string[];
isAdvancedSearchMode?: boolean;
moduleTree: MsTreeNodeData[];
modulesCount: Record<string, any>;
}>();
@ -120,7 +127,7 @@
return Object.keys(ReportStatus).map((key) => {
return {
value: key,
...Object.keys(ReportStatus[key]),
label: t(ReportStatus[key].label),
};
});
});
@ -236,6 +243,9 @@
const {
propsRes,
propsEvent,
viewId,
advanceFilter,
setAdvanceFilter,
loadList,
setLoadListParams,
resetSelector,
@ -289,14 +299,153 @@
});
}
const tableParams = await getTableParams();
setLoadListParams(tableParams);
loadList();
emit('getModuleCount', {
setLoadListParams({
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
moduleIds: props.isAdvancedSearchMode ? [] : tableParams.moduleIds,
protocols: props.isAdvancedSearchMode ? props.allProtocolList : props.protocols || [],
viewId: viewId.value,
combineSearch: advanceFilter,
});
loadList();
if (!props.isAdvancedSearchMode) {
emit('getModuleCount', {
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
});
}
}
const filterConfigList = computed<FilterFormItem[]>(() => [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'num',
type: FilterType.INPUT,
},
{
title: 'case.caseName',
dataIndex: 'name',
type: FilterType.INPUT,
},
{
title: 'common.belongModule',
dataIndex: 'moduleId',
type: FilterType.TREE_SELECT,
treeSelectData: props.moduleTree,
treeSelectProps: {
fieldNames: {
title: 'name',
key: 'id',
children: 'children',
},
multiple: true,
treeCheckable: true,
treeCheckStrictly: true,
},
},
{
title: 'apiTestManagement.protocol',
dataIndex: 'protocol',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: props.allProtocolList?.map((item) => ({ label: item, value: item })),
},
},
{
title: 'case.caseLevel',
dataIndex: 'priority',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: casePriorityOptions,
},
},
{
title: 'case.apiParamsChange',
dataIndex: 'apiChange',
type: FilterType.BOOLEAN,
selectProps: {
options: [
{ label: t('case.withoutChanges'), value: false },
{ label: t('case.withChanges'), value: true },
],
},
},
{
title: 'apiTestManagement.path',
dataIndex: 'path',
type: FilterType.INPUT,
},
{
title: 'apiTestManagement.apiStatus',
dataIndex: 'status',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: caseStatusOptions.map((item) => ({ label: t(item.label), value: item.value })),
},
},
{
title: 'case.lastReportStatus',
dataIndex: 'lastReportStatus',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: lastReportStatusListOptions.value,
},
},
{
title: 'case.passRate',
dataIndex: 'passRate',
type: FilterType.NUMBER,
numberProps: {
min: 0,
},
},
{
title: 'case.caseEnvironment',
dataIndex: 'environmentName',
type: FilterType.SELECT,
selectProps: {
labelKey: 'name',
valueKey: 'id',
multiple: true,
options: appStore.envList,
},
},
{
title: 'common.tag',
dataIndex: 'tags',
type: FilterType.TAGS_INPUT,
numberProps: {
min: 0,
precision: 0,
},
},
{
title: 'common.creator',
dataIndex: 'createUser',
type: FilterType.MEMBER,
},
{
title: 'common.createTime',
dataIndex: 'createTime',
type: FilterType.DATE_PICKER,
},
{
title: 'common.updateUserName',
dataIndex: 'updateUser',
type: FilterType.MEMBER,
},
{
title: 'common.updateTime',
dataIndex: 'updateTime',
type: FilterType.DATE_PICKER,
},
]);
function setCaseAdvanceFilter(filter: FilterResult, id: string) {
setAdvanceFilter(filter, id);
}
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
@ -328,7 +477,7 @@
watch(
() => props.activeModule,
(val) => {
if (val) {
if (val && !props.isAdvancedSearchMode) {
resetSelector();
resetFilterParams();
loadCaseList();
@ -397,6 +546,8 @@
defineExpose({
getApiCaseSaveParams,
loadCaseList,
filterConfigList,
setCaseAdvanceFilter,
});
await tableStore.initColumn(TableKeyEnum.ASSOCIATE_CASE_API_CASE, columns, 'drawer');

View File

@ -8,6 +8,7 @@
baseAction: [],
moreAction: [],
}"
:not-show-table-filter="props.isAdvancedSearchMode"
always-show-selected-count
v-on="propsEvent"
@filter-change="getModuleCount"
@ -39,6 +40,7 @@
</template>
<script setup lang="ts">
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
@ -53,6 +55,7 @@
import { ApiDefinitionDetail } from '@/models/apiTest/management';
import type { TableQueryParams } from '@/models/common';
import { FilterType } from '@/enums/advancedFilterEnum';
import { RequestMethods } from '@/enums/apiEnum';
import { CasePageApiTypeEnum } from '@/enums/associateCaseEnum';
import { CaseLinkEnum } from '@/enums/caseEnum';
@ -63,6 +66,7 @@
import type { moduleKeysType } from './types';
import useModuleSelection from './useModuleSelection';
import { getPublicLinkCaseListMap } from './utils/page';
import { apiStatusOptions } from '@/views/api-test/components/config';
const { t } = useI18n();
const { openNewPage } = useOpenNewPage();
@ -80,6 +84,8 @@
showType: string;
getPageApiType: keyof typeof CasePageApiTypeEnum; // Api
extraTableParams?: TableQueryParams; //
allProtocolList: string[];
isAdvancedSearchMode?: boolean;
protocols: string[];
moduleTree: MsTreeNodeData[];
modulesCount: Record<string, any>;
@ -193,6 +199,9 @@
const {
propsRes,
propsEvent,
viewId,
advanceFilter,
setAdvanceFilter,
loadList,
setLoadListParams,
setPagination,
@ -239,13 +248,120 @@
});
}
const tableParams = await getTableParams();
setLoadListParams(tableParams);
loadList();
emit('getModuleCount', {
setLoadListParams({
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
moduleIds: props.isAdvancedSearchMode ? [] : tableParams.moduleIds,
protocols: props.isAdvancedSearchMode ? props.allProtocolList : props.protocols || [],
viewId: viewId.value,
combineSearch: advanceFilter,
});
loadList();
if (!props.isAdvancedSearchMode) {
emit('getModuleCount', {
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
});
}
}
const filterConfigList = computed<FilterFormItem[]>(() => [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'num',
type: FilterType.INPUT,
},
{
title: 'apiTestManagement.apiName',
dataIndex: 'name',
type: FilterType.INPUT,
},
{
title: 'common.belongModule',
dataIndex: 'moduleId',
type: FilterType.TREE_SELECT,
treeSelectData: props.moduleTree,
treeSelectProps: {
fieldNames: {
title: 'name',
key: 'id',
children: 'children',
},
multiple: true,
treeCheckable: true,
treeCheckStrictly: true,
},
},
{
title: 'apiTestManagement.protocol',
dataIndex: 'protocol',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: props.allProtocolList?.map((item) => ({ label: item, value: item })),
},
},
{
title: 'apiTestManagement.apiType',
dataIndex: 'method',
type: FilterType.SELECT,
selectProps: {
multiple: true,
labelKey: 'key',
options: requestMethodsOptions.value,
},
},
{
title: 'apiTestManagement.path',
dataIndex: 'path',
type: FilterType.INPUT,
},
{
title: 'apiTestManagement.apiStatus',
dataIndex: 'status',
type: FilterType.SELECT,
selectProps: {
multiple: true,
labelKey: 'name',
options: apiStatusOptions,
},
},
{
title: 'apiTestManagement.caseTotal',
dataIndex: 'caseTotal',
type: FilterType.NUMBER,
numberProps: {
min: 0,
precision: 0,
},
},
{
title: 'common.tag',
dataIndex: 'tags',
type: FilterType.TAGS_INPUT,
numberProps: {
min: 0,
precision: 0,
},
},
{
title: 'common.creator',
dataIndex: 'createUser',
type: FilterType.MEMBER,
},
{
title: 'common.createTime',
dataIndex: 'createTime',
type: FilterType.DATE_PICKER,
},
{
title: 'common.updateTime',
dataIndex: 'updateTime',
type: FilterType.DATE_PICKER,
},
]);
function setCaseAdvanceFilter(filter: FilterResult, id: string) {
setAdvanceFilter(filter, id);
}
watch(
@ -277,7 +393,7 @@
watch(
() => props.activeModule,
(val) => {
if (val) {
if (val && !props.isAdvancedSearchMode) {
resetSelector();
resetFilterParams();
loadApiList();
@ -346,6 +462,8 @@
defineExpose({
getApiSaveParams,
loadApiList,
filterConfigList,
setCaseAdvanceFilter,
});
await tableStore.initColumn(TableKeyEnum.ASSOCIATE_CASE_API, columns, 'drawer');

View File

@ -7,6 +7,7 @@
baseAction: [],
moreAction: [],
}"
:not-show-table-filter="props.isAdvancedSearchMode"
always-show-selected-count
v-on="propsEvent"
@filter-change="getModuleCount"
@ -50,6 +51,8 @@
<script setup lang="ts">
import { ref } from 'vue';
import { getFilterCustomFields } from '@/components/pure/ms-advance-filter';
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
@ -58,11 +61,13 @@
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
import { getCustomFieldsTable } from '@/api/modules/case-management/featureCase';
import useOpenNewPage from '@/hooks/useOpenNewPage';
import useTableStore from '@/hooks/useTableStore';
import type { CaseManagementTable } from '@/models/caseManagement/featureCase';
import type { TableQueryParams } from '@/models/common';
import { FilterType } from '@/enums/advancedFilterEnum';
import { CasePageApiTypeEnum } from '@/enums/associateCaseEnum';
import { CaseLinkEnum } from '@/enums/caseEnum';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
@ -93,6 +98,7 @@
modulesCount: Record<string, any>;
getPageApiType: keyof typeof CasePageApiTypeEnum; // Api
extraTableParams?: TableQueryParams; //
isAdvancedSearchMode?: boolean;
}>();
const emit = defineEmits<{
@ -229,7 +235,17 @@
return getPublicLinkCaseListMap[props.getPageApiType][props.activeSourceType];
});
const { propsRes, propsEvent, loadList, setLoadListParams, resetFilterParams, setTableSelected } = useTable(
const {
propsRes,
propsEvent,
viewId,
advanceFilter,
setAdvanceFilter,
loadList,
setLoadListParams,
resetFilterParams,
setTableSelected,
} = useTable(
getPageList.value,
{
tableKey: TableKeyEnum.ASSOCIATE_CASE,
@ -278,13 +294,119 @@
});
}
const tableParams = await getTableParams();
setLoadListParams(tableParams);
loadList();
emit('getModuleCount', {
setLoadListParams({
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
moduleIds: props.isAdvancedSearchMode ? [] : tableParams.moduleIds,
viewId: viewId.value,
combineSearch: advanceFilter,
});
loadList();
if (!props.isAdvancedSearchMode) {
emit('getModuleCount', {
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
});
}
}
const filterConfigList = computed<FilterFormItem[]>(() => [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'num',
type: FilterType.INPUT,
},
{
title: 'caseManagement.featureCase.tableColumnName',
dataIndex: 'name',
type: FilterType.INPUT,
},
{
title: 'common.belongModule',
dataIndex: 'moduleId',
type: FilterType.TREE_SELECT,
treeSelectData: props.moduleTree,
treeSelectProps: {
fieldNames: {
title: 'name',
key: 'id',
children: 'children',
},
multiple: true,
treeCheckable: true,
treeCheckStrictly: true,
},
},
{
title: 'caseManagement.featureCase.tableColumnReviewResult',
dataIndex: 'reviewStatus',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: reviewResultOptions.value,
},
},
{
title: 'caseManagement.featureCase.tableColumnExecutionResult',
dataIndex: 'lastExecuteResult',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: executeResultOptions.value,
},
},
{
title: 'caseManagement.featureCase.associatedDemand',
dataIndex: 'demand',
type: FilterType.INPUT,
},
{
title: 'caseManagement.featureCase.relatedAttachments',
dataIndex: 'attachment',
type: FilterType.INPUT,
},
{
title: 'common.creator',
dataIndex: 'createUser',
type: FilterType.MEMBER,
},
{
title: 'common.createTime',
dataIndex: 'createTime',
type: FilterType.DATE_PICKER,
},
{
title: 'common.updateUserName',
dataIndex: 'updateUser',
type: FilterType.MEMBER,
},
{
title: 'common.updateTime',
dataIndex: 'updateTime',
type: FilterType.DATE_PICKER,
},
{
title: 'common.tag',
dataIndex: 'tags',
type: FilterType.TAGS_INPUT,
numberProps: {
min: 0,
precision: 0,
},
},
]);
const searchCustomFields = ref<FilterFormItem[]>([]);
async function initFilter() {
try {
const result = await getCustomFieldsTable(props.currentProject);
searchCustomFields.value = getFilterCustomFields(result); //
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
function setCaseAdvanceFilter(filter: FilterResult, id: string) {
setAdvanceFilter(filter, id);
}
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
@ -353,18 +475,37 @@
}
);
watch([() => props.currentProject, () => props.activeModule], () => {
resetFilterParams();
loadCaseList();
});
watch(
() => props.currentProject,
() => {
resetFilterParams();
loadCaseList();
initFilter();
}
);
watch(
() => props.activeModule,
() => {
if (!props.isAdvancedSearchMode) {
resetFilterParams();
loadCaseList();
initFilter();
}
}
);
onMounted(() => {
loadCaseList();
initFilter();
});
defineExpose({
getFunctionalSaveParams,
loadCaseList,
filterConfigList,
searchCustomFields,
setCaseAdvanceFilter,
});
await tableStore.initColumn(TableKeyEnum.ASSOCIATE_CASE, columns, 'drawer');

View File

@ -163,6 +163,7 @@
const treeFolderAllRef = ref<InstanceType<typeof TreeFolderAll>>();
const selectedProtocols = computed<string[]>(() => treeFolderAllRef.value?.selectedProtocols ?? []);
const allProtocolList = computed<string[]>(() => treeFolderAllRef.value?.allProtocolList ?? []);
const { calculateTreeCount } = useCalculateTreeCount();
/**
* 初始化模块树
@ -238,6 +239,11 @@
}
}
);
defineExpose({
setActiveFolder,
allProtocolList,
});
</script>
<style scoped lang="less">

View File

@ -114,7 +114,7 @@
</div>
</template>
<div class="flex h-[calc(100vh-118px)]">
<div class="w-[292px] border-r border-[var(--color-text-n8)] p-[16px]">
<div v-show="!isAdvancedSearchMode" class="w-[292px] border-r border-[var(--color-text-n8)] p-[16px]">
<CaseTree
ref="caseTreeRef"
v-model:checkedKeys="checkedKeys"
@ -143,18 +143,20 @@
</div>
</CaseTree>
</div>
<div class="relative flex w-[calc(100%-293px)] flex-col p-[16px]">
<div :class="[`relative flex ${!isAdvancedSearchMode ? 'w-[calc(100%-293px)]' : 'w-full'} flex-col p-[16px]`]">
<MsAdvanceFilter
ref="msAdvanceFilterRef"
v-model:keyword="keyword"
:filter-config-list="[]"
:custom-fields-config-list="[]"
:view-type="viewType"
:filter-config-list="filterConfigList"
:custom-fields-config-list="searchCustomFields"
:search-placeholder="searchPlaceholder"
@keyword-search="loadCaseList"
@adv-search="loadCaseList"
@refresh="loadCaseList"
@keyword-search="loadCaseList()"
@adv-search="handleAdvSearch"
@refresh="loadCaseList()"
>
<template #left>
<div class="flex w-full items-center justify-between">
<div class="flex items-center">
<a-radio-group
v-if="associationType === 'API'"
v-model="showType"
@ -187,6 +189,7 @@
ref="functionalTableRef"
v-model:selectedIds="selectedIds"
v-model:selectedModulesMaps="selectedModulesMaps"
:is-advanced-search-mode="isAdvancedSearchMode"
:association-type="associateType"
:get-page-api-type="getPageApiType"
:active-module="activeFolder"
@ -219,6 +222,8 @@
:active-source-type="associationType"
:keyword="keyword"
:show-type="showType"
:is-advanced-search-mode="isAdvancedSearchMode"
:all-protocol-list="allProtocolList"
:protocols="selectedProtocols"
:module-tree="moduleTree"
:modules-count="modulesCount"
@ -242,6 +247,8 @@
:active-source-type="associationType"
:keyword="keyword"
:show-type="showType"
:is-advanced-search-mode="isAdvancedSearchMode"
:all-protocol-list="allProtocolList"
:protocols="selectedProtocols"
:module-tree="moduleTree"
:modules-count="modulesCount"
@ -267,6 +274,8 @@
:keyword="keyword"
:module-tree="moduleTree"
:total-count="totalCount"
:is-advanced-search-mode="isAdvancedSearchMode"
:all-protocol-list="allProtocolList"
@get-module-count="initModulesCount"
@refresh="loadCaseList"
>
@ -353,6 +362,7 @@
import { isEqual } from 'lodash-es';
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import ApiCaseTable from './apiCaseTable.vue';
import ApiTable from './apiTable.vue';
@ -369,6 +379,7 @@
import type { ModuleTreeNode, TableQueryParams } from '@/models/common';
import type { ProjectListItem } from '@/models/setting/project';
import type { AssociateCaseRequestParams } from '@/models/testPlan/testPlan';
import { ViewTypeEnum } from '@/enums/advancedFilterEnum';
import { CaseModulesApiTypeEnum, CasePageApiTypeEnum } from '@/enums/associateCaseEnum';
import { CaseLinkEnum } from '@/enums/caseEnum';
@ -410,6 +421,7 @@
(e: 'init', val: TableQueryParams): void; //
(e: 'close'): void;
(e: 'save', params: any): void; // table
(e: 'handleAdvSearch', isStartAdvance: boolean): void;
}>();
const keyword = ref<string>('');
@ -630,6 +642,65 @@
break;
}
}
const caseTreeRef = ref<InstanceType<typeof CaseTree>>();
const allProtocolList = computed<string[]>(() => caseTreeRef.value?.allProtocolList ?? []);
const msAdvanceFilterRef = ref<InstanceType<typeof MsAdvanceFilter>>();
const isAdvancedSearchMode = computed(() => msAdvanceFilterRef.value?.isAdvancedSearchMode);
const viewType = computed(() => {
switch (associationType.value) {
case CaseLinkEnum.FUNCTIONAL:
return ViewTypeEnum.PLAN_FUNCTIONAL_CASE_DRAWER;
case CaseLinkEnum.API:
return showType.value === 'API' ? ViewTypeEnum.PLAN_API_DEFINITION_DRAWER : ViewTypeEnum.PLAN_API_CASE_DRAWER;
case CaseLinkEnum.SCENARIO:
return ViewTypeEnum.PLAN_API_SCENARIO_DRAWER;
default:
return ViewTypeEnum.PLAN_FUNCTIONAL_CASE_DRAWER;
}
});
function setAdvanceFilter(filter: FilterResult, id: string) {
switch (associationType.value) {
case CaseLinkEnum.FUNCTIONAL:
return functionalTableRef.value?.setCaseAdvanceFilter(filter, id);
case CaseLinkEnum.API:
return showType.value === 'API'
? apiTableRef.value?.setCaseAdvanceFilter(filter, id)
: caseTableRef.value?.setCaseAdvanceFilter(filter, id);
case CaseLinkEnum.SCENARIO:
return scenarioTableRef.value?.setCaseAdvanceFilter(filter, id);
default:
break;
}
}
const filterConfigList = computed<FilterFormItem[]>(() => {
switch (associationType.value) {
case CaseLinkEnum.FUNCTIONAL:
return functionalTableRef.value?.filterConfigList ?? [];
case CaseLinkEnum.API:
return (
(showType.value === 'API' ? apiTableRef.value?.filterConfigList : caseTableRef.value?.filterConfigList) ?? []
);
case CaseLinkEnum.SCENARIO:
return scenarioTableRef.value?.filterConfigList ?? [];
default:
return [];
}
});
const searchCustomFields = computed(() => {
if (associationType.value === CaseLinkEnum.FUNCTIONAL) {
return functionalTableRef.value?.searchCustomFields;
}
return [];
});
//
const handleAdvSearch = async (filter: FilterResult, id: string) => {
keyword.value = '';
caseTreeRef.value?.setActiveFolder('all');
setAdvanceFilter(filter, id);
await loadCaseList(); //
};
function initModuleTree(tree: ModuleTreeNode[], _protocols?: string[]) {
moduleTree.value = tree;

View File

@ -7,6 +7,7 @@
baseAction: [],
moreAction: [],
}"
:not-show-table-filter="props.isAdvancedSearchMode"
always-show-selected-count
v-on="propsEvent"
@filter-change="getModuleCount"
@ -47,6 +48,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
@ -62,6 +64,7 @@
import { ApiCaseDetail } from '@/models/apiTest/management';
import type { TableQueryParams } from '@/models/common';
import { FilterType } from '@/enums/advancedFilterEnum';
import { CasePageApiTypeEnum } from '@/enums/associateCaseEnum';
import { CaseLinkEnum } from '@/enums/caseEnum';
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
@ -73,6 +76,7 @@
import useModuleSelection from './useModuleSelection';
import { getPublicLinkCaseListMap } from './utils/page';
import { casePriorityOptions } from '@/views/api-test/components/config';
import { scenarioStatusOptions } from '@/views/api-test/scenario/components/config';
const { t } = useI18n();
const { openNewPage } = useOpenNewPage();
@ -89,6 +93,7 @@
extraTableParams?: TableQueryParams; //
moduleTree: MsTreeNodeData[];
modulesCount: Record<string, any>;
isAdvancedSearchMode?: boolean;
}>();
const emit = defineEmits<{
@ -208,19 +213,26 @@
return getPublicLinkCaseListMap[props.getPageApiType][props.activeSourceType];
});
const { propsRes, propsEvent, loadList, setLoadListParams, resetFilterParams, setTableSelected } = useTable(
getPageList.value,
{
tableKey: TableKeyEnum.ASSOCIATE_CASE_API_SCENARIO,
showSetting: true,
isSimpleSetting: true,
onlyPageSize: true,
selectable: true,
showSelectAll: true,
heightUsed: 310,
showSelectorAll: false,
}
);
const {
propsRes,
propsEvent,
viewId,
advanceFilter,
setAdvanceFilter,
loadList,
setLoadListParams,
resetFilterParams,
setTableSelected,
} = useTable(getPageList.value, {
tableKey: TableKeyEnum.ASSOCIATE_CASE_API_SCENARIO,
showSetting: true,
isSimpleSetting: true,
onlyPageSize: true,
selectable: true,
showSelectAll: true,
heightUsed: 310,
showSelectorAll: false,
});
async function getTableParams() {
const { excludeKeys } = propsRes.value;
@ -250,13 +262,138 @@
});
}
const tableParams = await getTableParams();
setLoadListParams(tableParams);
loadList();
emit('getModuleCount', {
setLoadListParams({
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
moduleIds: props.isAdvancedSearchMode ? [] : tableParams.moduleIds,
viewId: viewId.value,
combineSearch: advanceFilter,
});
loadList();
if (!props.isAdvancedSearchMode) {
emit('getModuleCount', {
...tableParams,
current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize,
});
}
}
const filterConfigList = computed<FilterFormItem[]>(() => {
return [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'num',
type: FilterType.INPUT,
},
{
title: 'apiScenario.table.columns.name',
dataIndex: 'name',
type: FilterType.INPUT,
},
{
title: 'common.belongModule',
dataIndex: 'moduleId',
type: FilterType.TREE_SELECT,
treeSelectData: props.moduleTree,
treeSelectProps: {
fieldNames: {
title: 'name',
key: 'id',
children: 'children',
},
multiple: true,
treeCheckable: true,
treeCheckStrictly: true,
},
},
{
title: 'apiScenario.table.columns.level',
dataIndex: 'priority',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: casePriorityOptions,
},
},
{
title: 'apiScenario.table.columns.status',
dataIndex: 'status',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: scenarioStatusOptions,
},
},
{
title: 'apiScenario.table.columns.runResult',
dataIndex: 'lastReportStatus',
type: FilterType.SELECT,
selectProps: {
multiple: true,
options: statusList.value,
},
},
{
title: 'common.tag',
dataIndex: 'tags',
type: FilterType.TAGS_INPUT,
numberProps: {
min: 0,
precision: 0,
},
},
{
title: 'apiScenario.table.columns.scenarioEnv',
dataIndex: 'environmentName',
type: FilterType.SELECT,
selectProps: {
labelKey: 'name',
valueKey: 'id',
multiple: true,
options: appStore.envList,
},
},
{
title: 'apiScenario.table.columns.steps',
dataIndex: 'stepTotal',
type: FilterType.NUMBER,
numberProps: {
min: 0,
precision: 0,
},
},
{
title: 'apiScenario.table.columns.passRate',
dataIndex: 'requestPassRate',
type: FilterType.NUMBER,
numberProps: {
min: 0,
},
},
{
title: 'common.creator',
dataIndex: 'createUser',
type: FilterType.MEMBER,
},
{
title: 'common.createTime',
dataIndex: 'createTime',
type: FilterType.DATE_PICKER,
},
{
title: 'apiScenario.table.columns.updateUser',
dataIndex: 'updateUser',
type: FilterType.MEMBER,
},
{
title: 'common.updateTime',
dataIndex: 'updateTime',
type: FilterType.DATE_PICKER,
},
];
});
function setCaseAdvanceFilter(filter: FilterResult, id: string) {
setAdvanceFilter(filter, id);
}
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
@ -325,16 +462,31 @@
pId: record.projectId,
});
}
watch([() => props.currentProject, () => props.activeModule], () => {
resetFilterParams();
loadScenarioList();
});
watch(
() => props.currentProject,
() => {
resetFilterParams();
loadScenarioList();
}
);
watch(
() => props.activeModule,
() => {
if (!props.isAdvancedSearchMode) {
resetFilterParams();
loadScenarioList();
}
}
);
onMounted(() => {
loadScenarioList();
});
defineExpose({
filterConfigList,
setCaseAdvanceFilter,
getScenarioSaveParams,
loadScenarioList,
});

View File

@ -310,6 +310,21 @@
}
}
watch([() => props.configList, () => props.customList], ([newConfigList, newCustomList]) => {
formModel.value.list.forEach((formModelListItem: FilterFormItem, index) => {
const listItem = [...newConfigList, ...(newCustomList ?? [])].find(
(item) => item.dataIndex === formModelListItem.dataIndex
);
if (listItem) {
formModel.value.list[index] = {
...listItem,
operator: formModelListItem.operator,
value: formModelListItem.value,
};
}
});
});
const isShowNameInput = ref(false);
const viewNameInputRef = ref<InstanceType<typeof ViewNameInput>>();
function showNameInput() {
@ -424,7 +439,7 @@
() => props.currentView,
async (val, oldValue) => {
await getUserViewDetail(val);
if (!oldValue.length) return;
if (!oldValue?.length) return;
handleFilter();
}
);

View File

@ -194,12 +194,22 @@ export function getAllDataDefaultConditions(viewType: ViewTypeEnum) {
{ name: 'name', operator: OperatorEnum.CONTAINS },
{ name: 'moduleId', operator: OperatorEnum.BELONG_TO },
];
if ([ViewTypeEnum.API_DEFINITION, ViewTypeEnum.PLAN_API_CASE].includes(viewType)) {
if (
[
ViewTypeEnum.API_DEFINITION,
ViewTypeEnum.PLAN_API_CASE,
ViewTypeEnum.PLAN_API_DEFINITION_DRAWER,
ViewTypeEnum.PLAN_API_CASE_DRAWER,
].includes(viewType)
) {
conditions.push({ name: 'protocol', operator: OperatorEnum.BELONG_TO });
}
if ([ViewTypeEnum.BUG, ViewTypeEnum.PLAN_BUG, ViewTypeEnum.PLAN_BUG_DRAWER].includes(viewType)) {
conditions.push({ name: 'title', operator: OperatorEnum.CONTAINS });
}
if ([ViewTypeEnum.API_MOCK].includes(viewType)) {
conditions.push({ name: 'expectNum', operator: OperatorEnum.CONTAINS });
}
if (
[ViewTypeEnum.PLAN_API_SCENARIO, ViewTypeEnum.PLAN_API_CASE, ViewTypeEnum.PLAN_FUNCTIONAL_CASE].includes(viewType)
) {

View File

@ -236,6 +236,14 @@
}
});
watch(
() => props.viewType,
async () => {
await getUserViewList();
currentView.value = internalViews.value[0]?.id;
}
);
const viewSelectOptionVisible = ref(false);
function changeView(item: ViewItem) {
currentView.value = item.id;

View File

@ -39,4 +39,8 @@ export enum ViewTypeEnum {
BUG = 'bug',
PLAN_BUG = 'plan-bug',
PLAN_BUG_DRAWER = 'plan-bug-drawer',
PLAN_API_SCENARIO_DRAWER = 'plan-api-scenario-drawer',
PLAN_API_CASE_DRAWER = 'plan-api-case-drawer',
PLAN_API_DEFINITION_DRAWER = 'plan-api-definition-drawer',
PLAN_FUNCTIONAL_CASE_DRAWER = 'plan-functional-case-drawer',
}

View File

@ -186,6 +186,25 @@ export const casePriorityOptions = [
{ label: 'P3', value: 'P3' },
];
export const apiStatusOptions = [
{
name: t('apiTestManagement.processing'),
value: RequestDefinitionStatus.PROCESSING,
},
{
name: t('apiTestManagement.done'),
value: RequestDefinitionStatus.DONE,
},
{
name: t('apiTestManagement.deprecate'),
value: RequestDefinitionStatus.DEPRECATED,
},
{
name: t('apiTestManagement.debugging'),
value: RequestDefinitionStatus.DEBUGGING,
},
];
// 用例状态选项
export const caseStatusOptions = [
{ label: 'apiTestManagement.processing', value: RequestCaseStatus.PROCESSING },

View File

@ -341,6 +341,8 @@
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { apiStatusOptions } from '@/views/api-test/components/config';
const cacheStore = useCacheStore();
defineOptions({
name: CacheTabTypeEnum.API_TEST_API_TABLE,
@ -414,24 +416,7 @@
};
});
});
const apiStatusOptions = [
{
name: t('apiTestManagement.processing'),
value: RequestDefinitionStatus.PROCESSING,
},
{
name: t('apiTestManagement.done'),
value: RequestDefinitionStatus.DONE,
},
{
name: t('apiTestManagement.deprecate'),
value: RequestDefinitionStatus.DEPRECATED,
},
{
name: t('apiTestManagement.debugging'),
value: RequestDefinitionStatus.DEBUGGING,
},
];
const apiTableRef = ref();
let columns: MsTableColumn = [
{

View File

@ -459,7 +459,7 @@
const filterConfigList = computed<FilterFormItem[]>(() => [
{
title: 'caseManagement.featureCase.tableColumnID',
dataIndex: 'num',
dataIndex: 'expectNum',
type: FilterType.INPUT,
},
{
@ -510,7 +510,7 @@
},
{
title: 'mockManagement.operationUser',
dataIndex: 'createUserName',
dataIndex: 'createUser',
type: FilterType.MEMBER,
},
{

View File

@ -499,6 +499,7 @@
};
const statusOption = ref<BugOptionItem[]>([]);
const handleUserOption = ref<BugOptionItem[]>([]);
const platformOption = ref<PoolOption[]>([]);
const initPlatformOption = async () => {
@ -529,7 +530,7 @@
selectProps: {
multiple: true,
labelKey: 'name',
valueKey: 'id',
valueKey: 'name',
options: platformOption.value,
},
},
@ -555,7 +556,12 @@
{
title: 'bugManagement.handleMan',
dataIndex: 'handleUser',
type: FilterType.MEMBER,
type: FilterType.SELECT,
selectProps: {
multiple: true,
labelKey: 'text',
options: handleUserOption.value,
},
},
{
title: 'common.tag',
@ -840,6 +846,7 @@
async function initFilterOptions() {
const res = await getCustomOptionHeader(appStore.currentProjectId);
statusOption.value = res.statusOption;
handleUserOption.value = res.handleUserOption;
const filterOptionsMaps: Record<string, any> = {
status: res.statusOption,
handleUser: res.handleUserOption,

View File

@ -280,10 +280,12 @@
};
const statusOption = ref<BugOptionItem[]>([]);
const handleUserOption = ref<BugOptionItem[]>([]);
async function initFilterOptions() {
try {
const res = await getCustomOptionHeader(appStore.currentProjectId);
statusOption.value = res.statusOption;
handleUserOption.value = res.handleUserOption;
} catch (error) {
// eslint-disable-next-line no-console
}
@ -318,7 +320,7 @@
selectProps: {
multiple: true,
labelKey: 'name',
valueKey: 'id',
valueKey: 'name',
options: platformOption.value,
},
},
@ -344,7 +346,12 @@
{
title: 'bugManagement.handleMan',
dataIndex: 'handleUser',
type: FilterType.MEMBER,
type: FilterType.SELECT,
selectProps: {
multiple: true,
labelKey: 'text',
options: handleUserOption.value,
},
},
{
title: 'common.tag',

View File

@ -549,6 +549,12 @@
console.log(error);
}
}
watch(
() => props.treeType,
() => {
initAnotherModules();
}
);
const filterConfigList = computed<FilterFormItem[]>(() => [
{
@ -635,17 +641,6 @@
options: caseStatusOptions.map((item) => ({ label: t(item.label), value: item.value })),
},
},
{
title: 'case.apiParamsChange',
dataIndex: 'apiChange',
type: FilterType.BOOLEAN,
selectProps: {
options: [
{ label: t('case.withoutChanges'), value: false },
{ label: t('case.withChanges'), value: true },
],
},
},
{
title: 'testPlan.featureCase.bugCount',
dataIndex: 'bugCount',

View File

@ -526,6 +526,12 @@
console.log(error);
}
}
watch(
() => props.treeType,
() => {
initAnotherModules();
}
);
const filterConfigList = computed<FilterFormItem[]>(() => [
{

View File

@ -198,6 +198,7 @@
};
const statusOption = ref<BugOptionItem[]>([]);
const handleUserOption = ref<BugOptionItem[]>([]);
const platformOption = ref<PoolOption[]>([]);
const initPlatformOption = async () => {
@ -228,7 +229,7 @@
selectProps: {
multiple: true,
labelKey: 'name',
valueKey: 'id',
valueKey: 'name',
options: platformOption.value,
},
},
@ -254,7 +255,12 @@
{
title: 'bugManagement.handleMan',
dataIndex: 'handleUser',
type: FilterType.MEMBER,
type: FilterType.SELECT,
selectProps: {
multiple: true,
labelKey: 'text',
options: handleUserOption.value,
},
},
{
title: 'common.tag',
@ -298,6 +304,7 @@
if (hasAnyPermission(['PROJECT_BUG:READ'])) {
const res = await getCustomOptionHeader(appStore.currentProjectId);
statusOption.value = res.statusOption;
handleUserOption.value = res.handleUserOption;
const optionsMap: Record<string, any> = {
status: res.statusOption,
};

View File

@ -622,6 +622,12 @@
console.log(error);
}
}
watch(
() => props.treeType,
() => {
initAnotherModules();
}
);
const reviewResultOptions = computed(() => {
return Object.keys(statusIconMap).map((key) => {