feat: ToNav-go v1.0.0 - 内部服务导航系统
功能: - 前台导航: 分类Tab切换、实时搜索、健康状态指示、响应式适配 - 后台管理: 服务/分类CRUD、系统设置、登录认证(bcrypt) - 健康检查: 定时检测(5min)、独立检查URL、三态指示(在线/离线/未检测) - 云端备份: WebDAV上传/下载/恢复/删除、定时自动备份、本地备份管理 技术栈: Go + Gin + GORM + SQLite
This commit is contained in:
119
handlers/views.go
Normal file
119
handlers/views.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"tonav-go/database"
|
||||
"tonav-go/models"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AuthRequired 登录验证中间件
|
||||
func AuthRequired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
userID := session.Get("user_id")
|
||||
if userID == nil {
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
mustChange := session.Get("must_change")
|
||||
if mustChange == true && c.Request.URL.Path != "/admin/change-password" && c.Request.URL.Path != "/admin/logout" {
|
||||
c.Redirect(http.StatusFound, "/admin/change-password")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// DashboardHandler 渲染后台首页
|
||||
func DashboardHandler(c *gin.Context) {
|
||||
var serviceCount, categoryCount int64
|
||||
var onlineCount, offlineCount int64
|
||||
database.DB.Model(&models.Service{}).Count(&serviceCount)
|
||||
database.DB.Model(&models.Category{}).Count(&categoryCount)
|
||||
database.DB.Model(&models.Service{}).Where("status = ?", "online").Count(&onlineCount)
|
||||
database.DB.Model(&models.Service{}).Where("status = ?", "offline").Count(&offlineCount)
|
||||
|
||||
c.HTML(http.StatusOK, "dashboard.html", gin.H{
|
||||
"service_count": serviceCount,
|
||||
"category_count": categoryCount,
|
||||
"online_count": onlineCount,
|
||||
"offline_count": offlineCount,
|
||||
})
|
||||
}
|
||||
|
||||
// IndexHandler 渲染前台首页
|
||||
func IndexHandler(c *gin.Context) {
|
||||
if database.DB == nil {
|
||||
c.String(http.StatusInternalServerError, "DB NIL")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取所有分类
|
||||
var categories []models.Category
|
||||
database.DB.Order("sort_order desc").Find(&categories)
|
||||
|
||||
// 获取所有启用的服务
|
||||
var services []models.Service
|
||||
database.DB.Where("is_enabled = ?", true).Order("category_id asc, sort_order desc").Find(&services)
|
||||
|
||||
// 获取站点标题设置
|
||||
var titleSetting models.Setting
|
||||
siteTitle := "ToNav"
|
||||
if err := database.DB.Where("key = ?", "site_title").First(&titleSetting).Error; err == nil && titleSetting.Value != "" {
|
||||
siteTitle = titleSetting.Value
|
||||
}
|
||||
|
||||
// 序列化为 JSON 供前端 JS 使用
|
||||
categoriesJSON, _ := json.Marshal(categories)
|
||||
servicesJSON, _ := json.Marshal(services)
|
||||
|
||||
c.HTML(http.StatusOK, "index.html", gin.H{
|
||||
"site_title": siteTitle,
|
||||
"categories": categories,
|
||||
"categories_json": template.JS(categoriesJSON),
|
||||
"services_json": template.JS(servicesJSON),
|
||||
})
|
||||
}
|
||||
|
||||
// ServicesPageHandler 渲染服务管理页面
|
||||
func ServicesPageHandler(c *gin.Context) {
|
||||
var categories []models.Category
|
||||
database.DB.Order("sort_order desc").Find(&categories)
|
||||
c.HTML(http.StatusOK, "services.html", gin.H{
|
||||
"categories": categories,
|
||||
})
|
||||
}
|
||||
|
||||
// CategoriesPageHandler 渲染分类管理页面
|
||||
func CategoriesPageHandler(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "categories.html", nil)
|
||||
}
|
||||
|
||||
// getSessionUserID 安全获取 session 中的 user_id
|
||||
func getSessionUserID(session sessions.Session) (uint, error) {
|
||||
userID := session.Get("user_id")
|
||||
if userID == nil {
|
||||
return 0, fmt.Errorf("user not logged in")
|
||||
}
|
||||
switch v := userID.(type) {
|
||||
case uint:
|
||||
return v, nil
|
||||
case int:
|
||||
return uint(v), nil
|
||||
case int64:
|
||||
return uint(v), nil
|
||||
case float64:
|
||||
return uint(v), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unexpected user_id type: %T", userID)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user