| | |
| | | package graph |
| | | |
| | | import ( |
| | | "path/filepath" |
| | | "strings" |
| | | |
| | | "github.com/aisim/kb-cli/internal/vault" |
| | | ) |
| | | |
| | |
| | | labelToID := make(map[string]int64) |
| | | nextVirtualID := int64(1000000) // 虚拟节点从 1000000 开始 |
| | | |
| | | getOrCreateVirtualNode := func(label string) int64 { |
| | | getOrCreateVirtualNode := func(label, nodeType string) int64 { |
| | | if id, ok := labelToID[label]; ok { |
| | | return id |
| | | } |
| | | id := nextVirtualID |
| | | nextVirtualID++ |
| | | labelToID[label] = id |
| | | g.Nodes = append(g.Nodes, &Node{ |
| | | ID: id, |
| | | Path: label, // label 已含 "tag:"/"entity:" 前缀 |
| | | Title: strings.TrimPrefix(strings.TrimPrefix(label, "tag:"), "entity:"), |
| | | NodeType: nodeType, |
| | | }) |
| | | return id |
| | | } |
| | | |
| | |
| | | Path: f.Path, |
| | | Title: f.Title, |
| | | Section: f.Section, |
| | | NodeType: "file", |
| | | Tags: f.Tags, |
| | | Entities: f.Entities, |
| | | Wikilinks: f.Wikilinks, |
| | |
| | | |
| | | // 创建 tag 边 |
| | | for _, tag := range f.Tags { |
| | | virtualID := getOrCreateVirtualNode("tag:" + tag) |
| | | virtualID := getOrCreateVirtualNode("tag:"+tag, "tag") |
| | | g.Edges = append(g.Edges, &Edge{ |
| | | FromNode: node.ID, |
| | | ToNode: virtualID, |
| | |
| | | |
| | | // 创建 entity 边 |
| | | for _, entity := range f.Entities { |
| | | virtualID := getOrCreateVirtualNode("entity:" + entity) |
| | | virtualID := getOrCreateVirtualNode("entity:"+entity, "entity") |
| | | g.Edges = append(g.Edges, &Edge{ |
| | | FromNode: node.ID, |
| | | ToNode: virtualID, |
| | |
| | | } |
| | | // 匹配文件名(不含扩展名和编号前缀) |
| | | // 例如:[[充装规格配置]] 匹配 "知识/002-充装规格配置.md" |
| | | return false // 简化版,后续可扩展 |
| | | base := filepath.Base(node.Path) |
| | | base = strings.TrimSuffix(base, ".md") |
| | | // 去掉编号前缀(如 "002-") |
| | | if idx := strings.Index(base, "-"); idx >= 0 { |
| | | base = base[idx+1:] |
| | | } |
| | | return base == link || node.Title == link |
| | | } |