Compare commits
	
		
			6 Commits
		
	
	
		
			565cf3fa6a
			...
			9caedd697d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9caedd697d | |||
| 6f3f7db870 | |||
| c7e2aaee89 | |||
| bab44e7e3a | |||
| 0895cf42b2 | |||
| d4ce0aa238 | 
@@ -9,7 +9,10 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/api/middleware"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/config"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/config"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller/device"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller/operation"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/controller/user"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller/user"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
				
			||||||
@@ -31,13 +34,22 @@ type API struct {
 | 
				
			|||||||
	// userController 用户控制器
 | 
						// userController 用户控制器
 | 
				
			||||||
	userController *user.Controller
 | 
						userController *user.Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// operationController 操作历史控制器
 | 
				
			||||||
 | 
						operationController *operation.Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// deviceController 设备控制控制器
 | 
				
			||||||
 | 
						deviceController *device.Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// authMiddleware 鉴权中间件
 | 
				
			||||||
 | 
						authMiddleware *middleware.AuthMiddleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// logger 日志记录器
 | 
						// logger 日志记录器
 | 
				
			||||||
	logger *logs.Logger
 | 
						logger *logs.Logger
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewAPI 创建并返回一个新的API实例
 | 
					// NewAPI 创建并返回一个新的API实例
 | 
				
			||||||
// 初始化Gin引擎和相关配置
 | 
					// 初始化Gin引擎和相关配置
 | 
				
			||||||
func NewAPI(cfg *config.Config, userRepo repository.UserRepo) *API {
 | 
					func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRepo repository.OperationHistoryRepo, deviceControlRepo repository.DeviceControlRepo, deviceRepo repository.DeviceRepo) *API {
 | 
				
			||||||
	// 设置Gin为发布模式
 | 
						// 设置Gin为发布模式
 | 
				
			||||||
	gin.SetMode(gin.ReleaseMode)
 | 
						gin.SetMode(gin.ReleaseMode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,10 +76,22 @@ func NewAPI(cfg *config.Config, userRepo repository.UserRepo) *API {
 | 
				
			|||||||
	// 创建用户控制器
 | 
						// 创建用户控制器
 | 
				
			||||||
	userController := user.NewController(userRepo)
 | 
						userController := user.NewController(userRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建操作历史控制器
 | 
				
			||||||
 | 
						operationController := operation.NewController(operationHistoryRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建设备控制控制器
 | 
				
			||||||
 | 
						deviceController := device.NewController(deviceControlRepo, deviceRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建鉴权中间件
 | 
				
			||||||
 | 
						authMiddleware := middleware.NewAuthMiddleware(userRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &API{
 | 
						return &API{
 | 
				
			||||||
		engine:              engine,
 | 
							engine:              engine,
 | 
				
			||||||
		config:              cfg,
 | 
							config:              cfg,
 | 
				
			||||||
		userController:      userController,
 | 
							userController:      userController,
 | 
				
			||||||
 | 
							operationController: operationController,
 | 
				
			||||||
 | 
							deviceController:    deviceController,
 | 
				
			||||||
 | 
							authMiddleware:      authMiddleware,
 | 
				
			||||||
		logger:              logs.NewLogger(),
 | 
							logger:              logs.NewLogger(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -129,6 +153,25 @@ func (a *API) setupRoutes() {
 | 
				
			|||||||
		userGroup.POST("/login", a.userController.Login)
 | 
							userGroup.POST("/login", a.userController.Login)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 需要鉴权的路由组
 | 
				
			||||||
 | 
						protectedGroup := a.engine.Group("/api/v1")
 | 
				
			||||||
 | 
						protectedGroup.Use(a.authMiddleware.Handle())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// 操作历史相关路由
 | 
				
			||||||
 | 
							operationGroup := protectedGroup.Group("/operation")
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								operationGroup.POST("/", a.operationController.Create)
 | 
				
			||||||
 | 
								operationGroup.GET("/list", a.operationController.ListByUser)
 | 
				
			||||||
 | 
								operationGroup.GET("/:id", a.operationController.Get)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 设备控制相关路由
 | 
				
			||||||
 | 
							deviceGroup := protectedGroup.Group("/device")
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								deviceGroup.POST("/switch", a.deviceController.Switch)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: 添加更多路由
 | 
						// TODO: 添加更多路由
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										156
									
								
								internal/controller/device/device.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								internal/controller/device/device.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,156 @@
 | 
				
			|||||||
 | 
					// Package device 提供设备控制相关功能的控制器
 | 
				
			||||||
 | 
					// 实现设备控制、查询等操作
 | 
				
			||||||
 | 
					package device
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/api/middleware"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Controller 设备控制控制器
 | 
				
			||||||
 | 
					type Controller struct {
 | 
				
			||||||
 | 
						deviceControlRepo repository.DeviceControlRepo
 | 
				
			||||||
 | 
						deviceRepo        repository.DeviceRepo
 | 
				
			||||||
 | 
						logger            *logs.Logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewController 创建设备控制控制器实例
 | 
				
			||||||
 | 
					func NewController(deviceControlRepo repository.DeviceControlRepo, deviceRepo repository.DeviceRepo) *Controller {
 | 
				
			||||||
 | 
						return &Controller{
 | 
				
			||||||
 | 
							deviceControlRepo: deviceControlRepo,
 | 
				
			||||||
 | 
							deviceRepo:        deviceRepo,
 | 
				
			||||||
 | 
							logger:            logs.NewLogger(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SwitchRequest 设备控制请求结构体
 | 
				
			||||||
 | 
					type SwitchRequest struct {
 | 
				
			||||||
 | 
						ParentID   *uint  `json:"parent_id"` // 区域主控ID
 | 
				
			||||||
 | 
						DeviceType string `json:"device_type" binding:"required,oneof=fan water_curtain"`
 | 
				
			||||||
 | 
						DeviceID   string `json:"device_id" binding:"required"`
 | 
				
			||||||
 | 
						Action     string `json:"action" binding:"required,oneof=on off"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SwitchResponseData 设备控制响应数据结构体
 | 
				
			||||||
 | 
					type SwitchResponseData struct {
 | 
				
			||||||
 | 
						DeviceType string `json:"device_type"`
 | 
				
			||||||
 | 
						DeviceID   string `json:"device_id"`
 | 
				
			||||||
 | 
						Action     string `json:"action"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Switch 设备控制接口
 | 
				
			||||||
 | 
					func (c *Controller) Switch(ctx *gin.Context) {
 | 
				
			||||||
 | 
						// 从上下文中获取用户信息
 | 
				
			||||||
 | 
						userValue, exists := ctx.Get("user")
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "无法获取用户信息")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user, ok := userValue.(*middleware.AuthUser)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户信息格式错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var req SwitchRequest
 | 
				
			||||||
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: 实际的设备控制逻辑
 | 
				
			||||||
 | 
						// 这里暂时用TODO代替具体逻辑
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建设备控制记录
 | 
				
			||||||
 | 
						if err := c.createDeviceControlRecord(
 | 
				
			||||||
 | 
							user.ID,
 | 
				
			||||||
 | 
							req.DeviceID,
 | 
				
			||||||
 | 
							req.DeviceType,
 | 
				
			||||||
 | 
							req.Action,
 | 
				
			||||||
 | 
							"success",
 | 
				
			||||||
 | 
							"设备控制成功",
 | 
				
			||||||
 | 
						); err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("创建设备控制记录失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "设备控制失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := SwitchResponseData{
 | 
				
			||||||
 | 
							DeviceType: req.DeviceType,
 | 
				
			||||||
 | 
							DeviceID:   req.DeviceID,
 | 
				
			||||||
 | 
							Action:     req.Action,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller.SendSuccessResponse(ctx, "设备控制成功", data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// createDeviceControlRecord 创建设备控制记录
 | 
				
			||||||
 | 
					func (c *Controller) createDeviceControlRecord(userID uint, deviceID, deviceType, action, status, result string) error {
 | 
				
			||||||
 | 
						// 获取设备信息
 | 
				
			||||||
 | 
						device, err := c.deviceRepo.FindByIDString(deviceID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 构建位置信息
 | 
				
			||||||
 | 
						var location string
 | 
				
			||||||
 | 
						switch device.Type {
 | 
				
			||||||
 | 
						case model.DeviceTypeRelay:
 | 
				
			||||||
 | 
							// 如果设备本身就是中继设备
 | 
				
			||||||
 | 
							location = device.Name
 | 
				
			||||||
 | 
						case model.DeviceTypePigPenController, model.DeviceTypeFeedMillController:
 | 
				
			||||||
 | 
							// 如果设备本身就是区域主控设备
 | 
				
			||||||
 | 
							if device.ParentID != nil {
 | 
				
			||||||
 | 
								// 获取中继设备
 | 
				
			||||||
 | 
								relayDevice, err := c.deviceRepo.FindByID(*device.ParentID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									location = device.Name
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									location = relayDevice.Name + " -> " + device.Name
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								location = device.Name
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							// 如果是普通设备(风机、水帘等)
 | 
				
			||||||
 | 
							if device.ParentID != nil {
 | 
				
			||||||
 | 
								// 获取区域主控设备
 | 
				
			||||||
 | 
								parentDevice, err := c.deviceRepo.FindByID(*device.ParentID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									location = "未知区域"
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// 检查区域主控设备是否有上级设备(中继设备)
 | 
				
			||||||
 | 
									if parentDevice.ParentID != nil {
 | 
				
			||||||
 | 
										// 获取中继设备
 | 
				
			||||||
 | 
										relayDevice, err := c.deviceRepo.FindByID(*parentDevice.ParentID)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											location = parentDevice.Name
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											location = relayDevice.Name + " -> " + parentDevice.Name
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										location = parentDevice.Name
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								location = "未知区域"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						control := &model.DeviceControl{
 | 
				
			||||||
 | 
							UserID:     userID,
 | 
				
			||||||
 | 
							Location:   location,
 | 
				
			||||||
 | 
							DeviceType: model.DeviceType(deviceType),
 | 
				
			||||||
 | 
							DeviceID:   deviceID,
 | 
				
			||||||
 | 
							Action:     action,
 | 
				
			||||||
 | 
							Status:     status,
 | 
				
			||||||
 | 
							Result:     result,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c.deviceControlRepo.Create(control)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										157
									
								
								internal/controller/operation/operation.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								internal/controller/operation/operation.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					// Package operation 提供操作历史相关功能的控制器
 | 
				
			||||||
 | 
					// 实现操作历史记录、查询等操作
 | 
				
			||||||
 | 
					package operation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/api/middleware"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Controller 操作历史控制器
 | 
				
			||||||
 | 
					type Controller struct {
 | 
				
			||||||
 | 
						operationHistoryRepo repository.OperationHistoryRepo
 | 
				
			||||||
 | 
						logger               *logs.Logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewController 创建操作历史控制器实例
 | 
				
			||||||
 | 
					func NewController(operationHistoryRepo repository.OperationHistoryRepo) *Controller {
 | 
				
			||||||
 | 
						return &Controller{
 | 
				
			||||||
 | 
							operationHistoryRepo: operationHistoryRepo,
 | 
				
			||||||
 | 
							logger:               logs.NewLogger(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CreateRequest 创建操作历史请求结构体
 | 
				
			||||||
 | 
					type CreateRequest struct {
 | 
				
			||||||
 | 
						Action     string `json:"action" binding:"required"`
 | 
				
			||||||
 | 
						Target     string `json:"target"`
 | 
				
			||||||
 | 
						Parameters string `json:"parameters"`
 | 
				
			||||||
 | 
						Status     string `json:"status" binding:"required"`
 | 
				
			||||||
 | 
						Result     string `json:"result"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create 创建操作历史记录
 | 
				
			||||||
 | 
					func (c *Controller) Create(ctx *gin.Context) {
 | 
				
			||||||
 | 
						// 从上下文中获取用户信息
 | 
				
			||||||
 | 
						userValue, exists := ctx.Get("user")
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "无法获取用户信息")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user, ok := userValue.(*middleware.AuthUser)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户信息格式错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var req CreateRequest
 | 
				
			||||||
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建操作历史记录
 | 
				
			||||||
 | 
						operation := &model.OperationHistory{
 | 
				
			||||||
 | 
							UserID:     user.ID,
 | 
				
			||||||
 | 
							Action:     req.Action,
 | 
				
			||||||
 | 
							Target:     req.Target,
 | 
				
			||||||
 | 
							Parameters: req.Parameters,
 | 
				
			||||||
 | 
							Status:     req.Status,
 | 
				
			||||||
 | 
							Result:     req.Result,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := c.operationHistoryRepo.Create(operation); err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("创建操作历史记录失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "创建操作历史记录失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller.SendSuccessResponse(ctx, "操作历史记录创建成功", nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListByUser 获取当前用户的所有操作历史记录
 | 
				
			||||||
 | 
					func (c *Controller) ListByUser(ctx *gin.Context) {
 | 
				
			||||||
 | 
						// 从上下文中获取用户信息
 | 
				
			||||||
 | 
						userValue, exists := ctx.Get("user")
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "无法获取用户信息")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user, ok := userValue.(*middleware.AuthUser)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户信息格式错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 获取分页参数
 | 
				
			||||||
 | 
						page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
 | 
				
			||||||
 | 
						limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 确保分页参数有效
 | 
				
			||||||
 | 
						if page < 1 {
 | 
				
			||||||
 | 
							page = 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if limit < 1 || limit > 100 {
 | 
				
			||||||
 | 
							limit = 10
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 计算偏移量
 | 
				
			||||||
 | 
						offset := (page - 1) * limit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 查询操作历史记录
 | 
				
			||||||
 | 
						operations, err := c.operationHistoryRepo.ListByUserID(user.ID, offset, limit)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("获取操作历史记录失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "获取操作历史记录失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller.SendSuccessResponse(ctx, "获取操作历史记录成功", operations)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get 获取单个操作历史记录
 | 
				
			||||||
 | 
					func (c *Controller) Get(ctx *gin.Context) {
 | 
				
			||||||
 | 
						// 获取操作历史记录ID
 | 
				
			||||||
 | 
						id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "无效的操作历史记录ID")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 查询操作历史记录
 | 
				
			||||||
 | 
						operation, err := c.operationHistoryRepo.FindByID(uint(id))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("获取操作历史记录失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "获取操作历史记录失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 从上下文中获取用户信息
 | 
				
			||||||
 | 
						userValue, exists := ctx.Get("user")
 | 
				
			||||||
 | 
						if !exists {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "无法获取用户信息")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user, ok := userValue.(*middleware.AuthUser)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户信息格式错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查操作历史记录是否属于当前用户
 | 
				
			||||||
 | 
						if operation.UserID != user.ID {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.ForbiddenCode, "无权访问该操作历史记录")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller.SendSuccessResponse(ctx, "获取操作历史记录成功", operation)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										60
									
								
								internal/controller/response.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								internal/controller/response.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					// Package controller 提供控制器层的公共功能
 | 
				
			||||||
 | 
					// 包含公共响应结构体和处理函数等
 | 
				
			||||||
 | 
					package controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// APIResponse 通用API响应结构体
 | 
				
			||||||
 | 
					type APIResponse struct {
 | 
				
			||||||
 | 
						Code    int         `json:"code"`
 | 
				
			||||||
 | 
						Message string      `json:"message"`
 | 
				
			||||||
 | 
						Data    interface{} `json:"data,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 自定义状态码常量
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SuccessCode             = 0    // 成功
 | 
				
			||||||
 | 
						InvalidParameterCode    = 1001 // 参数无效
 | 
				
			||||||
 | 
						UnauthorizedCode        = 1002 // 未授权
 | 
				
			||||||
 | 
						ForbiddenCode           = 1003 // 禁止访问
 | 
				
			||||||
 | 
						NotFoundCode            = 1004 // 资源未找到
 | 
				
			||||||
 | 
						InternalServerErrorCode = 1005 // 内部服务器错误
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SuccessResponseData 成功响应数据结构体
 | 
				
			||||||
 | 
					type SuccessResponseData struct {
 | 
				
			||||||
 | 
						Message string      `json:"message"`
 | 
				
			||||||
 | 
						Data    interface{} `json:"data,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SendSuccessResponse 发送成功响应的公共函数
 | 
				
			||||||
 | 
					func SendSuccessResponse(ctx *gin.Context, message string, data interface{}) {
 | 
				
			||||||
 | 
						response := APIResponse{
 | 
				
			||||||
 | 
							Code:    SuccessCode,
 | 
				
			||||||
 | 
							Message: message,
 | 
				
			||||||
 | 
							Data:    data,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(http.StatusOK, response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SendErrorResponse 发送错误响应的公共函数
 | 
				
			||||||
 | 
					func SendErrorResponse(ctx *gin.Context, code int, message string) {
 | 
				
			||||||
 | 
						response := APIResponse{
 | 
				
			||||||
 | 
							Code:    code,
 | 
				
			||||||
 | 
							Message: message,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(http.StatusOK, response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SendHTTPErrorResponse 发送HTTP错误响应的公共函数
 | 
				
			||||||
 | 
					func SendHTTPErrorResponse(ctx *gin.Context, httpCode int, code int, message string) {
 | 
				
			||||||
 | 
						response := APIResponse{
 | 
				
			||||||
 | 
							Code:    code,
 | 
				
			||||||
 | 
							Message: message,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(httpCode, response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,9 +3,8 @@
 | 
				
			|||||||
package user
 | 
					package user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/api/middleware"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/api/middleware"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/controller"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
@@ -26,101 +25,104 @@ func NewController(userRepo repository.UserRepo) *Controller {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterRequest 注册请求结构体
 | 
					// RegisterRequest 用户注册请求结构体
 | 
				
			||||||
type RegisterRequest struct {
 | 
					type RegisterRequest struct {
 | 
				
			||||||
	Username string `json:"username" binding:"required"`
 | 
						Username string `json:"username" binding:"required"`
 | 
				
			||||||
	Password string `json:"password" binding:"required"`
 | 
						Password string `json:"password" binding:"required"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterResponse 注册响应结构体
 | 
					// LoginRequest 用户登录请求结构体
 | 
				
			||||||
type RegisterResponse struct {
 | 
					 | 
				
			||||||
	ID        uint   `json:"id"`
 | 
					 | 
				
			||||||
	Username  string `json:"username"`
 | 
					 | 
				
			||||||
	CreatedAt string `json:"created_at"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Register 用户注册
 | 
					 | 
				
			||||||
func (c *Controller) Register(ctx *gin.Context) {
 | 
					 | 
				
			||||||
	var req RegisterRequest
 | 
					 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
					 | 
				
			||||||
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	user, err := c.userRepo.CreateUser(req.Username, req.Password)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		c.logger.Error("创建用户失败: " + err.Error())
 | 
					 | 
				
			||||||
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "创建用户失败"})
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	response := RegisterResponse{
 | 
					 | 
				
			||||||
		ID:        user.ID,
 | 
					 | 
				
			||||||
		Username:  user.Username,
 | 
					 | 
				
			||||||
		CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, gin.H{
 | 
					 | 
				
			||||||
		"message": "用户创建成功",
 | 
					 | 
				
			||||||
		"user":    response,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// LoginRequest 登录请求结构体
 | 
					 | 
				
			||||||
type LoginRequest struct {
 | 
					type LoginRequest struct {
 | 
				
			||||||
	Username string `json:"username" binding:"required"`
 | 
						Username string `json:"username" binding:"required"`
 | 
				
			||||||
	Password string `json:"password" binding:"required"`
 | 
						Password string `json:"password" binding:"required"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoginResponse 登录响应结构体
 | 
					// RegisterResponseData 用户注册响应数据
 | 
				
			||||||
type LoginResponse struct {
 | 
					type RegisterResponseData struct {
 | 
				
			||||||
 | 
						ID       uint   `json:"id"`
 | 
				
			||||||
 | 
						Username string `json:"username"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LoginResponseData 用户登录响应数据
 | 
				
			||||||
 | 
					type LoginResponseData struct {
 | 
				
			||||||
	ID       uint   `json:"id"`
 | 
						ID       uint   `json:"id"`
 | 
				
			||||||
	Username string `json:"username"`
 | 
						Username string `json:"username"`
 | 
				
			||||||
	Token    string `json:"token"`
 | 
						Token    string `json:"token"`
 | 
				
			||||||
	CreatedAt string `json:"created_at"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Login 用户登录
 | 
					// Register 用户注册接口
 | 
				
			||||||
 | 
					func (c *Controller) Register(ctx *gin.Context) {
 | 
				
			||||||
 | 
						var req RegisterRequest
 | 
				
			||||||
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查用户名是否已存在
 | 
				
			||||||
 | 
						_, err := c.userRepo.FindByUsername(req.Username)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "用户名已存在")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 对密码进行哈希处理
 | 
				
			||||||
 | 
						hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("密码哈希处理失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户注册失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建用户
 | 
				
			||||||
 | 
						user, err := c.userRepo.CreateUser(req.Username, string(hashedPassword))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.logger.Error("创建用户失败: " + err.Error())
 | 
				
			||||||
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户注册失败")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := RegisterResponseData{
 | 
				
			||||||
 | 
							ID:       user.ID,
 | 
				
			||||||
 | 
							Username: user.Username,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller.SendSuccessResponse(ctx, "用户注册成功", data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Login 用户登录接口
 | 
				
			||||||
func (c *Controller) Login(ctx *gin.Context) {
 | 
					func (c *Controller) Login(ctx *gin.Context) {
 | 
				
			||||||
	var req LoginRequest
 | 
						var req LoginRequest
 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
 | 
							controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 查找用户
 | 
						// 查找用户
 | 
				
			||||||
	user, err := c.userRepo.FindByUsername(req.Username)
 | 
						user, err := c.userRepo.FindByUsername(req.Username)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		c.logger.Error("查找用户失败: " + err.Error())
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "用户名或密码错误")
 | 
				
			||||||
		ctx.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 验证密码
 | 
						// 验证密码
 | 
				
			||||||
	err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password))
 | 
						if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
 | 
				
			||||||
	if err != nil {
 | 
							controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "用户名或密码错误")
 | 
				
			||||||
		ctx.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 生成JWT访问令牌
 | 
						// 生成JWT token
 | 
				
			||||||
	authMiddleware := middleware.NewAuthMiddleware(c.userRepo)
 | 
						token, err := middleware.NewAuthMiddleware(c.userRepo).GenerateToken(user.ID, user.Username)
 | 
				
			||||||
	token, err := authMiddleware.GenerateToken(user.ID, user.Username)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		c.logger.Error("生成令牌失败: " + err.Error())
 | 
							c.logger.Error("生成JWT token失败: " + err.Error())
 | 
				
			||||||
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "登录失败"})
 | 
							controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "登录失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	response := LoginResponse{
 | 
						data := LoginResponseData{
 | 
				
			||||||
		ID:       user.ID,
 | 
							ID:       user.ID,
 | 
				
			||||||
		Username: user.Username,
 | 
							Username: user.Username,
 | 
				
			||||||
		Token:    token,
 | 
							Token:    token,
 | 
				
			||||||
		CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, gin.H{
 | 
						controller.SendSuccessResponse(ctx, "登录成功", data)
 | 
				
			||||||
		"message": "登录成功",
 | 
					 | 
				
			||||||
		"user":    response,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,15 @@ type Application struct {
 | 
				
			|||||||
	// UserRepo 用户仓库实例
 | 
						// UserRepo 用户仓库实例
 | 
				
			||||||
	UserRepo repository.UserRepo
 | 
						UserRepo repository.UserRepo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// OperationHistoryRepo 操作历史仓库实例
 | 
				
			||||||
 | 
						OperationHistoryRepo repository.OperationHistoryRepo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceControlRepo 设备控制仓库实例
 | 
				
			||||||
 | 
						DeviceControlRepo repository.DeviceControlRepo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceRepo 设备仓库实例
 | 
				
			||||||
 | 
						DeviceRepo repository.DeviceRepo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Config 应用配置
 | 
						// Config 应用配置
 | 
				
			||||||
	Config *config.Config
 | 
						Config *config.Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,8 +62,17 @@ func NewApplication(cfg *config.Config) *Application {
 | 
				
			|||||||
	// 初始化用户仓库
 | 
						// 初始化用户仓库
 | 
				
			||||||
	userRepo := repository.NewUserRepo(store.GetDB())
 | 
						userRepo := repository.NewUserRepo(store.GetDB())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 初始化操作历史仓库
 | 
				
			||||||
 | 
						operationHistoryRepo := repository.NewOperationHistoryRepo(store.GetDB())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 初始化设备控制仓库
 | 
				
			||||||
 | 
						deviceControlRepo := repository.NewDeviceControlRepo(store.GetDB())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 初始化设备仓库
 | 
				
			||||||
 | 
						deviceRepo := repository.NewDeviceRepo(store.GetDB())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 初始化API组件
 | 
						// 初始化API组件
 | 
				
			||||||
	apiInstance := api.NewAPI(cfg, userRepo)
 | 
						apiInstance := api.NewAPI(cfg, userRepo, operationHistoryRepo, deviceControlRepo, deviceRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 初始化任务执行器组件(使用5个工作协程)
 | 
						// 初始化任务执行器组件(使用5个工作协程)
 | 
				
			||||||
	taskExecutor := task.NewExecutor(5)
 | 
						taskExecutor := task.NewExecutor(5)
 | 
				
			||||||
@@ -64,6 +82,9 @@ func NewApplication(cfg *config.Config) *Application {
 | 
				
			|||||||
		API:                  apiInstance,
 | 
							API:                  apiInstance,
 | 
				
			||||||
		TaskExecutor:         taskExecutor,
 | 
							TaskExecutor:         taskExecutor,
 | 
				
			||||||
		UserRepo:             userRepo,
 | 
							UserRepo:             userRepo,
 | 
				
			||||||
 | 
							OperationHistoryRepo: operationHistoryRepo,
 | 
				
			||||||
 | 
							DeviceControlRepo:    deviceControlRepo,
 | 
				
			||||||
 | 
							DeviceRepo:           deviceRepo,
 | 
				
			||||||
		Config:               cfg,
 | 
							Config:               cfg,
 | 
				
			||||||
		logger:               logs.NewLogger(),
 | 
							logger:               logs.NewLogger(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										102
									
								
								internal/model/device.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								internal/model/device.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					// Package model 提供数据模型定义
 | 
				
			||||||
 | 
					// 包含设备控制等相关数据结构
 | 
				
			||||||
 | 
					package model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeviceType 设备类型枚举
 | 
				
			||||||
 | 
					type DeviceType string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// DeviceTypeFan 风机
 | 
				
			||||||
 | 
						DeviceTypeFan DeviceType = "fan"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceTypeWaterCurtain 水帘
 | 
				
			||||||
 | 
						DeviceTypeWaterCurtain DeviceType = "water_curtain"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceTypePigPenController 猪舍主控
 | 
				
			||||||
 | 
						DeviceTypePigPenController DeviceType = "pig_pen_controller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceTypeFeedMillController 做料车间主控
 | 
				
			||||||
 | 
						DeviceTypeFeedMillController DeviceType = "feed_mill_controller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceTypeRelay 中继设备
 | 
				
			||||||
 | 
						DeviceTypeRelay DeviceType = "relay"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Device 代表设备信息
 | 
				
			||||||
 | 
					type Device struct {
 | 
				
			||||||
 | 
						// ID 设备ID
 | 
				
			||||||
 | 
						ID uint `gorm:"primaryKey;column:id" json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Name 设备名称
 | 
				
			||||||
 | 
						Name string `gorm:"not null;column:name" json:"name"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Type 设备类型
 | 
				
			||||||
 | 
						Type DeviceType `gorm:"not null;column:type" json:"type"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ParentID 上级设备ID(用于设备层级关系,指向区域主控设备)
 | 
				
			||||||
 | 
						ParentID *uint `gorm:"column:parent_id;index" json:"parent_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Status 设备状态
 | 
				
			||||||
 | 
						Status string `gorm:"not null;column:status" json:"status"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CreatedAt 创建时间
 | 
				
			||||||
 | 
						CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UpdatedAt 更新时间
 | 
				
			||||||
 | 
						UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeletedAt 删除时间(用于软删除)
 | 
				
			||||||
 | 
						DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TableName 指定Device模型对应的数据库表名
 | 
				
			||||||
 | 
					func (Device) TableName() string {
 | 
				
			||||||
 | 
						return "devices"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeviceControl 代表设备控制记录
 | 
				
			||||||
 | 
					type DeviceControl struct {
 | 
				
			||||||
 | 
						// ID 记录ID
 | 
				
			||||||
 | 
						ID uint `gorm:"primaryKey;column:id" json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UserID 用户ID
 | 
				
			||||||
 | 
						UserID uint `gorm:"not null;column:user_id;index" json:"user_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Location 设备安装位置描述
 | 
				
			||||||
 | 
						Location string `gorm:"not null;column:location" json:"location"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceType 设备类型
 | 
				
			||||||
 | 
						DeviceType DeviceType `gorm:"not null;column:device_type" json:"device_type"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeviceID 设备编号
 | 
				
			||||||
 | 
						DeviceID string `gorm:"not null;column:device_id" json:"device_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Action 控制动作(开/关)
 | 
				
			||||||
 | 
						Action string `gorm:"not null;column:action" json:"action"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Status 控制状态(成功/失败)
 | 
				
			||||||
 | 
						Status string `gorm:"not null;column:status" json:"status"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Result 控制结果详情(可选)
 | 
				
			||||||
 | 
						Result string `gorm:"column:result" json:"result"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CreatedAt 创建时间
 | 
				
			||||||
 | 
						CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UpdatedAt 更新时间
 | 
				
			||||||
 | 
						UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeletedAt 删除时间(用于软删除)
 | 
				
			||||||
 | 
						DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TableName 指定DeviceControl模型对应的数据库表名
 | 
				
			||||||
 | 
					func (DeviceControl) TableName() string {
 | 
				
			||||||
 | 
						return "device_controls"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								internal/model/operation_history.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								internal/model/operation_history.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					// Package model 提供数据模型定义
 | 
				
			||||||
 | 
					// 包含用户、操作历史等相关数据结构
 | 
				
			||||||
 | 
					package model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OperationHistory 代表用户操作历史记录
 | 
				
			||||||
 | 
					type OperationHistory struct {
 | 
				
			||||||
 | 
						// ID 记录ID
 | 
				
			||||||
 | 
						ID uint `gorm:"primaryKey;column:id" json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UserID 用户ID
 | 
				
			||||||
 | 
						UserID uint `gorm:"not null;column:user_id;index" json:"user_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Action 操作类型/指令
 | 
				
			||||||
 | 
						Action string `gorm:"not null;column:action" json:"action"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Target 操作目标(可选)
 | 
				
			||||||
 | 
						Target string `gorm:"column:target" json:"target"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parameters 操作参数(可选)
 | 
				
			||||||
 | 
						Parameters string `gorm:"column:parameters" json:"parameters"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Status 操作状态(成功/失败)
 | 
				
			||||||
 | 
						Status string `gorm:"not null;column:status" json:"status"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Result 操作结果详情(可选)
 | 
				
			||||||
 | 
						Result string `gorm:"column:result" json:"result"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CreatedAt 创建时间
 | 
				
			||||||
 | 
						CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UpdatedAt 更新时间
 | 
				
			||||||
 | 
						UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeletedAt 删除时间(用于软删除)
 | 
				
			||||||
 | 
						DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TableName 指定OperationHistory模型对应的数据库表名
 | 
				
			||||||
 | 
					func (OperationHistory) TableName() string {
 | 
				
			||||||
 | 
						return "operation_histories"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -27,6 +27,9 @@ type User struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// DeletedAt 删除时间(用于软删除)
 | 
						// DeletedAt 删除时间(用于软删除)
 | 
				
			||||||
	DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
						DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// OperationHistories 用户的操作历史记录
 | 
				
			||||||
 | 
						OperationHistories []OperationHistory `gorm:"foreignKey:UserID" json:"-"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TableName 指定User模型对应的数据库表名
 | 
					// TableName 指定User模型对应的数据库表名
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,10 +8,19 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
				
			||||||
	"gorm.io/driver/postgres"
 | 
						"gorm.io/driver/postgres"
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// migrateModels 需要自动迁移的数据库模型列表
 | 
				
			||||||
 | 
					var migrateModels = []interface{}{
 | 
				
			||||||
 | 
						&model.User{},
 | 
				
			||||||
 | 
						&model.OperationHistory{},
 | 
				
			||||||
 | 
						&model.Device{},
 | 
				
			||||||
 | 
						&model.DeviceControl{},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PostgresStorage 代表基于PostgreSQL的存储实现
 | 
					// PostgresStorage 代表基于PostgreSQL的存储实现
 | 
				
			||||||
// 使用GORM作为ORM库
 | 
					// 使用GORM作为ORM库
 | 
				
			||||||
type PostgresStorage struct {
 | 
					type PostgresStorage struct {
 | 
				
			||||||
@@ -75,6 +84,14 @@ func (ps *PostgresStorage) Connect() error {
 | 
				
			|||||||
	sqlDB.SetMaxIdleConns(ps.maxIdleConns)
 | 
						sqlDB.SetMaxIdleConns(ps.maxIdleConns)
 | 
				
			||||||
	sqlDB.SetConnMaxLifetime(time.Duration(ps.connMaxLifetime) * time.Second)
 | 
						sqlDB.SetConnMaxLifetime(time.Duration(ps.connMaxLifetime) * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 自动迁移数据库表结构
 | 
				
			||||||
 | 
						ps.logger.Info("正在自动迁移数据库表结构")
 | 
				
			||||||
 | 
						if err = ps.db.AutoMigrate(migrateModels...); err != nil {
 | 
				
			||||||
 | 
							ps.logger.Error(fmt.Sprintf("数据库表结构迁移失败: %v", err))
 | 
				
			||||||
 | 
							return fmt.Errorf("数据库表结构迁移失败: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ps.logger.Info("数据库表结构迁移完成")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ps.logger.Info("PostgreSQL数据库连接成功")
 | 
						ps.logger.Info("PostgreSQL数据库连接成功")
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										172
									
								
								internal/storage/repository/device.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								internal/storage/repository/device.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					// Package repository 提供数据访问层实现
 | 
				
			||||||
 | 
					// 包含设备控制等数据实体的仓库接口和实现
 | 
				
			||||||
 | 
					package repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
				
			||||||
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeviceRepo 设备仓库接口
 | 
				
			||||||
 | 
					type DeviceRepo interface {
 | 
				
			||||||
 | 
						// Create 创建设备
 | 
				
			||||||
 | 
						Create(device *model.Device) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByID 根据ID查找设备
 | 
				
			||||||
 | 
						FindByID(id uint) (*model.Device, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByIDString 根据ID字符串查找设备
 | 
				
			||||||
 | 
						FindByIDString(id string) (*model.Device, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByParentID 根据上级设备ID查找设备
 | 
				
			||||||
 | 
						FindByParentID(parentID uint) ([]*model.Device, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByType 根据设备类型查找设备
 | 
				
			||||||
 | 
						FindByType(deviceType model.DeviceType) ([]*model.Device, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update 更新设备信息
 | 
				
			||||||
 | 
						Update(device *model.Device) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete 删除设备
 | 
				
			||||||
 | 
						Delete(id uint) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeviceControlRepo 设备控制仓库接口
 | 
				
			||||||
 | 
					type DeviceControlRepo interface {
 | 
				
			||||||
 | 
						// Create 创建设备控制记录
 | 
				
			||||||
 | 
						Create(control *model.DeviceControl) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByUserID 根据用户ID查找设备控制记录
 | 
				
			||||||
 | 
						FindByUserID(userID uint) ([]*model.DeviceControl, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByID 根据ID查找设备控制记录
 | 
				
			||||||
 | 
						FindByID(id uint) (*model.DeviceControl, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// List 获取设备控制记录列表(分页)
 | 
				
			||||||
 | 
						List(offset, limit int) ([]*model.DeviceControl, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// deviceRepo 设备仓库实现
 | 
				
			||||||
 | 
					type deviceRepo struct {
 | 
				
			||||||
 | 
						db *gorm.DB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// deviceControlRepo 设备控制仓库实现
 | 
				
			||||||
 | 
					type deviceControlRepo struct {
 | 
				
			||||||
 | 
						db *gorm.DB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewDeviceRepo 创建设备仓库实例
 | 
				
			||||||
 | 
					func NewDeviceRepo(db *gorm.DB) DeviceRepo {
 | 
				
			||||||
 | 
						return &deviceRepo{
 | 
				
			||||||
 | 
							db: db,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewDeviceControlRepo 创建设备控制仓库实例
 | 
				
			||||||
 | 
					func NewDeviceControlRepo(db *gorm.DB) DeviceControlRepo {
 | 
				
			||||||
 | 
						return &deviceControlRepo{
 | 
				
			||||||
 | 
							db: db,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create 创建设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) Create(device *model.Device) error {
 | 
				
			||||||
 | 
						result := r.db.Create(device)
 | 
				
			||||||
 | 
						return result.Error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByID 根据ID查找设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) FindByID(id uint) (*model.Device, error) {
 | 
				
			||||||
 | 
						var device model.Device
 | 
				
			||||||
 | 
						result := r.db.First(&device, id)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &device, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByIDString 根据ID字符串查找设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) FindByIDString(id string) (*model.Device, error) {
 | 
				
			||||||
 | 
						deviceID, err := strconv.ParseUint(id, 10, 64)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var device model.Device
 | 
				
			||||||
 | 
						result := r.db.First(&device, deviceID)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &device, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByParentID 根据上级设备ID查找设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) FindByParentID(parentID uint) ([]*model.Device, error) {
 | 
				
			||||||
 | 
						var devices []*model.Device
 | 
				
			||||||
 | 
						result := r.db.Where("parent_id = ?", parentID).Find(&devices)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return devices, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByType 根据设备类型查找设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) FindByType(deviceType model.DeviceType) ([]*model.Device, error) {
 | 
				
			||||||
 | 
						var devices []*model.Device
 | 
				
			||||||
 | 
						result := r.db.Where("type = ?", deviceType).Find(&devices)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return devices, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Update 更新设备信息
 | 
				
			||||||
 | 
					func (r *deviceRepo) Update(device *model.Device) error {
 | 
				
			||||||
 | 
						result := r.db.Save(device)
 | 
				
			||||||
 | 
						return result.Error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Delete 删除设备
 | 
				
			||||||
 | 
					func (r *deviceRepo) Delete(id uint) error {
 | 
				
			||||||
 | 
						result := r.db.Delete(&model.Device{}, id)
 | 
				
			||||||
 | 
						return result.Error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create 创建设备控制记录
 | 
				
			||||||
 | 
					func (r *deviceControlRepo) Create(control *model.DeviceControl) error {
 | 
				
			||||||
 | 
						result := r.db.Create(control)
 | 
				
			||||||
 | 
						return result.Error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByUserID 根据用户ID查找设备控制记录
 | 
				
			||||||
 | 
					func (r *deviceControlRepo) FindByUserID(userID uint) ([]*model.DeviceControl, error) {
 | 
				
			||||||
 | 
						var controls []*model.DeviceControl
 | 
				
			||||||
 | 
						result := r.db.Where("user_id = ?", userID).Order("created_at DESC").Find(&controls)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return controls, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByID 根据ID查找设备控制记录
 | 
				
			||||||
 | 
					func (r *deviceControlRepo) FindByID(id uint) (*model.DeviceControl, error) {
 | 
				
			||||||
 | 
						var control model.DeviceControl
 | 
				
			||||||
 | 
						result := r.db.First(&control, id)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &control, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// List 获取设备控制记录列表(分页)
 | 
				
			||||||
 | 
					func (r *deviceControlRepo) List(offset, limit int) ([]*model.DeviceControl, error) {
 | 
				
			||||||
 | 
						var controls []*model.DeviceControl
 | 
				
			||||||
 | 
						result := r.db.Offset(offset).Limit(limit).Order("created_at DESC").Find(&controls)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return controls, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										84
									
								
								internal/storage/repository/operation_history.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								internal/storage/repository/operation_history.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					// Package repository 提供数据访问层实现
 | 
				
			||||||
 | 
					// 包含各种数据实体的仓库接口和实现
 | 
				
			||||||
 | 
					package repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
				
			||||||
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OperationHistoryRepo 操作历史仓库接口
 | 
				
			||||||
 | 
					type OperationHistoryRepo interface {
 | 
				
			||||||
 | 
						// Create 创建操作历史记录
 | 
				
			||||||
 | 
						Create(history *model.OperationHistory) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByUserID 根据用户ID查找操作历史记录
 | 
				
			||||||
 | 
						FindByUserID(userID uint) ([]*model.OperationHistory, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FindByID 根据ID查找操作历史记录
 | 
				
			||||||
 | 
						FindByID(id uint) (*model.OperationHistory, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// List 获取操作历史记录列表(分页)
 | 
				
			||||||
 | 
						List(offset, limit int) ([]*model.OperationHistory, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ListByUserID 根据用户ID获取操作历史记录列表(分页)
 | 
				
			||||||
 | 
						ListByUserID(userID uint, offset, limit int) ([]*model.OperationHistory, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// operationHistoryRepo 操作历史仓库实现
 | 
				
			||||||
 | 
					type operationHistoryRepo struct {
 | 
				
			||||||
 | 
						db *gorm.DB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewOperationHistoryRepo 创建操作历史仓库实例
 | 
				
			||||||
 | 
					func NewOperationHistoryRepo(db *gorm.DB) OperationHistoryRepo {
 | 
				
			||||||
 | 
						return &operationHistoryRepo{
 | 
				
			||||||
 | 
							db: db,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create 创建操作历史记录
 | 
				
			||||||
 | 
					func (r *operationHistoryRepo) Create(history *model.OperationHistory) error {
 | 
				
			||||||
 | 
						result := r.db.Create(history)
 | 
				
			||||||
 | 
						return result.Error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByUserID 根据用户ID查找操作历史记录
 | 
				
			||||||
 | 
					func (r *operationHistoryRepo) FindByUserID(userID uint) ([]*model.OperationHistory, error) {
 | 
				
			||||||
 | 
						var histories []*model.OperationHistory
 | 
				
			||||||
 | 
						result := r.db.Where("user_id = ?", userID).Order("created_at DESC").Find(&histories)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return histories, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindByID 根据ID查找操作历史记录
 | 
				
			||||||
 | 
					func (r *operationHistoryRepo) FindByID(id uint) (*model.OperationHistory, error) {
 | 
				
			||||||
 | 
						var history model.OperationHistory
 | 
				
			||||||
 | 
						result := r.db.First(&history, id)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &history, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// List 获取操作历史记录列表(分页)
 | 
				
			||||||
 | 
					func (r *operationHistoryRepo) List(offset, limit int) ([]*model.OperationHistory, error) {
 | 
				
			||||||
 | 
						var histories []*model.OperationHistory
 | 
				
			||||||
 | 
						result := r.db.Offset(offset).Limit(limit).Order("created_at DESC").Find(&histories)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return histories, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListByUserID 根据用户ID获取操作历史记录列表(分页)
 | 
				
			||||||
 | 
					func (r *operationHistoryRepo) ListByUserID(userID uint, offset, limit int) ([]*model.OperationHistory, error) {
 | 
				
			||||||
 | 
						var histories []*model.OperationHistory
 | 
				
			||||||
 | 
						result := r.db.Where("user_id = ?", userID).Offset(offset).Limit(limit).Order("created_at DESC").Find(&histories)
 | 
				
			||||||
 | 
						if result.Error != nil {
 | 
				
			||||||
 | 
							return nil, result.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return histories, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user