mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-04 12:40:07 +00:00
🌐 dashboard v0.13.1 improve localization
This commit is contained in:
@@ -2,7 +2,6 @@ package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
@@ -60,16 +60,18 @@ func (p *commonPage) issueViewPassword(c *gin.Context) {
|
||||
err := c.ShouldBind(&vpf)
|
||||
var hash []byte
|
||||
if err == nil && vpf.Password != singleton.Conf.Site.ViewPassword {
|
||||
err = errors.New("查看密码错误")
|
||||
err = errors.New(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "WrongAccessPassword"}))
|
||||
}
|
||||
if err == nil {
|
||||
hash, err = bcrypt.GenerateFromPassword([]byte(vpf.Password), bcrypt.DefaultCost)
|
||||
}
|
||||
if err != nil {
|
||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
Code: http.StatusOK,
|
||||
Title: "出现错误",
|
||||
Msg: fmt.Sprintf("请求错误:%s", err),
|
||||
Code: http.StatusOK,
|
||||
Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "AnErrorEccurred",
|
||||
}),
|
||||
Msg: err.Error(),
|
||||
}, true)
|
||||
c.Abort()
|
||||
return
|
||||
@@ -92,7 +94,7 @@ func (p *commonPage) checkViewPassword(c *gin.Context) {
|
||||
viewPassword, _ := c.Cookie(singleton.Conf.Site.CookieName + "-vp")
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(singleton.Conf.Site.ViewPassword)); err != nil {
|
||||
c.HTML(http.StatusOK, "theme-"+singleton.Conf.Site.Theme+"/viewpassword", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": "验证查看密码",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}),
|
||||
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||
}))
|
||||
c.Abort()
|
||||
@@ -116,7 +118,7 @@ func (p *commonPage) service(c *gin.Context) {
|
||||
}, nil
|
||||
})
|
||||
c.HTML(http.StatusOK, "theme-"+singleton.Conf.Site.Theme+"/service", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": "服务状态",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServicesStatus"}),
|
||||
"Services": res.([]interface{})[0],
|
||||
"CycleTransferStats": res.([]interface{})[1],
|
||||
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||
@@ -139,11 +141,13 @@ func (cp *commonPage) home(c *gin.Context) {
|
||||
stat, err := cp.getServerStat()
|
||||
if err != nil {
|
||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: "系统错误",
|
||||
Msg: "服务器状态获取失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "SystemError",
|
||||
}),
|
||||
Msg: "服务器状态获取失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
}, true)
|
||||
return
|
||||
}
|
||||
@@ -167,11 +171,13 @@ func (cp *commonPage) ws(c *gin.Context) {
|
||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: "网络错误",
|
||||
Msg: "Websocket协议切换失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "NetowrkError",
|
||||
}),
|
||||
Msg: "Websocket协议切换失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
}, true)
|
||||
return
|
||||
}
|
||||
@@ -312,11 +318,13 @@ func (cp *commonPage) terminal(c *gin.Context) {
|
||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: "网络错误",
|
||||
Msg: "Websocket协议切换失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "NetowrkError",
|
||||
}),
|
||||
Msg: "Websocket协议切换失败",
|
||||
Link: "/",
|
||||
Btn: "返回首页",
|
||||
}, true)
|
||||
return
|
||||
}
|
||||
@@ -447,11 +455,13 @@ func (cp *commonPage) createTerminal(c *gin.Context) {
|
||||
id, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: "系统错误",
|
||||
Msg: "生成会话ID失败",
|
||||
Link: "/server",
|
||||
Btn: "返回重试",
|
||||
Code: http.StatusInternalServerError,
|
||||
Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "SystemError",
|
||||
}),
|
||||
Msg: "生成会话ID失败",
|
||||
Link: "/server",
|
||||
Btn: "返回重试",
|
||||
}, true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -26,116 +26,7 @@ func ServeWeb(port uint) *http.Server {
|
||||
pprof.Register(r)
|
||||
}
|
||||
r.Use(mygin.RecordPath)
|
||||
r.SetFuncMap(template.FuncMap{
|
||||
"tr": func(id string, dataAndCount ...interface{}) string {
|
||||
conf := i18n.LocalizeConfig{
|
||||
MessageID: id,
|
||||
}
|
||||
if len(dataAndCount) > 0 {
|
||||
conf.TemplateData = dataAndCount[0]
|
||||
}
|
||||
if len(dataAndCount) > 1 {
|
||||
conf.PluralCount = dataAndCount[1]
|
||||
}
|
||||
return singleton.Localizer.MustLocalize(&conf)
|
||||
},
|
||||
"toValMap": func(val interface{}) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"Value": val,
|
||||
}
|
||||
},
|
||||
"tf": func(t time.Time) string {
|
||||
return t.In(singleton.Loc).Format("2006年1月2号 15:04:05")
|
||||
},
|
||||
"len": func(slice []interface{}) string {
|
||||
return strconv.Itoa(len(slice))
|
||||
},
|
||||
"safe": func(s string) template.HTML {
|
||||
return template.HTML(s) // #nosec
|
||||
},
|
||||
"tag": func(s string) template.HTML {
|
||||
return template.HTML(`<` + s + `>`) // #nosec
|
||||
},
|
||||
"stf": func(s uint64) string {
|
||||
return time.Unix(int64(s), 0).In(singleton.Loc).Format("2006年1月2号 15:04")
|
||||
},
|
||||
"sf": func(duration uint64) string {
|
||||
return time.Duration(time.Duration(duration) * time.Second).String()
|
||||
},
|
||||
"sft": func(future time.Time) string {
|
||||
return time.Until(future).Round(time.Second).String()
|
||||
},
|
||||
"bf": func(b uint64) string {
|
||||
return bytefmt.ByteSize(b)
|
||||
},
|
||||
"ts": func(s string) string {
|
||||
return strings.TrimSpace(s)
|
||||
},
|
||||
"float32f": func(f float32) string {
|
||||
return fmt.Sprintf("%.2f", f)
|
||||
},
|
||||
"divU64": func(a, b uint64) float32 {
|
||||
if b == 0 {
|
||||
if a > 0 {
|
||||
return 100
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if a == 0 {
|
||||
// 这是从未在线的情况
|
||||
return 0.00001 / float32(b) * 100
|
||||
}
|
||||
return float32(a) / float32(b) * 100
|
||||
},
|
||||
"div": func(a, b int) float32 {
|
||||
if b == 0 {
|
||||
if a > 0 {
|
||||
return 100
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if a == 0 {
|
||||
// 这是从未在线的情况
|
||||
return 0.00001 / float32(b) * 100
|
||||
}
|
||||
return float32(a) / float32(b) * 100
|
||||
},
|
||||
"addU64": func(a, b uint64) uint64 {
|
||||
return a + b
|
||||
},
|
||||
"add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
"dayBefore": func(i int) string {
|
||||
year, month, day := time.Now().Date()
|
||||
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
||||
return today.AddDate(0, 0, i-29).Format("1月2号")
|
||||
},
|
||||
"className": func(percent float32) string {
|
||||
if percent == 0 {
|
||||
return ""
|
||||
}
|
||||
if percent > 95 {
|
||||
return "good"
|
||||
}
|
||||
if percent > 80 {
|
||||
return "warning"
|
||||
}
|
||||
return "danger"
|
||||
},
|
||||
"statusName": func(percent float32) string {
|
||||
if percent == 0 {
|
||||
return "无数据"
|
||||
}
|
||||
if percent > 95 {
|
||||
return "良好"
|
||||
}
|
||||
if percent > 80 {
|
||||
return "低可用"
|
||||
}
|
||||
return "故障"
|
||||
},
|
||||
})
|
||||
r.SetFuncMap(funcMap)
|
||||
r.Static("/static", "resource/static")
|
||||
r.LoadHTMLGlob("resource/template/**/*.html")
|
||||
routers(r)
|
||||
@@ -176,3 +67,114 @@ func routers(r *gin.Engine) {
|
||||
ma.serve()
|
||||
}
|
||||
}
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"tr": func(id string, dataAndCount ...interface{}) string {
|
||||
conf := i18n.LocalizeConfig{
|
||||
MessageID: id,
|
||||
}
|
||||
if len(dataAndCount) > 0 {
|
||||
conf.TemplateData = dataAndCount[0]
|
||||
}
|
||||
if len(dataAndCount) > 1 {
|
||||
conf.PluralCount = dataAndCount[1]
|
||||
}
|
||||
return singleton.Localizer.MustLocalize(&conf)
|
||||
},
|
||||
"toValMap": func(val interface{}) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"Value": val,
|
||||
}
|
||||
},
|
||||
"tf": func(t time.Time) string {
|
||||
return t.In(singleton.Loc).Format("2006年1月2号 15:04:05")
|
||||
},
|
||||
"len": func(slice []interface{}) string {
|
||||
return strconv.Itoa(len(slice))
|
||||
},
|
||||
"safe": func(s string) template.HTML {
|
||||
return template.HTML(s) // #nosec
|
||||
},
|
||||
"tag": func(s string) template.HTML {
|
||||
return template.HTML(`<` + s + `>`) // #nosec
|
||||
},
|
||||
"stf": func(s uint64) string {
|
||||
return time.Unix(int64(s), 0).In(singleton.Loc).Format("2006年1月2号 15:04")
|
||||
},
|
||||
"sf": func(duration uint64) string {
|
||||
return time.Duration(time.Duration(duration) * time.Second).String()
|
||||
},
|
||||
"sft": func(future time.Time) string {
|
||||
return time.Until(future).Round(time.Second).String()
|
||||
},
|
||||
"bf": func(b uint64) string {
|
||||
return bytefmt.ByteSize(b)
|
||||
},
|
||||
"ts": func(s string) string {
|
||||
return strings.TrimSpace(s)
|
||||
},
|
||||
"float32f": func(f float32) string {
|
||||
return fmt.Sprintf("%.2f", f)
|
||||
},
|
||||
"divU64": func(a, b uint64) float32 {
|
||||
if b == 0 {
|
||||
if a > 0 {
|
||||
return 100
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if a == 0 {
|
||||
// 这是从未在线的情况
|
||||
return 0.00001 / float32(b) * 100
|
||||
}
|
||||
return float32(a) / float32(b) * 100
|
||||
},
|
||||
"div": func(a, b int) float32 {
|
||||
if b == 0 {
|
||||
if a > 0 {
|
||||
return 100
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if a == 0 {
|
||||
// 这是从未在线的情况
|
||||
return 0.00001 / float32(b) * 100
|
||||
}
|
||||
return float32(a) / float32(b) * 100
|
||||
},
|
||||
"addU64": func(a, b uint64) uint64 {
|
||||
return a + b
|
||||
},
|
||||
"add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
"dayBefore": func(i int) string {
|
||||
year, month, day := time.Now().Date()
|
||||
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
||||
return today.AddDate(0, 0, i-29).Format("1月2号")
|
||||
},
|
||||
"className": func(percent float32) string {
|
||||
if percent == 0 {
|
||||
return ""
|
||||
}
|
||||
if percent > 95 {
|
||||
return "good"
|
||||
}
|
||||
if percent > 80 {
|
||||
return "warning"
|
||||
}
|
||||
return "danger"
|
||||
},
|
||||
"statusName": func(percent float32) string {
|
||||
if percent == 0 {
|
||||
return "无数据"
|
||||
}
|
||||
if percent > 95 {
|
||||
return "良好"
|
||||
}
|
||||
if percent > 80 {
|
||||
return "低可用"
|
||||
}
|
||||
return "故障"
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/pkg/mygin"
|
||||
@@ -40,7 +41,7 @@ func (gp *guestPage) login(c *gin.Context) {
|
||||
RegistrationLink = "https://gitee.com/signup"
|
||||
}
|
||||
c.HTML(http.StatusOK, "dashboard/login", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": "登录",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
||||
"LoginType": LoginType,
|
||||
"RegistrationLink": RegistrationLink,
|
||||
}))
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/pkg/mygin"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
)
|
||||
|
||||
type memberPage struct {
|
||||
@@ -18,8 +19,8 @@ func (mp *memberPage) serve() {
|
||||
mr.Use(mygin.Authorize(mygin.AuthorizeOption{
|
||||
Member: true,
|
||||
IsPage: true,
|
||||
Msg: "此页面需要登录",
|
||||
Btn: "点此登录",
|
||||
Msg: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "YouAreNotAuthorized"}),
|
||||
Btn: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
||||
Redirect: "/login",
|
||||
}))
|
||||
mr.GET("/server", mp.server)
|
||||
@@ -33,14 +34,14 @@ 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{
|
||||
"Title": "服务器管理",
|
||||
"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{
|
||||
"Title": "服务监控",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServicesManagement"}),
|
||||
"Monitors": singleton.ServiceSentinelShared.Monitors(),
|
||||
}))
|
||||
}
|
||||
@@ -49,7 +50,7 @@ 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{
|
||||
"Title": "计划任务",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ScheduledTasks"}),
|
||||
"Crons": crons,
|
||||
}))
|
||||
}
|
||||
@@ -60,7 +61,7 @@ func (mp *memberPage) notification(c *gin.Context) {
|
||||
var ar []model.AlertRule
|
||||
singleton.DB.Find(&ar)
|
||||
c.HTML(http.StatusOK, "dashboard/notification", mygin.CommonEnvironment(c, gin.H{
|
||||
"Title": "报警通知",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Notification"}),
|
||||
"Notifications": nf,
|
||||
"AlertRules": ar,
|
||||
}))
|
||||
@@ -68,6 +69,6 @@ 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": "系统设置",
|
||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user