feat: Agent采集uptime, 后端持久化kernel/uptime/diskIO, 前端磁盘BPS+IOPS展示

- Agent: system.go 添加 readUptime(), SystemStat 携带 Uptime
- Backend: Server 模型新增 Kernel 字段, ReceiveReport 持久化 kernel+uptime
- Backend: /agent/latest 返回 kernel/uptime/port_info/disk_io_info/disk_total
- Frontend: 磁盘监控改为 BPS+IOPS (4张卡片), 系统信息修复内核/运行时长/监听端口/磁盘容量
- 图表单位从 MB/s 改为 KB/s, 添加 formatBPS 工具函数
This commit is contained in:
attacker committed 2026-06-19 01:10:00 +00:00
1 parent 31c2e338a3
commit 5949ec5d0c
48 files changed
+2182 -956

No files matched your search

+16 -6
View File
@@ -5,6 +5,7 @@ import (
"strconv"
"ezops/internal/models"
"ezops/pkg/crypto"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -12,12 +13,13 @@ import (
// ServerHandler 服务器处理器
type ServerHandler struct {
db *gorm.DB
db *gorm.DB
crypt *crypto.SecretBox
}
// NewServerHandler 创建服务器处理器
func NewServerHandler(db *gorm.DB) *ServerHandler {
return &ServerHandler{db: db}
func NewServerHandler(db *gorm.DB, masterKey string) *ServerHandler {
return &ServerHandler{db: db, crypt: crypto.NewSecretBox(masterKey)}
}
// recordServerAudit 记录服务器操作审计日志 // Logan.Li
@@ -91,6 +93,11 @@ func (h *ServerHandler) ListServers(c *gin.Context) {
Order("created_at DESC").
Find(&servers)
// 填充 has_auth 字段(密码和SSH密钥在JSON中隐藏,但前端需知道是否有凭据) // Logan.Li
for i := range servers {
servers[i].HasAuth = servers[i].Password != "" || servers[i].SSHKey != ""
}
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
@@ -324,7 +331,11 @@ func (h *ServerHandler) DeleteServer(c *gin.Context) {
return
}
if err := h.db.Delete(&models.Server{}, id).Error; err != nil {
// 硬删除:先清理关联数据,再物理删除服务器记录
h.db.Unscoped().Where("hostname = ?", server.Hostname).Delete(&models.AgentReport{})
h.db.Unscoped().Where("hostname = ?", server.Hostname).Delete(&models.MetricsAggregate{})
if err := h.db.Unscoped().Delete(&models.Server{}, id).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "删除失败",
@@ -333,10 +344,9 @@ func (h *ServerHandler) DeleteServer(c *gin.Context) {
}
h.recordServerAudit(c, "delete", server.Hostname+" ("+server.IP+")", strconv.Itoa(int(server.ID)), 1, "")
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "删除成功",
Message: "服务器已彻底删除",
})
}