mirror of
https://github.com/nezhahq/nezha.git
synced 2025-03-11 08:18:13 -04:00
✨ feat: 展示排序 close #29
This commit is contained in:
parent
35766e590d
commit
347bb7faa0
@ -27,7 +27,7 @@ func (cp *commonPage) home(c *gin.Context) {
|
|||||||
dao.ServerLock.RLock()
|
dao.ServerLock.RLock()
|
||||||
defer dao.ServerLock.RUnlock()
|
defer dao.ServerLock.RUnlock()
|
||||||
data := gin.H{
|
data := gin.H{
|
||||||
"Servers": dao.ServerList,
|
"Servers": dao.SortedServerList,
|
||||||
"CustomCode": dao.Conf.Site.CustomCode,
|
"CustomCode": dao.Conf.Site.CustomCode,
|
||||||
}
|
}
|
||||||
u, ok := c.Get(model.CtxKeyAuthorizedUser)
|
u, ok := c.Get(model.CtxKeyAuthorizedUser)
|
||||||
@ -54,7 +54,7 @@ func (cp *commonPage) ws(c *gin.Context) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
for {
|
for {
|
||||||
dao.ServerLock.RLock()
|
dao.ServerLock.RLock()
|
||||||
err = conn.WriteJSON(dao.ServerList)
|
err = conn.WriteJSON(dao.SortedServerList)
|
||||||
dao.ServerLock.RUnlock()
|
dao.ServerLock.RUnlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
|
@ -56,7 +56,8 @@ func (ma *memberAPI) delete(c *gin.Context) {
|
|||||||
defer dao.ServerLock.Unlock()
|
defer dao.ServerLock.Unlock()
|
||||||
err = dao.DB.Delete(&model.Server{}, "id = ?", id).Error
|
err = dao.DB.Delete(&model.Server{}, "id = ?", id).Error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
delete(dao.ServerList, strconv.FormatUint(id, 10))
|
delete(dao.ServerList, id)
|
||||||
|
dao.ReSortServer()
|
||||||
}
|
}
|
||||||
case "notification":
|
case "notification":
|
||||||
err = dao.DB.Delete(&model.Notification{}, "id = ?", id).Error
|
err = dao.DB.Delete(&model.Notification{}, "id = ?", id).Error
|
||||||
@ -84,6 +85,7 @@ func (ma *memberAPI) delete(c *gin.Context) {
|
|||||||
type serverForm struct {
|
type serverForm struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Name string `binding:"required"`
|
Name string `binding:"required"`
|
||||||
|
DisplayIndex int
|
||||||
Secret string
|
Secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,8 +99,8 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
|||||||
defer dao.ServerLock.Unlock()
|
defer dao.ServerLock.Unlock()
|
||||||
s.Name = sf.Name
|
s.Name = sf.Name
|
||||||
s.Secret = sf.Secret
|
s.Secret = sf.Secret
|
||||||
|
s.DisplayIndex = sf.DisplayIndex
|
||||||
s.ID = sf.ID
|
s.ID = sf.ID
|
||||||
}
|
|
||||||
if sf.ID == 0 {
|
if sf.ID == 0 {
|
||||||
s.Secret = com.MD5(fmt.Sprintf("%s%s%d", time.Now(), sf.Name, admin.ID))
|
s.Secret = com.MD5(fmt.Sprintf("%s%s%d", time.Now(), sf.Name, admin.ID))
|
||||||
s.Secret = s.Secret[:10]
|
s.Secret = s.Secret[:10]
|
||||||
@ -106,6 +108,7 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
err = dao.DB.Save(&s).Error
|
err = dao.DB.Save(&s).Error
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Response{
|
c.JSON(http.StatusOK, model.Response{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
@ -115,7 +118,8 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
s.Host = &model.Host{}
|
s.Host = &model.Host{}
|
||||||
s.State = &model.State{}
|
s.State = &model.State{}
|
||||||
dao.ServerList[fmt.Sprintf("%d", s.ID)] = &s
|
dao.ServerList[s.ID] = &s
|
||||||
|
dao.ReSortServer()
|
||||||
c.JSON(http.StatusOK, model.Response{
|
c.JSON(http.StatusOK, model.Response{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
})
|
})
|
||||||
|
@ -32,7 +32,7 @@ func (mp *memberPage) server(c *gin.Context) {
|
|||||||
defer dao.ServerLock.RUnlock()
|
defer dao.ServerLock.RUnlock()
|
||||||
c.HTML(http.StatusOK, "dashboard/server", mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, "dashboard/server", mygin.CommonEnvironment(c, gin.H{
|
||||||
"Title": "服务器管理",
|
"Title": "服务器管理",
|
||||||
"Servers": dao.ServerList,
|
"Servers": dao.SortedServerList,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
@ -17,7 +16,7 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var err error
|
var err error
|
||||||
dao.ServerList = make(map[string]*model.Server)
|
dao.ServerList = make(map[uint64]*model.Server)
|
||||||
dao.Conf = &model.Config{}
|
dao.Conf = &model.Config{}
|
||||||
err = dao.Conf.Read("data/config.yaml")
|
err = dao.Conf.Read("data/config.yaml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -43,8 +42,9 @@ func initDB() {
|
|||||||
innerS := s
|
innerS := s
|
||||||
innerS.Host = &model.Host{}
|
innerS.Host = &model.Host{}
|
||||||
innerS.State = &model.State{}
|
innerS.State = &model.State{}
|
||||||
dao.ServerList[fmt.Sprintf("%d", innerS.ID)] = &innerS
|
dao.ServerList[innerS.ID] = &innerS
|
||||||
}
|
}
|
||||||
|
dao.ReSortServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
Common
|
Common
|
||||||
Name string
|
Name string
|
||||||
|
DisplayIndex int // 展示权重,越大越靠前
|
||||||
Secret string `json:"-"`
|
Secret string `json:"-"`
|
||||||
|
|
||||||
Host *Host `gorm:"-"`
|
Host *Host `gorm:"-"`
|
||||||
|
@ -36,7 +36,10 @@ function showFormModal(modelSelector, formID, URL, getData) {
|
|||||||
form.children('.message').remove()
|
form.children('.message').remove()
|
||||||
btn.toggleClass('loading')
|
btn.toggleClass('loading')
|
||||||
const data = getData ? getData() : $(formID).serializeArray().reduce(function (obj, item) {
|
const data = getData ? getData() : $(formID).serializeArray().reduce(function (obj, item) {
|
||||||
obj[item.name] = (item.name.endsWith('_id') || item.name === 'id' || item.name === 'ID' || item.name === 'RequestType' || item.name === 'RequestMethod') ? parseInt(item.value) : item.value;
|
obj[item.name] = (item.name.endsWith('_id') ||
|
||||||
|
item.name === 'id' || item.name === 'ID' ||
|
||||||
|
item.name === 'RequestType' || item.name === 'RequestMethod' ||
|
||||||
|
item.name === 'DisplayIndex') ? parseInt(item.value) : item.value;
|
||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
$.post(URL, JSON.stringify(data)).done(function (resp) {
|
$.post(URL, JSON.stringify(data)).done(function (resp) {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.1/dist/semantic.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.1/dist/semantic.min.js"></script>
|
||||||
<script src="/static/semantic-ui-alerts.min.js"></script>
|
<script src="/static/semantic-ui-alerts.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js"></script>
|
||||||
<script src="/static/main.js?v202012211616"></script>
|
<script src="/static/main.js?v202101082103"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
<label>备注</label>
|
<label>备注</label>
|
||||||
<input type="text" name="name" placeholder="爱因斯坦-光速1号">
|
<input type="text" name="name" placeholder="爱因斯坦-光速1号">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>展示权重</label>
|
||||||
|
<input type="number" name="DisplayIndex" placeholder="越大越靠前">
|
||||||
|
</div>
|
||||||
<div class="secret field">
|
<div class="secret field">
|
||||||
<label>密钥</label>
|
<label>密钥</label>
|
||||||
<input type="text" name="secret">
|
<input type="text" name="secret">
|
||||||
|
@ -13,20 +13,20 @@
|
|||||||
<table class="ui very basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>权重</th>
|
||||||
<th>备注</th>
|
<th>备注</th>
|
||||||
|
<th>IP</th>
|
||||||
<th>密钥</th>
|
<th>密钥</th>
|
||||||
<th>最后活跃</th>
|
|
||||||
<th>管理</th>
|
<th>管理</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range $server := .Servers}}
|
{{range $server := .Servers}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{$server.ID}}</td>
|
<td>{{$server.DisplayIndex}}</td>
|
||||||
<td>{{$server.Name}}</td>
|
<td>{{$server.Name}}</td>
|
||||||
|
<td>{{$server.Host.IP}}</td>
|
||||||
<td>{{$server.Secret}}</td>
|
<td>{{$server.Secret}}</td>
|
||||||
<td>{{$server.LastActive}}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<div class="ui mini icon buttons">
|
<div class="ui mini icon buttons">
|
||||||
<button class="ui button" onclick="addOrEditServer({{$server.Marshal}})">
|
<button class="ui button" onclick="addOrEditServer({{$server.Marshal}})">
|
||||||
|
@ -172,9 +172,8 @@
|
|||||||
ws.onmessage = function (evt) {
|
ws.onmessage = function (evt) {
|
||||||
const oldServers = statusCards.servers
|
const oldServers = statusCards.servers
|
||||||
statusCards.servers = JSON.parse(evt.data)
|
statusCards.servers = JSON.parse(evt.data)
|
||||||
const keys = Object.keys(statusCards.servers)
|
for (let i = 0; i < statusCards.servers.length; i++) {
|
||||||
for (let i = 0; i < keys.length; i++) {
|
const ns = statusCards.servers[i];
|
||||||
const ns = statusCards.servers[keys[i]];
|
|
||||||
if (!ns.Host) ns.live = false
|
if (!ns.Host) ns.live = false
|
||||||
else {
|
else {
|
||||||
const lastActive = new Date(ns.LastActive).getTime()
|
const lastActive = new Date(ns.LastActive).getTime()
|
||||||
|
@ -238,9 +238,8 @@
|
|||||||
}
|
}
|
||||||
ws.onmessage = function (evt) {
|
ws.onmessage = function (evt) {
|
||||||
statusCards.servers = JSON.parse(evt.data)
|
statusCards.servers = JSON.parse(evt.data)
|
||||||
const keys = Object.keys(statusCards.servers)
|
for (let i = 0; i < statusCards.servers.length; i++) {
|
||||||
for (let i = 0; i < keys.length; i++) {
|
const ns = statusCards.servers[i];
|
||||||
const ns = statusCards.servers[keys[i]];
|
|
||||||
if (!ns.Host) ns.live = false
|
if (!ns.Host) ns.live = false
|
||||||
else {
|
else {
|
||||||
const lastActive = new Date(ns.LastActive).getTime()
|
const lastActive = new Date(ns.LastActive).getTime()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dao
|
package dao
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
@ -25,7 +26,8 @@ var Cache *cache.Cache
|
|||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
|
||||||
// ServerList ..
|
// ServerList ..
|
||||||
var ServerList map[string]*model.Server
|
var ServerList map[uint64]*model.Server
|
||||||
|
var SortedServerList []*model.Server
|
||||||
|
|
||||||
// ServerLock ..
|
// ServerLock ..
|
||||||
var ServerLock sync.RWMutex
|
var ServerLock sync.RWMutex
|
||||||
@ -39,6 +41,17 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReSortServer() {
|
||||||
|
SortedServerList = []*model.Server{}
|
||||||
|
for _, s := range ServerList {
|
||||||
|
SortedServerList = append(SortedServerList, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(SortedServerList, func(i, j int) bool {
|
||||||
|
return SortedServerList[i].DisplayIndex > SortedServerList[j].DisplayIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SendCommand ..
|
// SendCommand ..
|
||||||
func SendCommand(cmd *pb.Command) {
|
func SendCommand(cmd *pb.Command) {
|
||||||
ServerLock.RLock()
|
ServerLock.RLock()
|
||||||
|
@ -2,6 +2,7 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/naiba/nezha/service/dao"
|
"github.com/naiba/nezha/service/dao"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@ -26,18 +27,15 @@ func (a *AuthHandler) RequireTransportSecurity() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check ..
|
// Check ..
|
||||||
func (a *AuthHandler) Check(ctx context.Context) (clientID string, err error) {
|
func (a *AuthHandler) Check(ctx context.Context) (clientID uint64, err error) {
|
||||||
md, ok := metadata.FromIncomingContext(ctx)
|
md, ok := metadata.FromIncomingContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = status.Errorf(codes.Unauthenticated, "获取 metaData 失败")
|
err = status.Errorf(codes.Unauthenticated, "获取 metaData 失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var clientSecret string
|
||||||
var (
|
|
||||||
clientSecret string
|
|
||||||
)
|
|
||||||
if value, ok := md["client_id"]; ok {
|
if value, ok := md["client_id"]; ok {
|
||||||
clientID = value[0]
|
clientID, _ = strconv.ParseUint(value[0], 10, 64)
|
||||||
}
|
}
|
||||||
if value, ok := md["client_secret"]; ok {
|
if value, ok := md["client_secret"]; ok {
|
||||||
clientSecret = value[0]
|
clientSecret = value[0]
|
||||||
|
@ -17,7 +17,7 @@ type NezhaHandler struct {
|
|||||||
|
|
||||||
// ReportState ..
|
// ReportState ..
|
||||||
func (s *NezhaHandler) ReportState(c context.Context, r *pb.State) (*pb.Receipt, error) {
|
func (s *NezhaHandler) ReportState(c context.Context, r *pb.State) (*pb.Receipt, error) {
|
||||||
var clientID string
|
var clientID uint64
|
||||||
var err error
|
var err error
|
||||||
if clientID, err = s.Auth.Check(c); err != nil {
|
if clientID, err = s.Auth.Check(c); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -32,7 +32,7 @@ func (s *NezhaHandler) ReportState(c context.Context, r *pb.State) (*pb.Receipt,
|
|||||||
|
|
||||||
// Heartbeat ..
|
// Heartbeat ..
|
||||||
func (s *NezhaHandler) Heartbeat(r *pb.Beat, stream pb.NezhaService_HeartbeatServer) error {
|
func (s *NezhaHandler) Heartbeat(r *pb.Beat, stream pb.NezhaService_HeartbeatServer) error {
|
||||||
var clientID string
|
var clientID uint64
|
||||||
var err error
|
var err error
|
||||||
defer log.Printf("Heartbeat exit server:%v err:%v", clientID, err)
|
defer log.Printf("Heartbeat exit server:%v err:%v", clientID, err)
|
||||||
if clientID, err = s.Auth.Check(stream.Context()); err != nil {
|
if clientID, err = s.Auth.Check(stream.Context()); err != nil {
|
||||||
@ -52,7 +52,7 @@ func (s *NezhaHandler) Heartbeat(r *pb.Beat, stream pb.NezhaService_HeartbeatSer
|
|||||||
|
|
||||||
// Register ..
|
// Register ..
|
||||||
func (s *NezhaHandler) Register(c context.Context, r *pb.Host) (*pb.Receipt, error) {
|
func (s *NezhaHandler) Register(c context.Context, r *pb.Host) (*pb.Receipt, error) {
|
||||||
var clientID string
|
var clientID uint64
|
||||||
var err error
|
var err error
|
||||||
if clientID, err = s.Auth.Check(c); err != nil {
|
if clientID, err = s.Auth.Check(c); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user