feat(接口管理): 插件增删改查接口联调

This commit is contained in:
baiqi 2024-03-05 17:37:58 +08:00 committed by 刘瑞斌
parent 33fda25e5f
commit e0d1d6f3ed
24 changed files with 213 additions and 124 deletions

View File

@ -170,7 +170,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useVModel } from '@vueuse/core';
import { Message, TagData } from '@arco-design/web-vue'; import { Message, TagData } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
@ -281,9 +280,10 @@
label: fileItem[props.fields.name] || fileItem.name || '', label: fileItem[props.fields.name] || fileItem.name || '',
}); });
} else { } else {
innerFileList.value = [fileItem];
inputFileName.value = fileItem.name || ''; inputFileName.value = fileItem.name || '';
} }
emit('change', _fileList, { ...fileItem, local: true }); emit('change', innerFileList.value, { ...fileItem, local: true });
nextTick(() => { nextTick(() => {
// emit // emit
buttonDropDownVisible.value = false; buttonDropDownVisible.value = false;
@ -302,7 +302,7 @@
// //
watch( watch(
() => innerFileList.value, () => innerFileList.value,
() => { (arr) => {
getListFunParams.value.combine.hiddenIds = innerFileList.value getListFunParams.value.combine.hiddenIds = innerFileList.value
.filter((item) => !item.local) .filter((item) => !item.local)
.map((item) => item[props.fields.id] || item.uid); .map((item) => item[props.fields.id] || item.uid);

View File

@ -269,6 +269,7 @@ export interface TimeWaitingProcessor extends ExecuteConditionProcessorCommon {
export type ExpressionType = RequestExtractExpressionEnum; export type ExpressionType = RequestExtractExpressionEnum;
// 表达式配置 // 表达式配置
export interface ExpressionCommonConfig { export interface ExpressionCommonConfig {
id?: number | string; // 前端渲染使用字段
enable: boolean; // 是否启用 enable: boolean; // 是否启用
expression: string; expression: string;
extractType: ExpressionType; // 表达式类型 extractType: ExpressionType; // 表达式类型

View File

@ -41,10 +41,10 @@
const config = statusMap[props.status]; const config = statusMap[props.status];
return { return {
style: { style: {
backgroundColor: config.bgColor, backgroundColor: config?.bgColor,
color: config.color, color: config?.color,
}, },
text: t(config.text), text: t(config?.text),
}; };
}); });
</script> </script>

View File

@ -244,7 +244,7 @@
<div v-else-if="condition.processorType === RequestConditionProcessor.EXTRACT"> <div v-else-if="condition.processorType === RequestConditionProcessor.EXTRACT">
<paramTable <paramTable
ref="extractParamsTableRef" ref="extractParamsTableRef"
v-model:params="condition.extractParams" v-model:params="condition.extractors"
:default-param-item="defaultExtractParamItem" :default-param-item="defaultExtractParamItem"
:columns="extractParamsColumns" :columns="extractParamsColumns"
:selectable="false" :selectable="false"
@ -272,6 +272,7 @@
v-model:model-value="record.expression" v-model:model-value="record.expression"
class="ms-params-input" class="ms-params-input"
:max-length="255" :max-length="255"
size="mini"
@input="() => handleExpressionChange(rowIndex)" @input="() => handleExpressionChange(rowIndex)"
@change="() => handleExpressionChange(rowIndex)" @change="() => handleExpressionChange(rowIndex)"
> >
@ -649,7 +650,7 @@ if (!result){
const disabledExpressionSuffix = ref(false); const disabledExpressionSuffix = ref(false);
function handleExtractParamTableChange(resultArr: any[], isInit?: boolean) { function handleExtractParamTableChange(resultArr: any[], isInit?: boolean) {
condition.value.extractParams = [...resultArr]; condition.value.extractors = [...resultArr];
if (!isInit) { if (!isInit) {
emit('change'); emit('change');
} }
@ -697,13 +698,13 @@ if (!result){
* 提取参数表格-应用更多设置 * 提取参数表格-应用更多设置
*/ */
function applyMoreSetting(record: ExpressionConfig) { function applyMoreSetting(record: ExpressionConfig) {
condition.value.extractParams = condition.value.extractParams?.map((e) => { condition.value.extractors = condition.value.extractors?.map((e) => {
if (e.id === activeRecord.value.id) { if (e.id === activeRecord.value.id) {
record.moreSettingPopoverVisible = false; record.moreSettingPopoverVisible = false;
return { return {
...activeRecord.value, ...activeRecord.value,
moreSettingPopoverVisible: false, moreSettingPopoverVisible: false,
} as any; // TOOD: };
} }
return e; return e;
}); });
@ -714,7 +715,7 @@ if (!result){
* 提取参数表格-保存快速提取的配置 * 提取参数表格-保存快速提取的配置
*/ */
function handleFastExtractionApply(config: RegexExtract | JSONPathExtract | XPathExtract) { function handleFastExtractionApply(config: RegexExtract | JSONPathExtract | XPathExtract) {
condition.value.extractParams = condition.value.extractParams?.map((e) => { condition.value.extractors = condition.value.extractors?.map((e) => {
if (e.id === activeRecord.value.id) { if (e.id === activeRecord.value.id) {
return { return {
...e, ...e,
@ -726,7 +727,7 @@ if (!result){
fastExtractionVisible.value = false; fastExtractionVisible.value = false;
nextTick(() => { nextTick(() => {
extractParamsTableRef.value?.addTableLine( extractParamsTableRef.value?.addTableLine(
condition.value.extractParams?.findIndex((e) => e.id === activeRecord.value.id) || 0 condition.value.extractors?.findIndex((e) => e.id === activeRecord.value.id) || 0
); );
}); });
emit('change'); emit('change');

View File

@ -120,20 +120,23 @@
}, },
}); });
break; break;
// case RequestConditionProcessor.SQL: case RequestConditionProcessor.SQL:
// data.value.push({ data.value.push({
// id, id,
// enableCommonScript: false, processorType: RequestConditionProcessor.SQL,
// desc: '', enableCommonScript: false,
// enable: true, description: '',
// sqlSource: { enable: true,
// scriptName: '', dataSourceId: '',
// script: '', environmentId: '',
// storageType: 'column', queryTimeout: 0,
// params: [], resultVariable: '',
// }, script: '',
// }); variableNames: '',
// break; variables: [],
extractParams: [],
});
break;
case RequestConditionProcessor.TIME_WAITING: case RequestConditionProcessor.TIME_WAITING:
data.value.push({ data.value.push({
id, id,

View File

@ -216,12 +216,13 @@
break; break;
case RequestExtractExpressionEnum.JSON_PATH: case RequestExtractExpressionEnum.JSON_PATH:
try { try {
matchResult.value = JSONPath({ matchResult.value =
JSONPath({
json: props.response ? JSON.parse(props.response) : '', json: props.response ? JSON.parse(props.response) : '',
path: expressionForm.value.expression, path: expressionForm.value.expression,
}); }) || [];
} catch (error) { } catch (error) {
matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }); matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }) || [];
} }
break; break;
case RequestExtractExpressionEnum.REGEX: case RequestExtractExpressionEnum.REGEX:

View File

@ -5,7 +5,7 @@
{{ t('apiTestDebug.expressionMatchRule') }} {{ t('apiTestDebug.expressionMatchRule') }}
</div> </div>
<a-radio-group v-model:model-value="expressionForm.expressionMatchingRule" size="small"> <a-radio-group v-model:model-value="expressionForm.expressionMatchingRule" size="small">
<a-radio :value="RequestExtractExpressionRuleType.EXPRESSION.toLowerCase()"> <a-radio :value="RequestExtractExpressionRuleType.EXPRESSION">
<div class="flex items-center"> <div class="flex items-center">
{{ t('apiTestDebug.matchExpression') }} {{ t('apiTestDebug.matchExpression') }}
<a-tooltip :content="t('apiTestDebug.matchExpressionTip')" :content-style="{ maxWidth: '500px' }"> <a-tooltip :content="t('apiTestDebug.matchExpressionTip')" :content-style="{ maxWidth: '500px' }">
@ -16,7 +16,7 @@
</a-tooltip> </a-tooltip>
</div> </div>
</a-radio> </a-radio>
<a-radio :value="RequestExtractExpressionRuleType.GROUP.toLowerCase()"> <a-radio :value="RequestExtractExpressionRuleType.GROUP">
<div class="flex items-center"> <div class="flex items-center">
{{ t('apiTestDebug.matchGroup') }} {{ t('apiTestDebug.matchGroup') }}
<a-tooltip :content="t('apiTestDebug.matchGroupTip')" :content-style="{ maxWidth: '500px' }"> <a-tooltip :content="t('apiTestDebug.matchGroupTip')" :content-style="{ maxWidth: '500px' }">
@ -34,7 +34,7 @@
{{ t('apiTestDebug.resultMatchRule') }} {{ t('apiTestDebug.resultMatchRule') }}
</div> </div>
<a-radio-group v-model:model-value="expressionForm.resultMatchingRule" size="small"> <a-radio-group v-model:model-value="expressionForm.resultMatchingRule" size="small">
<a-radio :value="RequestExtractResultMatchingRule.RANDOM.toLowerCase()"> <a-radio :value="RequestExtractResultMatchingRule.RANDOM">
<div class="flex items-center"> <div class="flex items-center">
{{ t('apiTestDebug.randomMatch') }} {{ t('apiTestDebug.randomMatch') }}
<a-tooltip :content="t('apiTestDebug.randomMatchTip')" :content-style="{ maxWidth: '400px' }"> <a-tooltip :content="t('apiTestDebug.randomMatchTip')" :content-style="{ maxWidth: '400px' }">
@ -45,7 +45,7 @@
</a-tooltip> </a-tooltip>
</div> </div>
</a-radio> </a-radio>
<a-radio :value="RequestExtractResultMatchingRule.SPECIFIC.toLowerCase()"> <a-radio :value="RequestExtractResultMatchingRule.SPECIFIC">
<div class="flex items-center"> <div class="flex items-center">
{{ t('apiTestDebug.specifyMatch') }} {{ t('apiTestDebug.specifyMatch') }}
<a-tooltip :content="t('apiTestDebug.specifyMatchTip')" :content-style="{ maxWidth: '400px' }"> <a-tooltip :content="t('apiTestDebug.specifyMatchTip')" :content-style="{ maxWidth: '400px' }">
@ -56,7 +56,7 @@
</a-tooltip> </a-tooltip>
</div> </div>
</a-radio> </a-radio>
<a-radio :value="RequestExtractResultMatchingRule.ALL.toLowerCase()"> <a-radio :value="RequestExtractResultMatchingRule.ALL">
<div class="flex items-center"> <div class="flex items-center">
{{ t('apiTestDebug.allMatch') }} {{ t('apiTestDebug.allMatch') }}
<a-tooltip :content="t('apiTestDebug.allMatchTip')" :content-style="{ maxWidth: '400px' }"> <a-tooltip :content="t('apiTestDebug.allMatchTip')" :content-style="{ maxWidth: '400px' }">

View File

@ -111,9 +111,9 @@
@change="(val) => handleTypeChange(val, record, rowIndex, columnConfig.addLineDisabled)" @change="(val) => handleTypeChange(val, record, rowIndex, columnConfig.addLineDisabled)"
/> />
</template> </template>
<template #expressionType="{ record, columnConfig, rowIndex }"> <template #extractType="{ record, columnConfig, rowIndex }">
<a-select <a-select
v-model:model-value="record.expressionType" v-model:model-value="record.extractType"
:options="columnConfig.typeOptions || []" :options="columnConfig.typeOptions || []"
class="param-input w-[110px]" class="param-input w-[110px]"
size="mini" size="mini"

View File

@ -49,7 +49,6 @@
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { addDebugModule, updateDebug, updateDebugModule } from '@/api/modules/api-test/debug';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
@ -74,6 +73,9 @@
parentId?: string; // id parentId?: string; // id
nodeId?: string; // id nodeId?: string; // id
popupOffset?: number; popupOffset?: number;
addModuleApi?: (params: { projectId: string; parentId: string; name: string }) => Promise<any>;
updateModuleApi?: (params: { id: string; name: string }) => Promise<any>;
updateApiNodeApi?: (params: { id: string; name: string }) => Promise<any>;
}>(); }>();
const emit = defineEmits(['update:visible', 'close', 'addFinish', 'renameFinish', 'updateDescFinish']); const emit = defineEmits(['update:visible', 'close', 'addFinish', 'renameFinish', 'updateDescFinish']);
@ -121,26 +123,26 @@
if (!errors) { if (!errors) {
try { try {
loading.value = true; loading.value = true;
if (props.mode === 'add') { if (props.mode === 'add' && props.addModuleApi) {
// //
await addDebugModule({ await props.addModuleApi({
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
parentId: props.parentId || '', parentId: props.parentId || '',
name: form.value.field, name: form.value.field,
}); });
Message.success(t('common.addSuccess')); Message.success(t('common.addSuccess'));
emit('addFinish', form.value.field); emit('addFinish', form.value.field);
} else if (props.mode === 'rename' && props.nodeType === 'API') { } else if (props.mode === 'rename' && props.nodeType === 'API' && props.updateApiNodeApi) {
// //
await updateDebug({ await props.updateApiNodeApi({
id: props.nodeId || '', id: props.nodeId || '',
name: form.value.field, name: form.value.field,
}); });
Message.success(t('common.updateSuccess')); Message.success(t('common.updateSuccess'));
emit('renameFinish', form.value.field, props.nodeId); emit('renameFinish', form.value.field, props.nodeId);
} else if (props.mode === 'rename') { } else if (props.mode === 'rename' && props.updateModuleApi) {
// //
await updateDebugModule({ await props.updateModuleApi({
id: props.nodeId || '', id: props.nodeId || '',
name: form.value.field, name: form.value.field,
}); });

View File

@ -86,7 +86,7 @@
<MsCodeEditor <MsCodeEditor
v-model:model-value="currentBodyCode" v-model:model-value="currentBodyCode"
class="flex-1" class="flex-1"
theme="MS-text" theme="vs"
height="100%" height="100%"
:show-full-screen="false" :show-full-screen="false"
:show-theme-change="false" :show-theme-change="false"
@ -121,7 +121,7 @@
params: ExecuteBody; params: ExecuteBody;
layout: 'horizontal' | 'vertical'; layout: 'horizontal' | 'vertical';
secondBoxHeight: number; secondBoxHeight: number;
uploadTempFileApi?: (file: MsFileItem) => 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>; //
fileModuleOptionsApi?: (projectId: string) => Promise<ModuleTreeNode[]>; // fileModuleOptionsApi?: (projectId: string) => Promise<ModuleTreeNode[]>; //
@ -135,18 +135,18 @@
const { t } = useI18n(); const { t } = useI18n();
const innerParams = useVModel(props, 'params', emit); const innerParams = useVModel(props, 'params', emit);
const fileList = ref<any[]>( const fileList = ref<MsFileItem[]>([]);
innerParams.value.binaryBody && innerParams.value.binaryBody.file ? [innerParams.value.binaryBody.file] : []
);
async function handleFileChange(files: MsFileItem[]) { onBeforeMount(() => {
if (files.length === 0) { if (innerParams.value.binaryBody && innerParams.value.binaryBody.file) {
innerParams.value.binaryBody.file = undefined; fileList.value = [innerParams.value.binaryBody.file as unknown as MsFileItem];
return;
} }
});
async function handleFileChange() {
if (!props.uploadTempFileApi) return; if (!props.uploadTempFileApi) return;
try { try {
if (fileList.value[0]?.local) { if (fileList.value[0]?.local && fileList.value[0].file) {
appStore.showLoading(); appStore.showLoading();
const res = await props.uploadTempFileApi(fileList.value[0].file); const res = await props.uploadTempFileApi(fileList.value[0].file);
innerParams.value.binaryBody.file = { innerParams.value.binaryBody.file = {
@ -160,7 +160,7 @@
} else { } else {
innerParams.value.binaryBody.file = { innerParams.value.binaryBody.file = {
...fileList.value[0], ...fileList.value[0],
fileId: fileList.value[0].uid, fileId: fileList.value[0]?.uid,
fileName: fileList.value[0]?.originalName || '', fileName: fileList.value[0]?.originalName || '',
fileAlias: fileList.value[0]?.name || '', fileAlias: fileList.value[0]?.name || '',
local: false, local: false,

View File

@ -43,7 +43,9 @@
<a-input <a-input
v-model:model-value="requestVModel.url" v-model:model-value="requestVModel.url"
:max-length="255" :max-length="255"
:placeholder="t('apiTestDebug.urlPlaceholder')" :placeholder="
props.isDefinition ? t('apiTestDebug.definitionUrlPlaceholder') : t('apiTestDebug.urlPlaceholder')
"
allow-clear allow-clear
@change="handleUrlChange" @change="handleUrlChange"
/> />
@ -51,8 +53,7 @@
</div> </div>
<div class="ml-[16px]"> <div class="ml-[16px]">
<a-dropdown-button <a-dropdown-button
v-if="!requestVModel.executeLoading" v-if="!requestVModel.executeLoading && hasAnyPermission([props.permissionMap.execute])"
v-permission="[props.permissionMap.execute]"
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)" :disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
class="exec-btn" class="exec-btn"
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')" @click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
@ -70,12 +71,14 @@
</a-dropdown-button> </a-dropdown-button>
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">{{ t('common.stop') }}</a-button> <a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">{{ t('common.stop') }}</a-button>
<a-dropdown <a-dropdown
v-if="props.isDefinition" v-if="props.isDefinition && hasAnyPermission([props.permissionMap.create, props.permissionMap.update])"
v-permission="[props.permissionMap.create, props.permissionMap.update]"
:loading="saveLoading || (isHttpProtocol && !requestVModel.url)" :loading="saveLoading || (isHttpProtocol && !requestVModel.url)"
@select="handleSelect" @select="handleSelect"
> >
<a-button :disabled="requestVModel.url.trim() === '' || requestVModel.name.trim() === ''" type="secondary"> <a-button
:disabled="(isHttpProtocol && requestVModel.url.trim() === '') || requestVModel.name.trim() === ''"
type="secondary"
>
{{ t('common.save') }} {{ t('common.save') }}
</a-button> </a-button>
<template #content> <template #content>
@ -147,14 +150,14 @@
@change="handlePluginFormChange" @change="handlePluginFormChange"
/> />
</a-spin> </a-spin>
<debugHeader <httpHeader
v-if="requestVModel.activeTab === RequestComposition.HEADER" v-if="requestVModel.activeTab === RequestComposition.HEADER"
v-model:params="requestVModel.headers" v-model:params="requestVModel.headers"
:layout="activeLayout" :layout="activeLayout"
:second-box-height="secondBoxHeight" :second-box-height="secondBoxHeight"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<debugBody <httpBody
v-else-if="requestVModel.activeTab === RequestComposition.BODY" v-else-if="requestVModel.activeTab === RequestComposition.BODY"
v-model:params="requestVModel.body" v-model:params="requestVModel.body"
:layout="activeLayout" :layout="activeLayout"
@ -165,14 +168,14 @@
:file-module-options-api="props.fileModuleOptionsApi" :file-module-options-api="props.fileModuleOptionsApi"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<debugQuery <httpQuery
v-else-if="requestVModel.activeTab === RequestComposition.QUERY" v-else-if="requestVModel.activeTab === RequestComposition.QUERY"
v-model:params="requestVModel.query" v-model:params="requestVModel.query"
:layout="activeLayout" :layout="activeLayout"
:second-box-height="secondBoxHeight" :second-box-height="secondBoxHeight"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<debugRest <httpRest
v-else-if="requestVModel.activeTab === RequestComposition.REST" v-else-if="requestVModel.activeTab === RequestComposition.REST"
v-model:params="requestVModel.rest" v-model:params="requestVModel.rest"
:layout="activeLayout" :layout="activeLayout"
@ -182,6 +185,7 @@
<precondition <precondition
v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION" v-else-if="requestVModel.activeTab === RequestComposition.PRECONDITION"
v-model:config="requestVModel.children[0].preProcessorConfig" v-model:config="requestVModel.children[0].preProcessorConfig"
:is-definition="props.isDefinition"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<postcondition <postcondition
@ -190,14 +194,15 @@
:response="requestVModel.response?.requestResults[0]?.responseResult.body" :response="requestVModel.response?.requestResults[0]?.responseResult.body"
:layout="activeLayout" :layout="activeLayout"
:second-box-height="secondBoxHeight" :second-box-height="secondBoxHeight"
:is-definition="props.isDefinition"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<debugAuth <auth
v-else-if="requestVModel.activeTab === RequestComposition.AUTH" v-else-if="requestVModel.activeTab === RequestComposition.AUTH"
v-model:params="requestVModel.authConfig" v-model:params="requestVModel.authConfig"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
/> />
<debugSetting <setting
v-else-if="requestVModel.activeTab === RequestComposition.SETTING" v-else-if="requestVModel.activeTab === RequestComposition.SETTING"
v-model:params="requestVModel.otherConfig" v-model:params="requestVModel.otherConfig"
@change="handleActiveDebugChange" @change="handleActiveDebugChange"
@ -280,11 +285,11 @@
import MsIcon from '@/components/pure/ms-icon-font/index.vue'; import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue'; import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsTab from '@/components/pure/ms-tab/index.vue'; import MsTab from '@/components/pure/ms-tab/index.vue';
import debugAuth from './auth.vue'; import auth from './auth.vue';
import postcondition from './postcondition.vue'; import postcondition from './postcondition.vue';
import precondition from './precondition.vue'; import precondition from './precondition.vue';
import response from './response/index.vue'; import response from './response/index.vue';
import debugSetting from './setting.vue'; import setting from './setting.vue';
import apiMethodName from '@/views/api-test/components/apiMethodName.vue'; import apiMethodName from '@/views/api-test/components/apiMethodName.vue';
import apiMethodSelect from '@/views/api-test/components/apiMethodSelect.vue'; import apiMethodSelect from '@/views/api-test/components/apiMethodSelect.vue';
@ -323,10 +328,10 @@
import type { Api } from '@form-create/arco-design'; import type { Api } from '@form-create/arco-design';
// Http // Http
const debugHeader = defineAsyncComponent(() => import('./header.vue')); const httpHeader = defineAsyncComponent(() => import('./header.vue'));
const debugBody = defineAsyncComponent(() => import('./body.vue')); const httpBody = defineAsyncComponent(() => import('./body.vue'));
const debugQuery = defineAsyncComponent(() => import('./query.vue')); const httpQuery = defineAsyncComponent(() => import('./query.vue'));
const debugRest = defineAsyncComponent(() => import('./rest.vue')); const httpRest = defineAsyncComponent(() => import('./rest.vue'));
export interface RequestCustomAttr { export interface RequestCustomAttr {
isNew: boolean; isNew: boolean;
@ -615,9 +620,13 @@
watch( watch(
() => requestVModel.value.id, () => requestVModel.value.id,
() => { async () => {
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) {
//
await initProtocolList();
}
initPluginScript(); initPluginScript();
} }
}, },
@ -846,6 +855,7 @@
...parseRequestBodyResult, ...parseRequestBodyResult,
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
frontendDebug: executeType === 'localExec', frontendDebug: executeType === 'localExec',
isNew: requestVModel.value.isNew,
}; };
} }
@ -1004,7 +1014,6 @@
} }
onBeforeMount(() => { onBeforeMount(() => {
initProtocolList();
initLocalConfig(); initLocalConfig();
}); });

View File

@ -1,13 +1,13 @@
<template> <template>
<condition <condition
v-model:list="innerConfig.processors" v-model:list="innerConfig.processors"
:condition-types="[RequestConditionProcessor.SCRIPT]" :condition-types="conditionTypes"
add-text="apiTestDebug.postCondition" add-text="apiTestDebug.postCondition"
:response="props.response" :response="props.response"
:height-used="heightUsed" :height-used="heightUsed"
@change="emit('change')" @change="emit('change')"
> >
<!-- <template #titleRight> <template v-if="props.isDefinition" #titleRight>
<a-switch v-model:model-value="innerConfig.enableGlobal" size="small" type="line"></a-switch> <a-switch v-model:model-value="innerConfig.enableGlobal" size="small" type="line"></a-switch>
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.openGlobalPostCondition') }}</div> <div class="ml-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.openGlobalPostCondition') }}</div>
<a-tooltip :content="t('apiTestDebug.openGlobalPostConditionTip')" position="left"> <a-tooltip :content="t('apiTestDebug.openGlobalPostConditionTip')" position="left">
@ -16,7 +16,7 @@
size="16" size="16"
/> />
</a-tooltip> </a-tooltip>
</template> --> </template>
</condition> </condition>
</template> </template>
@ -25,23 +25,24 @@
import condition from '@/views/api-test/components/condition/index.vue'; import condition from '@/views/api-test/components/condition/index.vue';
import { useI18n } from '@/hooks/useI18n';
import { ExecuteConditionConfig, ExecuteConditionProcessor } from '@/models/apiTest/common'; import { ExecuteConditionConfig, ExecuteConditionProcessor } from '@/models/apiTest/common';
import { RequestConditionProcessor } from '@/enums/apiEnum'; import { RequestConditionProcessor } from '@/enums/apiEnum';
// import { useI18n } from '@/hooks/useI18n';
const props = defineProps<{ const props = defineProps<{
config: ExecuteConditionConfig; config: ExecuteConditionConfig;
secondBoxHeight?: number; secondBoxHeight?: number;
layout: 'horizontal' | 'vertical'; layout: 'horizontal' | 'vertical';
response?: string; // response?: string; //
isDefinition?: boolean; //
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:params', params: ExecuteConditionProcessor[]): void; (e: 'update:params', params: ExecuteConditionProcessor[]): void;
(e: 'change'): void; (e: 'change'): void;
}>(); }>();
// const { t } = useI18n(); const { t } = useI18n();
const innerConfig = useVModel(props, 'config', emit); const innerConfig = useVModel(props, 'config', emit);
const heightUsed = computed(() => { const heightUsed = computed(() => {
if (props.layout === 'horizontal') { if (props.layout === 'horizontal') {
@ -49,6 +50,13 @@
} }
return 428 + (props.secondBoxHeight || 0); return 428 + (props.secondBoxHeight || 0);
}); });
const conditionTypes = computed(() => {
if (props.isDefinition) {
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL, RequestConditionProcessor.EXTRACT];
}
return [RequestConditionProcessor.SCRIPT];
});
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped></style>

View File

@ -1,12 +1,11 @@
<template> <template>
<condition <condition
v-model:list="innerConfig.processors" v-model:list="innerConfig.processors"
:condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.TIME_WAITING]" :condition-types="conditionTypes"
add-text="apiTestDebug.precondition" add-text="apiTestDebug.precondition"
@change="emit('change')" @change="emit('change')"
/> >
<template v-if="props.isDefinition" #titleRight>
<!-- <template #titleRight>
<a-switch v-model:model-value="innerConfig.enableGlobal" size="small" type="line"></a-switch> <a-switch v-model:model-value="innerConfig.enableGlobal" size="small" type="line"></a-switch>
<div class="ml-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.openGlobalPrecondition') }}</div> <div class="ml-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.openGlobalPrecondition') }}</div>
<a-tooltip :content="t('apiTestDebug.openGlobalPreconditionTip')" position="left"> <a-tooltip :content="t('apiTestDebug.openGlobalPreconditionTip')" position="left">
@ -15,7 +14,8 @@
size="16" size="16"
/> />
</a-tooltip> </a-tooltip>
</template> --> </template>
</condition>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -23,21 +23,29 @@
import condition from '@/views/api-test/components/condition/index.vue'; import condition from '@/views/api-test/components/condition/index.vue';
import { useI18n } from '@/hooks/useI18n';
import { ExecuteConditionConfig } from '@/models/apiTest/common'; import { ExecuteConditionConfig } from '@/models/apiTest/common';
import { RequestConditionProcessor } from '@/enums/apiEnum'; import { RequestConditionProcessor } from '@/enums/apiEnum';
// import { useI18n } from '@/hooks/useI18n';
const props = defineProps<{ const props = defineProps<{
config: ExecuteConditionConfig; config: ExecuteConditionConfig;
isDefinition?: boolean; //
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:config', params: ExecuteConditionConfig): void; (e: 'update:config', params: ExecuteConditionConfig): void;
(e: 'change'): void; (e: 'change'): void;
}>(); }>();
// const { t } = useI18n(); const { t } = useI18n();
const innerConfig = useVModel(props, 'config', emit); const innerConfig = useVModel(props, 'config', emit);
const conditionTypes = computed(() => {
if (props.isDefinition) {
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL, RequestConditionProcessor.TIME_WAITING];
}
return [RequestConditionProcessor.SCRIPT, RequestConditionProcessor.TIME_WAITING];
});
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped></style>

View File

@ -109,7 +109,6 @@
:show-theme-change="false" :show-theme-change="false"
:show-language-change="false" :show-language-change="false"
:show-charset-change="false" :show-charset-change="false"
read-only
> >
<template #rightTitle> <template #rightTitle>
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="copyScript"> <a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="copyScript">
@ -171,7 +170,7 @@
const props = defineProps<{ const props = defineProps<{
responseDefinition: ResponseDefinition[]; responseDefinition: ResponseDefinition[];
uploadTempFileApi?: (...args) => Promise<any>; // uploadTempFileApi?: (file: File) => Promise<any>; //
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'change'): void; (e: 'change'): void;
@ -322,20 +321,17 @@
} }
} }
const fileList = ref<any[]>( const fileList = ref<MsFileItem[]>([]);
activeResponse.value.body.binaryBody && activeResponse.value.body.binaryBody.file onBeforeMount(() => {
? [activeResponse.value.body.binaryBody.file] if (activeResponse.value.body.binaryBody && activeResponse.value.body.binaryBody.file) {
: [] fileList.value = [activeResponse.value.body.binaryBody.file as unknown as MsFileItem];
);
async function handleFileChange(files: MsFileItem[]) {
if (files.length === 0) {
activeResponse.value.body.binaryBody.file = undefined;
return;
} }
});
async function handleFileChange() {
if (!props.uploadTempFileApi) return; if (!props.uploadTempFileApi) return;
try { try {
if (fileList.value[0]?.local) { if (fileList.value[0]?.local && fileList.value[0].file) {
appStore.showLoading(); appStore.showLoading();
const res = await props.uploadTempFileApi(fileList.value[0].file); const res = await props.uploadTempFileApi(fileList.value[0].file);
activeResponse.value.body.binaryBody.file = { activeResponse.value.body.binaryBody.file = {

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="h-full rounded-[var(--border-radius-small)] border border-[var(--color-text-n8)] p-[16px]"> <div class="setting">
<a-form :model="settingForm" layout="vertical"> <a-form :model="settingForm" layout="vertical">
<div class="flex items-center gap-[32px]"> <div class="flex items-center gap-[32px]">
<a-form-item class="flex-1"> <a-form-item class="flex-1">
@ -99,4 +99,13 @@
} }
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped>
.setting {
@apply h-full overflow-y-auto;
.ms-scroll-bar();
padding: 16px;
border: 1px solid var(--color-text-n8);
border-radius: var(--border-radius-small);
}
</style>

View File

@ -33,6 +33,7 @@
mode="add" mode="add"
:all-names="rootModulesName" :all-names="rootModulesName"
parent-id="NONE" parent-id="NONE"
:add-module-api="addDebugModule"
@add-finish="initModules" @add-finish="initModules"
> >
<MsButton v-permission="['PROJECT_API_DEBUG:READ+ADD']" type="icon" class="!mr-0 p-[2px]"> <MsButton v-permission="['PROJECT_API_DEBUG:READ+ADD']" type="icon" class="!mr-0 p-[2px]">
@ -100,6 +101,7 @@
:field-config="{ field: renameFolderTitle }" :field-config="{ field: renameFolderTitle }"
:all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')" :all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')"
:node-type="nodeData.type" :node-type="nodeData.type"
:add-module-api="addDebugModule"
@close="resetFocusNodeKey" @close="resetFocusNodeKey"
@rename-finish="handleRenameFinish" @rename-finish="handleRenameFinish"
> >
@ -111,6 +113,8 @@
mode="add" mode="add"
:all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')" :all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')"
:parent-id="nodeData.id" :parent-id="nodeData.id"
:update-module-api="updateDebugModule"
:update-api-node-api="updateDebug"
@close="resetFocusNodeKey" @close="resetFocusNodeKey"
@add-finish="() => initModules()" @add-finish="() => initModules()"
> >
@ -137,12 +141,15 @@
import popConfirm from '@/views/api-test/components/popConfirm.vue'; import popConfirm from '@/views/api-test/components/popConfirm.vue';
import { import {
addDebugModule,
deleteDebug, deleteDebug,
deleteDebugModule, deleteDebugModule,
dragDebug, dragDebug,
getDebugModuleCount, getDebugModuleCount,
getDebugModules, getDebugModules,
moveDebugModule, moveDebugModule,
updateDebug,
updateDebugModule,
} from '@/api/modules/api-test/debug'; } from '@/api/modules/api-test/debug';
import { dropPositionMap } from '@/config/common'; import { dropPositionMap } from '@/config/common';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';

View File

@ -2,6 +2,7 @@ export default {
'apiTestDebug.newApi': 'New request', 'apiTestDebug.newApi': 'New request',
'apiTestDebug.importApi': 'Import request', 'apiTestDebug.importApi': 'Import request',
'apiTestDebug.urlPlaceholder': 'Please enter the full URL including http or https', 'apiTestDebug.urlPlaceholder': 'Please enter the full URL including http or https',
'apiTestDebug.definitionUrlPlaceholder': 'Enter the interface URL, starting with "/"',
'apiTestDebug.serverExec': 'Server execution', 'apiTestDebug.serverExec': 'Server execution',
'apiTestDebug.localExec': 'Local execution', 'apiTestDebug.localExec': 'Local execution',
'apiTestDebug.noMatchModule': 'No matching module data yet', 'apiTestDebug.noMatchModule': 'No matching module data yet',

View File

@ -2,6 +2,7 @@ export default {
'apiTestDebug.newApi': '新建请求', 'apiTestDebug.newApi': '新建请求',
'apiTestDebug.importApi': '导入请求', 'apiTestDebug.importApi': '导入请求',
'apiTestDebug.urlPlaceholder': '请输入包含 http 或 https 的完整URL', 'apiTestDebug.urlPlaceholder': '请输入包含 http 或 https 的完整URL',
'apiTestDebug.definitionUrlPlaceholder': '输入接口URL以“/”开始',
'apiTestDebug.serverExec': '服务端执行', 'apiTestDebug.serverExec': '服务端执行',
'apiTestDebug.localExec': '本地执行', 'apiTestDebug.localExec': '本地执行',
'apiTestDebug.noMatchModule': '暂无匹配的模块数据', 'apiTestDebug.noMatchModule': '暂无匹配的模块数据',

View File

@ -11,12 +11,14 @@
read-only read-only
@init="(val) => (folderTree = val)" @init="(val) => (folderTree = val)"
@folder-node-select="handleNodeSelect" @folder-node-select="handleNodeSelect"
@change-protocol="handleProtocolChange"
/> />
<a-divider direction="vertical" :margin="16"></a-divider> <a-divider direction="vertical" :margin="16"></a-divider>
<apiTable <apiTable
:active-module="activeModule" :active-module="activeModule"
:offspring-ids="offspringIds" :offspring-ids="offspringIds"
class="flex-1 overflow-hidden !pl-0 !pr-[16px]" class="flex-1 overflow-hidden !pl-0 !pr-[16px]"
:protocol="protocol"
read-only read-only
/> />
</div> </div>
@ -46,11 +48,16 @@
const folderTree = ref<ModuleTreeNode[]>([]); const folderTree = ref<ModuleTreeNode[]>([]);
const activeModule = ref<string>('all'); const activeModule = ref<string>('all');
const offspringIds = ref<string[]>([]); const offspringIds = ref<string[]>([]);
const protocol = ref('HTTP');
function handleNodeSelect(keys: string[], _offspringIds: string[]) { function handleNodeSelect(keys: string[], _offspringIds: string[]) {
[activeModule.value] = keys; [activeModule.value] = keys;
offspringIds.value = _offspringIds; offspringIds.value = _offspringIds;
} }
function handleProtocolChange(val: string) {
protocol.value = val;
}
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped></style>

View File

@ -52,10 +52,10 @@
trigger="click" trigger="click"
@popup-visible-change="handleFilterHidden" @popup-visible-change="handleFilterHidden"
> >
<a-button type="text" class="arco-btn-text--secondary" @click="methodFilterVisible = true"> <MsButton type="text" class="arco-btn-text--secondary" @click="methodFilterVisible = true">
{{ t(columnConfig.title as string) }} {{ t(columnConfig.title as string) }}
<icon-down :class="methodFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" /> <icon-down :class="methodFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</a-button> </MsButton>
<template #content> <template #content>
<div class="arco-table-filters-content"> <div class="arco-table-filters-content">
<div class="flex items-center justify-center px-[6px] py-[2px]"> <div class="flex items-center justify-center px-[6px] py-[2px]">
@ -75,16 +75,16 @@
trigger="click" trigger="click"
@popup-visible-change="handleFilterHidden" @popup-visible-change="handleFilterHidden"
> >
<a-button type="text" class="arco-btn-text--secondary" @click="statusFilterVisible = true"> <MsButton type="text" class="arco-btn-text--secondary ml-[10px]" @click="statusFilterVisible = true">
{{ t(columnConfig.title as string) }} {{ t(columnConfig.title as string) }}
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" /> <icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
</a-button> </MsButton>
<template #content> <template #content>
<div class="arco-table-filters-content"> <div class="arco-table-filters-content">
<div class="flex items-center justify-center px-[6px] py-[2px]"> <div class="flex items-center justify-center px-[6px] py-[2px]">
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small"> <a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
<a-checkbox v-for="key of RequestDefinitionStatus" :key="key" :value="key"> <a-checkbox v-for="val of Object.values(RequestDefinitionStatus)" :key="val" :value="val">
<apiStatus :status="key" /> <apiStatus :status="val" />
</a-checkbox> </a-checkbox>
</a-checkbox-group> </a-checkbox-group>
</div> </div>
@ -108,7 +108,7 @@
<template #label> <template #label>
<apiStatus :status="record.status" /> <apiStatus :status="record.status" />
</template> </template>
<a-option v-for="item of RequestDefinitionStatus" :key="item" :value="item"> <a-option v-for="item of Object.values(RequestDefinitionStatus)" :key="item" :value="item">
<apiStatus :status="item" /> <apiStatus :status="item" />
</a-option> </a-option>
</a-select> </a-select>
@ -271,6 +271,7 @@
class?: string; class?: string;
activeModule: string; activeModule: string;
offspringIds: string[]; offspringIds: string[];
protocol: string; //
readOnly?: boolean; // readOnly?: boolean; //
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -346,12 +347,6 @@
titleSlotName: 'statusFilter', titleSlotName: 'statusFilter',
width: 130, width: 130,
}, },
{
title: 'apiTestManagement.responsiblePerson',
dataIndex: 'createUserName',
showTooltip: true,
width: 120,
},
{ {
title: 'apiTestManagement.path', title: 'apiTestManagement.path',
slotName: 'path', slotName: 'path',
@ -474,6 +469,7 @@
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
moduleIds: moduleIds.value, moduleIds: moduleIds.value,
env: checkedEnv.value, env: checkedEnv.value,
protocol: props.protocol,
filter: { status: statusFilters.value, type: methodFilters.value }, filter: { status: statusFilters.value, type: methodFilters.value },
}; };
setLoadListParams(params); setLoadListParams(params);
@ -495,6 +491,13 @@
} }
); );
watch(
() => props.protocol,
() => {
loadApiList();
}
);
function handleFilterHidden(val: boolean) { function handleFilterHidden(val: boolean) {
if (!val) { if (!val) {
loadApiList(); loadApiList();

View File

@ -9,7 +9,12 @@
</MsEditableTab> </MsEditableTab>
</div> </div>
<div v-show="activeApiTab.id === 'all'" class="flex-1"> <div v-show="activeApiTab.id === 'all'" class="flex-1">
<apiTable :active-module="props.activeModule" :offspring-ids="props.offspringIds" @open-api-tab="openApiTab" /> <apiTable
:active-module="props.activeModule"
:offspring-ids="props.offspringIds"
:protocol="props.protocol"
@open-api-tab="openApiTab"
/>
</div> </div>
<div v-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden"> <div v-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden">
<a-tabs default-active-key="definition" animation lazy-load class="ms-api-tab-nav"> <a-tabs default-active-key="definition" animation lazy-load class="ms-api-tab-nav">
@ -68,7 +73,7 @@
<template #label> <template #label>
<apiStatus :status="activeApiTab.status" /> <apiStatus :status="activeApiTab.status" />
</template> </template>
<a-option v-for="item of RequestDefinitionStatus" :key="item" :value="item"> <a-option v-for="item of Object.values(RequestDefinitionStatus)" :key="item" :value="item">
<apiStatus :status="item" /> <apiStatus :status="item" />
</a-option> </a-option>
</a-select> </a-select>
@ -178,6 +183,7 @@
activeModule: string; activeModule: string;
offspringIds: string[]; offspringIds: string[];
moduleTree: ModuleTreeNode[]; // moduleTree: ModuleTreeNode[]; //
protocol: string;
}>(); }>();
const emit = defineEmits(['addDone']); const emit = defineEmits(['addDone']);

View File

@ -7,6 +7,7 @@
:active-module="props.activeModule" :active-module="props.activeModule"
:all-count="props.allCount" :all-count="props.allCount"
:offspring-ids="props.offspringIds" :offspring-ids="props.offspringIds"
:protocol="protocol"
/> />
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="case" title="CASE" class="ms-api-tab-pane"> </a-tab-pane> <a-tab-pane key="case" title="CASE" class="ms-api-tab-pane"> </a-tab-pane>
@ -26,6 +27,7 @@
allCount: number; allCount: number;
activeModule: string; activeModule: string;
offspringIds: string[]; offspringIds: string[];
protocol: string;
moduleTree: ModuleTreeNode[]; // moduleTree: ModuleTreeNode[]; //
}>(); }>();

View File

@ -51,7 +51,13 @@
<a-doption value="addModule">{{ t('apiTestManagement.addSubModule') }}</a-doption> <a-doption value="addModule">{{ t('apiTestManagement.addSubModule') }}</a-doption>
</template> </template>
</a-dropdown> </a-dropdown>
<popConfirm mode="add" :all-names="rootModulesName" parent-id="NONE" @add-finish="initModules"> <popConfirm
mode="add"
:all-names="rootModulesName"
parent-id="NONE"
:add-module-api="addModule"
@add-finish="initModules"
>
<span id="addModulePopSpan"></span> <span id="addModulePopSpan"></span>
</popConfirm> </popConfirm>
</template> </template>
@ -105,6 +111,7 @@
mode="add" mode="add"
:all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')" :all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')"
:parent-id="nodeData.id" :parent-id="nodeData.id"
:add-module-api="addModule"
@close="resetFocusNodeKey" @close="resetFocusNodeKey"
@add-finish="() => initModules()" @add-finish="() => initModules()"
> >
@ -119,6 +126,8 @@
:node-id="nodeData.id" :node-id="nodeData.id"
:field-config="{ field: renameFolderTitle }" :field-config="{ field: renameFolderTitle }"
:all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')" :all-names="(nodeData.children || []).map((e: ModuleTreeNode) => e.name || '')"
:update-module-api="updateModule"
:update-api-node-api="updateModule"
@close="resetFocusNodeKey" @close="resetFocusNodeKey"
@rename-finish="initModules" @rename-finish="initModules"
> >
@ -144,11 +153,13 @@
import { getProtocolList } from '@/api/modules/api-test/common'; import { getProtocolList } from '@/api/modules/api-test/common';
import { import {
addModule,
deleteModule, deleteModule,
getModuleCount, getModuleCount,
getModuleTree, getModuleTree,
getModuleTreeOnlyModules, getModuleTreeOnlyModules,
moveModule, moveModule,
updateModule,
} from '@/api/modules/api-test/management'; } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal'; import useModal from '@/hooks/useModal';
@ -168,7 +179,7 @@
activeModule: 'all', activeModule: 'all',
} }
); );
const emit = defineEmits(['init', 'newApi', 'import', 'folderNodeSelect', 'clickApiNode']); const emit = defineEmits(['init', 'newApi', 'import', 'folderNodeSelect', 'clickApiNode', 'changeProtocol']);
const appStore = useAppStore(); const appStore = useAppStore();
const { t } = useI18n(); const { t } = useI18n();
@ -345,7 +356,7 @@
if (isSetDefaultKey) { if (isSetDefaultKey) {
selectedKeys.value = [folderTree.value[0].id]; selectedKeys.value = [folderTree.value[0].id];
} }
emit('init', folderTree.value); emit('init', folderTree.value, moduleProtocol.value);
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error); console.log(error);
@ -377,6 +388,7 @@
} }
async function handleProtocolChange() { async function handleProtocolChange() {
emit('changeProtocol', moduleProtocol.value);
await initModules(); await initModules();
initModuleCount(); initModuleCount();
} }

View File

@ -5,11 +5,12 @@
<div class="p-[24px]"> <div class="p-[24px]">
<moduleTree <moduleTree
:active-node-id="activeApi?.id" :active-node-id="activeApi?.id"
@init="(val) => (folderTree = val)" @init="handleModuleInit"
@new-api="newApi" @new-api="newApi"
@import="importDrawerVisible = true" @import="importDrawerVisible = true"
@folder-node-select="handleNodeSelect" @folder-node-select="handleNodeSelect"
@click-api-node="handleApiNodeClick" @click-api-node="handleApiNodeClick"
@change-protocol="handleProtocolChange"
/> />
</div> </div>
<!-- <div class="b-0 absolute w-[88%]"> <!-- <div class="b-0 absolute w-[88%]">
@ -42,6 +43,7 @@
:all-count="allCount" :all-count="allCount"
:active-module="activeModule" :active-module="activeModule"
:offspring-ids="offspringIds" :offspring-ids="offspringIds"
:protocol="protocol"
/> />
</div> </div>
</template> </template>
@ -66,9 +68,15 @@
const allCount = ref(0); const allCount = ref(0);
const importDrawerVisible = ref(false); const importDrawerVisible = ref(false);
const offspringIds = ref<string[]>([]); const offspringIds = ref<string[]>([]);
const protocol = ref('HTTP');
const activeApi = ref<RequestParam>(); const activeApi = ref<RequestParam>();
const managementRef = ref<InstanceType<typeof management>>(); const managementRef = ref<InstanceType<typeof management>>();
function handleModuleInit(tree, _protocol: string) {
folderTree.value = tree;
protocol.value = _protocol;
}
function newApi() { function newApi() {
managementRef.value?.newTab(); managementRef.value?.newTab();
} }
@ -86,6 +94,10 @@
activeApi.value = params; activeApi.value = params;
} }
function handleProtocolChange(val: string) {
protocol.value = val;
}
provide('setActiveApi', setActiveApi); provide('setActiveApi', setActiveApi);
</script> </script>