fix(all): 修复bugs
This commit is contained in:
parent
b094ebf8eb
commit
2f5e5ada03
|
@ -431,7 +431,7 @@
|
|||
}
|
||||
}
|
||||
.arco-checkbox-indeterminate .arco-checkbox-icon {
|
||||
border-color: rgba(var(--primary-7));
|
||||
border: 1px solid rgba(var(--primary-7)) !important;
|
||||
background-color: rgba(var(--primary-1));
|
||||
&::after {
|
||||
background-color: rgb(var(--primary-7));
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
:read-only="props.disabled"
|
||||
:show-full-screen="false"
|
||||
:show-theme-change="false"
|
||||
@change="() => emit('change')"
|
||||
>
|
||||
<template #rightBox>
|
||||
<MsScriptMenu
|
||||
|
@ -99,6 +100,9 @@
|
|||
showHeader: true,
|
||||
}
|
||||
);
|
||||
const emit = defineEmits<{
|
||||
(e: 'change'): void;
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
v-if="attrs.selectorType === 'checkbox'"
|
||||
:total="attrs.showPagination ? (attrs.msPagination as MsPaginationI).total : (attrs.data as MsTableDataItem<TableData>[]).length"
|
||||
:selected-keys="props.selectedKeys"
|
||||
:selector-status="props.selectorStatus"
|
||||
:exclude-keys="[...props.excludeKeys]"
|
||||
:exclude-keys="Array.from(props.excludeKeys)"
|
||||
:current-data="attrs.data as Record<string,any>[]"
|
||||
:show-select-all="!!attrs.showPagination && props.showSelectorAll"
|
||||
:disabled="(attrs.data as []).length === 0"
|
||||
|
@ -785,3 +784,20 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.arco-table-filters-content {
|
||||
@apply overflow-hidden;
|
||||
|
||||
max-width: 300px;
|
||||
.arco-checkbox-group {
|
||||
@apply flex w-full flex-col;
|
||||
.arco-checkbox {
|
||||
@apply w-full;
|
||||
.arco-checkbox-label {
|
||||
@apply flex-1 overflow-hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MsIcon from '../ms-icon-font/index.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
|
@ -41,7 +41,6 @@
|
|||
currentData: MsTableDataItem<Record<string, any>>[];
|
||||
showSelectAll: boolean;
|
||||
disabled: boolean;
|
||||
selectorStatus: SelectAllEnum;
|
||||
excludeKeys: string[];
|
||||
}>(),
|
||||
{
|
||||
|
@ -52,32 +51,31 @@
|
|||
}
|
||||
);
|
||||
|
||||
const selectAllStatus = ref<SelectAllEnum>(SelectAllEnum.NONE);
|
||||
const checked = computed({
|
||||
get: () => {
|
||||
if (props.selectorStatus !== 'all') {
|
||||
return props.selectedKeys.size > 0 && props.selectedKeys.size === props.total;
|
||||
}
|
||||
if (props.selectorStatus === 'all') {
|
||||
return !props.excludeKeys?.length
|
||||
? true
|
||||
: props.selectedKeys.size > 0 && props.selectedKeys.size === props.total;
|
||||
}
|
||||
// 如果是选中所有页则是全选状态(选中所有页分两种情况:一是直接通过下拉选项选中所有页;二是当前已选的数量等于表格总数)
|
||||
return (
|
||||
selectAllStatus.value === SelectAllEnum.ALL ||
|
||||
(props.selectedKeys.size > 0 && props.selectedKeys.size === props.total)
|
||||
);
|
||||
},
|
||||
set: (value) => {
|
||||
return value;
|
||||
},
|
||||
});
|
||||
const indeterminate = computed(() => {
|
||||
// 已选中的数量大于 0 且小于总数时是半选状态
|
||||
if (props.selectorStatus === 'current') {
|
||||
return props.selectedKeys.size > 0 && props.selectedKeys.size < props.total;
|
||||
}
|
||||
if (props.selectorStatus === 'all') {
|
||||
return !props.excludeKeys?.length ? false : props.selectedKeys.size > 0 && props.selectedKeys.size < props.total;
|
||||
}
|
||||
// 有无勾选的 key,或非全选所有页且已选中的数量大于 0 且小于总数时是半选状态
|
||||
return (
|
||||
props.excludeKeys.length > 0 ||
|
||||
(selectAllStatus.value !== SelectAllEnum.ALL &&
|
||||
props.selectedKeys.size > 0 &&
|
||||
props.selectedKeys.size < props.total)
|
||||
);
|
||||
});
|
||||
|
||||
const handleSelect = (v: string | number | Record<string, any> | undefined) => {
|
||||
selectAllStatus.value = v as SelectAllEnum;
|
||||
emit('change', v as SelectAllEnum);
|
||||
};
|
||||
|
||||
|
|
|
@ -415,7 +415,13 @@ export default function useTableProps<T>(
|
|||
if (v === SelectAllEnum.NONE) {
|
||||
// 清空选中项
|
||||
resetSelector();
|
||||
} else {
|
||||
} else if (v === SelectAllEnum.CURRENT) {
|
||||
// 先清空选中项,再选中当前页面所有数据
|
||||
resetSelector();
|
||||
collectIds(data as MsTableDataItem<T>[], rowKey);
|
||||
} else if (v === SelectAllEnum.ALL) {
|
||||
// 全选所有页的时候先清空排除项,再选中所有数据
|
||||
propsRes.value.excludeKeys.clear();
|
||||
collectIds(data as MsTableDataItem<T>[], rowKey);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -151,6 +151,7 @@
|
|||
innerInputValue.value = '';
|
||||
tagsLength.value += 1;
|
||||
emit('update:modelValue', innerModelValue.value);
|
||||
emit('change', innerModelValue.value);
|
||||
}
|
||||
emit('blur');
|
||||
}
|
||||
|
|
|
@ -317,8 +317,8 @@ export interface LoopStepDetail extends StepDetailsCommon {
|
|||
}
|
||||
// 场景引用配置
|
||||
export interface ScenarioStepConfig {
|
||||
useCurrentScenarioParam: boolean; // 是否优先使用当前场景参数
|
||||
useBothScenarioParam: boolean; // 是否当前场景参数和源场景参数都应用(勾选非空值时为 true)
|
||||
useOriginScenarioParam: boolean; // 是否优先使用当前场景参数
|
||||
useOriginScenarioParamPreferential: boolean; // 是否当前场景参数和源场景参数都应用(勾选非空值时为 true)
|
||||
enableScenarioEnv: boolean; // 是否应用源场景环境
|
||||
}
|
||||
// 场景步骤详情
|
||||
|
@ -436,8 +436,7 @@ export interface ApiScenarioDebugRequest {
|
|||
reportId: string | number;
|
||||
steps: ScenarioStepItem[];
|
||||
projectId: string;
|
||||
uploadFileIds: string[];
|
||||
linkFileIds: string[];
|
||||
stepFileParam: Record<string, ScenarioStepFileParams>;
|
||||
frontendDebug?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
size="small"
|
||||
@press-enter="isShowEditScriptNameInput = false"
|
||||
@blur="isShowEditScriptNameInput = false"
|
||||
@change="() => emit('change')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center justify-between px-[12px] pt-[12px]">
|
||||
|
@ -195,6 +196,7 @@
|
|||
:disabled="props.disabled"
|
||||
show-type="commonScript"
|
||||
:show-header="false"
|
||||
@change="() => emit('change')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -230,6 +232,7 @@
|
|||
:columns="scriptColumns"
|
||||
:height-used="heightUsed"
|
||||
:selectable="false"
|
||||
@change="() => emit('change')"
|
||||
/>
|
||||
<MsCodeEditor
|
||||
v-else-if="commonScriptShowType === 'scriptContent' && condition.commonScriptInfo"
|
||||
|
@ -703,6 +706,7 @@ if (!result){
|
|||
};
|
||||
scriptParams.value = (condition.value.commonScriptInfo?.params as any[]) || [];
|
||||
showQuoteDrawer.value = false;
|
||||
Message.success(t('apiTestDebug.introduceSourceApplySuccess'));
|
||||
}
|
||||
|
||||
const showAddScriptDrawer = ref(false);
|
||||
|
|
|
@ -798,6 +798,16 @@
|
|||
// 如果是更改了下拉框导致添加新的一列,需要将更改后的下拉框的值应用到下一行(产品为了方便统一输入参数类型)
|
||||
if (key) {
|
||||
nextLine[key] = lastLineData[key];
|
||||
// 根据参数类型自动推断 Content-Type 类型!!!特殊处理,这里contentType会随前面的参数类型变化,这里也需要变化
|
||||
if (nextLine.contentType) {
|
||||
if (lastLineData[key] === 'file') {
|
||||
nextLine.contentType = RequestContentTypeEnum.OCTET_STREAM;
|
||||
} else if (lastLineData[key] === 'json') {
|
||||
nextLine.contentType = RequestContentTypeEnum.JSON;
|
||||
} else {
|
||||
nextLine.contentType = RequestContentTypeEnum.TEXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
paramsData.value.push(nextLine);
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
disabledParamValue?: boolean; // 参数值禁用
|
||||
disabledExceptParam?: boolean; // 除了可以修改参数值其他都禁用
|
||||
secondBoxHeight: number;
|
||||
isDrawer?: boolean;
|
||||
uploadTempFileApi?: (file: File) => Promise<any>; // 上传临时文件接口
|
||||
fileSaveAsSourceId?: string | number; // 文件转存关联的资源id
|
||||
fileSaveAsApi?: (params: TransferFileParams) => Promise<string>; // 文件转存接口
|
||||
|
@ -267,7 +268,8 @@
|
|||
watch(
|
||||
() => props.layout,
|
||||
(val) => {
|
||||
heightUsed.value = val === 'horizontal' ? 428 : 430 + props.secondBoxHeight;
|
||||
const otherHeight = props.isDrawer ? 328 : 430;
|
||||
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
@ -278,7 +280,7 @@
|
|||
() => props.secondBoxHeight,
|
||||
(val) => {
|
||||
if (props.layout === 'vertical') {
|
||||
heightUsed.value = 430 + val;
|
||||
heightUsed.value = (props.isDrawer ? 328 : 430) + val;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
disabledParamValue?: boolean; // 参数值禁用
|
||||
disabledExceptParam?: boolean; // 除了可以修改参数值其他都禁用
|
||||
typeTitle?: string;
|
||||
isDrawer?: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:selectedKeys', value: string[]): void;
|
||||
|
@ -83,9 +84,9 @@
|
|||
|
||||
const heightUsed = computed(() => {
|
||||
if (props.layout === 'horizontal') {
|
||||
return 428;
|
||||
return props.isDrawer ? 328 : 428;
|
||||
}
|
||||
return 428 + props.secondBoxHeight;
|
||||
return (props.isDrawer ? 328 : 428) + props.secondBoxHeight;
|
||||
});
|
||||
const scroll = computed(() => (props.layout === 'horizontal' ? { x: '700px' } : { x: '100%' }));
|
||||
|
||||
|
|
|
@ -548,10 +548,11 @@
|
|||
const isHttpProtocol = computed(() => requestVModel.value.protocol === 'HTTP');
|
||||
const temporaryResponseMap = {}; // 缓存websocket返回的报告内容,避免执行接口后切换tab导致报告丢失
|
||||
const isInitPluginForm = ref(false);
|
||||
const isSwitchingContent = ref(false); // 是否正在切换显示内容,防止因切换显示内容导致触发更改
|
||||
|
||||
function handleActiveDebugChange() {
|
||||
if (!loading.value || (!isHttpProtocol.value && isInitPluginForm.value)) {
|
||||
// 如果是因为加载详情触发的change则不需要标记为未保存;或者是插件协议的话需要等待表单初始化完毕
|
||||
if ((!isSwitchingContent.value && !loading.value) || (!isHttpProtocol.value && isInitPluginForm.value)) {
|
||||
// 如果是因为加载详情或切换显示内容触发的change则不需要标记为未保存;或者是插件协议的话需要等待表单初始化完毕
|
||||
requestVModel.value.unSaved = true;
|
||||
}
|
||||
}
|
||||
|
@ -1225,6 +1226,10 @@
|
|||
watch(
|
||||
() => requestVModel.value.id,
|
||||
async () => {
|
||||
isSwitchingContent.value = true; // 正在切换内容
|
||||
nextTick(() => {
|
||||
isSwitchingContent.value = false; // 切换内容结束
|
||||
});
|
||||
if (requestVModel.value.protocol !== 'HTTP') {
|
||||
requestVModel.value.activeTab = RequestComposition.PLUGIN;
|
||||
if (protocolOptions.value.length === 0) {
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
}
|
||||
// 接口场景
|
||||
if (props.isScenario) {
|
||||
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL];
|
||||
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL, RequestConditionProcessor.TIME_WAITING];
|
||||
}
|
||||
// 接口调试
|
||||
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.TIME_WAITING];
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
disabledParamValue?: boolean; // 参数值禁用
|
||||
disabledExceptParam?: boolean; // 除了可以修改参数值其他都禁用
|
||||
secondBoxHeight: number;
|
||||
isDrawer?: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:params', value: any[]): void;
|
||||
|
@ -122,7 +123,8 @@
|
|||
watch(
|
||||
() => props.layout,
|
||||
(val) => {
|
||||
heightUsed.value = val === 'horizontal' ? 428 : 428 + props.secondBoxHeight;
|
||||
const otherHeight = props.isDrawer ? 328 : 430;
|
||||
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
@ -133,7 +135,7 @@
|
|||
() => props.secondBoxHeight,
|
||||
(val) => {
|
||||
if (props.layout === 'vertical') {
|
||||
heightUsed.value = 428 + val;
|
||||
heightUsed.value = (props.isDrawer ? 328 : 430) + val;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class="flex items-center justify-between gap-[24px] text-[14px]"
|
||||
>
|
||||
<a-tooltip :content="props.requestResult.fakeErrorCode">
|
||||
<executeStatus :status="props.requestResult.status" size="small" class="ml-[4px]" />
|
||||
<executeStatus :status="finalStatus" size="small" class="ml-[4px]" />
|
||||
</a-tooltip>
|
||||
<a-popover position="left" content-class="response-popover-content">
|
||||
<div class="one-line-text max-w-[200px]" :style="{ color: statusCodeColor }">
|
||||
|
@ -52,6 +52,7 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import { RequestResult } from '@/models/apiTest/common';
|
||||
import { ScenarioExecuteStatus } from '@/enums/apiEnum';
|
||||
|
||||
const props = defineProps<{
|
||||
requestResult?: RequestResult;
|
||||
|
@ -99,6 +100,12 @@
|
|||
}
|
||||
return '';
|
||||
});
|
||||
const finalStatus = computed(() => {
|
||||
if (props.requestResult?.fakeErrorCode) {
|
||||
return ScenarioExecuteStatus.FAKE_ERROR;
|
||||
}
|
||||
return props.requestResult?.isSuccessful ? ScenarioExecuteStatus.SUCCESS : ScenarioExecuteStatus.FAILED;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
secondBoxHeight: number;
|
||||
disabledParamValue?: boolean; // 参数值禁用
|
||||
disabledExceptParam?: boolean; // 除了可以修改参数值其他都禁用
|
||||
isDrawer?: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:params', value: any[]): void;
|
||||
|
@ -123,7 +124,8 @@
|
|||
watch(
|
||||
() => props.layout,
|
||||
(val) => {
|
||||
heightUsed.value = val === 'horizontal' ? 428 : 428 + props.secondBoxHeight;
|
||||
const otherHeight = props.isDrawer ? 328 : 430;
|
||||
heightUsed.value = val === 'horizontal' ? otherHeight : otherHeight + props.secondBoxHeight;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
@ -134,7 +136,7 @@
|
|||
() => props.secondBoxHeight,
|
||||
(val) => {
|
||||
if (props.layout === 'vertical') {
|
||||
heightUsed.value = 428 + val;
|
||||
heightUsed.value = (props.isDrawer ? 328 : 430) + val;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { cloneDeep, isEqual } from 'lodash-es';
|
||||
|
||||
import { RequestParam } from './requestComposition/index.vue';
|
||||
|
||||
import { ExecuteBody } from '@/models/apiTest/common';
|
||||
import { RequestParamsType } from '@/enums/apiEnum';
|
||||
|
||||
|
@ -11,6 +9,7 @@ import {
|
|||
defaultKeyValueParamItem,
|
||||
defaultRequestParamsItem,
|
||||
} from './config';
|
||||
import type { RequestParam } from './requestComposition/index.vue';
|
||||
|
||||
export interface ParseResult {
|
||||
uploadFileIds: string[];
|
||||
|
|
|
@ -348,7 +348,6 @@
|
|||
sortDefinition,
|
||||
updateDefinition,
|
||||
} from '@/api/modules/api-test/management';
|
||||
import { getProjectOptions } from '@/api/modules/project-management/projectMember';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import useTableStore from '@/hooks/useTableStore';
|
||||
|
|
|
@ -23,13 +23,31 @@
|
|||
v-if="props.step && [ScenarioStepType.API, ScenarioStepType.CUSTOM_REQUEST].includes(props.step?.stepType)"
|
||||
:step="props.step"
|
||||
/>
|
||||
<a-tooltip :content="title" position="bottom">
|
||||
<a-tooltip v-if="!isShowEditStepNameInput" :content="title" position="bottom">
|
||||
<div class="flex items-center gap-[4px]">
|
||||
<div class="one-line-text">
|
||||
{{ title }}
|
||||
</div>
|
||||
<MsIcon
|
||||
type="icon-icon_edit_outlined"
|
||||
class="cursor-pointer hover:text-[rgb(var(--primary-5))]"
|
||||
@click="isShowEditStepNameInput = true"
|
||||
/>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="ml-auto flex items-center gap-[16px]">
|
||||
<a-input
|
||||
v-if="isShowEditStepNameInput"
|
||||
ref="stepNameInputRef"
|
||||
v-model:model-value="requestVModel.name"
|
||||
class="flex-1"
|
||||
:placeholder="t('apiScenario.pleaseInputStepName')"
|
||||
:max-length="255"
|
||||
show-word-limit
|
||||
@press-enter="updateStepName"
|
||||
@blur="updateStepName"
|
||||
/>
|
||||
<div v-show="!isShowEditStepNameInput" class="ml-auto flex items-center gap-[16px]">
|
||||
<div
|
||||
v-if="!props.step || props.step?.stepType === ScenarioStepType.CUSTOM_REQUEST"
|
||||
class="customApiDrawer-title-right flex items-center gap-[16px]"
|
||||
|
@ -184,7 +202,7 @@
|
|||
class="no-content relative mt-[8px] border-b"
|
||||
/>
|
||||
</div>
|
||||
<div ref="splitContainerRef" class="h-[calc(100%-87px)]">
|
||||
<div ref="splitContainerRef" class="h-[calc(100%-97px)]">
|
||||
<MsSplitBox
|
||||
ref="verticalSplitBoxRef"
|
||||
v-model:size="splitBoxSize"
|
||||
|
@ -228,6 +246,7 @@
|
|||
:disabled-except-param="!isEditableApi"
|
||||
:layout="activeLayout"
|
||||
:second-box-height="secondBoxHeight"
|
||||
is-drawer
|
||||
@change="handleActiveDebugChange"
|
||||
/>
|
||||
<httpBody
|
||||
|
@ -241,6 +260,7 @@
|
|||
:file-save-as-source-id="scenarioId"
|
||||
:file-save-as-api="transferFile"
|
||||
:file-module-options-api="getTransferOptions"
|
||||
is-drawer
|
||||
@change="handleActiveDebugChange"
|
||||
/>
|
||||
<httpQuery
|
||||
|
@ -250,6 +270,7 @@
|
|||
:disabled-param-value="!isEditableApi && !isEditableParamValue"
|
||||
:disabled-except-param="!isEditableApi"
|
||||
:second-box-height="secondBoxHeight"
|
||||
is-drawer
|
||||
@change="handleActiveDebugChange"
|
||||
/>
|
||||
<httpRest
|
||||
|
@ -259,6 +280,7 @@
|
|||
:disabled-param-value="!isEditableApi && !isEditableParamValue"
|
||||
:disabled-except-param="!isEditableApi"
|
||||
:second-box-height="secondBoxHeight"
|
||||
is-drawer
|
||||
@change="handleActiveDebugChange"
|
||||
/>
|
||||
<precondition
|
||||
|
@ -542,9 +564,9 @@
|
|||
_stepType.value.isQuoteApi ||
|
||||
props.step?.stepType === ScenarioStepType.CUSTOM_REQUEST
|
||||
) {
|
||||
return props.step?.name;
|
||||
return requestVModel.value.name || props.step?.name;
|
||||
}
|
||||
return t('apiScenario.customApi');
|
||||
return requestVModel.value.name || t('apiScenario.customApi');
|
||||
});
|
||||
// 是否显示环境域名前缀
|
||||
const showEnvPrefix = computed(
|
||||
|
@ -589,16 +611,22 @@
|
|||
const isEditableParamValue = computed(() => !props.step?.isQuoteScenarioStep && _stepType.value.isQuoteApi);
|
||||
// 是否是 HTTP 协议
|
||||
const isHttpProtocol = computed(() => requestVModel.value.protocol === 'HTTP');
|
||||
|
||||
const isInitPluginForm = ref(false);
|
||||
const isSwitchingContent = ref(false); // 是否正在切换请求内容,当传入的详情数据变化时记录,避免触发未保存
|
||||
|
||||
function handleActiveDebugChange() {
|
||||
if (!loading.value || (!isHttpProtocol.value && isInitPluginForm.value)) {
|
||||
if ((!isSwitchingContent.value && !loading.value) || (!isHttpProtocol.value && isInitPluginForm.value)) {
|
||||
// 如果是因为加载详情触发的change则不需要标记为未保存;或者是插件协议的话需要等待表单初始化完毕
|
||||
requestVModel.value.unSaved = true;
|
||||
}
|
||||
}
|
||||
|
||||
const isShowEditStepNameInput = ref(false);
|
||||
|
||||
function updateStepName() {
|
||||
isShowEditStepNameInput.value = false;
|
||||
}
|
||||
|
||||
// 请求内容公共tabKey
|
||||
const commonContentTabKey = [
|
||||
RequestComposition.PRECONDITION,
|
||||
|
@ -1159,6 +1187,16 @@
|
|||
emit('replace', newStep);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.request?.stepId,
|
||||
() => {
|
||||
isSwitchingContent.value = true;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
async (val) => {
|
||||
|
@ -1194,6 +1232,9 @@
|
|||
});
|
||||
}
|
||||
requestVModel.value.activeTab = contentTabList.value[0].value;
|
||||
nextTick(() => {
|
||||
isSwitchingContent.value = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -32,7 +32,11 @@
|
|||
<a-tooltip :content="activeStep?.name">
|
||||
<div class="one-line-text max-w-[300px]"> {{ characterLimit(activeStep?.name) }}</div>
|
||||
</a-tooltip>
|
||||
<MsIcon type="icon-icon_edit_outlined" class="edit-script-name-icon" @click="showEditScriptNameInput" />
|
||||
<MsIcon
|
||||
type="icon-icon_edit_outlined"
|
||||
class="cursor-pointer hover:text-[rgb(var(--primary-5))]"
|
||||
@click="showEditScriptNameInput"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="activeStep && !activeStep.isQuoteScenarioStep && activeStep.resourceId"
|
||||
|
@ -117,7 +121,7 @@
|
|||
class="relative mt-[8px] border-b"
|
||||
/>
|
||||
</div>
|
||||
<div ref="splitContainerRef" class="h-[calc(100%-87px)]">
|
||||
<div ref="splitContainerRef" class="h-[calc(100%-97px)]">
|
||||
<MsSplitBox
|
||||
ref="verticalSplitBoxRef"
|
||||
v-model:size="splitBoxSize"
|
||||
|
@ -466,6 +470,7 @@
|
|||
const isEditableApi = computed(() => !activeStep.value?.isQuoteScenarioStep && _stepType.value.isCopyCase);
|
||||
const isHttpProtocol = computed(() => requestVModel.value.protocol === 'HTTP');
|
||||
const isInitPluginForm = ref(false);
|
||||
const isSwitchingContent = ref(false); // 是否正在切换请求内容,当传入的详情数据变化时记录,避免触发未保存
|
||||
const loading = ref(false);
|
||||
|
||||
function handleActiveDebugChange() {
|
||||
|
@ -991,6 +996,16 @@
|
|||
emit('replace', newStep);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.request?.stepId,
|
||||
() => {
|
||||
isSwitchingContent.value = true;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
async (val) => {
|
||||
|
@ -1010,6 +1025,9 @@
|
|||
await initQuoteCaseDetail();
|
||||
}
|
||||
handleActiveDebugProtocolChange(requestVModel.value.protocol);
|
||||
nextTick(() => {
|
||||
isSwitchingContent.value = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -24,7 +24,13 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-[10px] flex flex-1 gap-[8px]">
|
||||
<conditionContent v-if="visible" v-model:data="activeItem" :disabled="isReadonly" :is-build-in="true" />
|
||||
<conditionContent
|
||||
v-if="visible"
|
||||
v-model:data="activeItem"
|
||||
:disabled="isReadonly"
|
||||
:is-build-in="true"
|
||||
@change="unSaved = true"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="currentResponse?.console" class="p-[8px]">
|
||||
<div class="mb-[8px] font-medium text-[var(--color-text-1)]">{{ t('apiScenario.executionResult') }}</div>
|
||||
|
@ -72,7 +78,7 @@
|
|||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'add', name: string, scriptProcessor: ExecuteConditionProcessor): void;
|
||||
(e: 'save', name: string, scriptProcessor: ExecuteConditionProcessor): void;
|
||||
(e: 'save', name: string, scriptProcessor: ExecuteConditionProcessor, unSaved: boolean): void;
|
||||
}>();
|
||||
|
||||
const defaultScript = {
|
||||
|
@ -90,6 +96,7 @@
|
|||
|
||||
const visible = defineModel<boolean>('visible', { required: true });
|
||||
const isReadonly = computed(() => props.step?.isQuoteScenarioStep);
|
||||
const unSaved = ref(false);
|
||||
const currentLoop = ref(1);
|
||||
const currentResponse = computed(() => {
|
||||
if (props.step?.uniqueId) {
|
||||
|
@ -131,7 +138,7 @@
|
|||
|
||||
function handleClose() {
|
||||
if (props.detail) {
|
||||
emit('save', scriptName.value, activeItem.value);
|
||||
emit('save', scriptName.value, activeItem.value, unSaved.value);
|
||||
}
|
||||
scriptName.value = '';
|
||||
activeItem.value = defaultScript as unknown as ExecuteConditionProcessor;
|
||||
|
|
|
@ -54,8 +54,8 @@ export const defaultTimeController = {
|
|||
// 场景配置
|
||||
export const defaultScenarioStepConfig: ScenarioStepConfig = {
|
||||
enableScenarioEnv: false,
|
||||
useBothScenarioParam: false,
|
||||
useCurrentScenarioParam: true,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
};
|
||||
|
||||
export const defaultStepItemCommon = {
|
||||
|
|
|
@ -27,40 +27,6 @@
|
|||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div style="font-weight: bold">
|
||||
{{ t('apiScenario.setting.run.config') }}
|
||||
</div>
|
||||
<div class="mb-[16px] mt-[10px] flex items-center gap-[8px]">
|
||||
<a-switch v-model:model-value="form.enableStepWait" type="line" size="small" @change="emit('change')" />
|
||||
{{ t('apiScenario.setting.step.waitTime') }}
|
||||
<a-tooltip :content="t('apiScenario.setting.waitTime.tip')">
|
||||
<div>
|
||||
<MsIcon
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
type="icon-icon-maybe_outlined"
|
||||
/>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
<a-form-item v-if="form.stepWaitTime !== null || form.stepWaitTime !== undefined" class="flex-1">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
{{ t('apiScenario.setting.waitTime') }}
|
||||
<div class="text-[var(--color-text-brand)]">(ms)</div>
|
||||
</div>
|
||||
</template>
|
||||
<a-input-number
|
||||
v-model:model-value="form.stepWaitTime"
|
||||
mode="button"
|
||||
:step="100"
|
||||
:min="0"
|
||||
:max="600000"
|
||||
model-event="input"
|
||||
class="w-[160px]"
|
||||
@blur="handleInputChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item class="flex-1">
|
||||
<template #label>
|
||||
|
|
|
@ -317,35 +317,49 @@
|
|||
<a-radio :value="ScenarioStepRefType.PARTIAL_REF">{{ t('apiScenario.stepQuote') }}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('apiScenario.runRule')">
|
||||
<a-radio-group v-model:model-value="scenarioConfigForm.useCurrentScenarioParam" type="button">
|
||||
<a-radio :value="true">{{ t('apiScenario.currentScenario') }}</a-radio>
|
||||
<a-radio :value="false">{{ t('apiScenario.sourceScenario') }}</a-radio>
|
||||
</a-radio-group>
|
||||
<a-form-item label="" class="hidden-item">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-switch
|
||||
v-model:model-value="scenarioConfigForm.useOriginScenarioParam"
|
||||
class="ml-[6px]"
|
||||
size="small"
|
||||
></a-switch>
|
||||
{{ t('apiScenario.sourceScenarioParams') }}
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="
|
||||
scenarioConfigForm.useCurrentScenarioParam
|
||||
? t('apiScenario.currentScenarioTip')
|
||||
: t('apiScenario.sourceScenarioTip')
|
||||
"
|
||||
>
|
||||
<a-radio-group v-model:model-value="scenarioConfigForm.useBothScenarioParam">
|
||||
<a-radio :value="false">{{ t('apiScenario.empty') }}</a-radio>
|
||||
<a-form-item v-show="scenarioConfigForm.useOriginScenarioParam" class="hidden-item">
|
||||
<a-radio-group v-model:model-value="scenarioConfigForm.useOriginScenarioParamPreferential" type="button">
|
||||
<a-radio :value="true">
|
||||
{{
|
||||
t(
|
||||
scenarioConfigForm.useCurrentScenarioParam
|
||||
? 'apiScenario.sourceScenarioParams'
|
||||
: 'apiScenario.currentScenarioParams'
|
||||
)
|
||||
}}
|
||||
<div class="flex items-center gap-[4px]">
|
||||
{{ t('apiScenario.sourceScenario') }}
|
||||
<a-tooltip :content="t('apiScenario.sourceScenarioTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-radio>
|
||||
<a-radio :value="false">
|
||||
<div class="flex items-center gap-[4px]">
|
||||
{{ t('apiScenario.currentScenario') }}
|
||||
<a-tooltip :content="t('apiScenario.currentScenarioTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="" class="hidden-item !mb-0">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-checkbox v-model:model-value="scenarioConfigForm.enableScenarioEnv" class="ml-[6px]"></a-checkbox>
|
||||
<a-switch
|
||||
v-model:model-value="scenarioConfigForm.enableScenarioEnv"
|
||||
class="ml-[6px]"
|
||||
size="small"
|
||||
></a-switch>
|
||||
<div class="flex items-center gap-[4px]">
|
||||
{{ t('apiScenario.sourceScenarioEnv') }}
|
||||
<a-tooltip :content="t('apiScenario.sourceScenarioEnvTip')" position="right">
|
||||
|
@ -760,70 +774,70 @@
|
|||
>({
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useBothScenarioParam: false,
|
||||
useCurrentScenarioParam: true,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
});
|
||||
const showScenarioConfig = ref(false);
|
||||
const scenarioConfigParamTip = computed(() => {
|
||||
if (
|
||||
scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
!scenarioConfigForm.value.useBothScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-空值
|
||||
return t('apiScenario.currentScenarioAndNull');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
!scenarioConfigForm.value.useBothScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-空值-且选择源场景环境
|
||||
return t('apiScenario.currentScenarioAndNullAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
scenarioConfigForm.value.useBothScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-原场景参数
|
||||
return t('apiScenario.currentScenarioAndSourceScenario');
|
||||
}
|
||||
if (
|
||||
scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
scenarioConfigForm.value.useBothScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用当前场景参数-原场景参数-且选择源场景环境
|
||||
return t('apiScenario.currentScenarioAndSourceScenarioAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
!scenarioConfigForm.value.useBothScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-空值
|
||||
return t('apiScenario.sourceScenarioAndNull');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
!scenarioConfigForm.value.useBothScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-空值-且选择源场景环境
|
||||
return t('apiScenario.sourceScenarioAndNullAndSourceEnv');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
scenarioConfigForm.value.useBothScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
!scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-当前场景参数
|
||||
return t('apiScenario.sourceScenarioAndCurrentScenario');
|
||||
}
|
||||
if (
|
||||
!scenarioConfigForm.value.useCurrentScenarioParam &&
|
||||
scenarioConfigForm.value.useBothScenarioParam &&
|
||||
!scenarioConfigForm.value.useOriginScenarioParam &&
|
||||
scenarioConfigForm.value.useOriginScenarioParamPreferential &&
|
||||
scenarioConfigForm.value.enableScenarioEnv
|
||||
) {
|
||||
// 使用原场景参数-当前场景参数-且选择源场景环境
|
||||
|
@ -837,8 +851,8 @@
|
|||
scenarioConfigForm.value = {
|
||||
refType: ScenarioStepRefType.REF,
|
||||
enableScenarioEnv: false,
|
||||
useBothScenarioParam: false,
|
||||
useCurrentScenarioParam: true,
|
||||
useOriginScenarioParamPreferential: true,
|
||||
useOriginScenarioParam: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1382,10 +1396,7 @@
|
|||
}
|
||||
|
||||
async function realExecute(
|
||||
executeParams: Pick<
|
||||
ApiScenarioDebugRequest,
|
||||
'steps' | 'stepDetails' | 'reportId' | 'uploadFileIds' | 'linkFileIds'
|
||||
>,
|
||||
executeParams: Pick<ApiScenarioDebugRequest, 'steps' | 'stepDetails' | 'reportId' | 'stepFileParam'>,
|
||||
executeType?: 'localExec' | 'serverExec'
|
||||
) {
|
||||
const [currentStep] = executeParams.steps;
|
||||
|
@ -1455,8 +1466,9 @@
|
|||
steps: [realStep as ScenarioStepItem],
|
||||
stepDetails: _stepDetails,
|
||||
reportId: realStep.reportId,
|
||||
uploadFileIds: stepFileParam?.uploadFileIds || [],
|
||||
linkFileIds: stepFileParam?.linkFileIds || [],
|
||||
stepFileParam: {
|
||||
[realStep.id]: stepFileParam,
|
||||
},
|
||||
},
|
||||
isPriorityLocalExec?.value ? 'localExec' : 'serverExec'
|
||||
);
|
||||
|
@ -1474,6 +1486,7 @@
|
|||
delete scenario.value.stepResponses[realStep.uniqueId]; // 先移除上一次的执行结果
|
||||
realStep.reportId = getGenerateId();
|
||||
realStep.executeStatus = ScenarioExecuteStatus.EXECUTING;
|
||||
const stepFileParam = scenario.value.stepFileParam[realStep.id];
|
||||
request.executeLoading = true;
|
||||
realExecute(
|
||||
{
|
||||
|
@ -1482,15 +1495,15 @@
|
|||
[realStep.id]: request,
|
||||
},
|
||||
reportId: realStep.reportId,
|
||||
uploadFileIds: request.uploadFileIds || [],
|
||||
linkFileIds: request.linkFileIds || [],
|
||||
stepFileParam: {
|
||||
[realStep.uniqueId]: stepFileParam,
|
||||
},
|
||||
},
|
||||
executeType
|
||||
);
|
||||
} else {
|
||||
// 步骤列表找不到该步骤,说明是新建的自定义请求还未保存,则临时创建一个步骤进行调试(不保存步骤信息)
|
||||
const reportId = getGenerateId();
|
||||
delete scenario.value.stepResponses[request.stepId]; // 先移除上一次的执行结果
|
||||
request.executeLoading = true;
|
||||
activeStep.value = {
|
||||
id: request.stepId,
|
||||
|
@ -1513,9 +1526,13 @@
|
|||
[request.stepId]: request,
|
||||
},
|
||||
reportId,
|
||||
stepFileParam: {
|
||||
[request.stepId]: {
|
||||
uploadFileIds: request.uploadFileIds || [],
|
||||
linkFileIds: request.linkFileIds || [],
|
||||
},
|
||||
},
|
||||
},
|
||||
executeType
|
||||
);
|
||||
}
|
||||
|
@ -1668,7 +1685,7 @@
|
|||
handleCreateStep(
|
||||
{
|
||||
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
||||
name: t('apiScenario.customApi'),
|
||||
name: request.name || t('apiScenario.customApi'),
|
||||
config: {
|
||||
protocol: request.protocol,
|
||||
method: request.method,
|
||||
|
@ -1694,7 +1711,7 @@
|
|||
sort: steps.value.length + 1,
|
||||
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
||||
refType: ScenarioStepRefType.DIRECT,
|
||||
name: t('apiScenario.customApi'),
|
||||
name: request.name || t('apiScenario.customApi'),
|
||||
projectId: appStore.currentProjectId,
|
||||
});
|
||||
}
|
||||
|
@ -1731,6 +1748,7 @@
|
|||
...activeStep.value.config,
|
||||
method: request.method,
|
||||
};
|
||||
activeStep.value.name = request.name;
|
||||
emit('updateResource', request.uploadFileIds, request.linkFileIds);
|
||||
activeStep.value = undefined;
|
||||
}
|
||||
|
@ -1788,11 +1806,14 @@
|
|||
scenario.value.unSaved = true;
|
||||
}
|
||||
|
||||
function saveScriptStep(name: string, scriptProcessor: ExecuteConditionProcessor) {
|
||||
function saveScriptStep(name: string, scriptProcessor: ExecuteConditionProcessor, unSaved = false) {
|
||||
if (activeStep.value) {
|
||||
stepDetails.value[activeStep.value.id] = cloneDeep(scriptProcessor);
|
||||
activeStep.value.name = name;
|
||||
activeStep.value = undefined;
|
||||
if (unSaved) {
|
||||
scenario.value.unSaved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
:scenario="scenario as ScenarioDetail"
|
||||
:module-tree="props.moduleTree"
|
||||
class="w-[30%]"
|
||||
@change="scenario.unSaved = true"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
|
|
|
@ -256,9 +256,8 @@
|
|||
environmentId: currentEnvConfig.value?.id || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
uploadFileIds: activeScenarioTab.value.uploadFileIds,
|
||||
linkFileIds: activeScenarioTab.value.linkFileIds,
|
||||
...executeParams,
|
||||
stepFileParam: activeScenarioTab.value.stepFileParam,
|
||||
steps: mapTree(executeParams.steps, (node) => {
|
||||
return {
|
||||
...node,
|
||||
|
@ -274,8 +273,7 @@
|
|||
environmentId: currentEnvConfig.value?.id || '',
|
||||
projectId: appStore.currentProjectId,
|
||||
scenarioConfig: activeScenarioTab.value.scenarioConfig,
|
||||
uploadFileIds: activeScenarioTab.value.uploadFileIds,
|
||||
linkFileIds: activeScenarioTab.value.linkFileIds,
|
||||
stepFileParam: activeScenarioTab.value.stepFileParam,
|
||||
frontendDebug: executeType === 'localExec',
|
||||
...executeParams,
|
||||
steps: mapTree(executeParams.steps, (node) => {
|
||||
|
|
|
@ -167,7 +167,7 @@ export default {
|
|||
'apiScenario.empty': 'Empty Value',
|
||||
'apiScenario.currentScenarioParams': 'Current Scenario Parameters',
|
||||
'apiScenario.sourceScenarioParams': 'Source Scenario Parameters',
|
||||
'apiScenario.sourceScenarioEnv': 'Source Scenario Environment',
|
||||
'apiScenario.sourceScenarioEnv': 'Use source Scenario Environment',
|
||||
'apiScenario.valuePriority': 'Value Priority:',
|
||||
'apiScenario.currentScenarioAndNull':
|
||||
'Current Step Parameters > Current Scenario Parameters > Current Environment Parameters > Empty Value',
|
||||
|
|
|
@ -160,12 +160,12 @@ export default {
|
|||
'apiScenario.runRule': '参数取值规则',
|
||||
'apiScenario.currentScenario': '优先当前场景参数',
|
||||
'apiScenario.sourceScenario': '优先原场景参数',
|
||||
'apiScenario.currentScenarioTip': '当前场景参数不存在时,取',
|
||||
'apiScenario.sourceScenarioTip': '原场景参数不存在时,取',
|
||||
'apiScenario.sourceScenarioTip': '优先使用原场景参数,没有则取当前场景参数',
|
||||
'apiScenario.currentScenarioTip': '优先使用当前场景参数,没有则取原场景参数',
|
||||
'apiScenario.empty': '空值',
|
||||
'apiScenario.currentScenarioParams': '当前场景参数',
|
||||
'apiScenario.sourceScenarioParams': '原场景参数',
|
||||
'apiScenario.sourceScenarioEnv': '原场景环境',
|
||||
'apiScenario.sourceScenarioParams': '使用原场景参数',
|
||||
'apiScenario.sourceScenarioEnv': '使用原场景环境',
|
||||
'apiScenario.valuePriority': '取值优先级:',
|
||||
'apiScenario.currentScenarioAndNull': '当前步骤参数 > 当前场景参数 > 当前环境参数 > 空值',
|
||||
'apiScenario.currentScenarioAndNullAndSourceEnv': '当前步骤参数 > 当前场景参数 > 原环境参数 > 空值',
|
||||
|
@ -177,7 +177,7 @@ export default {
|
|||
'apiScenario.sourceScenarioAndCurrentScenarioAndSourceEnv': '原场景参数 > 原环境参数 > 当前步骤参数 > 当前场景参数',
|
||||
'apiScenario.fullQuoteTip': '完全引用:跟随原步骤内容及步骤状态变化,步骤状态不可调整',
|
||||
'apiScenario.stepQuoteTip': '步骤引用:仅跟随原步骤内容变化,步骤状态可调整',
|
||||
'apiScenario.sourceScenarioEnvTip': '运行环境,含环境参数',
|
||||
'apiScenario.sourceScenarioEnvTip': '使用原场景运行环境,包含环境参数',
|
||||
'apiScenario.setSuccess': '设置成功',
|
||||
'apiScenario.pleaseInputUrl': '请输入 url',
|
||||
'apiScenario.syncSaveAsCase': '同步添加测试接口用例',
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
<template>
|
||||
<a-trigger v-model:popup-visible="innerVisible" trigger="click" @popup-visible-change="handleFilterHidden">
|
||||
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click.stop="innerVisible = true">
|
||||
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" size="small" @click.stop="innerVisible = true">
|
||||
<div class="font-medium">
|
||||
{{ t(props.title) }}
|
||||
</div>
|
||||
<icon-down :class="innerVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<div class="arco-table-filters-content max-w-[400px]">
|
||||
<div class="ml-[6px] flex items-center justify-start px-[6px] py-[2px]">
|
||||
<div class="arco-table-filters-content">
|
||||
<div class="ml-[6px] flex w-full items-center justify-start overflow-hidden px-[6px] py-[2px]">
|
||||
<a-checkbox-group v-model:model-value="innerStatusFilters" direction="vertical" size="small">
|
||||
<a-checkbox
|
||||
v-for="(item, index) of props.list"
|
||||
:key="item[props.valueKey || 'value']"
|
||||
:value="item[props.valueKey || 'value']"
|
||||
>
|
||||
<div class="one-line-text max-w-[300px]">
|
||||
<a-tooltip :content="item[props.labelKey || 'text']" :mouse-enter-delay="300">
|
||||
<div class="one-line-text">
|
||||
<slot name="item" :item="item" :index="index"></slot>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
@ -41,12 +43,17 @@
|
|||
|
||||
const { t } = useI18n();
|
||||
|
||||
export interface FilterListItem {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
title: string;
|
||||
statusFilters: string[];
|
||||
list: any[];
|
||||
list: FilterListItem[];
|
||||
valueKey?: string;
|
||||
labelKey?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
Loading…
Reference in New Issue