feat: 展示排序 close

This commit is contained in:
naiba 2021-01-08 21:04:50 +08:00
parent 35766e590d
commit 347bb7faa0
14 changed files with 63 additions and 42 deletions
cmd/dashboard
model
resource
static
template
common
component
dashboard
theme-default
theme-hotaru
service

View File

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

View File

@ -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
@ -82,9 +83,10 @@ 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"`
Secret string DisplayIndex int
Secret string
} }
func (ma *memberAPI) addOrEditServer(c *gin.Context) { func (ma *memberAPI) addOrEditServer(c *gin.Context) {
@ -97,14 +99,15 @@ 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] err = dao.DB.Create(&s).Error
err = dao.DB.Create(&s).Error } 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{
@ -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,
}) })

View File

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

View File

@ -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() {

View File

@ -11,8 +11,9 @@ import (
// Server .. // Server ..
type Server struct { type Server struct {
Common Common
Name string Name string
Secret string `json:"-"` DisplayIndex int // 展示权重,越大越靠前
Secret string `json:"-"`
Host *Host `gorm:"-"` Host *Host `gorm:"-"`
State *State `gorm:"-"` State *State `gorm:"-"`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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