custon dashboard template [no ci]

This commit is contained in:
naiba 2022-06-03 09:45:11 +08:00
parent eb0501ad97
commit 2ab7a5fdd8
20 changed files with 95 additions and 37 deletions

View File

@ -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,
}))

View File

@ -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,

View File

@ -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

View File

@ -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,
}))
}

View File

@ -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": "/",
}))
}

View File

@ -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"
}

View File

@ -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,

View File

@ -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
}

View File

@ -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 = "管理后台主题"

View File

@ -1,4 +1,4 @@
{{define "dashboard/api"}}
{{define "dashboard-default/api"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">

View File

@ -1,4 +1,4 @@
{{define "dashboard/cron"}}
{{define "dashboard-default/cron"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">

View File

@ -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">

View File

@ -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">

View File

@ -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">

View File

@ -1,4 +1,4 @@
{{define "dashboard/notification"}}
{{define "dashboard-default/notification"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">

View File

@ -1,4 +1,4 @@
{{define "dashboard/redirect"}}
{{define "dashboard-default/redirect"}}
<!DOCTYPE html>
<html lang="{{.Conf.Language}}">

View File

@ -1,4 +1,4 @@
{{define "dashboard/server"}}
{{define "dashboard-default/server"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">

View File

@ -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">

View File

@ -1,4 +1,4 @@
{{define "dashboard/terminal"}}
{{define "dashboard-default/terminal"}}
<!DOCTYPE html>
<html lang="{{.Conf.Language}}">

View File

@ -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