mirror of https://github.com/1Panel-dev/1Panel
feat: 增加网站分组管理
parent
9621d6ea1f
commit
42134e315b
|
@ -5,10 +5,10 @@ import (
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BaseApi) GetWebGroups(c *gin.Context) {
|
func (b *BaseApi) GetWebGroups(c *gin.Context) {
|
||||||
|
|
||||||
list, err := websiteGroupService.GetGroups()
|
list, err := websiteGroupService.GetGroups()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
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) {
|
func (b *BaseApi) CreateWebGroup(c *gin.Context) {
|
||||||
|
|
||||||
var req dto.WebSiteGroupCreate
|
var req dto.WebSiteGroupCreate
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := websiteGroupService.CreateGroup(req); err != nil {
|
if err := websiteGroupService.CreateGroup(req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ func (a *WebsiteGroupRouter) InitWebsiteGroupRouter(Router *gin.RouterGroup) {
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
groupRouter.GET("", baseApi.GetWebGroups)
|
groupRouter.GET("", baseApi.GetWebGroups)
|
||||||
//groupRouter.GET("", baseApi.GetGroups)
|
groupRouter.POST("", baseApi.CreateWebGroup)
|
||||||
|
groupRouter.PUT("", baseApi.UpdateWebGroup)
|
||||||
|
groupRouter.DELETE("/:groupId", baseApi.DeleteWebGroup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,4 +46,9 @@ export namespace WebSite {
|
||||||
name: string;
|
name: string;
|
||||||
default: boolean;
|
default: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GroupOp {
|
||||||
|
name: string;
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@ export const SearchWebSites = (req: WebSite.WebSiteSearch) => {
|
||||||
return http.post<ResPage<WebSite.WebSite>>(`/websites/search`, req);
|
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) => {
|
export const CreateWebsite = (req: WebSite.WebSiteCreateReq) => {
|
||||||
return http.post<any>(`/websites`, req);
|
return http.post<any>(`/websites`, req);
|
||||||
};
|
};
|
||||||
|
@ -17,3 +13,19 @@ export const CreateWebsite = (req: WebSite.WebSiteCreateReq) => {
|
||||||
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
|
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
|
||||||
return http.post<any>(`/websites/del`, req);
|
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}`);
|
||||||
|
};
|
||||||
|
|
|
@ -44,6 +44,7 @@ const checkName = (rule: any, value: any, callback: any) => {
|
||||||
interface CommonRule {
|
interface CommonRule {
|
||||||
requiredInput: FormItemRule;
|
requiredInput: FormItemRule;
|
||||||
requiredSelect: FormItemRule;
|
requiredSelect: FormItemRule;
|
||||||
|
requiredSelectBusiness: FormItemRule;
|
||||||
name: FormItemRule;
|
name: FormItemRule;
|
||||||
password: FormItemRule;
|
password: FormItemRule;
|
||||||
email: FormItemRule;
|
email: FormItemRule;
|
||||||
|
@ -63,6 +64,14 @@ export const Rules: CommonRule = {
|
||||||
message: i18n.global.t('commons.rule.requiredSelect'),
|
message: i18n.global.t('commons.rule.requiredSelect'),
|
||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
|
requiredSelectBusiness: {
|
||||||
|
required: true,
|
||||||
|
min: 1,
|
||||||
|
max: 65535,
|
||||||
|
type: 'number',
|
||||||
|
message: i18n.global.t('commons.rule.requiredSelect'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
name: {
|
name: {
|
||||||
required: true,
|
required: true,
|
||||||
validator: checkName,
|
validator: checkName,
|
||||||
|
|
|
@ -673,12 +673,14 @@ export default {
|
||||||
alias: '代号',
|
alias: '代号',
|
||||||
remark: '备注',
|
remark: '备注',
|
||||||
group: '分组',
|
group: '分组',
|
||||||
|
groupSetting: '分组管理',
|
||||||
app: '应用',
|
app: '应用',
|
||||||
app_new: '新装应用',
|
appNew: '新装应用',
|
||||||
app_installed: '已装应用',
|
appInstalled: '已装应用',
|
||||||
create: '创建网站',
|
create: '创建网站',
|
||||||
delete: '删除网站',
|
delete: '删除网站',
|
||||||
deleteApp: '删除应用',
|
deleteApp: '删除应用',
|
||||||
deleteBackup: '删除备份',
|
deleteBackup: '删除备份',
|
||||||
|
domain: '域名',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,16 +21,16 @@
|
||||||
<el-form-item prop="appType">
|
<el-form-item prop="appType">
|
||||||
<el-radio-group v-model="website.appType" @change="changeAppType(website.appType)">
|
<el-radio-group v-model="website.appType" @change="changeAppType(website.appType)">
|
||||||
<el-radio :label="'installed'" :value="'installed'">
|
<el-radio :label="'installed'" :value="'installed'">
|
||||||
{{ $t('website.app_installed') }}
|
{{ $t('website.appInstalled') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
<el-radio :label="'new'">
|
<el-radio :label="'new'">
|
||||||
{{ $t('website.app_new') }}
|
{{ $t('website.appNew') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="website.appType == 'installed'"
|
v-if="website.appType == 'installed'"
|
||||||
:label="$t('website.app_installed')"
|
:label="$t('website.appInstalled')"
|
||||||
prop="appInstallID"
|
prop="appInstallID"
|
||||||
>
|
>
|
||||||
<el-select v-model="website.appInstallID">
|
<el-select v-model="website.appInstallID">
|
||||||
|
@ -125,13 +125,13 @@ const website = ref({
|
||||||
remark: '',
|
remark: '',
|
||||||
domains: [],
|
domains: [],
|
||||||
appType: 'installed',
|
appType: 'installed',
|
||||||
appInstallID: null,
|
appInstallID: 0,
|
||||||
webSiteGroupID: 1,
|
webSiteGroupID: 1,
|
||||||
otherDomains: '',
|
otherDomains: '',
|
||||||
appinstall: {
|
appinstall: {
|
||||||
appID: null,
|
appID: 0,
|
||||||
name: '',
|
name: '',
|
||||||
appDetailID: null,
|
appDetailID: 0,
|
||||||
params: {},
|
params: {},
|
||||||
version: '',
|
version: '',
|
||||||
},
|
},
|
||||||
|
@ -140,12 +140,12 @@ let rules = ref({
|
||||||
primaryDomain: [Rules.requiredInput],
|
primaryDomain: [Rules.requiredInput],
|
||||||
alias: [Rules.requiredInput],
|
alias: [Rules.requiredInput],
|
||||||
type: [Rules.requiredInput],
|
type: [Rules.requiredInput],
|
||||||
webSiteGroupID: [Rules.requiredInput],
|
webSiteGroupID: [Rules.requiredSelectBusiness],
|
||||||
appInstallID: [Rules.requiredInput],
|
appInstallID: [Rules.requiredSelectBusiness],
|
||||||
appType: [Rules.requiredInput],
|
appType: [Rules.requiredInput],
|
||||||
appinstall: {
|
appinstall: {
|
||||||
name: [Rules.requiredInput],
|
name: [Rules.requiredInput],
|
||||||
appID: [Rules.requiredInput],
|
appID: [Rules.requiredSelectBusiness],
|
||||||
params: {},
|
params: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
|
@ -2,7 +2,8 @@
|
||||||
<LayoutContent :header="'网站'">
|
<LayoutContent :header="'网站'">
|
||||||
<ComplexTable :data="data" @search="search()">
|
<ComplexTable :data="data" @search="search()">
|
||||||
<template #toolbar>
|
<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>
|
||||||
<el-button type="primary" plain>{{ '默认站点' }}</el-button>
|
<el-button type="primary" plain>{{ '默认站点' }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
<CreateWebSite ref="createRef" @close="search"></CreateWebSite>
|
<CreateWebSite ref="createRef" @close="search"></CreateWebSite>
|
||||||
<DeleteWebsite ref="deleteRef" @close="search"></DeleteWebsite>
|
<DeleteWebsite ref="deleteRef" @close="search"></DeleteWebsite>
|
||||||
|
<WebSiteGroup ref="groupRef"></WebSiteGroup>
|
||||||
</LayoutContent>
|
</LayoutContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -32,15 +34,18 @@
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
||||||
import router from '@/routers';
|
|
||||||
import CreateWebSite from './create/index.vue';
|
import CreateWebSite from './create/index.vue';
|
||||||
import DeleteWebsite from './delete/index.vue';
|
import DeleteWebsite from './delete/index.vue';
|
||||||
|
import WebSiteGroup from './group/index.vue';
|
||||||
import { SearchWebSites } from '@/api/modules/website';
|
import { SearchWebSites } from '@/api/modules/website';
|
||||||
import i18n from '@/lang';
|
|
||||||
import { WebSite } from '@/api/interface/website';
|
import { WebSite } from '@/api/interface/website';
|
||||||
|
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import router from '@/routers';
|
||||||
|
|
||||||
const createRef = ref();
|
const createRef = ref();
|
||||||
const deleteRef = ref();
|
const deleteRef = ref();
|
||||||
|
const groupRef = ref();
|
||||||
|
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
@ -86,6 +91,10 @@ const openCreate = () => {
|
||||||
createRef.value.acceptParams();
|
createRef.value.acceptParams();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openGroup = () => {
|
||||||
|
groupRef.value.acceptParams();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue