feat(接口测试):接口调试参数对齐收尾 (#28886)

Co-authored-by: BAIQI <443543832@qq.com>
This commit is contained in:
MeterSphere Bot 2024-02-12 16:51:33 +08:00 committed by GitHub
parent 8e2d37021d
commit 301b8ffda4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 270 additions and 989 deletions

View File

@ -400,45 +400,6 @@ export interface LoginRes {
<a name="d3Gdu"></a>
## -mock
提供全局接口数据 mock 功能,避免因为调试而修改请求代码导致出现问题,按功能模块划分文件,通过`index.ts`暴露,示例如下:
```typescript
import MOCK from '@/utils/setup-mock';
import './user';
```
```typescript
import { mock } from '@/utils/setup-mock';
import { RequestEnum } from '@/enums/httpEnum';
const getProjectList = () => {
return [
{
id: '0283f238hf2',
num: 0,
organizationId: 'v3v4h434c3',
name: '发了多少',
description: 'string',
createTime: 0,
updateTime: 0,
updateUser: 'string',
createUser: 'string',
deleteTime: 0,
deleted: true,
deleteUser: 'string',
enable: true,
},
];
};
mock(RequestEnum.GET, '/system/project/list', getProjectList(), 200);
```
<a name="QgxDQ"></a>
## -router
项目路由管理模块,入口文件`index.ts`注册并暴露全部路由,以模块命名文件夹划分模块路由放置在`routes/*`下;`guard/*`下放置路由导航控制,包含权限、登录重定向等;`app-menus/index.ts`为菜单相关的路由信息;`constants.ts`定义路由常量,包括路由白名单、重定向路由名、默认主页路由信息等

View File

@ -52,8 +52,8 @@
const columns: ParamTableColumn[] = [
{
title: 'ms.assertion.variableName', //
dataIndex: 'name',
slotName: 'name',
dataIndex: 'key',
slotName: 'key',
showInTable: true,
showDrag: true,
options: responseHeaderOption,

View File

@ -1,8 +1,12 @@
<template>
<MsDrawer
v-model:visible="insertScriptDrawer"
:title="t('project.commonScript.insertCommonScript')"
:width="768"
:title="
props.enableRadioSelected
? t('project.commonScript.insertCommonScript')
: t('project.commonScript.insertCommonScript')
"
:width="960"
unmount-on-close
:show-continue="false"
:ok-loading="drawerLoading"
@ -26,10 +30,7 @@
></a-input-search>
</div>
<ms-base-table v-bind="propsRes" ref="tableRef" v-on="propsEvent">
<template #radio="{ record }">
<a-radio v-model="record.checked" @change="(value) => changeRadio(value, record)"></a-radio>
</template>
<ms-base-table v-bind="propsRes" v-model:selected-key="innerCheckedKey" v-on="propsEvent">
<template #name="{ record }">
<div class="flex items-center">
<div class="one-line-text max-w-[200px] cursor-pointer text-[rgb(var(--primary-5))]">{{ record.name }}</div>
@ -61,9 +62,10 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { defineModel, ref } from 'vue';
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
import { Language } from '@/components/pure/ms-code-editor/types';
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
@ -74,20 +76,27 @@
import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
import { type Languages } from './utils';
import { RequestConditionScriptLanguage } from '@/enums/apiEnum';
import debounce from 'lodash-es/debounce';
const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId);
const { t } = useI18n();
const props = defineProps<{
visible: boolean;
scriptLanguage: Languages;
enableRadioSelected?: boolean; //
okText?: string;
}>();
const props = withDefaults(
defineProps<{
visible: boolean;
scriptLanguage?: Language | RequestConditionScriptLanguage;
enableRadioSelected?: boolean; //
okText?: string;
checkedId?: string; // id
}>(),
{
checkedId: '',
}
);
const emit = defineEmits(['update:visible', 'save', 'addScript']);
const emit = defineEmits(['update:visible', 'update:checkedId', 'save', 'addScript']);
const insertScriptDrawer = computed({
get() {
return props.visible;
@ -109,7 +118,6 @@
},
{
title: 'project.commonScript.description',
slotName: 'description',
dataIndex: 'description',
width: 200,
showDrag: true,
@ -125,7 +133,6 @@
{
title: 'project.commonScript.tags',
dataIndex: 'tags',
slotName: 'tags',
showInTable: true,
isTag: true,
width: 150,
@ -133,15 +140,13 @@
},
{
title: 'project.commonScript.createUser',
slotName: 'createUser',
dataIndex: 'createUser',
dataIndex: 'createUserName',
showInTable: true,
width: 200,
showDrag: true,
},
{
title: 'project.commonScript.createTime',
slotName: 'createTime',
dataIndex: 'createTime',
sortable: {
sortDirections: ['ascend', 'descend'],
@ -159,30 +164,9 @@
},
];
const tableRef = ref();
const innerCheckedKey = defineModel<string>('checkedId', { default: '' });
const radioColumn = [
{
title: '',
dataIndex: 'radio',
slotName: 'radio',
width: 50,
showInTable: true,
},
];
watch(
() => insertScriptDrawer.value,
(val) => {
if (val) {
if (props.enableRadioSelected) {
const result = [...radioColumn, ...columns];
tableRef.value.initColumn(result);
}
}
}
);
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setProps } = useTable(
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
getInsertCommonScriptPage,
{
columns,
@ -190,7 +174,8 @@
x: '100%',
},
showSetting: false,
selectable: !props.enableRadioSelected,
selectable: true,
selectorType: props.enableRadioSelected ? 'radio' : 'checkbox',
heightUsed: 300,
showSelectAll: !props.enableRadioSelected,
},
@ -211,7 +196,7 @@
const isDisabled = computed(() => {
if (props.enableRadioSelected) {
return propsRes.value.data.filter((item) => item.checked).length > 0;
return !!innerCheckedKey.value;
}
return propsRes.value.selectedKeys.size > 0;
});
@ -233,7 +218,7 @@
if (props.enableRadioSelected) {
emit(
'save',
propsRes.value.data.find((item) => item.checked)
propsRes.value.data.find((item) => item.id === innerCheckedKey.value)
);
} else {
const selectKeysIds = [...propsRes.value.selectedKeys];
@ -252,14 +237,6 @@
emit('addScript');
}
function changeRadio(value, record) {
propsRes.value.data.forEach((item) => {
item.checked = false;
});
record.checked = true;
setProps({ data: propsRes.value.data });
}
watch(
() => props.visible,
(val) => {

View File

@ -136,8 +136,8 @@
const columns: MsTableColumn = [
{
title: 'project.commonScript.ParameterNames',
slotName: 'name',
dataIndex: 'name',
slotName: 'key',
dataIndex: 'key',
},
{
title: 'project.commonScript.ParameterValue',

View File

@ -32,7 +32,7 @@
</div>
<span
v-if="innerExpand"
class="collapsebtn absolute right-2 z-10 mr-1 flex items-center justify-center"
class="collapsebtn absolute right-2 top-2 z-10 mr-1 flex items-center justify-center"
@click="expandedHandler"
>
<icon-right class="text-[12px] text-[var(--color-text-4)]" />
@ -40,12 +40,13 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useVModel } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
import { useI18n } from '@/hooks/useI18n';
import { RequestConditionScriptLanguage } from '@/enums/apiEnum';
import type { CommonScriptMenu } from './types';
import { getCodeTemplate, type Languages, SCRIPT_MENU } from './utils';
@ -53,7 +54,7 @@
const props = defineProps<{
expand: boolean;
languagesType: Languages;
languagesType: Languages | RequestConditionScriptLanguage;
}>();
const emit = defineEmits<{

View File

@ -1,5 +1,5 @@
<template>
<div v-if="props.showType === 'commonScript'" class="w-full bg-[var(--color-bg-3)] p-4 pb-0">
<div v-if="props.showHeader && props.showType === 'commonScript'" class="w-full bg-[var(--color-bg-3)] p-4 pb-0">
<div class="flex items-center justify-between">
<div>
<MsTag class="!mr-2 cursor-pointer" theme="outline" @click="undoHandler">
@ -20,14 +20,15 @@
</div>
</div>
<div v-if="props.showType === 'commonScript'" class="flex bg-[var(--color-bg-3)]">
<div class="w-full">
<div class="relative w-full">
<MsCodeEditor
ref="codeEditorRef"
v-model:model-value="innerCodeValue"
title=""
:width="expandMenu ? '100%' : '68%'"
height="460px"
theme="MS-text"
theme="vs"
:language="(innerLanguagesType as Language)"
:read-only="false"
:show-full-screen="false"
:show-theme-change="false"
@ -50,7 +51,8 @@
title=""
width="100%"
height="calc(100vh - 155px)"
theme="MS-text"
theme="vs"
:language="(innerLanguagesType as Language)"
:read-only="false"
:show-full-screen="false"
:show-theme-change="false"
@ -74,6 +76,7 @@
import { useVModel } from '@vueuse/core';
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
import { Language } from '@/components/pure/ms-code-editor/types';
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
import FormApiImportDrawer from './formApiImportDrawer.vue';
import InsertCommonScript from './insertCommonScript.vue';
@ -83,21 +86,27 @@
import useAppStore from '@/store/modules/app';
import type { CommonScriptItem } from '@/models/projectManagement/commonScript';
import { RequestConditionScriptLanguage } from '@/enums/apiEnum';
import { type Languages } from './utils';
const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId);
const props = defineProps<{
showType: 'commonScript' | 'executionResult'; //
language: Languages;
code: string;
enableRadioSelected?: boolean;
executionResult?: string; //
}>();
const props = withDefaults(
defineProps<{
showType: 'commonScript' | 'executionResult'; //
language: Languages | RequestConditionScriptLanguage;
code: string;
enableRadioSelected?: boolean;
executionResult?: string; //
showHeader?: boolean;
}>(),
{
showHeader: true,
}
);
const emit = defineEmits<{
(e: 'update:language', value: Languages): void;
(e: 'update:language', value: Languages | RequestConditionScriptLanguage): void;
(e: 'update:code', value: string): void;
}>();
@ -105,8 +114,6 @@
const projectId = ref<string>(appStore.currentProjectId);
const commonScriptValue = ref('');
const innerLanguagesType = useVModel(props, 'language', emit);
const executionResultValue = useVModel(props, 'executionResult', emit);
@ -140,21 +147,21 @@
formApiExportVisible.value = true;
}
const codeEditorRef = ref();
const codeEditorRef = ref<InstanceType<typeof MsCodeEditor>>();
function formatCoding() {
codeEditorRef.value.formatCode(commonScriptValue.value);
codeEditorRef.value?.format();
}
const confirmLoading = ref<boolean>(false);
function insertHandler(code: string) {
codeEditorRef.value.insertContent(code);
codeEditorRef.value?.insertContent(code);
}
function saveHandler(data: CommonScriptItem[]) {
if (props.enableRadioSelected) {
codeEditorRef.value.insertContent(data[0].script);
codeEditorRef.value?.insertContent(data[0].script);
} else {
let scriptStr = '';
data.forEach((item) => {
@ -163,12 +170,12 @@
${item.script}
`;
});
codeEditorRef.value.insertContent(scriptStr);
codeEditorRef.value?.insertContent(scriptStr);
}
}
function undoHandler() {
codeEditorRef.value.undo();
codeEditorRef.value?.undo();
}
function clearCode() {

View File

@ -1,18 +1,12 @@
import { Language } from '@/components/pure/ms-code-editor/types';
import { useI18n } from '@/hooks/useI18n';
import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
import { RequestConditionScriptLanguage } from '@/enums/apiEnum';
const { t } = useI18n();
export type Languages =
| 'beanshell-jsr233'
| 'groovy'
| 'python'
| 'beanshell'
| 'nashornScript'
| 'rhinoScript'
| 'javascript';
export const SCRIPT_MENU: CommonScriptMenu[] = [
{
title: t('project.code_segment.importApiTest'),
@ -504,7 +498,7 @@ function jsCode(requestObj) {
return _jsTemplate(requestObj);
}
export function getCodeTemplate(language: Languages, requestObj: any) {
export function getCodeTemplate(language: Language | RequestConditionScriptLanguage, requestObj: any) {
switch (language) {
case 'groovy':
return groovyCode(requestObj);

View File

@ -1,5 +1,8 @@
<template>
<div ref="fullRef" class="h-full rounded-[4px] bg-[var(--color-fill-1)] p-[12px]">
<div
ref="fullRef"
class="h-full overflow-hidden rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[12px]"
>
<div v-if="showTitleLine" class="mb-[12px] flex items-center justify-between">
<div class="flex flex-wrap gap-[4px]">
<a-select
@ -44,7 +47,11 @@
</div>
</div>
<!-- 这里的 40px 是顶部标题的 40px -->
<div :class="`flex ${showTitleLine ? 'h-[calc(100%-40px)]' : 'h-full'} w-full flex-row`">
<div
:class="`flex ${
showTitleLine ? 'h-[calc(100%-40px)]' : 'h-full'
} w-full flex-row overflow-hidden rounded-[var(--border-radius-small)]`"
>
<div ref="codeContainerRef" :class="['ms-code-editor', isFullScreen ? 'ms-code-editor-full-screen' : '']"></div>
<slot name="rightBox"> </slot>
</div>
@ -221,7 +228,7 @@
function format() {
if (editor) {
//
// TODO:
editor.getAction('editor.action.formatDocument')?.run();
}
}
@ -293,7 +300,6 @@
width: v-bind(width);
height: v-bind(height);
border-radius: var(--border-radius-small);
&[data-mode-id='plaintext'] {
:deep(.mtk1) {
color: rgb(var(--primary-5));

View File

@ -19,6 +19,11 @@ export const LanguageEnum = {
XML: 'xml' as const,
YAML: 'yaml' as const,
SHELL: 'shell' as const,
BEANSHELL: 'beanshell' as const,
BEANSHELLJSR233: 'beanshell-jsr233' as const,
GROOVY: 'groovy' as const,
NASHORNSCRIPT: 'nashornScript' as const,
RHINOSCRIPT: 'rhinoScript' as const,
} as const;
export type Language = (typeof LanguageEnum)[keyof typeof LanguageEnum];
export interface Options {

View File

@ -19,7 +19,7 @@
innerActiveItemKey === item[itemKeyField] ? props.activeItemClass : '',
]"
>
<div class="flex-1" @click="emit('itemClick', item, index)">
<div class="flex-1 overflow-x-hidden" @click="emit('itemClick', item, index)">
<slot name="title" :item="item" :index="index"></slot>
</div>
<div class="flex items-center gap-[4px]">

View File

@ -43,8 +43,8 @@
/>
<a-radio
v-else-if="attrs.selectorType === 'radio'"
v-model:model-value="innerSelectedKey"
:value="record[rowKey || 'id']"
v-model:model-value="record.tableChecked"
@change="(val) => handleRadioChange(val as boolean, record)"
/>
</template>
</a-table-column>
@ -245,7 +245,7 @@
</template>
<script lang="ts" setup>
import { computed, nextTick, onMounted, ref, useAttrs } from 'vue';
import { computed, nextTick, onMounted, ref, useAttrs, watch } from 'vue';
import { useVModel } from '@vueuse/core';
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
@ -398,7 +398,35 @@
}
};
const innerSelectedKey = useVModel(props, 'selectedKey', emit); //
const innerSelectedKey = defineModel<string>('selectedKey', { default: '' }); //
const tempRecord = ref<TableData>({});
watch(
() => attrs.data,
(arr) => {
if (innerSelectedKey.value && Array.isArray(arr) && arr.length > 0) {
arr = arr.map((item: TableData) => {
if (item.id === innerSelectedKey.value) {
item.tableChecked = true;
tempRecord.value = item;
}
return item;
});
}
},
{
immediate: true,
}
);
function handleRadioChange(val: boolean, record: TableData) {
if (val) {
innerSelectedKey.value = record.id;
record.tableChecked = true;
tempRecord.value.tableChecked = false;
tempRecord.value = record;
}
}
// change
const handleSelectAllChange = (v: SelectAllEnum) => {

View File

@ -1,112 +0,0 @@
import { mock } from '@/utils/setup-mock';
import { RequestEnum } from '@/enums/httpEnum';
const getList = () => {
return {
data: {
list: [
{
id: 'e7bd7179-d63a-43a5-1a65-218473ee69ca',
projectId: '1a0666f0-2cb8-436b-8bfa-7be43497061c',
name: 'ceshi',
method: 'GET',
modulePath: '/未规划接口',
environmentId: '',
schedule: null,
status: 'Underway',
moduleId: '0432d873-c16e-4d15-bef9-76f0cf971db6',
userId: 'admin',
createTime: 1680770595817,
updateTime: 1680770604939,
protocol: 'HTTP',
path: '/s',
num: 100012,
tags: '',
originalState: null,
createUser: 'Administrator',
caseTotal: '1',
caseStatus: 'SUCCESS',
casePassingRate: '100.00%',
deleteTime: null,
deleteUserId: null,
order: null,
refId: 'e7bd7179-d63a-43a5-1a65-218473ee69ca',
versionId: 'cd41a097-2483-409b-83ea-a17256b032b7',
latest: true,
toBeUpdated: null,
toBeUpdateTime: null,
description: null,
request:
'{"type":"HTTPSamplerProxy","clazzName":"io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy","id":"e7bd7179-d63a-43a5-1a65-218473ee69ca","resourceId":null,"name":"ceshi","label":null,"referenced":null,"active":false,"index":null,"enable":true,"refType":null,"hashTree":[{"type":"Assertions","clazzName":"io.metersphere.api.dto.definition.request.assertions.MsAssertions","id":"54fe1204-0213-4aa0-01a7-552170d36190","resourceId":"5ec0cc23-9642-4dc5-aaaa-cb3f41cc0a2e","name":null,"label":null,"referenced":null,"active":false,"index":null,"enable":true,"refType":null,"hashTree":null,"projectId":null,"isMockEnvironment":false,"environmentId":null,"pluginId":null,"stepName":null,"parent":null,"scenarioAss":false,"regex":[],"jsonPath":[],"jsr223":[],"xpath2":[],"duration":{"enable":true,"type":"Duration","value":0,"valid":false},"document":{"enable":true,"type":"JSON","data":{"jsonFollowAPI":"false","xmlFollowAPI":"false","json":[],"xml":[],"assertionName":null}},"mockEnvironment":false}],"projectId":null,"isMockEnvironment":false,"environmentId":null,"pluginId":null,"stepName":null,"parent":null,"protocol":"HTTP","domain":null,"port":null,"method":"GET","path":"/s","connectTimeout":"60000","responseTimeout":"60000","headers":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"file":false,"valid":false}],"body":{"type":"KeyValue","raw":null,"format":null,"kvs":[],"binary":[],"jsonSchema":null,"tmpFilePath":null,"valid":false,"kv":false,"xml":false,"json":false},"rest":[],"url":null,"followRedirects":true,"autoRedirects":false,"doMultipartPost":false,"useEnvironment":null,"arguments":[{"name":null,"value":null,"type":"text","files":null,"description":null,"contentType":"text/plain","enable":true,"urlEncode":false,"required":false,"min":0,"max":0,"file":false,"valid":false}],"authManager":null,"isRefEnvironment":null,"alias":null,"customizeReq":false,"implementation":null,"mockEnvironment":false}',
response:
'{"id":null,"name":null,"enable":null,"type":"HTTP","headers":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"file":false,"valid":false}],"statusCode":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"file":false,"valid":false}],"body":{"type":"KeyValue","raw":null,"format":null,"kvs":[],"binary":[],"jsonSchema":null,"tmpFilePath":null,"valid":false,"kv":false,"xml":false,"json":false}}',
remark: '',
projectName: 'JIra',
userName: 'Administrator',
scenarioTotal: 0,
deleteUser: null,
scenarioIds: null,
caseType: 'apiCase',
apiType: null,
versionName: 'v1.0.0',
versionEnable: true,
updated: false,
fields: null,
},
{
id: '937be890-79bb-1b68-e03e-7d37a8b0a607',
projectId: '1a0666f0-2cb8-436b-8bfa-7be43497061c',
name: 'copy_copy_copy_copy_copy_asfasdf',
method: 'GET',
modulePath: '/未规划接口',
environmentId: '',
schedule: null,
status: 'Underway',
moduleId: '0432d873-c16e-4d15-bef9-76f0cf971db6',
userId: 'admin',
createTime: 1671009286163,
updateTime: 1672816917472,
protocol: 'HTTP',
path: '/safdddsafdfsdafsadfVBBBVV',
num: 100006,
tags: '',
originalState: null,
createUser: 'Administrator',
caseTotal: '0',
caseStatus: '-',
casePassingRate: '-',
deleteTime: null,
deleteUserId: null,
order: null,
refId: '937be890-79bb-1b68-e03e-7d37a8b0a607',
versionId: 'cd41a097-2483-409b-83ea-a17256b032b7',
latest: true,
toBeUpdated: null,
toBeUpdateTime: null,
description: null,
request:
'{"type":"HTTPSamplerProxy","clazzName":"io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy","id":"937be890-79bb-1b68-e03e-7d37a8b0a607","resourceId":null,"name":"copy_copy_copy_copy_copy_asfasdf","label":null,"referenced":null,"active":false,"index":null,"enable":true,"refType":null,"hashTree":[{"type":"Assertions","clazzName":"io.metersphere.api.dto.definition.request.assertions.MsAssertions","id":"956ee64d-ddf0-2cab-b390-896e12a84848","resourceId":"0cf5742b-b699-425b-b966-6e19a09d58c9","name":null,"label":null,"referenced":null,"active":false,"index":null,"enable":true,"refType":null,"hashTree":null,"projectId":null,"isMockEnvironment":false,"environmentId":null,"pluginId":null,"stepName":null,"parent":null,"scenarioAss":false,"regex":[],"jsonPath":[],"jsr223":[],"xpath2":[],"duration":{"enable":true,"type":"Duration","value":0,"valid":false},"document":{"enable":true,"type":"JSON","data":{"jsonFollowAPI":"false","xmlFollowAPI":"false","json":[],"xml":[],"assertionName":null}},"mockEnvironment":false}],"projectId":null,"isMockEnvironment":false,"environmentId":null,"pluginId":null,"stepName":null,"parent":null,"protocol":"HTTP","domain":null,"port":null,"method":"GET","path":"/safdddsafdfsdafsadfVBBBVV","connectTimeout":"60000","responseTimeout":"60000","headers":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"valid":false,"file":false}],"body":{"type":"KeyValue","raw":null,"format":null,"kvs":[],"binary":[],"jsonSchema":null,"tmpFilePath":null,"oldKV":true,"kv":false,"xml":false,"json":false,"valid":false},"rest":[],"url":null,"followRedirects":true,"autoRedirects":false,"doMultipartPost":false,"useEnvironment":null,"arguments":[{"name":"a","value":null,"type":"text","files":null,"description":null,"contentType":"text/plain","enable":true,"urlEncode":false,"required":false,"min":null,"max":null,"valid":true,"file":false},{"name":null,"value":null,"type":"text","files":null,"description":null,"contentType":"text/plain","enable":true,"urlEncode":false,"required":false,"min":null,"max":null,"valid":false,"file":false}],"authManager":null,"isRefEnvironment":null,"alias":null,"customizeReq":false,"implementation":null,"mockEnvironment":false}',
response:
'{"id":null,"name":null,"enable":null,"type":"HTTP","headers":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"valid":false,"file":false}],"statusCode":[{"name":"","value":"","type":null,"files":null,"description":null,"contentType":null,"enable":true,"urlEncode":false,"required":true,"min":null,"max":null,"valid":false,"file":false}],"body":{"type":"KeyValue","raw":null,"format":null,"kvs":[],"binary":[],"jsonSchema":null,"tmpFilePath":null,"oldKV":true,"kv":false,"xml":false,"json":false,"valid":false}}',
remark: '',
projectName: 'JIra',
userName: 'Administrator',
scenarioTotal: 0,
deleteUser: null,
scenarioIds: null,
caseType: 'apiCase',
apiType: null,
versionName: 'v1.0.0',
versionEnable: true,
updated: false,
fields: null,
},
],
total: 2,
current: 1,
},
};
};
mock(RequestEnum.POST, '/mock/api-test/define/list/', getList(), 200);

View File

@ -1,10 +0,0 @@
import MOCK from '@/utils/setup-mock';
import './user';
import './message-box';
import './api-test';
import './system/user';
import './system/project';
import './system/resourcePool';
MOCK.onAny().passThrough();

View File

@ -1,84 +0,0 @@
import { mock } from '@/utils/setup-mock';
import { RequestEnum } from '@/enums/httpEnum';
const haveReadIds: number[] = [];
const getMessageList = () => {
return [
{
id: 1,
type: 'message',
title: '郑曦月',
subTitle: '的私信',
avatar:
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/8361eeb82904210b4f55fab888fe8416.png~tplv-uwbnlip3yd-webp.webp',
content: '审批请求已发送,请查收',
time: '今天 12:30:01',
},
{
id: 2,
type: 'message',
title: '宁波',
subTitle: '的回复',
avatar:
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
content: '此处 bug 已经修复',
time: '今天 12:30:01',
},
{
id: 3,
type: 'message',
title: '宁波',
subTitle: '的回复',
avatar:
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
content: '此处 bug 已经修复',
time: '今天 12:20:01',
},
{
id: 4,
type: 'notice',
title: '续费通知',
subTitle: '',
avatar: '',
content: '您的产品使用期限即将截止,如需继续使用产品请前往购…',
time: '今天 12:20:01',
messageType: 3,
},
{
id: 5,
type: 'notice',
title: '规则开通成功',
subTitle: '',
avatar: '',
content: '内容屏蔽规则于 2021-12-01 开通成功并生效',
time: '今天 12:20:01',
messageType: 1,
},
{
id: 6,
type: 'todo',
title: '质检队列变更',
subTitle: '',
avatar: '',
content: '内容质检队列于 2021-12-01 19:50:23 进行变更,请重新…',
time: '今天 12:20:01',
messageType: 0,
},
].map((item) => ({
...item,
status: haveReadIds.indexOf(item.id) === -1 ? 0 : 1,
}));
};
mock(RequestEnum.GET, '/api/message/list', getMessageList(), 200);
mock(
RequestEnum.GET,
'/api/message/read',
(params: { body: string }) => {
const { ids } = JSON.parse(params.body);
haveReadIds.push(...(ids || []));
return true;
},
200
);

View File

@ -1,55 +0,0 @@
import { mock } from '@/utils/setup-mock';
import { RequestEnum } from '@/enums/httpEnum';
const getProjectList = () => {
return [
{
id: '0283f238hf2',
num: 0,
organizationId: 'v3v4h434c3',
name: '发了多少',
description: 'string',
createTime: 0,
updateTime: 0,
updateUser: 'string',
createUser: 'string',
deleteTime: 0,
deleted: true,
deleteUser: 'string',
enable: true,
},
{
id: 'f9h832',
num: 0,
organizationId: 'v3v4h434c3',
name: '你了大 V',
description: 'string',
createTime: 0,
updateTime: 0,
updateUser: 'string',
createUser: 'string',
deleteTime: 0,
deleted: true,
deleteUser: 'string',
enable: true,
},
{
id: '0v023i92',
num: 0,
organizationId: 'v3v4h434c3',
name: '代付款就是快递方式觉得都是就',
description: 'string',
createTime: 0,
updateTime: 0,
updateUser: 'string',
createUser: 'string',
deleteTime: 0,
deleted: true,
deleteUser: 'string',
enable: true,
},
];
};
mock(RequestEnum.GET, '/system/project/list', getProjectList(), 200);

View File

@ -1,161 +0,0 @@
// import { mock } from '@/utils/setup-mock';
// import { PoolListUrl } from '@/api/requrls/system/resourcePool';
// import { RequestEnum } from '@/enums/httpEnum';
// const getPoolList = () => {
// return [
// {
// id: '938uh9',
// name: 'ksajdfkas',
// type: 'Node',
// description: '年卡是健康的就是肯德基富士康',
// enable: true,
// createTime: 0,
// updateTime: 0,
// createUser: 'hShdf',
// apiTest: true,
// loadTest: true,
// uiTest: true,
// serverUrl: 'fldskfsl.sdjks.com',
// deleted: false,
// configuration: 'akjfhbgkdjfsokdsdfs',
// organizationList: [
// {
// id: 'string',
// num: 0,
// name: '组织 1',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 2',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 3',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 4',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// ],
// resources: ['192.168.1.1', '192.168.11.23'],
// },
// {
// id: 'dfopi03wif3',
// name: 'ksajdfkas',
// type: 'K8s',
// description: '生动地很多次私董会佛山的',
// enable: false,
// createTime: 0,
// updateTime: 0,
// createUser: 'hShdf',
// apiTest: true,
// loadTest: true,
// uiTest: true,
// serverUrl: 'fldskfsl.sdjks.com',
// deleted: false,
// configuration: 'akjfhbgkdjfsokdsdfs',
// organizationList: [
// {
// id: 'string',
// num: 0,
// name: '组织 1',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 2',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 3',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 4',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// ],
// resources: ['192.168.1.1', '192.168.11.23'],
// },
// ];
// };
// mock(RequestEnum.POST, PoolListUrl, getPoolList(), 200, true);
export default {};

View File

@ -1,254 +0,0 @@
// import { mock } from '@/utils/setup-mock';
// import { RequestEnum } from '@/enums/httpEnum';
// const getUserList = () => {
// return [
// {
// id: '103423',
// name: '大家的',
// email: 'dehihu@kds.sd',
// enable: true,
// createTime: 1686905750716,
// updateTime: 0,
// lastOrganizationId: 'string',
// phone: '18473647583',
// source: 'string',
// lastProjectId: 'string',
// createUser: 'string',
// updateUser: 'string',
// organizationList: [
// {
// id: 'string',
// num: 0,
// name: '组织 1',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 2',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 3',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 4',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// ],
// userRoleList: [
// {
// id: 'string',
// name: '角色 1',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 2',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 3',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 4',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// ],
// },
// {
// id: '103233',
// name: '发热发热',
// email: 'dehihu@kds.sd',
// enable: false,
// createTime: 1686905750716,
// updateTime: 0,
// lastOrganizationId: 'string',
// phone: '18473647583',
// source: 'string',
// lastProjectId: 'string',
// createUser: 'string',
// updateUser: 'string',
// organizationList: [
// {
// id: 'string',
// num: 0,
// name: '组织 1',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 2',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 3',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// {
// id: 'string',
// num: 0,
// name: '组织 4',
// description: 'blabla',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// updateUser: 'string',
// deleted: true,
// deleteUser: 'string',
// deleteTime: 0,
// enable: true,
// },
// ],
// userRoleList: [
// {
// id: 'string',
// name: '角色 1',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 2',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 3',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// {
// id: 'string',
// name: '角色 4',
// description: 'sdadasd',
// internal: true,
// type: 'string',
// createTime: 0,
// updateTime: 0,
// createUser: 'string',
// scopeId: 'string',
// pos: 0,
// },
// ],
// },
// ];
// };
// mock(RequestEnum.POST, '/user/page', getUserList(), 200, true);
export default {};

View File

@ -1,7 +0,0 @@
import { LoginUrl, LogoutUrl } from '@/api/requrls/user';
import { mock } from '@/utils/setup-mock';
import { RequestEnum } from '@/enums/httpEnum';
// mock(RequestEnum.POST, LoginUrl, {}, 200);
mock(RequestEnum.POST, LogoutUrl, null, 200);

View File

@ -178,9 +178,9 @@ export interface ExecuteConditionProcessorCommon {
processorType: RequestConditionProcessor;
}
// 执行请求-前后置条件-脚本处理器
export type ScriptProcessor = ScriptCommonConfig;
export type ScriptProcessor = ScriptCommonConfig & ExecuteConditionProcessorCommon;
// 执行请求-前后置条件-SQL脚本处理器
export interface SQLProcessor {
export interface SQLProcessor extends ExecuteConditionProcessorCommon {
description: string; // 描述
dataSourceId: string; // 数据源ID
environmentId: string; // 环境ID
@ -192,7 +192,7 @@ export interface SQLProcessor {
extractParams: KeyValueParam[]; // 提取参数列表
}
// 执行请求-前后置条件-等待时间处理器
export interface TimeWaitingProcessor {
export interface TimeWaitingProcessor extends ExecuteConditionProcessorCommon {
delay: number; // 等待时间 单位:毫秒
}
// 表达式类型
@ -219,12 +219,14 @@ export interface XPathExtract extends ExpressionCommonConfig {
responseFormat: ResponseBodyXPathAssertionFormat; // 响应格式
}
// 执行请求-前后置条件-参数提取处理器
export interface ExtractProcessor {
export interface ExtractProcessor extends ExecuteConditionProcessorCommon {
extractors: (RegexExtract | JSONPathExtract | XPathExtract)[];
}
// 执行请求-前后置条件配置
export type ExecuteConditionProcessor = ExecuteConditionProcessorCommon &
Partial<ScriptProcessor & SQLProcessor & TimeWaitingProcessor & ExtractProcessor>;
export type ExecuteConditionProcessor = Partial<
ScriptProcessor & SQLProcessor & TimeWaitingProcessor & ExtractProcessor
> &
ExecuteConditionProcessorCommon;
export interface ExecuteConditionConfig {
enableGlobal?: boolean; // 是否启用全局前/后置 默认为 true
processors: ExecuteConditionProcessor[];

View File

@ -1,83 +0,0 @@
import MSR from '@/api/http';
import { RequestEnum } from '@/enums/httpEnum';
import MockAdapter from 'axios-mock-adapter';
const MOCK = new MockAdapter(MSR.axiosInstance, { onNoMatch: 'throwException' });
/**
* mock-
* @param data mock
* @returns
*/
export const successResponseWrap = (data: unknown) => {
return {
data,
status: 'ok',
message: '请求成功',
code: 0,
};
};
/**
* mock-
* @param data mock
* @returns
*/
export const successTableResponseWrap = (data: unknown) => {
return {
data: { list: data },
status: 'ok',
message: '请求成功',
code: 100200,
};
};
/**
* mock-
* @param data mock
* @param message
* @param code
* @returns
*/
export const failResponseWrap = (data: unknown, message?: string, messageDetail?: string) => {
return {
data,
message: message || '请求失败',
messageDetail,
};
};
export const mock = (
method: RequestEnum,
url: string | RegExp,
data: unknown,
code: number,
isTable?: boolean,
message?: string,
messageDetail?: string
) => {
const methodMap = {
[RequestEnum.GET]: MOCK.onGet(url),
[RequestEnum.POST]: MOCK.onPost(url),
[RequestEnum.PUT]: MOCK.onPut(url),
[RequestEnum.DELETE]: MOCK.onDelete(url),
};
if (code === 200) {
return methodMap[method].reply(code, isTable ? successTableResponseWrap(data) : successResponseWrap(data));
}
return methodMap[method].reply(code, failResponseWrap(data, message, messageDetail));
};
/**
* mock url
* @param url
* @returns url
*/
export const makeMockUrl = (url: string) => {
const mockOrigin = window.location.origin;
return `${mockOrigin}/front${url}`;
};
export default MOCK;

View File

@ -84,6 +84,13 @@
</a-button>
</div>
</div>
<MsScriptDefined
v-if="condition.script !== undefined && condition.scriptLanguage !== undefined"
v-model:code="condition.script"
v-model:language="condition.scriptLanguage"
show-type="commonScript"
:show-header="false"
></MsScriptDefined>
</div>
<div v-else class="flex h-[calc(100%-47px)] flex-col">
<div class="mb-[16px] flex w-full items-center bg-[var(--color-text-n9)] p-[12px]">
@ -91,7 +98,7 @@
{{ condition.scriptName || '-' }}
</div>
<a-divider margin="8px" direction="vertical" />
<MsButton type="text" class="font-medium">
<MsButton type="text" class="font-medium" @click="showQuoteDrawer = true">
{{ t('apiTestDebug.quote') }}
</MsButton>
</div>
@ -111,7 +118,7 @@
<div>*</div>
</div>
</a-tooltip>
{{ record.type }}
{{ record.value }}
</template>
</MsBaseTable>
<div v-show="commonScriptShowType === 'scriptContent'" class="h-[calc(100%-76px)]">
@ -206,7 +213,14 @@
{{ t('apiTestDebug.waitTime') }}
<div class="text-[var(--color-text-4)]">(ms)</div>
</div>
<a-input-number v-model:model-value="condition.delay" mode="button" :step="100" :min="0" class="w-[160px]" />
<a-input-number
v-model:model-value="condition.delay"
mode="button"
:step="100"
:min="0"
class="w-[160px]"
model-event="input"
/>
</div>
<!-- 提取参数 -->
<div v-else-if="condition.processorType === RequestConditionProcessor.EXTRACT">
@ -295,6 +309,12 @@
:config="activeRecord"
@apply="handleFastExtractionApply"
/>
<InsertCommonScript
v-model:visible="showQuoteDrawer"
:checked-id="condition.scriptId"
enable-radio-selected
@save="saveQuoteScriptHandler"
/>
</template>
<script setup lang="ts">
@ -309,6 +329,8 @@
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import InsertCommonScript from '@/components/business/ms-common-script/insertCommonScript.vue';
import MsScriptDefined from '@/components/business/ms-common-script/scriptDefined.vue';
import fastExtraction from '../fastExtraction/index.vue';
import moreSetting from '../fastExtraction/moreSetting.vue';
import paramTable, { type ParamTableColumn } from '../paramTable.vue';
@ -355,7 +377,18 @@
});
}
const scriptEx = ref('');
const scriptEx = ref(`2023-12-04 11:19:28 INFO 9026fd6a 1-1 Thread started: 9026fd6a 1-1
2023-12-04 11:19:28 ERROR 9026fd6a 1-1 Problem in JSR223 script JSR223Sampler, message: {}
In file: inline evaluation of: prev.getResponseCode() import java.net.URI; import org.apache.http.client.method . . . '' Encountered "import" at line 2, column 1.
in inline evaluation of: prev.getResponseCode() import java.net.URI; import org.apache.http.client.method . . . '' at line number 2
javax.script.ScriptException '' at line number 2
javax.script.ScriptException '' at line number 2
javax.script.ScriptException '' at line number 2
javax.script.ScriptException '' at line number 2
javax.script.ScriptException '' at line number 2
javax.script.ScriptException
org.apache.http.client.method . . . '' at line number 2
`);
const { copy, isSupported } = useClipboard();
function copyScriptEx() {
@ -408,25 +441,22 @@
const { propsRes, propsEvent } = useTable(() => Promise.resolve([]), {
scroll: { x: '100%' },
columns,
noDisable: true,
});
propsRes.value.data = [
{
id: new Date().getTime(),
required: false,
key: 'asdasd',
type: 'string',
value: '',
description: '',
},
{
id: new Date().getTime(),
required: true,
key: '23d23d',
type: 'string',
value: '',
description: '',
},
] as any;
const showQuoteDrawer = ref(false);
function saveQuoteScriptHandler(item: any) {
condition.value.script = item.script;
condition.value.scriptId = item.id;
condition.value.scriptName = item.name;
condition.value.params = (JSON.parse(item.params) || []).map((e: any) => {
return {
key: e.name,
...e,
};
});
propsRes.value.data = condition.value.params as any[];
showQuoteDrawer.value = false;
}
const sqlSourceColumns: ParamTableColumn[] = [
{

View File

@ -10,7 +10,6 @@
item-class="mb-[4px] bg-white !p-[4px_8px]"
:item-more-actions="itemMoreActions"
active-item-class="!bg-[rgb(var(--primary-1))] text-[rgb(var(--primary-5))]"
:virtual-list-props="{ threshold: 100, height: '100%', fixedSize: true }"
draggable
@item-click="handleItemClick"
@more-action-select="handleMoreActionSelect"
@ -25,7 +24,16 @@
>
{{ index + 1 }}
</div>
<div>{{ t(conditionTypeNameMap[item.type]) }}</div>
<div
v-if="item.processorType === RequestConditionProcessor.TIME_WAITING"
:title="`${t('apiTestDebug.wait')}${item.delay}ms`"
class="one-line-text"
>
{{ `${t('apiTestDebug.wait')}${item.delay}` }} ms
</div>
<div v-else>
{{ t(conditionTypeNameMap[item.processorType]) }}
</div>
</div>
</template>
<template #itemRight="{ item }">
@ -44,6 +52,7 @@
import { useI18n } from '@/hooks/useI18n';
import { ExecuteConditionProcessor } from '@/models/apiTest/debug';
import { RequestConditionProcessor } from '@/enums/apiEnum';
const props = defineProps<{
list: ExecuteConditionProcessor[];
@ -57,6 +66,7 @@
const { t } = useI18n();
const data = useVModel(props, 'list', emit);
//
const focusItemKey = ref<any>('');
//
@ -72,16 +82,25 @@
},
];
watch(
() => props.activeId,
(activeId) => {
activeItem.value = data.value.find((item) => item.id === activeId) || data.value[0] || {};
emit('activeChange', activeItem.value);
},
{
immediate: true,
watchEffect(() => {
// id
let hasNoIdItem = false;
const tempArr = props.list.map((item, i) => {
if (!item.id) {
hasNoIdItem = true;
return {
...item,
id: new Date().getTime() + i,
};
}
return item;
});
if (hasNoIdItem) {
data.value = tempArr;
}
);
activeItem.value = data.value.find((item) => item.id === props.activeId) || data.value[0] || {};
emit('activeChange', activeItem.value);
});
function handleItemClick(item: ExecuteConditionProcessor) {
activeItem.value = item;

View File

@ -47,6 +47,7 @@
/>
<div v-else-if="innerParams.bodyType === RequestBodyFormat.BINARY">
<div class="mb-[16px] flex justify-between gap-[8px] bg-[var(--color-text-n9)] p-[12px]">
<!--TODO:文件上传&关联组件-->
<a-input
v-model:model-value="innerParams.binaryBody.description"
:placeholder="t('common.desc')"

View File

@ -46,13 +46,16 @@
:disabled="executeLoading"
class="exec-btn"
@click="execute"
@select="execute"
>
{{ t('apiTestDebug.serverExec') }}
{{ isLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
<template #icon>
<icon-down />
</template>
<template #content>
<a-doption>{{ t('apiTestDebug.localExec') }}</a-doption>
<a-doption :value="isLocalExec ? 'localExec' : 'serverExec'">
{{ isLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
</a-doption>
</template>
</a-dropdown-button>
<a-button type="secondary" @click="handleSaveShortcut">
@ -219,6 +222,7 @@
import { addDebug, executeDebug, getDebugDetail, updateDebug } from '@/api/modules/api-test/debug';
import { getPluginScript, getProtocolList } from '@/api/modules/api-test/management';
import { getSocket } from '@/api/modules/project-management/commonScript';
import { getLocalConfig } from '@/api/modules/user/index';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import { filterTree, getGenerateId } from '@/utils';
@ -491,6 +495,17 @@
}
}
const isLocalExec = ref(false); //
async function initLocalConfig() {
try {
const res = await getLocalConfig();
isLocalExec.value = res.find((e) => e.type === 'API')?.enable || false;
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
const pluginScriptMap = ref<Record<string, any>>({}); //
const pluginLoading = ref(false);
const currentPluginScript = computed<Record<string, any>[]>(
@ -660,7 +675,12 @@
};
}
async function execute() {
/**
* 执行调试
* @param val 执行类型
*/
async function execute(execuetType?: 'localExec' | 'serverExec') {
// TODO:&
if (isHttpProtocol.value) {
try {
executeLoading.value = true;
@ -701,7 +721,7 @@
const saveModalFormRef = ref<FormInstance>();
const saveLoading = ref(false);
const selectTree = computed(() =>
filterTree(props.moduleTree, (e) => {
filterTree(cloneDeep(props.moduleTree), (e) => {
e.draggable = false;
return e.type === 'MODULE';
})
@ -817,6 +837,7 @@
onBeforeMount(() => {
initProtocolList();
initLocalConfig();
});
onMounted(() => {

View File

@ -73,9 +73,9 @@
</div>
</template>
<template #extra="nodeData">
<!-- 默认模块的 id 是root默认模块不可编辑不可添加子模块 -->
<!-- 默认模块的 id 是root默认模块不可编辑不可添加子模块API不可添加子模块 -->
<popConfirm
v-if="nodeData.id !== 'root'"
v-if="nodeData.id !== 'root' && nodeData.type !== 'API'"
mode="add"
:all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')"
:parent-id="nodeData.id"
@ -228,6 +228,7 @@
return {
...node,
count: res[node.id] || 0,
draggable: node.id !== 'root',
};
});
} catch (error) {

View File

@ -65,6 +65,7 @@ export default {
'apiTestDebug.sql': 'SQL',
'apiTestDebug.sqlScript': 'SQL script',
'apiTestDebug.waitTime': 'Wait time',
'apiTestDebug.wait': 'Wait',
'apiTestDebug.script': 'Script',
'apiTestDebug.preconditionScriptName': 'Pre-script name',
'apiTestDebug.preconditionScriptNamePlaceholder': 'Please enter the pre-script name',

View File

@ -62,6 +62,7 @@ export default {
'apiTestDebug.sql': 'SQL 操作',
'apiTestDebug.sqlScript': 'SQL 脚本',
'apiTestDebug.waitTime': '等待时间',
'apiTestDebug.wait': '等待',
'apiTestDebug.script': '脚本操作',
'apiTestDebug.preconditionScriptName': '前置脚本名称',
'apiTestDebug.preconditionScriptNamePlaceholder': '请输入前置脚本名称',

View File

@ -41,6 +41,7 @@ export default {
'project.commonScript.changeHistory': 'Change history',
'project.commonScript.apply': 'Apply',
'project.commonScript.insertCommonScript': 'Insert common scripts',
'project.commonScript.quoteCommonScript': 'Quote common scripts',
'project.commonScript.commonScriptList': 'Public Script list',
'project.commonScript.folderSearchPlaceholder': 'Please enter a module name',
'project.commonScript.allApis': 'All interface',
@ -51,20 +52,16 @@ export default {
'project.commonScript.responsible': 'Those responsible',
'project.commonScript.path': 'path',
'project.commonScript.saveAsDraft': 'Save as draft',
'code_segment': {
importApiTest: 'Import from API definition',
newApiTest: 'New API test[JSON]',
},
'processor': {
codeTemplateGetVariable: 'Get Variable',
codeTemplateSetVariable: 'Set Variable',
codeTemplateGetResponseHeader: 'Get Response Header',
codeTemplateGetResponseCode: 'Get Response Code',
codeTemplateGetResponseResult: 'Get Response Result',
paramEnvironmentSetGlobalVariable: 'Set run environment param',
insertPublicScript: 'Insert the public script',
terminationTest: 'Termination test',
code_hide_report_length: 'Hide report length',
code_add_report_length: 'Add report length to head',
},
'project.code_segment.importApiTest': 'Import from API definition',
'project.code_segment.newApiTest': 'New API test[JSON]',
'project.processor.codeTemplateGetVariable': 'Get Variable',
'project.processor.codeTemplateSetVariable': 'Set Variable',
'project.processor.codeTemplateGetResponseHeader': 'Get Response Header',
'project.processor.codeTemplateGetResponseCode': 'Get Response Code',
'project.processor.codeTemplateGetResponseResult': 'Get Response Result',
'project.processor.paramEnvironmentSetGlobalVariable': 'Set run environment param',
'project.processor.insertPublicScript': 'Insert the public script',
'project.processor.terminationTest': 'Termination test',
'project.processor.code_hide_report_length': 'Hide report length',
'project.processor.code_add_report_length': 'Add report length to head',
};

View File

@ -40,6 +40,7 @@ export default {
'project.commonScript.changeHistory': '变更历史',
'project.commonScript.apply': '应用',
'project.commonScript.insertCommonScript': '插入公共脚本',
'project.commonScript.quoteCommonScript': '引用公共脚本',
'project.commonScript.commonScriptList': '公共脚本列表',
'project.commonScript.folderSearchPlaceholder': '请输入模块名称',
'project.commonScript.allApis': '全部接口',
@ -52,22 +53,16 @@ export default {
'project.commonScript.saveAsDraft': '保存为草稿',
'project.commonScript.saveDraftSuccessfully': '保存草稿成功',
'project.commonScript.appliedSuccessfully': '应用成功',
'project': {
code_segment: {
importApiTest: '从API定义导入',
newApiTest: '新API测试(JSON)',
},
processor: {
codeTemplateGetVariable: '获取变量',
codeTemplateSetVariable: '设置变量',
codeTemplateGetResponseHeader: '获取响应头',
codeTemplateGetResponseCode: '获取响应码',
codeTemplateGetResponseResult: '获取响应结果',
paramEnvironmentSetGlobalVariable: '设置环境参数',
insertPublicScript: '插入公共脚本',
terminationTest: '终止测试',
code_hide_report_length: '隐藏报文长度',
code_add_report_length: '报文头添加长度',
},
},
'project.code_segment.importApiTest': '从API定义导入',
'project.code_segment.newApiTest': '新API测试(JSON)',
'project.processor.codeTemplateGetVariable': '获取变量',
'project.processor.codeTemplateSetVariable': '设置变量',
'project.processor.codeTemplateGetResponseHeader': '获取响应头',
'project.processor.codeTemplateGetResponseCode': '获取响应状态码',
'project.processor.codeTemplateGetResponseResult': '获取响应结果',
'project.processor.paramEnvironmentSetGlobalVariable': '设置环境参数',
'project.processor.insertPublicScript': '插入公共脚本',
'project.processor.terminationTest': '终止测试',
'project.processor.code_hide_report_length': '隐藏报文长度',
'project.processor.code_add_report_length': '报文头添加长度',
};

View File

@ -73,15 +73,15 @@
{
title: 'project.environmental.paramName',
dataIndex: 'key',
slotName: 'name',
slotName: 'key',
showInTable: true,
showDrag: true,
columnSelectorDisabled: true,
},
{
title: 'project.environmental.paramType',
dataIndex: 'type',
slotName: 'type',
dataIndex: 'paramType',
slotName: 'paramType',
showInTable: true,
showDrag: true,
columnSelectorDisabled: true,

View File

@ -49,7 +49,7 @@
{
title: 'apiTestDebug.paramName',
dataIndex: 'key',
slotName: 'name',
slotName: 'key',
},
{
title: 'apiTestDebug.paramValue',