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