import { defineStore } from 'pinia' import { ref, computed } from 'vue' // eslint-disable-next-line no-undef const graphDataRaw = __GRAPH_DATA__ // 由 vite.config.js 注入 // eslint-disable-next-line no-undef const postGraphListRaw = __POST_GRAPH_LIST__ || [] // 帖子图谱列表 console.log('人设图谱 loaded:', !!graphDataRaw) console.log('人设节点数:', Object.keys(graphDataRaw?.nodes || {}).length) console.log('帖子图谱数:', postGraphListRaw.length) export const useGraphStore = defineStore('graph', () => { // ==================== 人设图谱数据 ==================== const graphData = ref(graphDataRaw || { nodes: {}, edges: {}, index: {}, tree: {} }) // ==================== 帖子图谱数据 ==================== const postGraphList = ref(postGraphListRaw) const selectedPostIndex = ref(postGraphListRaw.length > 0 ? 0 : -1) // 当前选中的帖子图谱 const currentPostGraph = computed(() => { if (selectedPostIndex.value < 0 || selectedPostIndex.value >= postGraphList.value.length) { return null } return postGraphList.value[selectedPostIndex.value] }) // 帖子列表(用于下拉选择) const postList = computed(() => { return postGraphList.value.map((post, index) => ({ index, postId: post.meta?.postId, postTitle: post.meta?.postTitle || post.meta?.postId, createTime: post.meta?.postDetail?.create_time })) }) // 选择帖子 function selectPost(index) { selectedPostIndex.value = index // 清除帖子相关的选中状态 selectedPostNodeId.value = null highlightedPostNodeIds.value = new Set() } // ==================== 帖子树选中状态 ==================== const selectedPostNodeId = ref(null) const highlightedPostNodeIds = ref(new Set()) // 获取帖子节点 function getPostNode(nodeId) { return currentPostGraph.value?.nodes?.[nodeId] } // 选中帖子节点 function selectPostNode(nodeId) { selectedPostNodeId.value = nodeId highlightedPostNodeIds.value = new Set([nodeId]) } // 清除帖子选中 function clearPostSelection() { selectedPostNodeId.value = null highlightedPostNodeIds.value = new Set() } // 当前选中的节点 const selectedNodeId = ref(null) // 高亮的节点ID集合 const highlightedNodeIds = ref(new Set()) // 获取节点 function getNode(nodeId) { return graphData.value.nodes[nodeId] } // 获取邻居节点 function getNeighbors(nodeId, direction = 'both') { const neighbors = [] const seen = new Set() const index = graphData.value.index if (direction === 'out' || direction === 'both') { const outEdges = index.outEdges?.[nodeId] || {} for (const [edgeType, targets] of Object.entries(outEdges)) { for (const t of targets) { if (!seen.has(t.target)) { seen.add(t.target) neighbors.push({ nodeId: t.target, edgeType, direction: 'out', score: t.score }) } } } } if (direction === 'in' || direction === 'both') { const inEdges = index.inEdges?.[nodeId] || {} for (const [edgeType, sources] of Object.entries(inEdges)) { for (const s of sources) { if (!seen.has(s.source)) { seen.add(s.source) neighbors.push({ nodeId: s.source, edgeType, direction: 'in', score: s.score }) } } } } return neighbors } // 选中节点 function selectNode(nodeId) { selectedNodeId.value = nodeId // 更新高亮节点(邻居) const neighbors = getNeighbors(nodeId) highlightedNodeIds.value = new Set(neighbors.map(n => n.nodeId)) } // 清除选中 function clearSelection() { selectedNodeId.value = null highlightedNodeIds.value = new Set() } // 计算属性:当前选中节点的数据 const selectedNode = computed(() => { return selectedNodeId.value ? getNode(selectedNodeId.value) : null }) // 计算属性:树数据 const treeData = computed(() => graphData.value.tree) // 帖子树数据 const postTreeData = computed(() => currentPostGraph.value?.tree) return { // 人设图谱 graphData, selectedNodeId, highlightedNodeIds, selectedNode, treeData, getNode, getNeighbors, selectNode, clearSelection, // 帖子图谱 postGraphList, postList, selectedPostIndex, currentPostGraph, postTreeData, selectPost, selectedPostNodeId, highlightedPostNodeIds, getPostNode, selectPostNode, clearPostSelection } })