feat: 增加网站分组管理

pull/35/head
zhengkunwang223 2022-11-02 18:18:20 +08:00 committed by zhengkunwang223
parent 9621d6ea1f
commit 42134e315b
9 changed files with 198 additions and 22 deletions

View File

@ -5,10 +5,10 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
"strconv"
)
func (b *BaseApi) GetWebGroups(c *gin.Context) {
list, err := websiteGroupService.GetGroups()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@ -18,16 +18,46 @@ func (b *BaseApi) GetWebGroups(c *gin.Context) {
}
func (b *BaseApi) CreateWebGroup(c *gin.Context) {
var req dto.WebSiteGroupCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := websiteGroupService.CreateGroup(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) UpdateWebGroup(c *gin.Context) {
var req dto.WebSiteGroupUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := websiteGroupService.UpdateGroup(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) DeleteWebGroup(c *gin.Context) {
groupId := c.Param("groupId")
if groupId == "" {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, nil)
return
}
id, err := strconv.Atoi(groupId)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if err := websiteGroupService.DeleteGroup(uint(id)); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

View File

@ -16,6 +16,8 @@ func (a *WebsiteGroupRouter) InitWebsiteGroupRouter(Router *gin.RouterGroup) {
baseApi := v1.ApiGroupApp.BaseApi
{
groupRouter.GET("", baseApi.GetWebGroups)
//groupRouter.GET("", baseApi.GetGroups)
groupRouter.POST("", baseApi.CreateWebGroup)
groupRouter.PUT("", baseApi.UpdateWebGroup)
groupRouter.DELETE("/:groupId", baseApi.DeleteWebGroup)
}
}

View File

@ -46,4 +46,9 @@ export namespace WebSite {
name: string;
default: boolean;
}
export interface GroupOp {
name: string;
id?: number;
}
}

View File

@ -6,10 +6,6 @@ export const SearchWebSites = (req: WebSite.WebSiteSearch) => {
return http.post<ResPage<WebSite.WebSite>>(`/websites/search`, req);
};
export const ListGroups = () => {
return http.get<WebSite.Group[]>(`/websites/groups`);
};
export const CreateWebsite = (req: WebSite.WebSiteCreateReq) => {
return http.post<any>(`/websites`, req);
};
@ -17,3 +13,19 @@ export const CreateWebsite = (req: WebSite.WebSiteCreateReq) => {
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
return http.post<any>(`/websites/del`, req);
};
export const ListGroups = () => {
return http.get<WebSite.Group[]>(`/websites/groups`);
};
export const CreateGroup = (req: WebSite.GroupOp) => {
return http.post<any>(`/websites/groups`, req);
};
export const UpdateGroup = (req: WebSite.GroupOp) => {
return http.put<any>(`/websites/groups`, req);
};
export const DeleteGroup = (id: number) => {
return http.delete<any>(`/websites/groups/${id}`);
};

View File

@ -44,6 +44,7 @@ const checkName = (rule: any, value: any, callback: any) => {
interface CommonRule {
requiredInput: FormItemRule;
requiredSelect: FormItemRule;
requiredSelectBusiness: FormItemRule;
name: FormItemRule;
password: FormItemRule;
email: FormItemRule;
@ -63,6 +64,14 @@ export const Rules: CommonRule = {
message: i18n.global.t('commons.rule.requiredSelect'),
trigger: 'change',
},
requiredSelectBusiness: {
required: true,
min: 1,
max: 65535,
type: 'number',
message: i18n.global.t('commons.rule.requiredSelect'),
trigger: 'change',
},
name: {
required: true,
validator: checkName,

View File

@ -673,12 +673,14 @@ export default {
alias: '',
remark: '',
group: '',
groupSetting: '',
app: '',
app_new: '',
app_installed: '',
appNew: '',
appInstalled: '',
create: '',
delete: '',
deleteApp: '',
deleteBackup: '',
domain: '',
},
};

View File

@ -21,16 +21,16 @@
<el-form-item prop="appType">
<el-radio-group v-model="website.appType" @change="changeAppType(website.appType)">
<el-radio :label="'installed'" :value="'installed'">
{{ $t('website.app_installed') }}
{{ $t('website.appInstalled') }}
</el-radio>
<el-radio :label="'new'">
{{ $t('website.app_new') }}
{{ $t('website.appNew') }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="website.appType == 'installed'"
:label="$t('website.app_installed')"
:label="$t('website.appInstalled')"
prop="appInstallID"
>
<el-select v-model="website.appInstallID">
@ -125,13 +125,13 @@ const website = ref({
remark: '',
domains: [],
appType: 'installed',
appInstallID: null,
appInstallID: 0,
webSiteGroupID: 1,
otherDomains: '',
appinstall: {
appID: null,
appID: 0,
name: '',
appDetailID: null,
appDetailID: 0,
params: {},
version: '',
},
@ -140,12 +140,12 @@ let rules = ref({
primaryDomain: [Rules.requiredInput],
alias: [Rules.requiredInput],
type: [Rules.requiredInput],
webSiteGroupID: [Rules.requiredInput],
appInstallID: [Rules.requiredInput],
webSiteGroupID: [Rules.requiredSelectBusiness],
appInstallID: [Rules.requiredSelectBusiness],
appType: [Rules.requiredInput],
appinstall: {
name: [Rules.requiredInput],
appID: [Rules.requiredInput],
appID: [Rules.requiredSelectBusiness],
params: {},
},
});

View File

@ -0,0 +1,107 @@
<template>
<el-dialog v-model="open" :title="$t('website.groupSetting')" width="40%" :before-close="handleClose">
<ComplexTable :data="data" @search="search()">
<template #toolbar>
<el-button type="primary" plain @click="openCreate">{{ $t('commons.button.create') }}</el-button>
</template>
<el-table-column :label="$t('commons.table.name')" prop="name">
<template #default="{ row }">
<span v-if="!row.edit" @click="row.edit = true">{{ row.name }}</span>
<el-input v-if="row.edit" v-model="row.name" @blur="row.edit = false"></el-input>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.operate')">
<template #default="{ row, $index }">
<el-button link :disabled="row.default" type="primary" @click="saveGroup(row)">
{{ $t('commons.button.save') }}
</el-button>
<el-button link :disabled="row.default" type="primary" @click="deleteGroup($index)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
</el-table-column>
</ComplexTable>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import i18n from '@/lang';
import ComplexTable from '@/components/complex-table/index.vue';
import { ListGroups, CreateGroup, DeleteGroup, UpdateGroup } from '@/api/modules/website';
import { ElMessage } from 'element-plus';
interface groupData {
id: number;
name: string;
edit: boolean;
default: boolean;
}
let open = ref(false);
let data = ref<groupData[]>([]);
const handleClose = () => {
open.value = false;
data.value = [];
};
const search = () => {
ListGroups().then((res) => {
for (const d of res.data) {
const g = {
id: d.id,
name: d.name,
default: d.default,
edit: false,
};
data.value.push(g);
}
});
};
const saveGroup = (create: groupData) => {
const group = {
name: create.name,
id: create.id,
};
if (create.id == 0) {
CreateGroup(group).then(() => {
ElMessage.success(i18n.global.t('commons.msg.createSuccess'));
});
} else {
UpdateGroup(group).then(() => {
ElMessage.success(i18n.global.t('commons.msg.updateSuccess'));
});
}
};
const acceptParams = async () => {
open.value = true;
search();
};
const openCreate = () => {
const g = {
id: 0,
name: '',
default: false,
edit: true,
};
data.value.push(g);
};
const deleteGroup = (index: number) => {
const group = data.value[index];
if (group.id > 0) {
DeleteGroup(group.id).then(() => {
data.value.splice(index, 1);
ElMessage.success(i18n.global.t('commons.msg.deleteSuccess'));
});
} else {
data.value.splice(index, 1);
}
};
defineExpose({ acceptParams });
</script>

View File

@ -2,7 +2,8 @@
<LayoutContent :header="'网站'">
<ComplexTable :data="data" @search="search()">
<template #toolbar>
<el-button type="primary" plain @click="openCreate">{{ '' }}</el-button>
<el-button type="primary" plain @click="openCreate">{{ $t('commons.button.create') }}</el-button>
<el-button type="primary" plain @click="openGroup">{{ $t('website.group') }}</el-button>
<el-button type="primary" plain>{{ '修改默认页' }}</el-button>
<el-button type="primary" plain>{{ '默认站点' }}</el-button>
</template>
@ -25,6 +26,7 @@
</ComplexTable>
<CreateWebSite ref="createRef" @close="search"></CreateWebSite>
<DeleteWebsite ref="deleteRef" @close="search"></DeleteWebsite>
<WebSiteGroup ref="groupRef"></WebSiteGroup>
</LayoutContent>
</template>
@ -32,15 +34,18 @@
import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import { onMounted, reactive, ref } from '@vue/runtime-core';
import router from '@/routers';
import CreateWebSite from './create/index.vue';
import DeleteWebsite from './delete/index.vue';
import WebSiteGroup from './group/index.vue';
import { SearchWebSites } from '@/api/modules/website';
import i18n from '@/lang';
import { WebSite } from '@/api/interface/website';
import i18n from '@/lang';
import router from '@/routers';
const createRef = ref();
const deleteRef = ref();
const groupRef = ref();
const paginationConfig = reactive({
currentPage: 1,
@ -86,6 +91,10 @@ const openCreate = () => {
createRef.value.acceptParams();
};
const openGroup = () => {
groupRef.value.acceptParams();
};
onMounted(() => {
search();
});