feat(环境管理): 环境管理环境组接口对接

This commit is contained in:
RubyLiu 2024-02-27 21:30:17 +08:00 committed by Craftsman
parent ec3ef79081
commit f516cacbb3
8 changed files with 199 additions and 71 deletions

View File

@ -3,13 +3,15 @@ import { FileItem } from '@arco-design/web-vue';
import MSR from '@/api/http/index'; import MSR from '@/api/http/index';
import * as envURL from '@/api/requrls/project-management/envManagement'; import * as envURL from '@/api/requrls/project-management/envManagement';
import { DragCase } from '@/models/caseManagement/featureCase';
import type { import type {
DragParam,
EnvDetailItem, EnvDetailItem,
EnvGroupListItem, EnvGroupListItem,
EnvGroupProjectListItem,
EnvListItem, EnvListItem,
EnvPluginListItem, EnvPluginListItem,
GlobalParams, GlobalParams,
GroupItem,
ProjectOptionItem, ProjectOptionItem,
} from '@/models/projectManagement/environmental'; } from '@/models/projectManagement/environmental';
import { OptionsItem } from '@/models/setting/log'; import { OptionsItem } from '@/models/setting/log';
@ -56,24 +58,27 @@ export function getDetailEnv(id: string) {
export function deleteEnv(data: EnvListItem) { export function deleteEnv(data: EnvListItem) {
return MSR.post<EnvListItem>({ url: envURL.deleteEnvUrl, data }); return MSR.post<EnvListItem>({ url: envURL.deleteEnvUrl, data });
} }
export function groupUpdateEnv(data: EnvListItem) { export function groupUpdateEnv(data: any) {
return MSR.post<EnvListItem>({ url: envURL.groupUpdateEnvUrl, data }); return MSR.post<EnvListItem>({ url: envURL.groupUpdateEnvUrl, data });
} }
export function groupListEnv(data: { projectId: string; keyword: string }) { export function groupListEnv(data: { projectId: string; keyword: string }) {
return MSR.post<EnvListItem[]>({ url: envURL.groupListEnvUrl, data }); return MSR.post<EnvListItem[]>({ url: envURL.groupListEnvUrl, data });
} }
export function groupEditPosEnv(data: EnvGroupListItem) { export function groupEditPosEnv(data: DragParam) {
return MSR.post<EnvListItem>({ url: envURL.groupEditPosEnvUrl, data }); return MSR.post<EnvListItem>({ url: envURL.groupEditPosEnvUrl, data });
} }
export function groupAddEnv(data: EnvGroupListItem) { export function groupAddEnv(data: any) {
return MSR.post<EnvListItem>({ url: envURL.groupAddEnvUrl, data }); return MSR.post<EnvListItem>({ url: envURL.groupAddEnvUrl, data });
} }
export function deleteEnvGroup(id: string) {
return MSR.get<EnvListItem>({ url: envURL.groupDeleteEnvUrl + id });
}
export function getEnvPlugin(projectId: string) { export function getEnvPlugin(projectId: string) {
return MSR.get<EnvPluginListItem[]>({ url: envURL.getEnvPluginUrl + projectId }); return MSR.get<EnvPluginListItem[]>({ url: envURL.getEnvPluginUrl + projectId });
} }
// 项目管理-项目组-详情 // 项目管理-项目组-详情
export function groupDetailEnv(id: string) { export function getGroupDetailEnv(id: string) {
return MSR.get<EnvDetailItem>({ url: `${envURL.groupDetailEnvUrl}${id}` }); return MSR.get<GroupItem>({ url: `${envURL.groupDetailEnvUrl}${id}` });
} }
export function groupDeleteEnv(data: EnvListItem) { export function groupDeleteEnv(data: EnvListItem) {
return MSR.post<EnvListItem>({ url: envURL.groupDeleteEnvUrl, data }); return MSR.post<EnvListItem>({ url: envURL.groupDeleteEnvUrl, data });

View File

@ -7,4 +7,5 @@ export enum EnvAuthTypeEnum {
GLOBAL = 'GLOBAL', // 全局参数 GLOBAL = 'GLOBAL', // 全局参数
ENVIRONMENT = 'ENVIRONMENT', // 环境 ENVIRONMENT = 'ENVIRONMENT', // 环境
ENVIRONMENT_PARAM = 'ENVIRONMENT_PARAM', // 环境参数 ENVIRONMENT_PARAM = 'ENVIRONMENT_PARAM', // 环境参数
ENVIRONMENT_GROUP = 'ENVIRONMENT_GROUP', // 环境组
} }

View File

@ -350,9 +350,10 @@ export interface ChangeHistoryItem {
createUserName: string; createUserName: string;
versionName: string; versionName: string;
} }
//取消前后置依赖关系
// 取消前后置依赖关系
export interface DeleteDependencyParams { export interface DeleteDependencyParams {
id: string; id: string;
caseId: string; caseId: string;
type: string; type: string;
} }

View File

@ -89,3 +89,23 @@ export interface EnvPluginListItem {
pluginId: string; pluginId: string;
script: EnvPluginScript; script: EnvPluginScript;
} }
export interface EnvGroupProjectItem {
projectId: string;
environmentId: string;
}
export interface GroupItem {
id: string;
name: string;
description: string;
projectId: string;
envGroupProject: EnvGroupProjectItem[];
}
export interface DragParam {
projectId: string;
targetId: string;
moveMode: string;
moveId: string;
}

