319 lines
8.5 KiB
Go
319 lines
8.5 KiB
Go
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})
|
|
}
|