Skip to content

Commit

Permalink
feat(接口测试): pdf展示&部分 mock 页面
Browse files Browse the repository at this point in the history
  • Loading branch information
ba1q1 authored and liuruibin committed Apr 29, 2024
1 parent 10e3a7a commit 03bbdbf
Show file tree
Hide file tree
Showing 22 changed files with 431 additions and 69 deletions.
10 changes: 8 additions & 2 deletions frontend/src/assets/icon-font/iconfont.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@font-face {
font-family: iconfont; /* Project id 3462279 */
src: url('iconfont.woff2?t=1711511079663') format('woff2'), url('iconfont.woff?t=1711511079663') format('woff'),
url('iconfont.ttf?t=1711511079663') format('truetype'), url('iconfont.svg?t=1711511079663#iconfont') format('svg');
src: url('iconfont.woff2?t=1714372635707') format('woff2'), url('iconfont.woff?t=1714372635707') format('woff'),
url('iconfont.ttf?t=1714372635707') format('truetype'), url('iconfont.svg?t=1714372635707#iconfont') format('svg');
}
.iconfont {
font-size: 16px;
Expand All @@ -10,6 +10,12 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-icon_menu_unfold::before {
content: '\e7a9';
}
.icon-icon_menu_fold::before {
content: '\e7aa';
}
.icon-icon_stop::before {
content: '\e7a8';
}
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/assets/icon-font/iconfont.js

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions frontend/src/assets/icon-font/iconfont.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
"css_prefix_text": "icon-",
"description": "DE、MS项目icon管理",
"glyphs": [
{
"icon_id": "39725024",
"name": "icon_menu_unfold",
"font_class": "icon_menu_unfold",
"unicode": "e7a9",
"unicode_decimal": 59305
},
{
"icon_id": "39725023",
"name": "icon_menu_fold",
"font_class": "icon_menu_fold",
"unicode": "e7aa",
"unicode_decimal": 59306
},
{
"icon_id": "39710057",
"name": "icon_stop",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/assets/icon-font/iconfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/icon-font/iconfont.ttf
Binary file not shown.
Binary file modified frontend/src/assets/icon-font/iconfont.woff
Binary file not shown.
Binary file modified frontend/src/assets/icon-font/iconfont.woff2
Binary file not shown.
7 changes: 6 additions & 1 deletion frontend/src/components/business/ms-menu/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import { getFirstRouterNameByCurrentRoute } from '@/utils/permission';
import { listenerRouteChange } from '@/utils/route-listener';
import { ProjectManagementRouteEnum, SettingRouteEnum } from '@/enums/routeEnum';
import { ProjectManagementRouteEnum, RouteEnum, SettingRouteEnum } from '@/enums/routeEnum';
import useMenuTree from './use-menu-tree';
import type { RouteMeta } from 'vue-router';
Expand Down Expand Up @@ -123,6 +123,11 @@
selectedKey.value = [activeMenu || menuOpenKeys[menuOpenKeys.length - 1]];
}
if (newRoute.fullPath.includes(RouteEnum.SETTING)) {
appStore.updateSettings({ menuCollapse: false });
} else {
appStore.updateSettings({ menuCollapse: true });
}
}, true);
const setCollapse = (val: boolean) => {
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
class="no-content relative mt-[8px] border-b"
/>
</div>
<div ref="splitContainerRef" class="request-and-response h-[calc(100%-100px)]">
<div ref="splitContainerRef" class="request-and-response h-[calc(100%-92px)]">
<MsSplitBox
ref="verticalSplitBoxRef"
v-model:size="splitBoxSize"
Expand Down Expand Up @@ -991,8 +991,12 @@
const saveModalFormRef = ref<FormInstance>();
const saveLoading = ref(false);
const selectTree = computed(() => {
if (saveModalVisible.value || (!props.isCase && props.isDefinition && saveModalVisible.value)) {
// 调试模式打开保存弹窗,或者是接口定义模式下打开保存弹窗才进行计算,避免大数据量导致进入时就计算卡顿 TODO:worker线程处理计算任务
if (
requestVModel.value.activeTab === RequestComposition.BASE_INFO ||
saveModalVisible.value ||
(!props.isCase && props.isDefinition && saveModalVisible.value)
) {
// 切换到基础信息 tab、调试模式打开保存弹窗,或者是接口定义模式下打开保存弹窗才进行计算,避免大数据量导致进入时就计算卡顿 TODO:worker线程处理计算任务
return filterTree(cloneDeep(props.moduleTree || []), (e) => {
e.draggable = false;
return e.type === 'MODULE';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@
import { defaultKeyValueParamItem, defaultResponseItem, statusCodes } from '../../config';
const props = defineProps<{
responseDefinition: ResponseDefinition[];
uploadTempFileApi?: (file: File) => Promise<any>; // 上传临时文件接口
}>();
const emit = defineEmits<{
Expand All @@ -240,15 +239,25 @@
const responseTabs = defineModel<ResponseItem[]>('responseDefinition', {
required: true,
});
const activeResponse = ref<ResponseItem>(responseTabs.value[0] || defaultResponseItem);
const activeResponse = ref<ResponseItem>(responseTabs.value[0] || cloneDeep(defaultResponseItem));
watch(
() => responseTabs.value,
(arr) => {
if (arr.length > 0) {
[activeResponse.value] = arr;
}
}
);
function addResponseTab(defaultProps?: Partial<ResponseItem>) {
const id = new Date().getTime();
responseTabs.value.push({
...cloneDeep(defaultResponseItem),
label: t('apiTestManagement.response', { count: responseTabs.value.length + 1 }),
name: t('apiTestManagement.response', { count: responseTabs.value.length + 1 }),
...defaultProps,
id: new Date().getTime(),
id,
defaultFlag: false,
showPopConfirm: false,
showRenamePopConfirm: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div :class="['response-head', props.isExpanded ? '' : 'border-t']">
<slot name="titleLeft">
<div class="flex items-center justify-between">
<template v-if="props.activeLayout === 'vertical'">
<template v-if="activeLayout === 'vertical'">
<MsButton
v-if="props.isExpanded"
type="icon"
Expand Down Expand Up @@ -44,7 +44,7 @@
<div v-else class="ml-[4px] mr-[24px] font-medium">{{ t('apiTestDebug.responseContent') }}</div>
<a-radio-group
v-if="!props.hideLayoutSwitch"
v-model:model-value="innerLayout"
v-model:model-value="activeLayout"
type="button"
size="small"
@change="(val) => emit('changeLayout', val as Direction)"
Expand All @@ -62,14 +62,14 @@
:class="[isResponseModel ? 'h-[381px] w-full' : 'h-[calc(100%-35px)] w-full px-[16px] pb-[16px]']"
>
<edit
v-if="props.isEdit && activeResponseType === 'content' && innerResponseDefinition"
v-model:response-definition="innerResponseDefinition"
v-if="props.isEdit && activeResponseType === 'content' && responseDefinition"
v-model:response-definition="responseDefinition"
:upload-temp-file-api="props.uploadTempFileApi"
@change="handleResponseChange"
/>
<result
v-else-if="!props.isEdit || (props.isEdit && activeResponseType === 'result')"
v-model:active-tab="innerActiveTab"
v-model:active-tab="activeTab"
:request-result="props.requestResult"
:console="props.console"
:is-http-protocol="props.isHttpProtocol"
Expand Down Expand Up @@ -97,13 +97,10 @@
const props = withDefaults(
defineProps<{
activeTab: ResponseComposition;
isExpanded?: boolean;
isPriorityLocalExec?: boolean;
requestUrl?: string;
isHttpProtocol?: boolean;
activeLayout?: Direction;
responseDefinition?: ResponseItem[];
requestResult?: RequestResult;
console?: string;
hideLayoutSwitch?: boolean; // 隐藏布局切换
Expand All @@ -117,7 +114,6 @@
}>(),
{
isExpanded: true,
activeLayout: 'vertical',
hideLayoutSwitch: false,
showEmpty: true,
}
Expand All @@ -131,21 +127,21 @@
const { t } = useI18n();
const innerLayout = defineModel<Direction>('activeLayout', {
const activeLayout = defineModel<Direction>('activeLayout', {
default: 'vertical',
});
const innerActiveTab = defineModel<ResponseComposition>('activeTab', {
const activeTab = defineModel<ResponseComposition>('activeTab', {
required: true,
});
const innerResponseDefinition = defineModel<ResponseItem[]>('responseDefinition', {
const responseDefinition = defineModel<ResponseItem[]>('responseDefinition', {
default: [],
});
watchEffect(() => {
// 过滤无效数据后的有效响应数据;当接口导入时会存在部分字段为 null 的数据,需要设置默认值
let hasInvalid = false;
let validResponseDefinition: ResponseItem[] = [];
if (props.responseDefinition && props.responseDefinition.length > 0) {
validResponseDefinition = props.responseDefinition.map((item, i) => {
if (responseDefinition.value.length > 0) {
validResponseDefinition = responseDefinition.value.map((item, i) => {
// 某些字段在导入时接口返回 null,需要设置默认值
if (!item.headers) {
item.headers = [];
Expand Down Expand Up @@ -189,7 +185,7 @@
});
}
if (hasInvalid) {
innerResponseDefinition.value = validResponseDefinition;
responseDefinition.value = validResponseDefinition;
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
<template>
<div v-if="showImg">
<div v-if="showImg || isPdf" :class="showType === 'text' ? '' : 'h-full'">
<div class="mb-[8px] flex items-center gap-[16px]">
<a-button type="outline" class="arco-btn-outline--secondary" size="mini" @click="handleDownload">
{{ t('common.download') }}
</a-button>
<a-radio-group v-model:model-value="showType" type="button" size="small">
<a-radio value="image">{{ t('common.image') }}</a-radio>
<a-radio v-if="isPdf" value="pdf">pdf</a-radio>
<a-radio v-else value="image">{{ t('common.image') }}</a-radio>
<a-radio value="text">{{ t('common.text') }}</a-radio>
</a-radio-group>
</div>
<a-image v-show="showType === 'image'" :src="imageUrl"></a-image>
<object
v-if="isPdf && showType === 'pdf'"
:data="imageUrl"
type="application/pdf"
width="100%"
style="height: calc(100% - 30px)"
></object>
<a-image v-else-if="showType === 'image'" :src="imageUrl"></a-image>
</div>
<MsCodeEditor
v-show="!showImg || showType === 'text'"
v-show="(!showImg && !isPdf) || showType === 'text'"
ref="responseEditorRef"
:model-value="props.requestResult?.responseResult.body || ''"
:language="responseLanguage"
Expand Down Expand Up @@ -81,17 +89,37 @@
}
return false;
});
const isPdf = computed(() => {
if (props.requestResult) {
return props.requestResult.responseResult.contentType === 'application/pdf';
}
return false;
});
const imageUrl = computed(() => {
if (props.requestResult) {
return `data:${props.requestResult?.responseResult.contentType};base64,${props.requestResult?.responseResult.imageUrl}`;
}
return '';
});
const showType = ref<'image' | 'text'>('image');
const showType = ref<'image' | 'pdf' | 'text'>('image');
watchEffect(() => {
if (props.requestResult) {
if (showImg.value) {
showType.value = 'image';
} else if (isPdf.value) {
showType.value = 'pdf';
} else {
showType.value = 'text';
}
}
});
function handleDownload() {
if (imageUrl.value) {
if (isPdf.value) {
downloadUrlFile(imageUrl.value, 'response.pdf');
} else if (imageUrl.value) {
downloadUrlFile(imageUrl.value, `response.${props.requestResult?.responseResult.contentType.split('/')[1]}`);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,19 @@
:member-options="memberOptions"
/>
</a-tab-pane>
<!-- <a-tab-pane v-if="!activeApiTab.isNew" key="mock" title="MOCK" class="ms-api-tab-pane"> </a-tab-pane> -->
<a-tab-pane
v-if="!activeApiTab.isNew && activeApiTab.protocol === 'HTTP'"
key="mock"
title="MOCK"
class="ms-api-tab-pane"
>
<mockTable
:active-module="props.activeModule"
:offspring-ids="props.offspringIds"
:protocol="activeApiTab.protocol"
is-api
/>
</a-tab-pane>
</a-tabs>
</div>
</div>
Expand All @@ -115,7 +127,6 @@
import { cloneDeep } from 'lodash-es';
import { TabItem } from '@/components/pure/ms-editable-tab/types';
import caseTable from '../case/caseTable.vue';
// import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
import apiTable from './apiTable.vue';
import executeButton from '@/views/api-test/components/executeButton.vue';
Expand Down Expand Up @@ -156,6 +167,8 @@
() => import('@/views/api-test/components/requestComposition/index.vue')
);
const preview = defineAsyncComponent(() => import('./preview/index.vue'));
const mockTable = defineAsyncComponent(() => import('../mock/mockTable.vue'));
const caseTable = defineAsyncComponent(() => import('../case/caseTable.vue'));
const props = defineProps<{
activeModule: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
</div>
</template>
<template #num="{ record }">
<MsButton type="text" @click="isApi ? openCaseDetailDrawer(record.id) : openCaseTab(record)">{{
record.num
}}</MsButton>
<MsButton type="text" @click="isApi ? openCaseDetailDrawer(record.id) : openCaseTab(record)">
{{ record.num }}
</MsButton>
</template>
<template #caseLevel="{ record }">
<a-select
Expand Down
Loading

0 comments on commit 03bbdbf

Please sign in to comment.