feat(canvas): 条件读取与历史 - 减少画布同步传输并校准版本
This commit is contained in:
1 parent
bcccddb4e9
commit
6ad1adc197
17 files changed
+783
-25
No files matched your search
@@ -0,0 +1,276 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"infinite-canvas/backend/internal/model"
|
||||
)
|
||||
|
||||
// Canvas 数据访问层扩展
|
||||
|
||||
// Canvas 获取画布
|
||||
func (r *Repository) Canvas(userID, canvasID string) (model.Canvas, error) {
|
||||
var canvas model.Canvas
|
||||
err := r.db.Where("user_id = ? AND id = ?", userID, canvasID).First(&canvas).Error
|
||||
if err != nil {
|
||||
return canvas, fmt.Errorf("get canvas: %w", err)
|
||||
}
|
||||
return canvas, nil
|
||||
}
|
||||
|
||||
// GetCanvas is the explicit repository name used by Agent policy builders.
|
||||
func (r *Repository) GetCanvas(userID, canvasID string) (model.Canvas, error) {
|
||||
return r.Canvas(userID, canvasID)
|
||||
}
|
||||
|
||||
func (r *Repository) CanvasNodes(userID, canvasID string) ([]model.CanvasNode, error) {
|
||||
var nodes []model.CanvasNode
|
||||
err := r.db.Where("canvas_id IN (SELECT id FROM canvases WHERE user_id = ? AND id = ?)", userID, canvasID).
|
||||
Find(&nodes).Error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get canvas nodes: %w", err)
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// CanvasNode 获取单个节点
|
||||
func (r *Repository) CanvasNode(userID, canvasID, nodeID string) (model.CanvasNode, error) {
|
||||
var node model.CanvasNode
|
||||
err := r.db.Where("id = ? AND canvas_id IN (SELECT id FROM canvases WHERE user_id = ? AND id = ?)",
|
||||
nodeID, userID, canvasID).First(&node).Error
|
||||
if err != nil {
|
||||
return node, fmt.Errorf("get canvas node: %w", err)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// CreateCanvasNode 创建节点
|
||||
func (r *Repository) CreateCanvasNode(userID, canvasID string, node model.CanvasNode) (model.CanvasNode, error) {
|
||||
// 验证画布存在且属于用户
|
||||
var canvas model.Canvas
|
||||
err := r.db.Where("user_id = ? AND id = ?", userID, canvasID).First(&canvas).Error
|
||||
if err != nil {
|
||||
return node, fmt.Errorf("canvas not found: %w", err)
|
||||
}
|
||||
|
||||
// 生成节点 ID
|
||||
if node.ID == "" {
|
||||
node.ID = generateNodeID()
|
||||
}
|
||||
node.CanvasID = canvasID
|
||||
|
||||
// 创建节点
|
||||
err = r.db.Create(&node).Error
|
||||
if err != nil {
|
||||
return node, fmt.Errorf("create canvas node: %w", err)
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// UpdateCanvasNode 更新节点
|
||||
func (r *Repository) UpdateCanvasNode(userID, canvasID, nodeID string, update model.CanvasNodeUpdate) (model.CanvasNode, error) {
|
||||
// 获取现有节点
|
||||
node, err := r.CanvasNode(userID, canvasID, nodeID)
|
||||
if err != nil {
|
||||
return node, err
|
||||
}
|
||||
|
||||
// 应用更新
|
||||
if update.Content != nil {
|
||||
node.Content = *update.Content
|
||||
}
|
||||
if update.Position != nil {
|
||||
node.Position = update.Position
|
||||
}
|
||||
if update.Size != nil {
|
||||
node.Size = update.Size
|
||||
}
|
||||
if update.ParentID != nil {
|
||||
node.ParentID = update.ParentID
|
||||
}
|
||||
if update.Metadata != nil {
|
||||
if node.Metadata == nil {
|
||||
node.Metadata = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range update.Metadata {
|
||||
node.Metadata[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// 保存
|
||||
err = r.db.Save(&node).Error
|
||||
if err != nil {
|
||||
return node, fmt.Errorf("update canvas node: %w", err)
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// DeleteCanvasNode 删除节点,可选递归删除子节点。
|
||||
func (r *Repository) DeleteCanvasNode(userID, canvasID, nodeID string, recursive ...bool) error {
|
||||
// 验证节点存在且属于用户
|
||||
_, err := r.CanvasNode(userID, canvasID, nodeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(recursive) > 0 && recursive[0] {
|
||||
var children []model.CanvasNode
|
||||
if err := r.db.Where("canvas_id = ? AND parent_id = ?", canvasID, nodeID).Find(&children).Error; err != nil {
|
||||
return fmt.Errorf("list child nodes: %w", err)
|
||||
}
|
||||
for _, child := range children {
|
||||
if err := r.DeleteCanvasNode(userID, canvasID, child.ID, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除节点
|
||||
if err := r.db.Where("id = ? AND canvas_id = ?", nodeID, canvasID).Delete(&model.CanvasNode{}).Error; err != nil {
|
||||
return fmt.Errorf("delete canvas node: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCanvasNodeChildren 返回指定父节点的直接子节点。
|
||||
func (r *Repository) GetCanvasNodeChildren(userID, canvasID, parentID string) ([]model.CanvasNode, error) {
|
||||
if _, err := r.CanvasNode(userID, canvasID, parentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var children []model.CanvasNode
|
||||
if err := r.db.Where("canvas_id = ? AND parent_id = ?", canvasID, parentID).Find(&children).Error; err != nil {
|
||||
return nil, fmt.Errorf("get canvas node children: %w", err)
|
||||
}
|
||||
return children, nil
|
||||
}
|
||||
|
||||
// CanvasNodes 获取画布所有节点
|
||||
func (r *Repository) CreateCanvasRelationship(userID, canvasID string, rel model.CanvasRelationship) error {
|
||||
// 验证节点存在
|
||||
_, err := r.CanvasNode(userID, canvasID, rel.From)
|
||||
if err != nil {
|
||||
return fmt.Errorf("source node not found: %w", err)
|
||||
}
|
||||
_, err = r.CanvasNode(userID, canvasID, rel.To)
|
||||
if err != nil {
|
||||
return fmt.Errorf("target node not found: %w", err)
|
||||
}
|
||||
|
||||
// 存储关系到 from 节点的 metadata
|
||||
fromNode, err := r.CanvasNode(userID, canvasID, rel.From)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fromNode.Metadata == nil {
|
||||
fromNode.Metadata = make(map[string]interface{})
|
||||
}
|
||||
|
||||
relationshipsKey := "relationships"
|
||||
relationships, ok := fromNode.Metadata[relationshipsKey].([]interface{})
|
||||
if !ok {
|
||||
relationships = []interface{}{}
|
||||
}
|
||||
|
||||
// 检查关系是否已存在
|
||||
for _, r := range relationships {
|
||||
if relMap, ok := r.(map[string]interface{}); ok {
|
||||
if relMap["to"] == rel.To && relMap["type"] == rel.Type {
|
||||
return nil // 关系已存在
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加新关系
|
||||
relationships = append(relationships, map[string]interface{}{
|
||||
"to": rel.To,
|
||||
"type": rel.Type,
|
||||
})
|
||||
fromNode.Metadata[relationshipsKey] = relationships
|
||||
|
||||
// 保存
|
||||
err = r.db.Save(&fromNode).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("save relationship: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteCanvasRelationship 删除节点关系
|
||||
func (r *Repository) DeleteCanvasRelationship(userID, canvasID, from, to, relType string) error {
|
||||
fromNode, err := r.CanvasNode(userID, canvasID, from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fromNode.Metadata == nil {
|
||||
return errors.New("relationship not found")
|
||||
}
|
||||
|
||||
relationshipsKey := "relationships"
|
||||
relationships, ok := fromNode.Metadata[relationshipsKey].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("relationship not found")
|
||||
}
|
||||
|
||||
// 过滤掉要删除的关系
|
||||
filtered := make([]interface{}, 0)
|
||||
found := false
|
||||
for _, r := range relationships {
|
||||
if relMap, ok := r.(map[string]interface{}); ok {
|
||||
if relMap["to"] == to && relMap["type"] == relType {
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
filtered = append(filtered, r)
|
||||
}
|
||||
|
||||
if !found {
|
||||
return errors.New("relationship not found")
|
||||
}
|
||||
|
||||
fromNode.Metadata[relationshipsKey] = filtered
|
||||
|
||||
// 保存
|
||||
err = r.db.Save(&fromNode).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete relationship: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateApproval 创建审批
|
||||
func (r *Repository) CreateApproval(approval *model.Approval) error {
|
||||
return r.db.Create(approval).Error
|
||||
}
|
||||
|
||||
// GetApproval 获取审批
|
||||
func (r *Repository) GetApproval(approvalID string) (*model.Approval, error) {
|
||||
var approval model.Approval
|
||||
err := r.db.Where("id = ?", approvalID).First(&approval).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &approval, nil
|
||||
}
|
||||
|
||||
// UpdateApprovalDecision 更新审批决策
|
||||
func (r *Repository) UpdateApprovalDecision(approvalID, decision string) error {
|
||||
return r.db.Model(&model.Approval{}).
|
||||
Where("id = ?", approvalID).
|
||||
Updates(map[string]interface{}{
|
||||
"status": "completed",
|
||||
"decision": decision,
|
||||
}).Error
|
||||
}
|
||||
|
||||
// generateNodeID 生成节点 ID(简化实现)
|
||||
func generateNodeID() string {
|
||||
return fmt.Sprintf("node_%d", time.Now().UnixNano())
|
||||
}
|
||||
Reference in new issue
Block a user