feat: 优化页面
This commit is contained in:
parent
ed8048c111
commit
480c0f7404
147
clients.go
147
clients.go
@ -1,147 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 客户端信息结构
|
||||
type ClientInfo struct {
|
||||
IP string // IP地址
|
||||
Port string // 端口
|
||||
LastSeen time.Time // 最后活跃时间
|
||||
IsConnected bool // 是否当前连接
|
||||
}
|
||||
|
||||
// 客户端列表(使用互斥锁保护的映射)
|
||||
var (
|
||||
clientsMutex sync.Mutex
|
||||
clients = make(map[string]*ClientInfo)
|
||||
)
|
||||
|
||||
// addClient 添加客户端
|
||||
func addClient(addr string) {
|
||||
clientsMutex.Lock()
|
||||
defer clientsMutex.Unlock()
|
||||
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
Logger.Printf("解析客户端地址失败 %s: %v", addr, err)
|
||||
host = addr
|
||||
port = "unknown"
|
||||
}
|
||||
|
||||
clients[addr] = &ClientInfo{
|
||||
IP: host,
|
||||
Port: port,
|
||||
LastSeen: time.Now(),
|
||||
IsConnected: true,
|
||||
}
|
||||
|
||||
Logger.Printf("添加新客户端: %s", addr)
|
||||
}
|
||||
|
||||
// updateClientLastSeen 更新客户端最后活跃时间
|
||||
func updateClientLastSeen(addr string) {
|
||||
clientsMutex.Lock()
|
||||
defer clientsMutex.Unlock()
|
||||
|
||||
if client, exists := clients[addr]; exists {
|
||||
client.LastSeen = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
// removeClient 移除客户端(标记断开)
|
||||
func removeClient(addr string) {
|
||||
clientsMutex.Lock()
|
||||
defer clientsMutex.Unlock()
|
||||
|
||||
if client, exists := clients[addr]; exists {
|
||||
client.IsConnected = false
|
||||
Logger.Printf("客户端断开连接: %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
// getAllClients 获取所有客户端信息
|
||||
func getAllClients() []map[string]interface{} {
|
||||
clientsMutex.Lock()
|
||||
defer clientsMutex.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
result := make([]map[string]interface{}, 0, len(clients))
|
||||
|
||||
for addr, client := range clients {
|
||||
lastSeenDuration := now.Sub(client.LastSeen)
|
||||
|
||||
// 清理24小时前的记录
|
||||
if lastSeenDuration > 24*time.Hour {
|
||||
delete(clients, addr)
|
||||
continue
|
||||
}
|
||||
|
||||
// 连接状态判断:当前连接且2小时内活跃为在线
|
||||
isOnline := client.IsConnected && lastSeenDuration < 2*time.Hour
|
||||
var connectionStatus string
|
||||
if isOnline {
|
||||
connectionStatus = "保持连接"
|
||||
} else if client.IsConnected {
|
||||
connectionStatus = "连接超时"
|
||||
} else {
|
||||
connectionStatus = "已断开"
|
||||
}
|
||||
|
||||
result = append(result, map[string]interface{}{
|
||||
"address": addr,
|
||||
"ip": client.IP,
|
||||
"port": client.Port,
|
||||
"lastSeen": client.LastSeen,
|
||||
"isOnline": isOnline,
|
||||
"connectionStatus": connectionStatus,
|
||||
"lastSeenFormatted": formatDuration(lastSeenDuration),
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// formatDuration 格式化持续时间为友好的字符串
|
||||
func formatDuration(d time.Duration) string {
|
||||
if d < time.Minute {
|
||||
return "刚刚"
|
||||
} else if d < time.Hour {
|
||||
return fmt.Sprintf("%d分钟前", int(d.Minutes()))
|
||||
} else if d < 24*time.Hour {
|
||||
hours := int(d.Hours())
|
||||
minutes := int(d.Minutes()) % 60
|
||||
if minutes == 0 {
|
||||
return fmt.Sprintf("%d小时前", hours)
|
||||
} else {
|
||||
return fmt.Sprintf("%d小时%d分钟前", hours, minutes)
|
||||
}
|
||||
} else {
|
||||
return fmt.Sprintf("%d天前", int(d.Hours()/24))
|
||||
}
|
||||
}
|
||||
|
||||
// startClientCleanup 启动清理过期客户端的goroutine
|
||||
func startClientCleanup() {
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(1 * time.Hour) // 每小时检查一次
|
||||
|
||||
clientsMutex.Lock()
|
||||
now := time.Now()
|
||||
|
||||
for addr, client := range clients {
|
||||
if now.Sub(client.LastSeen) > 24*time.Hour {
|
||||
delete(clients, addr)
|
||||
Logger.Printf("移除过期客户端: %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
clientsMutex.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
187
db.go
187
db.go
@ -22,7 +22,7 @@ func InitDB() error {
|
||||
dbName := "probe_db"
|
||||
|
||||
// 连接字符串
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", username, password, host, port, dbName)
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=Asia%%2FShanghai", username, password, host, port, dbName)
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("mysql", dsn)
|
||||
@ -81,26 +81,22 @@ func SaveSensorData(sensorID int, x, y, z, temperature float64, deviceID string)
|
||||
|
||||
// 获取传感器数据 - 添加时间范围,包含温度字段
|
||||
func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) {
|
||||
query := `SELECT id, sensor_id, x_value, y_value, z_value,
|
||||
COALESCE(temperature, 0) as temperature,
|
||||
timestamp as timestamp
|
||||
FROM sensor_data
|
||||
WHERE sensor_id = ?`
|
||||
query := "SELECT id, sensor_id, x_value, y_value, z_value, COALESCE(temperature, 0) as temperature, `timestamp` as timestamp FROM sensor_data WHERE sensor_id = ?"
|
||||
|
||||
var args []interface{}
|
||||
args = append(args, sensorID)
|
||||
|
||||
if !startDate.IsZero() {
|
||||
query += " AND timestamp >= ?"
|
||||
query += " AND `timestamp` >= ?"
|
||||
args = append(args, startDate)
|
||||
}
|
||||
|
||||
if !endDate.IsZero() {
|
||||
query += " AND timestamp <= ?"
|
||||
query += " AND `timestamp` <= ?"
|
||||
args = append(args, endDate)
|
||||
}
|
||||
|
||||
query += " ORDER BY timestamp DESC"
|
||||
query += " ORDER BY `timestamp` DESC"
|
||||
|
||||
// 只有当limit > 0时才添加LIMIT子句
|
||||
if limit > 0 {
|
||||
@ -138,25 +134,21 @@ func GetSensorData(sensorID int, limit int, startDate time.Time, endDate time.Ti
|
||||
|
||||
// 获取所有传感器数据,包含温度字段
|
||||
func GetAllSensorData(limit int, startDate time.Time, endDate time.Time) ([]SensorData, error) {
|
||||
query := `SELECT id, sensor_id, x_value, y_value, z_value,
|
||||
COALESCE(temperature, 0) as temperature,
|
||||
timestamp as timestamp
|
||||
FROM sensor_data
|
||||
WHERE 1=1`
|
||||
query := "SELECT id, sensor_id, x_value, y_value, z_value, COALESCE(temperature, 0) as temperature, `timestamp` as timestamp FROM sensor_data WHERE 1=1"
|
||||
|
||||
var args []interface{}
|
||||
|
||||
if !startDate.IsZero() {
|
||||
query += " AND timestamp >= ?"
|
||||
query += " AND `timestamp` >= ?"
|
||||
args = append(args, startDate)
|
||||
}
|
||||
|
||||
if !endDate.IsZero() {
|
||||
query += " AND timestamp <= ?"
|
||||
query += " AND `timestamp` <= ?"
|
||||
args = append(args, endDate)
|
||||
}
|
||||
|
||||
query += " ORDER BY timestamp DESC"
|
||||
query += " ORDER BY `timestamp` DESC"
|
||||
|
||||
// 只有当limit > 0时才添加LIMIT子句
|
||||
if limit > 0 {
|
||||
@ -235,6 +227,18 @@ type Device struct {
|
||||
RegCodeHex sql.NullString
|
||||
}
|
||||
|
||||
// DeviceWithStats 包含设备统计信息
|
||||
type DeviceWithStats struct {
|
||||
ID int
|
||||
DeviceID string
|
||||
ForwardEnable bool
|
||||
Host sql.NullString
|
||||
Port sql.NullInt64
|
||||
RegCodeHex sql.NullString
|
||||
SensorCount int
|
||||
LastSeen sql.NullTime
|
||||
}
|
||||
|
||||
// GetDevice 获取设备配置(按设备字符串ID)
|
||||
func GetDevice(deviceID string) (*Device, error) {
|
||||
row := db.QueryRow(`SELECT id, device_id, COALESCE(forward_enable, 0) as forward_enable, host, port, reg_code_hex FROM devices WHERE device_id = ?`, deviceID)
|
||||
@ -249,3 +253,152 @@ func GetDevice(deviceID string) (*Device, error) {
|
||||
d.ForwardEnable = fe != 0
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
// GetDevicesWithStats 获取设备列表及统计
|
||||
func GetDevicesWithStats() ([]DeviceWithStats, error) {
|
||||
query := `SELECT d.id,
|
||||
d.device_id,
|
||||
COALESCE(d.forward_enable, 0) AS forward_enable,
|
||||
d.host,
|
||||
d.port,
|
||||
d.reg_code_hex,
|
||||
COALESCE(COUNT(DISTINCT sd.sensor_id), 0) AS sensor_count,
|
||||
MAX(sd.timestamp) AS last_seen
|
||||
FROM devices d
|
||||
LEFT JOIN sensor_data sd ON sd.device_id = d.device_id
|
||||
GROUP BY d.id, d.device_id, d.forward_enable, d.host, d.port, d.reg_code_hex
|
||||
ORDER BY d.id`
|
||||
|
||||
rows, err := db.Query(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var list []DeviceWithStats
|
||||
for rows.Next() {
|
||||
var item DeviceWithStats
|
||||
var fe int
|
||||
if err := rows.Scan(&item.ID, &item.DeviceID, &fe, &item.Host, &item.Port, &item.RegCodeHex, &item.SensorCount, &item.LastSeen); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.ForwardEnable = fe != 0
|
||||
list = append(list, item)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// GetSensorIDsByDevice 获取某设备下的传感器ID
|
||||
func GetSensorIDsByDevice(deviceID string) ([]int, error) {
|
||||
rows, err := db.Query(`SELECT DISTINCT sensor_id FROM sensor_data WHERE device_id = ? ORDER BY sensor_id`, deviceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var ids []int
|
||||
for rows.Next() {
|
||||
var id int
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// GetSensorDataByDevice 获取某设备下的数据(可选时间范围)
|
||||
func GetSensorDataByDevice(deviceID string, limit int, startDate, endDate time.Time) ([]SensorData, error) {
|
||||
query := "SELECT id, sensor_id, x_value, y_value, z_value, " +
|
||||
"COALESCE(temperature, 0) as temperature, " +
|
||||
"`timestamp` as timestamp " +
|
||||
"FROM sensor_data " +
|
||||
"WHERE device_id = ?"
|
||||
|
||||
var args []interface{}
|
||||
args = append(args, deviceID)
|
||||
|
||||
if !startDate.IsZero() {
|
||||
query += " AND `timestamp` >= ?"
|
||||
args = append(args, startDate)
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
query += " AND `timestamp` <= ?"
|
||||
args = append(args, endDate)
|
||||
}
|
||||
|
||||
query += " ORDER BY `timestamp` DESC"
|
||||
if limit > 0 {
|
||||
query += " LIMIT ?"
|
||||
args = append(args, limit)
|
||||
}
|
||||
|
||||
rows, err := db.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var result []SensorData
|
||||
for rows.Next() {
|
||||
var data SensorData
|
||||
var xInt, yInt, zInt, tempInt int
|
||||
if err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &tempInt, &data.Timestamp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.X = float64(xInt) / SCALING_FACTOR
|
||||
data.Y = float64(yInt) / SCALING_FACTOR
|
||||
data.Z = float64(zInt) / SCALING_FACTOR
|
||||
data.Temperature = float64(tempInt) / SCALING_FACTOR
|
||||
result = append(result, data)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetSensorDataByDeviceAndSensor 获取某设备某传感器的数据
|
||||
func GetSensorDataByDeviceAndSensor(deviceID string, sensorID int, limit int, startDate, endDate time.Time) ([]SensorData, error) {
|
||||
query := "SELECT id, sensor_id, x_value, y_value, z_value, " +
|
||||
"COALESCE(temperature, 0) as temperature, " +
|
||||
"`timestamp` as timestamp " +
|
||||
"FROM sensor_data " +
|
||||
"WHERE device_id = ? AND sensor_id = ?"
|
||||
|
||||
var args []interface{}
|
||||
args = append(args, deviceID, sensorID)
|
||||
|
||||
if !startDate.IsZero() {
|
||||
query += " AND `timestamp` >= ?"
|
||||
args = append(args, startDate)
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
query += " AND `timestamp` <= ?"
|
||||
args = append(args, endDate)
|
||||
}
|
||||
|
||||
query += " ORDER BY `timestamp` DESC"
|
||||
if limit > 0 {
|
||||
query += " LIMIT ?"
|
||||
args = append(args, limit)
|
||||
}
|
||||
|
||||
rows, err := db.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var result []SensorData
|
||||
for rows.Next() {
|
||||
var data SensorData
|
||||
var xInt, yInt, zInt, tempInt int
|
||||
if err := rows.Scan(&data.ID, &data.SensorID, &xInt, &yInt, &zInt, &tempInt, &data.Timestamp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.X = float64(xInt) / SCALING_FACTOR
|
||||
data.Y = float64(yInt) / SCALING_FACTOR
|
||||
data.Z = float64(zInt) / SCALING_FACTOR
|
||||
data.Temperature = float64(tempInt) / SCALING_FACTOR
|
||||
result = append(result, data)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@ -9,17 +9,20 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 启动HTTP服务器
|
||||
func StartHTTPServer(address string) error {
|
||||
http.HandleFunc("/", handleIndex)
|
||||
// 静态资源
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
|
||||
http.HandleFunc("/api/data", handleGetData)
|
||||
http.HandleFunc("/api/latest", handleGetLatest)
|
||||
http.HandleFunc("/api/sensors", handleGetSensors)
|
||||
http.HandleFunc("/api/clients", handleGetClients)
|
||||
http.HandleFunc("/api/devices", handleGetDevices)
|
||||
fmt.Printf("HTTP服务器已启动,正在监听 %s\n", address)
|
||||
return http.ListenAndServe(address, nil)
|
||||
}
|
||||
@ -60,6 +63,7 @@ func handleGetData(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
deviceID := r.URL.Query().Get("device_id")
|
||||
sensorIDStr := r.URL.Query().Get("sensor_id")
|
||||
limitStr := r.URL.Query().Get("limit")
|
||||
startDateStr := r.URL.Query().Get("start_date")
|
||||
@ -93,9 +97,11 @@ func handleGetData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// 使用北京时间解析前端传来的本地时间
|
||||
var startDate, endDate time.Time
|
||||
shLoc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
if startDateStr != "" {
|
||||
startDate, err = time.Parse("2006-01-02T15:04", startDateStr)
|
||||
startDate, err = time.ParseInLocation("2006-01-02T15:04", startDateStr, shLoc)
|
||||
if err != nil {
|
||||
log.Printf("错误: 无效的开始日期: %s, %v", startDateStr, err)
|
||||
http.Error(w, "无效的开始日期", http.StatusBadRequest)
|
||||
@ -104,7 +110,7 @@ func handleGetData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if endDateStr != "" {
|
||||
endDate, err = time.Parse("2006-01-02T15:04", endDateStr)
|
||||
endDate, err = time.ParseInLocation("2006-01-02T15:04", endDateStr, shLoc)
|
||||
if err != nil {
|
||||
log.Printf("错误: 无效的结束日期: %s, %v", endDateStr, err)
|
||||
http.Error(w, "无效的结束日期", http.StatusBadRequest)
|
||||
@ -112,18 +118,19 @@ func handleGetData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// 特殊处理获取最新数据的请求
|
||||
if limit == 1 && sensorIDStr == "" {
|
||||
log.Printf("检测到获取最新数据请求 (limit=1)")
|
||||
// 业务要求:必须提供 device_id;在设备下可选指定探头
|
||||
if strings.TrimSpace(deviceID) == "" {
|
||||
http.Error(w, "必须提供 device_id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var data []SensorData
|
||||
if sensorIDStr == "all" || sensorIDStr == "" {
|
||||
data, err = GetAllSensorData(limit, startDate, endDate)
|
||||
log.Printf("查询所有传感器数据,limit=%d, 结果数量=%d", limit, len(data))
|
||||
data, err = GetSensorDataByDevice(deviceID, limit, startDate, endDate)
|
||||
log.Printf("查询设备%s下所有传感器数据,limit=%d, 结果数量=%d", deviceID, limit, len(data))
|
||||
} else {
|
||||
data, err = GetSensorData(sensorID, limit, startDate, endDate)
|
||||
log.Printf("查询传感器%d数据,limit=%d, 结果数量=%d", sensorID, limit, len(data))
|
||||
data, err = GetSensorDataByDeviceAndSensor(deviceID, sensorID, limit, startDate, endDate)
|
||||
log.Printf("查询设备%s下传感器%d数据,limit=%d, 结果数量=%d", deviceID, sensorID, limit, len(data))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -156,8 +163,16 @@ func handleGetSensors(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("接收到获取传感器列表请求")
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
sensorIDs, err := GetAllSensorIDs()
|
||||
deviceID := r.URL.Query().Get("device_id")
|
||||
var (
|
||||
sensorIDs []int
|
||||
err error
|
||||
)
|
||||
if strings.TrimSpace(deviceID) != "" {
|
||||
sensorIDs, err = GetSensorIDsByDevice(deviceID)
|
||||
} else {
|
||||
sensorIDs, err = GetAllSensorIDs()
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("错误: 获取传感器ID失败: %v", err)
|
||||
http.Error(w, "获取传感器ID失败:"+err.Error(), http.StatusInternalServerError)
|
||||
@ -172,13 +187,52 @@ func handleGetSensors(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetClients(w http.ResponseWriter, r *http.Request) {
|
||||
// 已移除 /api/clients,在线统计改由 /api/devices 提供(3小时窗口)
|
||||
|
||||
// 处理获取设备列表及统计的API
|
||||
func handleGetDevices(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
clients := getAllClients()
|
||||
list, err := GetDevicesWithStats()
|
||||
if err != nil {
|
||||
log.Printf("错误: 获取设备列表失败: %v", err)
|
||||
http.Error(w, "获取设备列表失败:"+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(clients); err != nil {
|
||||
log.Printf("错误: 编码客户端信息JSON失败: %v", err)
|
||||
// 构造响应,计算是否在线(3小时内有上报)
|
||||
type deviceResp struct {
|
||||
ID int `json:"id"`
|
||||
DeviceID string `json:"device_id"`
|
||||
SensorCount int `json:"sensor_count"`
|
||||
LastSeen *time.Time `json:"last_seen"`
|
||||
Online bool `json:"online"`
|
||||
}
|
||||
|
||||
shLoc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
resp := make([]deviceResp, 0, len(list))
|
||||
now := time.Now().In(shLoc)
|
||||
for _, d := range list {
|
||||
var lsPtr *time.Time
|
||||
online := false
|
||||
if d.LastSeen.Valid {
|
||||
ls := d.LastSeen.Time.In(shLoc)
|
||||
lsPtr = &ls
|
||||
if now.Sub(ls) <= 3*time.Hour {
|
||||
online = true
|
||||
}
|
||||
}
|
||||
resp = append(resp, deviceResp{
|
||||
ID: d.ID,
|
||||
DeviceID: d.DeviceID,
|
||||
SensorCount: d.SensorCount,
|
||||
LastSeen: lsPtr,
|
||||
Online: online,
|
||||
})
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("错误: 编码设备列表JSON失败: %v", err)
|
||||
http.Error(w, "编码JSON失败:"+err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
1
static/css/tailwind.min.css
vendored
Normal file
1
static/css/tailwind.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
14
static/js/chart.js
Normal file
14
static/js/chart.js
Normal file
File diff suppressed because one or more lines are too long
1686
templates/index.html
1686
templates/index.html
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@ func StartUDPServer(address string) error {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
startClientCleanup()
|
||||
// 已移除客户端在线追踪;改由 DB 的 last_seen 统计在线
|
||||
|
||||
Logger.Printf("UDP服务器已启动,正在监听 %s\n", address)
|
||||
|
||||
@ -40,7 +40,7 @@ func StartUDPServer(address string) error {
|
||||
func handleUDPPacket(conn *net.UDPConn, addr *net.UDPAddr, data []byte) {
|
||||
remoteAddr := addr.String()
|
||||
|
||||
addClient(remoteAddr)
|
||||
// 已移除客户端在线追踪
|
||||
|
||||
rawData := string(data)
|
||||
TCPDataLogger.Printf("从UDP客户端 %s 接收到原始数据: %s", remoteAddr, rawData)
|
||||
@ -102,5 +102,5 @@ func handleUDPPacket(conn *net.UDPConn, addr *net.UDPAddr, data []byte) {
|
||||
Logger.Printf("发送响应到UDP客户端 %s 失败: %v", remoteAddr, err)
|
||||
}
|
||||
|
||||
updateClientLastSeen(remoteAddr)
|
||||
// 已移除客户端在线追踪
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user