FVS, 使用Echarts展示更多种类图表(热力图)

楼主
我是社区第1798935位番薯,欢迎点我头像关注我哦~

标题: 并解决开启FVS数据更新推送功能下嵌入Echarts图表后无法一起更新的问题. 

前言: 此贴参考了论坛中的帖子: fineReport整合echarts制作桑基图-我的帆软 (fanruan.com);    并将其和FVS结合, 解决了数据更新同步的问题.

项目背景: 

  • 有车间的工单转出需要绘制热力图, 但整体看板是使用FVS制作的, 所以如何在FVS中嵌入Echarts复杂图标就是个问题了
  • FVS表格自带的Echarts引入, 仅支持简单的 key->value 形式数据的解析, 而不支持像热力图这样的 x,y,value 的复杂数据类型的数据自解析

思路

  • 图表如何绘制? 
    • 使用js进行页面元素的插入和数据处理, 渲染操作. 但这时有一个问题, FVS的表格是没有初始化JS的(或许我不知道), 所以我们这里需要在决策报表里面绘制, 然后通过FVS网页框将决策报表引入到FVS大屏. 
  • 数据如何获取,更新?
    • 特别是在FVS有数据联动的情况下, 比如我的工单的转出数据是按照天, 周, 月, 年的时间段进行抽取出来的数据, 那我在FVS中更改了筛选条件后, 如何让决策报表里面的热力图数据也同步更新? 
  • FVS有推送更新, 决策报表如何一样即时更新? 
    • 如果是用网页框的监控刷新选项, 1. 网页框会整体刷新, 白屏然后展示, 观感上不好. 2. 测试出网页框的监控刷新和FVS的数据推送刷新互斥, 实际上无法使用, 决策报表的初始化JS倒是不互斥, 但是依然有1. 的问题, 太难看. 
    • 既然用了JS, 那么干脆用JS的  setInterval  方法算了, 按指定时间轮训重复从数据集获取数据.(注意, 这里不去查SQL, 所以影响的只是网页端的性能. 可以看后续代码部分.).

最后效果: 

前期准备

  • 导入 Echarts.js 文件. 
    • 下载Echarts: 在此页面 快速上手 - 使用手册 - Apache ECharts  按照说明下载 echarts.js文件.  下面这个链接是截止2024.0913时间的最新Echart.js链接: cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js
    • 导入到FineReport:  将下载好的js文件, 放置在 FineReport服务器 的 webroot 文件夹中, 和WEB_INF同级(注意,这里我测试放到WEB_INF里面引入的时候获取不到, 可能是权限问题, 感兴趣的可以自测下. )
    • 引入到FineReport: 

创建数据集

  • 这里需要注意的是, 这里的变量是要加到全局参数里面, 后面会有用, 切记!

FVS设置

  • 网页框组件, 设置参数: 
    • 注意, 参数名称一定要和决策报表中的全局参数名称一样
    • 参数内容一定是绑定了参数的全局参数,
  • 这样设置后, FVS页面通过下拉框/选择按钮修改了数据后, 因为绑定了全局参数, 所以全局参数进行了变化, 这个变化会同步到网页框关联的决策报表的全局参数中, 而网页框的全局参数变化, 会使得数据集的结果变化. 而JS中在循环中通过Value获取的数据也会发生变化. 

