style: 接口调试/用例/定义/场景展示布局优化

This commit is contained in:
teukkk 2024-05-06 20:11:39 +08:00 committed by Craftsman
parent f4fb8a7a04
commit ecae5a4d99
21 changed files with 626 additions and 896 deletions

View File

@ -364,9 +364,10 @@
<style lang="less" scoped> <style lang="less" scoped>
.ms-code-editor { .ms-code-editor {
@apply z-10; @apply z-10;
// TODO:
width: v-bind(width); width: v-bind(width);
height: v-bind(height); height: v-bind(height);
min-height: 200px;
// &.MS-text[data-mode-id='plaintext'] { // &.MS-text[data-mode-id='plaintext'] {
// :deep(.mtk1) { // :deep(.mtk1) {
// color: rgb(var(--primary-5)); // color: rgb(var(--primary-5));

View File

@ -342,7 +342,7 @@
.handle { .handle {
@apply absolute left-0 top-0 flex h-full items-center; @apply absolute left-0 top-0 flex h-full items-center;
z-index: 10; z-index: 200;
width: 8px; width: 8px;
background-color: var(--color-neutral-3); background-color: var(--color-neutral-3);
cursor: col-resize; cursor: col-resize;

View File

@ -231,7 +231,6 @@
:disabled-param-value="props.disabled" :disabled-param-value="props.disabled"
:scroll="{ x: '100%' }" :scroll="{ x: '100%' }"
:columns="scriptColumns" :columns="scriptColumns"
:height-used="heightUsed"
:selectable="false" :selectable="false"
@change="() => emit('change')" @change="() => emit('change')"
/> />
@ -375,7 +374,6 @@
:selectable="false" :selectable="false"
:scroll="{ x: '700px' }" :scroll="{ x: '700px' }"
:response="props.response" :response="props.response"
:height-used="props.heightUsed"
@change="handleExtractParamTableChange" @change="handleExtractParamTableChange"
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)" @more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
> >
@ -529,7 +527,6 @@
defineProps<{ defineProps<{
disabled?: boolean; disabled?: boolean;
response?: string; // response?: string; //
heightUsed?: number;
isBuildIn?: boolean; // isBuildIn?: boolean; //
showAssociatedScene?: boolean; // showAssociatedScene?: boolean; //
requestRadioTextProps?: Record<string, any>; // requestRadioTextProps?: Record<string, any>; //

View File

@ -39,7 +39,6 @@
:disabled="props.disabled" :disabled="props.disabled"
:total-list="list" :total-list="list"
:response="props.response" :response="props.response"
:height-used="props.heightUsed"
:show-associated-scene="props.showAssociatedScene" :show-associated-scene="props.showAssociatedScene"
:show-pre-post-request="props.showPrePostRequest" :show-pre-post-request="props.showPrePostRequest"
:request-radio-text-props="props.requestRadioTextProps" :request-radio-text-props="props.requestRadioTextProps"
@ -70,7 +69,6 @@
conditionTypes: Array<ConditionType>; conditionTypes: Array<ConditionType>;
addText: string; addText: string;
requestRadioTextProps?: Record<string, any>; requestRadioTextProps?: Record<string, any>;
heightUsed?: number;
response?: string; // response?: string; //
showAssociatedScene?: boolean; showAssociatedScene?: boolean;
showPrePostRequest?: boolean; // showPrePostRequest?: boolean; //

View File

@ -25,7 +25,6 @@
:draggable="!props.disabledExceptParam" :draggable="!props.disabledExceptParam"
:scroll="{ minWidth: 1160 }" :scroll="{ minWidth: 1160 }"
:columns="columns" :columns="columns"
:height-used="heightUsed"
:show-setting="true" :show-setting="true"
:table-key="TableKeyEnum.API_TEST_DEBUG_FORM_DATA" :table-key="TableKeyEnum.API_TEST_DEBUG_FORM_DATA"
:default-param-item="defaultBodyParamsItem" :default-param-item="defaultBodyParamsItem"
@ -44,7 +43,6 @@
:draggable="!props.disabledExceptParam" :draggable="!props.disabledExceptParam"
:scroll="{ minWidth: 1160 }" :scroll="{ minWidth: 1160 }"
:columns="columns" :columns="columns"
:height-used="heightUsed"
:show-setting="true" :show-setting="true"
:table-key="TableKeyEnum.API_TEST_DEBUG_FORM_URL_ENCODE" :table-key="TableKeyEnum.API_TEST_DEBUG_FORM_URL_ENCODE"
:default-param-item="defaultBodyParamsItem" :default-param-item="defaultBodyParamsItem"
@ -135,11 +133,8 @@
const props = defineProps<{ const props = defineProps<{
params: ExecuteBody; params: ExecuteBody;
layout: 'horizontal' | 'vertical';
disabledParamValue?: boolean; // disabledParamValue?: boolean; //
disabledExceptParam?: boolean; // disabledExceptParam?: boolean; //
secondBoxHeight: number;
isDrawer?: boolean;
uploadTempFileApi?: (file: File) => Promise<any>; // uploadTempFileApi?: (file: File) => Promise<any>; //
fileSaveAsSourceId?: string | number; // id fileSaveAsSourceId?: string | number; // id
fileSaveAsApi?: (params: TransferFileParams) => Promise<string>; // fileSaveAsApi?: (params: TransferFileParams) => Promise<string>; //
@ -260,31 +255,6 @@
]; ];
}); });
const heightUsed = ref<number | undefined>(undefined);
watch(
() => props.layout,
(val) => {
const otherHeight = props.isDrawer ? 328 : 372;
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
},
{
immediate: true,
}
);
watch(
() => props.secondBoxHeight,
(val) => {
if (props.layout === 'vertical') {
heightUsed.value = (props.isDrawer ? 328 : 372) + val;
}
},
{
immediate: true,
}
);
const showParamTable = computed(() => { const showParamTable = computed(() => {
// FORM_DATAX_WWW_FORM_URLENCODED // FORM_DATAX_WWW_FORM_URLENCODED
return [RequestBodyFormat.FORM_DATA, RequestBodyFormat.WWW_FORM].includes(innerParams.value.bodyType); return [RequestBodyFormat.FORM_DATA, RequestBodyFormat.WWW_FORM].includes(innerParams.value.bodyType);

View File

@ -7,7 +7,6 @@
:disabled-param-value="props.disabledParamValue" :disabled-param-value="props.disabledParamValue"
:disabled-except-param="props.disabledExceptParam" :disabled-except-param="props.disabledExceptParam"
:columns="columns" :columns="columns"
:height-used="heightUsed"
:scroll="scroll" :scroll="scroll"
:default-param-item="defaultHeaderParamsItem" :default-param-item="defaultHeaderParamsItem"
:draggable="!props.disabledExceptParam" :draggable="!props.disabledExceptParam"
@ -41,11 +40,9 @@
const props = defineProps<{ const props = defineProps<{
params: EnableKeyValueParam[]; params: EnableKeyValueParam[];
layout: 'horizontal' | 'vertical'; layout: 'horizontal' | 'vertical';
secondBoxHeight: number;
disabledParamValue?: boolean; // disabledParamValue?: boolean; //
disabledExceptParam?: boolean; // disabledExceptParam?: boolean; //
typeTitle?: string; typeTitle?: string;
isDrawer?: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:selectedKeys', value: string[]): void; (e: 'update:selectedKeys', value: string[]): void;
@ -88,12 +85,6 @@
]); ]);
const batchAddKeyValVisible = ref(false); const batchAddKeyValVisible = ref(false);
const heightUsed = computed(() => {
if (props.layout === 'horizontal') {
return props.isDrawer ? 328 : 372;
}
return (props.isDrawer ? 328 : 372) + props.secondBoxHeight;
});
const scroll = computed(() => (props.layout === 'horizontal' ? { x: '700px' } : { x: '100%' })); const scroll = computed(() => (props.layout === 'horizontal' ? { x: '700px' } : { x: '100%' }));
/** /**

View File

@ -187,153 +187,122 @@
<div v-if="isUrlError" class="url-input-tip"> <div v-if="isUrlError" class="url-input-tip">
<span>{{ t('apiTestDebug.apiUrlRequired') }}</span> <span>{{ t('apiTestDebug.apiUrlRequired') }}</span>
</div> </div>
<div class="px-[16px]"> <div :class="`${!props.isCase ? 'request-tab-and-response' : ''} mt-[8px] flex-1`">
<MsTab <MsTab
v-model:active-key="requestVModel.activeTab" v-model:active-key="requestVModel.activeTab"
:content-tab-list="contentTabList" :content-tab-list="contentTabList"
:get-text-func="getTabBadge" :get-text-func="getTabBadge"
class="no-content relative mt-[8px] border-b" class="sticky-content no-content relative top-0 border-b px-[16px]"
/> />
</div> <div :class="`request-content-and-response ${activeLayout}`">
<div ref="splitContainerRef" class="request-and-response h-[calc(100%-92px)]"> <a-spin class="request" :loading="requestVModel.executeLoading || loading">
<MsSplitBox <div class="request-tab-pane flex flex-col p-[16px]">
ref="verticalSplitBoxRef" <apiBaseForm
v-model:size="splitBoxSize" v-if="!props.isCase && props.isDefinition"
:max="!showResponse ? 1 : 0.98" v-show="requestVModel.activeTab === RequestComposition.BASE_INFO"
min="10px" ref="apiBaseFormRef"
:direction="activeLayout" v-model:requestVModel="requestVModel"
second-container-class="!overflow-y-hidden" :select-tree="selectTree as ModuleTreeNode[]"
:class="!showResponse ? 'hidden-second' : 'show-second'" />
@expand-change="handleVerticalExpandChange" <a-spin
> v-show="requestVModel.activeTab === RequestComposition.PLUGIN"
<template #first> :loading="pluginLoading"
<a-spin class="block h-full w-full" :loading="requestVModel.executeLoading || loading"> class="min-h-[100px] w-full"
<div
:class="`flex h-full min-w-[800px] flex-col p-[16px] ${
activeLayout === 'horizontal' ? ' pr-[16px]' : ''
}`"
> >
<div class="tab-pane-container"> <MsFormCreate
<apiBaseForm v-model:api="fApi"
v-if="!props.isCase && props.isDefinition" :rule="currentPluginScript"
v-show="requestVModel.activeTab === RequestComposition.BASE_INFO" :option="currentPluginOptions"
ref="apiBaseFormRef" @change="
v-model:requestVModel="requestVModel" () => {
:select-tree="selectTree as ModuleTreeNode[]" if (isInitPluginForm) {
/> handlePluginFormChange();
<a-spin }
v-show="requestVModel.activeTab === RequestComposition.PLUGIN" }
:loading="pluginLoading" "
class="min-h-[100px] w-full" />
> </a-spin>
<MsFormCreate <httpHeader
v-model:api="fApi" v-if="requestVModel.activeTab === RequestComposition.HEADER"
:rule="currentPluginScript" v-model:params="requestVModel.headers"
:option="currentPluginOptions" :layout="activeLayout"
@change=" @change="handleActiveDebugChange"
() => { />
if (isInitPluginForm) { <httpBody
handlePluginFormChange(); v-else-if="requestVModel.activeTab === RequestComposition.BODY"
} v-model:params="requestVModel.body"
} :upload-temp-file-api="props.uploadTempFileApi"
" :file-save-as-source-id="props.fileSaveAsSourceId"
/> :file-save-as-api="props.fileSaveAsApi"
</a-spin> :file-module-options-api="props.fileModuleOptionsApi"
<httpHeader @change="handleActiveDebugChange"
v-if="requestVModel.activeTab === RequestComposition.HEADER" />
v-model:params="requestVModel.headers" <httpQuery
:layout="activeLayout" v-else-if="requestVModel.activeTab === RequestComposition.QUERY"
:second-box-height="secondBoxHeight" v-model:params="requestVModel.query"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<httpBody <httpRest
v-else-if="requestVModel.activeTab === RequestComposition.BODY" v-else-if="requestVModel.activeTab === RequestComposition.REST"
v-model:params="requestVModel.body" v-model:params="requestVModel.rest"
:layout="activeLayout" @change="handleActiveDebugChange"
:second-box-height="secondBoxHeight" />
:upload-temp-file-api="props.uploadTempFileApi" <precondition
:file-save-as-source-id="props.fileSaveAsSourceId" v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION"
:file-save-as-api="props.fileSaveAsApi" v-model:config="requestVModel.children[0].preProcessorConfig"
:file-module-options-api="props.fileModuleOptionsApi" :is-definition="props.isDefinition"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<httpQuery <postcondition
v-else-if="requestVModel.activeTab === RequestComposition.QUERY" v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
v-model:params="requestVModel.query" v-model:config="requestVModel.children[0].postProcessorConfig"
:layout="activeLayout" :response="requestVModel.response?.requestResults[0]?.responseResult.body"
:second-box-height="secondBoxHeight" :is-definition="props.isDefinition"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<httpRest <assertion
v-else-if="requestVModel.activeTab === RequestComposition.REST" v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
v-model:params="requestVModel.rest" v-model:params="requestVModel.children[0].assertionConfig.assertions"
:layout="activeLayout" :is-definition="props.isDefinition"
:second-box-height="secondBoxHeight" :response="requestVModel.response?.requestResults[0]?.responseResult.body"
@change="handleActiveDebugChange" :assertion-config="requestVModel.children[0].assertionConfig"
/> :show-extraction="true"
<precondition />
v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION" <auth
v-model:config="requestVModel.children[0].preProcessorConfig" v-else-if="requestVModel.activeTab === RequestComposition.AUTH"
:is-definition="props.isDefinition" v-model:params="requestVModel.authConfig"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<postcondition <setting
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION" v-else-if="requestVModel.activeTab === RequestComposition.SETTING"
v-model:config="requestVModel.children[0].postProcessorConfig" v-model:params="requestVModel.otherConfig"
:response="requestVModel.response?.requestResults[0]?.responseResult.body" @change="handleActiveDebugChange"
:layout="activeLayout" />
:second-box-height="secondBoxHeight" </div>
:is-definition="props.isDefinition" </a-spin>
@change="handleActiveDebugChange" <response
/> v-show="showResponse"
<assertion ref="responseRef"
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION" v-model:active-layout="activeLayout"
v-model:params="requestVModel.children[0].assertionConfig.assertions" v-model:active-tab="requestVModel.responseActiveTab"
:is-definition="props.isDefinition" v-model:response-definition="requestVModel.responseDefinition"
:response="requestVModel.response?.requestResults[0]?.responseResult.body" class="response"
:assertion-config="requestVModel.children[0].assertionConfig" :show-response-result-button="requestVModel.mode === 'debug'"
:show-extraction="true" :is-http-protocol="isHttpProtocol"
/> :is-priority-local-exec="isPriorityLocalExec"
<auth :request-url="requestVModel.url"
v-else-if="requestVModel.activeTab === RequestComposition.AUTH" :is-expanded="isVerticalExpanded"
v-model:params="requestVModel.authConfig" :hide-layout-switch="props.hideResponseLayoutSwitch"
@change="handleActiveDebugChange" :request-result="requestVModel.response?.requestResults[0]"
/> :console="requestVModel.response?.console"
<setting :is-edit="props.isDefinition && isHttpProtocol && !props.isCase"
v-else-if="requestVModel.activeTab === RequestComposition.SETTING" :upload-temp-file-api="props.uploadTempFileApi"
v-model:params="requestVModel.otherConfig" :loading="requestVModel.executeLoading || loading"
@change="handleActiveDebugChange" :is-definition="props.isDefinition"
/> @change="handleActiveDebugChange"
</div> @execute="(executeType) => (props.isCase ? emit('execute', executeType) : execute(executeType))"
</div> />
</a-spin> </div>
</template>
<template #second>
<response
v-show="showResponse"
ref="responseRef"
v-model:active-layout="activeLayout"
v-model:active-tab="requestVModel.responseActiveTab"
v-model:response-definition="requestVModel.responseDefinition"
:show-response-result-button="requestVModel.mode === 'debug'"
:is-http-protocol="isHttpProtocol"
:is-priority-local-exec="isPriorityLocalExec"
:request-url="requestVModel.url"
:is-expanded="isVerticalExpanded"
:hide-layout-switch="props.hideResponseLayoutSwitch"
:request-result="requestVModel.response?.requestResults[0]"
:console="requestVModel.response?.console"
:is-edit="props.isDefinition && isHttpProtocol && !props.isCase"
:upload-temp-file-api="props.uploadTempFileApi"
:loading="requestVModel.executeLoading || loading"
:is-definition="props.isDefinition"
@change-expand="changeVerticalExpand"
@change-layout="handleActiveLayoutChange"
@change="handleActiveDebugChange"
@execute="(executeType) => (props.isCase ? emit('execute', executeType) : execute(executeType))"
/>
</template>
</MsSplitBox>
</div> </div>
</div> </div>
<a-modal <a-modal
@ -461,7 +430,6 @@
import { TabItem } from '@/components/pure/ms-editable-tab/types'; import { TabItem } from '@/components/pure/ms-editable-tab/types';
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue'; import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
import MsIcon from '@/components/pure/ms-icon-font/index.vue'; import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsTab from '@/components/pure/ms-tab/index.vue'; import MsTab from '@/components/pure/ms-tab/index.vue';
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue'; import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
import assertion from '@/components/business/ms-assertion/index.vue'; import assertion from '@/components/business/ms-assertion/index.vue';
@ -913,58 +881,12 @@
requestVModel.value.response?.requestResults[0]?.responseResult.responseCode || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode ||
props.isCase props.isCase
); );
const splitBoxSize = ref<string | number>(!showResponse.value ? 1 : 0.6);
const activeLayout = ref<'horizontal' | 'vertical'>('vertical'); const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
const splitContainerRef = ref<HTMLElement>(); const responseRef = ref<InstanceType<typeof response>>();
const secondBoxHeight = ref(0); const isVerticalExpanded = computed(() => activeLayout.value === 'vertical');
watch(
() => showResponse.value,
(val) => {
if (val) {
splitBoxSize.value = 0.6;
} else {
splitBoxSize.value = 1;
}
}
);
watch(
() => splitBoxSize.value,
debounce((val) => {
// 300ms
if (splitContainerRef.value) {
if (typeof val === 'string' && val.includes('px')) {
val = Number(val.split('px')[0]);
secondBoxHeight.value = splitContainerRef.value.clientHeight - val;
} else {
secondBoxHeight.value = splitContainerRef.value.clientHeight * (1 - val);
}
}
}, 300),
{
immediate: true,
}
);
const verticalSplitBoxRef = ref<InstanceType<typeof MsSplitBox>>();
const isVerticalExpanded = ref(true);
function handleVerticalExpandChange(val: boolean) {
isVerticalExpanded.value = val;
}
function changeVerticalExpand(val: boolean) { function changeVerticalExpand(val: boolean) {
isVerticalExpanded.value = val; responseRef.value?.changeExpand(val);
if (val) {
verticalSplitBoxRef.value?.expand(0.6);
} else {
verticalSplitBoxRef.value?.collapse(
splitContainerRef.value
? `${splitContainerRef.value.clientHeight - (props.hideResponseLayoutSwitch ? 37 : 42)}px`
: 0
);
}
} }
watch( watch(
() => showResponse.value, () => showResponse.value,
(val) => { (val) => {
@ -976,12 +898,6 @@
} }
); );
function handleActiveLayoutChange() {
isVerticalExpanded.value = true;
splitBoxSize.value = 0.6;
verticalSplitBoxRef.value?.expand(0.6);
}
const saveModalVisible = ref(false); const saveModalVisible = ref(false);
const saveModalForm = ref({ const saveModalForm = ref({
name: '', name: '',
@ -1232,8 +1148,6 @@
requestVModel.value.executeLoading = false; requestVModel.value.executeLoading = false;
} }
const responseRef = ref<InstanceType<typeof response>>();
watch( watch(
() => requestVModel.value.id, () => requestVModel.value.id,
async () => { async () => {
@ -1696,10 +1610,6 @@
.btn-base-primary-disabled(); .btn-base-primary-disabled();
} }
} }
.tab-pane-container {
@apply flex-1 overflow-y-auto;
.ms-scroll-bar();
}
:deep(.no-content) { :deep(.no-content) {
.arco-tabs-content { .arco-tabs-content {
display: none; display: none;
@ -1711,16 +1621,6 @@
:deep(.arco-tabs-tab) { :deep(.arco-tabs-tab) {
@apply leading-none; @apply leading-none;
} }
.hidden-second {
:deep(.arco-split-trigger) {
@apply hidden;
}
}
.show-second {
:deep(.arco-split-trigger) {
@apply block;
}
}
.url-input-tip { .url-input-tip {
margin-top: 2px 0 250px; margin-top: 2px 0 250px;
font-size: 12px; font-size: 12px;
@ -1728,4 +1628,45 @@
line-height: 16px; line-height: 16px;
@apply flex flex-col flex-nowrap items-center justify-start; @apply flex flex-col flex-nowrap items-center justify-start;
} }
.request-tab-and-response {
overflow-x: hidden;
overflow-y: auto;
.ms-scroll-bar();
}
.sticky-content {
@apply sticky bg-white;
z-index: 101; // .arco-scrollbar-track100
}
.request-content-and-response {
display: flex;
&.vertical {
flex-direction: column;
.response :deep(.response-head) {
@apply sticky bg-white;
top: 48px; // tab(border-bottom)
z-index: 11;
}
.request-tab-pane {
min-height: 400px;
}
}
&.horizontal {
flex-direction: row;
min-height: calc(100% - 49px); // 49px:tab
.request {
flex: 1;
overflow-x: auto;
.ms-scroll-bar();
.request-tab-pane {
min-width: 800px;
}
}
.response {
width: 500px;
border-left: 1px solid var(--color-text-n8);
}
}
}
</style> </style>

View File

@ -6,7 +6,6 @@
add-text="apiTestDebug.postCondition" add-text="apiTestDebug.postCondition"
:response="props.response" :response="props.response"
:disabled="props.disabled" :disabled="props.disabled"
:height-used="heightUsed"
:sql-code-editor-height="props.sqlCodeEditorHeight" :sql-code-editor-height="props.sqlCodeEditorHeight"
@change="emit('change')" @change="emit('change')"
> >
@ -43,8 +42,6 @@
const props = defineProps<{ const props = defineProps<{
config: ExecuteConditionConfig; config: ExecuteConditionConfig;
secondBoxHeight?: number;
layout: 'horizontal' | 'vertical';
response?: string; // response?: string; //
isDefinition?: boolean; // isDefinition?: boolean; //
isScenario?: boolean; // isScenario?: boolean; //
@ -59,12 +56,6 @@
const { t } = useI18n(); const { t } = useI18n();
const innerConfig = useVModel(props, 'config', emit); const innerConfig = useVModel(props, 'config', emit);
const heightUsed = computed(() => {
if (props.layout === 'horizontal') {
return 328;
}
return 328 + (props.secondBoxHeight || 0);
});
const conditionTypes = computed(() => { const conditionTypes = computed(() => {
if (props.isDefinition) { if (props.isDefinition) {

View File

@ -15,7 +15,6 @@
:disabled-param-value="props.disabledParamValue" :disabled-param-value="props.disabledParamValue"
:disabled-except-param="props.disabledExceptParam" :disabled-except-param="props.disabledExceptParam"
:columns="columns" :columns="columns"
:height-used="heightUsed"
:scroll="{ minWidth: 1160 }" :scroll="{ minWidth: 1160 }"
:show-setting="true" :show-setting="true"
:table-key="TableKeyEnum.API_TEST_DEBUG_QUERY" :table-key="TableKeyEnum.API_TEST_DEBUG_QUERY"
@ -51,11 +50,8 @@
const props = defineProps<{ const props = defineProps<{
params: ExecuteRequestCommonParam[]; params: ExecuteRequestCommonParam[];
layout: 'horizontal' | 'vertical';
disabledParamValue?: boolean; // disabledParamValue?: boolean; //
disabledExceptParam?: boolean; // disabledExceptParam?: boolean; //
secondBoxHeight: number;
isDrawer?: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:params', value: any[]): void; (e: 'update:params', value: any[]): void;
@ -124,30 +120,6 @@
]); ]);
const batchAddKeyValVisible = ref(false); const batchAddKeyValVisible = ref(false);
const heightUsed = ref<number | undefined>(undefined);
watch(
() => props.layout,
(val) => {
const otherHeight = props.isDrawer ? 328 : 372;
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
},
{
immediate: true,
}
);
watch(
() => props.secondBoxHeight,
(val) => {
if (props.layout === 'vertical') {
heightUsed.value = (props.isDrawer ? 328 : 372) + val;
}
},
{
immediate: true,
}
);
/** /**
* 批量参数代码转换为参数表格数据 * 批量参数代码转换为参数表格数据

View File

@ -117,7 +117,6 @@
activeResponse.body.bodyType activeResponse.body.bodyType
) )
" "
class="h-[calc(100%-35px)]"
> >
<!-- <MsJsonSchema <!-- <MsJsonSchema
v-if="activeResponse.body.jsonBody.enableJsonSchema" v-if="activeResponse.body.jsonBody.enableJsonSchema"
@ -129,7 +128,6 @@
v-model:model-value="currentBodyCode" v-model:model-value="currentBodyCode"
:language="currentCodeLanguage" :language="currentCodeLanguage"
theme="vs" theme="vs"
height="100%"
:show-full-screen="false" :show-full-screen="false"
:show-theme-change="false" :show-theme-change="false"
:show-language-change="false" :show-language-change="false"
@ -477,11 +475,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.response-container { .response-container {
@apply overflow-y-auto;
.ms-scroll-bar();
margin-top: 8px; margin-top: 8px;
height: calc(100% - 88px);
} }
:deep(.arco-table-th) { :deep(.arco-table-th) {
background-color: var(--color-text-n9); background-color: var(--color-text-n9);

View File

@ -1,25 +1,25 @@
<template> <template>
<div class="response flex h-full min-w-[300px] flex-col"> <div class="response flex min-w-[300px] flex-col">
<div :class="['response-head', props.isExpanded ? '' : 'border-t']"> <div :class="['response-head', activeLayout === 'vertical' ? 'border-t' : '']">
<slot name="titleLeft"> <slot name="titleLeft">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<template v-if="activeLayout === 'vertical'"> <template v-if="activeLayout === 'vertical'">
<MsButton <MsButton
v-if="props.isExpanded" v-show="innerIsExpanded"
type="icon" type="icon"
class="!mr-0 !rounded-full bg-[rgb(var(--primary-1))]" class="!mr-0 !rounded-full bg-[rgb(var(--primary-1))]"
size="small" size="small"
@click="emit('changeExpand', false)" @click="changeExpand(false)"
> >
<icon-down :size="8" /> <icon-down :size="8" />
</MsButton> </MsButton>
<MsButton <MsButton
v-else v-show="!innerIsExpanded"
type="icon" type="icon"
status="secondary" status="secondary"
class="!mr-0 !rounded-full bg-[rgb(var(--primary-1))]" class="!mr-0 !rounded-full bg-[rgb(var(--primary-1))]"
size="small" size="small"
@click="emit('changeExpand', true)" @click="changeExpand(true)"
> >
<icon-right :size="8" /> <icon-right :size="8" />
</MsButton> </MsButton>
@ -58,8 +58,9 @@
<responseCodeTimeSize :request-result="props.requestResult" /> <responseCodeTimeSize :request-result="props.requestResult" />
</div> </div>
<a-spin <a-spin
v-show="innerIsExpanded"
:loading="props.loading" :loading="props.loading"
:class="[isResponseModel ? 'h-[381px] w-full' : 'h-[calc(100%-35px)] w-full px-[16px] pb-[16px]']" :class="[isResponseModel ? 'h-[381px] w-full' : 'w-full px-[16px] pb-[16px]']"
> >
<edit <edit
v-if="props.isEdit && activeResponseType === 'content' && responseDefinition" v-if="props.isEdit && activeResponseType === 'content' && responseDefinition"
@ -119,7 +120,6 @@
} }
); );
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'changeExpand', value: boolean): void;
(e: 'changeLayout', value: Direction): void; (e: 'changeLayout', value: Direction): void;
(e: 'change'): void; (e: 'change'): void;
(e: 'execute', executeType: 'localExec' | 'serverExec'): void; (e: 'execute', executeType: 'localExec' | 'serverExec'): void;
@ -136,6 +136,23 @@
const responseDefinition = defineModel<ResponseItem[]>('responseDefinition', { const responseDefinition = defineModel<ResponseItem[]>('responseDefinition', {
default: [], default: [],
}); });
const innerIsExpanded = defineModel<boolean>('isExpanded', {
default: true,
});
function changeExpand(isExpanded: boolean) {
innerIsExpanded.value = isExpanded;
}
watch(
() => activeLayout.value,
(val) => {
if (val === 'horizontal') {
changeExpand(true);
}
}
);
watchEffect(() => { watchEffect(() => {
// null // null
let hasInvalid = false; let hasInvalid = false;
@ -210,6 +227,7 @@
defineExpose({ defineExpose({
setActiveResponse, setActiveResponse,
changeExpand,
}); });
</script> </script>

View File

@ -135,9 +135,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.response-container { .response-container {
overflow: hidden;
margin-top: 8px; margin-top: 8px;
height: calc(100% - 48px);
} }
:deep(.arco-table-th) { :deep(.arco-table-th) {
background-color: var(--color-text-n9); background-color: var(--color-text-n9);

View File

@ -16,7 +16,6 @@
:draggable="!props.disabledExceptParam" :draggable="!props.disabledExceptParam"
:disabled-param-value="props.disabledParamValue" :disabled-param-value="props.disabledParamValue"
:disabled-except-param="props.disabledExceptParam" :disabled-except-param="props.disabledExceptParam"
:height-used="heightUsed"
:scroll="{ minWidth: 1160 }" :scroll="{ minWidth: 1160 }"
:show-setting="true" :show-setting="true"
:table-key="TableKeyEnum.API_TEST_DEBUG_REST" :table-key="TableKeyEnum.API_TEST_DEBUG_REST"
@ -51,11 +50,8 @@
const props = defineProps<{ const props = defineProps<{
params: ExecuteRequestCommonParam[]; params: ExecuteRequestCommonParam[];
layout: 'horizontal' | 'vertical';
secondBoxHeight: number;
disabledParamValue?: boolean; // disabledParamValue?: boolean; //
disabledExceptParam?: boolean; // disabledExceptParam?: boolean; //
isDrawer?: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:params', value: any[]): void; (e: 'update:params', value: any[]): void;
@ -125,30 +121,6 @@
]); ]);
const batchAddKeyValVisible = ref(false); const batchAddKeyValVisible = ref(false);
const heightUsed = ref<number | undefined>(undefined);
watch(
() => props.layout,
(val) => {
const otherHeight = props.isDrawer ? 328 : 372;
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
},
{
immediate: true,
}
);
watch(
() => props.secondBoxHeight,
(val) => {
if (props.layout === 'vertical') {
heightUsed.value = (props.isDrawer ? 328 : 372) + val;
}
},
{
immediate: true,
}
);
/** /**
* 批量参数代码转换为参数表格数据 * 批量参数代码转换为参数表格数据

View File

@ -14,65 +14,61 @@
@cancel="handleSaveCaseCancel" @cancel="handleSaveCaseCancel"
> >
<div class="flex h-full flex-col overflow-hidden"> <div class="flex h-full flex-col overflow-hidden">
<div class="px-[16px] pt-[16px]"> <MsDetailCard
<MsDetailCard :title="`【${apiDetailInfo.num}】${apiDetailInfo.name}`"
:title="`【${apiDetailInfo.num}】${apiDetailInfo.name}`" :description="description"
:description="description" class="m-[16px] !flex-row justify-between"
class="!flex-row justify-between" >
> <template #type="{ value }">
<template #type="{ value }"> <apiMethodName :method="value as RequestMethods" tag-size="small" is-tag />
<apiMethodName :method="value as RequestMethods" tag-size="small" is-tag /> </template>
</template> </MsDetailCard>
</MsDetailCard> <a-form ref="formNameRef" class="flex-row items-start gap-[8px] px-[16px]" :model="detailForm" layout="vertical">
<a-form ref="formRef" class="mt-[16px]" :model="detailForm" layout="vertical"> <a-form-item field="name" label="" :rules="[{ required: true, message: t('case.caseNameRequired') }]">
<a-form-item field="name" label="" :rules="[{ required: true, message: t('case.caseNameRequired') }]"> <a-input
<div class="flex w-full items-center gap-[8px]"> v-model:model-value="detailForm.name"
<a-input :placeholder="t('case.caseNamePlaceholder')"
v-model:model-value="detailForm.name" allow-clear
:placeholder="t('case.caseNamePlaceholder')" :max-length="255"
allow-clear show-word-limit
:max-length="255" />
show-word-limit </a-form-item>
/> <MsEnvironmentSelect ref="environmentSelectRef" :env="environmentId" />
<MsEnvironmentSelect ref="environmentSelectRef" :env="environmentId" /> <executeButton
<executeButton ref="executeRef"
ref="executeRef" v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']"
v-permission="['PROJECT_API_DEFINITION_CASE:READ+EXECUTE']" :execute-loading="detailForm.executeLoading"
:execute-loading="detailForm.executeLoading" @stop-debug="stopDebug"
@stop-debug="stopDebug" @execute="handleExecute"
@execute="handleExecute" />
/> </a-form>
</div> <div class="request-tab-and-response flex-1">
<a-form ref="formRef" class="flex-row gap-[16px] px-[16px]" :model="detailForm" layout="vertical">
<a-form-item field="priority" :label="t('case.caseLevel')">
<a-select v-model:model-value="detailForm.priority" :placeholder="t('common.pleaseSelect')">
<template #label>
<span class="text-[var(--color-text-2)]"> <caseLevel :case-level="detailForm.priority" /></span>
</template>
<a-option v-for="item of casePriorityOptions" :key="item.value" :value="item.value">
<caseLevel :case-level="item.label as CaseLevel" />
</a-option>
</a-select>
</a-form-item>
<a-form-item field="status" :label="t('apiTestManagement.apiStatus')">
<a-select v-model:model-value="detailForm.status" :placeholder="t('common.pleaseSelect')">
<template #label>
<apiStatus :status="detailForm.status" size="small" />
</template>
<a-option v-for="item of Object.values(RequestCaseStatus)" :key="item" :value="item">
<apiStatus :status="item" size="small" />
</a-option>
</a-select>
</a-form-item>
<a-form-item field="tags" :label="t('common.tag')">
<MsTagsInput v-model:model-value="detailForm.tags" :max-tag-count="1" />
</a-form-item> </a-form-item>
<div class="flex gap-[16px]">
<a-form-item field="priority" :label="t('case.caseLevel')">
<a-select v-model:model-value="detailForm.priority" :placeholder="t('common.pleaseSelect')">
<template #label>
<span class="text-[var(--color-text-2)]"> <caseLevel :case-level="detailForm.priority" /></span>
</template>
<a-option v-for="item of casePriorityOptions" :key="item.value" :value="item.value">
<caseLevel :case-level="item.label as CaseLevel" />
</a-option>
</a-select>
</a-form-item>
<a-form-item field="status" :label="t('apiTestManagement.apiStatus')">
<a-select v-model:model-value="detailForm.status" :placeholder="t('common.pleaseSelect')">
<template #label>
<apiStatus :status="detailForm.status" size="small" />
</template>
<a-option v-for="item of Object.values(RequestCaseStatus)" :key="item" :value="item">
<apiStatus :status="item" size="small" />
</a-option>
</a-select>
</a-form-item>
<a-form-item field="tags" :label="t('common.tag')">
<MsTagsInput v-model:model-value="detailForm.tags" :max-tag-count="1" />
</a-form-item>
</div>
</a-form> </a-form>
</div> <div class="px-[16px] font-medium">{{ t('apiTestManagement.requestParams') }}</div>
<div class="px-[16px] font-medium">{{ t('apiTestManagement.requestParams') }}</div>
<div class="flex-1 overflow-hidden">
<requestComposition <requestComposition
ref="requestCompositionRef" ref="requestCompositionRef"
v-model:request="detailForm" v-model:request="detailForm"
@ -174,6 +170,7 @@
); );
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const formNameRef = ref<FormInstance>();
const requestCompositionRef = ref<InstanceType<typeof requestComposition>>(); const requestCompositionRef = ref<InstanceType<typeof requestComposition>>();
const defaultCaseParams = inject<RequestParam>('defaultCaseParams'); const defaultCaseParams = inject<RequestParam>('defaultCaseParams');
const defaultDetail = computed<RequestParam>(() => { const defaultDetail = computed<RequestParam>(() => {
@ -239,10 +236,11 @@
isEdit.value = false; isEdit.value = false;
innerVisible.value = false; innerVisible.value = false;
formRef.value?.resetFields(); formRef.value?.resetFields();
formNameRef.value?.resetFields();
} }
function handleDrawerConfirm(isContinue: boolean) { function handleDrawerConfirm(isContinue: boolean) {
formRef.value?.validate(async (errors) => { formNameRef.value?.validate(async (errors) => {
if (!errors) { if (!errors) {
// //
if (requestCompositionRef.value?.getFlattenedMessages()?.length) { if (requestCompositionRef.value?.getFlattenedMessages()?.length) {
@ -393,10 +391,12 @@
max-width: 50%; max-width: 50%;
} }
} }
:deep(.arco-form > .arco-form-item):nth-child(1) .arco-form-item-label-col { :deep(.arco-form):nth-of-type(1) > .arco-form-item .arco-form-item-label-col {
display: none; display: none;
} }
:deep(.request-and-response) { .request-tab-and-response {
height: calc(100% - 56px); overflow-x: hidden;
overflow-y: auto;
.ms-scroll-bar();
} }
</style> </style>

View File

@ -100,260 +100,227 @@
</template> </template>
</a-empty> </a-empty>
<div v-show="!pluginError || isHttpProtocol" class="flex h-full flex-col"> <div v-show="!pluginError || isHttpProtocol" class="flex h-full flex-col">
<div class="px-[18px] pt-[8px]"> <div class="flex flex-wrap items-center justify-between gap-[12px] px-[18px] pt-[8px]">
<div class="flex flex-wrap items-center justify-between gap-[12px]"> <div class="flex flex-1 items-center gap-[16px]">
<div class="flex flex-1 items-center gap-[16px]"> <a-select
<a-select v-if="requestVModel.isNew"
v-if="requestVModel.isNew" v-model:model-value="requestVModel.protocol"
v-model:model-value="requestVModel.protocol" :options="protocolOptions"
:options="protocolOptions" :loading="protocolLoading"
:loading="protocolLoading" :disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep"
:disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep" class="w-[90px]"
class="w-[90px]" @change="(val) => handleActiveDebugProtocolChange(val as string)"
@change="(val) => handleActiveDebugProtocolChange(val as string)" />
<div v-else class="flex items-center gap-[4px]">
<apiMethodName
:method="(requestVModel.protocol as RequestMethods)"
tag-background-color="rgb(var(--link-7))"
tag-text-color="white"
is-tag
class="flex items-center"
/> />
<div v-else class="flex items-center gap-[4px]"> <a-tooltip v-if="!isHttpProtocol" :content="requestVModel.name" :mouse-enter-delay="500">
<apiMethodName <div class="one-line-text max-w-[350px]"> {{ requestVModel.name }}</div>
:method="(requestVModel.protocol as RequestMethods)" </a-tooltip>
tag-background-color="rgb(var(--link-7))"
tag-text-color="white"
is-tag
class="flex items-center"
/>
<a-tooltip v-if="!isHttpProtocol" :content="requestVModel.name" :mouse-enter-delay="500">
<div class="one-line-text max-w-[350px]"> {{ requestVModel.name }}</div>
</a-tooltip>
</div>
<a-input-group v-if="isHttpProtocol" class="flex-1">
<apiMethodSelect
v-model:model-value="requestVModel.method"
class="w-[140px]"
:disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep"
@change="handleActiveDebugChange"
/>
<a-input
v-model:model-value="requestVModel.url"
:max-length="255"
:placeholder="showEnvPrefix ? t('apiScenario.pleaseInputUrl') : t('apiTestDebug.urlPlaceholder')"
allow-clear
class="hover:z-10"
:style="isUrlError ? 'border: 1px solid rgb(var(--danger-6);z-index: 10' : ''"
:disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep"
@input="() => (isUrlError = false)"
@change="handleUrlChange"
>
<template v-if="showEnvPrefix" #prefix>
{{ (appStore.currentEnvConfig as EnvConfig)?.httpConfig.find((e) => e.type === 'NONE')?.url }}
</template>
</a-input>
</a-input-group>
</div> </div>
<div v-permission="[props.permissionMap?.execute]"> <a-input-group v-if="isHttpProtocol" class="flex-1">
<template v-if="hasLocalExec"> <apiMethodSelect
<a-dropdown-button v-model:model-value="requestVModel.method"
v-if="!requestVModel.executeLoading" class="w-[140px]"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)" :disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep"
class="exec-btn" @change="handleActiveDebugChange"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')" />
@select="execute" <a-input
> v-model:model-value="requestVModel.url"
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }} :max-length="255"
<template #icon> :placeholder="showEnvPrefix ? t('apiScenario.pleaseInputUrl') : t('apiTestDebug.urlPlaceholder')"
<icon-down /> allow-clear
</template> class="hover:z-10"
<template #content> :style="isUrlError ? 'border: 1px solid rgb(var(--danger-6);z-index: 10' : ''"
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'"> :disabled="_stepType.isQuoteApi || props.step?.isQuoteScenarioStep"
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }} @input="() => (isUrlError = false)"
</a-doption> @change="handleUrlChange"
</template>
</a-dropdown-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">
{{ t('common.stop') }}
</a-button>
</template>
<a-button
v-else-if="!requestVModel.executeLoading"
class="mr-[12px]"
type="primary"
@click="() => execute('serverExec')"
> >
{{ t('apiTestDebug.serverExec') }} <template v-if="showEnvPrefix" #prefix>
</a-button> {{ (appStore.currentEnvConfig as EnvConfig)?.httpConfig.find((e) => e.type === 'NONE')?.url }}
</template>
</a-input>
</a-input-group>
</div>
<div v-permission="[props.permissionMap?.execute]">
<template v-if="hasLocalExec">
<a-dropdown-button
v-if="!requestVModel.executeLoading"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
class="exec-btn"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
@select="execute"
>
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
<template #icon>
<icon-down />
</template>
<template #content>
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
</template>
</a-dropdown-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug"> <a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">
{{ t('common.stop') }} {{ t('common.stop') }}
</a-button> </a-button>
</div> </template>
<a-button
v-else-if="!requestVModel.executeLoading"
class="mr-[12px]"
type="primary"
@click="() => execute('serverExec')"
>
{{ t('apiTestDebug.serverExec') }}
</a-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">
{{ t('common.stop') }}
</a-button>
</div> </div>
<a-input
v-if="props.step?.stepType && _stepType.isQuoteApi && isHttpProtocol"
v-model:model-value="requestVModel.name"
:max-length="255"
:placeholder="t('apiTestManagement.apiNamePlaceholder')"
:disabled="!isEditableApi"
allow-clear
class="mt-[8px]"
/>
</div> </div>
<div class="px-[16px]"> <div class="request-tab-and-response flex-1">
<div class="px-[18px]">
<a-input
v-if="props.step?.stepType && _stepType.isQuoteApi && isHttpProtocol"
v-model:model-value="requestVModel.name"
:max-length="255"
:placeholder="t('apiTestManagement.apiNamePlaceholder')"
:disabled="!isEditableApi"
allow-clear
class="my-[8px]"
/>
</div>
<MsTab <MsTab
v-if="requestVModel.activeTab" v-if="requestVModel.activeTab"
v-model:active-key="requestVModel.activeTab" v-model:active-key="requestVModel.activeTab"
:content-tab-list="contentTabList" :content-tab-list="contentTabList"
:get-text-func="getTabBadge" :get-text-func="getTabBadge"
class="no-content relative mt-[8px] border-b" class="sticky-content no-content relative top-0 mx-[16px] border-b"
/> />
</div> <div :class="`request-content-and-response ${activeLayout}`">
<div ref="splitContainerRef" class="h-[calc(100%-97px)]"> <a-spin class="request block h-full w-full" :loading="requestVModel.executeLoading || loading">
<MsSplitBox <div class="request-tab-pane flex flex-col p-[16px]">
ref="verticalSplitBoxRef" <a-spin
v-model:size="splitBoxSize" v-show="requestVModel.activeTab === RequestComposition.PLUGIN"
:max="!showResponse ? 1 : 0.98" :loading="pluginLoading"
min="10px" class="min-h-[100px] w-full"
:direction="activeLayout"
second-container-class="!overflow-y-hidden"
:class="!showResponse ? 'hidden-second' : 'show-second'"
@expand-change="handleVerticalExpandChange"
>
<template #first>
<a-spin class="block h-full w-full" :loading="requestVModel.executeLoading || loading">
<div
:class="`flex h-full min-w-[800px] flex-col p-[16px] ${
activeLayout === 'horizontal' ? ' pr-[16px]' : ''
}`"
> >
<div class="tab-pane-container"> <MsFormCreate
<a-spin v-model:api="fApi"
v-show="requestVModel.activeTab === RequestComposition.PLUGIN" :rule="currentPluginScript"
:loading="pluginLoading" :option="currentPluginOptions"
class="min-h-[100px] w-full" @change="
> () => {
<MsFormCreate if (isInitPluginForm) {
v-model:api="fApi" handlePluginFormChange();
:rule="currentPluginScript" }
:option="currentPluginOptions" }
@change=" "
() => { />
if (isInitPluginForm) { </a-spin>
handlePluginFormChange(); <httpHeader
} v-if="requestVModel.activeTab === RequestComposition.HEADER"
} v-model:params="requestVModel.headers"
" :disabled-param-value="!isEditableApi && !isEditableParamValue"
/> :disabled-except-param="!isEditableApi"
</a-spin> :layout="activeLayout"
<httpHeader @change="handleActiveDebugChange"
v-if="requestVModel.activeTab === RequestComposition.HEADER" />
v-model:params="requestVModel.headers" <httpBody
:disabled-param-value="!isEditableApi && !isEditableParamValue" v-else-if="requestVModel.activeTab === RequestComposition.BODY"
:disabled-except-param="!isEditableApi" v-model:params="requestVModel.body"
:layout="activeLayout" :disabled-param-value="!isEditableApi && !isEditableParamValue"
:second-box-height="secondBoxHeight" :disabled-except-param="!isEditableApi"
is-drawer :upload-temp-file-api="uploadTempFile"
@change="handleActiveDebugChange" :file-save-as-source-id="scenarioId"
/> :file-save-as-api="transferFile"
<httpBody :file-module-options-api="getTransferOptions"
v-else-if="requestVModel.activeTab === RequestComposition.BODY" @change="handleActiveDebugChange"
v-model:params="requestVModel.body" />
:layout="activeLayout" <httpQuery
:disabled-param-value="!isEditableApi && !isEditableParamValue" v-else-if="requestVModel.activeTab === RequestComposition.QUERY"
:disabled-except-param="!isEditableApi" v-model:params="requestVModel.query"
:second-box-height="secondBoxHeight" :disabled-param-value="!isEditableApi && !isEditableParamValue"
:upload-temp-file-api="uploadTempFile" :disabled-except-param="!isEditableApi"
:file-save-as-source-id="scenarioId" @change="handleActiveDebugChange"
:file-save-as-api="transferFile" />
:file-module-options-api="getTransferOptions" <httpRest
is-drawer v-else-if="requestVModel.activeTab === RequestComposition.REST"
@change="handleActiveDebugChange" v-model:params="requestVModel.rest"
/> :disabled-param-value="!isEditableApi && !isEditableParamValue"
<httpQuery :disabled-except-param="!isEditableApi"
v-else-if="requestVModel.activeTab === RequestComposition.QUERY" @change="handleActiveDebugChange"
v-model:params="requestVModel.query" />
:layout="activeLayout" <precondition
:disabled-param-value="!isEditableApi && !isEditableParamValue" v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION"
:disabled-except-param="!isEditableApi" v-model:config="requestVModel.children[0].preProcessorConfig"
:second-box-height="secondBoxHeight" is-definition
is-drawer :disabled="!isEditableApi"
@change="handleActiveDebugChange" :tip-content="t('apiScenario.openGlobalPreConditionTip')"
/> @change="handleActiveDebugChange"
<httpRest />
v-else-if="requestVModel.activeTab === RequestComposition.REST" <postcondition
v-model:params="requestVModel.rest" v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
:layout="activeLayout" v-model:config="requestVModel.children[0].postProcessorConfig"
:disabled-param-value="!isEditableApi && !isEditableParamValue" :response="responseResultBody"
:disabled-except-param="!isEditableApi" :disabled="!isEditableApi"
:second-box-height="secondBoxHeight" :tip-content="t('apiScenario.openGlobalPostConditionTip')"
is-drawer is-definition
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<precondition <assertion
v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION" v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
v-model:config="requestVModel.children[0].preProcessorConfig" v-model:params="requestVModel.children[0].assertionConfig.assertions"
is-definition :response="responseResultBody"
:disabled="!isEditableApi" is-definition
:tip-content="t('apiScenario.openGlobalPreConditionTip')" :disabled="!isEditableApi"
@change="handleActiveDebugChange" :assertion-config="requestVModel.children[0].assertionConfig"
/> :show-extraction="true"
<postcondition />
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION" <auth
v-model:config="requestVModel.children[0].postProcessorConfig" v-else-if="requestVModel.activeTab === RequestComposition.AUTH"
:response="responseResultBody" v-model:params="requestVModel.authConfig"
:layout="activeLayout" :disabled="!isEditableApi"
:disabled="!isEditableApi" @change="handleActiveDebugChange"
:second-box-height="secondBoxHeight" />
:tip-content="t('apiScenario.openGlobalPostConditionTip')" <setting
is-definition v-else-if="requestVModel.activeTab === RequestComposition.SETTING"
@change="handleActiveDebugChange" v-model:params="requestVModel.otherConfig"
/> :disabled="!isEditableApi"
<assertion @change="handleActiveDebugChange"
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION" />
v-model:params="requestVModel.children[0].assertionConfig.assertions" </div>
:response="responseResultBody" </a-spin>
is-definition
:disabled="!isEditableApi" <response
:assertion-config="requestVModel.children[0].assertionConfig" v-if="visible"
:show-extraction="true" v-show="showResponse"
/> ref="responseRef"
<auth v-model:active-layout="activeLayout"
v-else-if="requestVModel.activeTab === RequestComposition.AUTH" v-model:active-tab="requestVModel.responseActiveTab"
v-model:params="requestVModel.authConfig" class="response"
:disabled="!isEditableApi" :is-http-protocol="isHttpProtocol"
@change="handleActiveDebugChange" :is-priority-local-exec="isPriorityLocalExec"
/> :request-url="requestVModel.url"
<setting :is-expanded="isVerticalExpanded"
v-else-if="requestVModel.activeTab === RequestComposition.SETTING" :request-result="currentResponse"
v-model:params="requestVModel.otherConfig" :console="currentResponse?.console"
:disabled="!isEditableApi" :is-edit="false"
@change="handleActiveDebugChange" is-definition
/> hide-layout-switch
</div> :loading="requestVModel.executeLoading || loading"
</div> @execute="execute"
</a-spin> >
</template> <template #titleRight>
<template #second> <loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
<response </template>
v-if="visible" </response>
v-show="showResponse" </div>
v-model:active-layout="activeLayout"
v-model:active-tab="requestVModel.responseActiveTab"
:is-http-protocol="isHttpProtocol"
:is-priority-local-exec="isPriorityLocalExec"
:request-url="requestVModel.url"
:is-expanded="isVerticalExpanded"
:request-result="currentResponse"
:console="currentResponse?.console"
:is-edit="false"
is-definition
hide-layout-switch
:loading="requestVModel.executeLoading || loading"
@change-expand="changeVerticalExpand"
@change-layout="handleActiveLayoutChange"
@execute="execute"
>
<template #titleRight>
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
</template>
</response>
</template>
</MsSplitBox>
</div> </div>
</div> </div>
<!-- <addDependencyDrawer v-model:visible="showAddDependencyDrawer" :mode="addDependencyMode" /> --> <!-- <addDependencyDrawer v-model:visible="showAddDependencyDrawer" :mode="addDependencyMode" /> -->
@ -368,7 +335,6 @@
import MsDrawer from '@/components/pure/ms-drawer/index.vue'; import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue'; import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
import MsIcon from '@/components/pure/ms-icon-font/index.vue'; import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsTab from '@/components/pure/ms-tab/index.vue'; import MsTab from '@/components/pure/ms-tab/index.vue';
import assertion from '@/components/business/ms-assertion/index.vue'; import assertion from '@/components/business/ms-assertion/index.vue';
import loopPagination from './loopPagination.vue'; import loopPagination from './loopPagination.vue';
@ -936,47 +902,13 @@
const showResponse = computed( const showResponse = computed(
() => isHttpProtocol.value || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode () => isHttpProtocol.value || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode
); );
const splitBoxSize = ref<string | number>(!showResponse.value ? 1 : 0.6);
const activeLayout = ref<'horizontal' | 'vertical'>('vertical'); const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
const splitContainerRef = ref<HTMLElement>(); const isVerticalExpanded = computed(() => activeLayout.value === 'vertical');
const secondBoxHeight = ref(0); const responseRef = ref<InstanceType<typeof response>>();
watch(
() => splitBoxSize.value,
debounce((val) => {
// 300ms
if (splitContainerRef.value) {
if (typeof val === 'string' && val.includes('px')) {
val = Number(val.split('px')[0]);
secondBoxHeight.value = splitContainerRef.value.clientHeight - val;
} else {
secondBoxHeight.value = splitContainerRef.value.clientHeight * (1 - val);
}
}
}, 300),
{
immediate: true,
}
);
const verticalSplitBoxRef = ref<InstanceType<typeof MsSplitBox>>();
const isVerticalExpanded = ref(true);
function handleVerticalExpandChange(val: boolean) {
isVerticalExpanded.value = val;
}
function changeVerticalExpand(val: boolean) { function changeVerticalExpand(val: boolean) {
isVerticalExpanded.value = val; responseRef.value?.changeExpand(val);
if (val) {
verticalSplitBoxRef.value?.expand(0.6);
} else {
verticalSplitBoxRef.value?.collapse(
splitContainerRef.value ? `${splitContainerRef.value.clientHeight - 42}px` : 0
);
}
} }
watch( watch(
() => showResponse.value, () => showResponse.value,
(val) => { (val) => {
@ -984,19 +916,12 @@
if (val) { if (val) {
changeVerticalExpand(true); changeVerticalExpand(true);
} else { } else {
isVerticalExpanded.value = false; changeVerticalExpand(false);
verticalSplitBoxRef.value?.collapse(1);
} }
}); });
} }
); );
function handleActiveLayoutChange() {
isVerticalExpanded.value = true;
splitBoxSize.value = 0.6;
verticalSplitBoxRef.value?.expand(0.6);
}
/** /**
* 生成请求参数 * 生成请求参数
* @param executeType 执行类型执行时传入 * @param executeType 执行类型执行时传入
@ -1373,10 +1298,6 @@
.btn-base-primary-disabled(); .btn-base-primary-disabled();
} }
} }
.tab-pane-container {
@apply flex-1 overflow-y-auto;
.ms-scroll-bar();
}
:deep(.no-content) { :deep(.no-content) {
.arco-tabs-content { .arco-tabs-content {
display: none; display: none;
@ -1388,4 +1309,29 @@
:deep(.arco-tabs-tab) { :deep(.arco-tabs-tab) {
@apply leading-none; @apply leading-none;
} }
.request-tab-and-response {
overflow-x: hidden;
overflow-y: auto;
.ms-scroll-bar();
}
.sticky-content {
@apply sticky bg-white;
z-index: 101;
}
.request-content-and-response {
display: flex;
&.vertical {
flex-direction: column;
.response :deep(.response-head) {
@apply sticky bg-white;
top: 48px; // tab(border-bottom)
z-index: 11;
}
.request-tab-pane {
min-height: 400px;
}
}
}
</style> </style>

View File

@ -114,161 +114,131 @@
</a-button> </a-button>
</div> </div>
</div> </div>
<div class="px-[16px]"> <div class="request-tab-and-response flex-1">
<MsTab <MsTab
v-model:active-key="requestVModel.activeTab" v-model:active-key="requestVModel.activeTab"
:content-tab-list="contentTabList" :content-tab-list="contentTabList"
:get-text-func="getTabBadge" :get-text-func="getTabBadge"
no-content no-content
class="relative mt-[8px] border-b" class="sticky-content relative top-0 mx-[16px] border-b"
/> />
</div> <div :class="`request-content-and-response ${activeLayout}`">
<div ref="splitContainerRef" class="h-[calc(100%-97px)]"> <a-spin class="request block h-full w-full" :loading="requestVModel.executeLoading || loading">
<MsSplitBox <div class="request-tab-pane flex flex-col p-[16px]">
ref="verticalSplitBoxRef" <a-spin
v-model:size="splitBoxSize" v-show="requestVModel.activeTab === RequestComposition.PLUGIN"
:max="!showResponse ? 1 : 0.98" :loading="pluginLoading"
min="10px" class="min-h-[100px] w-full"
:direction="activeLayout"
second-container-class="!overflow-y-hidden"
:class="!showResponse ? 'hidden-second' : 'show-second'"
@expand-change="handleVerticalExpandChange"
>
<template #first>
<a-spin class="block h-full w-full" :loading="requestVModel.executeLoading || loading">
<div
:class="`flex h-full min-w-[800px] flex-col p-[16px] ${
activeLayout === 'horizontal' ? ' pr-[16px]' : ''
}`"
> >
<div class="tab-pane-container"> <MsFormCreate
<a-spin v-model:api="fApi"
v-show="requestVModel.activeTab === RequestComposition.PLUGIN" :rule="currentPluginScript"
:loading="pluginLoading" :option="currentPluginOptions"
class="min-h-[100px] w-full" @change="
> () => {
<MsFormCreate if (isInitPluginForm) {
v-model:api="fApi" handlePluginFormChange();
:rule="currentPluginScript" }
:option="currentPluginOptions" }
@change=" "
() => { />
if (isInitPluginForm) { </a-spin>
handlePluginFormChange(); <httpHeader
} v-if="requestVModel.activeTab === RequestComposition.HEADER"
} v-model:params="requestVModel.headers"
" :disabled-param-value="!isEditableApi"
/> :disabled-except-param="!isEditableApi"
</a-spin> :layout="activeLayout"
<httpHeader @change="handleActiveDebugChange"
v-if="requestVModel.activeTab === RequestComposition.HEADER" />
v-model:params="requestVModel.headers" <httpBody
:disabled-param-value="!isEditableApi" v-else-if="requestVModel.activeTab === RequestComposition.BODY"
:disabled-except-param="!isEditableApi" v-model:params="requestVModel.body"
:layout="activeLayout" :disabled-param-value="!isEditableApi"
:second-box-height="secondBoxHeight" :disabled-except-param="!isEditableApi"
@change="handleActiveDebugChange" :upload-temp-file-api="uploadTempFileCase"
/> :file-save-as-source-id="scenarioId"
<httpBody :file-save-as-api="transferFileCase"
v-else-if="requestVModel.activeTab === RequestComposition.BODY" :file-module-options-api="getTransferOptionsCase"
v-model:params="requestVModel.body" @change="handleActiveDebugChange"
:layout="activeLayout" />
:disabled-param-value="!isEditableApi" <httpQuery
:disabled-except-param="!isEditableApi" v-else-if="requestVModel.activeTab === RequestComposition.QUERY"
:second-box-height="secondBoxHeight" v-model:params="requestVModel.query"
:upload-temp-file-api="uploadTempFileCase" :disabled-param-value="!isEditableApi"
:file-save-as-source-id="scenarioId" :disabled-except-param="!isEditableApi"
:file-save-as-api="transferFileCase" @change="handleActiveDebugChange"
:file-module-options-api="getTransferOptionsCase" />
@change="handleActiveDebugChange" <httpRest
/> v-else-if="requestVModel.activeTab === RequestComposition.REST"
<httpQuery v-model:params="requestVModel.rest"
v-else-if="requestVModel.activeTab === RequestComposition.QUERY" :disabled-param-value="!isEditableApi"
v-model:params="requestVModel.query" :disabled-except-param="!isEditableApi"
:layout="activeLayout" @change="handleActiveDebugChange"
:disabled-param-value="!isEditableApi" />
:disabled-except-param="!isEditableApi" <precondition
:second-box-height="secondBoxHeight" v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION"
@change="handleActiveDebugChange" v-model:config="requestVModel.children[0].preProcessorConfig"
/> is-definition
<httpRest :disabled="!isEditableApi"
v-else-if="requestVModel.activeTab === RequestComposition.REST" @change="handleActiveDebugChange"
v-model:params="requestVModel.rest" />
:layout="activeLayout" <postcondition
:disabled-param-value="!isEditableApi" v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
:disabled-except-param="!isEditableApi" v-model:config="requestVModel.children[0].postProcessorConfig"
:second-box-height="secondBoxHeight" :response="responseResultBody"
@change="handleActiveDebugChange" :disabled="!isEditableApi"
/> is-definition
<precondition @change="handleActiveDebugChange"
v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION" />
v-model:config="requestVModel.children[0].preProcessorConfig" <assertion
is-definition v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
:disabled="!isEditableApi" v-model:params="requestVModel.children[0].assertionConfig.assertions"
@change="handleActiveDebugChange" :response="responseResultBody"
/> is-definition
<postcondition :disabled="!isEditableApi"
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION" :assertion-config="requestVModel.children[0].assertionConfig"
v-model:config="requestVModel.children[0].postProcessorConfig" :show-extraction="true"
:response="responseResultBody" script-code-editor-height="calc(100vh - 242px)"
:layout="activeLayout" />
:disabled="!isEditableApi" <auth
:second-box-height="secondBoxHeight" v-else-if="requestVModel.activeTab === RequestComposition.AUTH"
is-definition v-model:params="requestVModel.authConfig"
@change="handleActiveDebugChange" :disabled="!isEditableApi"
/> @change="handleActiveDebugChange"
<assertion />
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION" <setting
v-model:params="requestVModel.children[0].assertionConfig.assertions" v-else-if="requestVModel.activeTab === RequestComposition.SETTING"
:response="responseResultBody" v-model:params="requestVModel.otherConfig"
is-definition :disabled="!isEditableApi"
:disabled="!isEditableApi" @change="handleActiveDebugChange"
:assertion-config="requestVModel.children[0].assertionConfig" />
:show-extraction="true" </div>
script-code-editor-height="calc(100vh - 242px)" </a-spin>
/> <response
<auth v-if="visible"
v-else-if="requestVModel.activeTab === RequestComposition.AUTH" v-show="showResponse"
v-model:params="requestVModel.authConfig" ref="responseRef"
:disabled="!isEditableApi" v-model:active-layout="activeLayout"
@change="handleActiveDebugChange" v-model:active-tab="requestVModel.responseActiveTab"
/> class="response"
<setting :is-http-protocol="isHttpProtocol"
v-else-if="requestVModel.activeTab === RequestComposition.SETTING" :is-priority-local-exec="isPriorityLocalExec"
v-model:params="requestVModel.otherConfig" :request-url="requestVModel.url"
:disabled="!isEditableApi" :is-expanded="isVerticalExpanded"
@change="handleActiveDebugChange" :request-result="currentResponse"
/> :console="currentResponse?.console"
</div> :is-edit="false"
</div> is-definition
</a-spin> hide-layout-switch
</template> :loading="requestVModel.executeLoading || loading"
<template #second> @execute="execute"
<response >
v-if="visible" <template #titleRight>
v-show="showResponse" <loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" class="!mb-0" />
v-model:active-layout="activeLayout" </template>
v-model:active-tab="requestVModel.responseActiveTab" </response>
:is-http-protocol="isHttpProtocol" </div>
:is-priority-local-exec="isPriorityLocalExec"
:request-url="requestVModel.url"
:is-expanded="isVerticalExpanded"
:request-result="currentResponse"
:console="currentResponse?.console"
:is-edit="false"
is-definition
hide-layout-switch
:loading="requestVModel.executeLoading || loading"
@change-expand="changeVerticalExpand"
@change-layout="handleActiveLayoutChange"
@execute="execute"
>
<template #titleRight>
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" class="!mb-0" />
</template>
</response>
</template>
</MsSplitBox>
</div> </div>
</div> </div>
</MsDrawer> </MsDrawer>
@ -282,7 +252,6 @@
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
import MsDrawer from '@/components/pure/ms-drawer/index.vue'; import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue'; import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsTab from '@/components/pure/ms-tab/index.vue'; import MsTab from '@/components/pure/ms-tab/index.vue';
import assertion from '@/components/business/ms-assertion/index.vue'; import assertion from '@/components/business/ms-assertion/index.vue';
import loopPagination from './loopPagination.vue'; import loopPagination from './loopPagination.vue';
@ -772,47 +741,13 @@
const showResponse = computed( const showResponse = computed(
() => isHttpProtocol.value || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode () => isHttpProtocol.value || requestVModel.value.response?.requestResults[0]?.responseResult.responseCode
); );
const splitBoxSize = ref<string | number>(!showResponse.value ? 1 : 0.6);
const activeLayout = ref<'horizontal' | 'vertical'>('vertical'); const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
const splitContainerRef = ref<HTMLElement>(); const isVerticalExpanded = computed(() => activeLayout.value === 'vertical');
const secondBoxHeight = ref(0); const responseRef = ref<InstanceType<typeof response>>();
watch(
() => splitBoxSize.value,
debounce((val) => {
// 300ms
if (splitContainerRef.value) {
if (typeof val === 'string' && val.includes('px')) {
val = Number(val.split('px')[0]);
secondBoxHeight.value = splitContainerRef.value.clientHeight - val;
} else {
secondBoxHeight.value = splitContainerRef.value.clientHeight * (1 - val);
}
}
}, 300),
{
immediate: true,
}
);
const verticalSplitBoxRef = ref<InstanceType<typeof MsSplitBox>>();
const isVerticalExpanded = ref(true);
function handleVerticalExpandChange(val: boolean) {
isVerticalExpanded.value = val;
}
function changeVerticalExpand(val: boolean) { function changeVerticalExpand(val: boolean) {
isVerticalExpanded.value = val; responseRef.value?.changeExpand(val);
if (val) {
verticalSplitBoxRef.value?.expand(0.6);
} else {
verticalSplitBoxRef.value?.collapse(
splitContainerRef.value ? `${splitContainerRef.value.clientHeight - 42}px` : 0
);
}
} }
watch( watch(
() => showResponse.value, () => showResponse.value,
(val) => { (val) => {
@ -820,19 +755,12 @@
if (val) { if (val) {
changeVerticalExpand(true); changeVerticalExpand(true);
} else { } else {
isVerticalExpanded.value = false; changeVerticalExpand(false);
verticalSplitBoxRef.value?.collapse(1);
} }
}); });
} }
); );
function handleActiveLayoutChange() {
isVerticalExpanded.value = true;
splitBoxSize.value = 0.6;
verticalSplitBoxRef.value?.expand(0.6);
}
/** /**
* 生成请求参数 * 生成请求参数
* @param executeType 执行类型执行时传入 * @param executeType 执行类型执行时传入
@ -1132,14 +1060,35 @@
.btn-base-primary-disabled(); .btn-base-primary-disabled();
} }
} }
.tab-pane-container {
@apply flex-1 overflow-y-auto;
.ms-scroll-bar();
}
:deep(.arco-tabs-tab:first-child) { :deep(.arco-tabs-tab:first-child) {
margin-left: 0; margin-left: 0;
} }
:deep(.arco-tabs-tab) { :deep(.arco-tabs-tab) {
@apply leading-none; @apply leading-none;
} }
.request-tab-and-response {
overflow-x: hidden;
overflow-y: auto;
.ms-scroll-bar();
}
.sticky-content {
@apply sticky bg-white;
z-index: 101;
}
.request-content-and-response {
display: flex;
&.vertical {
flex-direction: column;
.response :deep(.response-head) {
@apply sticky bg-white;
top: 48px; // tab(border-bottom)
z-index: 11;
}
.request-tab-pane {
min-height: 400px;
}
}
}
</style> </style>

View File

@ -24,7 +24,6 @@
<postcondition <postcondition
v-model:config="postProcessorConfig" v-model:config="postProcessorConfig"
:is-definition="false" :is-definition="false"
:layout="activeLayout"
sql-code-editor-height="300px" sql-code-editor-height="300px"
:tip-content="t('apiScenario.openGlobalPostConditionTip')" :tip-content="t('apiScenario.openGlobalPostConditionTip')"
is-scenario is-scenario
@ -57,7 +56,6 @@
const { t } = useI18n(); const { t } = useI18n();
const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
const preProcessorConfig = defineModel<ExecuteConditionConfig>('preProcessorConfig', { const preProcessorConfig = defineModel<ExecuteConditionConfig>('preProcessorConfig', {
required: true, required: true,
}); });

View File

@ -4,7 +4,6 @@
:condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]" :condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]"
add-text="apiTestDebug.postCondition" add-text="apiTestDebug.postCondition"
response="" response=""
:height-used="600"
:show-associated-scene="props.showAssociatedScene" :show-associated-scene="props.showAssociatedScene"
:show-pre-post-request="props.showPrePostRequest" :show-pre-post-request="props.showPrePostRequest"
:request-radio-text-props="props.requestRadioTextProps" :request-radio-text-props="props.requestRadioTextProps"

View File

@ -4,7 +4,6 @@
:condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]" :condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]"
add-text="apiTestDebug.precondition" add-text="apiTestDebug.precondition"
response="" response=""
:height-used="600"
:show-associated-scene="props.showAssociatedScene" :show-associated-scene="props.showAssociatedScene"
:show-pre-post-request="props.showPrePostRequest" :show-pre-post-request="props.showPrePostRequest"
:request-radio-text-props="props.requestRadioTextProps" :request-radio-text-props="props.requestRadioTextProps"

View File

@ -175,7 +175,6 @@
:layout="activeLayout" :layout="activeLayout"
:disabled-param-value="false" :disabled-param-value="false"
:disabled-except-param="false" :disabled-except-param="false"
:second-box-height="secondBoxHeight"
:type-title="t('project.environmental.requestHeader')" :type-title="t('project.environmental.requestHeader')"
/> />
<a-form-item class="mt-4" asterisk-position="end" field="path" :label="t('project.environmental.http.authType')"> <a-form-item class="mt-4" asterisk-position="end" field="path" :label="t('project.environmental.http.authType')">
@ -303,7 +302,6 @@
const form = ref<HttpForm>({ ...initForm }); const form = ref<HttpForm>({ ...initForm });
const hostType = ref<string>('http://'); const hostType = ref<string>('http://');
const secondBoxHeight = ref(0);
const activeLayout = ref<'horizontal' | 'vertical'>('vertical'); const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
const httpRef = ref(); const httpRef = ref();

View File

@ -4,7 +4,6 @@
:layout="activeLayout" :layout="activeLayout"
:disabled-param-value="props.disabledParamValue" :disabled-param-value="props.disabledParamValue"
:disabled-except-param="props.disabledExceptParam" :disabled-except-param="props.disabledExceptParam"
:second-box-height="secondBoxHeight"
@change="emit('change')" @change="emit('change')"
/> />
</template> </template>
@ -32,7 +31,6 @@
}>(); }>();
const innerParams = useVModel(props, 'params', emit); const innerParams = useVModel(props, 'params', emit);
const secondBoxHeight = ref(0);
const activeLayout = ref<'horizontal' | 'vertical'>('vertical'); const activeLayout = ref<'horizontal' | 'vertical'>('vertical');
</script> </script>