package repository import ( "fmt" "strconv" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "gorm.io/gorm" ) // DeviceRepository 定义了与设备模型相关的数据库操作接口 // 这一层抽象使得上层业务逻辑无需关心底层数据库的具体实现。 type DeviceRepository interface { // Create 创建一个新设备记录 Create(device *models.Device) error // FindByID 根据主键 ID 查找设备 FindByID(id uint) (*models.Device, error) // FindByIDString 根据字符串形式的主键 ID 查找设备,方便控制器调用 FindByIDString(id string) (*models.Device, error) // ListAll 获取所有设备的列表 ListAll() ([]*models.Device, error) // ListByAreaControllerID 根据区域主控 ID 列出所有子设备。 ListByAreaControllerID(areaControllerID uint) ([]*models.Device, error) // FindByDeviceTemplateID 根据设备模板ID查找所有使用该模板的设备 FindByDeviceTemplateID(deviceTemplateID uint) ([]*models.Device, error) // Update 更新一个已有的设备信息 Update(device *models.Device) error // Delete 根据主键 ID 删除一个设备 Delete(id uint) error // FindByAreaControllerAndPhysicalAddress 根据区域主控ID和物理地址(总线号、总线地址)查找设备 FindByAreaControllerAndPhysicalAddress(areaControllerID uint, busNumber int, busAddress int) (*models.Device, error) } // gormDeviceRepository 是 DeviceRepository 的 GORM 实现 type gormDeviceRepository struct { db *gorm.DB } // NewGormDeviceRepository 创建一个新的 DeviceRepository GORM 实现实例 func NewGormDeviceRepository(db *gorm.DB) DeviceRepository { return &gormDeviceRepository{db: db} } // Create 创建一个新的设备记录 func (r *gormDeviceRepository) Create(device *models.Device) error { return r.db.Create(device).Error } // FindByID 根据 ID 查找设备 func (r *gormDeviceRepository) FindByID(id uint) (*models.Device, error) { var device models.Device if err := r.db.Preload("AreaController").Preload("DeviceTemplate").First(&device, id).Error; err != nil { return nil, err } return &device, nil } // FindByIDString 根据字符串形式的主键 ID 查找设备 func (r *gormDeviceRepository) FindByIDString(id string) (*models.Device, error) { // 将字符串ID转换为uint64 idInt, err := strconv.ParseUint(id, 10, 64) if err != nil { // 如果转换失败,说明ID格式不正确,返回一个明确的错误 return nil, fmt.Errorf("无效的设备ID格式: %w", err) } // 调用已有的 FindByID 方法 return r.FindByID(uint(idInt)) } // ListAll 获取所有设备的列表 func (r *gormDeviceRepository) ListAll() ([]*models.Device, error) { var devices []*models.Device if err := r.db.Preload("AreaController").Preload("DeviceTemplate").Find(&devices).Error; err != nil { return nil, err } return devices, nil } // ListByAreaControllerID 根据区域主控 ID 列出所有子设备 func (r *gormDeviceRepository) ListByAreaControllerID(areaControllerID uint) ([]*models.Device, error) { var devices []*models.Device err := r.db.Preload("AreaController").Preload("DeviceTemplate").Where("area_controller_id = ?", areaControllerID).Find(&devices).Error if err != nil { return nil, err } return devices, nil } // FindByDeviceTemplateID 根据设备模板ID查找所有使用该模板的设备 func (r *gormDeviceRepository) FindByDeviceTemplateID(deviceTemplateID uint) ([]*models.Device, error) { var devices []*models.Device err := r.db.Where("device_template_id = ?", deviceTemplateID).Find(&devices).Error if err != nil { return nil, fmt.Errorf("查询使用设备模板ID %d 的设备失败: %w", deviceTemplateID, err) } return devices, nil } // Update 更新一个已有的设备信息 // GORM 的 Save 方法会自动处理主键存在时更新,不存在时创建的逻辑,但这里我们明确用于更新。 func (r *gormDeviceRepository) Update(device *models.Device) error { return r.db.Save(device).Error } // Delete 根据 ID 删除一个设备 // GORM 使用软删除,记录不会从数据库中物理移除,而是设置 DeletedAt 字段。 func (r *gormDeviceRepository) Delete(id uint) error { return r.db.Delete(&models.Device{}, id).Error } // FindByAreaControllerAndPhysicalAddress 根据区域主控ID和物理地址(总线号、总线地址)查找设备 func (r *gormDeviceRepository) FindByAreaControllerAndPhysicalAddress(areaControllerID uint, busNumber int, busAddress int) (*models.Device, error) { var device models.Device err := r.db.Preload("AreaController").Preload("DeviceTemplate"). Where("area_controller_id = ?", areaControllerID). Where("properties->>'bus_number' = ?", strconv.Itoa(busNumber)). Where("properties->>'bus_address' = ?", strconv.Itoa(busAddress)). First(&device).Error if err != nil { return nil, fmt.Errorf("根据区域主控ID %d 和物理地址 (总线号: %d, 总线地址: %d) 查找设备失败: %w", areaControllerID, busNumber, busAddress, err) } return &device, nil }