添加区域主控相关路由
This commit is contained in:
@@ -55,6 +55,7 @@ func NewAPI(cfg config.ServerConfig,
|
||||
logger *logs.Logger,
|
||||
userRepo repository.UserRepository,
|
||||
deviceRepository repository.DeviceRepository,
|
||||
areaControllerRepository repository.AreaControllerRepository,
|
||||
planRepository repository.PlanRepository,
|
||||
userActionLogRepository repository.UserActionLogRepository,
|
||||
tokenService token.TokenService,
|
||||
@@ -85,7 +86,7 @@ func NewAPI(cfg config.ServerConfig,
|
||||
// 在 NewAPI 中初始化用户控制器,并将其作为 API 结构体的成员
|
||||
userController: user.NewController(userRepo, userActionLogRepository, logger, tokenService),
|
||||
// 在 NewAPI 中初始化设备控制器,并将其作为 API 结构体的成员
|
||||
deviceController: device.NewController(deviceRepository, logger),
|
||||
deviceController: device.NewController(deviceRepository, areaControllerRepository, logger),
|
||||
// 在 NewAPI 中初始化计划控制器,并将其作为 API 结构体的成员
|
||||
planController: plan.NewController(logger, planRepository, analysisTaskManager),
|
||||
}
|
||||
@@ -159,6 +160,17 @@ func (a *API) setupRoutes() {
|
||||
}
|
||||
a.logger.Info("设备相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
// 区域主控相关路由组
|
||||
areaControllerGroup := authGroup.Group("/area-controllers")
|
||||
{
|
||||
areaControllerGroup.POST("", a.deviceController.CreateAreaController)
|
||||
areaControllerGroup.GET("", a.deviceController.ListAreaControllers)
|
||||
areaControllerGroup.GET("/:id", a.deviceController.GetAreaController)
|
||||
areaControllerGroup.PUT("/:id", a.deviceController.UpdateAreaController)
|
||||
areaControllerGroup.DELETE("/:id", a.deviceController.DeleteAreaController)
|
||||
}
|
||||
a.logger.Info("区域主控相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
// 计划相关路由组
|
||||
planGroup := authGroup.Group("/plans")
|
||||
{
|
||||
|
||||
@@ -16,17 +16,23 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Controller 设备控制器,封装了所有与设备相关的业务逻辑
|
||||
// Controller 设备控制器,封装了所有与设备和区域主控相关的业务逻辑
|
||||
type Controller struct {
|
||||
repo repository.DeviceRepository
|
||||
logger *logs.Logger
|
||||
deviceRepo repository.DeviceRepository
|
||||
areaControllerRepo repository.AreaControllerRepository
|
||||
logger *logs.Logger
|
||||
}
|
||||
|
||||
// NewController 创建一个新的设备控制器实例
|
||||
func NewController(repo repository.DeviceRepository, logger *logs.Logger) *Controller {
|
||||
func NewController(
|
||||
deviceRepo repository.DeviceRepository,
|
||||
areaControllerRepo repository.AreaControllerRepository,
|
||||
logger *logs.Logger,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
repo: repo,
|
||||
logger: logger,
|
||||
deviceRepo: deviceRepo,
|
||||
areaControllerRepo: areaControllerRepo,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +56,22 @@ type UpdateDeviceRequest struct {
|
||||
Properties map[string]interface{} `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
// CreateAreaControllerRequest 定义了创建区域主控时需要传入的参数
|
||||
type CreateAreaControllerRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
NetworkID string `json:"network_id" binding:"required"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Properties map[string]interface{} `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateAreaControllerRequest 定义了更新区域主控时需要传入的参数
|
||||
type UpdateAreaControllerRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
NetworkID string `json:"network_id" binding:"required"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Properties map[string]interface{} `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
// --- Response DTOs ---
|
||||
|
||||
// DeviceResponse 定义了返回给客户端的单个设备信息的结构
|
||||
@@ -66,6 +88,18 @@ type DeviceResponse struct {
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// AreaControllerResponse 定义了返回给客户端的单个区域主控信息的结构
|
||||
type AreaControllerResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
NetworkID string `json:"network_id"`
|
||||
Location string `json:"location"`
|
||||
Status string `json:"status"`
|
||||
Properties map[string]interface{} `json:"properties"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// --- DTO 转换函数 ---
|
||||
|
||||
// newDeviceResponse 从数据库模型创建一个新的设备响应 DTO
|
||||
@@ -119,7 +153,45 @@ func newListDeviceResponse(devices []*models.Device) ([]*DeviceResponse, error)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// --- Controller Methods ---
|
||||
// newAreaControllerResponse 从数据库模型创建一个新的区域主控响应 DTO
|
||||
func newAreaControllerResponse(ac *models.AreaController) (*AreaControllerResponse, error) {
|
||||
if ac == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var props map[string]interface{}
|
||||
if len(ac.Properties) > 0 && string(ac.Properties) != "null" {
|
||||
if err := json.Unmarshal(ac.Properties, &props); err != nil {
|
||||
return nil, fmt.Errorf("解析区域主控属性失败 (ID: %d): %w", ac.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &AreaControllerResponse{
|
||||
ID: ac.ID,
|
||||
Name: ac.Name,
|
||||
NetworkID: ac.NetworkID,
|
||||
Location: ac.Location,
|
||||
Status: ac.Status,
|
||||
Properties: props,
|
||||
CreatedAt: ac.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: ac.UpdatedAt.Format(time.RFC3339),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newListAreaControllerResponse 从数据库模型切片创建一个新的区域主控列表响应 DTO 切片
|
||||
func newListAreaControllerResponse(acs []*models.AreaController) ([]*AreaControllerResponse, error) {
|
||||
list := make([]*AreaControllerResponse, 0, len(acs))
|
||||
for _, ac := range acs {
|
||||
resp, err := newAreaControllerResponse(ac)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = append(list, resp)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// --- Controller Methods: Devices ---
|
||||
|
||||
// CreateDevice godoc
|
||||
// @Summary 创建新设备
|
||||
@@ -154,25 +226,19 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
|
||||
Properties: propertiesJSON,
|
||||
}
|
||||
|
||||
// 在创建设备前进行自检
|
||||
// 注意:这里的 SelfCheck 依赖于 DeviceTemplate 和 AreaController 字段,
|
||||
// 但在创建时这些关联对象可能尚未完全加载。如果 SelfCheck 内部需要这些关联对象,
|
||||
// 则需要在调用 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
|
||||
}
|
||||
|
||||
if err := c.repo.Create(device); err != nil {
|
||||
if err := c.deviceRepo.Create(device); err != nil {
|
||||
c.logger.Errorf("%s: 数据库操作失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建设备失败: "+err.Error(), actionType, "数据库创建失败", device)
|
||||
return
|
||||
}
|
||||
|
||||
// 为了在响应中包含 DeviceTemplateName 和 AreaControllerName,需要重新从数据库加载设备,并预加载关联。
|
||||
createdDevice, err := c.repo.FindByID(device.ID)
|
||||
createdDevice, err := c.deviceRepo.FindByID(device.ID)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 重新加载创建的设备失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但重新加载设备失败", actionType, "重新加载设备失败", device)
|
||||
@@ -208,8 +274,7 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 假设 FindByIDString 方法会预加载 DeviceTemplate 和 AreaController
|
||||
device, err := c.repo.FindByIDString(deviceID)
|
||||
device, err := c.deviceRepo.FindByIDString(deviceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID)
|
||||
@@ -246,8 +311,7 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
|
||||
// @Router /api/v1/devices [get]
|
||||
func (c *Controller) ListDevices(ctx *gin.Context) {
|
||||
const actionType = "获取设备列表"
|
||||
// 假设 ListAll 方法会预加载 DeviceTemplate 和 AreaController
|
||||
devices, err := c.repo.ListAll()
|
||||
devices, err := c.deviceRepo.ListAll()
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备列表失败: "+err.Error(), actionType, "数据库查询失败", nil)
|
||||
@@ -279,9 +343,7 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
||||
const actionType = "更新设备"
|
||||
deviceID := ctx.Param("id")
|
||||
|
||||
// 1. 检查设备是否存在
|
||||
// 假设 FindByIDString 方法会预加载 DeviceTemplate 和 AreaController
|
||||
existingDevice, err := c.repo.FindByIDString(deviceID)
|
||||
existingDevice, err := c.deviceRepo.FindByIDString(deviceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID)
|
||||
@@ -298,7 +360,6 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 绑定请求参数
|
||||
var req UpdateDeviceRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
@@ -313,33 +374,25 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 更新从数据库中查出的现有设备对象的字段
|
||||
existingDevice.Name = req.Name
|
||||
existingDevice.DeviceTemplateID = req.DeviceTemplateID
|
||||
existingDevice.AreaControllerID = req.AreaControllerID
|
||||
existingDevice.Location = req.Location
|
||||
existingDevice.Properties = propertiesJSON
|
||||
|
||||
// 在更新设备前进行自检
|
||||
// 注意:这里的 SelfCheck 依赖于 DeviceTemplate 和 AreaController 字段,
|
||||
// 但在更新时这些关联对象可能尚未完全加载。如果 SelfCheck 内部需要这些关联对象,
|
||||
// 则需要在调用 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
|
||||
}
|
||||
|
||||
// 4. 将修改后的 existingDevice 对象保存回数据库
|
||||
if err := c.repo.Update(existingDevice); err != nil {
|
||||
if err := c.deviceRepo.Update(existingDevice); err != nil {
|
||||
c.logger.Errorf("%s: 数据库更新失败: %v, Device: %+v", actionType, err, existingDevice)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新设备失败: "+err.Error(), actionType, "数据库更新失败", existingDevice)
|
||||
return
|
||||
}
|
||||
|
||||
// 为了在响应中包含 DeviceTemplateName 和 AreaControllerName,需要重新从数据库加载设备,并预加载关联。
|
||||
updatedDevice, err := c.repo.FindByID(existingDevice.ID)
|
||||
updatedDevice, err := c.deviceRepo.FindByID(existingDevice.ID)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 重新加载更新的设备失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但重新加载设备失败", actionType, "重新加载设备失败", existingDevice)
|
||||
@@ -369,7 +422,6 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
|
||||
const actionType = "删除设备"
|
||||
deviceID := ctx.Param("id")
|
||||
|
||||
// 我们需要先将字符串ID转换为uint,因为Delete方法需要uint类型
|
||||
idUint, err := strconv.ParseUint(deviceID, 10, 64)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 设备ID格式错误: %v, ID: %s", actionType, err, deviceID)
|
||||
@@ -377,8 +429,7 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查设备是否存在(可选,但通常在删除前会检查)
|
||||
_, err = c.repo.FindByIDString(deviceID)
|
||||
_, err = c.deviceRepo.FindByIDString(deviceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID)
|
||||
@@ -390,7 +441,7 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.repo.Delete(uint(idUint)); err != nil {
|
||||
if err := c.deviceRepo.Delete(uint(idUint)); err != nil {
|
||||
c.logger.Errorf("%s: 数据库删除失败: %v, ID: %d", actionType, err, idUint)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除设备失败: "+err.Error(), actionType, "数据库删除失败", deviceID)
|
||||
return
|
||||
@@ -399,3 +450,245 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
|
||||
c.logger.Infof("%s: 设备删除成功, ID: %d", actionType, idUint)
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "设备删除成功", nil, actionType, "设备删除成功", deviceID)
|
||||
}
|
||||
|
||||
// --- Controller Methods: Area Controllers ---
|
||||
|
||||
// CreateAreaController godoc
|
||||
// @Summary 创建新区域主控
|
||||
// @Description 根据提供的信息创建一个新区域主控
|
||||
// @Tags 区域主控管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param areaController body CreateAreaControllerRequest true "区域主控信息"
|
||||
// @Success 200 {object} controller.Response{data=AreaControllerResponse}
|
||||
// @Router /api/v1/area-controllers [post]
|
||||
func (c *Controller) CreateAreaController(ctx *gin.Context) {
|
||||
const actionType = "创建区域主控"
|
||||
var req CreateAreaControllerRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
propertiesJSON, err := json.Marshal(req.Properties)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化属性失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", actionType, "属性序列化失败", req.Properties)
|
||||
return
|
||||
}
|
||||
|
||||
ac := &models.AreaController{
|
||||
Name: req.Name,
|
||||
NetworkID: req.NetworkID,
|
||||
Location: req.Location,
|
||||
Properties: propertiesJSON,
|
||||
}
|
||||
|
||||
if err := ac.SelfCheck(); err != nil {
|
||||
c.logger.Errorf("%s: 区域主控自检失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "区域主控参数不符合要求: "+err.Error(), actionType, "区域主控自检失败", ac)
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.areaControllerRepo.Create(ac); err != nil {
|
||||
c.logger.Errorf("%s: 数据库操作失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建区域主控失败: "+err.Error(), actionType, "数据库创建失败", ac)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := newAreaControllerResponse(ac)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化响应失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "区域主控创建成功,但响应生成失败", actionType, "响应序列化失败", ac)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Infof("%s: 区域主控创建成功, ID: %d", actionType, ac.ID)
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "区域主控创建成功", resp, actionType, "区域主控创建成功", resp)
|
||||
}
|
||||
|
||||
// GetAreaController godoc
|
||||
// @Summary 获取区域主控信息
|
||||
// @Description 根据ID获取单个区域主控的详细信息
|
||||
// @Tags 区域主控管理
|
||||
// @Produce json
|
||||
// @Param id path string true "区域主控ID"
|
||||
// @Success 200 {object} controller.Response{data=AreaControllerResponse}
|
||||
// @Router /api/v1/area-controllers/{id} [get]
|
||||
func (c *Controller) GetAreaController(ctx *gin.Context) {
|
||||
const actionType = "获取区域主控"
|
||||
acID := ctx.Param("id")
|
||||
|
||||
idUint, err := strconv.ParseUint(acID, 10, 64)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 区域主控ID格式错误: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的区域主控ID格式", actionType, "ID格式错误", acID)
|
||||
return
|
||||
}
|
||||
|
||||
ac, err := c.areaControllerRepo.FindByID(uint(idUint))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 区域主控不存在, ID: %s", actionType, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "区域主控未找到", actionType, "区域主控不存在", acID)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 数据库查询失败: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取区域主控信息失败: "+err.Error(), actionType, "数据库查询失败", acID)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := newAreaControllerResponse(ac)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化响应失败: %v, AreaController: %+v", actionType, err, ac)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取区域主控信息失败: 内部数据格式错误", actionType, "响应序列化失败", ac)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Infof("%s: 获取区域主控信息成功, ID: %d", actionType, ac.ID)
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取区域主控信息成功", resp, actionType, "获取区域主控信息成功", resp)
|
||||
}
|
||||
|
||||
// ListAreaControllers godoc
|
||||
// @Summary 获取所有区域主控列表
|
||||
// @Description 获取系统中所有区域主控的列表
|
||||
// @Tags 区域主控管理
|
||||
// @Produce json
|
||||
// @Success 200 {object} controller.Response{data=[]AreaControllerResponse}
|
||||
// @Router /api/v1/area-controllers [get]
|
||||
func (c *Controller) ListAreaControllers(ctx *gin.Context) {
|
||||
const actionType = "获取区域主控列表"
|
||||
acs, err := c.areaControllerRepo.ListAll()
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取区域主控列表失败: "+err.Error(), actionType, "数据库查询失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := newListAreaControllerResponse(acs)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化响应失败: %v, AreaControllers: %+v", actionType, err, acs)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取区域主控列表失败: 内部数据格式错误", actionType, "响应序列化失败", acs)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Infof("%s: 获取区域主控列表成功, 数量: %d", actionType, len(acs))
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取区域主控列表成功", resp, actionType, "获取区域主控列表成功", resp)
|
||||
}
|
||||
|
||||
// UpdateAreaController godoc
|
||||
// @Summary 更新区域主控信息
|
||||
// @Description 根据ID更新一个已存在的区域主控信息
|
||||
// @Tags 区域主控管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "区域主控ID"
|
||||
// @Param areaController body UpdateAreaControllerRequest true "要更新的区域主控信息"
|
||||
// @Success 200 {object} controller.Response{data=AreaControllerResponse}
|
||||
// @Router /api/v1/area-controllers/{id} [put]
|
||||
func (c *Controller) UpdateAreaController(ctx *gin.Context) {
|
||||
const actionType = "更新区域主控"
|
||||
acID := ctx.Param("id")
|
||||
|
||||
idUint, err := strconv.ParseUint(acID, 10, 64)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 区域主控ID格式错误: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的区域主控ID格式", actionType, "ID格式错误", acID)
|
||||
return
|
||||
}
|
||||
|
||||
existingAC, err := c.areaControllerRepo.FindByID(uint(idUint))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 区域主控不存在, ID: %s", actionType, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "区域主控未找到", actionType, "区域主控不存在", acID)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 数据库查询失败: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新区域主控失败: "+err.Error(), actionType, "数据库查询失败", acID)
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateAreaControllerRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
propertiesJSON, err := json.Marshal(req.Properties)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化属性失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", actionType, "属性序列化失败", req.Properties)
|
||||
return
|
||||
}
|
||||
|
||||
existingAC.Name = req.Name
|
||||
existingAC.NetworkID = req.NetworkID
|
||||
existingAC.Location = req.Location
|
||||
existingAC.Properties = propertiesJSON
|
||||
|
||||
if err := existingAC.SelfCheck(); err != nil {
|
||||
c.logger.Errorf("%s: 区域主控自检失败: %v", actionType, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "区域主控参数不符合要求: "+err.Error(), actionType, "区域主控自检失败", existingAC)
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.areaControllerRepo.Update(existingAC); err != nil {
|
||||
c.logger.Errorf("%s: 数据库更新失败: %v, AreaController: %+v", actionType, err, existingAC)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新区域主控失败: "+err.Error(), actionType, "数据库更新失败", existingAC)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := newAreaControllerResponse(existingAC)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 序列化响应失败: %v, AreaController: %+v", actionType, err, existingAC)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "区域主控更新成功,但响应生成失败", actionType, "响应序列化失败", existingAC)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Infof("%s: 区域主控更新成功, ID: %d", actionType, existingAC.ID)
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "区域主控更新成功", resp, actionType, "区域主控更新成功", resp)
|
||||
}
|
||||
|
||||
// DeleteAreaController godoc
|
||||
// @Summary 删除区域主控
|
||||
// @Description 根据ID删除一个区域主控(软删除)
|
||||
// @Tags 区域主控管理
|
||||
// @Produce json
|
||||
// @Param id path string true "区域主控ID"
|
||||
// @Success 200 {object} controller.Response
|
||||
// @Router /api/v1/area-controllers/{id} [delete]
|
||||
func (c *Controller) DeleteAreaController(ctx *gin.Context) {
|
||||
const actionType = "删除区域主控"
|
||||
acID := ctx.Param("id")
|
||||
|
||||
idUint, err := strconv.ParseUint(acID, 10, 64)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 区域主控ID格式错误: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的区域主控ID格式", actionType, "ID格式错误", acID)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = c.areaControllerRepo.FindByID(uint(idUint))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.logger.Warnf("%s: 区域主控不存在, ID: %s", actionType, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "区域主控未找到", actionType, "区域主控不存在", acID)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 查找区域主控失败: %v, ID: %s", actionType, err, acID)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除区域主控失败: 查找时发生内部错误", actionType, "数据库查询失败", acID)
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.areaControllerRepo.Delete(uint(idUint)); err != nil {
|
||||
c.logger.Errorf("%s: 数据库删除失败: %v, ID: %d", actionType, err, idUint)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除区域主控失败: "+err.Error(), actionType, "数据库删除失败", acID)
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Infof("%s: 区域主控删除成功, ID: %d", actionType, idUint)
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "区域主控删除成功", nil, actionType, "区域主控删除成功", acID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user