编写JS代码. 

  • 插入标签控件: ,
  • 控件名称自定义: 
  • 添加初始化后事件: 
  • 添加JS: 
    • 初始化变量:  这里主要是获取指定sql查询出的数据集.  不使用SQL函数, 所以不影响数据库性能. 
      •  

        var cs0 = "VALUE('查询指定厂的全部车间',1)"
        
        var cs1 = "VALUE('查询指定时间段的转出数据',1)"
        var cs2 = "VALUE('查询指定时间段的转出数据',2)"
        var cs3 = "VALUE('查询指定时间段的转出数据',3)"
    • 初始化Echarts组件 清空Label控件内容, 并在Label控件中添加div标签: 注意, LABEL0是FR中label的控件名称. 第二句的id名称需要和第三局getElementById的值相同!
      • $("div[widgetname=LABEL0]").empty();
        
        // 往标签控件里添加div,指定id
        $("div[widgetname=LABEL0]").append("
        ");
        
        var myChart = echarts.init(document.getElementById("echa"));
    •  数据处理: 用js将数据集数据转换为Echarts所需数据. 按照Echarts不同图标自己处理即可.  
      • // 获取车间数据, 以及所需的三列值
        	var dept = FR.remoteEvaluate(cs0);
        	var d1 = FR.remoteEvaluate(cs1);
        	var d2 = FR.remoteEvaluate(cs2);
        	var d3 = FR.remoteEvaluate(cs3);
        
        	
        	// 定义所需值的数组容器
        	var data = [];
        
        	// 通过三列查询数据拼接中间数据(转出车间-转入车间-数量)
        	var rawData = [];
        	// 热力图的展示最大值, 默认10
        	var maxCount = 10;
        	// 如果有比10更大的, 就使用最大值
        	// 获取rawData
        	for (i = 0; i < d1.length; i++) {
        		counti = d3[i];
        		if (maxCount < counti) {
        			maxCount = counti;
        		}
        		rawData.push([d1[i], d2[i], counti]);
        	}
        
        	// 将rawData转换为(x, y, value)
        	rawData.forEach(function(item) {
        		// 找到每个部门在 dept 数组中的索引位置作为 y 轴坐标
        		var indexx = dept.indexOf(item[0].toString());
        		var indexy = dept.indexOf(item[1].toString());
        		if (indexx !== -1 && indexy !== -1) {
        			data.push([indexx, indexy, item[2]]);
        		}
        	});
        
    • Echarts配置: 注意, 我这里的字体都调的是白色的, 需要自己调整即可. 
      • // 以下为echarts正常配置
        	var option = {
        		title: {
        			text: '转出数据热力图',
        			left: 'center',
        			top: 20,
        			textStyle: { // 设置字体颜色为白色
        				color: '#fff'
        			}
        		},
        		tooltip: {
        			position: 'top'
        		},
        		grid: {
        			height: '85%',
        			top: '5%'
        		},
        		xAxis: {
        			type: 'category',
                                // 这里是转换出的数组
        			data: dept,
        			splitArea: {
        				show: false
        			}
        		},
        		yAxis: {
        			type: 'category',
                                // 这里是转换出的数组
        			data: dept,
        			splitArea: {
        				show: false
        			}
        		},
        		visualMap: {
        			min: 0,
        			max: maxCount,
        			calculable: true,
        			orient: 'vertical',
        			right: '10px', // 将visualMap放置在图表的右侧
        			top: 'center', // 确保垂直居中
        			bottom: '0%',
        			textStyle: { // 设置字体颜色为白色
        				color: '#fff'
        			}
        		},
        		series: [{
        			name: '测试图表',
        			type: 'heatmap',
                                // 这里是转换出的数组
        			data: data,
        			label: {
        				show: true, // 显示标签
        				position: 'inside', // 标签位置,默认为 'inside'
        				formatter: function(params) {
        					// 自定义标签内容
        					return params.value[2];
        				}
        			},
        			emphasis: {
        				itemStyle: {
        					shadowBlur: 10,
        					shadowColor: 'rgba(0, 0, 0, 0.5)'
        				}
        			}
        		}]
        	};

整体JS:  

  • 要把整个数据处理-解析在setInterval之前重复一遍, 因为setInterval不会开始即运行, 而是指定时间后运行(如这里设置的5s). 
  • setInterval设置的是5s, 自行调整.
var cs0 = "VALUE('查询指定厂的全部车间',1)"

var cs1 = "VALUE('查询指定时间段的转出数据',1)"
var cs2 = "VALUE('查询指定时间段的转出数据',2)"
var cs3 = "VALUE('查询指定时间段的转出数据',3)"

// 先初始化一次
// 清空标签控件里的内容
	$("div[widgetname=LABEL0]").empty();

	// 往标签控件里添加div,指定id
	$("div[widgetname=LABEL0]").append("
");

	var myChart = echarts.init(document.getElementById("echa"));


	// 获取车间数据, 以及所需的三列值
	var dept = FR.remoteEvaluate(cs0);
	var d1 = FR.remoteEvaluate(cs1);
	var d2 = FR.remoteEvaluate(cs2);
	var d3 = FR.remoteEvaluate(cs3);

	
	// 定义所需值的数组容器
	var data = [];

	// 通过三列查询数据拼接中间数据(转出车间-转入车间-数量)
	var rawData = [];
	// 热力图的展示最大值, 默认10
	var maxCount = 10;
	// 如果有比10更大的, 就使用最大值
	// 获取rawData
	for (i = 0; i < d1.length; i++) {
		counti = d3[i];
		if (maxCount < counti) {
			maxCount = counti;
		}
		rawData.push([d1[i], d2[i], counti]);
	}

	// 将rawData转换为(x, y, value)
	rawData.forEach(function(item) {
		// 找到每个部门在 dept 数组中的索引位置作为 y 轴坐标
		var indexx = dept.indexOf(item[0].toString());
		var indexy = dept.indexOf(item[1].toString());
		if (indexx !== -1 && indexy !== -1) {
			data.push([indexx, indexy, item[2]]);
		}
	});


	// 以下为echarts正常配置
	var option = {
		title: {
			text: '转出数据热力图',
			left: 'center',
			top: 20,
			textStyle: { // 设置字体颜色为白色
				color: '#fff'
			}
		},
		tooltip: {
			position: 'top'
		},
		grid: {
			height: '85%',
			top: '5%'
		},
		xAxis: {
			type: 'category',
			data: dept,
			splitArea: {
				show: false
			}
		},
		yAxis: {
			type: 'category',
			data: dept,
			splitArea: {
				show: false
			}
		},
		visualMap: {
			min: 0,
			max: maxCount,
			calculable: true,
			orient: 'vertical',
			right: '10px', // 将visualMap放置在图表的右侧
			top: 'center', // 确保垂直居中
			bottom: '0%',
			textStyle: { // 设置字体颜色为白色
				color: '#fff'
			}
		},
		series: [{
			name: '测试图表',
			type: 'heatmap',
			data: data,
			label: {
				show: true, // 显示标签
				position: 'inside', // 标签位置,默认为 'inside'
				formatter: function(params) {
					// 自定义标签内容
					return params.value[2];
				}
			},
			emphasis: {
				itemStyle: {
					shadowBlur: 10,
					shadowColor: 'rgba(0, 0, 0, 0.5)'
				}
			}
		}]
	};

	// 设置图表选项
	if (option && typeof option === "object") {
		myChart.setOption(option, true);
	}



setInterval(function() {
	// 清空标签控件里的内容
//		$("div[widgetname=LABEL0]").empty();

	// 往标签控件里添加div,指定id
//	$("div[widgetname=LABEL0]").append("
");

//	var myChart = echarts.init(document.getElementById("echa"));


	// 获取车间数据, 以及所需的三列值
	var dept = FR.remoteEvaluate(cs0);
	var d1 = FR.remoteEvaluate(cs1);
	var d2 = FR.remoteEvaluate(cs2);
	var d3 = FR.remoteEvaluate(cs3);

	
	// 定义所需值的数组容器
	var data = [];

	// 通过三列查询拼接中间数据(转出车间-转入车间-数量)
	var rawData = [];
	// 热力图的展示最大值, 默认10
	var maxCount = 10;
	// 如果有比10更大的, 就使用最大值
	// 获取rawData
	for (i = 0; i < d1.length; i++) {
		counti = d3[i];
		if (maxCount < counti) {
			maxCount = counti;
		}
		rawData.push([d1[i], d2[i], counti]);
	}

	// 将rawData转换为(x, y, value)
	rawData.forEach(function(item) {
		// 找到每个部门在 dept 数组中的索引位置作为 y 轴坐标
		var indexx = dept.indexOf(item[0].toString());
		var indexy = dept.indexOf(item[1].toString());
		if (indexx !== -1 && indexy !== -1) {
			data.push([indexx, indexy, item[2]]);
		}
	});


	// 以下为echarts正常配置
	var option = {
		title: {
			text: '转出数据热力图',
			left: 'center',
			top: 20,
			textStyle: { // 设置字体颜色为白色
				color: '#fff'
			}
		},
		tooltip: {
			position: 'top'
		},
		grid: {
			height: '85%',
			top: '5%'
		},
		xAxis: {
			type: 'category',
			data: dept,
			splitArea: {
				show: false
			}
		},
		yAxis: {
			type: 'category',
			data: dept,
			splitArea: {
				show: false
			}
		},
		visualMap: {
			min: 0,
			max: maxCount,
			calculable: true,
			orient: 'vertical',
			right: '10px', // 将visualMap放置在图表的右侧
			top: 'center', // 确保垂直居中
			bottom: '0%',
			textStyle: { // 设置字体颜色为白色
				color: '#fff'
			}
		},
		series: [{
			name: '测试图表',
			type: 'heatmap',
			data: data,
			label: {
				show: true, // 显示标签
				position: 'inside', // 标签位置,默认为 'inside'
				formatter: function(params) {
					// 自定义标签内容
					return params.value[2];
				}
			},
			emphasis: {
				itemStyle: {
					shadowBlur: 10,
					shadowColor: 'rgba(0, 0, 0, 0.5)'
				}
			}
		}]
	};

	// 设置图表选项
	if (option && typeof option === "object") {
		myChart.setOption(option, true);
	}


}, 5000);

 

分享扩散:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

返回顶部 返回列表