mirror of
https://gitee.com/fit2cloud-feizhiyun/MeterSphere.git
synced 2024-11-30 11:08:38 +08:00
feat(接口测试): 导入导出
This commit is contained in:
parent
1ea2d56b07
commit
6c82da4de5
@ -107,8 +107,8 @@ import {
|
||||
ApiCaseExecuteHistoryParams,
|
||||
ApiCasePageParams,
|
||||
ApiDefinitionBatchDeleteParams,
|
||||
type ApiDefinitionBatchExportParams,
|
||||
ApiDefinitionBatchMoveParams,
|
||||
ApiDefinitionBatchParams,
|
||||
ApiDefinitionBatchUpdateParams,
|
||||
ApiDefinitionCreateParams,
|
||||
ApiDefinitionDeleteParams,
|
||||
@ -593,6 +593,6 @@ export function getCaseReportDetail(reportId: string, stepId: string) {
|
||||
}
|
||||
|
||||
// 导出定义
|
||||
export function exportApiDefinition(data: ApiDefinitionBatchParams, type: string) {
|
||||
export function exportApiDefinition(data: ApiDefinitionBatchExportParams, type: string) {
|
||||
return MSR.post({ url: `${ExportDefinitionUrl}/${type}`, data });
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 519 KiB After Width: | Height: | Size: 267 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -129,6 +129,7 @@ export interface MsTableProps<T> {
|
||||
paginationSize?: 'small' | 'mini' | 'medium' | 'large';
|
||||
// 行选择器禁用配置
|
||||
rowSelectionDisabledConfig?: MsTableRowSelectionDisabledConfig;
|
||||
sorter?: Record<string, any>; // 排序
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
|
@ -399,6 +399,7 @@ export default function useTableProps<T>(
|
||||
sortItem.value = sortObj;
|
||||
setTableDraggable(Object.keys(sortItem.value).length === 0);
|
||||
loadList();
|
||||
propsRes.value.sorter = sortObj;
|
||||
},
|
||||
|
||||
// 筛选触发
|
||||
@ -452,6 +453,7 @@ export default function useTableProps<T>(
|
||||
// 重置排序
|
||||
resetSort: () => {
|
||||
sortItem.value = {};
|
||||
propsRes.value.sorter = {};
|
||||
},
|
||||
// 重置筛选
|
||||
clearSelector: () => {
|
||||
|
@ -76,6 +76,14 @@ export const FileIconMap: FileIconMapping = {
|
||||
[UploadStatus.init]: 'icon-a-icon_file-json',
|
||||
[UploadStatus.done]: 'icon-a-icon_file-json',
|
||||
},
|
||||
jmx: {
|
||||
[UploadStatus.init]: 'icon-a-icon_file-JMX',
|
||||
[UploadStatus.done]: 'icon-a-icon_file-JMX',
|
||||
},
|
||||
har: {
|
||||
[UploadStatus.init]: 'icon-icon_file_har',
|
||||
[UploadStatus.done]: 'icon-icon_file_har',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -80,11 +80,10 @@ export enum ApiScenarioStatus {
|
||||
// 接口导入支持格式
|
||||
export enum RequestImportFormat {
|
||||
SWAGGER = 'Swagger3',
|
||||
// MeterSphere = 'MeterSphere',
|
||||
// Postman= 'Postman',
|
||||
// Plugin = 'Plugin',
|
||||
// Jmeter = 'Jmeter',
|
||||
// Har = 'Har',
|
||||
MeterSphere = 'MeterSphere',
|
||||
Postman = 'Postman',
|
||||
Jmeter = 'Jmeter',
|
||||
Har = 'Har',
|
||||
}
|
||||
// 接口导入方式
|
||||
export enum RequestImportType {
|
||||
|
@ -16,6 +16,8 @@ export enum UploadAcceptEnum {
|
||||
none = 'none',
|
||||
unknown = 'unknown',
|
||||
json = '.json',
|
||||
jmx = '.jmx',
|
||||
har = '.har',
|
||||
}
|
||||
|
||||
export enum UploadStatus {
|
||||
|
@ -183,6 +183,12 @@ export interface mockParams {
|
||||
export interface ApiDefinitionBatchParams extends BatchApiParams {
|
||||
protocols: string[];
|
||||
}
|
||||
// 批量导出定义参数
|
||||
export interface ApiDefinitionBatchExportParams extends ApiDefinitionBatchParams {
|
||||
exportApiCase: boolean;
|
||||
exportApiMock: boolean;
|
||||
sort: Record<string, any>;
|
||||
}
|
||||
// 批量更新定义参数
|
||||
export interface ApiDefinitionBatchUpdateParams extends ApiDefinitionBatchParams {
|
||||
type?: string;
|
||||
|
@ -2,42 +2,34 @@
|
||||
<div>
|
||||
<MsDrawer
|
||||
v-model:visible="visible"
|
||||
width="100%"
|
||||
:popup-container="props.popupContainer"
|
||||
:width="960"
|
||||
:title="t('apiTestManagement.importApi')"
|
||||
:closable="false"
|
||||
:ok-disabled="disabledConfirm"
|
||||
:ok-text="t('common.import')"
|
||||
:ok-loading="importLoading"
|
||||
disabled-width-drag
|
||||
desc
|
||||
no-title
|
||||
@confirm="confirmImport"
|
||||
@cancel="cancelImport"
|
||||
>
|
||||
<div class="flex items-center justify-between p-[12px_8px]">
|
||||
<div class="font-medium text-[var(--color-text-1)]">{{ t('apiTestManagement.importApi') }}</div>
|
||||
<a-radio-group v-model:model-value="importForm.type" type="button">
|
||||
<a-radio :value="RequestImportType.API">{{ t('apiTestManagement.fileImport') }}</a-radio>
|
||||
<a-radio :value="RequestImportType.SCHEDULE">{{ t('apiTestManagement.timeImport') }}</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div
|
||||
v-if="importType === 'file'"
|
||||
class="my-[16px] flex items-center gap-[16px] rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[16px]"
|
||||
>
|
||||
<div v-if="importType === 'file'" class="mb-[16px] flex items-center gap-[16px]">
|
||||
<div
|
||||
v-for="item of platformList"
|
||||
:key="item.value"
|
||||
:class="`import-item ${importForm.platform === item.value ? 'import-item--active' : ''}`"
|
||||
@click="() => setActiveImportFormat(item.value)"
|
||||
>
|
||||
<div class="flex h-[24px] w-[24px] items-center justify-center rounded-[var(--border-radius-small)] bg-white">
|
||||
<MsIcon :type="item.icon" :class="`text-[${item.iconColor}]`" :size="18" />
|
||||
</div>
|
||||
<div class="text-[var(--color-text-1)]">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-form ref="importFormRef" :model="importForm" layout="vertical">
|
||||
<a-form-item :label="t('apiTestManagement.importType')">
|
||||
<a-radio-group v-model:model-value="importForm.type" type="button">
|
||||
<a-radio :value="RequestImportType.API">{{ t('apiTestManagement.fileImport') }}</a-radio>
|
||||
<a-radio :value="RequestImportType.SCHEDULE">{{ t('apiTestManagement.timeImport') }}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<template v-if="importForm.type === RequestImportType.API">
|
||||
<a-form-item :label="t('apiTestManagement.belongModule')">
|
||||
<a-tree-select
|
||||
@ -57,56 +49,58 @@
|
||||
</template>
|
||||
</a-tree-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center gap-[2px]">
|
||||
{{ t('apiTestManagement.importMode') }}
|
||||
<a-tooltip position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
<template #content>
|
||||
<div>{{ t('apiTestManagement.importModeTip1') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip2') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip3') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip4') }}</div>
|
||||
<div class="h-[22px] w-full"></div>
|
||||
<div>{{ t('apiTestManagement.importModeTip5') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip6') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip7') }}</div>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<a-select v-model:model-value="importForm.coverData" class="w-[240px]">
|
||||
<a-option :value="true">{{ t('apiTestManagement.cover') }}</a-option>
|
||||
<a-option :value="false">{{ t('apiTestManagement.uncover') }}</a-option>
|
||||
</a-select>
|
||||
<a-form-item :label="t('apiTestManagement.importMode')">
|
||||
<a-radio-group v-model:model-value="importForm.coverData">
|
||||
<a-radio :value="true">
|
||||
<div class="flex items-center gap-[2px]">
|
||||
{{ t('apiTestManagement.cover') }}
|
||||
<a-tooltip position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
<template #content>
|
||||
<div>{{ t('apiTestManagement.importModeTip1') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip2') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip3') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip4') }}</div>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-radio>
|
||||
<a-radio :value="false">
|
||||
<div class="flex items-center gap-[2px]">
|
||||
{{ t('apiTestManagement.uncover') }}
|
||||
<a-tooltip position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
<template #content>
|
||||
<div>{{ t('apiTestManagement.importModeTip5') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip6') }}</div>
|
||||
<div>{{ t('apiTestManagement.importModeTip7') }}</div>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-collapse v-model:active-key="moreSettingActive" :bordered="false" :show-expand-icon="false">
|
||||
<a-collapse-item :key="1">
|
||||
<template #header>
|
||||
<MsButton
|
||||
type="text"
|
||||
@click="() => (moreSettingActive.length > 0 ? (moreSettingActive = []) : (moreSettingActive = [1]))"
|
||||
>
|
||||
{{ t('apiTestDebug.moreSetting') }}
|
||||
<icon-down v-if="moreSettingActive.length > 0" class="text-rgb(var(--primary-5))" />
|
||||
<icon-right v-else class="text-rgb(var(--primary-5))" />
|
||||
</MsButton>
|
||||
</template>
|
||||
<div class="mt-[16px]">
|
||||
<a-checkbox v-model:model-value="importForm.syncCase" class="mr-[24px]">
|
||||
{{ t('apiTestManagement.syncImportCase') }}
|
||||
</a-checkbox>
|
||||
<a-checkbox v-if="importForm.coverData" v-model:model-value="importForm.coverModule">
|
||||
{{ t('apiTestManagement.syncUpdateDirectory') }}
|
||||
</a-checkbox>
|
||||
</div>
|
||||
</a-collapse-item>
|
||||
</a-collapse>
|
||||
<a-form-item :label="t('apiTestManagement.importType')" class="mt-[8px]">
|
||||
<div v-if="importForm.coverData" class="mb-[16px] flex items-center gap-[4px]">
|
||||
<a-switch v-model:model-value="importForm.coverModule" size="small" />
|
||||
{{ t('apiTestManagement.syncUpdateDirectory') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="[RequestImportFormat.MeterSphere, RequestImportFormat.Postman].includes(importForm.platform)"
|
||||
class="mb-[16px] flex items-center gap-[4px]"
|
||||
>
|
||||
<a-switch v-model:model-value="importForm.syncCase" size="small" />
|
||||
{{ t('apiTestManagement.syncImportCase') }}
|
||||
</div>
|
||||
<a-form-item
|
||||
v-if="importForm.platform === RequestImportFormat.SWAGGER"
|
||||
:label="t('apiTestManagement.importMethod')"
|
||||
>
|
||||
<a-radio-group v-model:model-value="importType" type="button">
|
||||
<a-radio value="file">{{ t('apiTestManagement.fileImport') }}</a-radio>
|
||||
<a-radio value="swaggerUrl">{{ t('apiTestManagement.urlImport') }}</a-radio>
|
||||
@ -115,20 +109,23 @@
|
||||
<MsUpload
|
||||
v-if="importType === 'file'"
|
||||
v-model:file-list="fileList"
|
||||
accept="json"
|
||||
:accept="uploadAccept"
|
||||
:auto-upload="false"
|
||||
draggable
|
||||
size-unit="MB"
|
||||
class="w-full"
|
||||
>
|
||||
<template #subText>
|
||||
<div class="flex">
|
||||
<div v-if="importForm.platform === RequestImportFormat.SWAGGER" class="flex">
|
||||
{{ t('apiTestManagement.importSwaggerFileTip1') }}
|
||||
<span class="text-[rgb(var(--warning-6))]" @click.stop="openLink">{{
|
||||
t('apiTestManagement.importSwaggerFileTip2')
|
||||
}}</span>
|
||||
<span class="text-[rgb(var(--warning-6))]" @click.stop="openLink">
|
||||
{{ t('apiTestManagement.importSwaggerFileTip2') }}
|
||||
</span>
|
||||
{{ t('apiTestManagement.importSwaggerFileTip3') }}
|
||||
</div>
|
||||
<div v-else-if="importForm.platform === RequestImportFormat.Postman" class="flex">
|
||||
{{ t('apiTestManagement.importPostmanFileTip') }}
|
||||
</div>
|
||||
</template>
|
||||
</MsUpload>
|
||||
<template v-else>
|
||||
@ -329,7 +326,6 @@
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsCronSelect from '@/components/pure/ms-cron-select/index.vue';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
@ -356,7 +352,6 @@
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
moduleTree: ModuleTreeNode[];
|
||||
popupContainer?: string;
|
||||
activeModule: string;
|
||||
}>();
|
||||
const emit = defineEmits(['update:visible', 'done']);
|
||||
@ -372,8 +367,22 @@
|
||||
{
|
||||
name: 'Swagger',
|
||||
value: RequestImportFormat.SWAGGER,
|
||||
icon: 'icon-icon_swagger',
|
||||
iconColor: 'rgb(var(--success-7))',
|
||||
},
|
||||
{
|
||||
name: 'Postman',
|
||||
value: RequestImportFormat.Postman,
|
||||
},
|
||||
{
|
||||
name: 'Har',
|
||||
value: RequestImportFormat.Har,
|
||||
},
|
||||
{
|
||||
name: 'Jmeter',
|
||||
value: RequestImportFormat.Jmeter,
|
||||
},
|
||||
{
|
||||
name: 'MeterSphere',
|
||||
value: RequestImportFormat.MeterSphere,
|
||||
},
|
||||
];
|
||||
const fileList = ref<MsFileItem[]>([]);
|
||||
@ -395,6 +404,18 @@
|
||||
};
|
||||
const importForm = ref({ ...defaultForm });
|
||||
const importFormRef = ref<FormInstance>();
|
||||
const uploadAccept = computed(() => {
|
||||
if ([RequestImportFormat.SWAGGER, RequestImportFormat.Postman].includes(importForm.value.platform)) {
|
||||
return 'json';
|
||||
}
|
||||
if (importForm.value.platform === RequestImportFormat.Har) {
|
||||
return 'har';
|
||||
}
|
||||
if (importForm.value.platform === RequestImportFormat.Jmeter) {
|
||||
return 'jmx';
|
||||
}
|
||||
return 'json';
|
||||
});
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
@ -426,6 +447,9 @@
|
||||
|
||||
function setActiveImportFormat(format: RequestImportFormat) {
|
||||
importForm.value.platform = format;
|
||||
if (format !== RequestImportFormat.SWAGGER) {
|
||||
importType.value = 'file';
|
||||
}
|
||||
}
|
||||
|
||||
function cancelImport() {
|
||||
@ -647,9 +671,10 @@
|
||||
@apply flex cursor-pointer items-center bg-white;
|
||||
|
||||
padding: 8px;
|
||||
gap: 6px;
|
||||
width: 200px;
|
||||
border: 1px solid var(--color-text-n8);
|
||||
border-radius: var(--border-radius-small);
|
||||
gap: 6px;
|
||||
}
|
||||
.import-item--active {
|
||||
border: 1px solid rgb(var(--primary-5));
|
||||
|
@ -252,6 +252,42 @@
|
||||
@folder-node-select="folderNodeSelect"
|
||||
/>
|
||||
</a-modal>
|
||||
<a-modal
|
||||
v-model:visible="showExportModal"
|
||||
:title="t('common.export')"
|
||||
title-align="start"
|
||||
class="ms-modal-upload ms-modal-medium"
|
||||
:width="400"
|
||||
>
|
||||
<div class="mb-[16px] flex gap-[8px]">
|
||||
<div
|
||||
v-for="item of platformList"
|
||||
:key="item.value"
|
||||
:class="`import-item ${exportPlatform === item.value ? 'import-item--active' : ''}`"
|
||||
@click="exportPlatform = item.value"
|
||||
>
|
||||
<div class="text-[var(--color-text-1)]">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-[16px] flex items-center gap-[4px]">
|
||||
<a-switch v-model:model-value="exportApiCase" size="small" />
|
||||
{{ t('apiTestManagement.exportCase') }}
|
||||
</div>
|
||||
<div class="flex items-center gap-[4px]">
|
||||
<a-switch v-model:model-value="exportApiMock" size="small" />
|
||||
{{ t('apiTestManagement.exportMock') }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<a-button type="secondary" :disabled="exportLoading" @click="cancelExport">
|
||||
{{ t('common.cancel') }}
|
||||
</a-button>
|
||||
<a-button class="ml-3" type="primary" :loading="exportLoading" @click="exportApi">
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -294,7 +330,7 @@
|
||||
import { ProtocolItem } from '@/models/apiTest/common';
|
||||
import { ApiDefinitionDetail, ApiDefinitionGetModuleParams } from '@/models/apiTest/management';
|
||||
import { DragSortParams } from '@/models/common';
|
||||
import { RequestDefinitionStatus, RequestMethods } from '@/enums/apiEnum';
|
||||
import { RequestDefinitionStatus, RequestImportFormat, RequestMethods } from '@/enums/apiEnum';
|
||||
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||
@ -385,7 +421,7 @@
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const apiTableRef = ref();
|
||||
let columns: MsTableColumn = [
|
||||
{
|
||||
title: 'ID',
|
||||
@ -568,12 +604,6 @@
|
||||
{
|
||||
label: 'common.export',
|
||||
eventTag: 'export',
|
||||
children: [
|
||||
{
|
||||
label: 'apiTestManagement.swagger.export',
|
||||
eventTag: 'exportSwagger',
|
||||
},
|
||||
],
|
||||
permission: ['PROJECT_API_DEFINITION:READ+EXPORT'],
|
||||
},
|
||||
{
|
||||
@ -939,27 +969,60 @@
|
||||
selectedModuleKeys.value = keys;
|
||||
}
|
||||
|
||||
const showExportModal = ref(false);
|
||||
const platformList = [
|
||||
{
|
||||
name: 'Swagger',
|
||||
value: RequestImportFormat.SWAGGER,
|
||||
},
|
||||
{
|
||||
name: 'MeterSphere',
|
||||
value: RequestImportFormat.MeterSphere,
|
||||
},
|
||||
];
|
||||
const exportPlatform = ref(RequestImportFormat.SWAGGER);
|
||||
const exportApiCase = ref(false);
|
||||
const exportApiMock = ref(false);
|
||||
const exportLoading = ref(false);
|
||||
|
||||
function cancelExport() {
|
||||
showExportModal.value = false;
|
||||
exportPlatform.value = RequestImportFormat.SWAGGER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出接口
|
||||
*/
|
||||
async function exportApi(type: string, record?: ApiDefinitionDetail, params?: BatchActionQueryParams) {
|
||||
const result = await exportApiDefinition(
|
||||
{
|
||||
selectIds: tableSelected.value as string[],
|
||||
selectAll: !!params?.selectAll,
|
||||
excludeIds: params?.excludeIds || [],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
async function exportApi() {
|
||||
try {
|
||||
exportLoading.value = true;
|
||||
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,
|
||||
exportApiCase: exportApiCase.value,
|
||||
exportApiMock: exportApiMock.value,
|
||||
sort: propsRes.value.sorter || {},
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
moduleIds: await getModuleIds(),
|
||||
protocols: props.selectedProtocols,
|
||||
},
|
||||
type
|
||||
);
|
||||
const res = await getProjectInfo(appStore.currentProjectId);
|
||||
downloadByteFile(new Blob([JSON.stringify(result)]), `Swagger_Api_${res.name}.json`);
|
||||
exportPlatform.value
|
||||
);
|
||||
const res = await getProjectInfo(appStore.currentProjectId);
|
||||
downloadByteFile(new Blob([JSON.stringify(result)]), `Swagger_Api_${res.name}.json`);
|
||||
showExportModal.value = false;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
exportLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -970,8 +1033,8 @@
|
||||
tableSelected.value = params?.selectedIds || [];
|
||||
batchParams.value = params;
|
||||
switch (event.eventTag) {
|
||||
case 'exportSwagger':
|
||||
exportApi('swagger', undefined, params);
|
||||
case 'export':
|
||||
showExportModal.value = true;
|
||||
break;
|
||||
case 'delete':
|
||||
deleteApi(undefined, true, params);
|
||||
@ -1020,7 +1083,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
const apiTableRef = ref();
|
||||
watch(
|
||||
() => requestMethodsOptions.value,
|
||||
() => {
|
||||
@ -1030,6 +1092,19 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.import-item {
|
||||
@apply flex cursor-pointer items-center bg-white;
|
||||
|
||||
padding: 8px;
|
||||
width: 150px;
|
||||
border: 1px solid var(--color-text-n8);
|
||||
border-radius: var(--border-radius-small);
|
||||
gap: 6px;
|
||||
}
|
||||
.import-item--active {
|
||||
border: 1px solid rgb(var(--primary-5));
|
||||
background-color: rgb(var(--primary-1));
|
||||
}
|
||||
:deep(.param-input:not(.arco-input-focus, .arco-select-view-focus)) {
|
||||
&:not(:hover) {
|
||||
border-color: transparent !important;
|
||||
|
@ -1,48 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<template v-if="!props.isModal">
|
||||
<div class="mb-[8px] flex items-center gap-[8px]">
|
||||
<a-input
|
||||
v-model:model-value="moduleKeyword"
|
||||
:placeholder="props.isModal ? t('apiTestManagement.moveSearchTip') : t('apiTestManagement.searchTip')"
|
||||
allow-clear
|
||||
/>
|
||||
<template v-if="!props.readOnly && !props.trash">
|
||||
<a-dropdown-button
|
||||
v-if="hasAllPermission(['PROJECT_API_DEFINITION:READ+ADD', 'PROJECT_API_DEFINITION:READ+IMPORT'])"
|
||||
type="primary"
|
||||
@click="handleSelect('newApi')"
|
||||
>
|
||||
{{ t('common.newCreate') }}
|
||||
<template #icon>
|
||||
<icon-down />
|
||||
</template>
|
||||
<template #content>
|
||||
<a-doption value="import" @click="handleSelect('import')">
|
||||
{{ t('apiTestManagement.importApi') }}
|
||||
</a-doption>
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
<a-button
|
||||
v-else-if="
|
||||
!hasAnyPermission(['PROJECT_API_DEFINITION:READ+ADD']) &&
|
||||
hasAnyPermission(['PROJECT_API_DEFINITION:READ+IMPORT'])
|
||||
"
|
||||
type="primary"
|
||||
@click="handleSelect('import')"
|
||||
>
|
||||
{{ t('apiTestManagement.importApi') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else
|
||||
v-permission="['PROJECT_API_DEFINITION:READ+ADD']"
|
||||
type="primary"
|
||||
@click="handleSelect('newApi')"
|
||||
>
|
||||
{{ t('apiTestManagement.newApi') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<div v-if="!props.readOnly && !props.trash" class="mb-[8px] flex items-center gap-[8px]">
|
||||
<a-button
|
||||
v-permission="['PROJECT_API_DEFINITION:READ+ADD']"
|
||||
type="primary"
|
||||
long
|
||||
@click="handleSelect('newApi')"
|
||||
>
|
||||
{{ t('apiTestManagement.newApi') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-permission="['PROJECT_API_DEFINITION:READ+IMPORT']"
|
||||
type="outline"
|
||||
long
|
||||
@click="handleSelect('import')"
|
||||
>
|
||||
{{ t('apiTestManagement.importApi') }}
|
||||
</a-button>
|
||||
</div>
|
||||
<a-input
|
||||
v-model:model-value="moduleKeyword"
|
||||
:placeholder="props.isModal ? t('apiTestManagement.moveSearchTip') : t('apiTestManagement.searchTip')"
|
||||
class="mb-[8px]"
|
||||
allow-clear
|
||||
/>
|
||||
<TreeFolderAll
|
||||
v-if="!props.readOnly"
|
||||
ref="treeFolderAllRef"
|
||||
@ -193,7 +175,7 @@
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import { characterLimit, mapTree } from '@/utils';
|
||||
import { getLocalStorage } from '@/utils/local-storage';
|
||||
import { hasAllPermission, hasAnyPermission } from '@/utils/permission';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
import { ApiDefinitionGetModuleParams } from '@/models/apiTest/management';
|
||||
import { ModuleTreeNode } from '@/models/common';
|
||||
|
@ -79,14 +79,17 @@ export default {
|
||||
'apiTestManagement.cover': 'Cover',
|
||||
'apiTestManagement.uncover': 'Do Not Cover',
|
||||
'apiTestManagement.moreSetting': 'More Settings',
|
||||
'apiTestManagement.importType': 'Import Type',
|
||||
'apiTestManagement.importMethod': 'Import Method',
|
||||
'apiTestManagement.urlImport': 'URL Import',
|
||||
'apiTestManagement.swagger.export': 'Export Swagger3.0(Only supports HTTP protocol)',
|
||||
'apiTestManagement.exportCase': 'Synchronous export use case',
|
||||
'apiTestManagement.exportMock': 'Export Mock Synchronously',
|
||||
'apiTestManagement.syncImportCase': 'Sync Import API Cases',
|
||||
'apiTestManagement.syncUpdateDirectory': 'Sync Update API Directory',
|
||||
'apiTestManagement.importSwaggerFileTip1': 'Supports Swagger 3.0 version JSON files,',
|
||||
'apiTestManagement.importSwaggerFileTip2': '2.0 files can be converted to 3.0 on the official website',
|
||||
'apiTestManagement.importSwaggerFileTip3': 'with a size limit of 50MB',
|
||||
'apiTestManagement.importPostmanFileTip':
|
||||
'Postman only supports file import, and only supports json files in v2.1 format',
|
||||
'apiTestManagement.urlImportPlaceholder': 'Please enter OpenAPI/URL',
|
||||
'apiTestManagement.swaggerURLRequired': 'Swagger URL cannot be empty',
|
||||
'apiTestManagement.basicAuth': 'Basic Auth',
|
||||
|
@ -1,6 +1,7 @@
|
||||
export default {
|
||||
'apiTestManagement.newApi': '新建请求',
|
||||
'apiTestManagement.newApi': '新建接口',
|
||||
'apiTestManagement.importApi': '导入接口',
|
||||
'apiTestManagement.importType': '导入类型',
|
||||
'apiTestManagement.fileImport': '文件导入',
|
||||
'apiTestManagement.timeImport': '定时导入',
|
||||
'apiTestManagement.timeTask': '定时任务',
|
||||
@ -74,14 +75,16 @@ export default {
|
||||
'apiTestManagement.cover': '覆盖',
|
||||
'apiTestManagement.uncover': '不覆盖',
|
||||
'apiTestManagement.moreSetting': '更多设置',
|
||||
'apiTestManagement.importType': '导入方式',
|
||||
'apiTestManagement.importMethod': '导入方式',
|
||||
'apiTestManagement.urlImport': 'URL 导入',
|
||||
'apiTestManagement.swagger.export': '导出 Swagger3.0 格式(仅支持HTTP协议)',
|
||||
'apiTestManagement.exportCase': '同步导出用例',
|
||||
'apiTestManagement.exportMock': '同步导出 Mock',
|
||||
'apiTestManagement.syncImportCase': '同步导入接口用例',
|
||||
'apiTestManagement.syncUpdateDirectory': '同步更新接口所在目录',
|
||||
'apiTestManagement.importSwaggerFileTip1': '支持 Swagger 3.0 版本的 json 文件,',
|
||||
'apiTestManagement.importSwaggerFileTip2': '2.0 文件可以在官网一键转换 3.0',
|
||||
'apiTestManagement.importSwaggerFileTip3': ',大小不超过 50M',
|
||||
'apiTestManagement.importPostmanFileTip': 'Postman仅支持文件导入,且只支持v2.1格式的json文件',
|
||||
'apiTestManagement.urlImportPlaceholder': '请输入OpenAPI/URL',
|
||||
'apiTestManagement.swaggerURLRequired': 'SwaggerURL 不能为空',
|
||||
'apiTestManagement.basicAuth': 'Basic Auth 认证',
|
||||
|
Loading…
Reference in New Issue
Block a user