feat(项目管理): 环境管理环境组

This commit is contained in:
RubyLiu 2024-01-12 21:30:13 +08:00 committed by Craftsman
parent 2f0ff19744
commit 65b1266370
5 changed files with 269 additions and 42 deletions

View File

@ -2,3 +2,15 @@ export interface EnvListItem {
name: string; name: string;
id: string; id: string;
} }
export interface EnvGroupProjectListItem {
name: string;
env: string;
host: string;
description: string;
}
export interface EnvGroupListItem {
name: string;
id: string;
projectList: EnvGroupProjectListItem[];
}

View File

@ -1,5 +1,7 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { EnvGroupListItem } from '@/models/projectManagement/environmental';
export const ALL_PARAM = 'allParam'; export const ALL_PARAM = 'allParam';
const useProjectEnvStore = defineStore( const useProjectEnvStore = defineStore(
@ -7,8 +9,11 @@ const useProjectEnvStore = defineStore(
() => { () => {
const currentId = ref<string | number>(1); const currentId = ref<string | number>(1);
const httpNoWarning = ref(true); const httpNoWarning = ref(true);
const envGroupList = ref<EnvGroupListItem[]>([]);
const getCurrentId = computed(() => currentId.value); const getCurrentId = computed(() => currentId.value);
const getHttpNoWarning = computed(() => httpNoWarning.value); const getHttpNoWarning = computed(() => httpNoWarning.value);
const getGroupLength = computed(() => 1);
const getDatabaseList = computed(() => [{ id: 1, name: 'test' }]); const getDatabaseList = computed(() => [{ id: 1, name: 'test' }]);
function setCurrentId(id: string | number) { function setCurrentId(id: string | number) {
@ -25,6 +30,8 @@ const useProjectEnvStore = defineStore(
setHttpNoWarning, setHttpNoWarning,
getHttpNoWarning, getHttpNoWarning,
getDatabaseList, getDatabaseList,
envGroupList,
getGroupLength,
}; };
}, },
{ {

View File

@ -0,0 +1,132 @@
<template>
<div class="page">
<template v-if="store.getGroupLength">
<div class="header">
<a-form ref="envGroupForm" layout="vertical" :model="form">
<a-form-item
class="mb-[16px]"
asterisk-position="end"
field="name"
:label="t('project.environmental.group.envGroupName')"
:rules="[{ required: true, message: t('project.environmental.group.envGroupNameIsRequire') }]"
>
<a-input
v-model="form.name"
show-word-limit
:max-length="255"
class="w-[732px]"
:placeholder="t('project.environmental.group.envGroupPlaceholder')"
/>
</a-form-item>
<a-form-item
class="mb-[16px]"
asterisk-position="end"
field="description"
:label="t('project.environmental.group.desc')"
>
<a-textarea v-model="form.description" auto-size class="w-[732px]" :placeholder="t('common.pleaseInput')" />
</a-form-item>
</a-form>
<AllParamsTable
v-model:params="innerParams"
:show-setting="false"
:columns="columns"
@change="handleParamTableChange"
/>
</div>
<div class="footer" :style="{ width: '100%' }">
<a-button :disabled="!canSave" @click="handleReset">{{ t('common.cancel') }}</a-button>
<a-button :disabled="!canSave" type="primary" @click="handleSave">{{ t('common.save') }}</a-button>
</div>
</template>
<template v-else>
<div class="flex h-[400px] items-center justify-center">
<a-empty description="暂无数据" />
</div>
</template>
</div>
</template>
<script lang="ts" setup>
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import AllParamsTable from '../allParams/AllParamsTable.vue';
import { useI18n } from '@/hooks/useI18n';
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
const envGroupForm = ref();
const form = reactive({
name: '',
description: '',
});
const store = useProjectEnvStore();
const columns: MsTableColumn = [
{
title: 'project.environmental.project',
dataIndex: 'project',
slotName: 'project',
},
{
title: 'project.environmental.env',
dataIndex: 'env',
slotName: 'env',
},
{
title: 'project.environmental.host',
dataIndex: 'host',
slotName: 'host',
},
{
title: 'project.environmental.desc',
dataIndex: 'desc',
slotName: 'desc',
},
{
title: '',
slotName: 'operation',
width: 50,
},
];
const innerParams = ref<any[]>([]);
const canSave = ref(true);
const handleReset = () => {
envGroupForm.value?.resetFields();
};
const handleSave = () => {
envGroupForm.value?.validate(async (valid) => {
if (valid) {
console.log('form', form);
}
});
};
function handleParamTableChange(resultArr: any[]) {
innerParams.value = [...resultArr];
}
const { t } = useI18n();
</script>
<style lang="less" scoped>
.page {
transform: scale3d(1, 1, 1);
.header {
padding: 24px 24px 0;
}
.footer {
gap: 16px;
position: fixed;
right: 0;
bottom: 0;
z-index: 999;
display: flex;
justify-content: flex-end;
padding: 24px;
box-shadow: 0 -1px 4px rgb(2 2 2 / 10%);
}
}
</style>

View File

@ -7,50 +7,117 @@
<a-radio value="PROJECT">{{ t('project.environmental.project') }}</a-radio> <a-radio value="PROJECT">{{ t('project.environmental.project') }}</a-radio>
<a-radio value="PROJECT_GROUP">{{ t('project.environmental.projectGroup') }}</a-radio> <a-radio value="PROJECT_GROUP">{{ t('project.environmental.projectGroup') }}</a-radio>
</a-radio-group> </a-radio-group>
<a-input-search <template v-if="showType === 'PROJECT'">
:placeholder="t('project.environmental.searchHolder')" <a-input-search
allow-clear :placeholder="t('project.environmental.searchHolder')"
@press-enter="enterData" allow-clear
@search="searchData" @press-enter="enterData"
/> @search="searchData"
<!-- 全局参数--> />
<div class="p-[8px] text-[var(--color-text-4)]"> <!-- 全局参数-->
{{ t('project.environmental.allParam') }} <div class="p-[8px] text-[var(--color-text-4)]">
</div> {{ t('project.environmental.allParam') }}
<div
class="env-item justify-between font-medium text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]"
:class="{ 'bg-[rgb(var(--primary-1))]': activeKey === ALL_PARAM }"
@click="handleListItemClick({ id: 'allParam', name: 'allParam' })"
>
{{ t('project.environmental.allParam') }}
<div class="node-extra">
<MsMoreAction
:list="allMoreAction"
@select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.GLOBAL)"
/>
</div> </div>
</div> <div
<a-divider :margin="6" /> class="env-item justify-between font-medium text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]"
<!-- 环境--> :class="{ 'bg-[rgb(var(--primary-1))]': activeKey === ALL_PARAM }"
<div class="env-row p-[8px] hover:bg-[rgb(var(--primary-1))]"> @click="handleListItemClick({ id: 'allParam', name: 'allParam' })"
<div class="text-[var(--color-text-4)]">{{ t('project.environmental.env') }}</div> >
<div class="flex flex-row items-center"> {{ t('project.environmental.allParam') }}
<div class="env-row-extra"> <div class="node-extra">
<MsMoreAction <MsMoreAction
:list="allMoreAction" :list="allMoreAction"
@select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.ENVIRONMENT)" @select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.GLOBAL)"
/> />
</div> </div>
<MsButton type="icon" class="!mr-0 p-[2px]">
<MsIcon
type="icon-icon_create_planarity"
size="18"
class="text-[rgb(var(--primary-5))] hover:text-[rgb(var(--primary-4))]"
/>
</MsButton>
</div> </div>
</div> <a-divider :margin="6" />
<div> <!-- 环境-->
<div class="env-row p-[8px] hover:bg-[rgb(var(--primary-1))]">
<div class="text-[var(--color-text-4)]">{{ t('project.environmental.env') }}</div>
<div class="flex flex-row items-center">
<div class="env-row-extra">
<MsMoreAction
:list="allMoreAction"
@select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.ENVIRONMENT)"
/>
</div>
<MsButton type="icon" class="!mr-0 p-[2px]">
<MsIcon
type="icon-icon_create_planarity"
size="18"
class="text-[rgb(var(--primary-5))] hover:text-[rgb(var(--primary-4))]"
/>
</MsButton>
</div>
</div>
<div>
<!-- 环境list-->
<div v-if="envList.length">
<VueDraggable v-model="envList" ghost-class="ghost">
<div
v-for="element in envList"
:key="element.id"
class="env-item hover:bg-[rgb(var(--primary-1))]"
@click="handleListItemClick(element)"
>
<RenamePop
:list="envList"
:type="(showType as EnvAuthScopeEnum)"
v-bind="popVisible[element.id]"
@cancel="handleRenameCancel(element)"
@submit="handleRenameCancel(element, element.id)"
>
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
<a-tooltip :content="element.name">
<div
class="one-line-text"
:class="{ 'font-medium text-[rgb(var(--primary-5))]': element.id === activeKey }"
>{{ element.name }}</div
>
</a-tooltip>
<div class="node-extra">
<div class="flex flex-row items-center gap-[8px]">
<MsButton type="icon" class="!mr-0 p-[2px]">
<MsIcon
type="icon-icon_drag"
size="16"
class="text-[rgb(var(--primary-5))] hover:text-[rgb(var(--primary-4))]"
/>
</MsButton>
<MsMoreAction
:list="envMoreAction"
@select="
(value) => handleMoreAction(value, element.id, EnvAuthTypeEnum.ENVIRONMENT_PARAM)
"
/>
</div>
</div>
</div>
</RenamePop>
</div>
</VueDraggable>
</div>
<!-- 环境无数据 -->
<div v-else class="bg-[var(--color-text-n9)] p-[8px] text-[12px] text-[var(--color-text-4)]">
{{ t('project.environmental.envListIsNull') }}
</div>
</div>
</template>
<template v-else>
<!-- 环境组 -->
<div class="env-row mt-[8px] p-[8px]">
<div class="text-[var(--color-text-4)]">{{ t('project.environmental.group.envGroup') }}</div>
<div class="flex flex-row items-center">
<MsButton type="icon" class="!mr-0 p-[2px]">
<MsIcon
type="icon-icon_create_planarity"
size="18"
class="text-[rgb(var(--primary-5))] hover:text-[rgb(var(--primary-4))]"
/>
</MsButton>
</div>
</div>
<!-- 环境list--> <!-- 环境list-->
<div v-if="envList.length"> <div v-if="envList.length">
<VueDraggable v-model="envList" ghost-class="ghost"> <VueDraggable v-model="envList" ghost-class="ghost">
@ -95,18 +162,20 @@
</div> </div>
</VueDraggable> </VueDraggable>
</div> </div>
<!-- 环境无数据 -->
<div v-else class="bg-[var(--color-text-n9)] p-[8px] text-[12px] text-[var(--color-text-4)]"> <div v-else class="bg-[var(--color-text-n9)] p-[8px] text-[12px] text-[var(--color-text-4)]">
{{ t('project.environmental.envListIsNull') }} {{ t('project.environmental.envListIsNull') }}
</div> </div>
</div> </template>
</div> </div>
</template> </template>
<template #second> <template #second>
<!-- 全局参数 --> <!-- 全局参数 -->
<AllParamBox v-if="activeKey === ALL_PARAM" /> <AllParamBox v-if="showType === 'PROJECT' && activeKey === ALL_PARAM" />
<!-- 环境变量 --> <!-- 环境变量 -->
<EnvParamBox v-else /> <EnvParamBox v-else-if="showType === 'PROJECT' && activeKey !== ALL_PARAM" />
<!-- 环境组 -->
<EnvGroupBox v-else-if="showType === 'PROJECT_GROUP'" />
</template> </template>
</MsSplitBox> </MsSplitBox>
</div> </div>
@ -119,6 +188,7 @@
import MsMoreAction from '@/components/pure/ms-table-more-action/index.vue'; import MsMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types'; import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import AllParamBox from './components/AllParamBox.vue'; import AllParamBox from './components/AllParamBox.vue';
import EnvGroupBox from './components/envGroup/EnvGroupBox.vue';
import EnvParamBox from './components/envParams/EnvParamBox.vue'; import EnvParamBox from './components/envParams/EnvParamBox.vue';
import RenamePop from './components/RenamePop.vue'; import RenamePop from './components/RenamePop.vue';
@ -189,6 +259,7 @@
default: default:
break; break;
} }
console.log(item, id, scopeType);
}; };
function changeShowType(value: string | number | boolean) { function changeShowType(value: string | number | boolean) {

View File

@ -74,4 +74,9 @@ export default {
'project.environmental.host.hostNamePlaceholder': '请输入域名', 'project.environmental.host.hostNamePlaceholder': '请输入域名',
'project.environmental.host.desc': '描述', 'project.environmental.host.desc': '描述',
'project.environmental.host.descPlaceholder': '请输入描述', 'project.environmental.host.descPlaceholder': '请输入描述',
'project.environmental.group.desc': '描述',
'project.environmental.group.envGroup': '环境组',
'project.environmental.group.envGroupName': '环境组名称',
'project.environmental.group.envGroupNameIsRequire': '环境组名称不能为空',
'project.environmental.group.envGroupPlaceholder': '请输入环境组',
}; };