Compare commits

..

2 Commits

Author SHA1 Message Date
8b22514aad 前端设备列表展示设备状态 2025-09-09 00:03:23 +08:00
75f9e07fcc 获取设备列表接口增加设备状态 2025-09-08 23:41:04 +08:00
6 changed files with 86 additions and 10 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>猪场管理系统</title> <title>猪场管理系统</title>
<script type="module" crossorigin src="/assets/index.a5284bc3.js"></script> <script type="module" crossorigin src="/assets/index.2015effd.js"></script>
<link rel="stylesheet" href="/assets/index.af933240.css"> <link rel="stylesheet" href="/assets/index.7f062720.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@@ -30,6 +30,7 @@
<span class="node-title">{{ relay.name }}</span> <span class="node-title">{{ relay.name }}</span>
<span class="node-type relay-type">{{ getDeviceTypeText(relay.type) }}</span> <span class="node-type relay-type">{{ getDeviceTypeText(relay.type) }}</span>
<span v-if="relay.address" class="node-address">[{{ relay.address }}]</span> <span v-if="relay.address" class="node-address">[{{ relay.address }}]</span>
<span class="node-status" :class="{ 'status-active': relay.active, 'status-inactive': !relay.active }">{{ relay.active ? '在线' : '离线' }}</span>
</div> </div>
<div class="node-actions"> <div class="node-actions">
<button class="action-btn edit-btn" @click.stop="editDevice(relay)">编辑</button> <button class="action-btn edit-btn" @click.stop="editDevice(relay)">编辑</button>
@@ -50,6 +51,7 @@
<span class="node-title">{{ controller.name }}</span> <span class="node-title">{{ controller.name }}</span>
<span class="node-type controller-type">{{ getDeviceTypeText(controller.type) }}</span> <span class="node-type controller-type">{{ getDeviceTypeText(controller.type) }}</span>
<span v-if="controller.address" class="node-address">[{{ controller.address }}]</span> <span v-if="controller.address" class="node-address">[{{ controller.address }}]</span>
<span class="node-status" :class="{ 'status-active': controller.active, 'status-inactive': !controller.active }">{{ controller.active ? '在线' : '离线' }}</span>
</div> </div>
<div class="node-actions"> <div class="node-actions">
<button class="action-btn edit-btn" @click.stop="editDevice(controller)">编辑</button> <button class="action-btn edit-btn" @click.stop="editDevice(controller)">编辑</button>
@@ -69,6 +71,7 @@
<span class="node-title">{{ leaf.name }}</span> <span class="node-title">{{ leaf.name }}</span>
<span class="node-type device-type">{{ getDeviceTypeText(leaf.type) }}</span> <span class="node-type device-type">{{ getDeviceTypeText(leaf.type) }}</span>
<span v-if="leaf.address" class="node-address">[{{ leaf.address }}]</span> <span v-if="leaf.address" class="node-address">[{{ leaf.address }}]</span>
<span class="node-status" :class="{ 'status-active': leaf.active, 'status-inactive': !leaf.active }">{{ leaf.active ? '在线' : '离线' }}</span>
</div> </div>
<div class="node-actions"> <div class="node-actions">
<button class="action-btn edit-btn" @click.stop="editDevice(leaf)">编辑</button> <button class="action-btn edit-btn" @click.stop="editDevice(leaf)">编辑</button>
@@ -225,6 +228,11 @@ export default {
'fan': '风机', 'fan': '风机',
'water_curtain': '水帘' 'water_curtain': '水帘'
} }
const statusMap = {
'online': '在线',
'offline': '离线',
'error': '故障'
}
return typeMap[type] || type return typeMap[type] || type
}, },
@@ -621,6 +629,23 @@ export default {
text-transform: uppercase; text-transform: uppercase;
} }
.node-status {
font-size: 0.8rem;
padding: 0.3rem 0.6rem;
border-radius: 12px;
font-weight: 500;
}
.status-active {
background: #4caf50;
color: white;
}
.status-inactive {
background: #9e9e9e;
color: white;
}
.relay-type { .relay-type {
background: #ff9800; background: #ff9800;
color: white; color: white;

View File

@@ -222,6 +222,7 @@ func (a *API) setupRoutes() {
deviceGroup.POST("/create", a.deviceController.Create) deviceGroup.POST("/create", a.deviceController.Create)
deviceGroup.POST("/update", a.deviceController.Update) deviceGroup.POST("/update", a.deviceController.Update)
deviceGroup.POST("/delete", a.deviceController.Delete) deviceGroup.POST("/delete", a.deviceController.Delete)
deviceGroup.GET("/status", a.deviceController.GetDeviceStatus)
} }
// 远程控制相关路由 // 远程控制相关路由

View File

@@ -17,7 +17,13 @@ import (
// ListResponse 设备列表响应结构体 // ListResponse 设备列表响应结构体
type ListResponse struct { type ListResponse struct {
Devices []model.Device `json:"devices"` Devices []DeviceListItem `json:"devices"`
}
// DeviceListItem 设备列表项结构体
type DeviceListItem struct {
model.Device
Active bool `json:"active"`
} }
// DeviceRequest 设备创建/更新请求结构体 // DeviceRequest 设备创建/更新请求结构体
@@ -140,7 +146,22 @@ func (c *Controller) List(ctx *gin.Context) {
return return
} }
controller.SendSuccessResponse(ctx, "获取设备列表成功", ListResponse{Devices: devices}) // 构建设备列表项,包含设备状态信息
deviceList := make([]DeviceListItem, len(devices))
for i, device := range devices {
// 从设备状态池获取设备状态,默认为非激活状态
active := false
if status, exists := c.deviceStatusPool.GetStatus(strconv.FormatUint(uint64(device.ID), 10)); exists {
active = status.Active
}
deviceList[i] = DeviceListItem{
Device: device,
Active: active,
}
}
controller.SendSuccessResponse(ctx, "获取设备列表成功", ListResponse{Devices: deviceList})
} }
// Create 创建设备 // Create 创建设备
@@ -290,6 +311,12 @@ type SwitchResponseData struct {
Message string `json:"message"` // 添加消息字段 Message string `json:"message"` // 添加消息字段
} }
// DeviceStatusResponse 设备状态响应结构体
type DeviceStatusResponse struct {
DeviceID string `json:"device_id"`
Active bool `json:"active"`
}
// RelayControlData 发送给中继设备的控制数据结构体 // RelayControlData 发送给中继设备的控制数据结构体
type RelayControlData struct { type RelayControlData struct {
DeviceType string `json:"device_type"` DeviceType string `json:"device_type"`
@@ -438,3 +465,26 @@ func (c *Controller) createDeviceControlRecord(userID uint, deviceID, deviceType
return c.deviceControlRepo.Create(control) return c.deviceControlRepo.Create(control)
} }
// GetDeviceStatus 获取设备当前状态
func (c *Controller) GetDeviceStatus(ctx *gin.Context) {
deviceID := ctx.Query("device_id")
if deviceID == "" {
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "设备ID不能为空")
return
}
// 从设备状态池中获取设备状态
status, exists := c.deviceStatusPool.GetStatus(deviceID)
if !exists {
controller.SendErrorResponse(ctx, controller.NotFoundCode, "设备状态不存在")
return
}
response := DeviceStatusResponse{
DeviceID: deviceID,
Active: status.Active,
}
controller.SendSuccessResponse(ctx, "获取设备状态成功", response)
}