212 lines
4.9 KiB
Vue
212 lines
4.9 KiB
Vue
|
<script setup lang="ts">
|
|||
|
import * as echarts from 'echarts'
|
|||
|
import type { EChartsOption } from 'echarts'
|
|||
|
import { log } from 'echarts/types/src/util/log.js';
|
|||
|
import { onMounted } from 'vue';
|
|||
|
const a = {
|
|||
|
id: 1,
|
|||
|
parentId: null,
|
|||
|
label: "root",
|
|||
|
createTime: '2024-9-21',
|
|||
|
children: [
|
|||
|
{
|
|||
|
id: 2,
|
|||
|
parentId: 1,
|
|||
|
label: "root2", createTime: '2024-9-21',
|
|||
|
|
|||
|
children: [
|
|||
|
{
|
|||
|
id: 20,
|
|||
|
parentId: 12,
|
|||
|
label: "root20", createTime: '2024-9-23',
|
|||
|
|
|||
|
children: null
|
|||
|
}
|
|||
|
]
|
|||
|
}, {
|
|||
|
id: 3,
|
|||
|
parentId: 1,
|
|||
|
label: "root3", createTime: '2024-9-27', children: [{
|
|||
|
id: 30,
|
|||
|
parentId: 3,
|
|||
|
label: "root30", createTime: '2024-10-21',
|
|||
|
children: null
|
|||
|
}, {
|
|||
|
id: 31,
|
|||
|
parentId: 3,
|
|||
|
label: "root31", createTime: '2024-10-23',
|
|||
|
children: null
|
|||
|
}],
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
var option: EChartsOption;
|
|||
|
function transformToGraphData(data: any) {
|
|||
|
const graphData: [string, number][] = []; // 存储 [日期, 值]
|
|||
|
const links: { source: number; target: number }[] = []; // 存储连接关系
|
|||
|
const nodeInfoMap: Record<number, any> = {}; // 存储每个节点的对象数据,key 为 nodeId
|
|||
|
let nodeId = 0; // 用于标识每个节点的唯一索引
|
|||
|
const nodeMap: Record<number, number> = {}; // 用于映射节点 id 到 graphData 的索引
|
|||
|
|
|||
|
function traverse(node: any, parentIndex: number | null) {
|
|||
|
const currentIndex = nodeId++;
|
|||
|
// 映射当前节点 id 到 graphData 的索引
|
|||
|
nodeMap[node.id] = currentIndex;
|
|||
|
|
|||
|
// 添加当前节点的数据到 graphData
|
|||
|
graphData.push([node.createTime, node.id]);
|
|||
|
|
|||
|
// 存储当前节点完整对象到 nodeInfoMap
|
|||
|
nodeInfoMap[node.id] = { ...node };
|
|||
|
|
|||
|
// 如果存在父节点,创建 link
|
|||
|
if (parentIndex !== null) {
|
|||
|
links.push({
|
|||
|
source: parentIndex,
|
|||
|
target: currentIndex,
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
// 遍历子节点
|
|||
|
if (node.children && Array.isArray(node.children)) {
|
|||
|
node.children.forEach((child: any) => traverse(child, currentIndex));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 从根节点开始递归
|
|||
|
traverse(data, null);
|
|||
|
|
|||
|
return { graphData, links, nodeInfoMap };
|
|||
|
}
|
|||
|
const graphData1: [string, number][] = [
|
|||
|
['2017-02-01', 260],
|
|||
|
['2017-02-04', 200],
|
|||
|
['2017-02-09', 279],
|
|||
|
['2017-02-13', 847],
|
|||
|
['2017-02-18', 241],
|
|||
|
['2017-02-23', 411],
|
|||
|
['2017-03-14', 985]
|
|||
|
];
|
|||
|
const links2 = graphData1.map(function (item, idx) {
|
|||
|
return {
|
|||
|
source: idx,
|
|||
|
target: idx + 1
|
|||
|
};
|
|||
|
});
|
|||
|
links2.pop();
|
|||
|
function getVirtualData(year: string) {
|
|||
|
const date = +echarts.time.parse(year + '-01-01');
|
|||
|
const end = +echarts.time.parse(+year + 1 + '-01-01');
|
|||
|
const dayTime = 3600 * 24 * 1000;
|
|||
|
const data: [string, number][] = [];
|
|||
|
for (let time = date; time < end; time += dayTime) {
|
|||
|
data.push([
|
|||
|
echarts.time.format(time, '{yyyy}-{MM}-{dd}', false),
|
|||
|
Math.floor(Math.random() * 1000)
|
|||
|
]);
|
|||
|
}
|
|||
|
return data;
|
|||
|
}
|
|||
|
const { graphData, links, nodeInfoMap } = transformToGraphData(a);
|
|||
|
|
|||
|
option = {
|
|||
|
tooltip: {
|
|||
|
trigger:"item",
|
|||
|
formatter:(params)=>{
|
|||
|
const nodeData = nodeInfoMap[params.data[1]]; // 根据 ID 获取完整对象
|
|||
|
|
|||
|
if (params.dataType === 'node') {
|
|||
|
// 节点的悬浮提示内容
|
|||
|
return `
|
|||
|
<b>ID:</b> ${nodeData.id}<br>
|
|||
|
<b>Label:</b> ${nodeData.label}<br>
|
|||
|
<b>Create Time:</b> ${nodeData.createTime}
|
|||
|
`;
|
|||
|
}
|
|||
|
return '';
|
|||
|
}
|
|||
|
},
|
|||
|
calendar: {
|
|||
|
top: 'middle',
|
|||
|
left: 'center',
|
|||
|
orient: 'horizontal',
|
|||
|
cellSize: 40,
|
|||
|
yearLabel: {
|
|||
|
margin: 50,
|
|||
|
fontSize: 30
|
|||
|
},
|
|||
|
dayLabel: {
|
|||
|
firstDay: 1,
|
|||
|
nameMap: 'cn'
|
|||
|
},
|
|||
|
monthLabel: {
|
|||
|
nameMap: 'cn',
|
|||
|
margin: 15,
|
|||
|
fontSize: 20,
|
|||
|
color: '#999'
|
|||
|
},
|
|||
|
range: ['2024-09', '2024-12-31']
|
|||
|
},
|
|||
|
visualMap: {
|
|||
|
min: 0,
|
|||
|
max: 1000,
|
|||
|
type: 'piecewise',
|
|||
|
left: 'center',
|
|||
|
bottom: 20,
|
|||
|
inRange: {
|
|||
|
color: ['#5291FF', '#C7DBFF']
|
|||
|
},
|
|||
|
seriesIndex: [1],
|
|||
|
orient: 'horizontal'
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
type: 'graph',
|
|||
|
edgeSymbol: ['none', 'arrow'],
|
|||
|
coordinateSystem: 'calendar',
|
|||
|
links: links,
|
|||
|
symbolSize: 15,
|
|||
|
calendarIndex: 0,
|
|||
|
itemStyle: {
|
|||
|
color: 'yellow',
|
|||
|
shadowBlur: 9,
|
|||
|
shadowOffsetX: 1.5,
|
|||
|
shadowOffsetY: 3,
|
|||
|
shadowColor: '#555'
|
|||
|
},
|
|||
|
lineStyle: {
|
|||
|
color: '#D10E00',
|
|||
|
width: 1,
|
|||
|
opacity: 1
|
|||
|
},
|
|||
|
data: graphData,
|
|||
|
z: 20
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heatmap',
|
|||
|
coordinateSystem: 'calendar',
|
|||
|
data: getVirtualData('2024')
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
onMounted(() => {
|
|||
|
const doc = document.getElementById("threeContainer")
|
|||
|
const ele = echarts.init(doc)
|
|||
|
ele.setOption(option)
|
|||
|
|
|||
|
let data= transformToGraphData(a)
|
|||
|
console.log(data)
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
<template>
|
|||
|
<div class="home" id="threeContainer">
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
<style scoped lang="scss">
|
|||
|
.home {
|
|||
|
width: 100%;
|
|||
|
height: 100vh;
|
|||
|
background-color: #4a4b4b;
|
|||
|
}
|
|||
|
</style>
|