refactor(项目管理): 环境管理断言对接&样式调整
This commit is contained in:
parent
dd470ba328
commit
8265d5f21b
|
@ -37,7 +37,7 @@ export function exportEnv(selectIds: string[]) {
|
||||||
{ isTransformResponse: false }
|
{ isTransformResponse: false }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function editPosEnv(data: EnvListItem) {
|
export function editPosEnv(data: DragParam) {
|
||||||
return MSR.post<EnvListItem>({ url: envURL.editPosEnvUrl, data });
|
return MSR.post<EnvListItem>({ url: envURL.editPosEnvUrl, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,13 +303,7 @@
|
||||||
</paramsTable>
|
</paramsTable>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeTab === 'script'" class="mt-[16px]">
|
<div v-if="activeTab === 'script'" class="mt-[16px]">
|
||||||
<conditionContent
|
<conditionContent v-model:data="innerParams.script" :height-used="600" is-build-in class="mt-[16px]" />
|
||||||
:data="innerParams.script"
|
|
||||||
class="mt-[16px]"
|
|
||||||
@copy="copyListItem"
|
|
||||||
@delete="deleteListItem"
|
|
||||||
@change="emit('change')"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<fastExtraction v-model:visible="fastExtractionVisible" :config="activeRecord" @apply="handleFastExtractionApply" />
|
<fastExtraction v-model:visible="fastExtractionVisible" :config="activeRecord" @apply="handleFastExtractionApply" />
|
||||||
|
@ -362,25 +356,16 @@
|
||||||
(e: 'update:data', data: ExecuteConditionProcessor): void;
|
(e: 'update:data', data: ExecuteConditionProcessor): void;
|
||||||
(e: 'copy'): void;
|
(e: 'copy'): void;
|
||||||
(e: 'delete', id: number): void;
|
(e: 'delete', id: number): void;
|
||||||
(e: 'change'): void;
|
(e: 'change', param: Param): void;
|
||||||
}>();
|
}>();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const rootId = 0; // 1970-01-01 00:00:00 UTC
|
const rootId = 0; // 1970-01-01 00:00:00 UTC
|
||||||
|
|
||||||
// const innerParams = defineModel<Param>('modelValue', {
|
const props = defineProps<{
|
||||||
// default: {
|
value: Param;
|
||||||
// jsonPath: [],
|
}>();
|
||||||
// xPath: { responseFormat: 'XML', data: [] },
|
|
||||||
// script: {
|
const defaultParamItem = {
|
||||||
// id: new Date().getTime(),
|
|
||||||
// processorType: RequestConditionProcessor.SCRIPT,
|
|
||||||
// scriptName: '断言脚本名称',
|
|
||||||
// enableCommonScript: false,
|
|
||||||
// params: [],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
const innerParams = ref<Param>({
|
|
||||||
jsonPath: [],
|
jsonPath: [],
|
||||||
xPath: { responseFormat: 'XML', data: [] },
|
xPath: { responseFormat: 'XML', data: [] },
|
||||||
document: {
|
document: {
|
||||||
|
@ -408,6 +393,11 @@
|
||||||
scriptLanguage: RequestConditionScriptLanguage.JAVASCRIPT,
|
scriptLanguage: RequestConditionScriptLanguage.JAVASCRIPT,
|
||||||
script: new Date().getTime().toString(),
|
script: new Date().getTime().toString(),
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const innerParams = ref<Param>(props.value || defaultParamItem);
|
||||||
|
watchEffect(() => {
|
||||||
|
emit('change', innerParams.value);
|
||||||
});
|
});
|
||||||
const activeTab = ref('document');
|
const activeTab = ref('document');
|
||||||
const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>();
|
const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>();
|
||||||
|
@ -764,4 +754,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleScriptChange = (data: ExecuteConditionProcessor) => {
|
||||||
|
innerParams.value.script = data;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
const innerParams = defineModel<Param[]>('modelValue', { default: [] });
|
const innerParams = defineModel<Param[]>('modelValue', { default: [] });
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'change'): void; // 数据发生变化
|
(e: 'change', val: any[]): void; // 数据发生变化
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const defaultParamItem = {
|
const defaultParamItem = {
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
function handleParamTableChange(resultArr: any[], isInit?: boolean) {
|
function handleParamTableChange(resultArr: any[], isInit?: boolean) {
|
||||||
innerParams.value = [...resultArr];
|
innerParams.value = [...resultArr];
|
||||||
if (!isInit) {
|
if (!isInit) {
|
||||||
emit('change');
|
emit('change', resultArr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,18 +4,28 @@
|
||||||
<span class="text-[var(--color-text-1)]">{{ t('ms.assertion.responseTime') }}</span>
|
<span class="text-[var(--color-text-1)]">{{ t('ms.assertion.responseTime') }}</span>
|
||||||
<span class="text-[var(--color-text-4)]">(ms)</span>
|
<span class="text-[var(--color-text-4)]">(ms)</span>
|
||||||
</div>
|
</div>
|
||||||
<a-input-number v-model:model-value="value" :step="100" mode="button" />
|
<a-input-number v-model:model-value="innerParams" :step="100" mode="button" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const value = defineModel('modelValue', {
|
interface ResponseTimeTabProps {
|
||||||
default: 1000,
|
responseTime: number;
|
||||||
type: Number,
|
}
|
||||||
|
const props = defineProps<{
|
||||||
|
value: ResponseTimeTabProps;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const innerParams = ref(props.value.responseTime);
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change', val: ResponseTimeTabProps): void; // 数据发生变化
|
||||||
|
}>();
|
||||||
|
watchEffect(() => {
|
||||||
|
emit('change', { responseTime: innerParams.value });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,246 +1,41 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-full w-full flex-col">
|
<conditionContent v-model:data="innerParams" :height-used="600" is-build-in class="mt-[16px]" />
|
||||||
<a-radio-group v-model:model-value="condition.scriptType" size="small" class="mb-[16px]">
|
|
||||||
<a-radio value="manual">{{ t('apiTestDebug.manual') }}</a-radio>
|
|
||||||
<a-radio value="quote">{{ t('apiTestDebug.quote') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
<div
|
|
||||||
v-if="scriptType === 'manual'"
|
|
||||||
class="relative h-full w-full rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[12px]"
|
|
||||||
>
|
|
||||||
<div v-if="isShowEditScriptNameInput" class="absolute left-[12px] z-10 w-[calc(100%-24px)]">
|
|
||||||
<a-input
|
|
||||||
ref="scriptNameInputRef"
|
|
||||||
v-model:model-value="condition.name"
|
|
||||||
:placeholder="t('apiTestDebug.preconditionScriptNamePlaceholder')"
|
|
||||||
:max-length="255"
|
|
||||||
size="small"
|
|
||||||
@press-enter="isShowEditScriptNameInput = false"
|
|
||||||
@blur="isShowEditScriptNameInput = false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<a-tooltip :content="condition.name">
|
|
||||||
<div class="script-name-container">
|
|
||||||
<div class="one-line-text mr-[4px] max-w-[110px] font-medium text-[var(--color-text-1)]">
|
|
||||||
{{ condition.name }}
|
|
||||||
</div>
|
|
||||||
<MsIcon type="icon-icon_edit_outlined" class="edit-script-name-icon" @click="showEditScriptNameInput" />
|
|
||||||
</div>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-popover class="h-auto" position="top">
|
|
||||||
<div class="text-[rgb(var(--primary-5))]">{{ t('apiTestDebug.scriptEx') }}</div>
|
|
||||||
<template #content>
|
|
||||||
<div class="mb-[8px] flex items-center justify-between">
|
|
||||||
<div class="text-[14px] font-medium text-[var(--color-text-1)]">
|
|
||||||
{{ t('apiTestDebug.scriptEx') }}
|
|
||||||
</div>
|
|
||||||
<a-button
|
|
||||||
type="outline"
|
|
||||||
class="arco-btn-outline--secondary p-[0_8px]"
|
|
||||||
size="mini"
|
|
||||||
@click="copyScriptEx"
|
|
||||||
>
|
|
||||||
{{ t('common.copy') }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
<div class="flex h-[412px]">
|
|
||||||
<MsCodeEditor
|
|
||||||
v-model:model-value="scriptEx"
|
|
||||||
class="flex-1"
|
|
||||||
theme="MS-text"
|
|
||||||
width="500px"
|
|
||||||
height="388px"
|
|
||||||
:show-full-screen="false"
|
|
||||||
:show-theme-change="false"
|
|
||||||
read-only
|
|
||||||
>
|
|
||||||
</MsCodeEditor>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-[8px]">
|
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini">
|
|
||||||
<template #icon>
|
|
||||||
<MsIcon type="icon-icon_undo_outlined" class="text-var(--color-text-4)" size="12" />
|
|
||||||
</template>
|
|
||||||
{{ t('common.revoke') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="clearScript">
|
|
||||||
<template #icon>
|
|
||||||
<MsIcon type="icon-icon_clear" class="text-var(--color-text-4)" size="12" />
|
|
||||||
</template>
|
|
||||||
{{ t('common.clear') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="copyCondition">
|
|
||||||
{{ t('common.copy') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="deleteCondition">
|
|
||||||
{{ t('common.delete') }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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]">
|
|
||||||
<div class="text-[var(--color-text-2)]">
|
|
||||||
{{ condition.quoteScript.name || '-' }}
|
|
||||||
</div>
|
|
||||||
<a-divider margin="8px" direction="vertical" />
|
|
||||||
<MsButton type="text" class="font-medium">
|
|
||||||
{{ t('apiTestDebug.quote') }}
|
|
||||||
</MsButton>
|
|
||||||
</div>
|
|
||||||
<a-radio-group v-model:model-value="commonScriptShowType" size="small" type="button" class="mb-[8px] w-fit">
|
|
||||||
<a-radio value="parameters">{{ t('apiTestDebug.parameters') }}</a-radio>
|
|
||||||
<a-radio value="scriptContent">{{ t('apiTestDebug.scriptContent') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
<MsBaseTable v-show="commonScriptShowType === 'parameters'" v-bind="propsRes" v-on="propsEvent">
|
|
||||||
<template #value="{ record }">
|
|
||||||
<a-tooltip :content="t(record.required ? 'apiTestDebug.paramRequired' : 'apiTestDebug.paramNotRequired')">
|
|
||||||
<div
|
|
||||||
:class="[
|
|
||||||
record.required ? '!text-[rgb(var(--danger-5))]' : '!text-[var(--color-text-brand)]',
|
|
||||||
'!mr-[4px] !p-[4px]',
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<div>*</div>
|
|
||||||
</div>
|
|
||||||
</a-tooltip>
|
|
||||||
{{ record.type }}
|
|
||||||
</template>
|
|
||||||
</MsBaseTable>
|
|
||||||
<div v-show="commonScriptShowType === 'scriptContent'" class="h-[calc(100%-76px)]">
|
|
||||||
<MsCodeEditor
|
|
||||||
v-model:model-value="condition.quoteScript.script"
|
|
||||||
theme="MS-text"
|
|
||||||
height="100%"
|
|
||||||
:show-full-screen="false"
|
|
||||||
:show-theme-change="false"
|
|
||||||
read-only
|
|
||||||
>
|
|
||||||
</MsCodeEditor>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineModel } from 'vue';
|
import conditionContent from '@/views/api-test/components/condition/content.vue';
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
import { InputInstance, Message } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import { RequestConditionProcessor, RequestConditionScriptLanguage } from '@/enums/apiEnum';
|
||||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
interface ScriptItem {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = useI18n();
|
interface ScriptTabProps {
|
||||||
|
value: ScriptItem;
|
||||||
|
}
|
||||||
|
|
||||||
const scriptType = defineModel('scriptType', {
|
const defaultScriptItem: ScriptItem = {
|
||||||
type: String,
|
id: new Date().getTime(),
|
||||||
default: 'manual',
|
processorType: RequestConditionProcessor.SCRIPT,
|
||||||
});
|
scriptName: '断言脚本名称',
|
||||||
|
enableCommonScript: false,
|
||||||
|
params: [],
|
||||||
|
scriptId: '',
|
||||||
|
scriptLanguage: RequestConditionScriptLanguage.JAVASCRIPT,
|
||||||
|
script: '',
|
||||||
|
};
|
||||||
|
|
||||||
const condition = defineModel('modelValue', {
|
const props = defineProps<ScriptTabProps>();
|
||||||
type: Object,
|
|
||||||
default: () => ({
|
|
||||||
scriptType: 'manual',
|
|
||||||
name: '',
|
|
||||||
script: '',
|
|
||||||
quoteScript: {
|
|
||||||
name: '',
|
|
||||||
script: '',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
|
||||||
{
|
|
||||||
title: 'apiTestDebug.paramName',
|
|
||||||
dataIndex: 'name',
|
|
||||||
showTooltip: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'apiTestDebug.paramValue',
|
|
||||||
dataIndex: 'value',
|
|
||||||
slotName: 'value',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'apiTestDebug.desc',
|
|
||||||
dataIndex: 'desc',
|
|
||||||
showTooltip: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const { propsRes, propsEvent } = useTable(() => Promise.resolve([]), {
|
|
||||||
scroll: { x: '100%' },
|
|
||||||
columns,
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:data', data: Record<string, any>): void;
|
(e: 'change', val: ScriptItem): void; // 数据发生变化
|
||||||
(e: 'copy'): void;
|
|
||||||
(e: 'delete', id: string): void;
|
|
||||||
(e: 'change'): void;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 是否显示脚本名称编辑框
|
const innerParams = ref<any>(props.value || defaultScriptItem);
|
||||||
const isShowEditScriptNameInput = ref(false);
|
watchEffect(() => {
|
||||||
const scriptNameInputRef = ref<InputInstance>();
|
emit('change', innerParams.value);
|
||||||
|
});
|
||||||
function showEditScriptNameInput() {
|
|
||||||
isShowEditScriptNameInput.value = true;
|
|
||||||
nextTick(() => {
|
|
||||||
scriptNameInputRef.value?.focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
const commonScriptShowType = ref<'parameters' | 'scriptContent'>('parameters');
|
|
||||||
function copyScriptEx() {
|
|
||||||
if (isSupported) {
|
|
||||||
copy(scriptEx.value);
|
|
||||||
Message.success(t('apiTestDebug.scriptExCopySuccess'));
|
|
||||||
} else {
|
|
||||||
Message.warning(t('apiTestDebug.copyNotSupport'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function clearScript() {
|
|
||||||
condition.value.script = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制条件
|
|
||||||
*/
|
|
||||||
function copyCondition() {
|
|
||||||
emit('copy');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除条件
|
|
||||||
*/
|
|
||||||
function deleteCondition() {
|
|
||||||
emit('delete', condition.value.id);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -2,28 +2,60 @@
|
||||||
<div class="flex h-[62px] flex-row items-end gap-[8px] text-[var(--color-text-1)]">
|
<div class="flex h-[62px] flex-row items-end gap-[8px] text-[var(--color-text-1)]">
|
||||||
<div>
|
<div>
|
||||||
<div class="mb-[8px]">{{ t('ms.assertion.statusCode') }}</div>
|
<div class="mb-[8px]">{{ t('ms.assertion.statusCode') }}</div>
|
||||||
<a-select v-model="selectValue" class="w-[157px]">
|
<a-select
|
||||||
|
v-model="selectValue"
|
||||||
|
class="w-[157px]"
|
||||||
|
@change="
|
||||||
|
emit('change', {
|
||||||
|
statusCode: statusCode,
|
||||||
|
selectValue: selectValue,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
<a-option v-for="item in statusCodeOptions" :key="item.value" :value="item.value">
|
<a-option v-for="item in statusCodeOptions" :key="item.value" :value="item.value">
|
||||||
{{ t(item.label) }}
|
{{ t(item.label) }}
|
||||||
</a-option>
|
</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<a-input-number v-if="showInput" v-model:modelValue="statusCode" hide-button class="w-[157px]" />
|
<a-input-number
|
||||||
|
v-if="showInput"
|
||||||
|
v-model:modelValue="statusCode"
|
||||||
|
hide-button
|
||||||
|
class="w-[157px]"
|
||||||
|
@change="
|
||||||
|
emit('change', {
|
||||||
|
statusCode: statusCode,
|
||||||
|
selectValue: selectValue,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, defineModel } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
const selectValue = defineModel<string>('selectValue');
|
const props = defineProps<{
|
||||||
const statusCode = defineModel<number>('statusCode');
|
value: {
|
||||||
|
statusCode: number;
|
||||||
|
selectValue: string;
|
||||||
|
};
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['change']);
|
||||||
|
const selectValue = ref<string>('');
|
||||||
|
const statusCode = ref<number>(200);
|
||||||
const showInput = computed(() => selectValue.value !== 'none' && selectValue.value !== '');
|
const showInput = computed(() => selectValue.value !== 'none' && selectValue.value !== '');
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
watchEffect(() => {
|
||||||
|
selectValue.value = props.value.selectValue;
|
||||||
|
statusCode.value = props.value.statusCode;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<paramsTable
|
||||||
<paramsTable
|
v-model:params="innerParams"
|
||||||
v-model:params="innerParams"
|
:selectable="false"
|
||||||
:selectable="false"
|
:columns="columns"
|
||||||
:columns="columns"
|
:scroll="{ minWidth: '700px' }"
|
||||||
:scroll="{ minWidth: '700px' }"
|
:default-param-item="defaultParamItem"
|
||||||
:default-param-item="defaultParamItem"
|
@change="handleParamTableChange"
|
||||||
@change="handleParamTableChange"
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineModel } from 'vue';
|
|
||||||
|
|
||||||
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
import { statusCodeOptions } from '@/components/pure/ms-advance-filter/index';
|
||||||
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
|
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
|
||||||
|
|
||||||
|
@ -21,7 +17,11 @@
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const innerParams = defineModel<Param[]>('modelValue', { default: [] });
|
const props = defineProps<{
|
||||||
|
value?: Param[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const innerParams = ref(props.value || []);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'change'): void; // 数据发生变化
|
(e: 'change'): void; // 数据发生变化
|
||||||
|
|
|
@ -57,20 +57,41 @@
|
||||||
<section class="ms-assertion-body-right">
|
<section class="ms-assertion-body-right">
|
||||||
<StatusCodeTab
|
<StatusCodeTab
|
||||||
v-if="valueKey === 'statusCode'"
|
v-if="valueKey === 'statusCode'"
|
||||||
v-model:selectValue="codeTabState.selectValue"
|
:value="codeTabState.statusCode"
|
||||||
v-model:statusCode="codeTabState.statusCode"
|
@change="(val) => handleChange(val, 'statusCode')"
|
||||||
|
/>
|
||||||
|
<ResponseHeaderTab
|
||||||
|
v-if="valueKey === 'responseHeader'"
|
||||||
|
:value="codeTabState.responseHeader"
|
||||||
|
@change="(val) => handleChange(val, 'responseHeader')"
|
||||||
|
/>
|
||||||
|
<ResponseBodyTab
|
||||||
|
v-if="valueKey === 'responseBody'"
|
||||||
|
:value="codeTabState.responseBody"
|
||||||
|
@change="(val) => handleChange(val, 'responseBody')"
|
||||||
|
/>
|
||||||
|
<ResponseTimeTab
|
||||||
|
v-if="valueKey === 'responseTime'"
|
||||||
|
:value="codeTabState.responseTime"
|
||||||
|
@="(val) => handleChange(val, 'responseTime')"
|
||||||
|
/>
|
||||||
|
<VariableTab
|
||||||
|
v-if="valueKey === 'variable'"
|
||||||
|
:value="codeTabState.variable"
|
||||||
|
@change="(val) => handleChange(val, 'variable')"
|
||||||
|
/>
|
||||||
|
<ScriptTab
|
||||||
|
v-if="valueKey === 'script'"
|
||||||
|
:value="codeTabState.script"
|
||||||
|
@change="(val) => handleChange(val, 'script')"
|
||||||
/>
|
/>
|
||||||
<ResponseHeaderTab v-if="valueKey === 'responseHeader'" />
|
|
||||||
<ResponseBodyTab v-if="valueKey === 'responseBody'" />
|
|
||||||
<ResponseTimeTab v-if="valueKey === 'responseTime'" />
|
|
||||||
<VariableTab v-if="valueKey === 'variable'" />
|
|
||||||
<ScriptTab v-if="valueKey === 'script'" />
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { defineModel } from 'vue';
|
||||||
import { VueDraggable } from 'vue-draggable-plus';
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
@ -86,7 +107,7 @@
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { MsAssertionItem } from './type';
|
import { MsAssertionItem, ValueObject } from './type';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MsAssertion',
|
name: 'MsAssertion',
|
||||||
|
@ -96,17 +117,24 @@
|
||||||
// 当前鼠标所在的key
|
// 当前鼠标所在的key
|
||||||
const focusKey = ref<string>('');
|
const focusKey = ref<string>('');
|
||||||
// 选中的选项
|
// 选中的选项
|
||||||
const selectItems = ref<MsAssertionItem[]>([]);
|
const selectItems = defineModel<any[]>('params', { default: [] });
|
||||||
// Item点击的key
|
// Item点击的key
|
||||||
const activeKey = ref<string>('');
|
const activeKey = ref<string>('');
|
||||||
// valueKey
|
// valueKey
|
||||||
const valueKey = computed(() => {
|
const valueKey = computed(() => {
|
||||||
return activeKey.value && selectItems.value.find((item) => item.id === activeKey.value)?.value;
|
return activeKey.value && selectItems.value.find((item) => item.id === activeKey.value)?.value;
|
||||||
});
|
});
|
||||||
|
// 存储当前页面的所有状态
|
||||||
const codeTabState = reactive({
|
const codeTabState = computed({
|
||||||
selectValue: '',
|
get: () => {
|
||||||
statusCode: 200,
|
return (selectItems.value.find((item) => item.id === activeKey.value)?.valueObj || {}) as ValueObject;
|
||||||
|
},
|
||||||
|
set: (val: ValueObject) => {
|
||||||
|
const currentIndex = selectItems.value.findIndex((item) => item.id === val.assertionType);
|
||||||
|
const tmpArr = selectItems.value;
|
||||||
|
tmpArr[currentIndex].valueObj = { ...val };
|
||||||
|
selectItems.value = tmpArr;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const itemMoreActions: ActionsItem[] = [
|
const itemMoreActions: ActionsItem[] = [
|
||||||
{
|
{
|
||||||
|
@ -186,6 +214,10 @@
|
||||||
const handleItemClick = (item: MsAssertionItem) => {
|
const handleItemClick = (item: MsAssertionItem) => {
|
||||||
activeKey.value = item.id;
|
activeKey.value = item.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChange = (val: any, key: string) => {
|
||||||
|
codeTabState[key] = { ...val, assertionType: key };
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
|
export interface ValueObject {
|
||||||
|
assertionType: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
export interface MsAssertionItem {
|
export interface MsAssertionItem {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
valueObj: ValueObject;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ export interface EnvConfigItem {
|
||||||
export interface ProcessorConfig {
|
export interface ProcessorConfig {
|
||||||
apiProcessorConfig: ExecuteConditionProcessor[];
|
apiProcessorConfig: ExecuteConditionProcessor[];
|
||||||
}
|
}
|
||||||
|
export interface AssertionConfig {
|
||||||
|
assertions: EnvConfigItem[];
|
||||||
|
}
|
||||||
export interface EnvConfig {
|
export interface EnvConfig {
|
||||||
commonParams?: EnvConfigItem;
|
commonParams?: EnvConfigItem;
|
||||||
commmonVariables: EnvConfigItem[];
|
commmonVariables: EnvConfigItem[];
|
||||||
|
@ -42,7 +45,7 @@ export interface EnvConfig {
|
||||||
hostConfig: EnvConfigItem;
|
hostConfig: EnvConfigItem;
|
||||||
preProcessorConfig: ProcessorConfig;
|
preProcessorConfig: ProcessorConfig;
|
||||||
postProcessorConfig: ProcessorConfig;
|
postProcessorConfig: ProcessorConfig;
|
||||||
assertionConfig: EnvConfigItem[];
|
assertionConfig: AssertionConfig;
|
||||||
pluginConfigMap: EnvConfigItem;
|
pluginConfigMap: EnvConfigItem;
|
||||||
}
|
}
|
||||||
export interface EnvDetailItem {
|
export interface EnvDetailItem {
|
||||||
|
|
|
@ -24,7 +24,7 @@ const envParmasDefaultConfig = {
|
||||||
postProcessorConfig: {
|
postProcessorConfig: {
|
||||||
apiProcessorConfig: [],
|
apiProcessorConfig: [],
|
||||||
},
|
},
|
||||||
assertionConfig: [],
|
assertionConfig: { assertions: [] },
|
||||||
pluginConfigMap: {},
|
pluginConfigMap: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -77,10 +77,22 @@
|
||||||
</template>
|
</template>
|
||||||
{{ t('common.clear') }}
|
{{ t('common.clear') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="copyCondition">
|
<a-button
|
||||||
|
v-if="!props.isBuildIn"
|
||||||
|
type="outline"
|
||||||
|
class="arco-btn-outline--secondary p-[0_8px]"
|
||||||
|
size="mini"
|
||||||
|
@click="copyCondition"
|
||||||
|
>
|
||||||
{{ t('common.copy') }}
|
{{ t('common.copy') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="deleteCondition">
|
<a-button
|
||||||
|
v-if="!props.isBuildIn"
|
||||||
|
type="outline"
|
||||||
|
class="arco-btn-outline--secondary p-[0_8px]"
|
||||||
|
size="mini"
|
||||||
|
@click="deleteCondition"
|
||||||
|
>
|
||||||
{{ t('common.delete') }}
|
{{ t('common.delete') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -370,6 +382,7 @@
|
||||||
data: ExecuteConditionProcessor;
|
data: ExecuteConditionProcessor;
|
||||||
response?: string; // 响应内容
|
response?: string; // 响应内容
|
||||||
heightUsed?: number;
|
heightUsed?: number;
|
||||||
|
isBuildIn?: boolean; // 是否是内置的条件
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:data', data: ExecuteConditionProcessor): void;
|
(e: 'update:data', data: ExecuteConditionProcessor): void;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
<a-divider :margin="0" class="!mb-[16px]" />
|
<a-divider :margin="0" class="!mb-[16px]" />
|
||||||
<div class="px-[24px]">
|
<div class="content">
|
||||||
<EnvParamsTab v-if="activeKey === 'envParams'" />
|
<EnvParamsTab v-if="activeKey === 'envParams'" />
|
||||||
<HttpTab v-else-if="activeKey === 'http'" />
|
<HttpTab v-else-if="activeKey === 'http'" />
|
||||||
<DataBaseTab v-else-if="activeKey === 'database'" />
|
<DataBaseTab v-else-if="activeKey === 'database'" />
|
||||||
|
@ -34,16 +34,21 @@
|
||||||
<PostTab v-else-if="activeKey === 'post'" />
|
<PostTab v-else-if="activeKey === 'post'" />
|
||||||
<AssertTab v-else-if="activeKey === 'assert'" />
|
<AssertTab v-else-if="activeKey === 'assert'" />
|
||||||
<template v-for="item in envPluginList" :key="item.pluginId">
|
<template v-for="item in envPluginList" :key="item.pluginId">
|
||||||
<PluginTab v-if="activeKey === item.pluginId" :script="item.script" />
|
<PluginTab
|
||||||
|
v-if="activeKey === item.pluginId"
|
||||||
|
:model-value="store.currentEnvDetailInfo.config.pluginConfigMap[item.pluginId]"
|
||||||
|
:script="item.script"
|
||||||
|
@update:model-value="store.currentEnvDetailInfo.config.pluginConfigMap[item.pluginId] = $event"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<TabSettingDrawer v-model:visible="tabSettingVisible" @init-data="initTab" />
|
|
||||||
|
|
||||||
<div class="footer" :style="{ width: '100%' }">
|
<div class="footer" :style="{ width: '100%' }">
|
||||||
<a-button @click="handleReset">{{ t('common.cancel') }}</a-button>
|
<a-button @click="handleReset">{{ t('common.cancel') }}</a-button>
|
||||||
<a-button :disabled="!canSave" type="primary" @click="handleSave">{{ t('common.save') }}</a-button>
|
<a-button :disabled="!canSave" type="primary" @click="handleSave">{{ t('common.save') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<TabSettingDrawer v-model:visible="tabSettingVisible" @init-data="initTab" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -148,6 +153,7 @@
|
||||||
await initPlugin();
|
await initPlugin();
|
||||||
await store.initContentTabList([...sourceTabList, ...pluginTabList.value]);
|
await store.initContentTabList([...sourceTabList, ...pluginTabList.value]);
|
||||||
contentTabList.value = ((await store.getContentTabList()) || []).filter((item) => item.isShow);
|
contentTabList.value = ((await store.getContentTabList()) || []).filter((item) => item.isShow);
|
||||||
|
// 插件状态存储
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
envForm.value?.resetFields();
|
envForm.value?.resetFields();
|
||||||
|
@ -208,18 +214,24 @@
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.page {
|
.page {
|
||||||
|
position: relative;
|
||||||
transform: scale3d(1, 1, 1);
|
transform: scale3d(1, 1, 1);
|
||||||
padding-bottom: 180px;
|
height: 100%;
|
||||||
.header {
|
.header {
|
||||||
padding: 24px 24px 0;
|
padding: 24px 24px 0;
|
||||||
}
|
}
|
||||||
|
.content {
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0 24px;
|
||||||
|
max-height: calc(100% - 260px);
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
.no-content {
|
.no-content {
|
||||||
:deep(.arco-tabs-content) {
|
:deep(.arco-tabs-content) {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.footer {
|
.footer {
|
||||||
gap: 16px;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -227,7 +239,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
background-color: #ffffff;
|
||||||
box-shadow: 0 -1px 4px rgb(2 2 2 / 10%);
|
box-shadow: 0 -1px 4px rgb(2 2 2 / 10%);
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,16 +4,17 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MsAssertion from '@/components/business/ms-assertion/index.vue';
|
import MsAssertion from '@/components/business/ms-assertion/index.vue';
|
||||||
|
import { MsAssertionItem } from '@/components/business/ms-assertion/type';
|
||||||
|
|
||||||
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
||||||
|
|
||||||
const store = useProjectEnvStore();
|
const store = useProjectEnvStore();
|
||||||
|
|
||||||
const params = computed({
|
const params = computed({
|
||||||
set: (value: any) => {
|
set: (value: any[]) => {
|
||||||
store.currentEnvDetailInfo.config.assertionConfig = value;
|
store.currentEnvDetailInfo.config.assertionConfig.assertions = (value || []) as MsAssertionItem[];
|
||||||
},
|
},
|
||||||
get: () => store.currentEnvDetailInfo.config.assertionConfig || [],
|
get: () => (store.currentEnvDetailInfo.config.assertionConfig.assertions || []) as MsAssertionItem[],
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,12 @@
|
||||||
<div>
|
<div>
|
||||||
<!-- 环境list-->
|
<!-- 环境list-->
|
||||||
<div v-if="envList.length">
|
<div v-if="envList.length">
|
||||||
<VueDraggable v-model="envList" ghost-class="ghost" handle=".drag-handle">
|
<VueDraggable
|
||||||
|
v-model="envList"
|
||||||
|
ghost-class="ghost"
|
||||||
|
handle=".drag-handle"
|
||||||
|
@update="handleEnvGroupPosChange($event, EnvAuthTypeEnum.ENVIRONMENT_GROUP)"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="element in envList"
|
v-for="element in envList"
|
||||||
:key="element.id"
|
:key="element.id"
|
||||||
|
@ -125,7 +130,7 @@
|
||||||
v-model="evnGroupList"
|
v-model="evnGroupList"
|
||||||
ghost-class="ghost"
|
ghost-class="ghost"
|
||||||
handle=".drag-handle"
|
handle=".drag-handle"
|
||||||
@update="handleEnvGroupPosChange"
|
@update="handleEnvGroupPosChange($event, EnvAuthTypeEnum.ENVIRONMENT_GROUP)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="element in evnGroupList"
|
v-for="element in evnGroupList"
|
||||||
|
@ -215,6 +220,7 @@
|
||||||
import {
|
import {
|
||||||
deleteEnv,
|
deleteEnv,
|
||||||
deleteEnvGroup,
|
deleteEnvGroup,
|
||||||
|
editPosEnv,
|
||||||
exportEnv,
|
exportEnv,
|
||||||
exportGlobalParam,
|
exportGlobalParam,
|
||||||
groupEditPosEnv,
|
groupEditPosEnv,
|
||||||
|
@ -380,7 +386,7 @@
|
||||||
store.setCurrentGroupId(id);
|
store.setCurrentGroupId(id);
|
||||||
};
|
};
|
||||||
// 排序更新
|
// 排序更新
|
||||||
const handleEnvGroupPosChange = async (event: SortableEvent) => {
|
const handleEnvGroupPosChange = async (event: SortableEvent, type: EnvAuthTypeEnum) => {
|
||||||
try {
|
try {
|
||||||
const { oldIndex, newIndex } = event;
|
const { oldIndex, newIndex } = event;
|
||||||
if (oldIndex === newIndex) {
|
if (oldIndex === newIndex) {
|
||||||
|
@ -394,7 +400,11 @@
|
||||||
moveId: evnGroupList.value[_newIndex].id,
|
moveId: evnGroupList.value[_newIndex].id,
|
||||||
moveMode: _oldIndex > _newIndex ? 'BEFORE' : 'AFTER',
|
moveMode: _oldIndex > _newIndex ? 'BEFORE' : 'AFTER',
|
||||||
};
|
};
|
||||||
await groupEditPosEnv(params);
|
if (type === EnvAuthTypeEnum.ENVIRONMENT) {
|
||||||
|
await editPosEnv(params);
|
||||||
|
} else if (type === EnvAuthTypeEnum.ENVIRONMENT_GROUP) {
|
||||||
|
await groupEditPosEnv(params);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
Loading…
Reference in New Issue