2025-11-24 14:49:39 +08:00

357 lines
8.5 KiB
TypeScript
Raw 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.

import { useChartHooks } from '@/views/knowledge/hooks/chart.ts'
import { computed, ref } from 'vue'
import { router } from "@/router/index.ts";
import { createData } from './mockData'
// 存储已生成的颜色,确保不重复
const usedColors = new Set<string>()
/**
* 生成随机且不重复的颜色
* @returns 十六进制颜色值
*/
const generateRandomColor = (): string => {
// 生成随机颜色
const generateColor = (): string => {
// 生成更亮的颜色,避免太暗
const r = Math.floor(Math.random() * 155) + 100
const g = Math.floor(Math.random() * 155) + 100
const b = Math.floor(Math.random() * 155) + 100
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
}
let color: string
let attempts = 0
// 尝试生成不重复的颜色最多尝试100次
do {
color = generateColor()
attempts++
} while (usedColors.has(color) && attempts < 100)
// 如果尝试次数过多,清空已使用的颜色重新开始
if (attempts >= 100) {
usedColors.clear()
color = generateColor()
}
usedColors.add(color)
return color
}
/**
* 为关系类型生成颜色映射
*/
const relationColors = ref<Map<string, string>>(new Map())
/**
* 获取关系类型对应的颜色
*/
const getRelationColor = (type: string): string => {
if (!relationColors.value.has(type)) {
relationColors.value.set(type, generateRandomColor())
}
return relationColors.value.get(type) || '#000000'
}
/**
* 为节点类型生成颜色映射
*/
const nodeColors = ref<Map<string, string>>(new Map())
/**
* 获取节点类型对应的颜色
*/
const getNodeColor = (type: string): string => {
if (!nodeColors.value.has(type)) {
nodeColors.value.set(type, generateRandomColor())
}
return nodeColors.value.get(type) || '#000000'
}
export const useChartServices = () => {
const { option, createPointData, createLink} = useChartHooks()
// 图表原始数据
const chatData = ref({})
// 类型字典集合
const typesMap = ref<string[]>([])
// 节点集合
const nodes = ref<Record<string, any>[]>([])
// 节点字典集合
const nodesMap = computed(() => {
const dataMap = new Map()
nodes.value.forEach((node) => {
if (!dataMap.has(node.id)) {
dataMap.set(node.id, node)
}
})
return dataMap
})
// 关系字典集合
const relationMap = computed(() => {
const dataMap = new Map()
console.log('relationMap', relations.value)
relations.value.forEach((relation) => {
if (!dataMap.has(relation.id)) {
dataMap.set(relation.raw.id, relation)
}
})
return dataMap
})
// 关系节点集合
const relations = ref<Record<string, any>[]>([])
// 数据规整
const chartConfig = {
chatData,
relationMap: relationMap,
typesMap,
nodes,
relations
}
// 选中的类型
const selectTypes = ref<string[]>([])
// 选中的关系
const selectRelations = ref<string[]>([])
// 切换选中类型
const toggleSelectType = (type: string) => {
const i = selectTypes.value.indexOf(type)
if (i > -1) {
selectTypes.value.splice(i, 1)
} else {
selectTypes.value.push(type)
}
}
// 切换选中关系
const toggleRelation = (relation: string) => {
const i = selectRelations.value.indexOf(relation)
if (i > -1) {
selectRelations.value.splice(i, 1)
} else {
selectRelations.value.push(relation)
}
}
// 重置数据
const resetData = () => {
chatData.value = {}
relations.value = []
typesMap.value = []
nodes.value = []
// 重置颜色映射,以便下次生成新的颜色
relationColors.value.clear()
nodeColors.value.clear()
}
// 新增类型,已存在则跳过
const addTypeMap = (data: Record<string, any>) => {
if (typesMap.value.includes(data.labels)) return
typesMap.value.push(data.labels)
}
// 处理数据
const handleData = (data: Record<string, any>) => {
const { nodes: rawNodes, relationships } = data
rawNodes.forEach((node: Record<string, any>) => {
addTypeMap(node)
// 获取节点类型对应的颜色
const nodeColor = getNodeColor(node.labels)
const nodeInfo = createPointData({
...node,
type: node.labels,
name: node.id,
itemStyle: {
color: nodeColor
},
// name: node.properties.name
})
nodes.value.push(nodeInfo)
})
relationships.forEach((relation: Record<string, any>) => {
// addRelationMap(relation)
// 获取关系类型对应的颜色
const relationColor = getRelationColor(relation.type)
const link = createLink({
...relation,
parentIndex: getNodeIndex(relation.start_node_id),
index: getNodeIndex(relation.end_node_id),
type: relation.type,
lineStyle: {
color: relationColor,
width: 2 // 关系线条宽度
},
itemStyle: {
color: relationColor
}
})
relations.value.push(link)
})
}
// 获取节点索引
const getNodeIndex = (id: string, source?: Record<string, any>) => {
return (source || nodes.value).findIndex((item:Record<string, any>) => item.id === id)
}
// 显示用的数据
const showData = computed(() => {
// 生成带有颜色的分类配置
// const categoriesWithColor = relationsMap.value.map(item => ({
// name: item,
// itemStyle: {
// normal: {
// color: getRelationColor(item)
// }
// }
// }))
// 为每个节点添加category索引使其与对应关系类型关联
const nodesWithCategory = nodes.value.map(node => ({
...node,
// category: relationsMap.value.indexOf(node.type) !== -1 ?
// relationsMap.value.indexOf(node.type) : 0
}))
const useData = {
...option.value,
series: [
{
...option.value.series[0],
// categories: categoriesWithColor,
data: nodesWithCategory,
links: relations.value,
}
]
}
console.log('useData', useData)
return useData
})
const getDataPath = () => {
const { id } = router.currentRoute.value.query;
const jsonMap: Record<string, any> = {
'1': 'http://222.190.139.186:10001/public/demo/knowledge-chat/neo4j_export2.json',
'2': 'http://222.190.139.186:10001/public/demo/knowledge-chat/neo4j_export.json'
}
return jsonMap[id as string] || jsonMap[2]
}
const getMockData = () => {
const data = createData()
return data
}
const getData = async () => {
// const path = getDataPath()
// const res = await fetch(path)
// const mockData = await res.json()
const mockData = getMockData()
console.log('mockData', mockData)
chatData.value = mockData
handleData(chatData.value)
return mockData
}
// 获取节点关系
const getNodeRelationById = (id: string) => {
console.log('relations', relationMap.value)
const relationNode = []
relations.value.forEach((item: Record<string, any>) => {
if (item.raw.end_node_id == id || item.raw.start_node_id == id) {
let targetNodeId = null
// 如果是起始点, 相关点是终点
if (item.raw.start_node_id === id) {
targetNodeId = item.raw.end_node_id
} else {
// 如果是终点, 相关点是起始点
targetNodeId = item.raw.start_node_id
}
const nodeInfo = getNodeById(targetNodeId)
if (!nodeInfo) return
const params = {
type: item.raw.type,
node: nodeInfo.raw,
relation: item.raw
}
relationNode.push(params)
}
// 如果是起始点
// 如果是终点
// if (item.start_node_id === id) {
// targets.push(item)
// } else if (item.end_node_id === id) {
// ends.push(item)
// }
})
return relationNode
}
// 获取节点信息
const getNodeById = (id: string) => {
if (!id) return
return nodesMap.value.get(id)
}
const searchValue = ref('')
// 显示节点
const onShowNodeEven = () => {
}
// 隐藏节点
const onHideNodeEven = () => {}
const state = {
option,
showData,
chartConfig,
relationColors,
nodeColors,
searchValue
}
const api = {
getData,
handleData,
// addRelationMap,
addTypeMap,
resetData,
toggleSelectType,
toggleRelation,
getNodeById,
getNodeRelationById,
onShowNodeEven,
onHideNodeEven
}
return {
state,
api
}
}