feat: 网站子目录绑定域名 (#6098)

Refs https://github.com/1Panel-dev/1Panel/issues/2336
Refs https://github.com/1Panel-dev/1Panel/issues/6024
This commit is contained in:
zhengkunwang 2024-08-12 17:08:52 +08:00 committed by GitHub
parent e0f628c59f
commit c7c5f75d17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 258 additions and 79 deletions

View File

@ -52,9 +52,13 @@ func (b *BaseApi) GetWebsites(c *gin.Context) {
// @Description 获取网站列表
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Router /websites/options [get]
// @Router /websites/options [post]
func (b *BaseApi) GetWebsiteOptions(c *gin.Context) {
websites, err := websiteService.GetWebsiteOptions()
var req request.WebsiteOptionReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
websites, err := websiteService.GetWebsiteOptions(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return

View File

@ -27,8 +27,9 @@ type WebsiteCreate struct {
AppID uint `json:"appID"`
AppInstallID uint `json:"appInstallID"`
RuntimeID uint `json:"runtimeID"`
TaskID string `json:"taskID"`
RuntimeID uint `json:"runtimeID"`
TaskID string `json:"taskID"`
ParentWebsiteID uint `json:"parentWebsiteID"`
RuntimeConfig
FtpConfig
@ -36,6 +37,10 @@ type WebsiteCreate struct {
SSLConfig
}
type WebsiteOptionReq struct {
Types []string `json:"types"`
}
type RuntimeConfig struct {
ProxyType string `json:"proxyType"`
Port int `json:"port"`

View File

@ -32,6 +32,7 @@ type WebsiteRes struct {
SSLExpireDate time.Time `json:"sslExpireDate"`
SSLStatus string `json:"sslStatus"`
AppInstallID uint `json:"appInstallId"`
ChildSites []string `json:"childSites"`
}
type WebsiteOption struct {

View File

@ -4,32 +4,33 @@ import "time"
type Website struct {
BaseModel
Protocol string `gorm:"type:varchar;not null" json:"protocol"`
PrimaryDomain string `gorm:"type:varchar;not null" json:"primaryDomain"`
Type string `gorm:"type:varchar;not null" json:"type"`
Alias string `gorm:"type:varchar;not null" json:"alias"`
Remark string `gorm:"type:longtext;" json:"remark"`
Status string `gorm:"type:varchar;not null" json:"status"`
HttpConfig string `gorm:"type:varchar;not null" json:"httpConfig"`
Protocol string `gorm:"not null" json:"protocol"`
PrimaryDomain string `gorm:"not null" json:"primaryDomain"`
Type string `gorm:"not null" json:"type"`
Alias string `gorm:"not null" json:"alias"`
Remark string `json:"remark"`
Status string `gorm:"not null" json:"status"`
HttpConfig string `gorm:"not null" json:"httpConfig"`
ExpireDate time.Time `json:"expireDate"`
Proxy string `gorm:"type:varchar;" json:"proxy"`
ProxyType string `gorm:"type:varchar;" json:"proxyType"`
SiteDir string `gorm:"type:varchar;" json:"siteDir"`
Proxy string `json:"proxy"`
ProxyType string `json:"proxyType"`
SiteDir string `json:"siteDir"`
ErrorLog bool `json:"errorLog"`
AccessLog bool `json:"accessLog"`
DefaultServer bool `json:"defaultServer"`
IPV6 bool `json:"IPV6"`
Rewrite string `gorm:"type:varchar" json:"rewrite"`
Rewrite string `json:"rewrite"`
WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
RuntimeID uint `gorm:"type:integer" json:"runtimeID"`
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
FtpID uint `gorm:"type:integer" json:"ftpId"`
WebsiteGroupID uint `json:"webSiteGroupId"`
WebsiteSSLID uint `json:"webSiteSSLId"`
RuntimeID uint `json:"runtimeID"`
AppInstallID uint `json:"appInstallId"`
FtpID uint `json:"ftpId"`
ParentWebsiteID uint `json:"parentWebsiteID"`
User string `gorm:"type:varchar;" json:"user"`
Group string `gorm:"type:varchar;" json:"group"`
User string `json:"user"`
Group string `json:"group"`
DbType string `json:"dbType"`
DbID uint `json:"dbID"`

View File

@ -19,6 +19,9 @@ type IWebsiteRepo interface {
WithDomainLike(domain string) DBOption
WithRuntimeID(runtimeID uint) DBOption
WithIDs(ids []uint) DBOption
WithTypes(types []string) DBOption
WithParentID(websiteID uint) DBOption
Page(page, size int, opts ...DBOption) (int64, []model.Website, error)
List(opts ...DBOption) ([]model.Website, error)
GetFirst(opts ...DBOption) (model.Website, error)
@ -49,6 +52,12 @@ func (w *WebsiteRepo) WithIDs(ids []uint) DBOption {
}
}
func (w *WebsiteRepo) WithTypes(types []string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("type in (?)", types)
}
}
func (w *WebsiteRepo) WithRuntimeID(runtimeID uint) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("runtime_id = ?", runtimeID)
@ -79,6 +88,12 @@ func (w *WebsiteRepo) WithWebsiteSSLID(sslId uint) DBOption {
}
}
func (w *WebsiteRepo) WithParentID(websiteID uint) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("parent_website_id = ?", websiteID)
}
}
func (w *WebsiteRepo) WithGroupID(groupId uint) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("website_group_id = ?", groupId)

View File

@ -59,7 +59,7 @@ type IWebsiteService interface {
GetWebsites() ([]response.WebsiteDTO, error)
CreateWebsite(create request.WebsiteCreate) error
OpWebsite(req request.WebsiteOp) error
GetWebsiteOptions() ([]response.WebsiteOption, error)
GetWebsiteOptions(req request.WebsiteOptionReq) ([]response.WebsiteOption, error)
UpdateWebsite(req request.WebsiteUpdate) error
DeleteWebsite(req request.WebsiteDelete) error
GetWebsite(id uint) (response.WebsiteDTO, error)
@ -170,7 +170,7 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons
}
sitePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", web.Alias)
websiteDTOs = append(websiteDTOs, response.WebsiteRes{
siteDTO := response.WebsiteRes{
ID: web.ID,
CreatedAt: web.CreatedAt,
Protocol: web.Protocol,
@ -186,7 +186,15 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons
RuntimeName: runtimeName,
SitePath: sitePath,
AppInstallID: appInstallID,
})
}
sites, _ := websiteRepo.List(websiteRepo.WithParentID(web.ID))
if len(sites) > 0 {
for _, site := range sites {
siteDTO.ChildSites = append(siteDTO.ChildSites, site.PrimaryDomain)
}
}
websiteDTOs = append(websiteDTOs, siteDTO)
}
return total, websiteDTOs, nil
}
@ -198,9 +206,10 @@ func (w WebsiteService) GetWebsites() ([]response.WebsiteDTO, error) {
return nil, err
}
for _, web := range websites {
websiteDTOs = append(websiteDTOs, response.WebsiteDTO{
res := response.WebsiteDTO{
Website: web,
})
}
websiteDTOs = append(websiteDTOs, res)
}
return websiteDTOs, nil
}
@ -364,37 +373,47 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
return err
}
website.RuntimeID = runtime.ID
if runtime.Type == constant.RuntimePHP {
var (
req request.AppInstallCreate
install *model.AppInstall
)
reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
req.Name = reg.ReplaceAllString(strings.ToLower(alias), "")
req.AppDetailId = create.AppInstall.AppDetailId
req.Params = create.AppInstall.Params
req.Params["IMAGE_NAME"] = runtime.Image
req.AppContainerConfig = create.AppInstall.AppContainerConfig
req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www")
install, err = NewIAppService().Install(req)
if err != nil {
return err
switch runtime.Type {
case constant.RuntimePHP:
if runtime.Resource == constant.ResourceAppstore {
var (
req request.AppInstallCreate
install *model.AppInstall
)
reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
req.Name = reg.ReplaceAllString(strings.ToLower(alias), "")
req.AppDetailId = create.AppInstall.AppDetailId
req.Params = create.AppInstall.Params
req.Params["IMAGE_NAME"] = runtime.Image
req.AppContainerConfig = create.AppInstall.AppContainerConfig
req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www")
install, err = NewIAppService().Install(req)
if err != nil {
return err
}
website.AppInstallID = install.ID
appInstall = install
website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort)
} else {
website.ProxyType = create.ProxyType
if website.ProxyType == constant.RuntimeProxyUnix {
proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock"))
}
if website.ProxyType == constant.RuntimeProxyTcp {
proxy = fmt.Sprintf("127.0.0.1:%d", create.Port)
}
website.Proxy = proxy
}
website.AppInstallID = install.ID
appInstall = install
website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort)
} else {
website.ProxyType = create.ProxyType
if website.ProxyType == constant.RuntimeProxyUnix {
proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock"))
}
if website.ProxyType == constant.RuntimeProxyTcp {
proxy = fmt.Sprintf("127.0.0.1:%d", create.Port)
}
website.Proxy = proxy
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo:
website.Proxy = fmt.Sprintf("127.0.0.1:%d", runtime.Port)
}
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo:
website.Proxy = fmt.Sprintf("127.0.0.1:%d", runtime.Port)
case constant.Subsite:
parentWebsite, err := websiteRepo.GetFirst(commonRepo.WithByID(create.ParentWebsiteID))
if err != nil {
return err
}
website.ParentWebsiteID = parentWebsite.ID
}
if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 {
@ -489,8 +508,12 @@ func (w WebsiteService) OpWebsite(req request.WebsiteOp) error {
return websiteRepo.Save(context.Background(), &website)
}
func (w WebsiteService) GetWebsiteOptions() ([]response.WebsiteOption, error) {
webs, err := websiteRepo.List()
func (w WebsiteService) GetWebsiteOptions(req request.WebsiteOptionReq) ([]response.WebsiteOption, error) {
var options []repo.DBOption
if len(req.Types) > 0 {
options = append(options, websiteRepo.WithTypes(req.Types))
}
webs, err := websiteRepo.List(options...)
if err != nil {
return nil, err
}
@ -556,6 +579,16 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
if err != nil {
return err
}
if website.Type != constant.Subsite {
parentWebsites, _ := websiteRepo.List(websiteRepo.WithParentID(website.ID))
if len(parentWebsites) > 0 {
var names []string
for _, site := range parentWebsites {
names = append(names, site.PrimaryDomain)
}
return buserr.WithName("ErrParentWebsite", strings.Join(names, ","))
}
}
if err = delNginxConfig(website, req.ForceDelete); err != nil {
return err
}
@ -2759,7 +2792,7 @@ func (w WebsiteService) LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*res
}
res.Dirs = []string{"/"}
for _, file := range indexFiles {
if !file.IsDir() {
if !file.IsDir() || file.Name() == "node_modules" || file.Name() == "vendor" {
continue
}
res.Dirs = append(res.Dirs, fmt.Sprintf("/%s", file.Name()))

View File

@ -231,12 +231,9 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
case constant.RuntimePHP:
server.UpdateDirective("error_page", []string{"404", "/404.html"})
if runtime.Resource == constant.ResourceLocal {
switch runtime.Type {
case constant.RuntimePHP:
server.UpdateRoot(rootIndex)
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
}
server.UpdateRoot(rootIndex)
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
} else {
server.UpdateRoot(rootIndex)
server.UpdatePHPProxy([]string{website.Proxy}, "")
@ -245,6 +242,34 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port)
server.UpdateRootProxy([]string{proxy})
}
case constant.Subsite:
parentWebsite, err := websiteRepo.GetFirst(commonRepo.WithByID(website.ParentWebsiteID))
if err != nil {
return err
}
website.Proxy = parentWebsite.Proxy
rootIndex = path.Join("/www/sites", parentWebsite.Alias, "index", website.SiteDir)
server.UpdateDirective("error_page", []string{"404", "/404.html"})
if parentWebsite.Type == constant.Runtime {
parentRuntime, err := runtimeRepo.GetFirst(commonRepo.WithByID(parentWebsite.RuntimeID))
if err != nil {
return err
}
website.RuntimeID = parentRuntime.ID
if parentRuntime.Type == constant.RuntimePHP {
if parentRuntime.Resource == constant.ResourceLocal {
server.UpdateRoot(rootIndex)
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
} else {
server.UpdateRoot(rootIndex)
server.UpdatePHPProxy([]string{website.Proxy}, "")
}
}
}
if parentWebsite.Type == constant.Static {
server.UpdateRoot(rootIndex)
}
}
config.FilePath = configPath

View File

@ -14,6 +14,7 @@ const (
Static = "static"
Proxy = "proxy"
Runtime = "runtime"
Subsite = "subsite"
SSLExisted = "existed"
SSLAuto = "auto"

View File

@ -94,6 +94,7 @@ ErrPathPermission: 'A folder with non-1000:1000 permissions was detected in the
ErrDomainIsUsed: "Domain is already used by website {{ .name }}"
ErrDomainFormat: "{{ .name }} domain format error"
ErrDefaultAlias: "default is a reserved code name, please use another code name"
ErrParentWebsite: "You need to delete the subsite(s) {{ .name }} first"
#ssl
ErrSSLCannotDelete: "The certificate {{ .name }} is being used by the website and cannot be removed"

View File

@ -94,6 +94,7 @@ ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可
ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正確"
ErrDefaultAlias: "default 為保留代號,請使用其他代號"
ErrParentWebsite: "需要先刪除子網站 {{ .name }}"
#ssl
ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除"

View File

@ -94,6 +94,7 @@ ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可
ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正确"
ErrDefaultAlias: "default 为保留代号,请使用其他代号"
ErrParentWebsite: "需要先删除子网站 {{ .name }}"
#ssl
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"

View File

@ -290,7 +290,7 @@ var AddTask = &gormigrate.Migration{
}
var UpdateWebsite = &gormigrate.Migration{
ID: "20240807-update-website",
ID: "20240812-update-website",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.Website{})

View File

@ -19,7 +19,7 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
websiteRouter.POST("/operate", baseApi.OpWebsite)
websiteRouter.POST("/log", baseApi.OpWebsiteLog)
websiteRouter.POST("/check", baseApi.CreateWebsiteCheck)
websiteRouter.GET("/options", baseApi.GetWebsiteOptions)
websiteRouter.POST("/options", baseApi.GetWebsiteOptions)
websiteRouter.POST("/update", baseApi.UpdateWebsite)
websiteRouter.GET("/:id", baseApi.GetWebsite)
websiteRouter.POST("/del", baseApi.DeleteWebsite)

View File

@ -17,4 +17,5 @@ type System struct {
Entrance string `mapstructure:"entrance"`
IsDemo bool `mapstructure:"is_demo"`
ChangeUserInfo string `mapstructure:"change_user_info"`
DbPath string `mapstructure:"db_path"`
}

View File

@ -23,6 +23,7 @@ export namespace Website {
IPV6: boolean;
accessLog?: boolean;
errorLog?: boolean;
childSites?: string[];
}
export interface WebsiteDTO extends Website {
@ -111,6 +112,10 @@ export namespace Website {
pageSize?: number;
}
export interface OptionReq {
types?: string[];
}
export interface WebSiteLog {
enable: boolean;
content: string;

View File

@ -38,8 +38,8 @@ export const GetWebsite = (id: number) => {
return http.get<Website.WebsiteDTO>(`/websites/${id}`);
};
export const GetWebsiteOptions = () => {
return http.get<Array<string>>(`/websites/options`);
export const GetWebsiteOptions = (req: Website.OptionReq) => {
return http.post<any>(`/websites/options`, req);
};
export const GetWebsiteConfig = (id: number, type: string) => {

View File

@ -2134,6 +2134,10 @@ const message = {
domainSSLHelper:
'Enabling SSL on a non-443 port will cause the 443 port to stop listening. If you need the 443 port to continue listening, please add the domain:443',
global: 'Global',
subsite: 'Subsite',
subsiteHelper: 'A subsite can select an existing PHP or static website directory as the main directory.',
parentWbeiste: 'Parent Website',
deleteSubsite: 'To delete the current website, you must first delete the subsite(s) {0}',
},
php: {
short_open_tag: 'Short tag support',

View File

@ -1983,6 +1983,10 @@ const message = {
generateDomain: '生成',
domainSSLHelper: ' 443 端口開啟 SSL 會導致 443 端口移除監聽如需 443 端口繼續監聽請添加域名:443',
global: '全局',
subsite: '子網站',
subsiteHelper: '子網站可以選擇已存在的 PHP 和靜態網站的目錄作為主目錄',
parentWbeiste: '父級網站',
deleteSubsite: '刪除當前網站需要先刪除子網站 {0}',
},
php: {
short_open_tag: '短標簽支持',

View File

@ -1985,6 +1985,10 @@ const message = {
generateDomain: '生成',
domainSSLHelper: ' 443 端口开启 SSL 会导致 443 端口去掉监听如需 443 端口继续监听请添加域名:443',
global: '全局',
subsite: '子网站',
subsiteHelper: '子网站可以选择已存在的 PHP 和静态网站的目录作为主目录',
parentWbeiste: '父级网站',
deleteSubsite: '删除当前网站需要先删除子网站 {0}',
},
php: {
short_open_tag: '短标签支持',

View File

@ -632,7 +632,7 @@ const loadAppInstalls = async () => {
};
const loadWebsites = async () => {
const res = await GetWebsiteOptions();
const res = await GetWebsiteOptions({});
websiteOptions.value = res.data || [];
};

View File

@ -161,17 +161,10 @@ const initData = () => {
dirs.value = [];
};
function filterDirectories(directories: any[]) {
return directories.filter((dir) => {
return dir !== '/node_modules' && dir !== '/vendor';
});
}
const getDirConfig = async () => {
try {
const res = await GetDirConfig({ id: props.id });
dirs.value = res.data.dirs;
dirs.value = filterDirectories(dirs.value);
dirConfig.value = res.data;
} catch (error) {}
};

View File

@ -21,6 +21,10 @@
label: i18n.global.t('website.static'),
value: 'static',
},
{
label: i18n.global.t('website.subsite'),
value: 'subsite',
},
]"
:key="item.value"
>
@ -62,6 +66,12 @@
type="info"
:closable="false"
/>
<el-alert
v-if="website.type == 'subsite'"
:title="$t('website.subsiteHelper')"
type="info"
:closable="false"
/>
<br />
<el-form
ref="websiteForm"
@ -147,6 +157,28 @@
></Params>
</div>
</div>
<div v-if="website.type === 'subsite'">
<el-form-item :label="$t('website.parentWbeiste')" prop="parentWebsiteID">
<el-select v-model="website.parentWebsiteID" @change="getDirConfig(website.parentWebsiteID)">
<el-option
v-for="(site, index) in parentWebsites"
:key="index"
:label="site.primaryDomain"
:value="site.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('website.runDir')" prop="siteDir">
<el-select v-model="website.siteDir" filterable class="p-w-200">
<el-option
v-for="(item, index) in dirs"
:label="item"
:value="item"
:key="index"
></el-option>
</el-select>
</el-form-item>
</div>
<div v-if="website.type === 'runtime'">
<el-row :gutter="20">
<el-col :span="8">
@ -496,7 +528,14 @@
<script lang="ts" setup name="CreateWebSite">
import { App } from '@/api/interface/app';
import { GetApp, GetAppDetail, SearchApp, GetAppInstalled, GetAppDetailByID } from '@/api/modules/app';
import { CreateWebsite, ListSSL, PreCheck, SearchAcmeAccount } from '@/api/modules/website';
import {
CreateWebsite,
GetWebsiteOptions,
ListSSL,
PreCheck,
SearchAcmeAccount,
GetDirConfig,
} from '@/api/modules/website';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm, FormInstance } from 'element-plus';
@ -565,6 +604,8 @@ const initData = () => ({
websiteSSLID: undefined,
acmeAccountID: undefined,
domains: [],
parentWebsiteID: undefined,
siteDir: '',
});
const website = ref(initData());
const rules = ref<any>({
@ -594,6 +635,8 @@ const rules = ref<any>({
dbPassword: [Rules.requiredInput, Rules.paramComplexity],
dbHost: [Rules.requiredSelect],
websiteSSLID: [Rules.requiredSelect],
parentWebsiteID: [Rules.requiredSelect],
siteDir: [Rules.requiredSelect],
});
const open = ref(false);
@ -626,6 +669,8 @@ const taskLog = ref();
const dbServices = ref();
const ssls = ref();
const websiteSSL = ref();
const parentWebsites = ref();
const dirs = ref([]);
const handleClose = () => {
open.value = false;
@ -656,6 +701,9 @@ const changeType = (type: string) => {
website.value.proxyAddress = '';
searchAppInstalled('proxy');
break;
case 'subsite':
listWebsites();
break;
default:
website.value.appInstallId = undefined;
break;
@ -885,6 +933,27 @@ const changeAlias = (value: string) => {
website.value.alias = domain;
};
const listWebsites = async () => {
try {
const res = await GetWebsiteOptions({ types: ['static', 'runtime'] });
parentWebsites.value = res.data;
if (res.data.length > 0) {
website.value.parentWebsiteID = res.data[0].id;
getDirConfig(res.data[0].id);
}
} catch (error) {}
};
const getDirConfig = async (websiteID: number) => {
try {
const res = await GetDirConfig({ id: websiteID });
dirs.value = res.data.dirs;
if (res.data.dirs.length > 0) {
website.value.siteDir = res.data.dirs[0];
}
} catch (error) {}
};
defineExpose({
acceptParams,
});

View File

@ -23,16 +23,22 @@
<span class="input-help">
{{ $t('website.deleteAppHelper') }}
</span>
<span class="input-help" style="color: red" v-if="runtimeApp">
<span class="input-help text-red-500" v-if="runtimeApp">
{{ $t('website.deleteRuntimeHelper') }}
</span>
</el-form-item>
<el-form-item>
<el-checkbox v-model="deleteReq.deleteBackup" :label="$t('website.deleteBackup')" />
<span class="input-help">
{{ $t('website.deleteBackupHelper') }}
</span>
</el-form-item>
<el-form-item v-if="subSites != ''">
<span class="input-help text-red-500">
{{ $t('website.deleteSubsite', [subSites]) }}
</span>
</el-form-item>
<el-form-item>
<span v-html="deleteHelper"></span>
<el-input v-model="deleteInfo" :placeholder="websiteName" />
@ -74,6 +80,7 @@ const deleteInfo = ref('');
const websiteName = ref('');
const deleteHelper = ref('');
const runtimeApp = ref(false);
const subSites = ref('');
const handleClose = () => {
open.value = false;
@ -87,10 +94,14 @@ const acceptParams = async (website: Website.Website) => {
deleteBackup: false,
forceDelete: false,
};
subSites.value = '';
if (website.type === 'runtime' && website.appInstallId > 0) {
runtimeApp.value = true;
deleteReq.value.deleteApp = true;
}
if (website.childSites && website.childSites.length > 0) {
subSites.value = website.childSites.join(',');
}
deleteInfo.value = '';
deleteReq.value.id = website.id;
websiteName.value = website.primaryDomain;