feat(项目管理): 环境功能修改和部分bug修改

This commit is contained in:
xinxin.wu 2024-03-11 20:24:58 +08:00 committed by Craftsman
parent 79bdb3eee2
commit eb235d9a97
19 changed files with 322 additions and 117 deletions

View File

@ -25,7 +25,7 @@ export function updateOrAddEnv(data: { request: EnvDetailItem; fileList: FileIte
export function listEnv(data: { projectId: string; keyword: string }) {
return MSR.post<EnvListItem[]>({ url: envURL.listEnvUrl, data });
}
export function importEnv(data: { request: any; fileList: FileItem[] }) {
export function importEnv(data: { request: any; fileList: File[] }) {
return MSR.uploadFile({ url: envURL.importEnvUrl }, data, '', false);
}
export function getEntryEnv(data: EnvListItem) {
@ -94,7 +94,7 @@ export function updateOrAddGlobalParam(data: GlobalParams) {
return MSR.post<EnvListItem>({ url: data.id ? envURL.updateGlobalParamUrl : envURL.addGlobalParamUrl, data });
}
/** 项目管理-环境-全局参数-导入 */
export function importGlobalParam(data: { request: any; fileList: FileItem[] }) {
export function importGlobalParam(data: { request: any; fileList: File[] }) {
return MSR.uploadFile<EnvListItem>({ url: envURL.importGlobalParamUrl }, data, '', false);
}
/** 项目管理-环境-全局参数-详情 */

View File

@ -88,7 +88,13 @@
<!-- xPath开始 -->
<div v-if="activeTab === ResponseBodyAssertionType.XPATH" class="mt-[16px]">
<div class="text-[var(--color-text-1)]">{{ t('ms.assertion.responseContentType') }}</div>
<a-radio-group v-model="activeResponseFormat" class="mb-[16px] mt-[16px]" type="button" size="small">
<a-radio-group
v-model="activeResponseFormat"
class="mb-[16px] mt-[16px]"
type="button"
size="small"
@change="(value: string | number | boolean)=>changeHandler(value,ResponseBodyAssertionType.XPATH)"
>
<a-radio key="XML" value="XML">XML</a-radio>
<a-radio key="HTML" value="HTML">HTML</a-radio>
</a-radio-group>
@ -328,6 +334,7 @@
import moreSetting from '@/views/api-test/components/fastExtraction/moreSetting.vue';
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
import { conditionTypeNameMap } from '@/config/apiTest';
import { useI18n } from '@/hooks/useI18n';
import {
countNodes,
@ -403,10 +410,6 @@
};
const condition = useVModel(props, 'data', emit);
// const condition = ref<Param>(props.data || defaultParamItem);
// watchEffect(() => {
// emit('change', { ...condition.value });
// });
const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>();
const fastExtractionVisible = ref(false);
@ -782,4 +785,10 @@
const handleScriptChange = (data: ExecuteConditionProcessor) => {
condition.value.script = data;
};
// XML
function changeHandler(value: string | number | boolean, type: string) {
if (value === condition.value.responseFormat) {
handleChange([], type);
}
}
</script>

View File

@ -1,40 +1,53 @@
<template>
<conditionContent v-model:data="innerParams" :height-used="600" is-build-in class="mt-[16px]" />
<div class="h-full w-full">
<a-scrollbar
:style="{
overflow: 'auto',
height: 'calc(100vh - 490px)',
}"
>
<conditionContent v-model:data="condition" is-build-in />
</a-scrollbar>
</div>
</template>
<script lang="ts" setup>
import { useVModel } from '@vueuse/core';
import conditionContent from '@/views/api-test/components/condition/content.vue';
import { RequestConditionProcessor, RequestConditionScriptLanguage } from '@/enums/apiEnum';
import { getEnvironment } from '@/api/modules/api-test/common';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
const store = useProjectEnvStore();
interface ScriptItem {
[key: string]: any;
}
interface ScriptTabProps {
value: ScriptItem;
data: any;
}
const defaultScriptItem: ScriptItem = {
id: new Date().getTime(),
processorType: RequestConditionProcessor.SCRIPT,
scriptName: '断言脚本名称',
enableCommonScript: false,
params: [],
scriptId: '',
scriptLanguage: RequestConditionScriptLanguage.JAVASCRIPT,
script: '',
};
const props = defineProps<ScriptTabProps>();
const emit = defineEmits<{
(e: 'change', val: ScriptItem): void; //
}>();
const innerParams = ref<any>(props.value || defaultScriptItem);
watchEffect(() => {
emit('change', innerParams.value);
const condition = useVModel(props, 'data', emit);
const currentEnvConfig = ref({});
async function initEnvironment() {
try {
currentEnvConfig.value = await getEnvironment(store.currentId);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
/** 向孙组件提供属性 */
provide('currentEnvConfig', readonly(currentEnvConfig));
onBeforeMount(() => {
initEnvironment();
});
</script>

View File

@ -12,11 +12,12 @@
</template>
</a-dropdown>
<div v-if="showBody" class="ms-assertion-body">
<div v-if="showBody" class="ms-assertion-body w-full">
<a-scrollbar
:style="{
overflow: 'auto',
height: 'calc(100vh - 458px)',
width: '100%',
}"
>
<VueDraggable v-model="assertions" class="ms-assertion-body-left" ghost-class="ghost" handle=".sort-handle">
@ -63,49 +64,49 @@
</VueDraggable>
</a-scrollbar>
<section class="ms-assertion-body-right">
<a-scrollbar
<!-- <a-scrollbar
:style="{
overflow: 'auto',
height: '200px',
height: 'calc(100vh - 458px)',
}"
>
<!-- 响应头 -->
<ResponseHeaderTab
v-if="valueKey === ResponseAssertionType.RESPONSE_HEADER"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 状态码 -->
<StatusCodeTab
v-if="valueKey === ResponseAssertionType.RESPONSE_CODE"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 响应体 -->
<ResponseBodyTab
v-if="valueKey === ResponseAssertionType.RESPONSE_BODY"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 响应时间 -->
<ResponseTimeTab
v-if="valueKey === ResponseAssertionType.RESPONSE_TIME"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 变量 -->
<VariableTab
v-if="valueKey === ResponseAssertionType.VARIABLE"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 脚本 -->
<ScriptTab
v-if="valueKey === ResponseAssertionType.SCRIPT"
:value="getCurrentItemState"
@change="handleChange"
/>
</a-scrollbar>
> -->
<!-- 响应头 -->
<ResponseHeaderTab
v-if="valueKey === ResponseAssertionType.RESPONSE_HEADER"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 状态码 -->
<StatusCodeTab
v-if="valueKey === ResponseAssertionType.RESPONSE_CODE"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 响应体 -->
<ResponseBodyTab
v-if="valueKey === ResponseAssertionType.RESPONSE_BODY"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 响应时间 -->
<ResponseTimeTab
v-if="valueKey === ResponseAssertionType.RESPONSE_TIME"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 变量 -->
<VariableTab
v-if="valueKey === ResponseAssertionType.VARIABLE"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- 脚本 -->
<ScriptTab
v-if="valueKey === ResponseAssertionType.SCRIPT"
v-model:data="getCurrentItemState"
@change="handleChange"
/>
<!-- </a-scrollbar> -->
</section>
</div>
</div>
@ -117,6 +118,7 @@
import { VueDraggable } from 'vue-draggable-plus';
import MsButton from '@/components/pure/ms-button/index.vue';
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
@ -129,7 +131,8 @@
import { useI18n } from '@/hooks/useI18n';
import { ResponseAssertionType } from '@/enums/apiEnum';
import { ExecuteConditionProcessor } from '@/models/apiTest/common';
import { RequestConditionScriptLanguage, ResponseAssertionType } from '@/enums/apiEnum';
import { ExecuteAssertion, MsAssertionItem } from './type';
@ -192,6 +195,12 @@
bodyAssertionDataByType: {},
};
}
if (currentResItem && currentResItem?.assertionType === ResponseAssertionType.SCRIPT) {
return {
...currentResItem,
processorType: ResponseAssertionType.SCRIPT,
};
}
return currentResItem;
},
set: (val: ExecuteAssertion) => {
@ -303,6 +312,23 @@
});
break;
case ResponseAssertionType.SCRIPT:
assertions.value.push({
...tmpObj,
id,
processorType: ResponseAssertionType.SCRIPT,
scriptName: t('apiTestDebug.preconditionScriptName'),
enableCommonScript: true,
script: '',
scriptId: '',
scriptLanguage: LanguageEnum.BEANSHELL,
commonScriptInfo: {
id: '',
name: '',
script: '',
params: [{}],
scriptLanguage: LanguageEnum.BEANSHELL,
},
});
break;
default:
@ -360,6 +386,7 @@
getCurrentItemState.value =
assertions.value.find((item: any) => item.id === activeKey.value) || assertions.value[0] || {};
activeKey.value = getCurrentItemState.value.id;
console.log(getCurrentItemState.value, 'getCurrentItemState.value');
});
</script>

View File

@ -33,7 +33,7 @@
<template #name="{ record }">
<div class="flex items-center">
<div class="one-line-text max-w-[200px] cursor-pointer text-[rgb(var(--primary-5))]">{{ record.name }}</div>
<a-popover :title="t('project.commonScript.publicScriptName')" position="right">
<a-popover :title="record.name" position="right">
<a-button type="text" class="ml-2 px-0">{{ t('project.commonScript.preview') }}</a-button>
<template #content>
<div class="w-[436px] bg-[var(--color-bg-3)] px-2 pb-2">

View File

@ -15,7 +15,9 @@
<div class="inner-wrapper">
<div class="optional-field">
<div class="optional-header">
<div class="font-medium">{{ t('system.orgTemplate.optionalField') }}</div>
<div class="font-medium">{{
props.titleProps?.selectableTitle || t('system.orgTemplate.optionalField')
}}</div>
<a-checkbox :model-value="isCheckedAll" :indeterminate="indeterminate" @change="handleChangeAll">
<span class="font-medium text-[var(--color-text-3)]">{{ t('system.orgTemplate.selectAll') }}</span>
</a-checkbox>
@ -23,7 +25,9 @@
<div class="p-[16px]">
<a-checkbox-group :model-value="selectedIds" @change="handleGroupChange">
<div v-if="systemList.length" class="mb-[32px]">
<div class="text-[var(--color-text-4)]">{{ t('ms-export-drawer.systemFiled') }}</div>
<div class="text-[var(--color-text-4)]">{{
props.titleProps?.systemTitle || t('ms-export-drawer.systemFiled')
}}</div>
<div class="flex flex-row flex-wrap">
<a-checkbox
v-for="item in systemList"
@ -80,7 +84,9 @@
</div>
<div>
<div class="optional-header min-w-[270px]">
<div class="font-medium">{{ t('system.orgTemplate.selectedField') }}</div>
<div class="font-medium">{{
props.titleProps?.selectedTitle || t('system.orgTemplate.selectedField')
}}</div>
<MsButton @click="handleReset">{{ t('system.orgTemplate.clear') }}</MsButton>
</div>
<div class="p-[16px]">
@ -140,6 +146,11 @@
defaultSelectedKeys?: string[];
isArrayColumn?: boolean;
arrayColumn?: EnvListItem[];
titleProps?: {
selectableTitle: string; //
systemTitle: string; // |
selectedTitle: string; // |
};
}
const props = withDefaults(defineProps<MsExportDrawerProps>(), {

View File

@ -1,5 +1,5 @@
<template>
<div class="condition-content">
<div class="condition-content h-full">
<!-- 脚本操作 -->
<template
v-if="
@ -45,7 +45,7 @@
</div>
<!-- 前后置请求结束 -->
<div class="flex items-center justify-between">
<a-radio-group v-model:model-value="condition.enableCommonScript" class="mb-[8px]">
<a-radio-group v-model="condition.enableCommonScript" class="mb-[8px]">
<a-radio :value="false">{{ t('apiTestDebug.manual') }}</a-radio>
<a-radio :value="true">{{ t('apiTestDebug.quote') }}</a-radio>
</a-radio-group>

View File

@ -679,6 +679,36 @@
color: var(--color-text-1);
}
}
:deep(.arco-input-tag) {
border-color: transparent !important;
&:hover {
border-color: rgb(var(--primary-5)) !important;
}
}
:deep(.arco-select-view-multiple) {
border-color: transparent !important;
.arco-select-view-suffix {
visibility: hidden;
}
&:hover {
border-color: rgb(var(--primary-5)) !important;
.arco-select-view-suffix {
visibility: visible !important;
}
}
}
:deep(.arco-textarea-wrapper) {
border-color: transparent !important;
&:hover {
border-color: rgb(var(--primary-5)) !important;
}
}
:deep(.arco-input-number) {
border-color: transparent !important;
&:hover {
border-color: rgb(var(--primary-5)) !important;
}
}
}
.rightButtons {
:deep(.ms-button--secondary):hover,

View File

@ -409,7 +409,7 @@
label: item.fieldName,
value: initValue,
required: item.required,
options: item.options || [],
options: optionsValue || [],
props: {
modelValue: initValue,
options: optionsValue || [],

View File

@ -5,11 +5,14 @@ import type { MsFileItem } from '@/components/pure/ms-upload/types';
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
import { useI18n } from '@/hooks/useI18n';
import useUserStore from '@/store/modules/user';
import { hasAnyPermission } from '@/utils/permission';
import type { AssociatedList, CustomAttributes } from '@/models/caseManagement/featureCase';
import { StatusType } from '@/enums/caseEnum';
const userStore = useUserStore();
const { t } = useI18n();
export interface ReviewResult {
@ -171,19 +174,45 @@ export function initFormCreate(customFields: CustomAttributes[], permission: str
return customFields.map((item: any) => {
const multipleType = ['MULTIPLE_SELECT', 'CHECKBOX', 'MULTIPLE_MEMBER', 'MULTIPLE_INPUT'];
const numberType = ['INT', 'FLOAT'];
const memberType = ['MEMBER', 'MULTIPLE_MEMBER'];
let currentDefaultValue;
let optionsValue = item.options;
// 处理数字类型
if (numberType.includes(item.type)) {
currentDefaultValue = item.defaultValue * 1;
// 处理多选项类型为空的默认值
} else if (multipleType.includes(item.type) && Array.isArray(item.defaultValue) && item.defaultValue.length === 0) {
currentDefaultValue = item.defaultValue;
// 处理多选情况
} else if (multipleType.includes(item.type)) {
const tempValue = JSON.parse(item.defaultValue);
if (item.type !== 'MULTIPLE_INPUT') {
if (item.type !== 'MULTIPLE_INPUT' && !item.type.includes('MEMBER')) {
const optionsIds = item.options?.map((e: any) => e.value);
currentDefaultValue = optionsIds.filter((e: any) => tempValue.includes(e));
// 多选成员
} else if (memberType.includes(item.type)) {
optionsValue = [
{
fieldId: item.fieldId,
internal: item.internal,
text: userStore.name || '',
value: userStore.id || '',
},
];
currentDefaultValue = item.defaultValue;
} else {
currentDefaultValue = JSON.parse(item.defaultValue);
}
} else if (memberType.includes(item.type)) {
optionsValue = [
{
fieldId: item.fieldId,
internal: item.internal,
text: userStore.name || '',
value: userStore.id || '',
},
];
currentDefaultValue = item.defaultValue;
} else {
currentDefaultValue = item.defaultValue;
}
@ -194,11 +223,11 @@ export function initFormCreate(customFields: CustomAttributes[], permission: str
label: item.fieldName,
value: currentDefaultValue,
required: item.required,
options: item.options || [],
options: optionsValue || [],
props: {
modelValue: currentDefaultValue,
disabled: !hasAnyPermission(permission),
options: item.options || [],
options: optionsValue || [],
},
};
}) as FormItem[];

View File

@ -54,6 +54,13 @@
},
];
function initEnvDetail() {
projectEnvStore.initEnvDetail().then(() => {
headerParams.value = projectEnvStore.allParamDetailInfo?.globalParams.headers || [];
GlobalVariable.value = projectEnvStore.allParamDetailInfo?.globalParams.commonVariables || [];
});
}
const handleSave = async () => {
try {
loading.value = true;
@ -75,6 +82,7 @@
await updateOrAddGlobalParam(params);
Message.success(t('common.saveSuccess'));
canSave.value = false;
initEnvDetail();
} catch (error) {
Message.error(t('common.saveFailed'));
// eslint-disable-next-line no-console
@ -83,11 +91,13 @@
loading.value = false;
}
};
onBeforeMount(() => {
projectEnvStore.initEnvDetail().then(() => {
headerParams.value = projectEnvStore.allParamDetailInfo?.globalParams.headers || [];
GlobalVariable.value = projectEnvStore.allParamDetailInfo?.globalParams.commonVariables || [];
});
initEnvDetail();
});
defineExpose({
initEnvDetail,
});
</script>

View File

@ -45,14 +45,17 @@
'!mb-[16px]': !(activeKey === 'pre' || activeKey === 'post'),
}"
/>
<div class="content">
<div class="content h-full">
<EnvParamsTab v-if="activeKey === 'envParams'" />
<HttpTab v-else-if="activeKey === 'http'" />
<DataBaseTab v-else-if="activeKey === 'database'" />
<HostTab v-else-if="activeKey === 'host'" />
<!-- <PreTab v-else-if="activeKey === 'pre'" />
<PostTab v-else-if="activeKey === 'post'" /> -->
<PreAndPostTab v-else-if="activeKey === 'pre' || activeKey === 'post'" :active-type="activeKey" />
<div v-else-if="activeKey === 'pre' || activeKey === 'post'" class="h-full">
<PreAndPostTab :active-type="activeKey" />
</div>
<AssertTab v-else-if="activeKey === 'assert'" />
<template v-for="item in envPluginList" :key="item.pluginId">
<PluginTab
@ -67,7 +70,7 @@
</div>
<div class="footer" :style="{ width: '100%' }">
<a-button @click="handleReset">{{ t('common.cancel') }}</a-button>
<a-button :disabled="loading" @click="handleReset">{{ t('common.cancel') }}</a-button>
<a-button type="primary" :loading="loading" @click="handleSave">{{ t('common.save') }}</a-button>
</div>
</div>
@ -98,6 +101,7 @@
const emit = defineEmits<{
(e: 'ok'): void;
(e: 'resetEnv'): void;
}>();
const activeKey = ref('envParams');
@ -186,7 +190,7 @@
const handleReset = () => {
envForm.value?.resetFields();
store.initEnvDetail();
emit('resetEnv');
};
const handleSave = async () => {
@ -256,6 +260,7 @@
.content {
overflow-y: auto;
padding: 0 24px;
height: 100%;
max-height: calc(100% - 320px);
background-color: #ffffff;
}

View File

@ -57,8 +57,10 @@
</a-spin>
</a-spin>
<div>
<a-button type="secondary">{{ t('system.plugin.pluginCancel') }}</a-button>
<a-button class="ml-3" type="primary" @click="confirmHandler">{{ t('common.import') }}</a-button>
<a-button type="secondary" @click="handleCancel(false)">{{ t('system.plugin.pluginCancel') }}</a-button>
<a-button class="ml-3" type="primary" :loading="confirmLoading" @click="confirmHandler">{{
t('common.import')
}}</a-button>
</div>
</div>
</template>
@ -102,15 +104,19 @@
const confirmHandler = async () => {
try {
confirmLoading.value = true;
const params = {
const params: { request: Record<string, any>; fileList: File[] } = {
request: { cover: isCover.value },
fileList: fileList.value,
fileList: fileList.value.map((item: any) => item.file),
};
if (props.type === EnvAuthTypeEnum.GLOBAL) {
await importGlobalParam(params);
emit('submit', true);
} else if (props.type === EnvAuthTypeEnum.ENVIRONMENT) {
await importEnv(params);
emit('submit', true);
}
fileList.value = [];
Message.success(t('common.importSuccess'));
handleCancel(true);
} catch (error) {

View File

@ -222,6 +222,7 @@
if (errors) {
return;
}
const { driverId } = form.value;
try {
const index = store.currentEnvDetailInfo.config.dataSources.findIndex((item: any) => item.id === form.value.id);
if (index > -1 && !props.isCopy) {
@ -231,12 +232,14 @@
...form.value,
dataSource: `copy_${form.value.dataSource}`,
id: getGenerateId(),
driver: driverOption.value.find((item) => item.value === driverId)?.label,
};
store.currentEnvDetailInfo.config.dataSources.splice(index + 1, 0, insertItem);
} else {
const dataSourceItem = {
...form.value,
id: getGenerateId(),
driver: driverOption.value.find((item) => item.value === driverId)?.label,
};
store.currentEnvDetailInfo.config.dataSources.push(dataSourceItem);
}

View File

@ -1,25 +1,32 @@
<template>
<div>
<div class="h-full">
<a-tabs v-model:active-key="activeTab" lazy-load class="no-content">
<a-tab-pane v-for="item of tabList" :key="item.key" :title="item.label"></a-tab-pane>
</a-tabs>
<a-divider margin="0"></a-divider>
<div v-if="activeTab === 'scenarioProcessorConfig'" class="mt-4">
<div v-if="activeTab === 'scenarioProcessorConfig'" class="h-[calc(100vh - 100px)] mt-4">
<a-alert class="mb-4"> {{ t('project.environmental.sceneAlertDesc') }} </a-alert>
<PreTab
v-if="props.activeType === 'pre'"
:show-associated-scene="showAssociatedScene"
:show-pre-post-request="!showAssociatedScene"
:active-tab="activeTab"
/>
<PostTab
v-if="props.activeType === 'post'"
:show-associated-scene="showAssociatedScene"
:show-pre-post-request="!showAssociatedScene"
:active-tab="activeTab"
/>
<a-scrollbar
:style="{
overflow: 'auto',
height: 'calc(100vh - 540px)',
}"
>
<PreTab
v-if="props.activeType === 'pre'"
:show-associated-scene="showAssociatedScene"
:show-pre-post-request="!showAssociatedScene"
:active-tab="activeTab"
/>
<PostTab
v-if="props.activeType === 'post'"
:show-associated-scene="showAssociatedScene"
:show-pre-post-request="!showAssociatedScene"
:active-tab="activeTab"
/>
</a-scrollbar>
</div>
<div v-if="activeTab === 'requestProcessorConfig'" class="mt-4">
<div v-if="activeTab === 'requestProcessorConfig'" class="mt-4 h-full">
<a-alert class="mb-4"> {{ t('project.environmental.requestAlertDesc') }} </a-alert>
<PreTab
v-if="props.activeType === 'pre'"
@ -45,7 +52,11 @@
import PostTab from './PostTab.vue';
import PreTab from './PreTab.vue';
import { getEnvironment } from '@/api/modules/api-test/common';
import { useI18n } from '@/hooks/useI18n';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
const store = useProjectEnvStore();
const { t } = useI18n();
@ -85,6 +96,14 @@
};
}
});
const currentEnvConfig = ref({});
/** 向孙组件提供属性 */
provide('currentEnvConfig', readonly(currentEnvConfig));
onBeforeMount(() => {
currentEnvConfig.value = store.currentEnvDetailInfo.config;
});
</script>
<style scoped lang="less">

View File

@ -182,9 +182,13 @@
</template>
<template #second>
<!-- 全局参数 -->
<AllParamBox v-if="showType === 'PROJECT' && activeKey === ALL_PARAM" />
<AllParamBox v-if="showType === 'PROJECT' && activeKey === ALL_PARAM" ref="globalEnvRef" />
<!-- 环境变量 -->
<EnvParamBox v-else-if="showType === 'PROJECT' && activeKey !== ALL_PARAM" @ok="initData()" />
<EnvParamBox
v-else-if="showType === 'PROJECT' && activeKey !== ALL_PARAM"
@reset-env="resetHandler"
@ok="initData()"
/>
<!-- 环境组 -->
<EnvGroupBox v-else-if="showType === 'PROJECT_GROUP'" @save-or-update="handleUpdateEnvGroup" />
</template>
@ -197,6 +201,11 @@
:default-selected-keys="[]"
is-array-column
:array-column="envList"
:title-props="{
selectableTitle: t('project.environmental.env.selectableTitle'),
systemTitle: t('project.environmental.env.systemTitle'),
selectedTitle: t('project.environmental.env.selectedTitle'),
}"
@confirm="(v) => handleEnvExport(v.map((item) => item.id))"
/>
</template>
@ -339,13 +348,13 @@
console.log(error);
}
};
const globalEnvRef = ref();
const handleSubmit = (shouldSearch: boolean) => {
if (shouldSearch) {
if (importAuthType.value === EnvAuthTypeEnum.GLOBAL && store.currentId === ALL_PARAM) {
store.initEnvDetail();
globalEnvRef.value.initEnvDetail();
} else if (importAuthType.value === EnvAuthTypeEnum.ENVIRONMENT && store.currentId !== ALL_PARAM) {
store.initEnvDetail();
globalEnvRef.value.initEnvDetail();
}
}
};
@ -358,12 +367,15 @@
//
const handleCreateEnv = () => {
const tmpArr = envList.value;
tmpArr.unshift({
id: NEW_ENV_PARAM,
name: t('project.environmental.newEnv'),
});
store.setCurrentId(NEW_ENV_PARAM);
envList.value = tmpArr;
const unSaveEnv = envList.value.filter((item) => item.id === NEW_ENV_PARAM).length < 1;
if (unSaveEnv) {
tmpArr.unshift({
id: NEW_ENV_PARAM,
name: t('project.environmental.newEnv'),
});
store.setCurrentId(NEW_ENV_PARAM);
envList.value = tmpArr;
}
};
//
const handleCreateGroup = () => {
@ -562,6 +574,21 @@
break;
}
};
function resetHandler() {
const unSaveEnv = envList.value.filter((item) => item.id === NEW_ENV_PARAM).length < 2;
// NEW_ENV_PARAMid
if (unSaveEnv) {
envList.value = envList.value.filter((item: any) => item.id !== NEW_ENV_PARAM);
const excludeMock = envList.value.filter((item) => !item.mock);
if (showType.value === 'PROJECT' && !excludeMock.length) {
store.setCurrentId(ALL_PARAM);
} else if (excludeMock.length) {
store.setCurrentId(excludeMock[0].id);
}
}
}
onMounted(() => {
initData(keyword.value, true);
});

