2024-11-15 16:53:35 +08:00
|
|
|
package connect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"approveflow/app/base"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
|
|
|
type NodeConnectTest struct {
|
|
|
|
Nodes []*Node
|
|
|
|
NodeMap map[string]*Node // 用于快速查找节点
|
|
|
|
}
|
|
|
|
|
|
|
|
type NodeManager interface {
|
|
|
|
GetNodes() []AbstractNode
|
|
|
|
SetNodes([]AbstractNode)
|
|
|
|
GetNodeMap() map[string]AbstractNode
|
|
|
|
NewNodePathConfig(fromNodeKey, toNodeKey string) AbstractNodePathConfig
|
2024-11-19 17:03:12 +08:00
|
|
|
Delete()
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type NodeManagerS struct {
|
|
|
|
NodeManager
|
|
|
|
}
|
|
|
|
|
|
|
|
type AbstractNode interface {
|
|
|
|
GetPathConfigs() []AbstractNodePathConfig
|
|
|
|
SetPathConfigs([]AbstractNodePathConfig)
|
|
|
|
GetKey() string
|
2024-11-19 17:03:12 +08:00
|
|
|
Delete()
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type AbstractNodePathConfig interface {
|
|
|
|
GetKey() string
|
|
|
|
GetNodeID() int64
|
|
|
|
GetFromNodeKey() string
|
|
|
|
GetToNodeKey() string
|
2024-11-19 17:03:12 +08:00
|
|
|
Delete()
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type Node struct {
|
|
|
|
PathConfigs []AbstractNodePathConfig `gorm:"-" json:"path_configs"`
|
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) UnmarshalBinary(data []byte) error {
|
|
|
|
return json.Unmarshal(data, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) GetPathConfigs() []AbstractNodePathConfig {
|
|
|
|
return n.PathConfigs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) SetPathConfigs(configs []AbstractNodePathConfig) {
|
|
|
|
n.PathConfigs = configs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) GetKey() string {
|
|
|
|
return n.Key
|
|
|
|
}
|
|
|
|
|
|
|
|
type NodePathConfig struct {
|
|
|
|
NodeID int64 `gorm:"type:bigint;index;not null" json:"node_id"`
|
|
|
|
FromNodeKey string `gorm:"type:varchar(50);index;not null" json:"from_node_key"`
|
|
|
|
ToNodeKey string ` gorm:"type:varchar(50);index;not null" json:"to_node_key"`
|
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *NodePathConfig) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *NodePathConfig) UnmarshalBinary(data []byte) error {
|
|
|
|
return json.Unmarshal(data, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodePathConfig) GetKey() string {
|
|
|
|
return n.Key
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodePathConfig) GetNodeID() int64 {
|
|
|
|
return n.NodeID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodePathConfig) GetFromNodeKey() string {
|
|
|
|
return n.FromNodeKey
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodePathConfig) GetToNodeKey() string {
|
|
|
|
return n.ToNodeKey
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) InitializeNodeMap() {
|
|
|
|
InitializeNodeMap(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func InitializeNodeMap(nct NodeManager) {
|
|
|
|
for _, node := range nct.GetNodes() {
|
|
|
|
nct.GetNodeMap()[node.GetKey()] = node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetNextNodes(nct NodeManager, node AbstractNode) ([]AbstractNode, error) {
|
|
|
|
// 获取所有节点和路径配置
|
|
|
|
nodeMap := nct.GetNodeMap()
|
|
|
|
pathConfigs := node.GetPathConfigs()
|
|
|
|
// 存储下一个节点
|
|
|
|
var nextNodes []AbstractNode
|
|
|
|
// 遍历当前节点的路径配置
|
|
|
|
for _, pathConfig := range pathConfigs {
|
|
|
|
if pathConfig.GetFromNodeKey() == node.GetKey() {
|
|
|
|
// 根据路径配置的 ToNodeKey 找到目标节点
|
|
|
|
nextNodeKey := pathConfig.GetToNodeKey()
|
|
|
|
if nextNode, exists := nodeMap[nextNodeKey]; exists {
|
|
|
|
nextNodes = append(nextNodes, nextNode)
|
|
|
|
} else {
|
|
|
|
return nil, fmt.Errorf("next node with key %s not found", nextNodeKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nextNodes, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) InsertNodeFirst(newNode AbstractNode) *NodeManagerS {
|
|
|
|
if s.GetNodes() == nil {
|
|
|
|
s.SetNodes([]AbstractNode{newNode})
|
|
|
|
}
|
|
|
|
s.SetNodes(append(s.GetNodes(), newNode))
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func InsertNodeFirst(nct NodeManager, newNode AbstractNode) {
|
|
|
|
if nct.GetNodes() == nil {
|
|
|
|
nct.SetNodes([]AbstractNode{newNode})
|
|
|
|
}
|
|
|
|
nct.SetNodes(append(nct.GetNodes(), newNode))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) InsertNodeBetween(fromNode, toNode, newNode AbstractNode) error {
|
|
|
|
return InsertNodeBetween(s, fromNode, toNode, newNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// InsertNodeBetween 在两个节点之间插入新节点
|
|
|
|
func InsertNodeBetween(nct NodeManager, fromNode, toNode, newNode AbstractNode) error {
|
|
|
|
if fromNode == nil || toNode == nil || newNode == nil {
|
|
|
|
return fmt.Errorf("节点不能为空")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 移除从 fromNode 到 toNode 的路径
|
|
|
|
removePath(nct, fromNode, toNode)
|
|
|
|
|
|
|
|
// 添加从 fromNode 到 newNode 的路径
|
|
|
|
addPath(nct, fromNode, newNode)
|
|
|
|
|
|
|
|
// 添加从 newNode 到 toNode 的路径
|
|
|
|
addPath(nct, newNode, toNode)
|
|
|
|
|
|
|
|
// 如果新节点不在节点列表中,添加进去
|
|
|
|
if _, exists := nct.GetNodeMap()[newNode.GetKey()]; !exists {
|
|
|
|
nct.SetNodes(append(nct.GetNodes(), newNode))
|
|
|
|
nct.GetNodeMap()[newNode.GetKey()] = newNode
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) InsertNodeAfter(node, newNode AbstractNode) error {
|
|
|
|
return InsertNodeAfter(s, node, newNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// InsertNodeAfter 在指定节点之后插入节点
|
|
|
|
func InsertNodeAfter(nct NodeManager, node, newNode AbstractNode) error {
|
|
|
|
if node == nil || newNode == nil {
|
|
|
|
return fmt.Errorf("节点不能为空")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取从当前节点出去的所有节点
|
|
|
|
outgoingNodes := getOutgoingNodes(nct, node)
|
|
|
|
|
|
|
|
// 移除这些路径并重新连接
|
|
|
|
for _, toNode := range outgoingNodes {
|
|
|
|
removePath(nct, node, toNode)
|
|
|
|
addPath(nct, newNode, toNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 添加从当前节点到新节点的路径
|
|
|
|
addPath(nct, node, newNode)
|
|
|
|
|
|
|
|
// 如果新节点不在节点列表中,添加进去
|
|
|
|
if _, exists := nct.GetNodeMap()[newNode.GetKey()]; !exists {
|
|
|
|
nct.SetNodes(append(nct.GetNodes(), newNode))
|
|
|
|
nct.GetNodeMap()[newNode.GetKey()] = newNode
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) InsertNodeBefore(node, newNode AbstractNode) error {
|
|
|
|
return InsertNodeBefore(s, node, newNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// InsertNodeBefore 在指定节点之前插入节点
|
|
|
|
func InsertNodeBefore(nct NodeManager, node, newNode AbstractNode) error {
|
|
|
|
if node == nil || newNode == nil {
|
|
|
|
return fmt.Errorf("节点不能为空")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取指向当前节点的所有节点
|
|
|
|
incomingNodes := getIncomingNodes(nct, node)
|
|
|
|
|
|
|
|
// 移除这些路径并重新连接
|
|
|
|
for _, fromNode := range incomingNodes {
|
|
|
|
removePath(nct, fromNode, node)
|
|
|
|
addPath(nct, fromNode, newNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 添加从新节点到当前节点的路径
|
|
|
|
addPath(nct, newNode, node)
|
|
|
|
|
|
|
|
// 如果新节点不在节点列表中,添加进去
|
|
|
|
if _, exists := nct.GetNodeMap()[newNode.GetKey()]; !exists {
|
|
|
|
nct.SetNodes(append(nct.GetNodes(), newNode))
|
|
|
|
nct.GetNodeMap()[newNode.GetKey()] = newNode
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) VerifyConnections() error {
|
|
|
|
return VerifyConnections(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyConnections 验证节点连接
|
|
|
|
func VerifyConnections(nct NodeManager) error {
|
|
|
|
for _, node := range nct.GetNodes() {
|
|
|
|
for _, pc := range node.GetPathConfigs() {
|
|
|
|
if _, exists := nct.GetNodeMap()[pc.GetFromNodeKey()]; !exists {
|
|
|
|
return fmt.Errorf("FromNodeKey %s 不存在", pc.GetFromNodeKey())
|
|
|
|
}
|
|
|
|
if _, exists := nct.GetNodeMap()[pc.GetToNodeKey()]; !exists {
|
|
|
|
return fmt.Errorf("ToNodeKey %s 不存在", pc.GetToNodeKey())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *NodeManagerS) PrintConnections() {
|
|
|
|
PrintConnections(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrintConnections 打印连接情况
|
|
|
|
func PrintConnections(nct NodeManager) {
|
|
|
|
fmt.Println("节点连接情况:")
|
|
|
|
for _, node := range nct.GetNodes() {
|
|
|
|
for _, pc := range node.GetPathConfigs() {
|
|
|
|
fmt.Printf("节点 %s -> 节点 %s\n", pc.GetFromNodeKey(), pc.GetToNodeKey())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// addPath 添加路径
|
|
|
|
func addPath(nct NodeManager, fromNode, toNode AbstractNode) {
|
|
|
|
pathConfig := nct.NewNodePathConfig(fromNode.GetKey(), toNode.GetKey())
|
|
|
|
fromNode.SetPathConfigs(append(fromNode.GetPathConfigs(), pathConfig))
|
|
|
|
}
|
|
|
|
|
|
|
|
// removePath 移除路径
|
|
|
|
func removePath(nct NodeManager, fromNode, toNode AbstractNode) {
|
|
|
|
var newPathConfigs []AbstractNodePathConfig
|
|
|
|
for _, pc := range fromNode.GetPathConfigs() {
|
2024-11-19 17:03:12 +08:00
|
|
|
if pc.GetFromNodeKey() == fromNode.GetKey() && pc.GetToNodeKey() == toNode.GetKey() {
|
|
|
|
// 使用软删除的方式
|
|
|
|
pc.Delete()
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
newPathConfigs = append(newPathConfigs, pc)
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
fromNode.SetPathConfigs(newPathConfigs)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getOutgoingNodes 获取后继节点
|
|
|
|
func getOutgoingNodes(nct NodeManager, node AbstractNode) []AbstractNode {
|
|
|
|
var result []AbstractNode
|
|
|
|
for _, pc := range node.GetPathConfigs() {
|
|
|
|
if toNode, exists := nct.GetNodeMap()[pc.GetToNodeKey()]; exists {
|
|
|
|
result = append(result, toNode)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// getIncomingNodes 获取前驱节点
|
|
|
|
func getIncomingNodes(nct NodeManager, node AbstractNode) []AbstractNode {
|
|
|
|
var result []AbstractNode
|
|
|
|
for _, n := range nct.GetNodes() {
|
|
|
|
for _, pc := range n.GetPathConfigs() {
|
|
|
|
if pc.GetToNodeKey() == node.GetKey() {
|
|
|
|
result = append(result, n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|