|
@@ -29,125 +29,245 @@
|
|
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
- const timeList = [
|
|
|
- '开埠通商',
|
|
|
- '曲折发展',
|
|
|
- '步履维艰',
|
|
|
- '筚路蓝缕',
|
|
|
- '改革开放',
|
|
|
- '战略负重',
|
|
|
- '创新驱动',
|
|
|
- '追梦未来',
|
|
|
- ]
|
|
|
-
|
|
|
function randomColor() {
|
|
|
return '#' + Math.floor(
|
|
|
- (
|
|
|
- Math.random() * (1 - 0.3) + 0.3
|
|
|
- ) * 0xffffff
|
|
|
- ).toString(16)
|
|
|
+ (
|
|
|
+ Math.random() * (1 - 0.3) + 0.3
|
|
|
+ ) * 0xffffff
|
|
|
+ ).toString(16)
|
|
|
}
|
|
|
-
|
|
|
- const dataForRender = {}
|
|
|
+
|
|
|
+ const rawInfo = [
|
|
|
+ {
|
|
|
+ name: '开埠通商',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [
|
|
|
+ // {
|
|
|
+ // companyName: "正泰橡皮物品制造厂",
|
|
|
+ // createTime: "2023-08-03 14:21:45",
|
|
|
+ // creatorId: null,
|
|
|
+ // creatorName: "",
|
|
|
+ // description: "创办正泰橡皮物品制造厂,首创“回力”商标。",
|
|
|
+ // dirCode: "",
|
|
|
+ // display: null,
|
|
|
+ // fileIds: "",
|
|
|
+ // id: 10,
|
|
|
+ // name: "刘永康",
|
|
|
+ // sort: null,
|
|
|
+ // stage: "开埠通商",
|
|
|
+ // story: "",
|
|
|
+ // updateTime: "2023-08-03 14:21:45",
|
|
|
+ // }
|
|
|
+ ],
|
|
|
+ id: 'time-0'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '曲折发展',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '步履维艰',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-2'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '筚路蓝缕',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-3'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '改革开放',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-4'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '战略负重',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-5'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '创新驱动',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-6'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '追梦未来',
|
|
|
+ color: randomColor(),
|
|
|
+ corpList: [],
|
|
|
+ id: 'time-7'
|
|
|
+ },
|
|
|
+ ]
|
|
|
+
|
|
|
+ const nodesForRender = [
|
|
|
+ {
|
|
|
+ name: "历史回顾",
|
|
|
+ level: 0,
|
|
|
+ category: null,
|
|
|
+ symbolSize: 100,
|
|
|
+ itemStyle: {
|
|
|
+ color: {
|
|
|
+ type: "radial",
|
|
|
+ x: 0.5,
|
|
|
+ y: 0.5,
|
|
|
+ r: 0.5,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: "#00c7ef"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 0.8,
|
|
|
+ color: "#00c7ef"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: "rgba(0, 0, 0, 0.3)"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ global: false
|
|
|
+ },
|
|
|
+ shadowColor: "rgba(255, 255, 255, 0.5)",
|
|
|
+ shadowBlur: 10
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ position: 'inside',
|
|
|
+ show: true,
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: '18px',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ const edgesForRender = []
|
|
|
|
|
|
- let myChart = null
|
|
|
-
|
|
|
- var dom = document.getElementById('container');
|
|
|
- myChart = echarts.init(dom, null, {
|
|
|
- renderer: 'canvas',
|
|
|
- useDirtyRect: false
|
|
|
- });
|
|
|
-
|
|
|
- async function showChart(timeIdx) {
|
|
|
- myChart.clear()
|
|
|
-
|
|
|
- const res = await axios({
|
|
|
+ Promise.allSettled(rawInfo.map((timeInfoItem) => {
|
|
|
+ return axios({
|
|
|
method: 'post',
|
|
|
url: `https://sit-shgybwg.4dage.com/api/show/history/pageList`,
|
|
|
headers: {
|
|
|
"Content-Type": "application/json",
|
|
|
},
|
|
|
data: {
|
|
|
- stage: timeList[timeIdx]
|
|
|
+ stage: timeInfoItem.name
|
|
|
},
|
|
|
+ }).then((res) => {
|
|
|
+ return res.data.data.records
|
|
|
+ }).then((res) => {
|
|
|
+ timeInfoItem.corpList = res
|
|
|
})
|
|
|
- const corpList = res.data.data.records
|
|
|
-
|
|
|
- dataForRender.nodes = [
|
|
|
- {
|
|
|
- name: timeList[timeIdx],
|
|
|
- id: '-1',
|
|
|
- symbolSize: 100,
|
|
|
+ })).then((res) => {
|
|
|
+ for (const timeInfoItem of rawInfo) {
|
|
|
+ nodesForRender.push({
|
|
|
+ name: timeInfoItem.name,
|
|
|
+ level: 1,
|
|
|
+ category: timeInfoItem.name,
|
|
|
+ symbolSize: 50,
|
|
|
itemStyle: {
|
|
|
- color: randomColor()
|
|
|
+ color: timeInfoItem.color,
|
|
|
+ shadowColor: "rgba(255, 255, 255, 0.5)",
|
|
|
+ shadowBlur: 10
|
|
|
},
|
|
|
- },
|
|
|
- ]
|
|
|
- dataForRender.edges = []
|
|
|
-
|
|
|
- for (const iterator of corpList) {
|
|
|
- const newNode = {
|
|
|
- name: iterator.name || iterator.companyName,
|
|
|
- id: iterator.id.toString(),
|
|
|
- symbolSize: iterator.importance || (100 * Math.random()),
|
|
|
- itemStyle: {
|
|
|
- color: randomColor()
|
|
|
+ label: {
|
|
|
+ position: 'right',
|
|
|
+ show: true,
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: '16px',
|
|
|
}
|
|
|
- }
|
|
|
- dataForRender.nodes.push(newNode)
|
|
|
- }
|
|
|
- // 除了代表时代的那个节点,其他节点的尺寸归一化
|
|
|
- let vMax = Number.NEGATIVE_INFINITY
|
|
|
- let vMin = Number.POSITIVE_INFINITY
|
|
|
- const vMaxNew = 50
|
|
|
- const vMinNew = 30
|
|
|
- for (let index = 1; index < dataForRender.nodes.length; index++) {
|
|
|
- const size = dataForRender.nodes[index].symbolSize
|
|
|
- if (size > vMax) {
|
|
|
- vMax = size
|
|
|
- }
|
|
|
- if (size < vMin) {
|
|
|
- vMin = size
|
|
|
+ })
|
|
|
+ edgesForRender.push({
|
|
|
+ category: null,
|
|
|
+ lineStyle: {
|
|
|
+ normal: {
|
|
|
+ color: timeInfoItem.color,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ source: '历史回顾',
|
|
|
+ target: timeInfoItem.name,
|
|
|
+ })
|
|
|
+ for (const corpItem of timeInfoItem.corpList) {
|
|
|
+ nodesForRender.push({
|
|
|
+ name: corpItem.name,
|
|
|
+ level: 2,
|
|
|
+ idForSend: corpItem.id,
|
|
|
+ category: timeInfoItem.name,
|
|
|
+ symbolSize: 10,
|
|
|
+ itemStyle: {
|
|
|
+ borderColor: timeInfoItem.color,
|
|
|
+ color: 'transparent',
|
|
|
+ shadowColor: "rgba(255, 255, 255, 0.5)",
|
|
|
+ shadowBlur: 10
|
|
|
+ },
|
|
|
+ select: {
|
|
|
+ itemStyle: {
|
|
|
+ borderColor: timeInfoItem.color,
|
|
|
+ color: timeInfoItem.color,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ position: 'right',
|
|
|
+ show: true,
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: '14px',
|
|
|
+ }
|
|
|
+ })
|
|
|
+ edgesForRender.push({
|
|
|
+ category: timeInfoItem.name,
|
|
|
+ lineStyle: {
|
|
|
+ normal: {
|
|
|
+ color: timeInfoItem.color,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ source: timeInfoItem.name,
|
|
|
+ target: corpItem.name,
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- let scale = null
|
|
|
- if (vMax === vMin) {
|
|
|
- scale = 1
|
|
|
- for (const iterator of dataForRender.nodes.slice(1)) {
|
|
|
- iterator.symbolSize = vMinNew + (vMaxNew - vMinNew) / 2
|
|
|
- }
|
|
|
+ console.log(nodesForRender);
|
|
|
+ console.log(edgesForRender);
|
|
|
+ showAll()
|
|
|
+ })
|
|
|
+
|
|
|
+ let myChart = null
|
|
|
+ var dom = document.getElementById('container');
|
|
|
+ myChart = echarts.init(dom, null, {
|
|
|
+ renderer: 'canvas',
|
|
|
+ useDirtyRect: false
|
|
|
+ });
|
|
|
+
|
|
|
+ function showAll() {
|
|
|
+ return showChart()
|
|
|
+ }
|
|
|
+
|
|
|
+ function changeTime(timeIdx) {
|
|
|
+ if (Number.isInteger(timeIdx) && timeIdx >= 0) {
|
|
|
+ return showChart(timeIdx)
|
|
|
} else {
|
|
|
- scale = (vMaxNew - vMinNew) / (vMax - vMin)
|
|
|
- for (const iterator of dataForRender.nodes.slice(1)) {
|
|
|
- iterator.symbolSize = vMinNew + (iterator.symbolSize - vMin) * scale
|
|
|
- }
|
|
|
+ console.error('[page using echart] changeTime: invalid param!', timeIdx);
|
|
|
}
|
|
|
- // 画边
|
|
|
- for (let i = 0; i < dataForRender.nodes.length; i++) {
|
|
|
- for (let j = i + 1; j < dataForRender.nodes.length; j++) {
|
|
|
- const hasCenterNode = (i === 0 || j === 0)
|
|
|
- if (hasCenterNode) {
|
|
|
- const newEdge = {
|
|
|
- source: dataForRender.nodes[i].id,
|
|
|
- target: dataForRender.nodes[j].id,
|
|
|
- value: dataForRender.nodes[i].symbolSize * dataForRender.nodes[j].symbolSize * 10, // 值越大,连接的两个节点间斥力越小。
|
|
|
- }
|
|
|
- dataForRender.edges.push(newEdge)
|
|
|
- } else {
|
|
|
- const newEdge = {
|
|
|
- source: dataForRender.nodes[i].id,
|
|
|
- target: dataForRender.nodes[j].id,
|
|
|
- value: dataForRender.nodes[i].symbolSize * dataForRender.nodes[j].symbolSize * 1, // 值越大,连接的两个节点间斥力越小。
|
|
|
- lineStyle: {
|
|
|
- opacity: 0,
|
|
|
- }
|
|
|
- }
|
|
|
- dataForRender.edges.push(newEdge)
|
|
|
- }
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ let nodesForRenderTemp = null
|
|
|
+ let edgesForRenderTemp = null
|
|
|
+ function showChart(timeIdx) {
|
|
|
+ if (timeIdx !== undefined) {
|
|
|
+ nodesForRenderTemp = nodesForRender.filter((item) => {
|
|
|
+ return item.category === rawInfo[timeIdx].name
|
|
|
+ })
|
|
|
+ edgesForRenderTemp = edgesForRender.filter((item) => {
|
|
|
+ return item.category === rawInfo[timeIdx].name
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ nodesForRenderTemp = null
|
|
|
+ edgesForRenderTemp = null
|
|
|
}
|
|
|
- // console.log(dataForRender);
|
|
|
-
|
|
|
+
|
|
|
+ myChart.clear()
|
|
|
myChart.setOption({
|
|
|
animationDurationUpdate: 1500,
|
|
|
animationEasingUpdate: 'quinticInOut',
|
|
@@ -155,96 +275,77 @@
|
|
|
{
|
|
|
type: 'graph',
|
|
|
layout: 'force',
|
|
|
- draggable: false,
|
|
|
// 力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力,每条边的两个节点之间添加一个引力
|
|
|
force: {
|
|
|
- initLayout: 'circular', // 进行力引导布局前的初始化布局,初始化布局会影响到力引导的效果。默认不进行任何布局,使用节点中提供的 x, y 作为节点的位置。如果不存在的话会随机生成一个位置。也可以选择使用环形布局 'circular'。
|
|
|
- repulsion: 100, // 节点之间的斥力因子。傻逼文档把edgeLength当数组用的用法写到这上边了。
|
|
|
- gravity: 0.1, // 节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
|
|
|
- edgeLength: [50, 400], // 把各个边的两个节点之间的距离归一化到这个范围内。与repulsion共同作用。
|
|
|
+ // initLayout: 'circular', // 进行力引导布局前的初始化布局,初始化布局会影响到力引导的效果。默认不进行任何布局,使用节点中提供的 x, y 作为节点的位置。如果不存在的话会随机生成一个位置。也可以选择使用环形布局 'circular'。
|
|
|
+ // repulsion: 100, // 节点之间的斥力因子。傻逼文档把edgeLength当数组用的用法写到这上边了。
|
|
|
+ repulsion: 300, // 节点之间的斥力因子。傻逼文档把edgeLength当数组用的用法写到这上边了。
|
|
|
+ // gravity: 0.1, // 节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
|
|
|
+ // edgeLength: [50, 400], // 把各个边的两个节点之间的距离归一化到这个范围内。与repulsion共同作用。
|
|
|
+ edgeLength: 100, // 把各个边的两个节点之间的距离归一化到这个范围内。与repulsion共同作用。
|
|
|
layoutAnimation: true,
|
|
|
- friction: 0.1, // 这个参数能减缓节点的移动速度。取值范围 0 到 1。但是仍然是个试验性的参数,参见 #11024。
|
|
|
+ friction: 0.5, // 这个参数能减缓节点的移动速度。取值范围 0 到 1。但是仍然是个试验性的参数,参见 #11024。
|
|
|
},
|
|
|
- data: dataForRender.nodes,
|
|
|
+ data: timeIdx === undefined ? nodesForRender : nodesForRenderTemp,
|
|
|
// 或者叫edges
|
|
|
- links: dataForRender.edges,
|
|
|
+ links: timeIdx === undefined ? edgesForRender : edgesForRenderTemp,
|
|
|
+ // 单选or多选or不可选
|
|
|
selectedMode: 'single',
|
|
|
+ // 选中时的图形样式
|
|
|
select: {
|
|
|
itemStyle: {
|
|
|
- shadowBlur: 50,
|
|
|
+ shadowBlur: 30,
|
|
|
shadowColor: 'rgba(255, 255, 125, 0.7)',
|
|
|
},
|
|
|
label: {
|
|
|
- position: 'right',
|
|
|
- show: true,
|
|
|
- color: '#fff',
|
|
|
- fontSize: '20px',
|
|
|
fontWeight: 'bold',
|
|
|
- }
|
|
|
+ },
|
|
|
},
|
|
|
- // 高亮状态的图形样式
|
|
|
+ // hover时的图形样式
|
|
|
emphasis: {
|
|
|
scale: false,
|
|
|
- label: {
|
|
|
- position: 'right',
|
|
|
- show: true,
|
|
|
- color: '#fff',
|
|
|
- fontSize: '20px',
|
|
|
- fontWidth: 'bold',
|
|
|
- }
|
|
|
},
|
|
|
+ // hover时只照常显示有联系的那些节点和边,其余的暗色显示。
|
|
|
+ focusNodeAdjacency: true,
|
|
|
// 图表是否可以移动、缩放
|
|
|
roam: true,
|
|
|
+ scaleLimit: {
|
|
|
+ min: 0.5, //最小的缩放值
|
|
|
+ max: 3, //最大的缩放值
|
|
|
+ },
|
|
|
+ draggable: true,
|
|
|
lineStyle: {
|
|
|
- width: 0.5,
|
|
|
- curveness: 0.3,
|
|
|
- opacity: 0.7,
|
|
|
- }
|
|
|
+ normal: {
|
|
|
+ width: 1.5,
|
|
|
+ curveness: 0,
|
|
|
+ type: "solid"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ edgeSymbol: ["circle", "arrow"],
|
|
|
+ edgeSymbolSize: [4, 8],
|
|
|
}
|
|
|
]
|
|
|
}, true)
|
|
|
-
|
|
|
- setTimeout(() => {
|
|
|
- // 等myChart上注册了select回调后再执行
|
|
|
- // 一开始自动选中表示时代的那个节点
|
|
|
- myChart.dispatchAction({
|
|
|
- type: 'select',
|
|
|
- seriesIndex: 0,
|
|
|
- name: timeList[timeIdx],
|
|
|
- })
|
|
|
- }, 0);
|
|
|
}
|
|
|
|
|
|
- showChart(0)
|
|
|
-
|
|
|
// 用户选中节点后,向父窗口post message
|
|
|
function onSelect(params) {
|
|
|
- if (params.dataType === 'node') { // 用户选中节点触发的
|
|
|
- if (window.vuplex) {
|
|
|
- window.vuplex.postMessage({ type: 'select-id', message: dataForRender.nodes[params.dataIndexInside].id });
|
|
|
- } else {
|
|
|
- console.error('不存在window.vuplex!');
|
|
|
- }
|
|
|
- } else if (params.type === 'select') { // 程序里调用dispatchAction触发的,且type为select
|
|
|
- if (window.vuplex) {
|
|
|
- window.vuplex.postMessage({ type: 'select-id', message: dataForRender.nodes[0].id });
|
|
|
- } else {
|
|
|
- console.error('不存在window.vuplex!');
|
|
|
- }
|
|
|
+ if (params.dataType !== 'node') {
|
|
|
+ return
|
|
|
}
|
|
|
+ window.vuplex.postMessage({
|
|
|
+ msg: `node-selected`,
|
|
|
+ nodeLevel: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].level : nodesForRender[params.dataIndexInside].level,
|
|
|
+ nodeStageName: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].category : nodesForRender[params.dataIndexInside].category,
|
|
|
+ nodeStageIdx: rawInfo.findIndex((item) => {
|
|
|
+ return item.name === (nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].category : nodesForRender[params.dataIndexInside].category)
|
|
|
+ }),
|
|
|
+ nodeId: nodesForRenderTemp ? nodesForRenderTemp[params.dataIndexInside].idForSend : nodesForRender[params.dataIndexInside].idForSend,
|
|
|
+ })
|
|
|
}
|
|
|
myChart.on('select', onSelect)
|
|
|
|
|
|
window.addEventListener('resize', myChart.resize);
|
|
|
-
|
|
|
- // 切换时代
|
|
|
- window.changeTime = function (idx) {
|
|
|
- if (Number.isInteger(idx) && idx >= 0) {
|
|
|
- showChart(idx)
|
|
|
- } else {
|
|
|
- console.error('[page using echart] changeTime: invalid param!', idx);
|
|
|
- }
|
|
|
- }
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|