Wyle.Gong-巩文昕 67b0ad2723 init
2025-04-22 16:42:48 +08:00

237 lines
5.9 KiB
Go
Raw Permalink 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_link
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 links []models.GraphLink
if err := cfg.DB().Where("stage_id = ?", stageID).Find(&links).Error; err != nil {
return nil, err
}
return links, 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 link models.GraphLink
if err := cfg.DB().Where("id = ?", id).First(&link).Error; err != nil {
return nil, err
}
sourceNode, _ := link.SourceNode(cfg.DB())
targetNode, _ := link.TargetNode(cfg.DB())
return map[string]interface{}{
"link": link,
"source_node": sourceNode,
"target_node": targetNode,
}, nil
}
var _ = Router.Post("", postHandle)
// 创建图形连接
func postHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
link := &models.GraphLink{}
if err := json.NewDecoder(x.Request.Body).Decode(&link); err != nil {
return nil, err
}
link.ID = uuid.New().String()[0:32]
// 如果没有提供LinkID则生成一个
if link.LinkID == "" {
link.LinkID = fmt.Sprintf("%s-%s", link.SourceID, link.TargetID)
}
// 验证源节点是否存在
var sourceNode models.GraphNode
if err := cfg.DB().Where("instance_id = ?", link.SourceID).First(&sourceNode).Error; err != nil {
return nil, errors.New("源节点不存在")
}
// 验证目标节点是否存在
var targetNode models.GraphNode
if err := cfg.DB().Where("instance_id = ?", link.TargetID).First(&targetNode).Error; err != nil {
return nil, errors.New("目标节点不存在")
}
// 验证两个节点是否在同一个阶段
if sourceNode.StageID != targetNode.StageID {
return nil, errors.New("源节点和目标节点必须在同一个阶段")
}
// 设置阶段ID
link.StageID = sourceNode.StageID
// 验证是否已存在相同的连接
var count int64
if err := cfg.DB().Model(&models.GraphLink{}).Where("source_id = ? AND target_id = ?", link.SourceID, link.TargetID).Count(&count).Error; err != nil {
return nil, err
}
if count > 0 {
return nil, errors.New("已存在相同的连接")
}
if err := cfg.DB().Create(&link).Error; err != nil {
return nil, err
}
return link, 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 link models.GraphLink
if err := cfg.DB().Where("id = ?", id).First(&link).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("连接不存在")
}
return nil, err
}
// 如果更新包含source_id或target_id需要验证节点是否存在和是否在同一阶段
sourceID, hasSourceID := updateMap["source_id"]
targetID, hasTargetID := updateMap["target_id"]
if hasSourceID || hasTargetID {
newSourceID := link.SourceID
newTargetID := link.TargetID
if hasSourceID {
var ok bool
newSourceID, ok = sourceID.(string)
if !ok {
return nil, errors.New("source_id 必须是字符串类型")
}
}
if hasTargetID {
var ok bool
newTargetID, ok = targetID.(string)
if !ok {
return nil, errors.New("target_id 必须是字符串类型")
}
}
// 验证源节点是否存在
var sourceNode models.GraphNode
if err := cfg.DB().Where("instance_id = ?", newSourceID).First(&sourceNode).Error; err != nil {
return nil, errors.New("源节点不存在")
}
// 验证目标节点是否存在
var targetNode models.GraphNode
if err := cfg.DB().Where("instance_id = ?", newTargetID).First(&targetNode).Error; err != nil {
return nil, errors.New("目标节点不存在")
}
// 验证两个节点是否在同一个阶段
if sourceNode.StageID != targetNode.StageID {
return nil, errors.New("源节点和目标节点必须在同一个阶段")
}
// 验证是否已存在相同的连接
var count int64
if err := cfg.DB().Model(&models.GraphLink{}).Where("id != ? AND source_id = ? AND target_id = ?", id, newSourceID, newTargetID).Count(&count).Error; err != nil {
return nil, err
}
if count > 0 {
return nil, errors.New("已存在相同的连接")
}
// 更新阶段ID
updateMap["stage_id"] = sourceNode.StageID
// 更新LinkID
updateMap["link_id"] = fmt.Sprintf("%s-%s", newSourceID, newTargetID)
}
// 删除不允许更新的字段
delete(updateMap, "id")
// 只更新提供的字段
if len(updateMap) > 0 {
if err := cfg.DB().Model(&link).Updates(updateMap).Error; err != nil {
return nil, err
}
}
// 重新查询更新后的完整数据
if err := cfg.DB().Where("id = ?", id).First(&link).Error; err != nil {
return nil, err
}
return link, 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 link models.GraphLink
if err := cfg.DB().Where("id = ?", id).First(&link).Error; err != nil {
return nil, err
}
// 删除连接
if err := cfg.DB().Delete(&link).Error; err != nil {
return nil, err
}
return map[string]interface{}{
"msg": "删除成功",
}, nil
}
var _ = Router.Any("/*", anyHandle)
func anyHandle(x *rest.X) (any, error) {
utils.SetCORSHeaders(x)
return nil, nil
}