mirror of https://github.com/1Panel-dev/1Panel
feat: 网站日志页面优化
parent
48054b05ce
commit
28de822917
|
@ -320,3 +320,17 @@ func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) {
|
|||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) OpWebsiteLog(c *gin.Context) {
|
||||
var req request.WebsiteLogReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
res, err := websiteService.OpWebsiteLog(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
|
|
@ -116,3 +116,9 @@ type WebsiteNginxUpdate struct {
|
|||
ID uint `json:"id" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteLogReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
LogType string `json:"logType" validate:"required"`
|
||||
}
|
||||
|
|
|
@ -36,3 +36,8 @@ type WebsiteHTTPS struct {
|
|||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
}
|
||||
|
||||
type WebsiteLog struct {
|
||||
Enable bool `json:"enable"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ type Website struct {
|
|||
WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
||||
WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
||||
Proxy string `gorm:"type:varchar(128);not null" json:"proxy"`
|
||||
ErrorLog bool `json:"errorLog"`
|
||||
AccessLog bool `json:"accessLog"`
|
||||
Domains []WebsiteDomain `json:"domains"`
|
||||
WebsiteSSL WebsiteSSL `json:"webSiteSSL"`
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ func getNginxParamsByKeys(scope string, keys []string, website *model.Website) (
|
|||
}
|
||||
|
||||
func updateNginxConfig(scope string, params []dto.NginxParam, website *model.Website) error {
|
||||
|
||||
nginxFull, err := getNginxFull(website)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -49,6 +49,8 @@ type IWebsiteService interface {
|
|||
PreInstallCheck(req request.WebsiteInstallCheckReq) ([]response.WebsitePreInstallCheck, error)
|
||||
GetWafConfig(req request.WebsiteWafReq) (response.WebsiteWafConfig, error)
|
||||
UpdateWafConfig(req request.WebsiteWafUpdate) error
|
||||
UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error
|
||||
OpWebsiteLog(req request.WebsiteLogReq) (*response.WebsiteLog, error)
|
||||
}
|
||||
|
||||
func NewWebsiteService() IWebsiteService {
|
||||
|
@ -707,3 +709,71 @@ func (w WebsiteService) UpdateNginxConfigFile(req request.WebsiteNginxUpdate) er
|
|||
}
|
||||
return nginxCheckAndReload(nginxFull.SiteConfig.OldContent, filePath, nginxFull.Install.ContainerName)
|
||||
}
|
||||
|
||||
func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.WebsiteLog, error) {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nginx, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sitePath := path.Join(nginx.SiteDir, "sites", website.Alias)
|
||||
res := &response.WebsiteLog{
|
||||
Content: "",
|
||||
}
|
||||
switch req.Operate {
|
||||
case constant.GetLog:
|
||||
switch req.LogType {
|
||||
case constant.AccessLog:
|
||||
res.Enable = website.AccessLog
|
||||
if !website.AccessLog {
|
||||
return res, nil
|
||||
}
|
||||
case constant.ErrorLog:
|
||||
res.Enable = website.ErrorLog
|
||||
if !website.ErrorLog {
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
content, err := os.ReadFile(path.Join(sitePath, "log", req.LogType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Content = string(content)
|
||||
return res, nil
|
||||
case constant.DisableLog:
|
||||
key := "access_log"
|
||||
switch req.LogType {
|
||||
case constant.AccessLog:
|
||||
website.AccessLog = false
|
||||
case constant.ErrorLog:
|
||||
key = "error_log"
|
||||
website.ErrorLog = false
|
||||
}
|
||||
if err := deleteNginxConfig(constant.NginxScopeServer, []string{key}, &website); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := websiteRepo.Save(context.Background(), &website); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case constant.EnableLog:
|
||||
key := "access_log"
|
||||
logPath := path.Join("/www", "sites", website.Alias, "log", req.LogType)
|
||||
switch req.LogType {
|
||||
case constant.AccessLog:
|
||||
website.AccessLog = true
|
||||
case constant.ErrorLog:
|
||||
key = "error_log"
|
||||
website.ErrorLog = true
|
||||
}
|
||||
if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: key, Params: []string{logPath}}}, &website); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := websiteRepo.Save(context.Background(), &website); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -32,4 +32,11 @@ const (
|
|||
HTTPSOnly = "HTTPSOnly"
|
||||
HTTPAlso = "HTTPAlso"
|
||||
HTTPToHTTPS = "HTTPToHTTPS"
|
||||
|
||||
GetLog = "get"
|
||||
DisableLog = "disable"
|
||||
EnableLog = "enable"
|
||||
|
||||
AccessLog = "access.log"
|
||||
ErrorLog = "error.log"
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
|
|||
groupRouter.POST("/search", baseApi.PageWebsite)
|
||||
groupRouter.POST("", baseApi.CreateWebsite)
|
||||
groupRouter.POST("/operate", baseApi.OpWebsite)
|
||||
groupRouter.POST("/log", baseApi.OpWebsiteLog)
|
||||
groupRouter.POST("/check", baseApi.CreateWebsiteCheck)
|
||||
groupRouter.GET("/options", baseApi.GetWebsiteOptions)
|
||||
groupRouter.POST("/update", baseApi.UpdateWebsite)
|
||||
|
|
|
@ -76,6 +76,17 @@ export namespace Website {
|
|||
operate: string;
|
||||
}
|
||||
|
||||
export interface WebSiteOpLog {
|
||||
id: number;
|
||||
operate: string;
|
||||
logType: string;
|
||||
}
|
||||
|
||||
export interface WebSiteLog {
|
||||
enable: boolean;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface Group extends CommonModel {
|
||||
name: string;
|
||||
default: boolean;
|
||||
|
|
|
@ -15,6 +15,10 @@ export const OpWebsite = (req: Website.WebSiteOp) => {
|
|||
return http.post<any>(`/websites/operate`, req);
|
||||
};
|
||||
|
||||
export const OpWebsiteLog = (req: Website.WebSiteOpLog) => {
|
||||
return http.post<Website.WebSiteLog>(`/websites/log`, req);
|
||||
};
|
||||
|
||||
export const BackupWebsite = (req: Website.BackupReq) => {
|
||||
return http.post(`/websites/backup`, req);
|
||||
};
|
||||
|
|
|
@ -952,6 +952,7 @@ export default {
|
|||
ever: '永久',
|
||||
nextYear: '一年后',
|
||||
allGroup: '所有分组',
|
||||
noLog: '当前没有日志...',
|
||||
},
|
||||
nginx: {
|
||||
serverNamesHashBucketSizeHelper: '服务器名字的hash表大小',
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
<template>
|
||||
<el-tabs tab-position="left" type="border-card" v-model="index">
|
||||
<el-tab-pane :label="$t('website.accessLog')" name="0">
|
||||
<LogFile :path="website.accessLogPath" v-if="index == '0'"></LogFile>
|
||||
<LogFile :id="id" :log-type="'access.log'" v-if="index == '0'"></LogFile>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('website.errLog')" name="1">
|
||||
<LogFile :path="website.errorLogPath" v-if="index == '1'"></LogFile>
|
||||
<LogFile :id="id" :log-type="'error.log'" v-if="index == '1'"></LogFile>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { GetWebsite } from '@/api/modules/website';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import LogFile from './log-fiile/index.vue';
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -24,23 +23,5 @@ const id = computed(() => {
|
|||
return props.id;
|
||||
});
|
||||
|
||||
let loading = ref(false);
|
||||
let website = ref();
|
||||
let index = ref('-1');
|
||||
|
||||
const getWebsite = () => {
|
||||
loading.value = true;
|
||||
GetWebsite(id.value)
|
||||
.then((res) => {
|
||||
website.value = res.data;
|
||||
index.value = '0';
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getWebsite();
|
||||
});
|
||||
let index = ref('0');
|
||||
</script>
|
||||
|
|
|
@ -1,46 +1,81 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-form-item prop="enable" :label="$t('website.enable')">
|
||||
<el-switch v-model="data.enable" @change="updateEnable"></el-switch>
|
||||
</el-form-item>
|
||||
<codemirror
|
||||
style="max-height: 500px; width: 100%; min-height: 200px"
|
||||
:autofocus="true"
|
||||
placeholder="None data"
|
||||
:placeholder="$t('website.noLog')"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="margin-top: 10px; max-height: 500px"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
:styleActiveLine="true"
|
||||
:extensions="extensions"
|
||||
v-model="content"
|
||||
v-model="data.content"
|
||||
:readOnly="true"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { GetFileContent } from '@/api/modules/files';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { OpWebsiteLog } from '@/api/modules/website';
|
||||
|
||||
const extensions = [javascript(), oneDark];
|
||||
const props = defineProps({
|
||||
path: {
|
||||
logType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
const path = computed(() => {
|
||||
return props.path;
|
||||
const logType = computed(() => {
|
||||
return props.logType;
|
||||
});
|
||||
const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
let loading = ref(false);
|
||||
let content = ref('');
|
||||
let data = ref({
|
||||
enable: false,
|
||||
content: '',
|
||||
});
|
||||
|
||||
const getContent = () => {
|
||||
const req = {
|
||||
id: id.value,
|
||||
operate: 'get',
|
||||
logType: logType.value,
|
||||
};
|
||||
loading.value = true;
|
||||
GetFileContent({ path: path.value, expand: false, page: 1, pageSize: 1 })
|
||||
OpWebsiteLog(req)
|
||||
.then((res) => {
|
||||
content.value = res.data.content;
|
||||
data.value = res.data;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const updateEnable = () => {
|
||||
const operate = data.value.enable ? 'enable' : 'disable';
|
||||
const req = {
|
||||
id: id.value,
|
||||
operate: operate,
|
||||
logType: logType.value,
|
||||
};
|
||||
loading.value = true;
|
||||
OpWebsiteLog(req)
|
||||
.then(() => {
|
||||
getContent();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
|
|
Loading…
Reference in New Issue