Compare commits
	
		
			6 Commits
		
	
	
		
			565cf3fa6a
			...
			9caedd697d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9caedd697d | |||
| 6f3f7db870 | |||
| c7e2aaee89 | |||
| bab44e7e3a | |||
| 0895cf42b2 | |||
| d4ce0aa238 | 
@@ -9,7 +9,10 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"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/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/logs"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/storage/repository"
 | 
			
		||||
@@ -31,13 +34,22 @@ type API struct {
 | 
			
		||||
	// userController 用户控制器
 | 
			
		||||
	userController *user.Controller
 | 
			
		||||
 | 
			
		||||
	// operationController 操作历史控制器
 | 
			
		||||
	operationController *operation.Controller
 | 
			
		||||
 | 
			
		||||
	// deviceController 设备控制控制器
 | 
			
		||||
	deviceController *device.Controller
 | 
			
		||||
 | 
			
		||||
	// authMiddleware 鉴权中间件
 | 
			
		||||
	authMiddleware *middleware.AuthMiddleware
 | 
			
		||||
 | 
			
		||||
	// logger 日志记录器
 | 
			
		||||
	logger *logs.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAPI 创建并返回一个新的API实例
 | 
			
		||||
// 初始化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.SetMode(gin.ReleaseMode)
 | 
			
		||||
 | 
			
		||||
@@ -64,10 +76,22 @@ func NewAPI(cfg *config.Config, userRepo repository.UserRepo) *API {
 | 
			
		||||
	// 创建用户控制器
 | 
			
		||||
	userController := user.NewController(userRepo)
 | 
			
		||||
 | 
			
		||||
	// 创建操作历史控制器
 | 
			
		||||
	operationController := operation.NewController(operationHistoryRepo)
 | 
			
		||||
 | 
			
		||||
	// 创建设备控制控制器
 | 
			
		||||
	deviceController := device.NewController(deviceControlRepo, deviceRepo)
 | 
			
		||||
 | 
			
		||||
	// 创建鉴权中间件
 | 
			
		||||
	authMiddleware := middleware.NewAuthMiddleware(userRepo)
 | 
			
		||||
 | 
			
		||||
	return &API{
 | 
			
		||||
		engine:              engine,
 | 
			
		||||
		config:              cfg,
 | 
			
		||||
		userController:      userController,
 | 
			
		||||
		operationController: operationController,
 | 
			
		||||
		deviceController:    deviceController,
 | 
			
		||||
		authMiddleware:      authMiddleware,
 | 
			
		||||
		logger:              logs.NewLogger(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -129,6 +153,25 @@ func (a *API) setupRoutes() {
 | 
			
		||||
		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: 添加更多路由
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"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/storage/repository"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
@@ -26,101 +25,104 @@ func NewController(userRepo repository.UserRepo) *Controller {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterRequest 注册请求结构体
 | 
			
		||||
// RegisterRequest 用户注册请求结构体
 | 
			
		||||
type RegisterRequest struct {
 | 
			
		||||
	Username string `json:"username" binding:"required"`
 | 
			
		||||
	Password string `json:"password" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterResponse 注册响应结构体
 | 
			
		||||
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 登录请求结构体
 | 
			
		||||
// LoginRequest 用户登录请求结构体
 | 
			
		||||
type LoginRequest struct {
 | 
			
		||||
	Username string `json:"username" binding:"required"`
 | 
			
		||||
	Password string `json:"password" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoginResponse 登录响应结构体
 | 
			
		||||
type LoginResponse struct {
 | 
			
		||||
// RegisterResponseData 用户注册响应数据
 | 
			
		||||
type RegisterResponseData struct {
 | 
			
		||||
	ID       uint   `json:"id"`
 | 
			
		||||
	Username string `json:"username"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoginResponseData 用户登录响应数据
 | 
			
		||||
type LoginResponseData struct {
 | 
			
		||||
	ID       uint   `json:"id"`
 | 
			
		||||
	Username string `json:"username"`
 | 
			
		||||
	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) {
 | 
			
		||||
	var req LoginRequest
 | 
			
		||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
			
		||||
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 查找用户
 | 
			
		||||
	user, err := c.userRepo.FindByUsername(req.Username)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.logger.Error("查找用户失败: " + err.Error())
 | 
			
		||||
		ctx.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "用户名或密码错误")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 验证密码
 | 
			
		||||
	err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
 | 
			
		||||
	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "用户名或密码错误")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 生成JWT访问令牌
 | 
			
		||||
	authMiddleware := middleware.NewAuthMiddleware(c.userRepo)
 | 
			
		||||
	token, err := authMiddleware.GenerateToken(user.ID, user.Username)
 | 
			
		||||
	// 生成JWT token
 | 
			
		||||
	token, err := middleware.NewAuthMiddleware(c.userRepo).GenerateToken(user.ID, user.Username)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.logger.Error("生成令牌失败: " + err.Error())
 | 
			
		||||
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "登录失败"})
 | 
			
		||||
		c.logger.Error("生成JWT token失败: " + err.Error())
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "登录失败")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := LoginResponse{
 | 
			
		||||
	data := LoginResponseData{
 | 
			
		||||
		ID:       user.ID,
 | 
			
		||||
		Username: user.Username,
 | 
			
		||||
		Token:    token,
 | 
			
		||||
		CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, gin.H{
 | 
			
		||||
		"message": "登录成功",
 | 
			
		||||
		"user":    response,
 | 
			
		||||
	})
 | 
			
		||||
	controller.SendSuccessResponse(ctx, "登录成功", data)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,15 @@ type Application struct {
 | 
			
		||||
	// UserRepo 用户仓库实例
 | 
			
		||||
	UserRepo repository.UserRepo
 | 
			
		||||
 | 
			
		||||
	// OperationHistoryRepo 操作历史仓库实例
 | 
			
		||||
	OperationHistoryRepo repository.OperationHistoryRepo
 | 
			
		||||
 | 
			
		||||
	// DeviceControlRepo 设备控制仓库实例
 | 
			
		||||
	DeviceControlRepo repository.DeviceControlRepo
 | 
			
		||||
 | 
			
		||||
	// DeviceRepo 设备仓库实例
 | 
			
		||||
	DeviceRepo repository.DeviceRepo
 | 
			
		||||
 | 
			
		||||
	// Config 应用配置
 | 
			
		||||
	Config *config.Config
 | 
			
		||||
 | 
			
		||||
@@ -53,8 +62,17 @@ func NewApplication(cfg *config.Config) *Application {
 | 
			
		||||
	// 初始化用户仓库
 | 
			
		||||
	userRepo := repository.NewUserRepo(store.GetDB())
 | 
			
		||||
 | 
			
		||||
	// 初始化操作历史仓库
 | 
			
		||||
	operationHistoryRepo := repository.NewOperationHistoryRepo(store.GetDB())
 | 
			
		||||
 | 
			
		||||
	// 初始化设备控制仓库
 | 
			
		||||
	deviceControlRepo := repository.NewDeviceControlRepo(store.GetDB())
 | 
			
		||||
 | 
			
		||||
	// 初始化设备仓库
 | 
			
		||||
	deviceRepo := repository.NewDeviceRepo(store.GetDB())
 | 
			
		||||
 | 
			
		||||
	// 初始化API组件
 | 
			
		||||
	apiInstance := api.NewAPI(cfg, userRepo)
 | 
			
		||||
	apiInstance := api.NewAPI(cfg, userRepo, operationHistoryRepo, deviceControlRepo, deviceRepo)
 | 
			
		||||
 | 
			
		||||
	// 初始化任务执行器组件(使用5个工作协程)
 | 
			
		||||
	taskExecutor := task.NewExecutor(5)
 | 
			
		||||
@@ -64,6 +82,9 @@ func NewApplication(cfg *config.Config) *Application {
 | 
			
		||||
		API:                  apiInstance,
 | 
			
		||||
		TaskExecutor:         taskExecutor,
 | 
			
		||||
		UserRepo:             userRepo,
 | 
			
		||||
		OperationHistoryRepo: operationHistoryRepo,
 | 
			
		||||
		DeviceControlRepo:    deviceControlRepo,
 | 
			
		||||
		DeviceRepo:           deviceRepo,
 | 
			
		||||
		Config:               cfg,
 | 
			
		||||
		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 gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"`
 | 
			
		||||
 | 
			
		||||
	// OperationHistories 用户的操作历史记录
 | 
			
		||||
	OperationHistories []OperationHistory `gorm:"foreignKey:UserID" json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TableName 指定User模型对应的数据库表名
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,19 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/logs"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/model"
 | 
			
		||||
	"gorm.io/driver/postgres"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// migrateModels 需要自动迁移的数据库模型列表
 | 
			
		||||
var migrateModels = []interface{}{
 | 
			
		||||
	&model.User{},
 | 
			
		||||
	&model.OperationHistory{},
 | 
			
		||||
	&model.Device{},
 | 
			
		||||
	&model.DeviceControl{},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PostgresStorage 代表基于PostgreSQL的存储实现
 | 
			
		||||
// 使用GORM作为ORM库
 | 
			
		||||
type PostgresStorage struct {
 | 
			
		||||
@@ -75,6 +84,14 @@ func (ps *PostgresStorage) Connect() error {
 | 
			
		||||
	sqlDB.SetMaxIdleConns(ps.maxIdleConns)
 | 
			
		||||
	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数据库连接成功")
 | 
			
		||||
	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