2025-09-07 17:50:04 +08:00
|
|
|
|
// Package feed 提供饲料控制功能
|
|
|
|
|
|
// 实现饲料制备和分配的控制逻辑
|
|
|
|
|
|
// 通过任务执行器执行具体控制任务
|
|
|
|
|
|
package feed
|
|
|
|
|
|
|
2025-09-10 13:41:24 +08:00
|
|
|
|
import (
|
2025-09-10 14:35:54 +08:00
|
|
|
|
"strconv"
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
"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 饲料控制器
|
2025-09-07 17:50:04 +08:00
|
|
|
|
// 管理饲料制备和分配设备的控制逻辑
|
2025-09-10 13:41:24 +08:00
|
|
|
|
type Controller struct {
|
|
|
|
|
|
feedPlanRepo repository.FeedPlanRepo
|
|
|
|
|
|
logger *logs.Logger
|
2025-09-07 17:50:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 13:41:24 +08:00
|
|
|
|
// NewController 创建并返回一个新的饲料控制器实例
|
|
|
|
|
|
func NewController(feedPlanRepo repository.FeedPlanRepo) *Controller {
|
2025-09-07 17:50:04 +08:00
|
|
|
|
// TODO: 实现饲料控制器初始化
|
2025-09-10 13:41:24 +08:00
|
|
|
|
return &Controller{
|
|
|
|
|
|
feedPlanRepo: feedPlanRepo,
|
|
|
|
|
|
logger: logs.NewLogger(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 15:13:31 +08:00
|
|
|
|
// CreateRequest 创建计划请求结构体
|
|
|
|
|
|
type CreateRequest struct {
|
|
|
|
|
|
// Name 计划名称
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
|
|
|
|
|
|
|
// Description 计划描述
|
|
|
|
|
|
Description string `json:"description"`
|
|
|
|
|
|
|
|
|
|
|
|
// Type 计划类型(手动触发/自动触发)
|
|
|
|
|
|
Type model.FeedingPlanType `json:"type"`
|
|
|
|
|
|
|
|
|
|
|
|
// Enabled 是否启用
|
|
|
|
|
|
Enabled bool `json:"enabled"`
|
|
|
|
|
|
|
|
|
|
|
|
// ScheduleCron 定时任务表达式(仅当Type为auto时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ScheduleCron *string `json:"schedule_cron,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// ExecutionLimit 执行次数限制(0表示无限制,仅当Type为auto时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ExecutionLimit int `json:"execution_limit"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// ParentID 父计划ID(用于支持子计划结构)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ParentID *uint `json:"parent_id,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// OrderInParent 在父计划中的执行顺序
|
2025-09-10 19:03:41 +08:00
|
|
|
|
OrderInParent *int `json:"order_in_parent,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// IsMaster 是否为主计划(主计划可以包含子计划)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
IsMaster bool `json:"is_master"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// Steps 计划步骤列表
|
|
|
|
|
|
Steps []FeedingPlanStep `json:"steps"`
|
|
|
|
|
|
|
|
|
|
|
|
// SubPlans 子计划列表
|
2025-09-10 19:03:41 +08:00
|
|
|
|
SubPlans []CreateRequest `json:"sub_plans"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create 创建饲料计划
|
|
|
|
|
|
func (c *Controller) Create(ctx *gin.Context) {
|
|
|
|
|
|
var req CreateRequest
|
|
|
|
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换请求结构体为模型
|
|
|
|
|
|
plan := c.convertToCreateModel(&req)
|
|
|
|
|
|
|
|
|
|
|
|
// 调用仓库创建计划
|
|
|
|
|
|
if err := c.feedPlanRepo.CreateFeedingPlan(plan); err != nil {
|
|
|
|
|
|
c.logger.Error("创建计划失败: " + err.Error())
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "创建计划失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
controller.SendSuccessResponse(ctx, "创建计划成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// convertToCreateModel 将创建请求结构体转换为数据库模型
|
|
|
|
|
|
func (c *Controller) convertToCreateModel(req *CreateRequest) *model.FeedingPlan {
|
|
|
|
|
|
plan := &model.FeedingPlan{
|
|
|
|
|
|
Name: req.Name,
|
|
|
|
|
|
Description: req.Description,
|
|
|
|
|
|
Type: req.Type,
|
|
|
|
|
|
Enabled: req.Enabled,
|
|
|
|
|
|
ScheduleCron: req.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: req.ExecutionLimit,
|
|
|
|
|
|
ParentID: req.ParentID,
|
|
|
|
|
|
OrderInParent: req.OrderInParent,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换步骤
|
|
|
|
|
|
plan.Steps = make([]model.FeedingPlanStep, len(req.Steps))
|
|
|
|
|
|
for i, step := range req.Steps {
|
|
|
|
|
|
plan.Steps[i] = model.FeedingPlanStep{
|
|
|
|
|
|
// ID在创建时不需要设置
|
|
|
|
|
|
// PlanID会在创建过程中自动设置
|
|
|
|
|
|
StepOrder: step.StepOrder,
|
|
|
|
|
|
DeviceID: step.DeviceID,
|
|
|
|
|
|
TargetValue: step.TargetValue,
|
|
|
|
|
|
Action: step.Action,
|
|
|
|
|
|
ScheduleCron: step.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: step.ExecutionLimit,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换子计划
|
|
|
|
|
|
plan.SubPlans = make([]model.FeedingPlan, len(req.SubPlans))
|
|
|
|
|
|
for i, subReq := range req.SubPlans {
|
|
|
|
|
|
plan.SubPlans[i] = *c.convertToCreateModel(&subReq)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return plan
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 14:46:47 +08:00
|
|
|
|
// Delete 删除饲料计划
|
|
|
|
|
|
func (c *Controller) Delete(ctx *gin.Context) {
|
|
|
|
|
|
// 获取路径参数中的计划ID
|
2025-09-10 16:25:52 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
ID uint `json:"id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error())
|
2025-09-10 14:46:47 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用仓库删除计划
|
2025-09-10 16:25:52 +08:00
|
|
|
|
if err := c.feedPlanRepo.DeleteFeedingPlan(uint(req.ID)); err != nil {
|
2025-09-10 14:46:47 +08:00
|
|
|
|
c.logger.Error("删除计划失败: " + err.Error())
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "删除计划失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
controller.SendSuccessResponse(ctx, "删除计划成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 13:41:24 +08:00
|
|
|
|
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{
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ID: introduction.ID,
|
|
|
|
|
|
Name: introduction.Name,
|
|
|
|
|
|
Description: introduction.Description,
|
|
|
|
|
|
Enabled: introduction.Enabled,
|
|
|
|
|
|
Type: introduction.Type,
|
|
|
|
|
|
ScheduleCron: introduction.ScheduleCron,
|
2025-09-10 13:41:24 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
controller.SendSuccessResponse(ctx, "success", resp)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 14:42:54 +08:00
|
|
|
|
// UpdateRequest 更新计划请求结构体
|
|
|
|
|
|
type UpdateRequest struct {
|
2025-09-10 15:13:31 +08:00
|
|
|
|
// 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时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ScheduleCron *string `json:"schedule_cron,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// ExecutionLimit 执行次数限制(0表示无限制,仅当Type为auto时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ExecutionLimit int `json:"execution_limit"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// ParentID 父计划ID(用于支持子计划结构)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ParentID *uint `json:"parent_id,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// OrderInParent 在父计划中的执行顺序
|
2025-09-10 19:03:41 +08:00
|
|
|
|
OrderInParent *int `json:"order_in_parent,omitempty"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// IsMaster 是否为主计划(主计划可以包含子计划)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
IsMaster bool `json:"is_master"`
|
2025-09-10 15:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
// Steps 计划步骤列表
|
|
|
|
|
|
Steps []FeedingPlanStep `json:"steps"`
|
|
|
|
|
|
|
|
|
|
|
|
// SubPlans 子计划列表
|
2025-09-10 19:03:41 +08:00
|
|
|
|
SubPlans []UpdateRequest `json:"sub_plans"`
|
2025-09-10 14:42:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 13:41:24 +08:00
|
|
|
|
// 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时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ScheduleCron *string `json:"schedule_cron,omitempty"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// ExecutionLimit 执行次数限制(0表示无限制,仅当Type为auto时有效)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ExecutionLimit int `json:"execution_limit"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// ParentID 父计划ID(用于支持子计划结构)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ParentID *uint `json:"parent_id,omitempty"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// OrderInParent 在父计划中的执行顺序
|
2025-09-10 19:03:41 +08:00
|
|
|
|
OrderInParent *int `json:"order_in_parent,omitempty"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// Steps 计划步骤列表
|
|
|
|
|
|
Steps []FeedingPlanStep `json:"steps"`
|
|
|
|
|
|
|
|
|
|
|
|
// SubPlans 子计划列表
|
2025-09-10 19:03:41 +08:00
|
|
|
|
SubPlans []DetailResponse `json:"sub_plans"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FeedingPlanStep 喂料计划步骤表,表示计划中的每个设备动作
|
|
|
|
|
|
type FeedingPlanStep struct {
|
|
|
|
|
|
// ID 步骤ID
|
|
|
|
|
|
ID uint `json:"id"`
|
|
|
|
|
|
|
|
|
|
|
|
// PlanID 关联的计划ID
|
2025-09-10 19:03:41 +08:00
|
|
|
|
PlanID uint `json:"plan_id"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// StepOrder 步骤顺序
|
2025-09-10 19:03:41 +08:00
|
|
|
|
StepOrder int `json:"step_order"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// DeviceID 关联的设备ID
|
2025-09-10 19:03:41 +08:00
|
|
|
|
DeviceID uint `json:"device_id"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// TargetValue 目标值(达到该值后停止工作切换到下一个设备)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
TargetValue float64 `json:"target_value"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// Action 动作(如:打开设备)
|
|
|
|
|
|
Action string `json:"action"`
|
|
|
|
|
|
|
|
|
|
|
|
// ScheduleCron 步骤定时任务表达式(可选)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ScheduleCron *string `json:"schedule_cron,omitempty"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
|
|
|
|
|
// ExecutionLimit 步骤执行次数限制(0表示无限制)
|
2025-09-10 19:03:41 +08:00
|
|
|
|
ExecutionLimit int `json:"execution_limit"`
|
2025-09-10 13:41:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Detail 获取饲料计划列细节
|
|
|
|
|
|
func (c *Controller) Detail(ctx *gin.Context) {
|
2025-09-10 18:16:07 +08:00
|
|
|
|
// 获取查询参数中的计划ID
|
|
|
|
|
|
planIDStr := ctx.Query("id")
|
|
|
|
|
|
if planIDStr == "" {
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "缺少计划ID参数")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 14:35:54 +08:00
|
|
|
|
planID, err := strconv.ParseUint(planIDStr, 10, 32)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "无效的计划ID")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从仓库中获取计划详情
|
|
|
|
|
|
plan, err := c.feedPlanRepo.FindFeedingPlanByID(uint(planID))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.logger.Error("获取计划详情失败: " + err.Error())
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "获取计划详情失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为响应结构体
|
|
|
|
|
|
resp := c.convertToDetailResponse(plan)
|
|
|
|
|
|
|
|
|
|
|
|
controller.SendSuccessResponse(ctx, "success", resp)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 14:42:54 +08:00
|
|
|
|
// Update 更新饲料计划
|
|
|
|
|
|
func (c *Controller) Update(ctx *gin.Context) {
|
|
|
|
|
|
var req UpdateRequest
|
|
|
|
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换请求结构体为模型
|
|
|
|
|
|
plan := c.convertToUpdateModel(&req)
|
|
|
|
|
|
|
|
|
|
|
|
// 调用仓库更新计划
|
|
|
|
|
|
if err := c.feedPlanRepo.UpdateFeedingPlan(plan); err != nil {
|
|
|
|
|
|
c.logger.Error("更新计划失败: " + err.Error())
|
|
|
|
|
|
controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "更新计划失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
controller.SendSuccessResponse(ctx, "更新计划成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// convertToUpdateModel 将更新请求结构体转换为数据库模型
|
|
|
|
|
|
func (c *Controller) convertToUpdateModel(req *UpdateRequest) *model.FeedingPlan {
|
|
|
|
|
|
plan := &model.FeedingPlan{
|
|
|
|
|
|
ID: req.ID,
|
|
|
|
|
|
Name: req.Name,
|
|
|
|
|
|
Description: req.Description,
|
|
|
|
|
|
Type: req.Type,
|
|
|
|
|
|
Enabled: req.Enabled,
|
|
|
|
|
|
ScheduleCron: req.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: req.ExecutionLimit,
|
|
|
|
|
|
ParentID: req.ParentID,
|
|
|
|
|
|
OrderInParent: req.OrderInParent,
|
|
|
|
|
|
Steps: make([]model.FeedingPlanStep, len(req.Steps)),
|
|
|
|
|
|
SubPlans: make([]model.FeedingPlan, len(req.SubPlans)),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换步骤
|
|
|
|
|
|
for i, step := range req.Steps {
|
|
|
|
|
|
plan.Steps[i] = model.FeedingPlanStep{
|
|
|
|
|
|
ID: step.ID,
|
|
|
|
|
|
PlanID: step.PlanID,
|
|
|
|
|
|
StepOrder: step.StepOrder,
|
|
|
|
|
|
DeviceID: step.DeviceID,
|
|
|
|
|
|
TargetValue: step.TargetValue,
|
|
|
|
|
|
Action: step.Action,
|
|
|
|
|
|
ScheduleCron: step.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: step.ExecutionLimit,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换子计划
|
|
|
|
|
|
for i, subReq := range req.SubPlans {
|
|
|
|
|
|
plan.SubPlans[i] = *c.convertToUpdateModel(&subReq)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return plan
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 14:35:54 +08:00
|
|
|
|
// convertToDetailResponse 将数据库模型转换为响应结构体
|
|
|
|
|
|
func (c *Controller) convertToDetailResponse(plan *model.FeedingPlan) *DetailResponse {
|
|
|
|
|
|
resp := &DetailResponse{
|
|
|
|
|
|
ID: plan.ID,
|
|
|
|
|
|
Name: plan.Name,
|
|
|
|
|
|
Description: plan.Description,
|
|
|
|
|
|
Type: plan.Type,
|
|
|
|
|
|
Enabled: plan.Enabled,
|
|
|
|
|
|
ScheduleCron: plan.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: plan.ExecutionLimit,
|
|
|
|
|
|
ParentID: plan.ParentID,
|
|
|
|
|
|
OrderInParent: plan.OrderInParent,
|
|
|
|
|
|
Steps: make([]FeedingPlanStep, len(plan.Steps)),
|
|
|
|
|
|
SubPlans: make([]DetailResponse, len(plan.SubPlans)),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换步骤
|
|
|
|
|
|
for i, step := range plan.Steps {
|
|
|
|
|
|
resp.Steps[i] = FeedingPlanStep{
|
|
|
|
|
|
ID: step.ID,
|
|
|
|
|
|
PlanID: step.PlanID,
|
|
|
|
|
|
StepOrder: step.StepOrder,
|
|
|
|
|
|
DeviceID: step.DeviceID,
|
|
|
|
|
|
TargetValue: step.TargetValue,
|
|
|
|
|
|
Action: step.Action,
|
|
|
|
|
|
ScheduleCron: step.ScheduleCron,
|
|
|
|
|
|
ExecutionLimit: step.ExecutionLimit,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换子计划
|
|
|
|
|
|
for i, subPlan := range plan.SubPlans {
|
|
|
|
|
|
// 递归转换子计划
|
2025-09-10 15:13:31 +08:00
|
|
|
|
resp.SubPlans[i] = *c.convertToDetailResponse(&subPlan)
|
2025-09-10 14:35:54 +08:00
|
|
|
|
}
|
2025-09-10 13:41:24 +08:00
|
|
|
|
|
2025-09-10 14:35:54 +08:00
|
|
|
|
return resp
|
2025-09-07 17:50:04 +08:00
|
|
|
|
}
|