后端更新: - 在 machines 表新增 offline_count、total_offline_seconds、last_offline_at、last_offline_reason 字段,用于记录机器离线统计信息。 - 新增 offline_logs 表,记录每次离线的开始时间、结束时间、持续时长及离线原因。 - 重写 ping 服务为状态机模式: – 单台机器依次使用 system ping / ICMP / TCP(SSH端口) 三种方式检测连通性; – 任意一次成功即视为在线; – 若一次失败,则会连续重试 3 次(间隔 2 秒),3 次均失败才判定为离线,避免网络抖动导致误判。 – 仅在状态发生 online→offline 或 offline→online 变化时更新 offline_logs 与累计时长。 – 机器按顺序逐个检测,每台间隔 30 秒。 - 新增 API:GET /admin/machines/:id/offline-logs,用于查询最近 50 条离线记录。 - CleanupLogs 增加对 offline_logs 的过期清理。 前端更新: - 机器详情页(MachineDetail.vue)新增离线统计卡片,展示离线次数、累计离线时长、上次离线原因及最近 5 条离线记录。 - 全局支持暗黑模式: – App.vue 引入 light/dark CSS 变量,并加载 Element Plus 深色主题(dark/css-vars.css)。 – MainLayout.vue 侧边栏新增主题切换按钮,支持深浅色切换并持久化到 localStorage。 – Topology.vue 监听主题变化,动态重绘 G6 节点/边的颜色、背景与阴影。 – MachineList.vue / MachineDetail.vue 全面适配深色变量(卡片、表格、标签、进度条等)。 - 机器列表卡片 UI 调整:改为顶部 OS 色点 + 在线/离线状态胶囊标签,离线卡片降低透明度并去色。 构建与部署: - 重新构建前端并打包静态资源。 - 交叉编译 Linux amd64 二进制并更新 deploy/lan-manager-debian12.tar.gz 部署包。
128 lines
3.8 KiB
Go
128 lines
3.8 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
type NullString struct {
|
|
sql.NullString
|
|
}
|
|
|
|
func (ns NullString) MarshalJSON() ([]byte, error) {
|
|
if ns.Valid {
|
|
return json.Marshal(ns.String)
|
|
}
|
|
return json.Marshal("")
|
|
}
|
|
|
|
func (ns *NullString) UnmarshalJSON(data []byte) error {
|
|
if string(data) == "null" {
|
|
ns.Valid = false
|
|
ns.String = ""
|
|
return nil
|
|
}
|
|
var s string
|
|
if err := json.Unmarshal(data, &s); err != nil {
|
|
return err
|
|
}
|
|
ns.String = s
|
|
ns.Valid = true
|
|
return nil
|
|
}
|
|
|
|
type Machine struct {
|
|
ID int64 `json:"id"`
|
|
Hostname string `json:"hostname"`
|
|
IP string `json:"ip"`
|
|
MAC NullString `json:"mac"`
|
|
OsType string `json:"os_type"`
|
|
OsVersion NullString `json:"os_version"`
|
|
Notes NullString `json:"notes"`
|
|
SSHPort int `json:"ssh_port"`
|
|
SSHUsername NullString `json:"ssh_username"`
|
|
SSHPassword NullString `json:"ssh_password"`
|
|
IsOnline bool `json:"is_online"`
|
|
LastPingAt *time.Time `json:"last_ping_at"`
|
|
CPUInfo NullString `json:"cpu_info"`
|
|
MemoryInfo NullString `json:"memory_info"`
|
|
DiskInfo NullString `json:"disk_info"`
|
|
Uptime NullString `json:"uptime"`
|
|
ListenPorts NullString `json:"listen_ports"`
|
|
SSHSyncedAt *time.Time `json:"ssh_synced_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
ServiceCount int `json:"service_count"`
|
|
OfflineCount int `json:"offline_count"`
|
|
TotalOfflineSeconds int `json:"total_offline_seconds"`
|
|
LastOfflineAt *time.Time `json:"last_offline_at"`
|
|
LastOfflineReason NullString `json:"last_offline_reason"`
|
|
}
|
|
|
|
type OfflineLog struct {
|
|
ID int64 `json:"id"`
|
|
MachineID int64 `json:"machine_id"`
|
|
Reason string `json:"reason"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
EndedAt *time.Time `json:"ended_at"`
|
|
DurationSeconds *int `json:"duration_seconds"`
|
|
}
|
|
|
|
type Service struct {
|
|
ID int64 `json:"id"`
|
|
MachineID int64 `json:"machine_id"`
|
|
Name string `json:"name"`
|
|
Port int `json:"port"`
|
|
Protocol string `json:"protocol"`
|
|
Notes string `json:"notes"`
|
|
TargetMachineID *int64 `json:"target_machine_id"`
|
|
TargetNotes string `json:"target_notes"`
|
|
}
|
|
|
|
type Relationship struct {
|
|
ID int64 `json:"id"`
|
|
SourceMachineID int64 `json:"source_machine_id"`
|
|
TargetMachineID int64 `json:"target_machine_id"`
|
|
RelationType string `json:"relation_type"`
|
|
SourcePort *int `json:"source_port"`
|
|
TargetPort *int `json:"target_port"`
|
|
Notes string `json:"notes"`
|
|
}
|
|
|
|
type OperationLog struct {
|
|
ID int64 `json:"id"`
|
|
Action string `json:"action"`
|
|
EntityType string `json:"entity_type"`
|
|
EntityID *int64 `json:"entity_id"`
|
|
EntityName string `json:"entity_name"`
|
|
OldValue string `json:"old_value"`
|
|
NewValue string `json:"new_value"`
|
|
SourceIP string `json:"source_ip"`
|
|
Username string `json:"username"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
type LoginRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
}
|
|
|
|
type SSHInfoRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
type SSHInfoResult struct {
|
|
Hostname string `json:"hostname"`
|
|
OsVersion string `json:"os_version"`
|
|
CPU string `json:"cpu"`
|
|
Memory string `json:"memory"`
|
|
Disk string `json:"disk"`
|
|
Uptime string `json:"uptime"`
|
|
ListenPorts []int `json:"listen_ports"`
|
|
RawCPUInfo string `json:"raw_cpu_info"`
|
|
RawMemoryInfo string `json:"raw_memory_info"`
|
|
RawDiskInfo string `json:"raw_disk_info"`
|
|
}
|