fix(接口测试): csv/mock 功能 bug 修复
This commit is contained in:
parent
fa0fdb1ee4
commit
7afaa42513
|
@ -27,7 +27,7 @@
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
@click.stop="handleExpand(_props)"
|
@click.stop="handleExpand(_props)"
|
||||||
>
|
>
|
||||||
<icon-caret-down v-if="_props.expanded" class="text-[var(--color-text-4)]" />
|
<icon-caret-down v-if="_props.expanded || props.expandAll" class="text-[var(--color-text-4)]" />
|
||||||
<icon-caret-right v-else class="text-[var(--color-text-4)]" />
|
<icon-caret-right v-else class="text-[var(--color-text-4)]" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="h-full w-[16px]"></div>
|
<div v-else class="h-full w-[16px]"></div>
|
||||||
|
@ -98,6 +98,7 @@
|
||||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
|
||||||
import useContainerShadow from '@/hooks/useContainerShadow';
|
import useContainerShadow from '@/hooks/useContainerShadow';
|
||||||
|
import { mapTree } from '@/utils';
|
||||||
|
|
||||||
import type { MsTreeExpandedData, MsTreeFieldNames, MsTreeNodeData, MsTreeSelectedData } from './types';
|
import type { MsTreeExpandedData, MsTreeFieldNames, MsTreeNodeData, MsTreeSelectedData } from './types';
|
||||||
import { VirtualListProps } from '@arco-design/web-vue/es/_components/virtual-list-v2/interface';
|
import { VirtualListProps } from '@arco-design/web-vue/es/_components/virtual-list-v2/interface';
|
||||||
|
@ -190,12 +191,17 @@
|
||||||
overHeight: 32,
|
overHeight: 32,
|
||||||
containerClassName: 'ms-tree-container',
|
containerClassName: 'ms-tree-container',
|
||||||
});
|
});
|
||||||
|
const filterTreeData = ref<MsTreeNodeData[]>([]); // 初始化时全量的树数据或在非搜索情况下更新后的全量树数据
|
||||||
|
|
||||||
function init(isFirstInit = false) {
|
function init(isFirstInit = false) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (isFirstInit) {
|
if (isFirstInit) {
|
||||||
if (props.defaultExpandAll) {
|
if (props.defaultExpandAll) {
|
||||||
treeRef.value?.expandAll(true);
|
treeRef.value?.expandAll(true);
|
||||||
|
filterTreeData.value = mapTree(filterTreeData.value, (node) => {
|
||||||
|
node.expanded = true;
|
||||||
|
return node;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!isInitListener.value && treeRef.value) {
|
if (!isInitListener.value && treeRef.value) {
|
||||||
setContainer(
|
setContainer(
|
||||||
|
@ -240,8 +246,6 @@
|
||||||
return search(data.value);
|
return search(data.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterTreeData = ref<MsTreeNodeData[]>([]); // 初始化时全量的树数据或在非搜索情况下更新后的全量树数据
|
|
||||||
|
|
||||||
// 防抖搜索
|
// 防抖搜索
|
||||||
const updateDebouncedSearch = debounce(() => {
|
const updateDebouncedSearch = debounce(() => {
|
||||||
if (props.keyword) {
|
if (props.keyword) {
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ms-detail-card">
|
<div class="ms-detail-card">
|
||||||
<div class="ms-detail-card-title flex items-center justify-between">
|
<div class="ms-detail-card-title">
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex flex-1 items-center gap-[8px]">
|
||||||
<a-tooltip :content="t(props.title)">
|
<a-tooltip :content="t(props.title)">
|
||||||
<div class="one-line-text flex-1 font-medium text-[var(--color-text-1)]">
|
<div class="one-line-text max-w-[300px] flex-1 font-medium text-[var(--color-text-1)]">
|
||||||
{{ t(props.title) }}
|
{{ t(props.title) }}
|
||||||
</div>
|
</div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<slot name="titleAppend"></slot>
|
<slot name="titleAppend"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$slots.titleRight" class="flex items-center">
|
<div v-if="$slots.titleRight" class="flex items-center overflow-hidden">
|
||||||
<slot name="titleRight"></slot>
|
<slot name="titleRight"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -104,8 +104,10 @@
|
||||||
border-radius: var(--border-radius-small);
|
border-radius: var(--border-radius-small);
|
||||||
background-color: var(--color-text-n9);
|
background-color: var(--color-text-n9);
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
.one-line-text {
|
.ms-detail-card-title {
|
||||||
max-width: 300px;
|
@apply flex items-center justify-between overflow-hidden;
|
||||||
|
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
.ms-detail-card-desc {
|
.ms-detail-card-desc {
|
||||||
@apply flex flex-wrap overflow-hidden; // TODO:过渡动画
|
@apply flex flex-wrap overflow-hidden; // TODO:过渡动画
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template #typeTitle="{ columnConfig }">
|
<template #typeTitle="{ columnConfig }">
|
||||||
<div class="flex items-center text-[var(--color-text-3)]">
|
<div class="flex items-center text-[var(--color-text-3)]">
|
||||||
{{ t('apiTestDebug.paramType') }}
|
{{ t((columnConfig.title as string) || 'apiTestDebug.paramType') }}
|
||||||
<a-tooltip :disabled="!columnConfig.typeTitleTooltip" position="right">
|
<a-tooltip :disabled="!columnConfig.typeTitleTooltip" position="right">
|
||||||
<template #content>
|
<template #content>
|
||||||
<template v-if="Array.isArray(columnConfig.typeTitleTooltip)">
|
<template v-if="Array.isArray(columnConfig.typeTitleTooltip)">
|
||||||
|
@ -299,7 +299,6 @@
|
||||||
input-size="small"
|
input-size="small"
|
||||||
tag-size="small"
|
tag-size="small"
|
||||||
@change="(files, file) => handleFileChange(files, record, rowIndex, file)"
|
@change="(files, file) => handleFileChange(files, record, rowIndex, file)"
|
||||||
@delete-file="() => handleSingleFileDelete(record)"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<!-- 长度范围 -->
|
<!-- 长度范围 -->
|
||||||
|
@ -1028,6 +1027,18 @@
|
||||||
fileName: files[0].originalName || '',
|
fileName: files[0].originalName || '',
|
||||||
fileAlias: files[0].name || '',
|
fileAlias: files[0].name || '',
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
paramsData.value.forEach((e) => {
|
||||||
|
if (e.id === record.id) {
|
||||||
|
e.file = {
|
||||||
|
fileId: '',
|
||||||
|
fileName: '',
|
||||||
|
fileAlias: '',
|
||||||
|
local: false,
|
||||||
|
delete: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
addTableLine(rowIndex);
|
addTableLine(rowIndex);
|
||||||
emitChange('handleFileChange');
|
emitChange('handleFileChange');
|
||||||
|
@ -1039,17 +1050,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSingleFileDelete(record: Record<string, any>) {
|
|
||||||
record.file = {
|
|
||||||
fileId: '',
|
|
||||||
fileName: '',
|
|
||||||
fileAlias: '',
|
|
||||||
local: false,
|
|
||||||
delete: false,
|
|
||||||
};
|
|
||||||
emitChange('deleteFile');
|
|
||||||
}
|
|
||||||
|
|
||||||
const showQuickInputParam = ref(false);
|
const showQuickInputParam = ref(false);
|
||||||
const activeQuickInputRecord = ref<any>({});
|
const activeQuickInputRecord = ref<any>({});
|
||||||
const quickInputParamValue = ref('');
|
const quickInputParamValue = ref('');
|
||||||
|
|
|
@ -45,15 +45,15 @@
|
||||||
class="mb-[16px]"
|
class="mb-[16px]"
|
||||||
>
|
>
|
||||||
<template #titleRight>
|
<template #titleRight>
|
||||||
<div class="flex items-center gap-[16px]">
|
<div class="flex items-center gap-[16px] overflow-hidden">
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex items-center gap-[8px]">
|
||||||
<div class="whitespace-nowrap text-[var(--color-text-4)]">{{ t('apiTestManagement.apiType') }}</div>
|
<div class="whitespace-nowrap text-[var(--color-text-4)]">{{ t('apiTestManagement.apiType') }}</div>
|
||||||
<apiMethodName :method="props.definitionDetail.method" tag-size="small" is-tag />
|
<apiMethodName :method="props.definitionDetail.method" tag-size="small" is-tag />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex items-center gap-[8px] overflow-hidden">
|
||||||
<div class="whitespace-nowrap text-[var(--color-text-4)]">{{ t('apiTestManagement.path') }}</div>
|
<div class="whitespace-nowrap text-[var(--color-text-4)]">{{ t('apiTestManagement.path') }}</div>
|
||||||
<a-tooltip :content="props.definitionDetail.url">
|
<a-tooltip :content="props.definitionDetail.url || props.definitionDetail.path" position="tl">
|
||||||
<div class="one-line-text">{{ props.definitionDetail.url }}</div>
|
<div class="one-line-text">{{ props.definitionDetail.url || props.definitionDetail.path }}</div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -104,6 +104,7 @@
|
||||||
v-model:matchRules="currentMatchRules"
|
v-model:matchRules="currentMatchRules"
|
||||||
:key-options="currentKeyOptions"
|
:key-options="currentKeyOptions"
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
|
:form-key="activeTab"
|
||||||
/>
|
/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="mb-[8px] flex items-center justify-between">
|
<div class="mb-[8px] flex items-center justify-between">
|
||||||
|
|
|
@ -173,6 +173,7 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id?: string;
|
id?: string;
|
||||||
|
formKey?: string;
|
||||||
keyOptions: SelectOptionData[];
|
keyOptions: SelectOptionData[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
@ -203,6 +204,17 @@
|
||||||
matchRules: matchRules.value,
|
matchRules: matchRules.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.formKey,
|
||||||
|
() => {
|
||||||
|
formModel.value = {
|
||||||
|
matchAll: matchAll.value,
|
||||||
|
matchRules: matchRules.value,
|
||||||
|
};
|
||||||
|
formRef.value?.clearValidate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function handleDeleteItem(index: number) {
|
function handleDeleteItem(index: number) {
|
||||||
matchRules.value.splice(index, 1);
|
matchRules.value.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@
|
||||||
:disabled="!hasAnyPermission(['PROJECT_API_DEFINITION_MOCK:READ+UPDATE'])"
|
:disabled="!hasAnyPermission(['PROJECT_API_DEFINITION_MOCK:READ+UPDATE'])"
|
||||||
></a-switch>
|
></a-switch>
|
||||||
</template>
|
</template>
|
||||||
|
<template #apiMethod="{ record }">
|
||||||
|
<apiMethodName :method="record.apiMethod" is-tag />
|
||||||
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<MsButton
|
<MsButton
|
||||||
v-permission="['PROJECT_API_DEFINITION_MOCK:READ+UPDATE']"
|
v-permission="['PROJECT_API_DEFINITION_MOCK:READ+UPDATE']"
|
||||||
|
@ -205,6 +208,7 @@
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||||
import mockDetailDrawer from './mockDetailDrawer.vue';
|
import mockDetailDrawer from './mockDetailDrawer.vue';
|
||||||
|
import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
|
||||||
import { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
import { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -274,10 +278,11 @@
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'common.tag',
|
title: 'apiTestManagement.apiType',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'apiMethod',
|
||||||
isTag: true,
|
slotName: 'apiMethod',
|
||||||
isStringTag: true,
|
width: 200,
|
||||||
|
showDrag: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'mockManagement.apiPath',
|
title: 'mockManagement.apiPath',
|
||||||
|
@ -285,12 +290,21 @@
|
||||||
slotName: 'apiPath',
|
slotName: 'apiPath',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
width: 200,
|
width: 200,
|
||||||
|
showDrag: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'common.tag',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
isTag: true,
|
||||||
|
isStringTag: true,
|
||||||
|
showDrag: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'common.status',
|
title: 'common.status',
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enable',
|
||||||
slotName: 'enable',
|
slotName: 'enable',
|
||||||
width: 100,
|
width: 100,
|
||||||
|
showDrag: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'mockManagement.operationUser',
|
title: 'mockManagement.operationUser',
|
||||||
|
@ -306,6 +320,7 @@
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
|
showDrag: true,
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
<a-trigger
|
<a-trigger
|
||||||
v-model:popup-visible="record.settingVisible"
|
v-model:popup-visible="record.settingVisible"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
position="br"
|
position="left"
|
||||||
class="scenario-csv-trigger"
|
class="scenario-csv-trigger"
|
||||||
|
:popup-translate="[-2, 244]"
|
||||||
>
|
>
|
||||||
<MsButton type="text" class="!mr-0" @click="handleRecordConfig(record)">
|
<MsButton type="text" class="!mr-0" @click="handleRecordConfig(record)">
|
||||||
{{ t('apiScenario.params.config') }}
|
{{ t('apiScenario.params.config') }}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
>
|
>
|
||||||
<MsBaseTable v-bind="propsRes" v-model:selected-key="selectedKey" v-on="propsEvent">
|
<MsBaseTable v-bind="propsRes" v-model:selected-key="selectedKey" v-on="propsEvent">
|
||||||
<template #scope="{ record }">
|
<template #scope="{ record }">
|
||||||
{{ record.scope === 'scenario' ? t('apiScenario.scenario') : t('apiScenario.step') }}
|
{{ record.scope === 'SCENARIO' ? t('apiScenario.scenario') : t('apiScenario.step') }}
|
||||||
</template>
|
</template>
|
||||||
<template #file="{ record }">
|
<template #file="{ record }">
|
||||||
<a-tooltip :content="record.file?.name">
|
<a-tooltip :content="record.file?.name">
|
||||||
|
|
|
@ -204,7 +204,7 @@ export const defaultCsvParamItem: CsvVariable = {
|
||||||
ignoreFirstLine: false,
|
ignoreFirstLine: false,
|
||||||
delimiter: ',',
|
delimiter: ',',
|
||||||
allowQuotedData: false,
|
allowQuotedData: false,
|
||||||
recycleOnEof: false,
|
recycleOnEof: true,
|
||||||
stopThreadOnEof: false,
|
stopThreadOnEof: false,
|
||||||
settingVisible: false,
|
settingVisible: false,
|
||||||
file: {
|
file: {
|
||||||
|
|
|
@ -546,8 +546,7 @@
|
||||||
).validParams,
|
).validParams,
|
||||||
csvVariables: filterKeyValParams(
|
csvVariables: filterKeyValParams(
|
||||||
activeScenarioTab.value.scenarioConfig.variable.csvVariables,
|
activeScenarioTab.value.scenarioConfig.variable.csvVariables,
|
||||||
defaultCsvParamItem,
|
defaultCsvParamItem
|
||||||
true
|
|
||||||
).validParams,
|
).validParams,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -610,8 +609,7 @@
|
||||||
).validParams,
|
).validParams,
|
||||||
csvVariables: filterKeyValParams(
|
csvVariables: filterKeyValParams(
|
||||||
activeScenarioTab.value.scenarioConfig.variable.csvVariables,
|
activeScenarioTab.value.scenarioConfig.variable.csvVariables,
|
||||||
defaultCsvParamItem,
|
defaultCsvParamItem
|
||||||
true
|
|
||||||
).validParams,
|
).validParams,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue