feat(接口测试): 定义api支持高级搜索&优化视图交互
This commit is contained in:
parent
fa5a4200bb
commit
1320bfe264
|
@ -60,10 +60,10 @@
|
|||
});
|
||||
}
|
||||
|
||||
function validateForm(cb: () => void) {
|
||||
function validateForm(cb: (param?: any) => void, params?: any) {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
cb();
|
||||
cb(params);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
{{ t(option.title as string) }}
|
||||
</a-option>
|
||||
<a-divider
|
||||
v-if="(props?.customList || [])?.length && (currentConfigList || []).length - 1 === currentOptionsIndex"
|
||||
v-if="(props?.customList || [])?.length && !option.customField && currentOptions(item.dataIndex as string)[currentOptionsIndex+1]?.customField"
|
||||
class="!my-1"
|
||||
/>
|
||||
</div>
|
||||
|
@ -189,25 +189,28 @@
|
|||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
<MsButton type="text" class="mt-[5px]" @click="handleAddItem">
|
||||
<MsButton type="text" class="mt-[5px] w-[fit-content]" @click="handleAddItem">
|
||||
<MsIcon type="icon-icon_add_outlined" class="mr-[3px]" />
|
||||
{{ t('advanceFilter.addCondition') }}
|
||||
</MsButton>
|
||||
<template #footer>
|
||||
<div v-if="!isSaveAsView" class="flex items-center gap-[8px]">
|
||||
<a-button type="primary" @click="handleFilter">{{ t('common.filter') }}</a-button>
|
||||
<a-button v-if="!formModel?.id" type="primary" @click="handleSaveAndFilter">{{
|
||||
t('advanceFilter.saveAndFilter')
|
||||
}}</a-button>
|
||||
<a-button v-if="formModel?.id" type="primary" @click="handleFilter">{{ t('common.filter') }}</a-button>
|
||||
<a-button class="mr-[16px]" @click="handleReset">{{ t('common.reset') }}</a-button>
|
||||
<MsButton
|
||||
v-if="!isInternalViews(formModel?.id)"
|
||||
v-if="!isInternalViews(formModel?.id) && formModel?.id"
|
||||
type="text"
|
||||
:loading="saveLoading"
|
||||
class="!text-[var(--color-text-1)]"
|
||||
@click="handleSaveView"
|
||||
@click="handleSaveView()"
|
||||
>
|
||||
{{ t('common.save') }}
|
||||
</MsButton>
|
||||
<MsButton
|
||||
v-if="formModel?.id && !isInternalViews(formModel?.id)"
|
||||
v-if="(formModel?.id && !isInternalViews(formModel?.id)) || formModel?.id === 'all_data'"
|
||||
type="text"
|
||||
class="!text-[var(--color-text-1)]"
|
||||
@click="handleToSaveAs"
|
||||
|
@ -262,6 +265,7 @@
|
|||
const emit = defineEmits<{
|
||||
(e: 'handleFilter', value: FilterResult): void;
|
||||
(e: 'refreshViewList'): void;
|
||||
(e: 'changeViewToFirstCustom'): void;
|
||||
}>();
|
||||
const visible = defineModel<boolean>('visible', { required: true });
|
||||
|
||||
|
@ -397,12 +401,22 @@
|
|||
}
|
||||
|
||||
function getParams() {
|
||||
const conditions = formModel.value.list.map(({ value, operator, customField, dataIndex }) => ({
|
||||
value,
|
||||
operator,
|
||||
customField: customField ?? false,
|
||||
name: dataIndex,
|
||||
}));
|
||||
const conditions = formModel.value.list.map(({ type, value, operator, customField, dataIndex }) => {
|
||||
let timeValue;
|
||||
// 转换成时间戳
|
||||
if (type === FilterType.DATE_PICKER) {
|
||||
timeValue =
|
||||
operator === OperatorEnum.BETWEEN
|
||||
? [new Date(value[0]).getTime(), new Date(value[1]).getTime()]
|
||||
: new Date(value).getTime();
|
||||
}
|
||||
return {
|
||||
value: timeValue ?? value,
|
||||
operator,
|
||||
customField: customField ?? false,
|
||||
name: dataIndex,
|
||||
};
|
||||
});
|
||||
return { searchMode: formModel.value.searchMode, conditions };
|
||||
}
|
||||
|
||||
|
@ -449,7 +463,7 @@
|
|||
|
||||
// 保存视图
|
||||
const saveLoading = ref(false);
|
||||
function realSaveView() {
|
||||
function realSaveView(isChangeView = false) {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
|
@ -466,7 +480,11 @@
|
|||
}
|
||||
Message.success(t('common.saveSuccess'));
|
||||
savedFormModel.value = cloneDeep(formModel.value);
|
||||
emit('refreshViewList');
|
||||
if (!isChangeView) {
|
||||
emit('refreshViewList');
|
||||
} else {
|
||||
emit('changeViewToFirstCustom');
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
|
@ -476,11 +494,11 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
function handleSaveView() {
|
||||
function handleSaveView(isChangeView = false) {
|
||||
if (viewNameInputRef.value) {
|
||||
viewNameInputRef.value?.validateForm(realSaveView);
|
||||
viewNameInputRef.value?.validateForm(realSaveView, isChangeView);
|
||||
} else {
|
||||
realSaveView();
|
||||
realSaveView(isChangeView);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,6 +549,9 @@
|
|||
async function handleAddView() {
|
||||
saveAsViewNameInputRef.value?.validateForm(realAddView);
|
||||
}
|
||||
function handleSaveAndFilter() {
|
||||
handleSaveView(true);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
resetToNewViewForm,
|
||||
|
|
|
@ -77,6 +77,7 @@ export const CustomTypeMaps: Record<string, any> = {
|
|||
propsKey: 'selectProps',
|
||||
props: {
|
||||
mode: 'static',
|
||||
multiple: true,
|
||||
valueKey: 'value',
|
||||
labelKey: 'text',
|
||||
options: [],
|
||||
|
@ -171,10 +172,13 @@ export const CustomTypeMaps: Record<string, any> = {
|
|||
// TODO lmy 计划详情功能用例增加:测试点;接口定义、计划详情接口用例增加:协议;
|
||||
export function getAllDataDefaultConditions(viewType: ViewTypeEnum) {
|
||||
const conditions = [
|
||||
{ name: 'id', operator: OperatorEnum.CONTAINS },
|
||||
{ name: 'num', operator: OperatorEnum.CONTAINS },
|
||||
{ name: 'name', operator: OperatorEnum.CONTAINS },
|
||||
{ name: 'moduleId', operator: OperatorEnum.BELONG_TO },
|
||||
];
|
||||
if ([ViewTypeEnum.API_DEFINITION].includes(viewType)) {
|
||||
return [...conditions, { name: 'protocol', operator: OperatorEnum.BELONG_TO }];
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
:member-options="memberOptions"
|
||||
@handle-filter="handleFilter"
|
||||
@refresh-view-list="getUserViewList"
|
||||
@change-view-to-first-custom="changeViewToFirstCustom"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -149,7 +150,6 @@
|
|||
import { FilterFormItem, FilterResult, ViewItem } from './type';
|
||||
|
||||
const props = defineProps<{
|
||||
rowCount: number;
|
||||
filterConfigList: FilterFormItem[]; // 系统字段
|
||||
customFieldsConfigList?: FilterFormItem[]; // 自定义字段
|
||||
searchPlaceholder?: string;
|
||||
|
@ -161,7 +161,7 @@
|
|||
|
||||
const emit = defineEmits<{
|
||||
(e: 'keywordSearch', value: string | undefined): void; // keyword 搜索 TODO:可以去除,父组件通过 v-model:keyword 获取关键字
|
||||
(e: 'advSearch', value: FilterResult, viewId: string): void; // 高级搜索
|
||||
(e: 'advSearch', value: FilterResult, viewId: string, isAdvancedSearchMode: boolean): void; // 高级搜索
|
||||
(e: 'refresh', value: FilterResult): void;
|
||||
}>();
|
||||
|
||||
|
@ -275,7 +275,7 @@
|
|||
// 开启高级筛选:非默认视图或有筛选条件
|
||||
isAdvancedSearchMode.value = currentView.value !== internalViews.value[0].id || haveConditions;
|
||||
filterResult.value = filter;
|
||||
emit('advSearch', filter, currentView.value);
|
||||
emit('advSearch', filter, currentView.value, isAdvancedSearchMode.value);
|
||||
};
|
||||
|
||||
const handleRefresh = () => {
|
||||
|
@ -295,11 +295,17 @@
|
|||
function clearFilter() {
|
||||
if (currentView.value === internalViews.value[0].id) {
|
||||
filterDrawerRef.value?.handleReset();
|
||||
handleFilter({ searchMode: 'AND', conditions: [] });
|
||||
} else {
|
||||
currentView.value = internalViews.value[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
async function changeViewToFirstCustom() {
|
||||
await getUserViewList();
|
||||
currentView.value = customViews.value[0].id;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
isAdvancedSearchMode,
|
||||
});
|
||||
|
|
|
@ -42,4 +42,5 @@ export default {
|
|||
'advanceFilter.filterContentRequired': 'Filter content cannot be empty',
|
||||
'advanceFilter.filterTip': 'Filter mode, module filtering can only be operated in the current filter',
|
||||
'advanceFilter.maxViewTip': 'Up to 10 views can be added',
|
||||
'advanceFilter.saveAndFilter': 'Save And filter',
|
||||
};
|
||||
|
|
|
@ -42,4 +42,5 @@ export default {
|
|||
'advanceFilter.filterContentRequired': '筛选内容不能为空',
|
||||
'advanceFilter.filterTip': '筛选模式,模块过滤仅可在当前过滤器中操作',
|
||||
'advanceFilter.maxViewTip': '最多可添加 10 个视图',
|
||||
'advanceFilter.saveAndFilter': '保存并筛选',
|
||||
};
|
||||
|
|
|
@ -26,7 +26,6 @@ export default function useShortCut(shortcuts: Shortcuts, options: MinderOperati
|
|||
const { minderCopy, minderCut, minderPaste } = useMinderOperation(options);
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
event.preventDefault();
|
||||
const nodes: MinderJsonNode[] = window.minder.getSelectedNodes();
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
|
|
|
@ -31,4 +31,6 @@ export enum FilterType {
|
|||
|
||||
export enum ViewTypeEnum {
|
||||
FUNCTIONAL_CASE = 'functional-case',
|
||||
API_DEFINITION = 'api-definition',
|
||||
REVIEW_FUNCTIONAL_CASE = 'review-functional-case',
|
||||
}
|
||||
|
|
|
@ -1,35 +1,28 @@
|
|||
<template>
|
||||
<div :class="['p-[0_16px_8px_16px]', props.class]">
|
||||
<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="loadApiList(false)"
|
||||
@press-enter="loadApiList(false)"
|
||||
@clear="loadApiList(false)"
|
||||
/>
|
||||
<a-button type="outline" class="arco-btn-outline--secondary !p-[8px]" @click="loadApiList(false)">
|
||||
<template #icon>
|
||||
<icon-refresh class="text-[var(--color-text-4)]" />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<MsAdvanceFilter
|
||||
ref="msAdvanceFilterRef"
|
||||
v-model:keyword="keyword"
|
||||
:view-type="ViewTypeEnum.API_DEFINITION"
|
||||
:filter-config-list="filterConfigList"
|
||||
:search-placeholder="t('apiTestManagement.searchPlaceholder')"
|
||||
@keyword-search="loadApiList(false)"
|
||||
@adv-search="handleAdvSearch"
|
||||
@refresh="loadApiList(false)"
|
||||
/>
|
||||
<ms-base-table
|
||||
ref="apiTableRef"
|
||||
v-bind="propsRes"
|
||||
:action-config="batchActions"
|
||||
:first-column-width="44"
|
||||
no-disable
|
||||
class="mt-[16px]"
|
||||
:not-show-table-filter="isAdvancedSearchMode"
|
||||
filter-icon-align-left
|
||||
v-on="propsEvent"
|
||||
@selected-change="handleTableSelect"
|
||||
@batch-action="handleTableBatch"
|
||||
@drag-change="handleTableDragSort"
|
||||
@module-change="loadApiList(false)"
|
||||
>
|
||||
<template #[FilterSlotNameEnum.API_TEST_API_REQUEST_METHODS]="{ filterContent }">
|
||||
<apiMethodName :method="filterContent.value" />
|
||||
|
@ -176,7 +169,7 @@
|
|||
:disabled="batchForm.attr === ''"
|
||||
>
|
||||
<a-option v-for="item of valueOptions" :key="item.value" :value="item.value">
|
||||
{{ t(item.name) }}
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
@ -294,6 +287,8 @@
|
|||
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import MsAdvanceFilter from '@/components/pure/ms-advance-filter/index.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 type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
|
@ -307,7 +302,6 @@
|
|||
import apiStatus from '@/views/api-test/components/apiStatus.vue';
|
||||
import moduleTree from '@/views/api-test/management/components/moduleTree.vue';
|
||||
|
||||
import { getProtocolList } from '@/api/modules/api-test/common';
|
||||
import {
|
||||
batchDeleteDefinition,
|
||||
batchMoveDefinition,
|
||||
|
@ -329,7 +323,8 @@
|
|||
|
||||
import { ProtocolItem } from '@/models/apiTest/common';
|
||||
import { ApiDefinitionDetail, ApiDefinitionGetModuleParams } from '@/models/apiTest/management';
|
||||
import { DragSortParams } from '@/models/common';
|
||||
import { DragSortParams, ModuleTreeNode } from '@/models/common';
|
||||
import { FilterType, ViewTypeEnum } from '@/enums/advancedFilterEnum';
|
||||
import { RequestDefinitionStatus, RequestImportFormat, RequestMethods } from '@/enums/apiEnum';
|
||||
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
|
@ -347,6 +342,7 @@
|
|||
selectedProtocols: string[]; // 查看的协议类型
|
||||
readOnly?: boolean; // 是否是只读模式
|
||||
refreshTimeStamp?: number;
|
||||
moduleTreeData?: ModuleTreeNode[];
|
||||
memberOptions: { label: string; value: string }[];
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
|
@ -354,6 +350,7 @@
|
|||
(e: 'openCopyApiTab', record: ApiDefinitionDetail): void;
|
||||
(e: 'addApiTab'): void;
|
||||
(e: 'import'): void;
|
||||
(e: 'handleAdvSearch', isStartAdvance: boolean): void;
|
||||
(
|
||||
e: 'openEditApiTab',
|
||||
options: { apiInfo: ApiDefinitionDetail; isCopy: boolean; isExecute: boolean; isEdit: boolean }
|
||||
|
@ -380,22 +377,7 @@
|
|||
])
|
||||
);
|
||||
|
||||
// TODO: 后期优化 放store里
|
||||
const protocolList = ref<ProtocolItem[]>([]);
|
||||
async function initProtocolList() {
|
||||
try {
|
||||
const res = await getProtocolList(appStore.currentOrgId);
|
||||
protocolList.value = res.map((e) => ({
|
||||
protocol: e.protocol,
|
||||
polymorphicName: e.polymorphicName,
|
||||
pluginId: e.pluginId,
|
||||
}));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const protocolList = inject<Ref<ProtocolItem[]>>('protocols', ref([]));
|
||||
const requestMethodsOptions = computed(() => {
|
||||
const otherMethods = protocolList.value
|
||||
.filter((e) => e.protocol !== 'HTTP')
|
||||
|
@ -421,6 +403,24 @@
|
|||
};
|
||||
});
|
||||
});
|
||||
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 = [
|
||||
{
|
||||
|
@ -574,31 +574,31 @@
|
|||
);
|
||||
}
|
||||
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
|
||||
getDefinitionPage,
|
||||
{
|
||||
columns: props.readOnly ? columns : [],
|
||||
scroll: { x: '100%' },
|
||||
tableKey: props.readOnly ? undefined : TableKeyEnum.API_TEST,
|
||||
showSetting: !props.readOnly,
|
||||
selectable: hasAnyPermission([
|
||||
'PROJECT_API_DEFINITION:READ+DELETE',
|
||||
'PROJECT_API_DEFINITION:READ+EXECUTE',
|
||||
'PROJECT_API_DEFINITION:READ+UPDATE',
|
||||
]),
|
||||
showSelectAll: !props.readOnly,
|
||||
draggable: hasAnyPermission(['PROJECT_API_DEFINITION:READ+UPDATE']) ? { type: 'handle', width: 32 } : undefined,
|
||||
heightUsed: 272,
|
||||
paginationSize: 'mini',
|
||||
showSubdirectory: true,
|
||||
},
|
||||
(item) => ({
|
||||
...item,
|
||||
fullPath: folderTreePathMap?.[item.moduleId],
|
||||
createTime: dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
})
|
||||
);
|
||||
const { propsRes, propsEvent, viewId, advanceFilter, setAdvanceFilter, loadList, setLoadListParams, resetSelector } =
|
||||
useTable(
|
||||
getDefinitionPage,
|
||||
{
|
||||
columns: props.readOnly ? columns : [],
|
||||
scroll: { x: '100%' },
|
||||
tableKey: props.readOnly ? undefined : TableKeyEnum.API_TEST,
|
||||
showSetting: !props.readOnly,
|
||||
selectable: hasAnyPermission([
|
||||
'PROJECT_API_DEFINITION:READ+DELETE',
|
||||
'PROJECT_API_DEFINITION:READ+EXECUTE',
|
||||
'PROJECT_API_DEFINITION:READ+UPDATE',
|
||||
]),
|
||||
showSelectAll: !props.readOnly,
|
||||
draggable: hasAnyPermission(['PROJECT_API_DEFINITION:READ+UPDATE']) ? { type: 'handle', width: 32 } : undefined,
|
||||
heightUsed: 272,
|
||||
paginationSize: 'mini',
|
||||
},
|
||||
(item) => ({
|
||||
...item,
|
||||
fullPath: folderTreePathMap?.[item.moduleId],
|
||||
createTime: dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||
})
|
||||
);
|
||||
const batchActions = {
|
||||
baseAction: [
|
||||
{
|
||||
|
@ -635,9 +635,11 @@
|
|||
},
|
||||
];
|
||||
|
||||
const msAdvanceFilterRef = ref<InstanceType<typeof MsAdvanceFilter>>();
|
||||
const isAdvancedSearchMode = computed(() => msAdvanceFilterRef.value?.isAdvancedSearchMode);
|
||||
async function getModuleIds() {
|
||||
let moduleIds: string[] = [];
|
||||
if (props.activeModule !== 'all') {
|
||||
if (props.activeModule !== 'all' && !isAdvancedSearchMode.value) {
|
||||
moduleIds = [props.activeModule];
|
||||
const getAllChildren = await tableStore.getSubShow(TableKeyEnum.API_TEST);
|
||||
if (getAllChildren) {
|
||||
|
@ -653,11 +655,13 @@
|
|||
keyword: keyword.value,
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds,
|
||||
protocols: props.selectedProtocols,
|
||||
protocols: isAdvancedSearchMode.value ? protocolList.value.map((item) => item.protocol) : props.selectedProtocols,
|
||||
filter: propsRes.value.filter,
|
||||
viewId: viewId.value,
|
||||
combineSearch: advanceFilter,
|
||||
};
|
||||
|
||||
if (!hasRefreshTree && typeof refreshModuleTreeCount === 'function') {
|
||||
if (!hasRefreshTree && typeof refreshModuleTreeCount === 'function' && !isAdvancedSearchMode.value) {
|
||||
refreshModuleTreeCount({
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
|
@ -688,6 +692,105 @@
|
|||
}
|
||||
);
|
||||
|
||||
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.moduleTreeData,
|
||||
treeSelectProps: {
|
||||
fieldNames: {
|
||||
title: 'name',
|
||||
key: 'id',
|
||||
children: 'children',
|
||||
},
|
||||
multiple: true,
|
||||
treeCheckable: true,
|
||||
treeCheckStrictly: true,
|
||||
maxTagCount: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'apiTestManagement.protocol',
|
||||
dataIndex: 'protocol',
|
||||
type: FilterType.SELECT,
|
||||
selectProps: {
|
||||
multiple: true,
|
||||
labelKey: 'protocol',
|
||||
valueKey: 'protocol',
|
||||
options: protocolList.value,
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
},
|
||||
{
|
||||
title: 'common.tag',
|
||||
dataIndex: 'tags',
|
||||
type: FilterType.TAGS_INPUT,
|
||||
},
|
||||
{
|
||||
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,
|
||||
},
|
||||
]);
|
||||
// 高级检索
|
||||
const handleAdvSearch = async (filter: FilterResult, id: string, isStartAdvance: boolean) => {
|
||||
resetSelector();
|
||||
emit('handleAdvSearch', isStartAdvance);
|
||||
keyword.value = '';
|
||||
setAdvanceFilter(filter, id);
|
||||
await loadApiList(false); // 基础筛选都清空
|
||||
};
|
||||
|
||||
async function handleStatusChange(record: ApiDefinitionDetail) {
|
||||
try {
|
||||
await updateDefinition({
|
||||
|
@ -702,7 +805,6 @@
|
|||
}
|
||||
|
||||
function onMountedLoad() {
|
||||
initProtocolList();
|
||||
if (props.selectedProtocols.length > 0) {
|
||||
loadApiList(true);
|
||||
}
|
||||
|
@ -731,6 +833,20 @@
|
|||
excludeIds: [],
|
||||
currentSelectCount: 0,
|
||||
});
|
||||
async function getBatchConditionParams() {
|
||||
const selectModules = await getModuleIds();
|
||||
return {
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
viewId: viewId.value,
|
||||
combineSearch: advanceFilter,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
protocols: isAdvancedSearchMode.value ? protocolList.value.map((item) => item.protocol) : props.selectedProtocols,
|
||||
moduleIds: selectModules,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口
|
||||
|
@ -757,18 +873,13 @@
|
|||
onBeforeOk: async () => {
|
||||
try {
|
||||
if (isBatch) {
|
||||
const batchConditionParams = await getBatchConditionParams();
|
||||
await batchDeleteDefinition({
|
||||
selectIds,
|
||||
selectAll: !!params?.selectAll,
|
||||
excludeIds: params?.excludeIds || [],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds: await getModuleIds(),
|
||||
...batchConditionParams,
|
||||
deleteAll: true,
|
||||
protocols: props.selectedProtocols,
|
||||
});
|
||||
} else {
|
||||
await deleteDefinition(record?.id as string);
|
||||
|
@ -842,24 +953,7 @@
|
|||
const valueOptions = computed(() => {
|
||||
switch (batchForm.value.attr) {
|
||||
case 'status':
|
||||
return [
|
||||
{
|
||||
name: 'apiTestManagement.processing',
|
||||
value: RequestDefinitionStatus.PROCESSING,
|
||||
},
|
||||
{
|
||||
name: 'apiTestManagement.done',
|
||||
value: RequestDefinitionStatus.DONE,
|
||||
},
|
||||
{
|
||||
name: 'apiTestManagement.deprecate',
|
||||
value: RequestDefinitionStatus.DEPRECATED,
|
||||
},
|
||||
{
|
||||
name: 'apiTestManagement.debugging',
|
||||
value: RequestDefinitionStatus.DEBUGGING,
|
||||
},
|
||||
];
|
||||
return apiStatusOptions;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
@ -881,17 +975,12 @@
|
|||
if (!errors) {
|
||||
try {
|
||||
batchUpdateLoading.value = true;
|
||||
const batchConditionParams = await getBatchConditionParams();
|
||||
await batchUpdateDefinition({
|
||||
selectIds: batchParams.value?.selectedIds || [],
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds: await getModuleIds(),
|
||||
protocols: props.selectedProtocols,
|
||||
...batchConditionParams,
|
||||
type: batchForm.value.attr,
|
||||
append: batchForm.value.append,
|
||||
[batchForm.value.attr]: batchForm.value.attr === 'tags' ? batchForm.value.values : batchForm.value.value,
|
||||
|
@ -923,18 +1012,13 @@
|
|||
async function handleApiMove() {
|
||||
try {
|
||||
batchMoveApiLoading.value = true;
|
||||
const batchConditionParams = await getBatchConditionParams();
|
||||
await batchMoveDefinition({
|
||||
selectIds: isBatchMove.value ? batchParams.value?.selectedIds || [] : [activeApi.value?.id || ''],
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds: await getModuleIds(),
|
||||
...batchConditionParams,
|
||||
moduleId: selectedModuleKeys.value[0],
|
||||
protocols: props.selectedProtocols,
|
||||
});
|
||||
Message.success(t('common.batchMoveSuccess'));
|
||||
if (isBatchMove.value) {
|
||||
|
@ -996,18 +1080,13 @@
|
|||
async function exportApi() {
|
||||
try {
|
||||
exportLoading.value = true;
|
||||
const batchConditionParams = await getBatchConditionParams();
|
||||
const result = await exportApiDefinition(
|
||||
{
|
||||
selectIds: tableSelected.value as string[],
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds: await getModuleIds(),
|
||||
protocols: props.selectedProtocols,
|
||||
...batchConditionParams,
|
||||
exportApiCase: exportApiCase.value,
|
||||
exportApiMock: exportApiMock.value,
|
||||
sort: propsRes.value.sorter || {},
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
class="flex-1 pt-[8px]"
|
||||
:active-module="props.activeModule"
|
||||
:offspring-ids="props.offspringIds"
|
||||
:module-tree-data="props.moduleTree"
|
||||
:selected-protocols="props.selectedProtocols"
|
||||
:refresh-time-stamp="refreshTableTimeStamp"
|
||||
:member-options="memberOptions"
|
||||
|
@ -14,6 +15,7 @@
|
|||
@add-api-tab="addApiTab"
|
||||
@import="() => emit('import')"
|
||||
@open-edit-api-tab="openApiTab"
|
||||
@handle-adv-search="(val) => emit('handleAdvSearch', val)"
|
||||
/>
|
||||
</keep-alive>
|
||||
<div v-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden">
|
||||
|
@ -184,6 +186,7 @@
|
|||
const emit = defineEmits<{
|
||||
(e: 'deleteApi', id: string): void;
|
||||
(e: 'import'): void;
|
||||
(e: 'handleAdvSearch', isStartAdvance: boolean): void;
|
||||
(e: 'openCaseTab', apiCaseDetail: ApiCaseDetail): void;
|
||||
}>();
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
@import="emit('import')"
|
||||
@open-case-tab="(apiCaseDetail:ApiCaseDetail)=>newCaseTab(apiCaseDetail.id)"
|
||||
@delete-api="(id) => handleDeleteApiFromModuleTree(id)"
|
||||
@handle-adv-search="(val) => emit('handleAdvSearch', val)"
|
||||
/>
|
||||
<apiCase
|
||||
v-show="(activeApiTab.id === 'all' && currentTab === 'case') || activeApiTab.type === 'case'"
|
||||
|
@ -131,6 +132,7 @@
|
|||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'import'): void;
|
||||
(e: 'handleAdvSearch', isStartAdvance: boolean): void;
|
||||
}>();
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
|
@ -399,9 +401,4 @@
|
|||
|
||||
<style lang="less" scoped>
|
||||
.ms-input-group--prepend();
|
||||
:deep(.arco-select-view-prefix) {
|
||||
margin-right: 8px;
|
||||
padding-right: 0;
|
||||
border-right: 1px solid var(--color-text-input-border);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -641,6 +641,7 @@
|
|||
defineExpose({
|
||||
refresh,
|
||||
initModuleCount,
|
||||
setActiveFolder,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<MsCard simple no-content-padding>
|
||||
<MsSplitBox :size="300" :max="0.5">
|
||||
<MsSplitBox :not-show-first="isAdvancedSearchMode" :size="300" :max="0.5">
|
||||
<template #first>
|
||||
<div class="flex flex-col">
|
||||
<div class="p-[16px]" :style="{ height: `calc(100vh - 120px)` }">
|
||||
|
@ -56,6 +56,7 @@
|
|||
:offspring-ids="offspringIds"
|
||||
:selected-protocols="selectedProtocols"
|
||||
@import="importDrawerVisible = true"
|
||||
@handle-adv-search="handleAdvSearch"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -195,6 +196,12 @@
|
|||
}
|
||||
};
|
||||
|
||||
const isAdvancedSearchMode = ref(false);
|
||||
function handleAdvSearch(isStartAdvance: boolean) {
|
||||
isAdvancedSearchMode.value = isStartAdvance;
|
||||
moduleTreeRef.value?.setActiveFolder('all');
|
||||
}
|
||||
|
||||
/** 向子孙组件提供方法和值 */
|
||||
provide('setActiveApi', setActiveApi);
|
||||
provide('refreshModuleTree', refreshModuleTree);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
:filter-config-list="filterConfigList"
|
||||
:custom-fields-config-list="searchCustomFields"
|
||||
:search-placeholder="t('caseManagement.featureCase.searchPlaceholder')"
|
||||
:row-count="filterRowCount"
|
||||
:count="props.modulesCount[props.activeFolder] || 0"
|
||||
:name="moduleNamePath"
|
||||
@keyword-search="fetchData"
|
||||
|
@ -474,7 +473,6 @@
|
|||
const minderStore = useMinderStore();
|
||||
|
||||
const keyword = ref<string>('');
|
||||
const filterRowCount = ref(0);
|
||||
const groupKeyword = ref<string>('');
|
||||
|
||||
const showType = ref<string>('list');
|
||||
|
@ -776,7 +774,7 @@
|
|||
const filterConfigList = computed<FilterFormItem[]>(() => [
|
||||
{
|
||||
title: 'caseManagement.featureCase.tableColumnID',
|
||||
dataIndex: 'id',
|
||||
dataIndex: 'num',
|
||||
type: FilterType.INPUT,
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue