mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 增加配置网站运行目录功能 (#675)
This commit is contained in:
parent
2944ea508e
commit
1086597e3a
@ -604,3 +604,25 @@ func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update Site Dir
|
||||
// @Description 更新网站目录
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteUpdateDir true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dir/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"}
|
||||
func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
|
||||
var req request.WebsiteUpdateDir
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdateSiteDir(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
@ -145,3 +145,8 @@ type WebsitePHPFileUpdate struct {
|
||||
Type string `json:"type" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteUpdateDir struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
SiteDir string `json:"siteDir" validate:"required"`
|
||||
}
|
||||
|
@ -4,24 +4,28 @@ import "time"
|
||||
|
||||
type Website struct {
|
||||
BaseModel
|
||||
Protocol string `gorm:"type:varchar(64);not null" json:"protocol"`
|
||||
PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"`
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Alias string `gorm:"type:varchar(128);not null" json:"alias"`
|
||||
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(64);not null" json:"status"`
|
||||
HttpConfig string `gorm:"type:varchar(64);not null" json:"httpConfig"`
|
||||
Status string `gorm:"type:varchar;not null" json:"status"`
|
||||
HttpConfig string `gorm:"type:varchar;not null" json:"httpConfig"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||
WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
||||
WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
||||
Proxy string `gorm:"type:varchar(128);not null" json:"proxy"`
|
||||
|
||||
Proxy string `gorm:"type:varchar;" json:"proxy"`
|
||||
ProxyType string `gorm:"type:varchar;" json:"proxyType"`
|
||||
SiteDir string `gorm:"type:varchar;" json:"siteDir"`
|
||||
ErrorLog bool `json:"errorLog"`
|
||||
AccessLog bool `json:"accessLog"`
|
||||
DefaultServer bool `json:"defaultServer"`
|
||||
Rewrite string `gorm:"type:varchar" 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"`
|
||||
|
||||
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
|
||||
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ type IWebsiteService interface {
|
||||
UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error
|
||||
GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error)
|
||||
UpdateRewriteConfig(req request.NginxRewriteUpdate) error
|
||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||
}
|
||||
|
||||
func NewIWebsiteService() IWebsiteService {
|
||||
@ -147,6 +148,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
WebsiteGroupID: create.WebsiteGroupID,
|
||||
Protocol: constant.ProtocolHTTP,
|
||||
Proxy: create.Proxy,
|
||||
SiteDir: "/",
|
||||
AccessLog: true,
|
||||
ErrorLog: true,
|
||||
}
|
||||
@ -1056,3 +1058,20 @@ func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response
|
||||
Content: string(contentByte),
|
||||
}, err
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateSiteDir(req request.WebsiteUpdateDir) error {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runDir := req.SiteDir
|
||||
siteDir := path.Join("/www/sites", website.Alias, "index")
|
||||
if req.SiteDir != "/" {
|
||||
siteDir = fmt.Sprintf("%s/%s", siteDir, req.SiteDir)
|
||||
}
|
||||
if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "root", Params: []string{siteDir}}}, &website); err != nil {
|
||||
return err
|
||||
}
|
||||
website.SiteDir = runDir
|
||||
return websiteRepo.Save(context.Background(), &website)
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func createIndexFile(website *model.Website, runtime *model.Runtime) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if runtime.Resource == constant.ResourceAppstore {
|
||||
if website.Type == constant.Runtime && runtime.Resource == constant.ResourceAppstore {
|
||||
if err := chownRootDir(indexFolder); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -276,8 +276,14 @@ var UpdateTableHost = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var UpdateTableWebsite = &gormigrate.Migration{
|
||||
ID: "20230414-update-table-website",
|
||||
ID: "20230417-update-table-website",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.Website{})
|
||||
if err := tx.AutoMigrate(&model.Website{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.Website{}).Where("1 = 1").Update("site_dir", "/").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -48,5 +48,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
|
||||
|
||||
groupRouter.POST("/rewrite", baseApi.GetRewriteConfig)
|
||||
groupRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
|
||||
|
||||
groupRouter.POST("/dir/update", baseApi.UpdateSiteDir)
|
||||
}
|
||||
}
|
||||
|
@ -8083,6 +8083,57 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/dir/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新网站目录",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website"
|
||||
],
|
||||
"summary": "Update Site Dir",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteUpdateDir"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_colume": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_colume": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "Update domain [domain] dir",
|
||||
"formatZH": "更新网站 [domain] 目录",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/dns": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -11918,6 +11969,9 @@ var doc = `{
|
||||
"runtimeID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -13117,6 +13171,21 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteUpdateDir": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"siteDir"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -13533,6 +13602,9 @@ var doc = `{
|
||||
"runtimeName": {
|
||||
"type": "string"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"sitePath": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -8069,6 +8069,57 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/dir/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新网站目录",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website"
|
||||
],
|
||||
"summary": "Update Site Dir",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteUpdateDir"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_colume": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_colume": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "Update domain [domain] dir",
|
||||
"formatZH": "更新网站 [domain] 目录",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/dns": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -11904,6 +11955,9 @@
|
||||
"runtimeID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -13103,6 +13157,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteUpdateDir": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"siteDir"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -13519,6 +13588,9 @@
|
||||
"runtimeName": {
|
||||
"type": "string"
|
||||
},
|
||||
"siteDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"sitePath": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -1746,6 +1746,8 @@ definitions:
|
||||
type: string
|
||||
runtimeID:
|
||||
type: integer
|
||||
siteDir:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type:
|
||||
@ -2548,6 +2550,16 @@ definitions:
|
||||
- primaryDomain
|
||||
- webSiteGroupID
|
||||
type: object
|
||||
request.WebsiteUpdateDir:
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
siteDir:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- siteDir
|
||||
type: object
|
||||
request.WebsiteWafReq:
|
||||
properties:
|
||||
key:
|
||||
@ -2824,6 +2836,8 @@ definitions:
|
||||
type: integer
|
||||
runtimeName:
|
||||
type: string
|
||||
siteDir:
|
||||
type: string
|
||||
sitePath:
|
||||
type: string
|
||||
status:
|
||||
@ -8009,6 +8023,39 @@ paths:
|
||||
formatEN: Delete website [domain]
|
||||
formatZH: 删除网站 [domain]
|
||||
paramKeys: []
|
||||
/websites/dir/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 更新网站目录
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteUpdateDir'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update Site Dir
|
||||
tags:
|
||||
- Website
|
||||
x-panel-log:
|
||||
BeforeFuntions:
|
||||
- db: websites
|
||||
input_colume: id
|
||||
input_value: id
|
||||
isList: false
|
||||
output_colume: primary_domain
|
||||
output_value: domain
|
||||
bodyKeys:
|
||||
- id
|
||||
formatEN: Update domain [domain] dir
|
||||
formatZH: 更新网站 [domain] 目录
|
||||
paramKeys: []
|
||||
/websites/dns:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -294,4 +294,9 @@ export namespace Website {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface DirUpdate {
|
||||
id: number;
|
||||
siteDir: string;
|
||||
}
|
||||
}
|
||||
|
@ -178,3 +178,7 @@ export const GetRewriteConfig = (req: Website.RewriteReq) => {
|
||||
export const UpdateRewriteConfig = (req: Website.RewriteUpdate) => {
|
||||
return http.post<any>(`/websites/rewrite/update`, req);
|
||||
};
|
||||
|
||||
export const UpdateWebsiteDir = (req: Website.DirUpdate) => {
|
||||
return http.post<any>(`/websites/dir/update`, req);
|
||||
};
|
||||
|
@ -1171,6 +1171,9 @@ const message = {
|
||||
current: 'Current',
|
||||
rewriteHelper:
|
||||
'If the website cannot be accessed normally after setting pseudo-static, please try to set it back to default',
|
||||
runDir: 'Run Directory',
|
||||
runDirHelper:
|
||||
'Some programs need to specify a secondary directory as the running directory, such as ThinkPHP5, Laravel',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: 'Short tag support',
|
||||
|
@ -1163,6 +1163,8 @@ const message = {
|
||||
rewriteMode: '方案',
|
||||
current: '当前',
|
||||
rewriteHelper: '若设置伪静态后,网站无法正常访问,请尝试设置回default',
|
||||
runDir: '运行目录',
|
||||
runDirHelper: '部分程序需要指定二级目录作为运行目录,如ThinkPHP5,Laravel',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短标签支持',
|
||||
|
@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14" :offset="1">
|
||||
<br />
|
||||
<el-descriptions :column="1" border v-loading="loading">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item :label="$t('website.siteAlias')">{{ website.alias }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('website.primaryPath')">
|
||||
{{ website.sitePath }}
|
||||
@ -20,11 +21,42 @@
|
||||
<el-descriptions-item label="index">{{ $t('website.indexFolder') }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
<el-col :span="14" :offset="1" v-if="configDir">
|
||||
<br />
|
||||
<el-form :inline="true" ref="siteForm" :model="update">
|
||||
<el-form-item :label="$t('website.runDir')" prop="runDir">
|
||||
<el-select v-model="update.siteDir">
|
||||
<el-option :label="'/'" :value="'/'"></el-option>
|
||||
<el-option
|
||||
v-for="(item, index) in dirs"
|
||||
:label="item"
|
||||
:value="item"
|
||||
:key="index"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submit(siteForm)">{{ $t('nginx.saveAndReload') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form-item>
|
||||
<el-alert :closable="false">
|
||||
<template #default>
|
||||
<span style="white-space: pre-line">{{ $t('website.runDirHelper') }}</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { GetWebsite } from '@/api/modules/website';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { GetFilesList } from '@/api/modules/files';
|
||||
import { GetWebsite, UpdateWebsiteDir } from '@/api/modules/website';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
|
||||
@ -37,25 +69,86 @@ const props = defineProps({
|
||||
const websiteId = computed(() => {
|
||||
return Number(props.id);
|
||||
});
|
||||
let website = ref<any>({});
|
||||
let loading = ref(false);
|
||||
const website = ref<any>({});
|
||||
const loading = ref(false);
|
||||
const configDir = ref(false);
|
||||
const update = reactive({
|
||||
id: 0,
|
||||
siteDir: '/',
|
||||
});
|
||||
const siteForm = ref<FormInstance>();
|
||||
const dirReq = reactive({
|
||||
path: '/',
|
||||
expand: true,
|
||||
showHidden: false,
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
search: '',
|
||||
containSub: false,
|
||||
dir: true,
|
||||
});
|
||||
const dirs = ref([]);
|
||||
|
||||
const search = () => {
|
||||
loading.value = true;
|
||||
GetWebsite(websiteId.value)
|
||||
.then((res) => {
|
||||
website.value = res.data;
|
||||
update.id = website.value.id;
|
||||
update.siteDir = website.value.siteDir;
|
||||
if (website.value.type === 'static' || website.value.runtimeID > 0) {
|
||||
configDir.value = true;
|
||||
dirReq.path = website.value.sitePath + '/index';
|
||||
getDirs();
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
UpdateWebsiteDir(update)
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
search();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getDirs = async () => {
|
||||
loading.value = true;
|
||||
await GetFilesList(dirReq)
|
||||
.then((res) => {
|
||||
const items = res.data.items || [];
|
||||
for (const item of items) {
|
||||
dirs.value.push(item.name);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const initData = () => {
|
||||
dirs.value = [];
|
||||
};
|
||||
|
||||
const toFolder = (folder: string) => {
|
||||
router.push({ path: '/hosts/files', query: { path: folder } });
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initData();
|
||||
search();
|
||||
});
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user