Files
goauto/server/app/goauto/device/list.go
T

146 lines
4.7 KiB
Go

package device
import (
"context"
"strconv"
"strings"
"time"
"go-admin/app/goauto/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ListRequest struct {
Page int
PageSize int
Name string
Status string
OwnerUserID *uint64
}
type DeviceListItem struct {
ID uint64 `json:"id"`
Name string `json:"name"`
Manufacturer string `json:"manufacturer"`
Model string `json:"model"`
AndroidVersion string `json:"androidVersion"`
AgentVersion string `json:"agentVersion"`
PDDVersion string `json:"pddVersion"`
Capabilities []string `json:"capabilities"`
Status string `json:"status"`
Busy bool `json:"busy"`
Selectable bool `json:"selectable"`
TokenRevoked bool `json:"tokenRevoked"`
CurrentTaskID *uint64 `json:"currentTaskId"`
LastHeartbeatAt *time.Time `json:"lastHeartbeatAt"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
OwnerUserID *uint64 `json:"ownerUserId"`
OwnerName string `json:"ownerName"`
}
type DeviceListResponse struct {
Items []DeviceListItem `json:"items"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
func (service *Service) List(ctx context.Context, request ListRequest) (DeviceListResponse, error) {
if request.Page < 1 {
request.Page = 1
}
if request.PageSize < 1 {
request.PageSize = 20
}
if request.PageSize > 100 {
request.PageSize = 100
}
request.Name = strings.TrimSpace(request.Name)
request.Status = strings.TrimSpace(request.Status)
if request.Status != "" && request.Status != models.DeviceStatusOnline && request.Status != models.DeviceStatusOffline && request.Status != models.DeviceStatusDisabled {
return DeviceListResponse{}, invalidRequest("status 无效")
}
query := service.DB.WithContext(ctx).Model(&models.AgentDevice{})
if request.Name != "" {
query = query.Where("name LIKE ?", "%"+request.Name+"%")
}
if request.Status != "" {
query = query.Where("status = ?", request.Status)
}
if request.OwnerUserID != nil {
query = query.Where("owner_user_id = ?", *request.OwnerUserID)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return DeviceListResponse{}, internalError(err)
}
var records []models.AgentDevice
if err := query.Order("updated_at DESC, id DESC").
Offset((request.Page - 1) * request.PageSize).Limit(request.PageSize).Find(&records).Error; err != nil {
return DeviceListResponse{}, internalError(err)
}
items := make([]DeviceListItem, 0, len(records))
if len(records) == 0 {
return DeviceListResponse{Items: items, Total: total, Page: request.Page, PageSize: request.PageSize}, nil
}
ids := make([]uint64, 0, len(records))
for _, record := range records {
ids = append(ids, record.ID)
}
currentTasks, err := currentTaskIDsForDevices(service.DB.WithContext(ctx), ids)
if err != nil {
return DeviceListResponse{}, err
}
for _, record := range records {
capabilities, err := Capabilities(record)
if err != nil {
return DeviceListResponse{}, err
}
item := DeviceListItem{
ID: record.ID, Name: record.Name, Manufacturer: record.Manufacturer, Model: record.Model,
AndroidVersion: record.AndroidVersion, AgentVersion: record.AgentVersion, PDDVersion: record.PDDVersion,
Capabilities: capabilities,
Status: record.Status, LastHeartbeatAt: record.LastHeartbeatAt,
TokenRevoked: record.TokenRevokedAt != nil, OwnerUserID: record.OwnerUserID,
CreatedAt: record.CreatedAt, UpdatedAt: record.UpdatedAt,
}
if taskID, busy := currentTasks[record.ID]; busy {
item.Busy = true
item.CurrentTaskID = &taskID
}
item.Selectable = item.Status == models.DeviceStatusOnline && !item.Busy
items = append(items, item)
}
return DeviceListResponse{Items: items, Total: total, Page: request.Page, PageSize: request.PageSize}, nil
}
func parseListRequest(context *gin.Context) (ListRequest, error) {
request := ListRequest{Name: context.Query("name"), Status: context.Query("status")}
var err error
request.Page, err = positiveQueryInt(context.Query("page"), 1)
if err != nil {
return request, invalidRequest("page 必须是正整数")
}
request.PageSize, err = positiveQueryInt(context.Query("pageSize"), 20)
if err != nil {
return request, invalidRequest("pageSize 必须是正整数")
}
return request, nil
}
func positiveQueryInt(value string, fallback int) (int, error) {
if strings.TrimSpace(value) == "" {
return fallback, nil
}
parsed, err := strconv.Atoi(value)
if err != nil || parsed < 1 {
return 0, gorm.ErrInvalidValue
}
return parsed, nil
}