fix(接口测试): csv/mock 功能 bug 修复

This commit is contained in:
baiqi 2024-05-23 11:54:16 +08:00 committed by 刘瑞斌
parent fa0fdb1ee4
commit 7afaa42513
10 changed files with 70 additions and 37 deletions

View File

@ -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) {

View File

@ -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:

View File

@ -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('');

View File

@ -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">

View File

@ -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);
} }

View File

@ -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,
}, },
{ {

View File

@ -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') }}

View File

@ -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">

View File

@ -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: {

View 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,
}, },
}, },