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() /** * 生成随机且不重复的颜色 * @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>(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>(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([]) // 节点集合 const nodes = ref[]>([]) // 节点字典集合 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[]>([]) // 数据规整 const chartConfig = { chatData, relationMap: relationMap, typesMap, nodes, relations } // 选中的类型 const selectTypes = ref([]) // 选中的关系 const selectRelations = ref([]) // 切换选中类型 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) => { if (typesMap.value.includes(data.labels)) return typesMap.value.push(data.labels) } // 处理数据 const handleData = (data: Record) => { const { nodes: rawNodes, relationships } = data rawNodes.forEach((node: Record) => { 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) => { // 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) => { return (source || nodes.value).findIndex((item:Record) => 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 = { '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) => { 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 } }