feat(接口场景): 执行响应优化&循环响应展示
This commit is contained in:
parent
2441a882cc
commit
e8f1ce98cc
|
@ -3,7 +3,7 @@ import { SelectProps } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import { Size } from './types';
|
import { Size } from './types';
|
||||||
|
|
||||||
export const PAGE_ITEM_TYPES = ['page', 'more', 'previous', 'next'] as const;
|
export const PAGE_ITEM_TYPES = ['page', 'more', 'previous', 'next', 'jumper'] as const;
|
||||||
|
|
||||||
export type PageItemType = (typeof PAGE_ITEM_TYPES)[number];
|
export type PageItemType = (typeof PAGE_ITEM_TYPES)[number];
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
@enter="handleChange"
|
@enter="handleChange"
|
||||||
/>
|
/>
|
||||||
<span v-if="$slots['jumper-append']" :class="`${prefixCls}-append`"><slot name="jumper-append" /></span>
|
<span v-if="$slots['jumper-append']" :class="`${prefixCls}-append`">
|
||||||
<span :class="`${prefixCls}-total-page`" :style="{ 'min-width': totalPageWidth }">{{
|
<slot name="jumper-append" />
|
||||||
t('msPagination.page', { page: pages })
|
</span>
|
||||||
}}</span>
|
<span :class="`${prefixCls}-total-page`" :style="{ 'min-width': totalPageWidth }">
|
||||||
|
{{ t('msPagination.page', { page: pages }) }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -389,7 +389,7 @@ export interface Scenario {
|
||||||
executeSuccessCount: number; // 执行成功数量
|
executeSuccessCount: number; // 执行成功数量
|
||||||
executeFailCount: number; // 执行失败数量
|
executeFailCount: number; // 执行失败数量
|
||||||
reportId?: string | number; // 场景报告 id
|
reportId?: string | number; // 场景报告 id
|
||||||
stepResponses: Record<string | number, RequestResult>; // 步骤响应集合,key 为步骤 id,value 为步骤响应内容
|
stepResponses: Record<string | number, Array<RequestResult>>; // 步骤响应集合,key 为步骤 id,value 为步骤响应内容
|
||||||
isExecute?: boolean; // 是否从列表执行进去场景详情
|
isExecute?: boolean; // 是否从列表执行进去场景详情
|
||||||
isDebug?: boolean; // 是否调试,区分执行场景和批量调试步骤
|
isDebug?: boolean; // 是否调试,区分执行场景和批量调试步骤
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep, each } from 'lodash-es';
|
||||||
import JSEncrypt from 'jsencrypt';
|
import JSEncrypt from 'jsencrypt';
|
||||||
|
|
||||||
import { BatchActionQueryParams, MsTableColumnData } from '@/components/pure/ms-table/type';
|
import { BatchActionQueryParams, MsTableColumnData } from '@/components/pure/ms-table/type';
|
||||||
|
@ -194,6 +194,31 @@ export interface TreeNode<T> {
|
||||||
* @param tree 树形数组或树
|
* @param tree 树形数组或树
|
||||||
* @param customNodeFn 自定义节点函数
|
* @param customNodeFn 自定义节点函数
|
||||||
* @param customChildrenKey 自定义子节点的key
|
* @param customChildrenKey 自定义子节点的key
|
||||||
|
*/
|
||||||
|
export function traverseTree<T>(
|
||||||
|
tree: TreeNode<T> | TreeNode<T>[] | T | T[],
|
||||||
|
customNodeFn: (node: TreeNode<T>) => TreeNode<T> | null = (node) => node,
|
||||||
|
customChildrenKey = 'children'
|
||||||
|
) {
|
||||||
|
if (!Array.isArray(tree)) {
|
||||||
|
tree = [tree];
|
||||||
|
}
|
||||||
|
for (let i = 0; i < tree.length; i++) {
|
||||||
|
const node = tree[i];
|
||||||
|
if (typeof customNodeFn === 'function') {
|
||||||
|
customNodeFn(node);
|
||||||
|
}
|
||||||
|
if (node[customChildrenKey] && Array.isArray(node[customChildrenKey]) && node[customChildrenKey].length > 0) {
|
||||||
|
traverseTree(node[customChildrenKey], customNodeFn, customChildrenKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归遍历树形数组或树,返回新的树
|
||||||
|
* @param tree 树形数组或树
|
||||||
|
* @param customNodeFn 自定义节点函数
|
||||||
|
* @param customChildrenKey 自定义子节点的key
|
||||||
* @param parent 父节点
|
* @param parent 父节点
|
||||||
* @param parentPath 父节点路径
|
* @param parentPath 父节点路径
|
||||||
* @param level 节点层级
|
* @param level 节点层级
|
||||||
|
|
|
@ -61,7 +61,9 @@
|
||||||
value: item.id,
|
value: item.id,
|
||||||
}));
|
}));
|
||||||
currentEnv.value = currentEnv.value.length ? currentEnv.value : res[0]?.id;
|
currentEnv.value = currentEnv.value.length ? currentEnv.value : res[0]?.id;
|
||||||
await initEnvironment();
|
if (currentEnv.value) {
|
||||||
|
await initEnvironment();
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
<MsEditableTab
|
<MsEditableTab
|
||||||
v-model:active-tab="activeDebug"
|
v-model:active-tab="activeDebug"
|
||||||
v-model:tabs="debugTabs"
|
v-model:tabs="debugTabs"
|
||||||
:limit="10"
|
|
||||||
:readonly="!hasAnyPermission(['PROJECT_API_DEBUG:READ+ADD'])"
|
:readonly="!hasAnyPermission(['PROJECT_API_DEBUG:READ+ADD'])"
|
||||||
at-least-one
|
at-least-one
|
||||||
@add="addDebugTab"
|
@add="addDebugTab"
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex max-w-[60%] items-center gap-[8px]">
|
<div class="flex max-w-[60%] items-center gap-[8px]">
|
||||||
<stepTypeVue v-if="props.step" :step="props.step" />
|
<stepTypeVue
|
||||||
|
v-if="props.step && [ScenarioStepType.API, ScenarioStepType.CUSTOM_REQUEST].includes(props.step?.stepType)"
|
||||||
|
:step="props.step"
|
||||||
|
/>
|
||||||
<a-tooltip :content="title" position="bottom">
|
<a-tooltip :content="title" position="bottom">
|
||||||
<div class="one-line-text">
|
<div class="one-line-text">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
@ -228,7 +231,7 @@
|
||||||
<postcondition
|
<postcondition
|
||||||
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
|
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
|
||||||
v-model:config="requestVModel.children[0].postProcessorConfig"
|
v-model:config="requestVModel.children[0].postProcessorConfig"
|
||||||
:response="props.stepResponses?.[requestVModel.stepId]?.responseResult.body"
|
:response="responseResultBody"
|
||||||
:layout="activeLayout"
|
:layout="activeLayout"
|
||||||
:disabled="!isEditableApi || isQuoteScenarioStep"
|
:disabled="!isEditableApi || isQuoteScenarioStep"
|
||||||
:second-box-height="secondBoxHeight"
|
:second-box-height="secondBoxHeight"
|
||||||
|
@ -238,7 +241,7 @@
|
||||||
<assertion
|
<assertion
|
||||||
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
|
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
|
||||||
v-model:params="requestVModel.children[0].assertionConfig.assertions"
|
v-model:params="requestVModel.children[0].assertionConfig.assertions"
|
||||||
:response="props.stepResponses?.[requestVModel.stepId]?.responseResult.body"
|
:response="responseResultBody"
|
||||||
is-definition
|
is-definition
|
||||||
:disabled="!isEditableApi || isQuoteScenarioStep"
|
:disabled="!isEditableApi || isQuoteScenarioStep"
|
||||||
:assertion-config="requestVModel.children[0].assertionConfig"
|
:assertion-config="requestVModel.children[0].assertionConfig"
|
||||||
|
@ -269,8 +272,8 @@
|
||||||
:is-priority-local-exec="isPriorityLocalExec"
|
:is-priority-local-exec="isPriorityLocalExec"
|
||||||
:request-url="requestVModel.url"
|
:request-url="requestVModel.url"
|
||||||
:is-expanded="isVerticalExpanded"
|
:is-expanded="isVerticalExpanded"
|
||||||
:request-result="props.stepResponses?.[requestVModel.stepId]"
|
:request-result="requestResult"
|
||||||
:console="props.stepResponses?.[requestVModel.stepId]?.console"
|
:console="requestResult?.console"
|
||||||
:is-edit="false"
|
:is-edit="false"
|
||||||
is-definition
|
is-definition
|
||||||
:loading="requestVModel.executeLoading || loading"
|
:loading="requestVModel.executeLoading || loading"
|
||||||
|
@ -387,7 +390,7 @@
|
||||||
create: string;
|
create: string;
|
||||||
update: string;
|
update: string;
|
||||||
};
|
};
|
||||||
stepResponses?: Record<string | number, RequestResult>;
|
stepResponses?: Record<string | number, RequestResult[]>;
|
||||||
fileParams?: ScenarioStepFileParams;
|
fileParams?: ScenarioStepFileParams;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@ -485,13 +488,27 @@
|
||||||
if (_stepType.value.isCopyApi || _stepType.value.isQuoteApi) {
|
if (_stepType.value.isCopyApi || _stepType.value.isQuoteApi) {
|
||||||
return props.step?.name;
|
return props.step?.name;
|
||||||
}
|
}
|
||||||
return props.step?.name || t('apiScenario.customApi');
|
return t('apiScenario.customApi');
|
||||||
});
|
});
|
||||||
const showEnvPrefix = computed(
|
const showEnvPrefix = computed(
|
||||||
() =>
|
() =>
|
||||||
requestVModel.value.customizeRequestEnvEnable &&
|
requestVModel.value.customizeRequestEnvEnable &&
|
||||||
currentEnvConfig?.value.httpConfig.find((e) => e.type === 'NONE')?.url
|
currentEnvConfig?.value.httpConfig.find((e) => e.type === 'NONE')?.url
|
||||||
);
|
);
|
||||||
|
const responseResultBody = computed(() => {
|
||||||
|
const length = props.stepResponses?.[requestVModel.value.stepId]
|
||||||
|
? props.stepResponses?.[requestVModel.value.stepId]?.length
|
||||||
|
: 0;
|
||||||
|
// 取最后一次执行的结果
|
||||||
|
return props.stepResponses?.[requestVModel.value.stepId]?.[length].responseResult.body;
|
||||||
|
});
|
||||||
|
const requestResult = computed(() => {
|
||||||
|
const length = props.stepResponses?.[requestVModel.value.stepId]
|
||||||
|
? props.stepResponses?.[requestVModel.value.stepId]?.length
|
||||||
|
: 0;
|
||||||
|
// 取最后一次执行的结果
|
||||||
|
return props.stepResponses?.[requestVModel.value.stepId]?.[length];
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.stepResponses,
|
() => props.stepResponses,
|
||||||
|
@ -1086,6 +1103,7 @@
|
||||||
requestVModel.value = cloneDeep({
|
requestVModel.value = cloneDeep({
|
||||||
...defaultApiParams,
|
...defaultApiParams,
|
||||||
...props.request,
|
...props.request,
|
||||||
|
url: props.request.path, // 后台字段是 path
|
||||||
activeTab: contentTabList.value[0].value,
|
activeTab: contentTabList.value[0].value,
|
||||||
responseActiveTab: ResponseComposition.BODY,
|
responseActiveTab: ResponseComposition.BODY,
|
||||||
isNew: false,
|
isNew: false,
|
||||||
|
|
|
@ -178,7 +178,7 @@
|
||||||
<postcondition
|
<postcondition
|
||||||
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
|
v-else-if="requestVModel.activeTab === RequestComposition.POST_CONDITION"
|
||||||
v-model:config="requestVModel.children[0].postProcessorConfig"
|
v-model:config="requestVModel.children[0].postProcessorConfig"
|
||||||
:response="props.stepResponses?.[requestVModel.stepId]?.responseResult.body"
|
:response="responseResultBody"
|
||||||
:layout="activeLayout"
|
:layout="activeLayout"
|
||||||
:disabled="!isEditableApi"
|
:disabled="!isEditableApi"
|
||||||
:second-box-height="secondBoxHeight"
|
:second-box-height="secondBoxHeight"
|
||||||
|
@ -188,7 +188,7 @@
|
||||||
<assertion
|
<assertion
|
||||||
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
|
v-else-if="requestVModel.activeTab === RequestComposition.ASSERTION"
|
||||||
v-model:params="requestVModel.children[0].assertionConfig.assertions"
|
v-model:params="requestVModel.children[0].assertionConfig.assertions"
|
||||||
:response="props.stepResponses?.[requestVModel.stepId]?.responseResult.body"
|
:response="responseResultBody"
|
||||||
is-definition
|
is-definition
|
||||||
:disabled="!isEditableApi"
|
:disabled="!isEditableApi"
|
||||||
:assertion-config="requestVModel.children[0].assertionConfig"
|
:assertion-config="requestVModel.children[0].assertionConfig"
|
||||||
|
@ -219,8 +219,8 @@
|
||||||
:is-priority-local-exec="isPriorityLocalExec"
|
:is-priority-local-exec="isPriorityLocalExec"
|
||||||
:request-url="requestVModel.url"
|
:request-url="requestVModel.url"
|
||||||
:is-expanded="isVerticalExpanded"
|
:is-expanded="isVerticalExpanded"
|
||||||
:request-result="props.stepResponses?.[requestVModel.stepId]"
|
:request-result="requestResult"
|
||||||
:console="props.stepResponses?.[requestVModel.stepId]?.console"
|
:console="requestResult?.console"
|
||||||
:is-edit="false"
|
:is-edit="false"
|
||||||
is-definition
|
is-definition
|
||||||
:loading="requestVModel.executeLoading || loading"
|
:loading="requestVModel.executeLoading || loading"
|
||||||
|
@ -297,7 +297,7 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
request?: RequestParam; // 请求参数集合
|
request?: RequestParam; // 请求参数集合
|
||||||
stepResponses?: Record<string | number, RequestResult>;
|
stepResponses?: Record<string | number, RequestResult[]>;
|
||||||
fileParams?: ScenarioStepFileParams;
|
fileParams?: ScenarioStepFileParams;
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -396,6 +396,20 @@
|
||||||
() =>
|
() =>
|
||||||
activeStep.value?.stepType === ScenarioStepType.API_CASE && activeStep.value?.refType === ScenarioStepRefType.REF
|
activeStep.value?.stepType === ScenarioStepType.API_CASE && activeStep.value?.refType === ScenarioStepRefType.REF
|
||||||
);
|
);
|
||||||
|
const responseResultBody = computed(() => {
|
||||||
|
const length = props.stepResponses?.[requestVModel.value.stepId]
|
||||||
|
? props.stepResponses?.[requestVModel.value.stepId]?.length
|
||||||
|
: 0;
|
||||||
|
// 取最后一次执行的结果
|
||||||
|
return props.stepResponses?.[requestVModel.value.stepId]?.[length].responseResult.body;
|
||||||
|
});
|
||||||
|
const requestResult = computed(() => {
|
||||||
|
const length = props.stepResponses?.[requestVModel.value.stepId]
|
||||||
|
? props.stepResponses?.[requestVModel.value.stepId]?.length
|
||||||
|
: 0;
|
||||||
|
// 取最后一次执行的结果
|
||||||
|
return props.stepResponses?.[requestVModel.value.stepId]?.[length];
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.stepResponses,
|
() => props.stepResponses,
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
<template>
|
||||||
|
<MsPagination
|
||||||
|
v-if="props.loopTotal > 1"
|
||||||
|
v-model:current="currentLoop"
|
||||||
|
:page-size="1"
|
||||||
|
:total="props.loopTotal"
|
||||||
|
:show-jumper="props.loopTotal > 5"
|
||||||
|
show-total
|
||||||
|
size="mini"
|
||||||
|
class="loop-pagination"
|
||||||
|
>
|
||||||
|
<template #total="{ total }">
|
||||||
|
<div
|
||||||
|
class="rounded-[var(--border-radius-small)] bg-[var(--color-text-n8)] p-[2px_6px] leading-[20px] text-[var(--color-text-2)]"
|
||||||
|
>
|
||||||
|
{{ t('apiScenario.sumLoop', { count: total }) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #jumper-append>
|
||||||
|
{{ t('apiScenario.times') }}
|
||||||
|
</template>
|
||||||
|
</MsPagination>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import MsPagination from '@/components/pure/ms-pagination';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
loopTotal: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const currentLoop = defineModel<number>('currentLoop', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.arco-popover {
|
||||||
|
.loop-pagination {
|
||||||
|
@apply justify-start;
|
||||||
|
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
.ms-pagination-list {
|
||||||
|
gap: 2px;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
background-color: var(--color-text-n8);
|
||||||
|
.ms-pagination-item {
|
||||||
|
padding: 0 6px;
|
||||||
|
min-width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--border-radius-mini);
|
||||||
|
color: var(--color-text-1);
|
||||||
|
background-color: white;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.ms-pagination-item-previous {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.ms-pagination-item-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: var(--color-text-4);
|
||||||
|
}
|
||||||
|
.ms-pagination-item-active {
|
||||||
|
border: 1px solid rgb(var(--primary-5)) !important;
|
||||||
|
color: rgb(var(--primary-5)) !important;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-pagination-jumper {
|
||||||
|
gap: 4px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: var(--border-radius-mini);
|
||||||
|
color: var(--color-text-2);
|
||||||
|
background-color: var(--color-text-n8);
|
||||||
|
.ms-pagination-jumper-input {
|
||||||
|
width: 48px;
|
||||||
|
background-color: white;
|
||||||
|
input {
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-pagination-jumper-total-page {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<a-popover
|
||||||
|
position="br"
|
||||||
|
content-class="scenario-step-response-popover"
|
||||||
|
@popup-visible-change="emit('visibleChange', $event, props.step)"
|
||||||
|
>
|
||||||
|
<executeStatus :status="lastExecuteStatus" size="small" class="ml-[4px]" />
|
||||||
|
<template #content>
|
||||||
|
<div class="flex h-full flex-col">
|
||||||
|
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
||||||
|
<div class="flex-1">
|
||||||
|
<responseResult
|
||||||
|
:active-tab="ResponseComposition.BODY"
|
||||||
|
:request-result="currentResponse"
|
||||||
|
:console="currentResponse?.console"
|
||||||
|
:show-empty="false"
|
||||||
|
:is-edit="false"
|
||||||
|
is-definition
|
||||||
|
>
|
||||||
|
<template #titleLeft>
|
||||||
|
<div class="flex items-center text-[14px]">
|
||||||
|
<div class="font-medium text-[var(--color-text-1)]">{{ t('apiScenario.response') }}</div>
|
||||||
|
<a-tooltip :content="props.step.name">
|
||||||
|
<div class="one-line-text">({{ props.step.name }})</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</responseResult>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import executeStatus from './executeStatus.vue';
|
||||||
|
import loopPagination from './loopPagination.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { RequestResult } from '@/models/apiTest/common';
|
||||||
|
import { ScenarioStepItem } from '@/models/apiTest/scenario';
|
||||||
|
import { ResponseComposition, ScenarioExecuteStatus } from '@/enums/apiEnum';
|
||||||
|
|
||||||
|
const responseResult = defineAsyncComponent(
|
||||||
|
() => import('@/views/api-test/components/requestComposition/response/index.vue')
|
||||||
|
);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
step: ScenarioStepItem;
|
||||||
|
stepResponses: Record<string | number, Array<RequestResult>>;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits(['visibleChange']);
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const currentLoop = ref(1);
|
||||||
|
const currentResponse = computed(() => props.stepResponses?.[props.step.id]?.[currentLoop.value - 1]);
|
||||||
|
const loopTotal = computed(() => props.stepResponses?.[props.step.id]?.length || 0);
|
||||||
|
const lastExecuteStatus = computed(() => {
|
||||||
|
if (props.stepResponses[props.step.id] && props.stepResponses[props.step.id].length > 0) {
|
||||||
|
// 有一次失败就是失败
|
||||||
|
return props.stepResponses[props.step.id].some((report) => !report.isSuccessful)
|
||||||
|
? ScenarioExecuteStatus.FAILED
|
||||||
|
: ScenarioExecuteStatus.SUCCESS;
|
||||||
|
}
|
||||||
|
return props.step.executeStatus;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.scenario-step-response-popover {
|
||||||
|
width: 540px;
|
||||||
|
height: 500px;
|
||||||
|
.arco-popover-content {
|
||||||
|
@apply h-full;
|
||||||
|
.response {
|
||||||
|
.response-head {
|
||||||
|
background-color: var(--color-text-n9);
|
||||||
|
}
|
||||||
|
|
||||||
|
border: 1px solid var(--color-text-n8);
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
.arco-spin {
|
||||||
|
padding: 0;
|
||||||
|
.response-container {
|
||||||
|
padding: 0 16px 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -82,8 +82,16 @@
|
||||||
() => visible.value,
|
() => visible.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
scriptName.value = props.name || '';
|
scriptName.value = props.detail ? props.name || '' : '';
|
||||||
activeItem.value = cloneDeep(props.detail || defaultScript);
|
activeItem.value = cloneDeep(
|
||||||
|
props.detail
|
||||||
|
? {
|
||||||
|
...props.detail,
|
||||||
|
processorType: RequestConditionProcessor.SCRIPT,
|
||||||
|
polymorphicName: 'MsScriptElement',
|
||||||
|
}
|
||||||
|
: defaultScript
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default function useCreateActions() {
|
||||||
* @param steps 需要判断的步骤
|
* @param steps 需要判断的步骤
|
||||||
* @param parent 需要判断的父节点
|
* @param parent 需要判断的父节点
|
||||||
*/
|
*/
|
||||||
function checkedIfNeed(
|
function selectedIfNeed(
|
||||||
selectedKeys: (string | number)[],
|
selectedKeys: (string | number)[],
|
||||||
steps: (ScenarioStepItem | TreeNode<ScenarioStepItem>)[],
|
steps: (ScenarioStepItem | TreeNode<ScenarioStepItem>)[],
|
||||||
parent?: TreeNode<ScenarioStepItem>
|
parent?: TreeNode<ScenarioStepItem>
|
||||||
|
@ -59,7 +59,7 @@ export default function useCreateActions() {
|
||||||
step.id,
|
step.id,
|
||||||
newStep,
|
newStep,
|
||||||
createStepAction,
|
createStepAction,
|
||||||
(newNode, parent) => checkedIfNeed(selectedKeys, [newNode], parent),
|
(newNode, parent) => selectedIfNeed(selectedKeys, [newNode], parent),
|
||||||
'id'
|
'id'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -174,13 +174,13 @@ export default function useCreateActions() {
|
||||||
undefined,
|
undefined,
|
||||||
'id'
|
'id'
|
||||||
);
|
);
|
||||||
checkedIfNeed(selectedKeys, readyInsertSteps, step);
|
selectedIfNeed(selectedKeys, readyInsertSteps, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleCreateStep,
|
handleCreateStep,
|
||||||
buildInsertStepInfos,
|
buildInsertStepInfos,
|
||||||
handleCreateSteps,
|
handleCreateSteps,
|
||||||
checkedIfNeed,
|
selectedIfNeed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-[4px]">
|
<div
|
||||||
<a-popover
|
v-if="
|
||||||
v-if="
|
[ScenarioStepType.API, ScenarioStepType.API_CASE, ScenarioStepType.API_SCENARIO].includes(props.data.stepType)
|
||||||
[ScenarioStepType.API, ScenarioStepType.API_CASE, ScenarioStepType.API_SCENARIO].includes(props.data.stepType)
|
"
|
||||||
"
|
class="flex items-center gap-[4px]"
|
||||||
position="bl"
|
>
|
||||||
content-class="detail-popover"
|
<a-popover position="bl" content-class="detail-popover" arrow-class="hidden">
|
||||||
arrow-class="hidden"
|
|
||||||
>
|
|
||||||
<MsIcon type="icon-icon-draft" class="text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]" />
|
<MsIcon type="icon-icon-draft" class="text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]" />
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-col gap-[16px]">
|
<div class="flex flex-col gap-[16px]">
|
||||||
|
|
|
@ -178,7 +178,7 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #extraEnd="step">
|
<template #extraEnd="step">
|
||||||
<a-popover
|
<responsePopover
|
||||||
v-if="
|
v-if="
|
||||||
![
|
![
|
||||||
ScenarioStepType.LOOP_CONTROLLER,
|
ScenarioStepType.LOOP_CONTROLLER,
|
||||||
|
@ -189,32 +189,16 @@
|
||||||
(getExecuteStatus(step) === ScenarioExecuteStatus.SUCCESS ||
|
(getExecuteStatus(step) === ScenarioExecuteStatus.SUCCESS ||
|
||||||
getExecuteStatus(step) === ScenarioExecuteStatus.FAILED)
|
getExecuteStatus(step) === ScenarioExecuteStatus.FAILED)
|
||||||
"
|
"
|
||||||
position="br"
|
:step="step"
|
||||||
content-class="scenario-step-response-popover"
|
:step-responses="scenario.stepResponses"
|
||||||
@popup-visible-change="handleResponsePopoverVisibleChange($event, step)"
|
@visible-change="handleResponsePopoverVisibleChange"
|
||||||
>
|
/>
|
||||||
<executeStatus :status="getExecuteStatus(step)" size="small" />
|
<executeStatus
|
||||||
<template #content>
|
v-else-if="step.executeStatus"
|
||||||
<responseResult
|
:status="getExecuteStatus(step)"
|
||||||
:active-tab="ResponseComposition.BODY"
|
size="small"
|
||||||
:request-result="scenario.stepResponses?.[step.id]"
|
class="ml-[4px]"
|
||||||
:console="scenario.stepResponses?.[step.id]?.console"
|
/>
|
||||||
:show-empty="false"
|
|
||||||
:is-edit="false"
|
|
||||||
is-definition
|
|
||||||
>
|
|
||||||
<template #titleLeft>
|
|
||||||
<div class="flex items-center text-[14px]">
|
|
||||||
<div class="font-medium text-[var(--color-text-1)]">{{ t('apiScenario.response') }}</div>
|
|
||||||
<a-tooltip :content="step.name">
|
|
||||||
<div class="one-line-text">({{ step.name }})</div>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</responseResult>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
<executeStatus v-else-if="step.executeStatus" :status="getExecuteStatus(step)" size="small" />
|
|
||||||
</template>
|
</template>
|
||||||
<template v-if="steps.length === 0 && stepKeyword.trim() !== ''" #empty>
|
<template v-if="steps.length === 0 && stepKeyword.trim() !== ''" #empty>
|
||||||
<div
|
<div
|
||||||
|
@ -422,6 +406,7 @@
|
||||||
handleTreeDragDrop,
|
handleTreeDragDrop,
|
||||||
insertNodes,
|
insertNodes,
|
||||||
mapTree,
|
mapTree,
|
||||||
|
traverseTree,
|
||||||
TreeNode,
|
TreeNode,
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
|
|
||||||
|
@ -437,7 +422,6 @@
|
||||||
} from '@/models/apiTest/scenario';
|
} from '@/models/apiTest/scenario';
|
||||||
import { EnvConfig } from '@/models/projectManagement/environmental';
|
import { EnvConfig } from '@/models/projectManagement/environmental';
|
||||||
import {
|
import {
|
||||||
ResponseComposition,
|
|
||||||
ScenarioAddStepActionType,
|
ScenarioAddStepActionType,
|
||||||
ScenarioExecuteStatus,
|
ScenarioExecuteStatus,
|
||||||
ScenarioStepRefType,
|
ScenarioStepRefType,
|
||||||
|
@ -445,6 +429,7 @@
|
||||||
} from '@/enums/apiEnum';
|
} from '@/enums/apiEnum';
|
||||||
|
|
||||||
import type { RequestParam } from '../common/customApiDrawer.vue';
|
import type { RequestParam } from '../common/customApiDrawer.vue';
|
||||||
|
import updateStepStatus from '../utils';
|
||||||
import useCreateActions from './createAction/useCreateActions';
|
import useCreateActions from './createAction/useCreateActions';
|
||||||
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
|
||||||
import getStepType from '@/views/api-test/scenario/components/common/stepType/utils';
|
import getStepType from '@/views/api-test/scenario/components/common/stepType/utils';
|
||||||
|
@ -456,9 +441,7 @@
|
||||||
const customCaseDrawer = defineAsyncComponent(() => import('../common/customCaseDrawer.vue'));
|
const customCaseDrawer = defineAsyncComponent(() => import('../common/customCaseDrawer.vue'));
|
||||||
const importApiDrawer = defineAsyncComponent(() => import('../common/importApiDrawer/index.vue'));
|
const importApiDrawer = defineAsyncComponent(() => import('../common/importApiDrawer/index.vue'));
|
||||||
const scriptOperationDrawer = defineAsyncComponent(() => import('../common/scriptOperationDrawer.vue'));
|
const scriptOperationDrawer = defineAsyncComponent(() => import('../common/scriptOperationDrawer.vue'));
|
||||||
const responseResult = defineAsyncComponent(
|
const responsePopover = defineAsyncComponent(() => import('../common/responsePopover.vue'));
|
||||||
() => import('@/views/api-test/components/requestComposition/response/index.vue')
|
|
||||||
);
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
stepKeyword: string;
|
stepKeyword: string;
|
||||||
|
@ -500,9 +483,10 @@
|
||||||
|
|
||||||
function getExecuteStatus(step: ScenarioStepItem) {
|
function getExecuteStatus(step: ScenarioStepItem) {
|
||||||
if (scenario.value.stepResponses && scenario.value.stepResponses[step.id]) {
|
if (scenario.value.stepResponses && scenario.value.stepResponses[step.id]) {
|
||||||
return scenario.value.stepResponses[step.id].isSuccessful
|
// 有一次失败就是失败
|
||||||
? ScenarioExecuteStatus.SUCCESS
|
return scenario.value.stepResponses[step.id].some((report) => !report.isSuccessful)
|
||||||
: ScenarioExecuteStatus.FAILED;
|
? ScenarioExecuteStatus.FAILED
|
||||||
|
: ScenarioExecuteStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
return step.executeStatus;
|
return step.executeStatus;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +536,7 @@
|
||||||
/**
|
/**
|
||||||
* 增加步骤时判断父节点是否选中,如果选中则需要把新节点也选中
|
* 增加步骤时判断父节点是否选中,如果选中则需要把新节点也选中
|
||||||
*/
|
*/
|
||||||
function checkedIfNeed(step: TreeNode<ScenarioStepItem>, parent?: TreeNode<ScenarioStepItem>) {
|
function selectedIfNeed(step: TreeNode<ScenarioStepItem>, parent?: TreeNode<ScenarioStepItem>) {
|
||||||
if (parent && selectedKeys.value.includes(parent.id)) {
|
if (parent && selectedKeys.value.includes(parent.id)) {
|
||||||
// 添加子节点时,当前节点已选中,则需要把新节点也需要选中(因为父级选中子级也会展示选中状态)
|
// 添加子节点时,当前节点已选中,则需要把新节点也需要选中(因为父级选中子级也会展示选中状态)
|
||||||
selectedKeys.value.push(step.id);
|
selectedKeys.value.push(step.id);
|
||||||
|
@ -803,7 +787,7 @@
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
'after',
|
'after',
|
||||||
checkedIfNeed,
|
selectedIfNeed,
|
||||||
'id'
|
'id'
|
||||||
);
|
);
|
||||||
scenario.value.unSaved = true;
|
scenario.value.unSaved = true;
|
||||||
|
@ -971,6 +955,15 @@
|
||||||
customApiDrawerVisible.value = true;
|
customApiDrawerVisible.value = true;
|
||||||
} else if (step.stepType === ScenarioStepType.API_CASE) {
|
} else if (step.stepType === ScenarioStepType.API_CASE) {
|
||||||
activeStep.value = step;
|
activeStep.value = step;
|
||||||
|
if (
|
||||||
|
_stepType.isCopyCase &&
|
||||||
|
((stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||||
|
(stepDetails.value[step.id] === undefined && !step.isNew))
|
||||||
|
) {
|
||||||
|
// 只有复制的 case 需要查看步骤详情,引用的无法更改所以不需要在此初始化详情
|
||||||
|
// 查看场景详情时,详情映射中没有对应数据,初始化步骤详情(复制的步骤没有加载详情前就被复制,打开复制后的步骤就初始化被复制步骤的详情)
|
||||||
|
await getStepDetail(step);
|
||||||
|
}
|
||||||
customCaseDrawerVisible.value = true;
|
customCaseDrawerVisible.value = true;
|
||||||
} else if (step.stepType === ScenarioStepType.SCRIPT) {
|
} else if (step.stepType === ScenarioStepType.SCRIPT) {
|
||||||
activeStep.value = step;
|
activeStep.value = step;
|
||||||
|
@ -998,6 +991,7 @@
|
||||||
scenario.value.stepResponses[report.stepId] = temporaryStepReportMap[key];
|
scenario.value.stepResponses[report.stepId] = temporaryStepReportMap[key];
|
||||||
});
|
});
|
||||||
temporaryStepReportMap = {};
|
temporaryStepReportMap = {};
|
||||||
|
updateStepStatus(steps.value, scenario.value.stepResponses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1017,22 +1011,25 @@
|
||||||
if (step.reportId === data.reportId) {
|
if (step.reportId === data.reportId) {
|
||||||
// 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值
|
// 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值
|
||||||
data.taskResult.requestResults.forEach((result) => {
|
data.taskResult.requestResults.forEach((result) => {
|
||||||
scenario.value.stepResponses[result.stepId] = {
|
if (scenario.value.stepResponses[result.stepId] === undefined) {
|
||||||
|
scenario.value.stepResponses[result.stepId] = [];
|
||||||
|
}
|
||||||
|
scenario.value.stepResponses[result.stepId].push({
|
||||||
...result,
|
...result,
|
||||||
console: data.taskResult.console,
|
console: data.taskResult.console,
|
||||||
};
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 不是则需要把报告缓存起来,等切换到对应的tab再赋值
|
// 不是则需要把报告缓存起来,等切换到对应的tab再赋值
|
||||||
data.taskResult.requestResults.forEach((result) => {
|
data.taskResult.requestResults.forEach((result) => {
|
||||||
if (step.reportId) {
|
if (step.reportId) {
|
||||||
if (temporaryStepReportMap[step.reportId] === undefined) {
|
if (temporaryStepReportMap[step.reportId] === undefined) {
|
||||||
temporaryStepReportMap[step.reportId] = {};
|
temporaryStepReportMap[step.reportId] = [];
|
||||||
}
|
}
|
||||||
temporaryStepReportMap[step.reportId] = {
|
temporaryStepReportMap[step.reportId].push({
|
||||||
...result,
|
...result,
|
||||||
console: data.taskResult.console,
|
console: data.taskResult.console,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1041,6 +1038,7 @@
|
||||||
websocketMap[reportId].close();
|
websocketMap[reportId].close();
|
||||||
if (step.reportId === data.reportId) {
|
if (step.reportId === data.reportId) {
|
||||||
step.isExecuting = false;
|
step.isExecuting = false;
|
||||||
|
updateStepStatus([step], scenario.value.stepResponses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1056,6 +1054,7 @@
|
||||||
const [currentStep] = executeParams.steps;
|
const [currentStep] = executeParams.steps;
|
||||||
try {
|
try {
|
||||||
currentStep.isExecuting = true;
|
currentStep.isExecuting = true;
|
||||||
|
currentStep.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||||
debugSocket(currentStep, executeParams.reportId, executeType); // 开启websocket
|
debugSocket(currentStep, executeParams.reportId, executeType); // 开启websocket
|
||||||
const res = await debugScenario({
|
const res = await debugScenario({
|
||||||
id: scenario.value.id || '',
|
id: scenario.value.id || '',
|
||||||
|
@ -1093,21 +1092,18 @@
|
||||||
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, node.id, 'id');
|
const realStep = findNodeByKey<ScenarioStepItem>(steps.value, node.id, 'id');
|
||||||
if (realStep) {
|
if (realStep) {
|
||||||
realStep.reportId = getGenerateId();
|
realStep.reportId = getGenerateId();
|
||||||
if (
|
const _stepDetails = {};
|
||||||
[ScenarioStepType.API, ScenarioStepType.API_CASE, ScenarioStepType.CUSTOM_REQUEST].includes(realStep.stepType)
|
|
||||||
) {
|
|
||||||
// 请求和场景类型才直接显示执行中,其他控制器需要等待执行完毕才结算执行结果
|
|
||||||
realStep.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
|
||||||
}
|
|
||||||
const stepDetail = stepDetails.value[realStep.id];
|
|
||||||
delete scenario.value.stepResponses[realStep.id]; // 先移除上一次的执行结果
|
|
||||||
const stepFileParam = scenario.value.stepFileParam[realStep.id];
|
const stepFileParam = scenario.value.stepFileParam[realStep.id];
|
||||||
|
traverseTree(realStep, (step) => {
|
||||||
|
_stepDetails[step.id] = stepDetails.value[step.id];
|
||||||
|
step.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||||
|
delete scenario.value.stepResponses[step.id]; // 先移除上一次的执行结果
|
||||||
|
return step;
|
||||||
|
});
|
||||||
realExecute(
|
realExecute(
|
||||||
{
|
{
|
||||||
steps: [realStep as ScenarioStepItem],
|
steps: [realStep as ScenarioStepItem],
|
||||||
stepDetails: {
|
stepDetails: _stepDetails,
|
||||||
[realStep.id]: stepDetail,
|
|
||||||
},
|
|
||||||
reportId: realStep.reportId,
|
reportId: realStep.reportId,
|
||||||
uploadFileIds: stepFileParam?.uploadFileIds || [],
|
uploadFileIds: stepFileParam?.uploadFileIds || [],
|
||||||
linkFileIds: stepFileParam?.linkFileIds || [],
|
linkFileIds: stepFileParam?.linkFileIds || [],
|
||||||
|
@ -1286,7 +1282,10 @@
|
||||||
{
|
{
|
||||||
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
||||||
name: t('apiScenario.customApi'),
|
name: t('apiScenario.customApi'),
|
||||||
method: request.method,
|
config: {
|
||||||
|
protocol: request.protocol,
|
||||||
|
method: request.method,
|
||||||
|
},
|
||||||
id: request.stepId,
|
id: request.stepId,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
},
|
},
|
||||||
|
@ -1355,6 +1354,8 @@
|
||||||
if (activeStep.value && activeCreateAction.value) {
|
if (activeStep.value && activeCreateAction.value) {
|
||||||
handleCreateStep(
|
handleCreateStep(
|
||||||
{
|
{
|
||||||
|
id,
|
||||||
|
refType: ScenarioStepRefType.DIRECT,
|
||||||
stepType: ScenarioStepType.SCRIPT,
|
stepType: ScenarioStepType.SCRIPT,
|
||||||
name,
|
name,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
|
@ -1532,27 +1533,6 @@
|
||||||
color: rgb(var(--primary-5));
|
color: rgb(var(--primary-5));
|
||||||
background-color: rgb(var(--primary-1));
|
background-color: rgb(var(--primary-1));
|
||||||
}
|
}
|
||||||
.scenario-step-response-popover {
|
|
||||||
width: 500px;
|
|
||||||
height: 450px;
|
|
||||||
.arco-popover-content {
|
|
||||||
@apply h-full;
|
|
||||||
.response {
|
|
||||||
.response-head {
|
|
||||||
background-color: var(--color-text-n9);
|
|
||||||
}
|
|
||||||
|
|
||||||
border: 1px solid var(--color-text-n8);
|
|
||||||
border-radius: var(--border-radius-small);
|
|
||||||
.arco-spin {
|
|
||||||
padding: 0;
|
|
||||||
.response-container {
|
|
||||||
padding: 0 16px 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -8,10 +8,11 @@ import { ScenarioExecuteStatus, ScenarioStepType } from '@/enums/apiEnum';
|
||||||
*/
|
*/
|
||||||
export default function updateStepStatus(
|
export default function updateStepStatus(
|
||||||
steps: ScenarioStepItem[],
|
steps: ScenarioStepItem[],
|
||||||
stepResponses: Record<string | number, RequestResult>
|
stepResponses: Record<string | number, RequestResult[]>
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < steps.length; i++) {
|
for (let i = 0; i < steps.length; i++) {
|
||||||
const node = steps[i];
|
const node = steps[i];
|
||||||
|
console.log('node', node.stepType, node.executeStatus);
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
ScenarioStepType.LOOP_CONTROLLER,
|
ScenarioStepType.LOOP_CONTROLLER,
|
||||||
|
@ -54,10 +55,11 @@ export default function updateStepStatus(
|
||||||
node.executeStatus = ScenarioExecuteStatus.SUCCESS;
|
node.executeStatus = ScenarioExecuteStatus.SUCCESS;
|
||||||
} else if (node.executeStatus === ScenarioExecuteStatus.EXECUTING) {
|
} else if (node.executeStatus === ScenarioExecuteStatus.EXECUTING) {
|
||||||
// 非逻辑控制器直接更改本身状态
|
// 非逻辑控制器直接更改本身状态
|
||||||
if (stepResponses[node.id]) {
|
if (stepResponses[node.id] && stepResponses[node.id].length > 0) {
|
||||||
node.executeStatus = stepResponses[node.id].isSuccessful
|
console.log('stepResponses[node.id]', stepResponses[node.id]);
|
||||||
? ScenarioExecuteStatus.SUCCESS
|
node.executeStatus = stepResponses[node.id].some((report) => !report.isSuccessful)
|
||||||
: ScenarioExecuteStatus.FAILED;
|
? ScenarioExecuteStatus.FAILED
|
||||||
|
: ScenarioExecuteStatus.SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
node.executeStatus = ScenarioExecuteStatus.UN_EXECUTE;
|
node.executeStatus = ScenarioExecuteStatus.UN_EXECUTE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,13 +161,6 @@
|
||||||
|
|
||||||
function setStepExecuteStatus() {
|
function setStepExecuteStatus() {
|
||||||
updateStepStatus(activeScenarioTab.value.steps, activeScenarioTab.value.stepResponses);
|
updateStepStatus(activeScenarioTab.value.steps, activeScenarioTab.value.stepResponses);
|
||||||
// activeScenarioTab.value.steps = mapTree<ScenarioStepItem>(activeScenarioTab.value.steps, (step) => {
|
|
||||||
// if (step.executeStatus === ScenarioExecuteStatus.EXECUTING) {
|
|
||||||
// // 如果结束执行时还有步骤是执行中状态,则设置为未执行
|
|
||||||
// step.executeStatus = ScenarioExecuteStatus.UN_EXECUTE;
|
|
||||||
// }
|
|
||||||
// return step;
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,10 +178,13 @@
|
||||||
if (activeScenarioTab.value.reportId === data.reportId) {
|
if (activeScenarioTab.value.reportId === data.reportId) {
|
||||||
// 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值
|
// 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值
|
||||||
data.taskResult.requestResults.forEach((result) => {
|
data.taskResult.requestResults.forEach((result) => {
|
||||||
activeScenarioTab.value.stepResponses[result.stepId] = {
|
if (activeScenarioTab.value.stepResponses[result.stepId] === undefined) {
|
||||||
|
activeScenarioTab.value.stepResponses[result.stepId] = [];
|
||||||
|
}
|
||||||
|
activeScenarioTab.value.stepResponses[result.stepId].push({
|
||||||
...result,
|
...result,
|
||||||
console: data.taskResult.console,
|
console: data.taskResult.console,
|
||||||
};
|
});
|
||||||
if (result.isSuccessful) {
|
if (result.isSuccessful) {
|
||||||
activeScenarioTab.value.executeSuccessCount += 1;
|
activeScenarioTab.value.executeSuccessCount += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,10 +198,13 @@
|
||||||
if (temporaryScenarioReportMap[activeScenarioTab.value.reportId] === undefined) {
|
if (temporaryScenarioReportMap[activeScenarioTab.value.reportId] === undefined) {
|
||||||
temporaryScenarioReportMap[activeScenarioTab.value.reportId] = {};
|
temporaryScenarioReportMap[activeScenarioTab.value.reportId] = {};
|
||||||
}
|
}
|
||||||
temporaryScenarioReportMap[activeScenarioTab.value.reportId][result.stepId] = {
|
if (temporaryScenarioReportMap[activeScenarioTab.value.reportId][result.stepId]) {
|
||||||
|
temporaryScenarioReportMap[activeScenarioTab.value.reportId][result.stepId] = [];
|
||||||
|
}
|
||||||
|
temporaryScenarioReportMap[activeScenarioTab.value.reportId][result.stepId].push({
|
||||||
...result,
|
...result,
|
||||||
console: data.taskResult.console,
|
console: data.taskResult.console,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@ export default {
|
||||||
'api_scenario.table.tableNoDataAndPlease': '暂无数据,请',
|
'api_scenario.table.tableNoDataAndPlease': '暂无数据,请',
|
||||||
'api_scenario.table.or': '或',
|
'api_scenario.table.or': '或',
|
||||||
'apiScenario.execute': '执行',
|
'apiScenario.execute': '执行',
|
||||||
|
'apiScenario.prev': '上一次',
|
||||||
|
'apiScenario.next': '下一次',
|
||||||
|
'apiScenario.sumLoop': '共{count}次循环',
|
||||||
|
'apiScenario.times': '次',
|
||||||
// 批量操作文案
|
// 批量操作文案
|
||||||
'api_scenario.batch_operation.success': '成功{opt}至 {name}',
|
'api_scenario.batch_operation.success': '成功{opt}至 {name}',
|
||||||
'api_scenario.table.batchMoveConfirm': '{opt}{count}个场景至已选模块',
|
'api_scenario.table.batchMoveConfirm': '{opt}{count}个场景至已选模块',
|
||||||
|
|
Loading…
Reference in New Issue