Files
pig-farm-controller/internal/infra/models/models.go
2025-09-30 21:44:03 +08:00

95 lines
2.0 KiB
Go

package models
import (
"database/sql/driver"
"errors"
"fmt"
"strconv"
"strings"
)
// GetAllModels 返回一个包含所有数据库模型实例的切片。
// 这个函数用于在数据库初始化时自动迁移所有的表结构。
func GetAllModels() []interface{} {
return []interface{}{
&User{},
&Device{},
&Plan{},
&SubPlan{},
&Task{},
&PlanExecutionLog{},
&TaskExecutionLog{},
&PendingTask{},
&SensorData{},
&DeviceCommandLog{},
&PendingCollection{},
&AreaController{},
&DeviceTemplate{},
&UserActionLog{},
}
}
// UintArray 是一个自定义类型,代表 uint 的切片。
// 它实现了 gorm.Scanner 和 driver.Valuer 接口,
// 以便能与数据库的 bigint[] 类型进行原生映射。
type UintArray []uint
// Value 实现了 driver.Valuer 接口。
// 它告诉 GORM 如何将 UintArray ([]) 转换为数据库能够理解的格式。
func (a UintArray) Value() (driver.Value, error) {
if a == nil {
return "{}", nil
}
var b strings.Builder
b.WriteString("{")
for i, v := range a {
if i > 0 {
b.WriteString(",")
}
b.WriteString(strconv.FormatUint(uint64(v), 10))
}
b.WriteString("}")
return b.String(), nil
}
// Scan 实现了 gorm.Scanner 接口。
// 它告诉 GORM 如何将从数据库读取的数据转换为我们的 UintArray ([])。
func (a *UintArray) Scan(src interface{}) error {
if src == nil {
*a = nil
return nil
}
var srcStr string
switch v := src.(type) {
case []byte:
srcStr = string(v)
case string:
srcStr = v
default:
return errors.New("无法扫描非字符串或字节类型的源到 UintArray")
}
// 去掉花括号
srcStr = strings.Trim(srcStr, "{}")
if srcStr == "" {
*a = []uint{}
return nil
}
// 按逗号分割
parts := strings.Split(srcStr, ",")
arr := make([]uint, len(parts))
for i, p := range parts {
val, err := strconv.ParseUint(p, 10, 64)
if err != nil {
return fmt.Errorf("解析 UintArray 元素失败: %w", err)
}
arr[i] = uint(val)
}
*a = arr
return nil
}