调整 Controller
This commit is contained in:
@@ -34,37 +34,36 @@ func NewController(repo repository.DeviceRepository, logger *logs.Logger) *Contr
|
|||||||
|
|
||||||
// CreateDeviceRequest 定义了创建设备时需要传入的参数
|
// CreateDeviceRequest 定义了创建设备时需要传入的参数
|
||||||
type CreateDeviceRequest struct {
|
type CreateDeviceRequest struct {
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Type models.DeviceType `json:"type" binding:"required"`
|
DeviceTemplateID uint `json:"device_template_id" binding:"required"`
|
||||||
SubType models.DeviceSubType `json:"sub_type,omitempty"`
|
AreaControllerID uint `json:"area_controller_id" binding:"required"`
|
||||||
ParentID *uint `json:"parent_id,omitempty"`
|
Location string `json:"location,omitempty"`
|
||||||
Location string `json:"location,omitempty"`
|
Properties map[string]interface{} `json:"properties,omitempty"`
|
||||||
Properties map[string]interface{} `json:"properties,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeviceRequest 定义了更新设备时需要传入的参数
|
// UpdateDeviceRequest 定义了更新设备时需要传入的参数
|
||||||
type UpdateDeviceRequest struct {
|
type UpdateDeviceRequest struct {
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Type models.DeviceType `json:"type" binding:"required"`
|
DeviceTemplateID uint `json:"device_template_id" binding:"required"`
|
||||||
SubType models.DeviceSubType `json:"sub_type,omitempty"`
|
AreaControllerID uint `json:"area_controller_id" binding:"required"`
|
||||||
ParentID *uint `json:"parent_id,omitempty"`
|
Location string `json:"location,omitempty"`
|
||||||
Location string `json:"location,omitempty"`
|
Properties map[string]interface{} `json:"properties,omitempty"`
|
||||||
Properties map[string]interface{} `json:"properties,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Response DTOs ---
|
// --- Response DTOs ---
|
||||||
|
|
||||||
// DeviceResponse 定义了返回给客户端的单个设备信息的结构
|
// DeviceResponse 定义了返回给客户端的单个设备信息的结构
|
||||||
type DeviceResponse struct {
|
type DeviceResponse struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type models.DeviceType `json:"type"`
|
DeviceTemplateID uint `json:"device_template_id"`
|
||||||
SubType models.DeviceSubType `json:"sub_type"`
|
DeviceTemplateName string `json:"device_template_name"`
|
||||||
ParentID *uint `json:"parent_id"`
|
AreaControllerID uint `json:"area_controller_id"`
|
||||||
Location string `json:"location"`
|
AreaControllerName string `json:"area_controller_name"`
|
||||||
Properties map[string]interface{} `json:"properties"`
|
Location string `json:"location"`
|
||||||
CreatedAt string `json:"created_at"`
|
Properties map[string]interface{} `json:"properties"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- DTO 转换函数 ---
|
// --- DTO 转换函数 ---
|
||||||
@@ -82,16 +81,28 @@ func newDeviceResponse(device *models.Device) (*DeviceResponse, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保 DeviceTemplate 和 AreaController 已预加载
|
||||||
|
deviceTemplateName := ""
|
||||||
|
if device.DeviceTemplate.ID != 0 {
|
||||||
|
deviceTemplateName = device.DeviceTemplate.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
areaControllerName := ""
|
||||||
|
if device.AreaController.ID != 0 {
|
||||||
|
areaControllerName = device.AreaController.Name
|
||||||
|
}
|
||||||
|
|
||||||
return &DeviceResponse{
|
return &DeviceResponse{
|
||||||
ID: device.ID,
|
ID: device.ID,
|
||||||
Name: device.Name,
|
Name: device.Name,
|
||||||
Type: device.Type,
|
DeviceTemplateID: device.DeviceTemplateID,
|
||||||
SubType: device.SubType,
|
DeviceTemplateName: deviceTemplateName,
|
||||||
ParentID: device.ParentID,
|
AreaControllerID: device.AreaControllerID,
|
||||||
Location: device.Location,
|
AreaControllerName: areaControllerName,
|
||||||
Properties: props,
|
Location: device.Location,
|
||||||
CreatedAt: device.CreatedAt.Format(time.RFC3339),
|
Properties: props,
|
||||||
UpdatedAt: device.UpdatedAt.Format(time.RFC3339),
|
CreatedAt: device.CreatedAt.Format(time.RFC3339),
|
||||||
|
UpdatedAt: device.UpdatedAt.Format(time.RFC3339),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,18 +147,21 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
device := &models.Device{
|
device := &models.Device{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Type: req.Type,
|
DeviceTemplateID: req.DeviceTemplateID,
|
||||||
SubType: req.SubType,
|
AreaControllerID: req.AreaControllerID,
|
||||||
ParentID: req.ParentID,
|
Location: req.Location,
|
||||||
Location: req.Location,
|
Properties: propertiesJSON,
|
||||||
Properties: propertiesJSON,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在创建设备前进行自检
|
// 在创建设备前进行自检
|
||||||
if !device.SelfCheck() {
|
// 注意:这里的 SelfCheck 依赖于 DeviceTemplate 和 AreaController 字段,
|
||||||
c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, device)
|
// 但在创建时这些关联对象可能尚未完全加载。如果 SelfCheck 内部需要这些关联对象,
|
||||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", actionType, "设备属性自检失败", device)
|
// 则需要在调用 SelfCheck 之前手动加载或调整 SelfCheck 逻辑。
|
||||||
|
// 目前假设 SelfCheck 仅检查 ID 和 Properties。
|
||||||
|
if err := device.SelfCheck(); err != nil {
|
||||||
|
c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, err)
|
||||||
|
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求: "+err.Error(), actionType, "设备属性自检失败", device)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,10 +171,18 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := newDeviceResponse(device)
|
// 为了在响应中包含 DeviceTemplateName 和 AreaControllerName,需要重新从数据库加载设备,并预加载关联。
|
||||||
|
createdDevice, err := c.repo.FindByID(device.ID)
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Errorf("%s: 重新加载创建的设备失败: %v", actionType, err)
|
||||||
|
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但重新加载设备失败", actionType, "重新加载设备失败", device)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := newDeviceResponse(createdDevice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf("%s: 序列化响应失败: %v", actionType, err)
|
c.logger.Errorf("%s: 序列化响应失败: %v", actionType, err)
|
||||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但响应生成失败", actionType, "响应序列化失败", device)
|
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但响应生成失败", actionType, "响应序列化失败", createdDevice)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +208,7 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 假设 FindByIDString 方法会预加载 DeviceTemplate 和 AreaController
|
||||||
device, err := c.repo.FindByIDString(deviceID)
|
device, err := c.repo.FindByIDString(deviceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -223,6 +246,7 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
|
|||||||
// @Router /api/v1/devices [get]
|
// @Router /api/v1/devices [get]
|
||||||
func (c *Controller) ListDevices(ctx *gin.Context) {
|
func (c *Controller) ListDevices(ctx *gin.Context) {
|
||||||
const actionType = "获取设备列表"
|
const actionType = "获取设备列表"
|
||||||
|
// 假设 ListAll 方法会预加载 DeviceTemplate 和 AreaController
|
||||||
devices, err := c.repo.ListAll()
|
devices, err := c.repo.ListAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err)
|
c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err)
|
||||||
@@ -256,6 +280,7 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
|||||||
deviceID := ctx.Param("id")
|
deviceID := ctx.Param("id")
|
||||||
|
|
||||||
// 1. 检查设备是否存在
|
// 1. 检查设备是否存在
|
||||||
|
// 假设 FindByIDString 方法会预加载 DeviceTemplate 和 AreaController
|
||||||
existingDevice, err := c.repo.FindByIDString(deviceID)
|
existingDevice, err := c.repo.FindByIDString(deviceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -290,16 +315,19 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
|||||||
|
|
||||||
// 3. 更新从数据库中查出的现有设备对象的字段
|
// 3. 更新从数据库中查出的现有设备对象的字段
|
||||||
existingDevice.Name = req.Name
|
existingDevice.Name = req.Name
|
||||||
existingDevice.Type = req.Type
|
existingDevice.DeviceTemplateID = req.DeviceTemplateID
|
||||||
existingDevice.SubType = req.SubType
|
existingDevice.AreaControllerID = req.AreaControllerID
|
||||||
existingDevice.ParentID = req.ParentID
|
|
||||||
existingDevice.Location = req.Location
|
existingDevice.Location = req.Location
|
||||||
existingDevice.Properties = propertiesJSON
|
existingDevice.Properties = propertiesJSON
|
||||||
|
|
||||||
// 在更新设备前进行自检
|
// 在更新设备前进行自检
|
||||||
if !existingDevice.SelfCheck() {
|
// 注意:这里的 SelfCheck 依赖于 DeviceTemplate 和 AreaController 字段,
|
||||||
c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, existingDevice)
|
// 但在更新时这些关联对象可能尚未完全加载。如果 SelfCheck 内部需要这些关联对象,
|
||||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", actionType, "设备属性自检失败", existingDevice)
|
// 则需要在调用 SelfCheck 之前手动加载或调整 SelfCheck 逻辑。
|
||||||
|
// 目前假设 SelfCheck 仅检查 ID 和 Properties。
|
||||||
|
if err := existingDevice.SelfCheck(); err != nil {
|
||||||
|
c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, err)
|
||||||
|
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求: "+err.Error(), actionType, "设备属性自检失败", existingDevice)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,10 +338,18 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := newDeviceResponse(existingDevice)
|
// 为了在响应中包含 DeviceTemplateName 和 AreaControllerName,需要重新从数据库加载设备,并预加载关联。
|
||||||
|
updatedDevice, err := c.repo.FindByID(existingDevice.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf("%s: 序列化响应失败: %v, Device: %+v", actionType, err, existingDevice)
|
c.logger.Errorf("%s: 重新加载更新的设备失败: %v", actionType, err)
|
||||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但响应生成失败", actionType, "响应序列化失败", existingDevice)
|
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但重新加载设备失败", actionType, "重新加载设备失败", existingDevice)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := newDeviceResponse(updatedDevice)
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Errorf("%s: 序列化响应失败: %v, Device: %+v", actionType, err, updatedDevice)
|
||||||
|
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但响应生成失败", actionType, "响应序列化失败", updatedDevice)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +382,7 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID)
|
c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID)
|
||||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备不存在", actionType, "设备不存在", deviceID)
|
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备未找到", actionType, "设备不存在", deviceID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.logger.Errorf("%s: 查找设备失败: %v, ID: %s", actionType, err, deviceID)
|
c.logger.Errorf("%s: 查找设备失败: %v, ID: %s", actionType, err, deviceID)
|
||||||
|
|||||||
Reference in New Issue
Block a user