package controller import ( "encoding/json" "net/http" "strconv" "ezops/model" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // WorkflowHandler 审批流程配置处理器 type WorkflowHandler struct { db *gorm.DB } // NewWorkflowHandler 创建处理器 func NewWorkflowHandler(db *gorm.DB) *WorkflowHandler { return &WorkflowHandler{db: db} } // ListWorkflows 获取审批流程列表 func (h *WorkflowHandler) ListWorkflows(c *gin.Context) { category := c.Query("category") db := h.db.Model(&model.ApprovalWorkflow{}) if category != "" { db = db.Where("category = ?", category) } var total int64 db.Count(&total) var workflows []model.ApprovalWorkflow db.Order("id ASC").Find(&workflows) // 预加载步骤 for i := range workflows { var steps []model.ApprovalWorkflowStep h.db.Where("workflow_id = ?", workflows[i].ID).Order("step_number ASC").Find(&steps) if steps == nil { steps = []model.ApprovalWorkflowStep{} } workflows[i].Steps = steps } c.JSON(http.StatusOK, model.Response{ Code: 200, Message: "success", Data: model.ListResponse{ List: workflows, Total: total, }, }) } // GetWorkflow 获取审批流程详情 func (h *WorkflowHandler) GetWorkflow(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var workflow model.ApprovalWorkflow if err := h.db.First(&workflow, id).Error; err != nil { c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "流程不存在"}) return } var steps []model.ApprovalWorkflowStep h.db.Where("workflow_id = ?", workflow.ID).Order("step_number ASC").Find(&steps) if steps == nil { steps = []model.ApprovalWorkflowStep{} } workflow.Steps = steps c.JSON(http.StatusOK, model.Response{Code: 200, Message: "success", Data: workflow}) } // CreateWorkflow 创建审批流程 func (h *WorkflowHandler) CreateWorkflow(c *gin.Context) { var req model.CreateWorkflowRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "参数错误: " + err.Error()}) return } if len(req.Steps) == 0 { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "至少需要一个步骤"}) return } cat := req.Category if cat == "" { cat = "resource" } workflow := model.ApprovalWorkflow{ Name: req.Name, Description: req.Description, Category: cat, IsActive: true, } tx := h.db.Begin() if err := tx.Create(&workflow).Error; err != nil { tx.Rollback() c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "创建失败"}) return } for _, s := range req.Steps { step := model.ApprovalWorkflowStep{ WorkflowID: workflow.ID, StepNumber: s.StepNumber, Name: s.Name, StepType: s.StepType, ApproverIDs: s.ApproverIDs, IsRequired: s.IsRequired, TimeoutHours: s.TimeoutHours, AutoApprove: s.AutoApproveTimeout, } if step.TimeoutHours == 0 { step.TimeoutHours = 24 } if err := tx.Create(&step).Error; err != nil { tx.Rollback() c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "创建步骤失败"}) return } } tx.Commit() // Reload with steps h.db.First(&workflow, workflow.ID) var steps []model.ApprovalWorkflowStep h.db.Where("workflow_id = ?", workflow.ID).Order("step_number ASC").Find(&steps) workflow.Steps = steps c.JSON(http.StatusCreated, model.Response{Code: 201, Message: "创建成功", Data: workflow}) } // UpdateWorkflow 更新审批流程 func (h *WorkflowHandler) UpdateWorkflow(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var workflow model.ApprovalWorkflow if err := h.db.First(&workflow, id).Error; err != nil { c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "流程不存在"}) return } var req model.UpdateWorkflowRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "参数错误: " + err.Error()}) return } tx := h.db.Begin() // 更新基本字段 updates := map[string]interface{}{} if req.Name != nil { updates["name"] = *req.Name } if req.Description != nil { updates["description"] = *req.Description } if req.Category != nil { updates["category"] = *req.Category } if req.IsActive != nil { updates["is_active"] = *req.IsActive } if req.IsDefault != nil { // 设为默认时,先取消同 category 其他默认 if *req.IsDefault { tx.Model(&model.ApprovalWorkflow{}). Where("category = ? AND is_default = ?", workflow.Category, true). Update("is_default", false) } updates["is_default"] = *req.IsDefault } if len(updates) > 0 { if err := tx.Model(&workflow).Updates(updates).Error; err != nil { tx.Rollback() c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "更新失败"}) return } } // 更新步骤(先删后建) if req.Steps != nil { tx.Where("workflow_id = ?", workflow.ID).Delete(&model.ApprovalWorkflowStep{}) for _, s := range req.Steps { step := model.ApprovalWorkflowStep{ WorkflowID: workflow.ID, StepNumber: s.StepNumber, Name: s.Name, StepType: s.StepType, ApproverIDs: s.ApproverIDs, IsRequired: s.IsRequired, TimeoutHours: s.TimeoutHours, AutoApprove: s.AutoApproveTimeout, } if step.TimeoutHours == 0 { step.TimeoutHours = 24 } if err := tx.Create(&step).Error; err != nil { tx.Rollback() c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "更新步骤失败"}) return } } } tx.Commit() // Reload h.db.First(&workflow, id) var steps []model.ApprovalWorkflowStep h.db.Where("workflow_id = ?", workflow.ID).Order("step_number ASC").Find(&steps) workflow.Steps = steps c.JSON(http.StatusOK, model.Response{Code: 200, Message: "更新成功", Data: workflow}) } // DeleteWorkflow 删除审批流程 func (h *WorkflowHandler) DeleteWorkflow(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) tx := h.db.Begin() tx.Where("workflow_id = ?", id).Delete(&model.ApprovalWorkflowStep{}) if err := tx.Delete(&model.ApprovalWorkflow{}, id).Error; err != nil { tx.Rollback() c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "删除失败"}) return } tx.Commit() c.JSON(http.StatusOK, model.Response{Code: 200, Message: "删除成功"}) } // SetDefaultWorkflow 设为默认流程 func (h *WorkflowHandler) SetDefaultWorkflow(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var workflow model.ApprovalWorkflow if err := h.db.First(&workflow, id).Error; err != nil { c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "流程不存在"}) return } tx := h.db.Begin() // 取消同 category 的其他默认 tx.Model(&model.ApprovalWorkflow{}). Where("category = ? AND is_default = ?", workflow.Category, true). Update("is_default", false) // 设置当前为默认 tx.Model(&workflow).Update("is_default", true) tx.Commit() c.JSON(http.StatusOK, model.Response{Code: 200, Message: "已设为默认"}) } // GetWorkflowSteps 获取流程步骤(用于申请页加载) func (h *WorkflowHandler) GetWorkflowSteps(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var workflow model.ApprovalWorkflow if err := h.db.First(&workflow, id).Error; err != nil { c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "流程不存在"}) return } var steps []model.ApprovalWorkflowStep h.db.Where("workflow_id = ?", workflow.ID).Order("step_number ASC").Find(&steps) if steps == nil { steps = []model.ApprovalWorkflowStep{} } // Parse approver_ids from JSON string to arrays for the frontend type stepResp struct { ID uint `json:"id"` StepNumber int `json:"step_number"` Name string `json:"name"` StepType string `json:"step_type"` ApproverIDs []int `json:"approver_ids"` IsRequired bool `json:"is_required"` TimeoutHours int `json:"timeout_hours"` AutoApproveTimeout bool `json:"auto_approve_on_timeout"` } result := make([]stepResp, 0, len(steps)) for _, s := range steps { var ids []int if s.ApproverIDs != "" { json.Unmarshal([]byte(s.ApproverIDs), &ids) } if ids == nil { ids = []int{} } result = append(result, stepResp{ ID: s.ID, StepNumber: s.StepNumber, Name: s.Name, StepType: s.StepType, ApproverIDs: ids, IsRequired: s.IsRequired, TimeoutHours: s.TimeoutHours, AutoApproveTimeout: s.AutoApprove, }) } c.JSON(http.StatusOK, model.Response{Code: 200, Message: "success", Data: result}) }