mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 12:48:14 -05:00
✨ custon dashboard template [no ci]
This commit is contained in:
parent
eb0501ad97
commit
2ab7a5fdd8
@ -489,7 +489,7 @@ func (cp *commonPage) createTerminal(c *gin.Context) {
|
||||
useSSL: createTerminalReq.Protocol == "https:",
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "dashboard/terminal", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/terminal", mygin.CommonEnvironment(c, gin.H{
|
||||
"SessionID": id,
|
||||
"ServerName": server.Name,
|
||||
}))
|
||||
|
@ -46,7 +46,7 @@ func (gp *guestPage) login(c *gin.Context) {
|
||||
LoginType = "Jihulab"
|
||||
RegistrationLink = "https://jihulab.com/users/sign_up"
|
||||
}
|
||||
c.HTML(http.StatusOK, "dashboard/login", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/login", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
||||
"LoginType": LoginType,
|
||||
"RegistrationLink": RegistrationLink,
|
||||
|
@ -702,6 +702,7 @@ type settingForm struct {
|
||||
Admin string
|
||||
Language string
|
||||
Theme string
|
||||
DashboardTheme string
|
||||
CustomCode string
|
||||
ViewPassword string
|
||||
IgnoredIPNotification string
|
||||
@ -722,6 +723,23 @@ func (ma *memberAPI) updateSetting(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if yes, err := utils.IsDirEmpty("resource/template/theme-" + sf.Theme); err != nil || yes {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("前台主题文件异常:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if yes, err := utils.IsDirEmpty("resource/template/dashboard-" + sf.DashboardTheme); err != nil || yes {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("后台主题文件异常:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
singleton.Conf.Language = sf.Language
|
||||
singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification == "on"
|
||||
singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification == "on"
|
||||
@ -731,6 +749,7 @@ func (ma *memberAPI) updateSetting(c *gin.Context) {
|
||||
singleton.Conf.IPChangeNotificationTag = sf.IPChangeNotificationTag
|
||||
singleton.Conf.Site.Brand = sf.Title
|
||||
singleton.Conf.Site.Theme = sf.Theme
|
||||
singleton.Conf.Site.DashboardTheme = sf.DashboardTheme
|
||||
singleton.Conf.Site.CustomCode = sf.CustomCode
|
||||
singleton.Conf.Site.ViewPassword = sf.ViewPassword
|
||||
singleton.Conf.Oauth2.Admin = sf.Admin
|
||||
|
@ -34,7 +34,7 @@ func (mp *memberPage) serve() {
|
||||
func (mp *memberPage) api(c *gin.Context) {
|
||||
singleton.ApiLock.RLock()
|
||||
defer singleton.ApiLock.RUnlock()
|
||||
c.HTML(http.StatusOK, "dashboard/api", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/api", mygin.CommonEnvironment(c, gin.H{
|
||||
"title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ApiManagement"}),
|
||||
"Tokens": singleton.ApiTokenList,
|
||||
}))
|
||||
@ -43,14 +43,14 @@ func (mp *memberPage) api(c *gin.Context) {
|
||||
func (mp *memberPage) server(c *gin.Context) {
|
||||
singleton.SortedServerLock.RLock()
|
||||
defer singleton.SortedServerLock.RUnlock()
|
||||
c.HTML(http.StatusOK, "dashboard/server", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/server", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServersManagement"}),
|
||||
"Servers": singleton.SortedServerList,
|
||||
}))
|
||||
}
|
||||
|
||||
func (mp *memberPage) monitor(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "dashboard/monitor", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/monitor", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServicesManagement"}),
|
||||
"Monitors": singleton.ServiceSentinelShared.Monitors(),
|
||||
}))
|
||||
@ -59,7 +59,7 @@ func (mp *memberPage) monitor(c *gin.Context) {
|
||||
func (mp *memberPage) cron(c *gin.Context) {
|
||||
var crons []model.Cron
|
||||
singleton.DB.Find(&crons)
|
||||
c.HTML(http.StatusOK, "dashboard/cron", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/cron", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ScheduledTasks"}),
|
||||
"Crons": crons,
|
||||
}))
|
||||
@ -70,7 +70,7 @@ func (mp *memberPage) notification(c *gin.Context) {
|
||||
singleton.DB.Find(&nf)
|
||||
var ar []model.AlertRule
|
||||
singleton.DB.Find(&ar)
|
||||
c.HTML(http.StatusOK, "dashboard/notification", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/notification", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Notification"}),
|
||||
"Notifications": nf,
|
||||
"AlertRules": ar,
|
||||
@ -78,9 +78,10 @@ func (mp *memberPage) notification(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (mp *memberPage) setting(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "dashboard/setting", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
||||
"Languages": model.Languages,
|
||||
"Themes": model.Themes,
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/setting", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
||||
"Languages": model.Languages,
|
||||
"Themes": model.Themes,
|
||||
"DashboardThemes": model.DashboardThemes,
|
||||
}))
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func (oa *oauth2controller) login(c *gin.Context) {
|
||||
singleton.Cache.Set(fmt.Sprintf("%s%s", model.CacheKeyOauth2State, stateKey), state, cache.DefaultExpiration)
|
||||
url := oa.getCommonOauth2Config(c).AuthCodeURL(state, oauth2.AccessTypeOnline)
|
||||
c.SetCookie(singleton.Conf.Site.CookieName+"-sk", stateKey, 60*5, "", "", false, false)
|
||||
c.HTML(http.StatusOK, "dashboard/redirect", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/redirect", mygin.CommonEnvironment(c, gin.H{
|
||||
"URL": url,
|
||||
}))
|
||||
}
|
||||
@ -172,7 +172,7 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
||||
user.IssueNewToken()
|
||||
singleton.DB.Save(&user)
|
||||
c.SetCookie(singleton.Conf.Site.CookieName, user.Token, 60*60*24, "", "", false, false)
|
||||
c.HTML(http.StatusOK, "dashboard/redirect", mygin.CommonEnvironment(c, gin.H{
|
||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/redirect", mygin.CommonEnvironment(c, gin.H{
|
||||
"URL": "/",
|
||||
}))
|
||||
}
|
||||
|
@ -21,7 +21,12 @@ var Themes = map[string]string{
|
||||
"daynight": "JackieSung DayNight",
|
||||
"mdui": "Neko Mdui",
|
||||
"hotaru": "Hotaru",
|
||||
"custom": "Custom(third-party)",
|
||||
"custom": "Custom(local)",
|
||||
}
|
||||
|
||||
var DashboardThemes = map[string]string{
|
||||
"default": "Default",
|
||||
"custom": "Custom(local)",
|
||||
}
|
||||
|
||||
const (
|
||||
@ -70,11 +75,12 @@ type Config struct {
|
||||
Debug bool // debug模式开关
|
||||
Language string // 系统语言,默认 zh-CN
|
||||
Site struct {
|
||||
Brand string // 站点名称
|
||||
CookieName string // 浏览器 Cookie 名称
|
||||
Theme string
|
||||
CustomCode string
|
||||
ViewPassword string // 前台查看密码
|
||||
Brand string // 站点名称
|
||||
CookieName string // 浏览器 Cookie 名称
|
||||
Theme string
|
||||
DashboardTheme string
|
||||
CustomCode string
|
||||
ViewPassword string // 前台查看密码
|
||||
}
|
||||
Oauth2 struct {
|
||||
Type string
|
||||
@ -117,6 +123,9 @@ func (c *Config) Read(path string) error {
|
||||
if c.Site.Theme == "" {
|
||||
c.Site.Theme = "default"
|
||||
}
|
||||
if c.Site.DashboardTheme == "" {
|
||||
c.Site.DashboardTheme = "default"
|
||||
}
|
||||
if c.Language == "" {
|
||||
c.Language = "zh-CN"
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
)
|
||||
|
||||
type ErrInfo struct {
|
||||
@ -18,7 +19,7 @@ type ErrInfo struct {
|
||||
|
||||
func ShowErrorPage(c *gin.Context, i ErrInfo, isPage bool) {
|
||||
if isPage {
|
||||
c.HTML(i.Code, "dashboard/error", CommonEnvironment(c, gin.H{
|
||||
c.HTML(i.Code, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/error", CommonEnvironment(c, gin.H{
|
||||
"Code": i.Code,
|
||||
"Title": i.Title,
|
||||
"Msg": i.Msg,
|
||||
|
@ -3,6 +3,7 @@ package utils
|
||||
import (
|
||||
"crypto/md5" // #nosec
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"regexp"
|
||||
@ -93,3 +94,17 @@ func SplitIPAddr(v4v6Bundle string) (string, string, string) {
|
||||
}
|
||||
return ipv4, ipv6, validIP
|
||||
}
|
||||
|
||||
func IsDirEmpty(name string) (bool, error) {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.Readdirnames(1)
|
||||
if err == io.EOF {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
13
resource/l10n/zh-CN.toml
vendored
13
resource/l10n/zh-CN.toml
vendored
@ -470,19 +470,19 @@ other = "服务监控"
|
||||
other = "计划任务"
|
||||
|
||||
[ApiManagement]
|
||||
other="API"
|
||||
other = "API"
|
||||
|
||||
[IssueNewApiToken]
|
||||
other="添加Token"
|
||||
other = "添加Token"
|
||||
|
||||
[Token]
|
||||
other="Token"
|
||||
other = "Token"
|
||||
|
||||
[DeleteToken]
|
||||
other="删除Token"
|
||||
other = "删除Token"
|
||||
|
||||
[ConfirmToDeleteThisToken]
|
||||
other="确认删除Token"
|
||||
other = "确认删除Token"
|
||||
|
||||
[YouAreNotAuthorized]
|
||||
other = "此页面需要登录"
|
||||
@ -531,3 +531,6 @@ other = "IP变更"
|
||||
|
||||
[Transleft]
|
||||
other = "流量剩余"
|
||||
|
||||
[DashboardTheme]
|
||||
other = "管理后台主题"
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/api"}}
|
||||
{{define "dashboard-default/api"}}
|
||||
{{template "common/header" .}}
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/cron"}}
|
||||
{{define "dashboard-default/cron"}}
|
||||
{{template "common/header" .}}
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/error"}}
|
||||
{{define "dashboard-default/error"}}
|
||||
{{template "common/header" .}}
|
||||
<div class="login nb-container">
|
||||
<div class="ui center aligned grid">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/login"}}
|
||||
{{define "dashboard-default/login"}}
|
||||
{{template "common/header" .}}
|
||||
<div class="login nb-container">
|
||||
<div class="ui center aligned grid">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/monitor"}} {{template "common/header" .}} {{template
|
||||
{{define "dashboard-default/monitor"}} {{template "common/header" .}} {{template
|
||||
"common/menu" .}}
|
||||
<div class="nb-container">
|
||||
<div class="ui container">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/notification"}}
|
||||
{{define "dashboard-default/notification"}}
|
||||
{{template "common/header" .}}
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/redirect"}}
|
||||
{{define "dashboard-default/redirect"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{.Conf.Language}}">
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/server"}}
|
||||
{{define "dashboard-default/server"}}
|
||||
{{template "common/header" .}}
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/setting"}}
|
||||
{{define "dashboard-default/setting"}}
|
||||
{{template "common/header" .}}
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
@ -20,6 +20,14 @@
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{tr "DashboardTheme"}}</label>
|
||||
<select name="DashboardTheme">
|
||||
{{range $k,$v := .DashboardThemes}}
|
||||
<option value="{{$k}}" {{if eq $.Conf.Site.DashboardTheme $k }} selected="selected" {{end}}>{{$v}}
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Language</label>
|
||||
<select name="Language">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "dashboard/terminal"}}
|
||||
{{define "dashboard-default/terminal"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{.Conf.Language}}">
|
||||
|
||||
|
@ -6,8 +6,10 @@ services:
|
||||
restart: always
|
||||
volumes:
|
||||
- ./data:/dashboard/data
|
||||
- ./theme-custom/template:/dashboard/resuorce/template/theme-default:ro
|
||||
- ./theme-custom/static:/dashboard/resuorce/static/theme-default:ro
|
||||
- ./theme-custom/template:/dashboard/resuorce/template/theme-custom:ro
|
||||
- ./theme-custom/static:/dashboard/resuorce/static/theme-custom:ro
|
||||
- ./dashboard-custom/template:/dashboard/resuorce/template/dashboard-custom:ro
|
||||
- ./dashboard-custom/static:/dashboard/resuorce/static/dashboard-custom:ro
|
||||
ports:
|
||||
- nz_site_port:80
|
||||
- nz_grpc_port:nz_grpc_port
|
||||
|
Loading…
Reference in New Issue
Block a user