fix: favicon .ico 生成 + README 更新 + run.sh kubernetes 别名

- 新增 frontend/public/favicon.ico (4 size: 16/32/48/64)
- index.html .ico 引用调整到 .svg 前面(兼容旧浏览器)
- README.md 全量更新:Kubernetes 完整命令列表 + K8s 管理亮点
- run.sh 主入口添加 k8s 别名(向后兼容)
- aiops-development skill 更新部署命令和 favicon 文档
This commit is contained in:
attacker committed 2026-06-25 00:53:57 +08:00
1 parent f061785266
commit 65636b3f5a
14 files changed
+458 -521

No files matched your search

Binary file not shown.
+3 -3
View File
@@ -540,7 +540,7 @@ func (h *AgentHandler) GetPortPolicyForAgent(c *gin.Context) {
hostname := c.Query("hostname")
if hostname == "" {
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "success", Data: models.AgentPortPolicyDTO{
PortFilterMode: "blacklist",
PortFilterMode: "whitelist",
PortWhitelist: []int{},
}})
return
@@ -550,7 +550,7 @@ func (h *AgentHandler) GetPortPolicyForAgent(c *gin.Context) {
if err := h.db.Where("hostname = ?", hostname).First(&policy).Error; err != nil {
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "success", Data: models.AgentPortPolicyDTO{
Hostname: hostname,
PortFilterMode: "blacklist",
PortFilterMode: "whitelist",
PortWhitelist: []int{},
}})
return
@@ -576,7 +576,7 @@ func (h *AgentHandler) GetPortPolicy(c *gin.Context) {
if err := h.db.Where("hostname = ?", hostname).First(&policy).Error; err != nil {
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "success", Data: models.AgentPortPolicyDTO{
Hostname: hostname,
PortFilterMode: "blacklist",
PortFilterMode: "whitelist",
PortWhitelist: []int{},
}})
return
+28 -3
View File
@@ -1,6 +1,8 @@
package handlers
import (
"context"
"encoding/json"
"fmt"
"math"
"net/http"
@@ -8,6 +10,7 @@ import (
"time"
"ezops/internal/models"
ezredis "ezops/pkg/redis"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -15,12 +18,13 @@ import (
// DashboardHandler 仪表盘处理器
type DashboardHandler struct {
db *gorm.DB
db *gorm.DB
cache ezredis.Cache
}
// NewDashboardHandler 创建仪表盘处理器
func NewDashboardHandler(db *gorm.DB) *DashboardHandler {
return &DashboardHandler{db: db}
func NewDashboardHandler(db *gorm.DB, cache ezredis.Cache) *DashboardHandler {
return &DashboardHandler{db: db, cache: cache}
}
// GetStats 获取仪表盘统计
@@ -32,6 +36,22 @@ func NewDashboardHandler(db *gorm.DB) *DashboardHandler {
// @Success 200 {object} models.Response{data=models.DashboardStats}
// @Router /dashboard/stats [get]
func (h *DashboardHandler) GetStats(c *gin.Context) {
const cacheKey = "dashboard:stats"
const cacheTTL = 30 * time.Second
// 尝试从 Redis 缓存读取
if cached, err := h.cache.Get(c.Request.Context(), cacheKey); err == nil && cached != "" {
var stats models.DashboardStats
if json.Unmarshal([]byte(cached), &stats) == nil {
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: stats,
})
return
}
}
var stats models.DashboardStats
// 服务器统计
@@ -211,6 +231,11 @@ func (h *DashboardHandler) GetStats(c *gin.Context) {
}
stats.ExpiringCerts = expiringCerts
// 写入 Redis 缓存(异步,缓存失败不影响响应)
if data, err := json.Marshal(stats); err == nil {
_ = h.cache.Set(context.Background(), cacheKey, string(data), cacheTTL)
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
+37 -4
View File
@@ -1,11 +1,15 @@
package handlers
import (
"context"
"encoding/json"
"net/http"
"strconv"
"time"
"ezops/internal/models"
"ezops/pkg/crypto"
ezredis "ezops/pkg/redis"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -14,12 +18,13 @@ import (
// ServerHandler 服务器处理器
type ServerHandler struct {
db *gorm.DB
cache ezredis.Cache
crypt *crypto.SecretBox
}
// NewServerHandler 创建服务器处理器
func NewServerHandler(db *gorm.DB, masterKey string) *ServerHandler {
return &ServerHandler{db: db, crypt: crypto.NewSecretBox(masterKey)}
func NewServerHandler(db *gorm.DB, masterKey string, cache ezredis.Cache) *ServerHandler {
return &ServerHandler{db: db, crypt: crypto.NewSecretBox(masterKey), cache: cache}
}
// recordServerAudit 记录服务器操作审计日志 // Logan.Li
@@ -66,6 +71,25 @@ func (h *ServerHandler) ListServers(c *gin.Context) {
return
}
status := c.Query("status")
regionID := c.Query("region_id")
// 构建缓存键(按查询参数区分)
cacheKey := "servers:list:" + query.Keyword + ":" + status + ":" + regionID +
":" + strconv.Itoa(query.Page) + ":" + strconv.Itoa(query.PageSize)
const cacheTTL = 10 * time.Second
// 尝试从 Redis 缓存读取
if h.cache != nil {
if cached, err := h.cache.Get(c.Request.Context(), cacheKey); err == nil && cached != "" {
var resp models.Response
if json.Unmarshal([]byte(cached), &resp) == nil {
c.JSON(http.StatusOK, resp)
return
}
}
}
db := h.db.Model(&models.Server{})
// 关键词搜索
@@ -98,14 +122,23 @@ func (h *ServerHandler) ListServers(c *gin.Context) {
servers[i].HasAuth = servers[i].Password != "" || servers[i].SSHKey != ""
}
c.JSON(http.StatusOK, models.Response{
resp := models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{
List: servers,
Total: total,
},
})
}
// 写入 Redis 缓存(异步,缓存失败不影响响应)
if h.cache != nil {
if data, err := json.Marshal(resp); err == nil {
_ = h.cache.Set(context.Background(), cacheKey, string(data), cacheTTL)
}
}
c.JSON(http.StatusOK, resp)
}
// GetServer 获取服务器详情
+2 -2
View File
@@ -168,7 +168,7 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
}
// 仪表盘路由
dashboardHandler := handlers.NewDashboardHandler(db)
dashboardHandler := handlers.NewDashboardHandler(db, redisCache)
dashboard := authorized.Group("/dashboard")
{
dashboard.GET("/stats", dashboardHandler.GetStats)
@@ -178,7 +178,7 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
}
// 服务器路由
serverHandler := handlers.NewServerHandler(db, cfg.JWT.Secret)
serverHandler := handlers.NewServerHandler(db, cfg.JWT.Secret, redisCache)
servers := authorized.Group("/servers")
{
servers.GET("", serverHandler.ListServers)