mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-16 18:54:43 +08:00
feat: 新增创建域名
This commit is contained in:
parent
35e85930b9
commit
cfa5f08cdd
@ -82,3 +82,17 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) CreateWebDomain(c *gin.Context) {
|
||||||
|
var req dto.WebSiteDomainCreate
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
domain, err := websiteService.CreateWebsiteDomain(req)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, domain)
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package dto
|
package dto
|
||||||
|
|
||||||
import "github.com/1Panel-dev/1Panel/backend/app/model"
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
|
||||||
|
)
|
||||||
|
|
||||||
type WebSiteReq struct {
|
type WebSiteReq struct {
|
||||||
PageInfo
|
PageInfo
|
||||||
@ -43,16 +46,23 @@ type WebSiteDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WebSiteGroupCreate struct {
|
type WebSiteGroupCreate struct {
|
||||||
Name string
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSiteGroupUpdate struct {
|
type WebSiteGroupUpdate struct {
|
||||||
ID uint
|
ID uint `json:"id"`
|
||||||
Name string
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSiteDomainCreate struct {
|
type WebSiteDomainCreate struct {
|
||||||
|
WebSiteID uint `json:"webSiteId"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSiteDomainDel struct {
|
type NginxConfig struct {
|
||||||
|
FilePath string `json:"filePath"`
|
||||||
|
ContainerName string `json:"containerName"`
|
||||||
|
Config *components.Config `json:"config"`
|
||||||
|
OldContent string `json:"oldContent"`
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,28 @@ func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteService) CreateWebsiteDomain() {
|
func (w WebsiteService) CreateWebsiteDomain(create dto.WebSiteDomainCreate) (model.WebSiteDomain, error) {
|
||||||
|
var domainModel model.WebSiteDomain
|
||||||
|
var ports []int
|
||||||
|
var domains []string
|
||||||
|
|
||||||
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebSiteID))
|
||||||
|
if err != nil {
|
||||||
|
return domainModel, err
|
||||||
|
}
|
||||||
|
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(create.WebSiteID), websiteDomainRepo.WithPort(create.Port)); len(oldDomains) == 0 {
|
||||||
|
ports = append(ports, create.Port)
|
||||||
|
}
|
||||||
|
domains = append(domains, create.Domain)
|
||||||
|
if err := addListenAndServerName(website, ports, domains); err != nil {
|
||||||
|
return domainModel, err
|
||||||
|
}
|
||||||
|
domainModel = model.WebSiteDomain{
|
||||||
|
Domain: create.Domain,
|
||||||
|
Port: create.Port,
|
||||||
|
WebSiteID: create.WebSiteID,
|
||||||
|
}
|
||||||
|
return domainModel, websiteDomainRepo.Create(context.TODO(), &domainModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebSiteDomain, error) {
|
func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebSiteDomain, error) {
|
||||||
|
@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
@ -137,23 +138,59 @@ func nginxCheckAndReload(oldContent string, filePath string, containerName strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error {
|
func getNginxConfig(primaryDomain string) (dto.NginxConfig, error) {
|
||||||
|
var nginxConfig dto.NginxConfig
|
||||||
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
|
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nginxConfig, err
|
||||||
}
|
}
|
||||||
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
|
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nginxConfig, err
|
||||||
}
|
}
|
||||||
|
|
||||||
configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", website.PrimaryDomain+".conf")
|
configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", primaryDomain+".conf")
|
||||||
content, err := os.ReadFile(configPath)
|
content, err := os.ReadFile(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nginxConfig, err
|
||||||
}
|
}
|
||||||
config := parser.NewStringParser(string(content)).Parse()
|
config := parser.NewStringParser(string(content)).Parse()
|
||||||
|
config.FilePath = configPath
|
||||||
|
nginxConfig.Config = config
|
||||||
|
nginxConfig.OldContent = string(content)
|
||||||
|
nginxConfig.ContainerName = nginxInstall.ContainerName
|
||||||
|
nginxConfig.FilePath = configPath
|
||||||
|
|
||||||
|
return nginxConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addListenAndServerName(website model.WebSite, ports []int, domains []string) error {
|
||||||
|
|
||||||
|
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
config := nginxConfig.Config
|
||||||
|
server := config.FindServers()[0]
|
||||||
|
for _, port := range ports {
|
||||||
|
server.AddListen(strconv.Itoa(port), false)
|
||||||
|
}
|
||||||
|
for _, domain := range domains {
|
||||||
|
server.AddServerName(domain)
|
||||||
|
}
|
||||||
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error {
|
||||||
|
|
||||||
|
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
config := nginxConfig.Config
|
||||||
server := config.FindServers()[0]
|
server := config.FindServers()[0]
|
||||||
for _, port := range ports {
|
for _, port := range ports {
|
||||||
server.DeleteListen(strconv.Itoa(port))
|
server.DeleteListen(strconv.Itoa(port))
|
||||||
@ -162,10 +199,8 @@ func deleteListenAndServerName(website model.WebSite, ports []int, domains []str
|
|||||||
server.DeleteServerName(domain)
|
server.DeleteServerName(domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.FilePath = configPath
|
|
||||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nginxCheckAndReload(string(content), configPath, nginxInstall.ContainerName)
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,5 +20,6 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
|
|||||||
groupRouter.POST("/del", baseApi.DeleteWebSite)
|
groupRouter.POST("/del", baseApi.DeleteWebSite)
|
||||||
groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
|
groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
|
||||||
groupRouter.DELETE("/domains/:id", baseApi.DeleteWebDomain)
|
groupRouter.DELETE("/domains/:id", baseApi.DeleteWebDomain)
|
||||||
|
groupRouter.POST("/domains", baseApi.CreateWebDomain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,13 @@ func (s *Server) DeleteServerName(name string) {
|
|||||||
s.UpdateServerName(names)
|
s.UpdateServerName(names)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddServerName(name string) {
|
||||||
|
dirs := s.FindDirectives("server_name")
|
||||||
|
params := dirs[0].GetParameters()
|
||||||
|
params = append(params, name)
|
||||||
|
s.UpdateServerName(params)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) UpdateServerName(names []string) {
|
func (s *Server) UpdateServerName(names []string) {
|
||||||
serverNameDirective := Directive{
|
serverNameDirective := Directive{
|
||||||
Name: "server_name",
|
Name: "server_name",
|
||||||
|
@ -52,8 +52,15 @@ export namespace WebSite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Domain {
|
export interface Domain {
|
||||||
name: string;
|
websiteId: number;
|
||||||
port: number;
|
port: number;
|
||||||
id: number;
|
id: number;
|
||||||
|
domain: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DomainCreate {
|
||||||
|
websiteId: number;
|
||||||
|
port: number;
|
||||||
|
domain: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,3 +37,7 @@ export const ListDomains = (id: number) => {
|
|||||||
export const DeleteDomain = (id: number) => {
|
export const DeleteDomain = (id: number) => {
|
||||||
return http.delete<any>(`/websites/domains/${id}`);
|
return http.delete<any>(`/websites/domains/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CreateDomain = (req: WebSite.DomainCreate) => {
|
||||||
|
return http.post<any>(`/websites/domains`, req);
|
||||||
|
};
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="open" :title="$t('website.create')" width="40%" :before-close="handleClose">
|
||||||
|
<el-form ref="domainForm" label-position="right" :model="domain" label-width="130px" :rules="rules">
|
||||||
|
<el-form-item :label="$t('website.domain')" prop="domain">
|
||||||
|
<el-input v-model="domain.domain"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.port')" prop="port">
|
||||||
|
<el-input v-model.number="domain.port"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit(domainForm)" :loading="loading">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { CreateDomain } from '@/api/modules/website';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { ElMessage, FormInstance } from 'element-plus';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const domainForm = ref<FormInstance>();
|
||||||
|
|
||||||
|
let rules = ref({
|
||||||
|
domain: [Rules.requiredInput],
|
||||||
|
port: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
|
||||||
|
let open = ref(false);
|
||||||
|
let loading = ref(false);
|
||||||
|
let domain = ref({
|
||||||
|
websiteId: 0,
|
||||||
|
domain: '',
|
||||||
|
port: 80,
|
||||||
|
});
|
||||||
|
|
||||||
|
const em = defineEmits(['close']);
|
||||||
|
const handleClose = () => {
|
||||||
|
open.value = false;
|
||||||
|
em('close', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptParams = async (websiteId: number) => {
|
||||||
|
domain.value.websiteId = Number(websiteId);
|
||||||
|
open.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
console.log(domain.value);
|
||||||
|
CreateDomain(domain.value)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.createSuccess'));
|
||||||
|
handleClose();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,16 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<ComplexTable :data="data" @search="search" v-loading="loading">
|
<ComplexTable :data="data" @search="search" v-loading="loading">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-button type="primary" plain>{{ $t('website.addDomain') }}</el-button>
|
<el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column :label="$t('website.domain')" prop="domain"></el-table-column>
|
<el-table-column :label="$t('website.domain')" prop="domain"></el-table-column>
|
||||||
<el-table-column :label="$t('website.port')" prop="port"></el-table-column>
|
<el-table-column :label="$t('website.port')" prop="port"></el-table-column>
|
||||||
<fu-table-operations :ellipsis="1" :buttons="buttons" :label="$t('commons.table.operate')" fixed="right" fix />
|
<fu-table-operations :ellipsis="1" :buttons="buttons" :label="$t('commons.table.operate')" fixed="right" fix />
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
|
<Domain ref="domainRef" @close="search(id)"></Domain>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
|
import Domain from './create/index.vue';
|
||||||
import { WebSite } from '@/api/interface/website';
|
import { WebSite } from '@/api/interface/website';
|
||||||
import { DeleteDomain, ListDomains } from '@/api/modules/website';
|
import { DeleteDomain, ListDomains } from '@/api/modules/website';
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
@ -23,13 +25,12 @@ const props = defineProps({
|
|||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const id = computed(() => {
|
const id = computed(() => {
|
||||||
return props.id;
|
return props.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
let loading = ref(false);
|
let loading = ref(false);
|
||||||
const data = ref<WebSite.Domain[]>([]);
|
const data = ref<WebSite.Domain[]>([]);
|
||||||
|
const domainRef = ref();
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
{
|
{
|
||||||
@ -40,6 +41,10 @@ const buttons = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const openCreate = () => {
|
||||||
|
domainRef.value.acceptParams(id.value);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteDoamin = async (domainId: number) => {
|
const deleteDoamin = async (domainId: number) => {
|
||||||
await useDeleteData(DeleteDomain, domainId, 'commons.msg.delete', loading.value);
|
await useDeleteData(DeleteDomain, domainId, 'commons.msg.delete', loading.value);
|
||||||
search(id.value);
|
search(id.value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user