View File

@ -3,7 +3,7 @@ export default {
'project.environmental.project': 'Project',
'project.environmental.envGroup': 'Environmental group',
'project.environmental.searchHolder': 'Please enter the environment name',
'project.environmental.allParam': 'All Parameters',
'project.environmental.allParam': 'Global request header',
'project.environmental.env': 'Environment',
'project.environmental.envListIsNull': 'No data, please click "+" above to create an environment',
'project.environmental.requestHeader': 'Request Header',
@ -108,4 +108,7 @@ export default {
'project.environmental.cover.enable': 'Enable: Import and cover the environment with the same name',
'project.environmental.cover.disable': 'Disable: Import and do not cover the environment with the same name',
'project.environmental.ENVIRONMENT': 'Environment',
'project.environmental.env.selectableTitle': 'Optional Environments',
'project.environmental.env.systemTitle': 'environment',
'project.environmental.env.selectedTitle': 'Selected environment',
};

View File

@ -3,11 +3,11 @@ export default {
'project.environmental.project': '项目',
'project.environmental.envGroup': '环境组',
'project.environmental.searchHolder': '请输入环境名称',
'project.environmental.allParam': '全局参数',
'project.environmental.allParam': '全局请求头',
'project.environmental.env': '环境',
'project.environmental.envListIsNull': '暂无数据,请点击上方“+”创建环境',
'project.environmental.requestHeader': '请求头',
'project.environmental.allParams': '全局参数',
'project.environmental.allParams': '全局请求',
'project.environmental.GLOBAL': '全局参数',
'project.environmental.ENVIRONMENT': '环境',
'project.environmental.ENVIRONMENT_PARAM': '全局参数',
@ -119,4 +119,7 @@ export default {
'project.environmental.cover': '覆盖',
'project.environmental.cover.enable': '开启: 环境名称重复则覆盖,不重复则新增',
'project.environmental.cover.disable': '关闭: 环境名称重复则不导入',
'project.environmental.env.selectableTitle': '可选环境',
'project.environmental.env.systemTitle': '环境',
'project.environmental.env.selectedTitle': '已选环境',
};

View File

@ -519,6 +519,16 @@
currentFormRules.options = selectOptions;
}
//
if (item.type === 'MEMBER' || item.type === 'MULTIPLE_MEMBER') {
selectOptions = [
{
label: t('system.organization.creator'),
value: 'CREATE_USER',
},
];
currentFormRules.options = selectOptions;
}
let initValue;
if (multipleType.includes(item.type)) {
const optionsIds = selectOptions.map((e: any) => e.value);