testFlow/api/graph_node/handler.go
Wyle.Gong-巩文昕 67b0ad2723 init
2025-04-22 16:42:48 +08:00

242 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package graph_node
import (
"app/cfg"
"app/models"
"app/utils"
"encoding/json"
"errors"
"fmt"
"io"
"github.com/google/uuid"
"github.com/veypi/OneBD/rest"
"gorm.io/gorm"
)
var _ = Router.Get("/:id/", getHandle) //TODO第一个命名生效
var _ = Router.Get("", getHandle)
func getHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
stageID, ok := x.Params.Get("id")
if !ok {
return nil, errors.New("缺少stage_id")
}
var nodes []models.GraphNode
if err := cfg.DB().Where("stage_id = ?", stageID).Find(&nodes).Error; err != nil {
return nil, err
}
return nodes, nil
}
// 获取单个节点详情
func getOneHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
id, ok := x.Params.Get("id")
if !ok {
return nil, errors.New("缺少id")
}
var node models.GraphNode
if err := cfg.DB().Where("id = ?", id).First(&node).Error; err != nil {
return nil, err
}
tree, _ := node.Tree(cfg.DB())
links, _ := node.Links(cfg.DB())
return map[string]interface{}{
"node": node,
"tree": tree,
"links": links,
}, nil
}
var _ = Router.Post("", postHandle)
// 创建图形节点
func postHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
node := &models.GraphNode{}
if err := json.NewDecoder(x.Request.Body).Decode(&node); err != nil {
return nil, err
}
node.ID = uuid.New().String()[0:32]
// 验证树节点是否存在
var tree models.Tree
if err := cfg.DB().Where("id = ?", node.TreeID).First(&tree).Error; err != nil {
return nil, errors.New("树节点不存在")
}
// 验证阶段是否存在
var stage models.Stage
if err := cfg.DB().Where("id = ?", node.StageID).First(&stage).Error; err != nil {
return nil, errors.New("阶段不存在")
}
// 验证树节点是否是阶段指定树节点的子孙节点
if stage.TreeID != "" && stage.TreeID != "root" {
var stageTree models.Tree
if err := cfg.DB().Where("id = ?", stage.TreeID).First(&stageTree).Error; err != nil {
return nil, errors.New("阶段指定的树节点不存在")
}
// 获取阶段树节点的所有子孙节点
descendants, err := stageTree.Descendants(cfg.DB())
if err != nil {
return nil, err
}
// 检查当前树节点是否是阶段树节点或其子孙节点
isValid := tree.ID == stageTree.ID
for _, d := range descendants {
if tree.ID == d.ID {
isValid = true
break
}
}
if !isValid {
return nil, errors.New("树节点不满足阶段要求")
}
}
if err := cfg.DB().Create(&node).Error; err != nil {
return nil, err
}
return node, nil
}
var _ = Router.Patch("/:id/", patchHandle)
// 更新图形节点
func patchHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
// 从URL获取ID
body, err := io.ReadAll(x.Request.Body)
if err != nil {
return nil, fmt.Errorf("读取请求体失败: %v", err)
}
id, ok := x.Params.Get("id")
if !ok {
return nil, errors.New("缺少id")
}
var updateMap map[string]interface{}
if err := json.Unmarshal(body, &updateMap); err != nil {
return nil, fmt.Errorf("解析JSON失败: %v", err)
}
// 先检查节点是否存在
var node models.GraphNode
if err := cfg.DB().Where("id = ?", id).First(&node).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("节点不存在")
}
return nil, err
}
// 如果更新包含tree_id需要验证树节点是否存在和是否符合阶段要求
if treeID, ok := updateMap["tree_id"]; ok {
newTreeID, ok := treeID.(string)
if !ok {
return nil, errors.New("tree_id 必须是字符串类型")
}
var tree models.Tree
if err := cfg.DB().Where("id = ?", newTreeID).First(&tree).Error; err != nil {
return nil, errors.New("树节点不存在")
}
var stage models.Stage
if err := cfg.DB().Where("id = ?", node.StageID).First(&stage).Error; err != nil {
return nil, errors.New("阶段不存在")
}
// 验证树节点是否是阶段指定树节点的子孙节点
if stage.TreeID != "" && stage.TreeID != "root" {
var stageTree models.Tree
if err := cfg.DB().Where("id = ?", stage.TreeID).First(&stageTree).Error; err != nil {
return nil, errors.New("阶段指定的树节点不存在")
}
// 获取阶段树节点的所有子孙节点
descendants, err := stageTree.Descendants(cfg.DB())
if err != nil {
return nil, err
}
// 检查当前树节点是否是阶段树节点或其子孙节点
isValid := tree.ID == stageTree.ID
for _, d := range descendants {
if tree.ID == d.ID {
isValid = true
break
}
}
if !isValid {
return nil, errors.New("树节点不满足阶段要求")
}
}
}
// 删除不允许更新的字段
delete(updateMap, "id")
// 只更新提供的字段
if len(updateMap) > 0 {
if err := cfg.DB().Model(&node).Updates(updateMap).Error; err != nil {
return nil, err
}
}
// 重新查询更新后的完整数据
if err := cfg.DB().Where("id = ?", id).First(&node).Error; err != nil {
return nil, err
}
return node, nil
}
var _ = Router.Delete("/:id/", deleteHandle)
// 删除图形节点
func deleteHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
id, ok := x.Params.Get("id")
if !ok {
return nil, errors.New("缺少id")
}
var node models.GraphNode
if err := cfg.DB().Where("id = ?", id).First(&node).Error; err != nil {
return nil, err
}
// 开始事务
tx := cfg.DB().Begin()
// 删除与该节点关联的所有连接
if err := tx.Where("prev_id = ? OR next_id = ?", id, id).Delete(&models.GraphLink{}).Error; err != nil {
tx.Rollback()
return nil, err
}
// 删除节点
if err := tx.Delete(&node).Error; err != nil {
tx.Rollback()
return nil, err
}
tx.Commit()
return map[string]interface{}{
"msg": "删除成功",
}, nil
}
var _ = Router.Any("/*", anyHandle)
func anyHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
return nil, nil
}