mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-09 15:06:37 +08:00
feat: 伪静态支持保存为模版 (#6663)
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Refs https://github.com/1Panel-dev/1Panel/issues/705
This commit is contained in:
parent
958993f81f
commit
2565373db6
13 changed files with 278 additions and 30 deletions
|
@ -1047,3 +1047,39 @@ func (b *BaseApi) ChangeWebsiteDatabase(c *gin.Context) {
|
|||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Operate custom rewrite
|
||||
// @Description 编辑自定义重写模版
|
||||
// @Accept json
|
||||
// @Param request body request.CustomRewriteOperate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/rewrite/custom [post]
|
||||
func (b *BaseApi) OperateCustomRewrite(c *gin.Context) {
|
||||
var req request.CustomRewriteOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.OperateCustomRewrite(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary List custom rewrite
|
||||
// @Description 获取自定义重写模版列表
|
||||
// @Accept json
|
||||
// @Success 200 {object} []string
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/rewrite/custom [get]
|
||||
func (b *BaseApi) ListCustomRewrite(c *gin.Context) {
|
||||
res, err := websiteService.ListCustomRewrite()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@ type NginxRewriteReq struct {
|
|||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
type CustomRewriteOperate struct {
|
||||
Operate string `json:"operate" validate:"required,oneof=create delete"`
|
||||
Content string `json:"content"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type NginxRewriteUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
|
|
|
@ -134,7 +134,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), GetSitePath(*website, SiteConfDir)); err != nil {
|
||||
if err = fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), GetOpenrestyDir(SiteConfDir)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ type IWebsiteService interface {
|
|||
|
||||
GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error)
|
||||
UpdateRewriteConfig(req request.NginxRewriteUpdate) error
|
||||
OperateCustomRewrite(req request.CustomRewriteOperate) error
|
||||
ListCustomRewrite() ([]string, error)
|
||||
|
||||
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
|
||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
||||
|
@ -1431,9 +1434,11 @@ func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response
|
|||
}
|
||||
} else {
|
||||
rewriteFile := fmt.Sprintf("rewrite/%s.conf", strings.ToLower(req.Name))
|
||||
contentByte, err = nginx_conf.Rewrites.ReadFile(rewriteFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
contentByte, _ = nginx_conf.Rewrites.ReadFile(rewriteFile)
|
||||
if contentByte == nil {
|
||||
customRewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
customRewriteFile := path.Join(customRewriteDir, fmt.Sprintf("%s.conf", strings.ToLower(req.Name)))
|
||||
contentByte, err = files.NewFileOp().GetContent(customRewriteFile)
|
||||
}
|
||||
}
|
||||
return &response.NginxRewriteRes{
|
||||
|
@ -1441,6 +1446,47 @@ func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response
|
|||
}, err
|
||||
}
|
||||
|
||||
func (w WebsiteService) OperateCustomRewrite(req request.CustomRewriteOperate) error {
|
||||
rewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(rewriteDir) {
|
||||
if err := fileOp.CreateDir(rewriteDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
rewriteFile := path.Join(rewriteDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
switch req.Operate {
|
||||
case "create":
|
||||
if fileOp.Stat(rewriteFile) {
|
||||
return buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
return fileOp.WriteFile(rewriteFile, strings.NewReader(req.Content), 0755)
|
||||
case "delete":
|
||||
return fileOp.DeleteFile(rewriteFile)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) ListCustomRewrite() ([]string, error) {
|
||||
rewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(rewriteDir) {
|
||||
return nil, nil
|
||||
}
|
||||
entries, err := os.ReadDir(rewriteDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
res = append(res, strings.TrimSuffix(entry.Name(), ".conf"))
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateSiteDir(req request.WebsiteUpdateDir) error {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
|
|
|
@ -1194,19 +1194,21 @@ func GteSiteDir(alias string) string {
|
|||
}
|
||||
|
||||
const (
|
||||
SiteConf = "SiteConf"
|
||||
SiteAccessLog = "access.log"
|
||||
SiteErrorLog = "error.log"
|
||||
WebsiteRootDir = "WebsiteRootDir"
|
||||
SiteDir = "SiteDir"
|
||||
SiteIndexDir = "SiteIndexDir"
|
||||
SiteProxyDir = "SiteProxyDir"
|
||||
SiteSSLDir = "SiteSSLDir"
|
||||
SiteReWritePath = "SiteReWritePath"
|
||||
SiteRedirectDir = "SiteRedirectDir"
|
||||
SiteCacheDir = "SiteCacheDir"
|
||||
SiteConfDir = "SiteConfDir"
|
||||
SitesRootDir = "SitesRootDir"
|
||||
SiteConf = "SiteConf"
|
||||
SiteAccessLog = "access.log"
|
||||
SiteErrorLog = "error.log"
|
||||
WebsiteRootDir = "WebsiteRootDir"
|
||||
SiteDir = "SiteDir"
|
||||
SiteIndexDir = "SiteIndexDir"
|
||||
SiteProxyDir = "SiteProxyDir"
|
||||
SiteSSLDir = "SiteSSLDir"
|
||||
SiteReWritePath = "SiteReWritePath"
|
||||
SiteRedirectDir = "SiteRedirectDir"
|
||||
SiteCacheDir = "SiteCacheDir"
|
||||
SiteConfDir = "SiteConfDir"
|
||||
SitesRootDir = "SitesRootDir"
|
||||
DefaultDir = "DefaultDir"
|
||||
DefaultRewriteDir = "DefaultRewriteDir"
|
||||
)
|
||||
|
||||
func GetSitePath(website model.Website, confType string) string {
|
||||
|
@ -1217,8 +1219,6 @@ func GetSitePath(website model.Website, confType string) string {
|
|||
return path.Join(GteSiteDir(website.Alias), "log", "access.log")
|
||||
case SiteErrorLog:
|
||||
return path.Join(GteSiteDir(website.Alias), "log", "error.log")
|
||||
case WebsiteRootDir:
|
||||
return GetWebSiteRootDir()
|
||||
case SiteDir:
|
||||
return GteSiteDir(website.Alias)
|
||||
case SiteIndexDir:
|
||||
|
@ -1233,10 +1233,22 @@ func GetSitePath(website model.Website, confType string) string {
|
|||
return path.Join(GteSiteDir(website.Alias), "rewrite", website.Alias+".conf")
|
||||
case SiteRedirectDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "redirect")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetOpenrestyDir(confType string) string {
|
||||
switch confType {
|
||||
case WebsiteRootDir:
|
||||
return GetWebSiteRootDir()
|
||||
case SiteConfDir:
|
||||
return path.Join(GetWebSiteRootDir(), "conf.d")
|
||||
case SitesRootDir:
|
||||
return path.Join(GetWebSiteRootDir(), "sites")
|
||||
case DefaultDir:
|
||||
return path.Join(GetWebSiteRootDir(), "default")
|
||||
case DefaultRewriteDir:
|
||||
return path.Join(GetWebSiteRootDir(), "default", "rewrite")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
|||
|
||||
websiteRouter.POST("/rewrite", baseApi.GetRewriteConfig)
|
||||
websiteRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
|
||||
websiteRouter.POST("/rewrite/custom", baseApi.OperateCustomRewrite)
|
||||
websiteRouter.GET("/rewrite/custom", baseApi.ListCustomRewrite)
|
||||
|
||||
websiteRouter.POST("/dir/update", baseApi.UpdateSiteDir)
|
||||
websiteRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission)
|
||||
|
|
|
@ -350,6 +350,12 @@ export namespace Website {
|
|||
content: string;
|
||||
}
|
||||
|
||||
export interface CustomRewirte {
|
||||
operate: string;
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface DirUpdate {
|
||||
id: number;
|
||||
siteDir: string;
|
||||
|
|
|
@ -331,3 +331,11 @@ export const GetWebsiteDatabase = () => {
|
|||
export const ChangeDatabase = (req: Website.ChangeDatabase) => {
|
||||
return http.post(`/websites/databases`, req);
|
||||
};
|
||||
|
||||
export const OperateCustomRewrite = (req: Website.CustomRewirte) => {
|
||||
return http.post(`/websites/rewrite/custom`, req);
|
||||
};
|
||||
|
||||
export const ListCustomRewrite = () => {
|
||||
return http.get<string[]>(`/websites/rewrite/custom`);
|
||||
};
|
||||
|
|
|
@ -2244,6 +2244,7 @@ const message = {
|
|||
changeDatabase: 'Change Database',
|
||||
changeDatabaseHelper1: 'Database association is used for backing up and restoring the website.',
|
||||
changeDatabaseHelper2: 'Switching to another database will cause previous backups to be unrecoverable.',
|
||||
saveCustom: 'Save as Template',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: 'Short tag support',
|
||||
|
|
|
@ -2091,6 +2091,7 @@ const message = {
|
|||
changeDatabase: '切換資料庫',
|
||||
changeDatabaseHelper1: '資料庫關聯用於備份恢復網站。',
|
||||
changeDatabaseHelper2: '切換其他資料庫會導致以前的備份無法恢復。',
|
||||
saveCustom: '另存为模版',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短標簽支持',
|
||||
|
|
|
@ -2089,6 +2089,7 @@ const message = {
|
|||
changeDatabase: '切换数据库',
|
||||
changeDatabaseHelper1: '数据库关联用于备份恢复网站',
|
||||
changeDatabaseHelper2: '切换其他数据库会导致以前的备份无法恢复',
|
||||
saveCustom: '另存为模版',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短标签支持',
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<DrawerPro v-model="open" :header="$t('website.saveCustom')" :back="handleClose">
|
||||
<el-form ref="rewriteForm" label-position="top" :model="req" :rules="rules">
|
||||
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||
<el-input v-model="req.name"></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(rewriteForm)" :disabled="loading">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { OperateCustomRewrite } from '@/api/modules/website';
|
||||
import i18n from '@/lang';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { ref } from 'vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
|
||||
const rewriteForm = ref<FormInstance>();
|
||||
const open = ref(false);
|
||||
const loading = ref(false);
|
||||
const req = ref({
|
||||
name: '',
|
||||
operate: 'create',
|
||||
content: '',
|
||||
});
|
||||
const rules = ref({
|
||||
name: [Rules.requiredInput],
|
||||
});
|
||||
|
||||
const em = defineEmits(['close']);
|
||||
const handleClose = () => {
|
||||
rewriteForm.value?.resetFields();
|
||||
open.value = false;
|
||||
em('close', false);
|
||||
};
|
||||
|
||||
const acceptParams = async (conetnt: string) => {
|
||||
req.value.content = conetnt;
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
OperateCustomRewrite(req.value)
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
|
||||
handleClose();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
|
@ -4,11 +4,20 @@
|
|||
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)" class="p-w-200">
|
||||
<el-option :label="$t('website.current')" :value="'current'"></el-option>
|
||||
<el-option
|
||||
v-for="(rewrite, index) in Rewrites"
|
||||
v-for="(rewrite, index) in rewrites"
|
||||
:key="index"
|
||||
:label="rewrite"
|
||||
:value="rewrite"
|
||||
></el-option>
|
||||
:label="rewrite.name"
|
||||
:value="rewrite.name"
|
||||
>
|
||||
<span>{{ rewrite.name }}</span>
|
||||
<el-button
|
||||
class="float-right mt-1.5"
|
||||
v-if="rewrite.resource == 'custom'"
|
||||
link
|
||||
icon="Close"
|
||||
@click="deleteCustomRewrite(rewrite.name)"
|
||||
></el-button>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-text type="warning">{{ $t('website.rewriteHelper2') }}</el-text>
|
||||
|
@ -20,43 +29,54 @@
|
|||
<el-button type="primary" @click="submit()">
|
||||
{{ $t('nginx.saveAndReload') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="operateCustomRewrite()" :disabled="content == ''">
|
||||
{{ $t('website.saveCustom') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<CustomRewrite ref="customRef" @close="init()" />
|
||||
<OpDialog ref="deleteRef" @search="init()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { GetWebsite, GetRewriteConfig, UpdateRewriteConfig } from '@/api/modules/website';
|
||||
import {
|
||||
GetWebsite,
|
||||
GetRewriteConfig,
|
||||
UpdateRewriteConfig,
|
||||
ListCustomRewrite,
|
||||
OperateCustomRewrite,
|
||||
} from '@/api/modules/website';
|
||||
import { Rewrites } from '@/global/mimetype';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||
import i18n from '@/lang';
|
||||
import CustomRewrite from '@/views/website/website/config/basic/rewrite/custom/index.vue';
|
||||
|
||||
const loading = ref(false);
|
||||
const content = ref(' ');
|
||||
const codeRef = ref();
|
||||
|
||||
const customRef = ref();
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
|
||||
const req = reactive({
|
||||
websiteID: id.value,
|
||||
name: 'default',
|
||||
});
|
||||
|
||||
const update = reactive({
|
||||
websiteID: id.value,
|
||||
content: 'd',
|
||||
name: '',
|
||||
});
|
||||
const rewrites = ref([]);
|
||||
const deleteRef = ref();
|
||||
|
||||
const getRewriteConfig = async (rewrite: string) => {
|
||||
loading.value = true;
|
||||
|
@ -68,7 +88,6 @@ const getRewriteConfig = async (rewrite: string) => {
|
|||
if (res.data.content == '') {
|
||||
content.value = ' ';
|
||||
}
|
||||
|
||||
setCursorPosition();
|
||||
} catch (error) {
|
||||
} finally {
|
||||
|
@ -97,7 +116,41 @@ const submit = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const operateCustomRewrite = async () => {
|
||||
customRef.value.acceptParams(content.value);
|
||||
};
|
||||
|
||||
const deleteCustomRewrite = (name: string) => {
|
||||
deleteRef.value.acceptParams({
|
||||
title: i18n.global.t('commons.msg.deleteTitle'),
|
||||
names: [name],
|
||||
msg: i18n.global.t('commons.msg.operatorHelper', [
|
||||
i18n.global.t('container.template'),
|
||||
i18n.global.t('commons.button.delete'),
|
||||
]),
|
||||
api: OperateCustomRewrite,
|
||||
params: { name: name, operate: 'delete' },
|
||||
});
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
ListCustomRewrite().then((res) => {
|
||||
rewrites.value = [];
|
||||
if (res && res.data) {
|
||||
for (const d of res.data) {
|
||||
rewrites.value.push({
|
||||
resource: 'custom',
|
||||
name: d,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const r of Rewrites) {
|
||||
rewrites.value.push({
|
||||
resource: 'default',
|
||||
name: r,
|
||||
});
|
||||
}
|
||||
});
|
||||
GetWebsite(id.value).then((res) => {
|
||||
const name = res.data.rewrite == '' ? 'default' : 'current';
|
||||
if (name === 'current') {
|
||||
|
@ -105,5 +158,9 @@ onMounted(() => {
|
|||
}
|
||||
getRewriteConfig(name);
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Add table
Reference in a new issue