View File

@ -1,7 +1,7 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import localforage from 'localforage'; import localforage from 'localforage';
import { getDetailEnv, getGlobalParamDetail, groupDetailEnv } from '@/api/modules/project-management/envManagement'; import { getDetailEnv, getGlobalParamDetail } from '@/api/modules/project-management/envManagement';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import { isArraysEqualWithOrder } from '@/utils/equal'; import { isArraysEqualWithOrder } from '@/utils/equal';
@ -21,8 +21,6 @@ const useProjectEnvStore = defineStore(
const currentEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情 const currentEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情
const backupEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情-备份 const backupEnvDetailInfo = ref<EnvDetailItem>({ projectId: '', name: '', config: {} }); // 当前选中的环境详情-备份
const allParamDetailInfo = ref<GlobalParams>(); // 全局参数详情 const allParamDetailInfo = ref<GlobalParams>(); // 全局参数详情
// 当前选中的项目组详情
const groupDetailInfo = ref<EnvDetailItem>();
const httpNoWarning = ref(true); const httpNoWarning = ref(true);
const getHttpNoWarning = computed(() => httpNoWarning.value); const getHttpNoWarning = computed(() => httpNoWarning.value);
@ -62,16 +60,6 @@ const useProjectEnvStore = defineStore(
console.log(e); console.log(e);
} }
} }
// 初始化项目组详情
async function initGroupDetail() {
try {
const id = currentGroupId.value;
groupDetailInfo.value = await groupDetailEnv(id);
} catch (e) {
// eslint-disable-next-line no-console
console.log(e);
}
}
// 初始化内容tab列表 // 初始化内容tab列表
async function initContentTabList(arr: ContentTabItem[]) { async function initContentTabList(arr: ContentTabItem[]) {
@ -127,13 +115,11 @@ const useProjectEnvStore = defineStore(
allParamDetailInfo, allParamDetailInfo,
currentEnvDetailInfo, currentEnvDetailInfo,
backupEnvDetailInfo, backupEnvDetailInfo,
groupDetailInfo,
setCurrentId, setCurrentId,
setCurrentGroupId, setCurrentGroupId,
setHttpNoWarning, setHttpNoWarning,
setAllParamDetailInfo, setAllParamDetailInfo,
initEnvDetail, initEnvDetail,
initGroupDetail,
initContentTabList, initContentTabList,
getContentTabList, getContentTabList,
setContentTabList, setContentTabList,

View File

@ -338,15 +338,16 @@
<span v-else></span> <span v-else></span>
</template> </template>
<template #host="{ record }"> <template #host="{ record }">
<span v-if="record.host.length === 1" class="text-[var(--color-text-4)]">{{ record.host }}</span> <!-- TODO: 等接口 -->
<!-- <span v-if="record.host.length === 1" class="text-[var(--color-text-4)]">{{ record.host }}</span>
<span <span
v-if="record.host.length > 1" v-if="record.host.length > 1"
class="cursor-pointer text-[var(--color-text-4)]" class="cursor-pointer text-[var(--color-text-4)]"
@click="showHostModal(record)" @click="showHostModal(record)"
> >
{{ t('common.more') }} {{ t('common.more') }}
</span> </span> -->
<span v-else></span> <span v-if="record.host">{{ record.host }}</span>
</template> </template>
<template #operation="{ record, rowIndex, columnConfig }"> <template #operation="{ record, rowIndex, columnConfig }">
<div class="flex flex-row items-center" :class="{ 'justify-end': columnConfig.align === 'right' }"> <div class="flex flex-row items-center" :class="{ 'justify-end': columnConfig.align === 'right' }">

View File

@ -36,6 +36,7 @@
v-model:params="innerParams" v-model:params="innerParams"
:show-setting="false" :show-setting="false"
:columns="columns" :columns="columns"
:selectable="false"
@change="handleParamTableChange" @change="handleParamTableChange"
/> />
</div> </div>
@ -53,14 +54,24 @@
</template> </template>
<script lang="ts" setup async> <script lang="ts" setup async>
import { ValidatedError } from '@arco-design/web-vue';
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue'; import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
import { getGroupDetailEnv, groupAddEnv, groupUpdateEnv } from '@/api/modules/project-management/envManagement';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore'; import { useAppStore } from '@/store';
import useProjectEnvStore, { NEW_ENV_GROUP } from '@/store/modules/setting/useProjectEnvStore';
import { EnvListItem } from '@/models/projectManagement/environmental';
const { t } = useI18n(); const { t } = useI18n();
const appStore = useAppStore();
const envGroupForm = ref(); const envGroupForm = ref();
const emit = defineEmits<{
(e: 'saveOrUpdate', id: string): void;
}>();
const form = reactive({ const form = reactive({
name: '', name: '',
description: '', description: '',
@ -98,24 +109,71 @@
}, },
]); ]);
const innerParams = ref<any[]>([]); const innerParams = ref<Record<string, any>[]>([]);
const canSave = ref(true); const canSave = ref(true);
const handleReset = () => { const handleReset = () => {
envGroupForm.value?.resetFields(); envGroupForm.value?.resetFields();
innerParams.value = [];
emit('saveOrUpdate', '');
}; };
const initDetail = async (id: string) => {
if (id === NEW_ENV_GROUP) {
form.name = '';
form.description = '';
innerParams.value = [];
return;
}
const detail = await getGroupDetailEnv(id);
if (detail) {
form.name = detail.name;
form.description = detail.description;
innerParams.value = detail.envGroupProject;
}
};
const handleSave = () => { const handleSave = () => {
envGroupForm.value?.validate(async (valid) => { envGroupForm.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
if (valid) { if (errors) {
console.log('form', form); return;
}
try {
const id = store.currentGroupId === NEW_ENV_GROUP ? undefined : store.currentGroupId;
const envGroupProject = innerParams.value.filter((item) => item.projectId && item.environmentId);
if (!envGroupProject.length) {
return;
}
const params = {
id,
name: form.name,
description: form.description,
projectId: appStore.currentProjectId,
envGroupProject,
};
let res: EnvListItem;
if (id) {
res = await groupUpdateEnv(params);
initDetail(res.id);
} else {
res = await groupAddEnv(params);
}
emit('saveOrUpdate', res.id);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
} }
}); });
}; };
function handleParamTableChange(resultArr: any[]) { function handleParamTableChange(resultArr: any[]) {
innerParams.value = [...resultArr]; innerParams.value = [...resultArr];
} }
watchEffect(() => {
if (store.currentGroupId) {
initDetail(store.currentGroupId);
}
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -121,7 +121,12 @@
</div> </div>
<!-- 环境组list--> <!-- 环境组list-->
<div v-if="evnGroupList.length"> <div v-if="evnGroupList.length">
<VueDraggable v-model="evnGroupList" ghost-class="ghost" handle=".drag-handle"> <VueDraggable
v-model="evnGroupList"
ghost-class="ghost"
handle=".drag-handle"
@end="handleEnvGroupPosChange"
>
<div <div
v-for="element in evnGroupList" v-for="element in evnGroupList"
:key="element.id" :key="element.id"
@ -153,8 +158,8 @@
/> />
</MsButton> </MsButton>
<MsMoreAction <MsMoreAction
:list="envMoreAction" :list="groupMoreAction"
@select="(value) => handleMoreAction(value, element.id, EnvAuthTypeEnum.ENVIRONMENT_PARAM)" @select="(value) => handleMoreAction(value, element.id, EnvAuthTypeEnum.ENVIRONMENT_GROUP)"
/> />
</div> </div>
</div> </div>
@ -176,7 +181,7 @@
<!-- 环境变量 --> <!-- 环境变量 -->
<EnvParamBox v-else-if="showType === 'PROJECT' && activeKey !== ALL_PARAM" /> <EnvParamBox v-else-if="showType === 'PROJECT' && activeKey !== ALL_PARAM" />
<!-- 环境组 --> <!-- 环境组 -->
<EnvGroupBox v-else-if="showType === 'PROJECT_GROUP'" /> <EnvGroupBox v-else-if="showType === 'PROJECT_GROUP'" @save-or-update="handleUpdateEnvGroup" />
</template> </template>
</MsSplitBox> </MsSplitBox>
</div> </div>
@ -184,6 +189,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { number } from 'echarts';
import { VueDraggable } from 'vue-draggable-plus'; import { VueDraggable } from 'vue-draggable-plus';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
@ -197,7 +203,13 @@
import EnvParamBox from './components/EnvParamBox.vue'; import EnvParamBox from './components/EnvParamBox.vue';
import RenamePop from './components/RenamePop.vue'; import RenamePop from './components/RenamePop.vue';
import { exportGlobalParam, groupListEnv, listEnv } from '@/api/modules/project-management/envManagement'; import {
deleteEnvGroup,
exportGlobalParam,
groupEditPosEnv,
groupListEnv,
listEnv,
} from '@/api/modules/project-management/envManagement';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import useProjectEnvStore, { import useProjectEnvStore, {
@ -211,6 +223,8 @@
import { PopVisible } from '@/models/setting/usergroup'; import { PopVisible } from '@/models/setting/usergroup';
import { EnvAuthScopeEnum, EnvAuthTypeEnum } from '@/enums/envEnum'; import { EnvAuthScopeEnum, EnvAuthTypeEnum } from '@/enums/envEnum';
import { SortableEvent } from 'sortablejs';
const { t } = useI18n(); const { t } = useI18n();
const store = useProjectEnvStore(); const store = useProjectEnvStore();
@ -237,10 +251,6 @@
// MoreAction // MoreAction
const envMoreAction: ActionsItem[] = [ const envMoreAction: ActionsItem[] = [
{
label: t('common.rename'),
eventTag: 'rename',
},
{ {
label: t('common.export'), label: t('common.export'),
eventTag: 'export', eventTag: 'export',
@ -254,6 +264,7 @@
eventTag: 'delete', eventTag: 'delete',
}, },
]; ];
// / MoreAction // / MoreAction
const allMoreAction: ActionsItem[] = [ const allMoreAction: ActionsItem[] = [
{ {
@ -266,6 +277,15 @@
}, },
]; ];
// moreAction
const groupMoreAction: ActionsItem[] = [
{
label: t('common.delete'),
danger: true,
eventTag: 'delete',
},
];
// //
const handleGlobalImport = () => { const handleGlobalImport = () => {
importVisible.value = true; importVisible.value = true;
@ -295,32 +315,6 @@
// //
const handleEnvImport = () => {}; const handleEnvImport = () => {};
// MoreAction
const handleMoreAction = (item: ActionsItem, id: string, scopeType: EnvAuthTypeEnum) => {
const { eventTag } = item;
switch (eventTag) {
case 'rename':
break;
case 'export':
if (scopeType === EnvAuthTypeEnum.GLOBAL) {
handleGlobalExport();
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT) {
handleEnvImport();
}
break;
case 'delete':
break;
case 'import':
if (scopeType === EnvAuthTypeEnum.GLOBAL) {
handleGlobalImport();
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT) {
handleEnvImport();
}
break;
default:
break;
}
};
// //
const handleCreateEnv = () => { const handleCreateEnv = () => {
const tmpArr = envList.value; const tmpArr = envList.value;
@ -341,7 +335,6 @@
store.setCurrentGroupId(NEW_ENV_GROUP); store.setCurrentGroupId(NEW_ENV_GROUP);
evnGroupList.value = tmpArr; evnGroupList.value = tmpArr;
}; };
const initGroupList = async (keywordStr = '') => { const initGroupList = async (keywordStr = '') => {
try { try {
evnGroupList.value = await groupListEnv({ projectId: appStore.currentProjectId, keyword: keywordStr }); evnGroupList.value = await groupListEnv({ projectId: appStore.currentProjectId, keyword: keywordStr });
@ -351,6 +344,44 @@
} }
}; };
//
const handleUpdateEnvGroup = async (id: string) => {
await initGroupList();
store.setCurrentGroupId(id);
};
//
const handleEnvGroupPosChange = async (event: SortableEvent) => {
try {
const { oldIndex, newIndex } = event;
if (oldIndex === newIndex) {
return;
}
const _oldIndex = oldIndex as number;
const _newIndex = newIndex as number;
const params = {
projectId: appStore.currentProjectId,
targetId: evnGroupList.value[_newIndex].id,
moveId: evnGroupList.value[_oldIndex].id,
moveMode: _oldIndex > _newIndex ? 'BEFORE' : 'AFTER',
};
await groupEditPosEnv(params);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
};
//
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 = '') => { const initData = async (keywordStr = '') => {
try { try {
envList.value = await listEnv({ projectId: appStore.currentProjectId, keyword: keywordStr }); envList.value = await listEnv({ projectId: appStore.currentProjectId, keyword: keywordStr });
@ -392,15 +423,40 @@
const handleListItemClickGroup = (element: EnvListItem) => { const handleListItemClickGroup = (element: EnvListItem) => {
const { id } = element; const { id } = element;
store.setCurrentGroupId(id); store.setCurrentGroupId(id);
if (id !== NEW_ENV_GROUP) {
//
store.initGroupDetail();
}
}; };
function searchData() { function searchData() {
initData(keyword.value); 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();
}
break;
case 'delete':
if (scopeType === EnvAuthTypeEnum.ENVIRONMENT_GROUP) {
handleDeleteEnvGroup(id);
}
break;
case 'import':
if (scopeType === EnvAuthTypeEnum.GLOBAL) {
handleGlobalImport();
} else if (scopeType === EnvAuthTypeEnum.ENVIRONMENT) {
handleEnvImport();
}
break;
default:
break;
}
};
onMounted(() => { onMounted(() => {
initData(); initData();
}); });