refactor(项目管理): 环境变量接口对接

This commit is contained in:
RubyLiu 2024-02-29 19:39:34 +08:00 committed by Craftsman
parent e28284be97
commit 213de72e3b
16 changed files with 357 additions and 172 deletions

View File

@ -3,11 +3,9 @@ import { FileItem } from '@arco-design/web-vue';
import MSR from '@/api/http/index';
import * as envURL from '@/api/requrls/project-management/envManagement';
import { DragCase } from '@/models/caseManagement/featureCase';
import type {
DragParam,
EnvDetailItem,
EnvGroupListItem,
EnvListItem,
EnvPluginListItem,
GlobalParams,
@ -27,14 +25,17 @@ 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: EnvListItem; fileList: FileItem[] }) {
return MSR.uploadFile({ url: envURL.importEnvUrl }, data, '', true);
export function importEnv(data: { request: any; fileList: FileItem[] }) {
return MSR.uploadFile({ url: envURL.importEnvUrl }, data, '', false);
}
export function getEntryEnv(data: EnvListItem) {
return MSR.post<EnvListItem>({ url: envURL.getEntryEnvUrl, data });
}
export function exportEnv(id: string) {
return MSR.get<EnvListItem>({ url: envURL.exportEnvUrl + id, responseType: 'blob' }, { isTransformResponse: false });
export function exportEnv(selectIds: string[]) {
return MSR.post<Blob>(
{ url: envURL.exportEnvUrl, data: { selectIds }, responseType: 'blob' },
{ isTransformResponse: false }
);
}
export function editPosEnv(data: EnvListItem) {
return MSR.post<EnvListItem>({ url: envURL.editPosEnvUrl, data });
@ -55,8 +56,8 @@ export function addEnv(data: EnvListItem) {
export function getDetailEnv(id: string) {
return MSR.get<EnvDetailItem>({ url: envURL.detailEnvUrl + id });
}
export function deleteEnv(data: EnvListItem) {
return MSR.post<EnvListItem>({ url: envURL.deleteEnvUrl, data });
export function deleteEnv(id: string) {
return MSR.get<EnvListItem>({ url: envURL.deleteEnvUrl + id });
}
export function groupUpdateEnv(data: any) {
return MSR.post<EnvListItem>({ url: envURL.groupUpdateEnvUrl, data });

View File

@ -125,6 +125,8 @@
import { useI18n } from '@/hooks/useI18n';
import { EnvListItem } from '@/models/projectManagement/environmental';
import { MsExportDrawerMap, MsExportDrawerOption } from './types';
const { t } = useI18n();
@ -136,6 +138,8 @@
allData: MsExportDrawerMap;
// keys
defaultSelectedKeys?: string[];
isArrayColumn?: boolean;
arrayColumn?: EnvListItem[];
}
const props = withDefaults(defineProps<MsExportDrawerProps>(), {
@ -161,6 +165,15 @@
});
const systemList = computed(() => {
if (props.isArrayColumn && props.arrayColumn) {
return props.arrayColumn.map((item) => {
return {
key: item.id,
text: item.name,
columnType: 'system',
};
});
}
const { systemColumns } = props.allData;
if (systemColumns) {
return Object.keys(systemColumns).map((key) => {

View File

@ -10,4 +10,5 @@ export interface MsExportDrawerOption {
text: string;
key: string;
columnType: string;
[key: string]: any;
}

View File

@ -1,3 +1,5 @@
import { ExecuteConditionProcessor } from '../apiTest/debug';
export interface EnvListItem {
name: string;
id: string;
@ -29,17 +31,19 @@ export interface DataSourceItem {
export interface EnvConfigItem {
[key: string]: any;
}
export interface ProcessorConfig {
apiProcessorConfig: ExecuteConditionProcessor[];
}
export interface EnvConfig {
commonParams?: EnvConfigItem;
commmonVariables?: EnvConfigItem[];
httpConfig?: EnvConfigItem[];
dataSource?: DataSourceItem[];
hostConfig?: EnvConfigItem;
authConfig?: EnvConfigItem;
preProcessorConfig?: EnvConfigItem;
postProcessorConfig?: EnvConfigItem;
assertionConfig?: EnvConfigItem;
pluginConfigMap?: EnvConfigItem;
commmonVariables: EnvConfigItem[];
httpConfig: EnvConfigItem[];
dataSources: DataSourceItem[];
hostConfig: EnvConfigItem;
preProcessorConfig: ProcessorConfig;
postProcessorConfig: ProcessorConfig;
assertionConfig: EnvConfigItem[];
pluginConfigMap: EnvConfigItem;
}
export interface EnvDetailItem {
id?: string;
@ -109,3 +113,13 @@ export interface DragParam {
moveMode: string;
moveId: string;
}
export interface HttpForm {
id?: string;
description?: string;
hostname: string;
enableCondition: string;
path: string;
operator: string;
headerParams: any[];
}

View File

@ -10,16 +10,42 @@ import { ContentTabItem, ContentTabsMap, EnvDetailItem, GlobalParams } from '@/m
export const ALL_PARAM = 'allParam';
export const NEW_ENV_PARAM = 'newEnvParam';
export const NEW_ENV_GROUP = 'newEnvGroup';
const envParmasDefaultConfig = {
commmonVariables: [],
httpConfig: [],
dataSources: [],
hostConfig: {
enable: false,
hosts: [],
},
preProcessorConfig: {
apiProcessorConfig: [],
},
postProcessorConfig: {
apiProcessorConfig: [],
},
assertionConfig: [],
pluginConfigMap: {},
};
const useProjectEnvStore = defineStore(
'projectEnv',
() => {
// 项目中的key值
const currentId = ref<string>('1052215449649153');
const currentId = ref<string>('');
// 项目组选中的key值
const currentGroupId = ref<string>('');
const currentEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情
const backupEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情-备份
// 当前选中的环境详情
const currentEnvDetailInfo = ref<EnvDetailItem>({
projectId: '',
name: '',
config: envParmasDefaultConfig,
});
const backupEnvDetailInfo = ref<EnvDetailItem>({
projectId: '',
name: '',
config: envParmasDefaultConfig,
});
const allParamDetailInfo = ref<GlobalParams>(); // 全局参数详情
const httpNoWarning = ref(true);
const getHttpNoWarning = computed(() => httpNoWarning.value);
@ -46,14 +72,22 @@ const useProjectEnvStore = defineStore(
const appStore = useAppStore();
try {
if (id === NEW_ENV_PARAM) {
currentEnvDetailInfo.value = { projectId: appStore.currentProjectId, name: '', config: {} };
backupEnvDetailInfo.value = { projectId: appStore.currentProjectId, name: '', config: {} };
currentEnvDetailInfo.value = {
projectId: appStore.currentProjectId,
name: '',
config: envParmasDefaultConfig,
};
backupEnvDetailInfo.value = {
projectId: appStore.currentProjectId,
name: '',
config: envParmasDefaultConfig,
};
} else if (id === ALL_PARAM) {
allParamDetailInfo.value = await getGlobalParamDetail(appStore.currentProjectId);
} else if (id !== ALL_PARAM && id) {
const tmpObj = await getDetailEnv(id);
currentEnvDetailInfo.value = tmpObj;
backupEnvDetailInfo.value = JSON.parse(JSON.stringify(tmpObj));
backupEnvDetailInfo.value = tmpObj;
}
} catch (e) {
// eslint-disable-next-line no-console

View File

@ -209,7 +209,7 @@
/>
</div>
</template>
<template #tag="{ record, columnConfig, rowIndex }">
<template #tag="{ record, columnConfig }">
<a-popover
position="tl"
:disabled="record[columnConfig.dataIndex as string].length === 0"
@ -228,7 +228,6 @@
:max-tag-count="1"
input-class="param-input"
size="mini"
@change="() => addTableLine(rowIndex)"
/>
</a-popover>
</template>

View File

@ -42,7 +42,7 @@
import MsUpload from '@/components/pure/ms-upload/index.vue';
import { importGlobalParam } from '@/api/modules/project-management/envManagement';
import { importEnv, importGlobalParam } from '@/api/modules/project-management/envManagement';
import { useI18n } from '@/hooks/useI18n';
import { EnvAuthTypeEnum } from '@/enums/envEnum';
@ -73,10 +73,14 @@
try {
confirmLoading.value = true;
const params = {
request: null,
request: {},
fileList: fileList.value,
};
await importGlobalParam(params);
if (props.type === EnvAuthTypeEnum.GLOBAL) {
await importGlobalParam(params);
} else if (props.type === EnvAuthTypeEnum.ENVIRONMENT) {
await importEnv(params);
}
Message.success(t('common.importSuccess'));
handleCancel(true);
} catch (error) {

View File

@ -3,7 +3,6 @@
<a-button type="outline" @click="handleAdd">{{ t('project.environmental.database.addDatabase') }}</a-button>
<a-input-search
v-model="keyword"
:placeholder="t('system.user.searchUser')"
class="w-[240px]"
allow-clear
@press-enter="fetchData"
@ -23,9 +22,10 @@
</MsBaseTable>
<AddDatabaseModal
v-model:visible="addVisible"
v-model="currentDatabase"
:current-database="currentDatabase"
:current-id="currentId"
@close="addVisible = false"
@add-or-update="handleAddOrUpdate"
/>
</template>
@ -34,7 +34,7 @@
import MsButton from '@/components/pure/ms-button/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { MsTableColumn } from '@/components/pure/ms-table/type';
import { MsTableColumn, MsTableDataItem } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
@ -45,18 +45,15 @@
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
import { BugListItem } from '@/models/bug-management';
import { CommonList } from '@/models/common';
import { DataSourceItem } from '@/models/projectManagement/environmental';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
const store = useProjectEnvStore();
const innerParam = computed({
get: () => (store.currentEnvDetailInfo.config.dataSource || []) as DataSourceItem[],
set: (value: DataSourceItem[] | undefined) => {
store.currentEnvDetailInfo.config.dataSource = value;
},
});
const innerParam = computed(() => store.currentEnvDetailInfo.config.dataSources || []);
const keyword = ref('');
const tableStore = useTableStore();
const addVisible = ref(false);
@ -121,15 +118,21 @@
},
];
await tableStore.initColumn(TableKeyEnum.PROJECT_MANAGEMENT_ENV_ENV_HTTP, columns);
const { propsRes, propsEvent } = useTable(undefined, {
tableKey: TableKeyEnum.PROJECT_MANAGEMENT_ENV_ENV_HTTP,
scroll: { x: '100%' },
selectable: false,
noDisable: true,
showSetting: true,
showPagination: false,
showMode: false,
});
const { propsRes, propsEvent } = useTable(
() =>
Promise.resolve([]) as unknown as Promise<
MsTableDataItem<DataSourceItem> | CommonList<MsTableDataItem<DataSourceItem>>
>,
{
tableKey: TableKeyEnum.PROJECT_MANAGEMENT_ENV_ENV_HTTP,
scroll: { x: '100%' },
selectable: false,
showSetting: true,
showPagination: false,
showMode: false,
isSimpleSetting: true,
}
);
const moreActionList: ActionsItem[] = [
{
@ -140,7 +143,10 @@
];
const handleSingleDelete = (record?: TableData) => {
console.log('handleSingleDelete', record);
if (record) {
const index = innerParam.value.findIndex((item) => item.id === record.id);
innerParam.value.splice(index, 1);
}
};
function handleMoreActionSelect(item: ActionsItem, record: BugListItem) {
@ -150,22 +156,37 @@
}
const handleCopy = (record: any) => {
console.log('handleCopy', record);
addVisible.value = true;
currentId.value = '';
currentDatabase.value = { ...record, id: '' };
};
const handleEdit = (record: any) => {
addVisible.value = true;
currentId.value = record.id;
};
const handleAdd = () => {
currentDatabase.value = { name: '', dbUrl: '', username: '' };
addVisible.value = true;
};
const fetchData = () => {};
const initData = () => {
propsRes.value.data = innerParam.value;
const fetchData = () => {
if (keyword.value) {
propsRes.value.data = innerParam.value.filter((item) => item.name.includes(keyword.value));
} else {
propsRes.value.data = innerParam.value;
}
};
onMounted(() => {
initData();
const handleAddOrUpdate = (data: DataSourceItem, cb: (v: boolean) => void) => {
if (data.id) {
const index = innerParam.value.findIndex((item) => item.id === data.id);
store.currentEnvDetailInfo.config.dataSources[index] = data;
} else {
data.id = new Date().getTime().toString();
store.currentEnvDetailInfo.config.dataSources.push(data);
}
cb(true);
};
watch(innerParam.value, () => {
fetchData();
});
</script>

View File

@ -28,7 +28,6 @@
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
import { EnvConfigItem } from '@/models/projectManagement/environmental';
import { FakeTableListItem } from '@/models/projectManagement/menuManagement';
const { t } = useI18n();
@ -37,7 +36,6 @@
const currentList = computed({
get: () => store.currentEnvDetailInfo.config.hostConfig || {},
set: (value: EnvConfigItem) => {
console.log(value);
store.currentEnvDetailInfo.config.hostConfig = value || {};
},
});

View File

@ -39,7 +39,7 @@
</div>
</template>
</MsBaseTable>
<AddHttpDrawer v-model:visible="addVisible" :current-id="currentId" @close="addVisible = false" />
<AddHttpDrawer v-model:visible="addVisible" :current-obj="currentObj" @close="addVisible = false" />
</template>
<script lang="ts" async setup>
@ -58,6 +58,7 @@
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
import { BugListItem } from '@/models/bug-management';
import { HttpForm } from '@/models/projectManagement/environmental';
import { TableKeyEnum } from '@/enums/tableEnum';
const { t } = useI18n();
@ -67,15 +68,14 @@
const showTitle = computed(() => store.httpNoWarning);
const tableStore = useTableStore();
const addVisible = ref(false);
const currentId = ref('');
const innerParam = computed({
set: (value: TableData[]) => {
store.currentEnvDetailInfo.config.httpConfig = value;
},
get: () => store.currentEnvDetailInfo.config.httpConfig || [],
const currentObj = ref<HttpForm>({
id: '',
hostname: '',
enableCondition: 'none',
path: '',
operator: '',
headerParams: [],
});
const columns: MsTableColumn = [
{
title: 'project.environmental.http.host',
@ -144,7 +144,12 @@
];
const handleSingleDelete = (record?: TableData) => {
console.log('handleSingleDelete', record);
if (record) {
const index = store.currentEnvDetailInfo.config.httpConfig.findIndex((item) => item.id === record.id);
if (index > -1) {
store.currentEnvDetailInfo.config.httpConfig.splice(index, 1);
}
}
};
function handleMoreActionSelect(item: ActionsItem, record: BugListItem) {
@ -152,26 +157,32 @@
handleSingleDelete(record);
}
}
const handleCopy = (record: any) => {
console.log('handleCopy', record);
currentObj.value = record;
currentObj.value.id = '';
addVisible.value = true;
};
const handleEdit = (record: any) => {
currentObj.value = record;
addVisible.value = true;
currentId.value = record.id;
};
const handleAddHttp = () => {
currentObj.value = {
id: '',
hostname: '',
enableCondition: 'none',
path: '',
operator: '',
headerParams: [],
};
addVisible.value = true;
};
const handleNoWarning = () => {
store.setHttpNoWarning(false);
};
const initData = () => {
propsRes.value.data = innerParam.value;
};
onMounted(() => {
initData();
watch(store.currentEnvDetailInfo.config.httpConfig, () => {
propsRes.value.data = store.currentEnvDetailInfo.config.httpConfig;
});
</script>

View File

@ -1,20 +1,27 @@
<template>
<PostTab v-model:config="params" layout="horizontal" />
<condition
v-model:list="innerParams"
:condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]"
add-text="apiTestDebug.postCondition"
response=""
:height-used="600"
>
</condition>
</template>
<script lang="ts" setup>
import PostTab from '@/views/api-test/components/requestComposition/postcondition.vue';
import condition from '@/views/api-test/components/condition/index.vue';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
const store = useProjectEnvStore();
import { RequestConditionProcessor } from '@/enums/apiEnum';
// TODO:
const params = computed<any>({
const store = useProjectEnvStore();
const innerParams = computed({
set: (value: any) => {
store.currentEnvDetailInfo.config.postProcessorConfig = value;
store.currentEnvDetailInfo.config.postProcessorConfig.apiProcessorConfig = value || [];
},
get: () => store.currentEnvDetailInfo.config.postProcessorConfig || {},
get: () => store.currentEnvDetailInfo.config.postProcessorConfig.apiProcessorConfig || [],
});
</script>

View File

@ -1,20 +1,27 @@
<template>
<PreTab v-model:config="params" layout="horizontal" />
<condition
v-model:list="innerParams"
:condition-types="[RequestConditionProcessor.SCRIPT, RequestConditionProcessor.SQL]"
add-text="apiTestDebug.precondition"
response=""
:height-used="600"
>
</condition>
</template>
<script lang="ts" setup>
import PreTab from '@/views/api-test/components/requestComposition/precondition.vue';
import condition from '@/views/api-test/components/condition/index.vue';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
const store = useProjectEnvStore();
import { RequestConditionProcessor } from '@/enums/apiEnum';
// TODO:
const params = computed<any>({
const store = useProjectEnvStore();
const innerParams = computed({
set: (value: any) => {
store.currentEnvDetailInfo.config.preProcessorConfig = value;
store.currentEnvDetailInfo.config.preProcessorConfig.apiProcessorConfig = value || [];
},
get: () => store.currentEnvDetailInfo.config.preProcessorConfig || {},
get: () => store.currentEnvDetailInfo.config.preProcessorConfig.apiProcessorConfig || [],
});
</script>

View File

@ -1,5 +1,12 @@
<template>
<MsDrawer :width="891" :visible="visible" unmount-on-close :mask="false" @cancel="emit('close')">
<MsDrawer
:width="891"
:visible="visible"
unmount-on-close
:mask="false"
@confirm="handleAddOrUpdate"
@cancel="emit('close')"
>
<template #title>
<div>{{ title }}</div>
</template>
@ -22,12 +29,6 @@
</template>
</a-input>
</a-form-item>
<a-form-item class="mb-[16px]" field="applyModule" :label="t('project.environmental.http.applyModule')">
<a-checkbox-group v-model="form.applyModule">
<a-checkbox value="apiTest">{{ t('menu.apiTest') }}</a-checkbox>
<a-checkbox value="uiTest">{{ t('menu.uiTest') }}</a-checkbox>
</a-checkbox-group>
</a-form-item>
<a-form-item class="mb-[16px]" field="enableCondition" :label="t('project.environmental.http.enableCondition')">
<a-select v-model:model-value="form.enableCondition">
<a-option value="none">{{ t('project.environmental.http.none') }}</a-option>
@ -36,7 +37,7 @@
</a-select>
</a-form-item>
<!-- 接口模块选择 -->
<a-form-item
<!-- <a-form-item
v-if="showApiModule"
class="mb-[16px]"
field="apiModule"
@ -47,9 +48,12 @@
<a-select v-model:model-value="form.apiModule" multiple :placeholder="t('common.pleaseSelect')">
<a-option value="none">{{ t('project.environmental.http.none') }}</a-option>
</a-select>
</a-form-item> -->
<a-form-item class="mb-[16px]" field="description" :label="t('project.environmental.http.description')">
<a-input />
</a-form-item>
<!-- 选择UI测试模块 -->
<a-form-item
<!-- <a-form-item
v-if="showUIModule"
class="mb-[16px]"
field="enableCondition"
@ -60,7 +64,7 @@
<a-select v-model:model-value="form.uiModule" multiple :placeholder="t('common.pleaseSelect')">
<a-option value="none">{{ t('project.environmental.http.none') }}</a-option>
</a-select>
</a-form-item>
</a-form-item> -->
<!-- 路径 -->
<a-form-item
v-if="showPathInput"
@ -88,7 +92,7 @@
</a-input>
</a-form-item>
</a-form>
<RequestHeader :params="headerParams" />
<RequestHeader :params="form.headerParams" />
</MsDrawer>
</template>
@ -100,57 +104,51 @@
import RequestHeader from '../../requestHeader/index.vue';
import { useI18n } from '@/hooks/useI18n';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
import { HttpForm } from '@/models/projectManagement/environmental';
const props = defineProps<{
currentId?: string;
currentObj: HttpForm;
}>();
const store = useProjectEnvStore();
const emit = defineEmits<{
(e: 'close'): void;
}>();
const form = reactive<{
hostname: string;
applyModule: string[];
enableCondition: string;
apiModule: string[];
uiModule: string[];
path: string;
operator: string;
}>({
const form = ref<HttpForm>({
id: '',
hostname: '',
applyModule: [],
enableCondition: 'none',
apiModule: [],
uiModule: [],
path: '',
operator: '',
headerParams: [],
});
const httpRef = ref();
const showApiModule = computed(() => form.enableCondition === 'module' && form.applyModule.includes('apiTest'));
const showUIModule = computed(() => form.enableCondition === 'module' && form.applyModule.includes('uiTest'));
const showPathInput = computed(() => form.enableCondition === 'path');
const headerParams = ref<[]>([]);
const showPathInput = computed(() => form.value.enableCondition === 'path');
const visible = defineModel('visible', { required: true, type: Boolean, default: false });
const { t } = useI18n();
const isEdit = computed(() => !!props.currentId);
const isEdit = computed(() => !!props.currentObj.id);
const title = computed(() => {
return isEdit.value ? t('project.environmental.http.edit') : t('project.environmental.http.add');
});
watchEffect(() => {
if (showApiModule.value) {
form.apiModule = [];
const handleAddOrUpdate = () => {
if (form.value.id) {
const index = store.currentEnvDetailInfo.config.httpConfig.findIndex((item) => item.id === form.value.id);
store.currentEnvDetailInfo.config.httpConfig.splice(index, 1, form.value);
} else {
store.currentEnvDetailInfo.config.httpConfig.push(form);
}
if (showUIModule.value) {
form.uiModule = [];
}
});
emit('close');
};
</script>
<style lang="less" scoped>

View File

@ -24,7 +24,12 @@
asterisk-position="end"
:rules="[{ required: true, message: t('project.environmental.database.nameIsRequire') }]"
>
<a-input v-model="form.name" allow-clear :placeholder="t('project.environmental.database.namePlaceholder')" />
<a-input
v-model="form.name"
:max-length="255"
allow-clear
:placeholder="t('project.environmental.database.namePlaceholder')"
/>
</a-form-item>
<a-form-item field="driverId" asterisk-position="end" :label="t('project.environmental.database.driver')">
<a-select v-model="form.driverId" :options="driverOption" />
@ -37,7 +42,7 @@
:extra="t('project.environmental.database.urlExtra')"
:rules="[{ required: true, message: t('project.environmental.database.urlIsRequire') }]"
>
<a-input v-model="form.dbUrl" allow-clear :placeholder="t('common.pleaseInput')" />
<a-input v-model="form.dbUrl" :max-length="255" allow-clear :placeholder="t('common.pleaseInput')" />
</a-form-item>
<a-form-item
field="username"
@ -111,7 +116,7 @@
const { t } = useI18n();
const props = defineProps<{
modelValue: DataSourceItem;
currentDatabase: DataSourceItem;
visible: boolean;
}>();
@ -124,6 +129,7 @@
const emit = defineEmits<{
(e: 'cancel', shouldSearch: boolean): void;
(e: 'addOrUpdate', data: DataSourceItem, cb: (v: boolean) => void): void;
}>();
const currentVisible = defineModel('visible', {
@ -131,11 +137,19 @@
type: Boolean,
});
const form = defineModel<DataSourceItem>('modelValue', {
required: true,
const form = ref<DataSourceItem>({
id: '',
name: '',
driverId: '',
dbUrl: '',
username: '',
password: '',
poolMax: 1,
timeout: 1000,
enable: true,
});
const isEdit = computed(() => form.value.id);
const isEdit = computed(() => !!props.currentDatabase.id);
const getDriverOption = async () => {
try {
@ -188,19 +202,17 @@
});
const formReset = () => {
if (!isEdit.value) {
form.value = {
id: '',
name: '',
driverId: '',
dbUrl: '',
username: '',
password: '',
poolMax: 1,
timeout: 1000,
enable: true,
};
}
form.value = {
id: '',
name: '',
driverId: '',
dbUrl: '',
username: '',
password: '',
poolMax: 1,
timeout: 1000,
enable: true,
};
};
const handleCancel = (shouldSearch: boolean) => {
emit('cancel', shouldSearch);
@ -215,13 +227,14 @@
}
try {
loading.value = true;
Message.success(
isEdit.value
? t('project.environmental.database.updateProjectSuccess')
: t('project.environmental.database.createProjectSuccess')
);
handleCancel(true);
emit('addOrUpdate', form.value, (v: boolean) => {
Message.success(
isEdit.value
? t('project.environmental.database.updateDataSourceSuccess')
: t('project.environmental.database.createDataSourceSuccess')
);
handleCancel(v);
});
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
@ -234,8 +247,15 @@
getDriverOption();
};
watchEffect(() => {
if (props.visible) {
initData();
initData();
if (props.currentDatabase?.id) {
//
if (props.currentDatabase) {
form.value = { ...props.currentDatabase };
}
} else {
//
formReset();
}
});
</script>

View File

@ -186,12 +186,22 @@
</MsSplitBox>
</div>
<CommonImportPop v-model:visible="importVisible" :type="importAuthType" @submit="handleSubmit" />
<MsExportDrawer
v-model:visible="envExportVisible"
:all-data="exportOptionData"
:default-selected-keys="[]"
is-array-column
:array-column="envList"
@confirm="(v) => handleEnvExport(v.map((item) => item.id))"
/>
</template>
<script lang="ts" setup>
import { VueDraggable } from 'vue-draggable-plus';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsExportDrawer from '@/components/pure/ms-export-drawer/index.vue';
import { MsExportDrawerMap } from '@/components/pure/ms-export-drawer/types';
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsMoreAction from '@/components/pure/ms-table-more-action/index.vue';
@ -203,7 +213,9 @@
import RenamePop from './components/RenamePop.vue';
import {
deleteEnv,
deleteEnvGroup,
exportEnv,
exportGlobalParam,
groupEditPosEnv,
groupListEnv,
@ -247,6 +259,12 @@
const importVisible = ref<boolean>(false);
//
const importAuthType = ref<EnvAuthTypeEnum>(EnvAuthTypeEnum.GLOBAL);
// Drawer
const envExportVisible = ref<boolean>(false);
// option
const exportOptionData = ref<MsExportDrawerMap>({
systemColumns: {},
});
// MoreAction
const envMoreAction: ActionsItem[] = [
@ -301,6 +319,16 @@
console.log(error);
}
};
//
const handleEnvExport = async (id: string | string[]) => {
try {
const blob = await exportEnv(Array.isArray(id) ? id : [id]);
downloadByteFile(blob, 'EnvParam.json');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};
const handleSubmit = (shouldSearch: boolean) => {
if (shouldSearch) {
@ -312,7 +340,10 @@
}
};
//
const handleEnvImport = () => {};
const handleEnvImport = () => {
importVisible.value = true;
importAuthType.value = EnvAuthTypeEnum.ENVIRONMENT;
};
//
const handleCreateEnv = () => {
@ -370,17 +401,6 @@
}
};
//
const handleDeleteEnvGroup = async (id: string) => {
try {
await deleteEnvGroup(id);
await initGroupList();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};
const initData = async (keywordStr = '') => {
try {
envList.value = await listEnv({ projectId: appStore.currentProjectId, keyword: keywordStr });
@ -393,6 +413,35 @@
}
};
function searchData() {
initData(keyword.value);
}
//
const handleDeleteEnv = async (id: string) => {
try {
await deleteEnv(id);
if (store.currentId === id) {
store.setCurrentId('');
}
searchData();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};
//
const handleDeleteEnvGroup = async (id: string) => {
try {
await deleteEnvGroup(id);
await initGroupList();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
};
function changeShowType(value: string | number | boolean) {
if (value === 'PROJECT_GROUP') {
initGroupList();
@ -424,25 +473,26 @@
store.setCurrentGroupId(id);
};
function searchData() {
initData(keyword.value);
}
// MoreAction
const handleMoreAction = (item: ActionsItem, id: string, scopeType: EnvAuthTypeEnum) => {
const { eventTag } = item;
switch (eventTag) {
case 'export':
if (scopeType === EnvAuthTypeEnum.GLOBAL) {
//
handleGlobalExport();
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT) {
handleEnvImport();
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT_PARAM) {
handleEnvImport();
//
handleEnvExport(id);
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT) {
envExportVisible.value = true;
}
break;
case 'delete':
if (scopeType === EnvAuthTypeEnum.ENVIRONMENT_GROUP) {
handleDeleteEnvGroup(id);
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT_PARAM) {
handleDeleteEnv(id);
}
break;
case 'import':
@ -493,9 +543,11 @@
}
}
.env-row {
@apply flex flex-row justify-between;
@apply flex flex-row justify-between;
&-extra {
@apply relative hidden;
@apply relative;
opacity: 0;
}
&:hover {
.env-row-extra {

View File

@ -62,8 +62,12 @@ export default {
'project.environmental.http.uiModuleSelect': '选择UI测试模块',
'project.environmental.http.pathRequired': '路径必填',
'project.environmental.http.pathPlaceholder': '请输入路径',
'project.environmental.http.description': '描述',
'project.environmental.database.title': '数据库',
'project.environmental.database.addDatabase': '添加数据源',
'project.environmental.database.updateDatabase': '更新数据源{name}',
'project.environmental.database.updateDataSourceSuccess': '更新数据源成功',
'project.environmental.database.createDataSourceSuccess': '创建数据源成功',
'project.environmental.database.name': '数据源名称',
'project.environmental.database.nameIsRequire': '数据源名称不能为空',
'project.environmental.database.namePlaceholder': '请输入数据源名称',
@ -77,6 +81,7 @@ export default {
'project.environmental.database.urlExtra': '执行多条 SQL 语句需配置 allowMultiQueries=true',
'project.environmental.database.urlIsRequire': '数据库连接 URL 必填',
'project.environmental.database.testConnection': '测试连接',
'project.environmental.database.testConnectionSuccess': '连接成功',
'project.environmental.host.config': 'Host 配置',
'project.environmental.host.ip': 'IP',
'project.environmental.host.ipPlaceholder': '请输入 IP 地址',