Compare commits
7 Commits
52cf8c58ed
...
64c86de71e
| Author | SHA1 | Date | |
|---|---|---|---|
| 64c86de71e | |||
| 3ecbf3b5af | |||
| 1a14aec19b | |||
| 008677467b | |||
| 2b4dd3e74d | |||
| 8468a96398 | |||
| e27aec0ca2 |
@@ -13,6 +13,7 @@ import (
|
|||||||
"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/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/device"
|
||||||
|
"git.huangwc.com/pig/pig-farm-controller/internal/controller/feed"
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/controller/operation"
|
"git.huangwc.com/pig/pig-farm-controller/internal/controller/operation"
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/controller/remote"
|
"git.huangwc.com/pig/pig-farm-controller/internal/controller/remote"
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/controller/user"
|
"git.huangwc.com/pig/pig-farm-controller/internal/controller/user"
|
||||||
@@ -44,6 +45,9 @@ type API struct {
|
|||||||
// deviceController 设备控制控制器
|
// deviceController 设备控制控制器
|
||||||
deviceController *device.Controller
|
deviceController *device.Controller
|
||||||
|
|
||||||
|
// feedController 饲喂管理控制器
|
||||||
|
feedController *feed.Controller
|
||||||
|
|
||||||
// remoteController 远程控制控制器
|
// remoteController 远程控制控制器
|
||||||
remoteController *remote.Controller
|
remoteController *remote.Controller
|
||||||
|
|
||||||
@@ -98,6 +102,9 @@ func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRe
|
|||||||
// 创建设备控制控制器
|
// 创建设备控制控制器
|
||||||
deviceController := device.NewController(deviceControlRepo, deviceRepo, websocketManager, heartbeatService, deviceStatusPool)
|
deviceController := device.NewController(deviceControlRepo, deviceRepo, websocketManager, heartbeatService, deviceStatusPool)
|
||||||
|
|
||||||
|
// 创建饲喂管理控制器
|
||||||
|
feedController := feed.NewController()
|
||||||
|
|
||||||
// 创建远程控制控制器
|
// 创建远程控制控制器
|
||||||
remoteController := remote.NewController(websocketManager)
|
remoteController := remote.NewController(websocketManager)
|
||||||
|
|
||||||
@@ -110,6 +117,7 @@ func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRe
|
|||||||
userController: userController,
|
userController: userController,
|
||||||
operationController: operationController,
|
operationController: operationController,
|
||||||
deviceController: deviceController,
|
deviceController: deviceController,
|
||||||
|
feedController: feedController,
|
||||||
remoteController: remoteController,
|
remoteController: remoteController,
|
||||||
authMiddleware: authMiddleware,
|
authMiddleware: authMiddleware,
|
||||||
websocketManager: websocketManager,
|
websocketManager: websocketManager,
|
||||||
@@ -222,6 +230,13 @@ func (a *API) setupRoutes() {
|
|||||||
deviceGroup.GET("/status", a.deviceController.GetDeviceStatus)
|
deviceGroup.GET("/status", a.deviceController.GetDeviceStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 饲喂相关路由
|
||||||
|
feedGroup := protectedGroup.Group("/feed")
|
||||||
|
{
|
||||||
|
feedGroup.GET("/plan/list", a.feedController.ListPlans)
|
||||||
|
feedGroup.GET("/plan/detail", a.feedController.Detail)
|
||||||
|
}
|
||||||
|
|
||||||
// 远程控制相关路由
|
// 远程控制相关路由
|
||||||
remoteGroup := protectedGroup.Group("/remote")
|
remoteGroup := protectedGroup.Group("/remote")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,14 +3,169 @@
|
|||||||
// 通过任务执行器执行具体控制任务
|
// 通过任务执行器执行具体控制任务
|
||||||
package feed
|
package feed
|
||||||
|
|
||||||
// FeedController 饲料控制器
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Controller 饲料控制器
|
||||||
// 管理饲料制备和分配设备的控制逻辑
|
// 管理饲料制备和分配设备的控制逻辑
|
||||||
type FeedController struct {
|
type Controller struct {
|
||||||
// TODO: 定义饲料控制器结构
|
feedPlanRepo repository.FeedPlanRepo
|
||||||
|
logger *logs.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFeedController 创建并返回一个新的饲料控制器实例
|
// NewController 创建并返回一个新的饲料控制器实例
|
||||||
func NewFeedController() *FeedController {
|
func NewController(feedPlanRepo repository.FeedPlanRepo) *Controller {
|
||||||
// TODO: 实现饲料控制器初始化
|
// TODO: 实现饲料控制器初始化
|
||||||
return nil
|
return &Controller{
|
||||||
|
feedPlanRepo: feedPlanRepo,
|
||||||
|
logger: logs.NewLogger(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListPlansResponse struct {
|
||||||
|
Plans []ListPlanResponseItem `json:"plans"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListPlanResponseItem struct {
|
||||||
|
// ID 计划ID
|
||||||
|
ID uint `json:"id"`
|
||||||
|
|
||||||
|
// Name 计划名称
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Description 计划描述
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Type 计划类型
|
||||||
|
Type model.FeedingPlanType `json:"type"`
|
||||||
|
|
||||||
|
// Enabled 是否启用
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ScheduleCron 定时任务表达式
|
||||||
|
ScheduleCron *string `json:"schedule_cron,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPlans 获取饲料计划列表
|
||||||
|
func (c *Controller) ListPlans(ctx *gin.Context) {
|
||||||
|
|
||||||
|
introductions, err := c.feedPlanRepo.ListAllPlanIntroduction()
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Error("获取设备列表失败: " + err.Error())
|
||||||
|
controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "获取计划列表失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := ListPlansResponse{
|
||||||
|
Plans: []ListPlanResponseItem{},
|
||||||
|
}
|
||||||
|
for _, introduction := range introductions {
|
||||||
|
resp.Plans = append(resp.Plans, ListPlanResponseItem{
|
||||||
|
ID: introduction.ID,
|
||||||
|
Name: introduction.Name,
|
||||||
|
Description: introduction.Description,
|
||||||
|
Enabled: introduction.Enabled,
|
||||||
|
Type: introduction.Type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.SendSuccessResponse(ctx, "success", resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetailResponse 喂料计划主表
|
||||||
|
type DetailResponse struct {
|
||||||
|
// ID 计划ID
|
||||||
|
ID uint `json:"id"`
|
||||||
|
|
||||||
|
// Name 计划名称
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Description 计划描述
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Type 计划类型(手动触发/自动触发)
|
||||||
|
Type model.FeedingPlanType `json:"type"`
|
||||||
|
|
||||||
|
// Enabled 是否启用
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ScheduleCron 定时任务表达式(仅当Type为auto时有效)
|
||||||
|
ScheduleCron *string `json:"scheduleCron"`
|
||||||
|
|
||||||
|
// ExecutionLimit 执行次数限制(0表示无限制,仅当Type为auto时有效)
|
||||||
|
ExecutionLimit int `json:"executionLimit"`
|
||||||
|
|
||||||
|
// ParentID 父计划ID(用于支持子计划结构)
|
||||||
|
ParentID *uint `json:"parentID"`
|
||||||
|
|
||||||
|
// OrderInParent 在父计划中的执行顺序
|
||||||
|
OrderInParent *int `json:"orderInParent"`
|
||||||
|
|
||||||
|
// IsMaster 是否为主计划(主计划可以包含子计划)
|
||||||
|
IsMaster bool `json:"isMaster"`
|
||||||
|
|
||||||
|
// CreatedAt 创建时间
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
|
||||||
|
// UpdatedAt 更新时间
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
|
||||||
|
// DeletedAt 删除时间(用于软删除)
|
||||||
|
DeletedAt gorm.DeletedAt `json:"deletedAt"`
|
||||||
|
|
||||||
|
// Steps 计划步骤列表
|
||||||
|
Steps []FeedingPlanStep `json:"steps"`
|
||||||
|
|
||||||
|
// SubPlans 子计划列表
|
||||||
|
SubPlans []DetailResponse `json:"subPlans"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeedingPlanStep 喂料计划步骤表,表示计划中的每个设备动作
|
||||||
|
type FeedingPlanStep struct {
|
||||||
|
// ID 步骤ID
|
||||||
|
ID uint `json:"id"`
|
||||||
|
|
||||||
|
// PlanID 关联的计划ID
|
||||||
|
PlanID uint `json:"planID"`
|
||||||
|
|
||||||
|
// StepOrder 步骤顺序
|
||||||
|
StepOrder int `json:"stepOrder"`
|
||||||
|
|
||||||
|
// DeviceID 关联的设备ID
|
||||||
|
DeviceID uint `json:"deviceID"`
|
||||||
|
|
||||||
|
// TargetValue 目标值(达到该值后停止工作切换到下一个设备)
|
||||||
|
TargetValue float64 `json:"targetValue"`
|
||||||
|
|
||||||
|
// Action 动作(如:打开设备)
|
||||||
|
Action string `json:"action"`
|
||||||
|
|
||||||
|
// ScheduleCron 步骤定时任务表达式(可选)
|
||||||
|
ScheduleCron *string `json:"scheduleCron"`
|
||||||
|
|
||||||
|
// ExecutionLimit 步骤执行次数限制(0表示无限制)
|
||||||
|
ExecutionLimit int `json:"executionLimit"`
|
||||||
|
|
||||||
|
// CreatedAt 创建时间
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
|
||||||
|
// UpdatedAt 更新时间
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
|
||||||
|
// DeletedAt 删除时间(用于软删除)
|
||||||
|
DeletedAt gorm.DeletedAt `json:"deletedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detail 获取饲料计划列细节
|
||||||
|
func (c *Controller) Detail(ctx *gin.Context) {
|
||||||
|
// TODO: 实现获取饲料计划列表的逻辑
|
||||||
|
|
||||||
|
controller.SendSuccessResponse(ctx, "success", &DetailResponse{})
|
||||||
}
|
}
|
||||||
|
|||||||
196
internal/model/feed.go
Normal file
196
internal/model/feed.go
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FeedingPlanType 喂料计划类型枚举
|
||||||
|
type FeedingPlanType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FeedingPlanTypeManual 手动触发
|
||||||
|
FeedingPlanTypeManual FeedingPlanType = "manual"
|
||||||
|
// FeedingPlanTypeAuto 自动触发
|
||||||
|
FeedingPlanTypeAuto FeedingPlanType = "auto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FeedingPlan 喂料计划主表
|
||||||
|
type FeedingPlan struct {
|
||||||
|
// ID 计划ID
|
||||||
|
ID uint `gorm:"primaryKey;column:id" json:"id"`
|
||||||
|
|
||||||
|
// Name 计划名称
|
||||||
|
Name string `gorm:"not null;column:name" json:"name"`
|
||||||
|
|
||||||
|
// Description 计划描述
|
||||||
|
Description string `gorm:"column:description" json:"description"`
|
||||||
|
|
||||||
|
// Type 计划类型(手动触发/自动触发)
|
||||||
|
Type FeedingPlanType `gorm:"not null;column:type" json:"type"`
|
||||||
|
|
||||||
|
// Enabled 是否启用
|
||||||
|
Enabled bool `gorm:"not null;default:true;column:enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// ScheduleCron 定时任务表达式(仅当Type为auto时有效)
|
||||||
|
ScheduleCron *string `gorm:"column:schedule_cron" json:"schedule_cron,omitempty"`
|
||||||
|
|
||||||
|
// ExecutionLimit 执行次数限制(0表示无限制,仅当Type为auto时有效)
|
||||||
|
ExecutionLimit int `gorm:"not null;default:0;column:execution_limit" json:"execution_limit"`
|
||||||
|
|
||||||
|
// ParentID 父计划ID(用于支持子计划结构)
|
||||||
|
ParentID *uint `gorm:"column:parent_id;index" json:"parent_id,omitempty"`
|
||||||
|
|
||||||
|
// OrderInParent 在父计划中的执行顺序
|
||||||
|
OrderInParent *int `gorm:"column:order_in_parent" json:"order_in_parent,omitempty"`
|
||||||
|
|
||||||
|
// IsMaster 是否为主计划(主计划可以包含子计划)
|
||||||
|
IsMaster bool `gorm:"not null;default:false;column:is_master" json:"is_master"`
|
||||||
|
|
||||||
|
// 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:"-"`
|
||||||
|
|
||||||
|
// Steps 计划步骤列表
|
||||||
|
Steps []FeedingPlanStep `gorm:"foreignKey:PlanID" json:"-"`
|
||||||
|
|
||||||
|
// SubPlans 子计划列表
|
||||||
|
SubPlans []FeedingPlan `gorm:"foreignKey:ParentID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 指定FeedingPlan模型对应的数据库表名
|
||||||
|
func (FeedingPlan) TableName() string {
|
||||||
|
return "feeding_plans"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeedingPlanStep 喂料计划步骤表,表示计划中的每个设备动作
|
||||||
|
type FeedingPlanStep struct {
|
||||||
|
// ID 步骤ID
|
||||||
|
ID uint `gorm:"primaryKey;column:id" json:"id"`
|
||||||
|
|
||||||
|
// PlanID 关联的计划ID
|
||||||
|
PlanID uint `gorm:"not null;column:plan_id;index" json:"plan_id"`
|
||||||
|
|
||||||
|
// StepOrder 步骤顺序
|
||||||
|
StepOrder int `gorm:"not null;column:step_order" json:"step_order"`
|
||||||
|
|
||||||
|
// DeviceID 关联的设备ID
|
||||||
|
DeviceID uint `gorm:"not null;column:device_id;index" json:"device_id"`
|
||||||
|
|
||||||
|
// TargetValue 目标值(达到该值后停止工作切换到下一个设备)
|
||||||
|
TargetValue float64 `gorm:"not null;column:target_value" json:"target_value"`
|
||||||
|
|
||||||
|
// Action 动作(如:打开设备)
|
||||||
|
Action string `gorm:"not null;column:action" json:"action"`
|
||||||
|
|
||||||
|
// ScheduleCron 步骤定时任务表达式(可选)
|
||||||
|
ScheduleCron *string `gorm:"column:schedule_cron" json:"schedule_cron,omitempty"`
|
||||||
|
|
||||||
|
// ExecutionLimit 步骤执行次数限制(0表示无限制)
|
||||||
|
ExecutionLimit int `gorm:"not null;default:0;column:execution_limit" json:"execution_limit"`
|
||||||
|
|
||||||
|
// 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 指定FeedingPlanStep模型对应的数据库表名
|
||||||
|
func (FeedingPlanStep) TableName() string {
|
||||||
|
return "feeding_plan_steps"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeedingExecution 喂料执行记录表
|
||||||
|
type FeedingExecution struct {
|
||||||
|
// ID 执行记录ID
|
||||||
|
ID uint `gorm:"primaryKey;column:id" json:"id"`
|
||||||
|
|
||||||
|
// PlanID 关联的计划ID
|
||||||
|
PlanID uint `gorm:"not null;column:plan_id;index" json:"plan_id"`
|
||||||
|
|
||||||
|
// MasterPlanID 主计划ID(如果是子计划执行,记录主计划ID)
|
||||||
|
MasterPlanID *uint `gorm:"column:master_plan_id;index" json:"master_plan_id,omitempty"`
|
||||||
|
|
||||||
|
// TriggerType 触发类型(手动/自动)
|
||||||
|
TriggerType FeedingPlanType `gorm:"not null;column:trigger_type" json:"trigger_type"`
|
||||||
|
|
||||||
|
// Status 执行状态(进行中/已完成/已取消/失败)
|
||||||
|
Status string `gorm:"not null;column:status" json:"status"`
|
||||||
|
|
||||||
|
// StartedAt 开始执行时间
|
||||||
|
StartedAt *time.Time `gorm:"column:started_at" json:"started_at,omitempty"`
|
||||||
|
|
||||||
|
// FinishedAt 完成时间
|
||||||
|
FinishedAt *time.Time `gorm:"column:finished_at" json:"finished_at,omitempty"`
|
||||||
|
|
||||||
|
// 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:"-"`
|
||||||
|
|
||||||
|
// Steps 执行步骤详情
|
||||||
|
Steps []FeedingExecutionStep `gorm:"foreignKey:ExecutionID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 指定FeedingExecution模型对应的数据库表名
|
||||||
|
func (FeedingExecution) TableName() string {
|
||||||
|
return "feeding_executions"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeedingExecutionStep 喂料执行步骤详情表
|
||||||
|
type FeedingExecutionStep struct {
|
||||||
|
// ID 执行步骤ID
|
||||||
|
ID uint `gorm:"primaryKey;column:id" json:"id"`
|
||||||
|
|
||||||
|
// ExecutionID 关联的执行记录ID
|
||||||
|
ExecutionID uint `gorm:"not null;column:execution_id;index" json:"execution_id"`
|
||||||
|
|
||||||
|
// StepID 关联的计划步骤ID
|
||||||
|
StepID uint `gorm:"not null;column:step_id;index" json:"step_id"`
|
||||||
|
|
||||||
|
// DeviceID 关联的设备ID
|
||||||
|
DeviceID uint `gorm:"not null;column:device_id;index" json:"device_id"`
|
||||||
|
|
||||||
|
// TargetValue 目标值
|
||||||
|
TargetValue float64 `gorm:"not null;column:target_value" json:"target_value"`
|
||||||
|
|
||||||
|
// ActualValue 实际值
|
||||||
|
ActualValue *float64 `gorm:"column:actual_value" json:"actual_value,omitempty"`
|
||||||
|
|
||||||
|
// Status 步骤状态(待执行/执行中/已完成/失败)
|
||||||
|
Status string `gorm:"not null;column:status" json:"status"`
|
||||||
|
|
||||||
|
// StartedAt 开始执行时间
|
||||||
|
StartedAt *time.Time `gorm:"column:started_at" json:"started_at,omitempty"`
|
||||||
|
|
||||||
|
// FinishedAt 完成时间
|
||||||
|
FinishedAt *time.Time `gorm:"column:finished_at" json:"finished_at,omitempty"`
|
||||||
|
|
||||||
|
// 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 指定FeedingExecutionStep模型对应的数据库表名
|
||||||
|
func (FeedingExecutionStep) TableName() string {
|
||||||
|
return "feeding_execution_steps"
|
||||||
|
}
|
||||||
180
internal/storage/repository/feed.go
Normal file
180
internal/storage/repository/feed.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"git.huangwc.com/pig/pig-farm-controller/internal/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FeedPlanRepo 饲喂管理接口
|
||||||
|
type FeedPlanRepo interface {
|
||||||
|
|
||||||
|
// ListAllPlanIntroduction 获取所有计划简介
|
||||||
|
ListAllPlanIntroduction() ([]*model.FeedingPlan, error)
|
||||||
|
|
||||||
|
// FindFeedingPlanByID 根据ID获取计划详情
|
||||||
|
FindFeedingPlanByID(id uint) (*model.FeedingPlan, error)
|
||||||
|
|
||||||
|
// CreateFeedingPlan 创建饲料计划
|
||||||
|
CreateFeedingPlan(feedingPlan *model.FeedingPlan) error
|
||||||
|
|
||||||
|
// DeleteFeedingPlan 删除饲料计划及其所有子计划和步骤
|
||||||
|
DeleteFeedingPlan(id uint) error
|
||||||
|
|
||||||
|
// UpdateFeedingPlan 更新饲料计划,采用先删除再重新创建的方式
|
||||||
|
UpdateFeedingPlan(feedingPlan *model.FeedingPlan) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type feedPlanRepo struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFeedPlanRepo(db *gorm.DB) FeedPlanRepo {
|
||||||
|
return &feedPlanRepo{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllPlanIntroduction 获取所有计划简介
|
||||||
|
func (f *feedPlanRepo) ListAllPlanIntroduction() ([]*model.FeedingPlan, error) {
|
||||||
|
var plans []*model.FeedingPlan
|
||||||
|
err := f.db.Model(&model.FeedingPlan{}).
|
||||||
|
Select("id, name, description, type, enabled, schedule_cron").
|
||||||
|
Find(&plans).Error
|
||||||
|
return plans, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFeedingPlanByID 根据ID获取计划详情
|
||||||
|
func (f *feedPlanRepo) FindFeedingPlanByID(feedingPlanID uint) (*model.FeedingPlan, error) {
|
||||||
|
var plan model.FeedingPlan
|
||||||
|
err := f.db.Where("id = ?", feedingPlanID).
|
||||||
|
Preload("Steps").
|
||||||
|
Preload("SubPlans").
|
||||||
|
First(&plan).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &plan, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFeedingPlan 创建饲料计划,包括步骤和子计划
|
||||||
|
func (f *feedPlanRepo) CreateFeedingPlan(feedingPlan *model.FeedingPlan) error {
|
||||||
|
return f.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
return f.createFeedingPlanWithTx(tx, feedingPlan)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFeedingPlan 更新饲料计划,采用先删除再重新创建的方式
|
||||||
|
func (f *feedPlanRepo) UpdateFeedingPlan(feedingPlan *model.FeedingPlan) error {
|
||||||
|
// 检查计划是否存在
|
||||||
|
_, err := f.FindFeedingPlanByID(feedingPlan.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// 先删除原有的计划
|
||||||
|
if err := f.deleteFeedingPlanWithTx(tx, feedingPlan.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再重新创建更新后的计划
|
||||||
|
if err := f.createFeedingPlanWithTx(tx, feedingPlan); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFeedingPlan 删除饲料计划及其所有子计划和步骤
|
||||||
|
func (f *feedPlanRepo) DeleteFeedingPlan(id uint) error {
|
||||||
|
return f.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// 递归删除计划及其所有子计划
|
||||||
|
if err := f.deleteFeedingPlanWithTx(tx, id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteFeedingPlanWithTx 在事务中递归删除饲料计划
|
||||||
|
func (f *feedPlanRepo) deleteFeedingPlanWithTx(tx *gorm.DB, id uint) error {
|
||||||
|
// 先查找计划及其子计划
|
||||||
|
var plan model.FeedingPlan
|
||||||
|
if err := tx.Where("id = ?", id).Preload("SubPlans").First(&plan).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归删除所有子计划
|
||||||
|
for _, subPlan := range plan.SubPlans {
|
||||||
|
if err := f.deleteFeedingPlanWithTx(tx, subPlan.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除该计划的所有步骤
|
||||||
|
if err := tx.Where("plan_id = ?", id).Delete(&model.FeedingPlanStep{}).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除计划本身
|
||||||
|
if err := tx.Delete(&model.FeedingPlan{}, id).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createFeedingPlanWithTx 在事务中递归创建饲料计划
|
||||||
|
func (f *feedPlanRepo) createFeedingPlanWithTx(tx *gorm.DB, feedingPlan *model.FeedingPlan) error {
|
||||||
|
// 先创建计划主体
|
||||||
|
if err := tx.Create(feedingPlan).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理步骤 - 先按现有顺序排序,再重新分配从0开始的连续编号
|
||||||
|
sort.Slice(feedingPlan.Steps, func(i, j int) bool {
|
||||||
|
return feedingPlan.Steps[i].StepOrder < feedingPlan.Steps[j].StepOrder
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重新填充步骤编号
|
||||||
|
for i := range feedingPlan.Steps {
|
||||||
|
feedingPlan.Steps[i].StepOrder = i
|
||||||
|
feedingPlan.Steps[i].PlanID = feedingPlan.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有步骤,批量创建步骤
|
||||||
|
if len(feedingPlan.Steps) > 0 {
|
||||||
|
if err := tx.Create(&feedingPlan.Steps).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理子计划 - 重新填充子计划编号和父ID
|
||||||
|
sort.Slice(feedingPlan.SubPlans, func(i, j int) bool {
|
||||||
|
// 如果OrderInParent为nil,放在最后
|
||||||
|
if feedingPlan.SubPlans[i].OrderInParent == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if feedingPlan.SubPlans[j].OrderInParent == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *feedingPlan.SubPlans[i].OrderInParent < *feedingPlan.SubPlans[j].OrderInParent
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重新填充子计划编号和父ID
|
||||||
|
for i := range feedingPlan.SubPlans {
|
||||||
|
order := i
|
||||||
|
feedingPlan.SubPlans[i].OrderInParent = &order
|
||||||
|
feedingPlan.SubPlans[i].ParentID = &feedingPlan.ID
|
||||||
|
|
||||||
|
// 递归创建子计划
|
||||||
|
if err := f.createFeedingPlanWithTx(tx, &feedingPlan.SubPlans[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -23,6 +23,12 @@ type Task interface {
|
|||||||
|
|
||||||
// GetPriority 获取任务优先级
|
// GetPriority 获取任务优先级
|
||||||
GetPriority() int
|
GetPriority() int
|
||||||
|
|
||||||
|
// Done 返回一个channel,当任务执行完毕时该channel会被关闭
|
||||||
|
Done() <-chan struct{}
|
||||||
|
|
||||||
|
// IsDone 检查任务是否已完成
|
||||||
|
IsDone() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// taskItem 任务队列中的元素
|
// taskItem 任务队列中的元素
|
||||||
|
|||||||
Reference in New Issue
Block a user