nezha/cmd/dashboard/controller/controller.go

220 lines
4.7 KiB
Go
Raw Normal View History

2019-12-08 03:59:58 -05:00
package controller
import (
"fmt"
"html/template"
2023-11-28 10:01:37 -05:00
"io/fs"
"net/http"
2021-11-04 00:06:20 -04:00
"strconv"
2020-12-18 21:57:10 -05:00
"strings"
2021-08-17 23:56:54 -04:00
"sync"
2019-12-08 03:59:58 -05:00
"time"
2019-12-09 05:14:31 -05:00
"code.cloudfoundry.org/bytefmt"
2021-05-10 06:04:38 -04:00
"github.com/gin-contrib/pprof"
2019-12-08 03:59:58 -05:00
"github.com/gin-gonic/gin"
2022-04-27 11:51:45 -04:00
"github.com/nicksnyder/go-i18n/v2/i18n"
2019-12-08 03:59:58 -05:00
2020-11-10 21:07:45 -05:00
"github.com/naiba/nezha/pkg/mygin"
2023-11-28 10:01:37 -05:00
"github.com/naiba/nezha/resource"
2022-01-08 22:54:14 -05:00
"github.com/naiba/nezha/service/singleton"
2019-12-08 03:59:58 -05:00
)
func ServeWeb(port uint) *http.Server {
2019-12-08 10:18:29 -05:00
gin.SetMode(gin.ReleaseMode)
2021-05-10 06:04:38 -04:00
r := gin.Default()
2023-11-28 10:01:37 -05:00
tmpl := template.New("").Funcs(funcMap)
var err error
tmpl, err = tmpl.ParseFS(resource.TemplateFS, "template/**/*.html")
if err != nil {
panic(err)
}
tmpl, err = tmpl.ParseGlob("resource/template/**/*.html")
if err != nil {
panic(err)
}
r.SetHTMLTemplate(tmpl)
2022-01-08 22:54:14 -05:00
if singleton.Conf.Debug {
2019-12-08 10:18:29 -05:00
gin.SetMode(gin.DebugMode)
2021-05-10 06:04:38 -04:00
pprof.Register(r)
2019-12-08 10:18:29 -05:00
}
2019-12-08 03:59:58 -05:00
r.Use(mygin.RecordPath)
2023-11-28 10:01:37 -05:00
staticFs, err := fs.Sub(resource.StaticFS, "static")
if err != nil {
panic(err)
}
r.StaticFS("/static", http.FS(staticFs))
2019-12-08 03:59:58 -05:00
routers(r)
2021-08-10 08:13:17 -04:00
page404 := func(c *gin.Context) {
mygin.ShowErrorPage(c, mygin.ErrInfo{
Code: http.StatusNotFound,
Title: "该页面不存在",
Msg: "该页面内容可能已着陆火星",
Link: "/",
Btn: "返回首页",
}, true)
}
r.NoRoute(page404)
r.NoMethod(page404)
srv := &http.Server{
2022-06-22 00:53:21 -04:00
Addr: fmt.Sprintf(":%d", port),
ReadHeaderTimeout: time.Second * 5,
Handler: r,
}
return srv
2019-12-08 03:59:58 -05:00
}
func routers(r *gin.Engine) {
// 通用页面
2021-08-17 23:56:54 -04:00
cp := commonPage{r: r, terminals: make(map[string]*terminalContext), terminalsLock: new(sync.Mutex)}
2019-12-08 03:59:58 -05:00
cp.serve()
// 游客页面
gp := guestPage{r}
gp.serve()
// 会员页面
mp := &memberPage{r}
mp.serve()
// API
api := r.Group("api")
{
ma := &memberAPI{api}
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 {
2022-04-30 09:30:58 -04:00
return t.In(singleton.Loc).Format("01/02/2006 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 {
2022-04-30 09:30:58 -04:00
return time.Unix(int64(s), 0).In(singleton.Loc).Format("01/02/2006 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 {
2022-04-30 09:30:58 -04:00
return fmt.Sprintf("%.3f", 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
},
"TransLeftPercent": func(a, b float64) (n float64) {
n, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (100-(a/b)*100)), 64)
if n < 0 {
n = 0
}
return
},
"TransLeft": func(a, b uint64) string {
if a < b {
2022-05-31 03:12:15 -04:00
return "0B"
}
return bytefmt.ByteSize(a - b)
},
"TransClassName": func(a float64) string {
if a == 0 {
return "offline"
}
if a > 50 {
return "fine"
}
if a > 20 {
return "warning"
}
if a > 0 {
return "error"
}
return "offline"
},
"UintToFloat": func(a uint64) (n float64) {
n, _ = strconv.ParseFloat((strconv.FormatUint(a, 10)), 64)
return
},
"dayBefore": func(i int) string {
year, month, day := time.Now().Date()
2022-10-12 11:06:25 -04:00
today := time.Date(year, month, day, 0, 0, 0, 0, singleton.Loc)
2022-04-30 09:30:58 -04:00
return today.AddDate(0, 0, i-29).Format("01/02")
},
"className": func(percent float32) string {
if percent == 0 {
return ""
}
if percent > 95 {
return "good"
}
if percent > 80 {
return "warning"
}
return "danger"
},
"statusName": func(val float32) string {
return singleton.StatusCodeToString(singleton.GetStatusCode(val))
},
}