mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-12 10:55:51 +02:00
feat: Online modify settings #32
This commit is contained in:
parent
65b192c8be
commit
0f58c86613
8 changed files with 130 additions and 31 deletions
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
|
@ -21,6 +21,7 @@ declare module '@vue/runtime-core' {
|
||||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||||
AInput: typeof import('ant-design-vue/es')['Input']
|
AInput: typeof import('ant-design-vue/es')['Input']
|
||||||
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
||||||
|
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||||
ALayout: typeof import('ant-design-vue/es')['Layout']
|
ALayout: typeof import('ant-design-vue/es')['Layout']
|
||||||
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
||||||
|
|
12
frontend/src/api/settings.ts
Normal file
12
frontend/src/api/settings.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import http from '@/lib/http'
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
get() {
|
||||||
|
return http.get('/settings')
|
||||||
|
},
|
||||||
|
save(data: any) {
|
||||||
|
return http.post('/settings', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default settings
|
|
@ -40,7 +40,7 @@ function save() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="dir-editor-item">
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper">
|
||||||
<code-editor v-if="directive.directive === If" v-model:content="directive.params"
|
<code-editor v-if="directive.directive === If" v-model:content="directive.params"
|
||||||
defaultHeight="100px" style="width: 100%;"/>
|
defaultHeight="100px" style="width: 100%;"/>
|
||||||
|
@ -71,7 +71,7 @@ function save() {
|
||||||
<a-form-item :label="$gettext('Comments')">
|
<a-form-item :label="$gettext('Comments')">
|
||||||
<a-textarea v-model:value="directive.comments"/>
|
<a-textarea v-model:value="directive.comments"/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item :label="$gettext('Include Content')" v-if="directive.directive==='include'">
|
<a-form-item :label="$gettext('Content')" v-if="directive.directive==='include'">
|
||||||
<code-editor v-model:content="content"
|
<code-editor v-model:content="content"
|
||||||
defaultHeight="200px" style="width: 100%;"/>
|
defaultHeight="200px" style="width: 100%;"/>
|
||||||
<div class="save-btn">
|
<div class="save-btn">
|
||||||
|
@ -87,6 +87,10 @@ function save() {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.dir-editor-item {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.directive-editor-extra {
|
.directive-editor-extra {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
|
@ -116,6 +120,5 @@ function save() {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 15px 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,22 +1,45 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {useGettext} from 'vue3-gettext'
|
import {useGettext} from 'vue3-gettext'
|
||||||
import {reactive} from 'vue'
|
import {reactive, ref} from 'vue'
|
||||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||||
import {useSettingsStore} from '@/pinia'
|
import {useSettingsStore} from '@/pinia'
|
||||||
import {dark_mode} from '@/lib/theme'
|
import {dark_mode} from '@/lib/theme'
|
||||||
|
import settings from '@/api/settings'
|
||||||
|
import {message} from 'ant-design-vue'
|
||||||
|
|
||||||
const {$gettext} = useGettext()
|
const {$gettext} = useGettext()
|
||||||
|
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
|
const theme = ref('auto')
|
||||||
|
const data = ref({
|
||||||
|
server: {
|
||||||
|
http_port: 9000,
|
||||||
|
run_mode: 'debug',
|
||||||
|
jwt_secret: '',
|
||||||
|
start_cmd: '',
|
||||||
|
email: '',
|
||||||
|
http_challenge_port: 9180
|
||||||
|
},
|
||||||
|
nginx_log: {
|
||||||
|
access_log_path: '',
|
||||||
|
error_log_path: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const data = reactive({
|
settings.get().then(r => {
|
||||||
theme: settingsStore.theme
|
data.value = r
|
||||||
})
|
})
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
settingsStore.set_theme(data.theme)
|
settingsStore.set_theme(theme.value)
|
||||||
settingsStore.set_preference_theme(data.theme)
|
settingsStore.set_preference_theme(theme.value)
|
||||||
dark_mode(data.theme === 'dark')
|
dark_mode(theme.value === 'dark')
|
||||||
|
settings.save(data.value).then(r => {
|
||||||
|
data.value = r
|
||||||
|
message.success($gettext('Save successfully'))
|
||||||
|
}).catch(e => {
|
||||||
|
message.error(e?.message ?? $gettext('Server error'))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -24,8 +47,23 @@ function save() {
|
||||||
<a-card :title="$gettext('Preference')">
|
<a-card :title="$gettext('Preference')">
|
||||||
<div class="preference-container">
|
<div class="preference-container">
|
||||||
<a-form layout="vertical">
|
<a-form layout="vertical">
|
||||||
|
<a-form-item :label="$gettext('HTTP Port')">
|
||||||
|
<p>{{ data.server.http_port }}</p>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Run Mode')">
|
||||||
|
<p>{{ data.server.run_mode }}</p>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Jwt Secret')">
|
||||||
|
<p>{{ data.server.jwt_secret }}</p>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Terminal Start Command')">
|
||||||
|
<p>{{ data.server.start_cmd }}</p>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('HTTP Challenge Port')">
|
||||||
|
<a-input-number v-model:value="data.server.http_challenge_port"/>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item :label="$gettext('Theme')">
|
<a-form-item :label="$gettext('Theme')">
|
||||||
<a-select v-model:value="data.theme">
|
<a-select v-model:value="theme">
|
||||||
<a-select-option value="auto">
|
<a-select-option value="auto">
|
||||||
{{ $gettext('Auto') }}
|
{{ $gettext('Auto') }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
|
@ -37,6 +75,12 @@ function save() {
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Nginx Access Log Path')">
|
||||||
|
<a-input v-model:value="data.nginx_log.access_log_path"/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Nginx Error Log Path')">
|
||||||
|
<a-input v-model:value="data.nginx_log.error_log_path"/>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
38
server/api/settings.go
Normal file
38
server/api/settings.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSettings(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"server": settings.ServerSettings,
|
||||||
|
"nginx_log": settings.NginxLogSettings,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func SaveSettings(c *gin.Context) {
|
||||||
|
var json struct {
|
||||||
|
Server settings.Server `json:"server"`
|
||||||
|
NginxLog settings.NginxLog `json:"nginx_log"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if !BindAndValid(c, &json) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Conf.Section("server").Key("Email").SetValue(json.Server.Email)
|
||||||
|
settings.Conf.Section("server").Key("HTTPChallengePort").SetValue(json.Server.HTTPChallengePort)
|
||||||
|
settings.Conf.Section("nginx_log").Key("AccessLogPath").SetValue(json.NginxLog.AccessLogPath)
|
||||||
|
settings.Conf.Section("nginx_log").Key("ErrorLogPath").SetValue(json.NginxLog.ErrorLogPath)
|
||||||
|
|
||||||
|
err := settings.Save()
|
||||||
|
if err != nil {
|
||||||
|
ErrHandler(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSettings(c)
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ package router
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"github.com/0xJacky/Nginx-UI/server/api"
|
"github.com/0xJacky/Nginx-UI/server/api"
|
||||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
|
||||||
"github.com/gin-contrib/static"
|
"github.com/gin-contrib/static"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -34,13 +33,6 @@ func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
root := r.Group("/api")
|
root := r.Group("/api")
|
||||||
{
|
{
|
||||||
|
|
||||||
root.GET("settings", func(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"demo": settings.ServerSettings.Demo,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
root.GET("install", api.InstallLockCheck)
|
root.GET("install", api.InstallLockCheck)
|
||||||
root.POST("install", api.InstallNginxUI)
|
root.POST("install", api.InstallNginxUI)
|
||||||
|
|
||||||
|
@ -96,6 +88,10 @@ func InitRouter() *gin.Engine {
|
||||||
// Nginx log
|
// Nginx log
|
||||||
g.GET("nginx_log", api.NginxLog)
|
g.GET("nginx_log", api.NginxLog)
|
||||||
g.POST("nginx_log", api.GetNginxLogPage)
|
g.POST("nginx_log", api.GetNginxLogPage)
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
g.GET("settings", api.GetSettings)
|
||||||
|
g.POST("settings", api.SaveSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,22 +16,21 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
HttpPort string
|
HttpPort string `json:"http_port"`
|
||||||
RunMode string
|
RunMode string `json:"run_mode"`
|
||||||
WebSocketToken string
|
JwtSecret string `json:"jwt_secret"`
|
||||||
JwtSecret string
|
HTTPChallengePort string `json:"http_challenge_port"`
|
||||||
HTTPChallengePort string
|
Email string `json:"email"`
|
||||||
Email string
|
Database string `json:"database"`
|
||||||
Database string
|
StartCmd string `json:"start_cmd"`
|
||||||
StartCmd string
|
CADir string `json:"ca_dir"`
|
||||||
CADir string
|
Demo bool `json:"demo"`
|
||||||
Demo bool
|
PageSize int `json:"page_size"`
|
||||||
PageSize int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NginxLog struct {
|
type NginxLog struct {
|
||||||
AccessLogPath string
|
AccessLogPath string `json:"access_log_path"`
|
||||||
ErrorLogPath string
|
ErrorLogPath string `json:"error_log_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var ServerSettings = &Server{
|
var ServerSettings = &Server{
|
||||||
|
|
6
template/template.go
Normal file
6
template/template.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package template
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *
|
||||||
|
var DistFS embed.FS
|
Loading…
Add table
Add a link
Reference in a new issue