echarts柱状图多个联合查询,自定义echarts底部区间,后台根据区间查询数据

需求:

页面上展示echarts柱状图表,根据区域查询每个区域的人数,根据分数段查询每个分数区间的人数。
其中,分数段统计,底部区间可以点击按钮自定义分数段,并且保存到数据库,后台根据自定义的区间,统计对应的人数
效果如下:

在这里插入图片描述

在这里插入图片描述

点击设置分数段按钮,弹出层,这部分使用ajax查询后台保存的分数节点,然后回显到页面上
输入分数段保存会校验是否重复,验证数量是否是9个,不需要限制的话,可以将相关代码去掉
另外需要注意,如果底部区间过多,可能会造成样式变形或遮盖

在这里插入图片描述

主表逻辑根据自己项目来,这里就不赘述了,有需要的可以私信,这里简单讲下分数段表设计

1. 表中我们需要存入分数字段,这里我们需要关联具体的项目,所以,有一个项目id, 下面是mysql的表设计内容:

CREATE TABLE `score_interval`  (
  `ID` BIGINT NOT NULL AUTO_INCREMENT COMMENT '唯一主键',
  `PROJECTID` BIGINT NOT NULL COMMENT '活动id',
  `SCORE` BIGINT NOT NULL COMMENT '分数区间',
  `IS_DELETE` VARCHAR(20) DEFAULT NULL COMMENT '0,未删除,1删除',
  PRIMARY KEY (`ID`),
  KEY `IDX_PROJECTID` (`PROJECTID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
下面是oracle表设计
create table SCORE_INTERVAL             
(
  ID                 NUMBER(10) NOT NULL,
  PROJECTID          NUMBER(10) ,
  SCORE           	 NUMBER(10) ,
  IS_DELETE          VARCHAR2(20),
);
  
-- Add comments to the columns 
comment on column SCORE_INTERVAL.ID is '主键';
comment on column SCORE_INTERVAL.PROJECTID is '项目id';
comment on column SCORE_INTERVAL.SCORE is '分数段';

--设置主键
ALTER TABLE SCORE_INTERVAL ADD CONSTRAINT "PK_SCORE_INTERVAL" PRIMARY KEY ("ID");
  
  --表序列
create sequence SEQ_SCORE_INTERVAL
minvalue 1
maxvalue 9999999999
start with 1
increment by 1
cache 20;

2.建完表以后,生成基础代码,这里直接讲页面的写法,这个页面整体样式使用layui的布局,页面上有些基础样式,不需要可以去除,layui需要引入。

需要引入的有layui.css,jquery-1.7.2.min.js,layui.js,echarts.min.js,其中index.css是自己写的样式,这里放在后面连接,有需要的可以自己下载。

<head>
	<meta charset="utf-8">
	<meta name="renderer" content="webkit">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
	<title>招生项目管理系统</title>
	<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/js/layui/css/layui.css">
	<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/enroll/css/index.css?v1">
	<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/jquery-1.7.2.min.js"></script>
	<script src="${pageContext.request.contextPath}/resources/js/layui/layui.js"></script>
<script src="${pageContext.request.contextPath}/resources/enroll/js/echarts.min.js"></script>
	<style>
		body {
			background-color: #F0F2F5;
		}

		.layui-form-pane .layui-form-label {
			color: #aaa;
			width: 120px;
			background-color: #f6f6f6;
		}

		.layui-form {
			background-color: #fff;
			padding: 20px;
			margin-bottom: 10px;
			border-radius: 20px;
		}

		.layui-laydate-range {
			left: 50% !important;
			top: 30px !important;
			transform: translateX(-69%) !important;
		}

		.submitcon .layui-btn {
			border-radius: 5px;
		}
		.layui-elem-field legend{
			font-size: 17px;
			font-weight: bold;
		}
		
		/*------弹出层操作提示 ----------------*/
		#tips{width:100%; position:relative; padding-top:26px; padding-bottom:15px;}
		#tips i{position:absolute; top:0; left:0; width:100px; padding-top:36px; text-indent:34px; height:26px; line-height:26px; background:url(${pageContext.request.contextPath}/resources/images/basetheme/list/tips.gif) 18px 15px no-repeat; font-style:normal; font-weight:bold;}
		.cz_rig{ padding:10px 10px 10px 100px; border:1px solid #FFDC3D; background:#FFFFE7;}
		.cz_rig li{line-height:26px; line-height:26px;}

	</style>
</head>

3.这部分代码是顶部查询条件,如果需要更改查询条件,在这部分删改,样式使用的是layui的样式,不用动,直接复制到页面上,引入css就可以

<div class="charspacon">
	<form class="layui-form layui-form-pane" action="">
		<fieldset class="layui-elem-field layui-field-title" style="margin: 0 0 15px 0;">
			<legend>类型选择</legend>
		</fieldset>
		<fieldset class="layui-elem-field" style="border: none;margin: 0;">
			<div>
				<div class="layui-form-item relistcon">
					<div class="layui-inline">
						<label class="layui-form-label">登记所属类型</label>
						<div class="layui-input-inline ">
							<select name="enrollType" id="enrollType" lay-filter="enrollType">
								<option value="0" selected>普高类登记信息</option>
								<option value="1">特长生登记信息</option>
							</select>
						</div>
					</div>
					<div class="layui-inline">
						<label class="layui-form-label">分数类型</label>
						<div class="layui-input-inline  charselcon">
							<select name="scoreType" id="scoreType" lay-search lay-filter="scoreType">
								<option value="0" selected>一模总分(不含体育、口语)</option>
								<option value="1">中考总分(含体育、口语)</option>
							</select>
						</div>
					</div>
					<div class="layui-inline" id="firstScoreAll">
						<label class="layui-form-label">分数范围</label>
						<div class="layui-input-inline charsincon">
							<input type="tel" name="firstScoreAllge" id="firstScoreAllge" autocomplete="off" class="layui-input"
								   placeholder="请输入一模总分">
							<span class="charsinline">~</span>
							<input type="tel" name="firstScoreAllle" id="firstScoreAllle" autocomplete="off" class="layui-input"
								   placeholder="请输入一模总分">
						</div>
					</div>
					<div class="layui-inline" id="midtermExamScoreAll" style="display: none">
						<label class="layui-form-label">分数范围</label>
						<div class="layui-input-inline charsincon">
							<input type="tel" name="midtermExamScoreAllge" id="midtermExamScoreAllge" autocomplete="off" class="layui-input"
								   placeholder="请输入中考总分">
							<span class="charsinline">~</span>
							<input type="tel" name="midtermExamScoreAllle" id="midtermExamScoreAllle" autocomplete="off" class="layui-input"
								   placeholder="请输入中考总分">
						</div>
					</div>
				</div>
				<div style="display: flex;">
					<div class="layui-form-item submitcon charsub">
						<div id="demo1" class="layui-btn  layui-btn-lg" lay-submit lay-filter="demo1">搜索</div>
					</div>
					<div class="chheadti chheadti1">设置分数段</div>
				</div>
			</div>
		</fieldset>
	</form>
	<div class="eclist">
		<div class="ec_lecon">
			<div class="ec_lehe">
				<div class="ec_leti">登记人数统计</div>
				<div class="ec_leti">合计:<span style="color: red" id="areaNum"></span></div>
				<div class="ec_le_ri">
					<div class="ec_lehelist">
						<div class="ec_litem ec_iac" data-index="0">全部</div>
						<span class="inte_l"></span>
						<div class="ec_litem" data-index="1">按日</div>
						<span class="inte_l"></span>
						<div class="ec_litem" data-index="2">按周</div>
						<span class="inte_l"></span>
						<div class="ec_litem" data-index="3">按月</div>
						<span class="inte_l"></span>
						<div id="cur_bar_time" class="ec_litem" data-index="4">自定义</div>
						<input id="cur_bar_input_time" type="text" hidden />
					</div>
				</div>

			</div>
			<div id="ec_le" class="ec_le"></div>
		</div>

		<div class="ec_ricon">
			<div class="ec_lehe">
				<div class="ec_leti2">一模总分分数段统计</div>
				<div class="ec_leti">合计:<span style="color: red" id="scoreNum"></span></div>
				<div class="ec_lehelist2">
					<div class="ec_litem2 ec_iac" data-index="0">全部</div>
					<span class="inte_l"></span>
					<div class="ec_litem2" data-index="1">按日</div>
					<span class="inte_l"></span>
					<div class="ec_litem2" data-index="2">按周</div>
					<span class="inte_l"></span>
					<div class="ec_litem2" data-index="3">按月</div>
					<span class="inte_l"></span>
					<div id="cur_bar2_time" class="ec_litem2" data-index="4">自定义</div>
					<input id="cur_bar2_input_time" type="text" hidden />
				</div>
			</div>
			<div id="ec_ri" class="ec_ri"></div>
		</div>
	</div>
</div>

4. 这部分是点击设置分数段,弹出层的代码,初始化隐藏,点击按钮弹出,设置分数段的代码

<div class="scopopcon" style="display: none" >
	<div class="scoreopcon">
		<div class="scoohe">
			<div class="scoohele">
				<img class="scoi1" src="${pageContext.request.contextPath}/resources/enroll/img/scoi1.png" alt="" />
				<span>设置分数段</span>
			</div>
			<div class="scooheri">
				<div class="sherite1">请输入分数段节点 <span class="sheritec1">(如50)</span>最多可设置9个 -</div>
				<input class="sheriinput" type="text" maxlength="3" placeholder="输入分数段..." />
				<button type="button" class="sheribtn">添加</button>
			</div>
		</div>
		<div class="showdomar">
			<div>已设置分数节点</div>
			<div class="showdomarri"></div>
		</div>
		<div class="scooce">
			<div class="scoocele">
				<div class="scooceleline"></div>
				<div class="scoocelete">0</div>
			</div>
			<div class="scoocece"></div>
			<div class="scooceri">
				<div class="scooceriline"></div>
				<div class="scoocelete">700</div>
			</div>
		</div>
		<div class="scoobo">
			<button class="scoobobtn btn2" type="button">确定</button>
		</div>
	</div>
</div>
<div id="tips">
	<i style="width: 150px">分数段统计说明:</i>
	<ul class="cz_rig">
		<li style="margin-left: 50px">1.未设置分数段,按照查询的分数区间平均分为10段,最少按照1分1段</li>
		<li style="margin-left: 50px">2.设置分数段后,根据分数段展示统计人数</li>
		<li style="margin-left: 50px">3.分数段范围含头不含尾,比如100-200,包含100,不包含200,200分在200-300的范围内,以此类推。
			最后一个分数段范围包含全部,比如600-700,包含700分</li>
	</ul>
</div>

5. 接下来是js部分实现,现在分步骤来详细讲解,后面后统一放出来代码。

首先,layui需要引入使用的部分,我们所有的代码都在这里面实现

layui.use(['form', "laydate", "jquery"], function() {
		var form = layui.form,
				layer = layui.layer,
				laydate = layui.laydate,
				$ = layui.jquery;
				
				//这里实现代码逻辑,下面所有的js都复制到这个地方


	}

6. 初始化就加载方法,这里有两个柱状图,那就是要加载两次,点击搜索的时候,也调用两个方法

demo1是搜索按钮的id,这里可以根据自己的按钮id更改,一定要同步,否则会造成搜索按钮失效

$("#demo1").on("click", function(event) { //搜索按钮
			areaSts();
			scoreSts();
		})
		//初始化地区统计
		areaSts();
		//初始化分数统计
		scoreSts();

7. 第一个柱状图查询方法,点击查询时,会调用这个方法,这里是根据日期查询,如果不需要根据日期查询,可以去掉,后面ajax查询后台数据,并且将数据赋值给echars图上

function areaSts(){
			var bDate = $('#begWdateId').val();		//起始时间
			var eDate = $('#endWdateId').val();		//结束时间
			//TODO 这里的方法改成你自己的方法
			var url = ' 请求地址 ';
			$.ajax({
				type: 'post',
				url: url,
				data: {},
				success: function (data) {
					if (data.code == '0') {
						var area_value = [];
						var ser_val = [];
						var num =0;
						for (var key in data.result) {
							area_value.push(key);
							ser_val.push(data.result[key]);
							if(data.result[key] != null){
								num+=data.result[key];
							}
						}
						$('#areaNum').html(num);
						option1_bar.yAxis.data = area_value;
						option1_bar.series[0].data = ser_val;
						chart1.setOption(option1_bar, true);
					}
				}
			});
		}

8. 接下来是另一个柱状图的请求方法,同上,需要修改成自己的后台请求路径地址

function scoreSts(){
			var bDate = $('#begWdateScore').val();		//起始时间
			var eDate = $('#endWdateScore').val();		//结束时间
			//TODO 这里的方法改成你自己的方法
			var url = ' 请求地址 ';
			$.ajax({
				type: 'post',
				url: url,
				data: {},
				success: function (data) {
					if (data.code == '0') {
						var score_range = [];
						var score_arr = [];
						var num =0;
						for (var key in data.result) {
							score_range.push(key);
							score_arr.push(data.result[key]);
							if(data.result[key] != null){
								num+=data.result[key];
							}
						}
						$('#scoreNum').html(num);
						option2.xAxis.data = score_range;
						option2.series[0].data = score_arr;
						chart2.setOption(option2, true);
					}
				}
			});
		}

9. 这里是查询部分改变事件,我们可以看到,登记类型是下拉,那么如果我们需要再点击下拉时,同时改变我们页面上的文字描述,或者显示隐藏其他模板,就可以使用以下方法,如果不存在条件查询,那么这步骤可以省略

在这里插入图片描述

form.on('select(scoreType)', function(data) { //选择分数类型后改变页面显示
			if('0' == data.value){
				$('#midtermExamScoreAll').hide();
				$('#firstScoreAll').show();
				$('#midtermExamScoreAllge').val('');
				$('#midtermExamScoreAllle').val('');
				$('.ec_leti2').html('一模总分分数段统计');

			}else{
				$('#firstScoreAll').hide();
				$('#midtermExamScoreAll').show();
				$('#firstScoreAllge').val('');
				$('#firstScoreAllle').val('');
				$('.ec_leti2').html('中考总分分数段统计');
			}
			areaSts();
			scoreSts();
		});

10. 地区柱状图,echarts图表的使用,如果各位不是很清楚,可以参考echart官网,这里面主要是设置了柱状图的样式,颜色,大小等,需要改变属性或者形状,可以参考官网 ,官网地址:https://echarts.apache.org/zh/index.html

		/*
          柱状图选项
          bar_user_info:柱状图数据
          bar_user_name:姓名
          bar_user_value:用户值
        */
		var chartDom = document.getElementById('ec_le');
		var chart1 = echarts.init(chartDom);
		var colorList = ['#0085FF', '#16B777', '#FF9933', '#31BDEC']
		var bar_user_name = [];
		var bar_user_value = [];
		var bar_user_info = [];
		for (var i = 0; i < bar_user_info.length; i++) {
			bar_user_name.push(bar_user_info[i].name)
			bar_user_value.push(bar_user_info[i].value)
		}
		var option1_bar;
		option1_bar = {
			tooltip: {
				trigger: 'axis',
				axisPointer: {
					type: 'shadow'
				}
			},

			legend: {},
			grid: {
				left: '0%',
				right: '4%',
				top: "20%",
				bottom: '3%',
				containLabel: true
			},
			xAxis: {
				type: 'value',
				boundaryGap: [0, 0.01]
			},
			yAxis: {
				type: 'category',
				data: bar_user_name,
				axisLabel: {
					interval: 0,
				},
			},
			series: [{
				type: 'bar',
				data: bar_user_value,
				barWidth: "30%",
				itemStyle: {
					borderRadius: [0, 20, 20, 0],
					color: function(params) {
						return colorList[params.dataIndex % colorList.length];
					}
				},
				label: {
					show: true,
					position: 'right',
				},
			}, ],
			dataZoom: [
				{
					type: 'slider',
					left: '93%',
					yAxisIndex: 0,
					start: 0,
					end: 60
				}
			]
		}
		option1_bar && chart1.setOption(option1_bar);
		//地区统计-自定义时间
		laydate.render({
			elem: '#cur_bar_input_time',
			eventElem: '#cur_bar_time',
			type: 'date',
			range: true,
			done: function(value, date, endDate) { //自定义选择
				if (!WisEmpty(value)) {
					var dateArr = value.split(" - ");
					$('#begWdateId').val(dateArr[0]);
					$('#endWdateId').val(dateArr[1]);
					areaSts();
				}
			}
		});

11. 分数柱状图,这两个图的id需要对应,我们在上面的ajax方法中,请求数据要赋值到对应的图表上面

var chartDom2 = document.getElementById('ec_ri');
		var chart2 = echarts.init(chartDom2);
		var score_range = [];
		var score_arr = [];
		var option2;
		option2 = {
			grid: {
				left: '0%',
				right: '4%',
				top: "20%",
				bottom: '3%',
				containLabel: true
			},
			tooltip: {
				trigger: 'axis',
				axisPointer: {
					type: 'shadow'
				}
			},
			xAxis: {
				type: 'category',
				axisLabel: {
					interval: 0,
					rotate: 45
				},
				data: score_range
			},
			yAxis: {
				type: 'value'
			},
			series: [{
				barWidth: "20%",
				data: score_arr,
				type: 'bar',
				itemStyle: {
					borderRadius: [5, 5, 0, 0],
					color: function(params) {
						return colorList[params.dataIndex % colorList.length]
					}
				},
				label: {
					show: true,
					position: 'top',
				},
			}]
		}
		option2 && chart2.setOption(option2);

12. 点击切换日期事件,可以看到,我们右上角有按日、按周、按月、自定义来搜索查询数据,那么点击这个会重新按照日期查询数据,这里也需要调用我们获取时间区间的js方法

,

$(".ec_lehelist").on("click", function(event) { //登记人数筛选事件
			var target = event.target;
			if (target.className == "ec_litem") {
				var index = target.getAttribute("data-index");
				$('.ec_litem').removeClass("ec_iac");
				$(target).addClass("ec_iac");
				var return_data = [];
				if (index == "1") { //按日
					$('#begWdateId').val(getCurrentDate());
					$('#endWdateId').val(getCurrentDate());
				} else if (index == "2") { //按周
					$('#begWdateId').val(getMondayDate());
					$('#endWdateId').val(getSundayDate());
				} else if (index == "3") { //按月
					$('#begWdateId').val(getFirstDayOfMonth());
					$('#endWdateId').val(getLastDayOfMonth());
				} else if (index == "4") { //自定义
					return
				} else { //全部
					$('#begWdateId').val('');
					$('#endWdateId').val('');
				}
				areaSts();
			}
		});

$(".ec_lehelist2").on("click", function(event) { //总分分数段统计筛选事件
			var target = event.target;
			if (target.className == "ec_litem2") {
				var index = target.getAttribute("data-index");
				$('.ec_litem2').removeClass("ec_iac");
				$(target).addClass("ec_iac");
				if (index == "1") { //按日
					$('#begWdateScore').val(getCurrentDate());
					$('#endWdateScore').val(getCurrentDate());
				} else if (index == "2") { //按周
					$('#begWdateScore').val(getMondayDate());
					$('#endWdateScore').val(getSundayDate());
				} else if (index == "3") { //按月
					$('#begWdateScore').val(getFirstDayOfMonth());
					$('#endWdateScore').val(getLastDayOfMonth());
				} else if (index == "4") { //自定义
					return
				} else { //全部
					$('#begWdateScore').val('');
					$('#endWdateScore').val('');
				}
				scoreSts();
			}
		});

13. 统计日期插件

//总分统计-自定义时间
		laydate.render({
			elem: '#cur_bar2_input_time',
			eventElem: '#cur_bar2_time',
			type: 'date',
			range: true,
			done: function(value, date, endDate) { //自定义选择
				if (!WisEmpty(value)) {
					var dateArr = value.split(" - ");
					$('#begWdateScore').val(dateArr[0]);
					$('#endWdateScore').val(dateArr[1]);
					scoreSts();
				}
			}
		});

14. 加载图表方法

function throttle(fun, delay) {
			let last, deferTimer;
			return function(args) {
				let that = this;
				let _args = arguments;
				let now = +new Date();
				if (last && now < last + delay) {
					clearTimeout(deferTimer);
					deferTimer = setTimeout(function() {
						last = now;
						fun.apply(that, _args);
					}, delay);
				} else {
					last = now;
					fun.apply(that, _args);
				}
			};
		}

		window.addEventListener("resize", throttle(threize, 100));
		function threize() {
			chart1.resize();
			chart2.resize();
		}

15. 点击设置分数段按钮,请求后台,查询已经设置的分数段,用于回显,这里需要自己写方法,同时增加删除方法

var sc_arr = [];
		$(".chheadti").on("click", function() {
			sc_arr = [];
			$.ajax({
				url: '获取已存在的数据',
				type: "post",
				async: false,
				data:{
					projectId: '${projectId}',
				},
				dataType: "json",
				success: function (data) {
					var dateCode = data.code;
					if (dateCode == '0') {
						var date = data.result;
						$('.scoocece').text('');
						$('.showdomarri').text('');
						for (var index = 0; index < date.length; index++) {
							var value =  date[index].selectText;
							var id =  date[index].selectValue;
							var str = $('<div class="scoceitem"style=left:' + (value - 6) +
									'px; title="' + value + '">' + '<div class="scoceihe">' + '' +
									'<img class="scocei2" src="${pageContext.request.contextPath}/resources/enroll/img/scoi2.png" alt="" />' + '' +
									'<span class="scoceite1">' + value + '</span>' + '' +
									'</div> </div>');
							var str2 = $('<div class="sdomitem">' + '' +
									'<span>' + value + '</span>' + '' +
									'<img class="sdomiclose" id="'+id+'" data-value="'+value+'" src="${pageContext.request.contextPath}/resources/enroll/img/scoclose.png" alt="" />' + '' +
									'</div>');

							$(".scoocece").append(str);
							$(".showdomarri").append(str2);
							sc_arr.push(value);
							str2.find(".sdomiclose").on("click", function(e) {
								var index = layer.load("删除中...", {time: -1, shade: [0.5, '#999'], scrollbar: false, offset: '40%'});
								var elementId = e.target.id;
								//删除
								$.ajax({
									url: '删除方法',
									type: "post",
									async: false,
									data:{
										projectId: '${projectId}',
										id:elementId,
									},
									dataType: "json",
									success: function (data) {
										layer.close(index);
										var dateCode = data.code;
										if (dateCode == '0') {
											layer.msg("删除成功");
											var target = $(e.target);
											var parel = target.parent();
											for (var i = 0; i < sc_arr.length; i++) {
												if (sc_arr[i] == parel.text()) {
													sc_arr.splice(i, 1);
													$(".scoceitem").eq(i).remove();
													target.parent().remove();
													return
												}
											}
										} else if (dateCode == '1') {
											layer.msg(data.msg);
										}
									},
									error: function (data) {
										layer.close(index);
										layer.msg("请求失败,请稍后重试...");
									}
								});
							})
						}
						$(".scopopcon").show();
					} else if (dateCode == '1') {
						layer.close(index);
						layer.msg(data.msg);
					}
				},
				error: function (data) {
					layer.close(index);
					layer.msg("请求失败,请稍后重试...");
				}
			});
		})

		var progress = $(".scoocece").width();
		$(".scoocece").css({
			"width": progress - 2
		});
		 
		$(".scoobo").on("click", function(e) {
			var target = e.target;
			if (target.tagName == "BUTTON") {
				if (target.className == "scoobobtn btn2") {
					scoreSts();
				}
				$(".scopopcon").hide();
			}
		})

16. 点击新增保存按钮,会验证是否重复,这里限制了只能保存9个,如果不需要,可以放开

$(".sheribtn").on("click", function() {
			var index = layer.load("保存中...", {time: -1, shade: [0.5, '#999'], scrollbar: false, offset: '40%'});
			if (sc_arr.length < 9) {
				var val = parseFloat($(".sheriinput").val());
				if (val >= 0 && val <= progress) {
					var value = parseFloat(val.toFixed(1));
					for (var i = 0; i < sc_arr.length; i++) {
						if (sc_arr[i] == value) {
							layer.close(index);
							layer.msg('请勿设置重复分数节点');
							return
						}
					}
					// 使用 AJAX 保存数据
					$.ajax({
						url: '保存方法',
						type: "post",
						async: false,
						data:{
							projectId: '${projectId}',
							score:val,
						},
						dataType: "json",
						success: function (data) {
							var dateCode = data.code;
							if (dateCode == '0') {
								layer.close(index);
								layer.msg('保存成功!');
								$(".sheriinput").val("");
								var id = data.result.id;
								var str = $('<div class="scoceitem"style=left:' + (value - 6) +
										'px; title="' + value + '">' + '<div class="scoceihe">' + '' +
										'<img class="scocei2" src="${pageContext.request.contextPath}/resources/enroll/img/scoi2.png" alt="" />' + '' +
										'<span class="scoceite1">' + value + '</span>' + '' +
										'</div> </div>');

								var str2 = $('<div class="sdomitem">' + '' +
										'<span>' + value + '</span>' + '' +
										'<img class="sdomiclose" id="'+id+'" data-value="'+value+'" src="${pageContext.request.contextPath}/resources/enroll/img/scoclose.png" alt="" />' + '' +
										'</div>');

								$(".scoocece").append(str);
								$(".showdomarri").append(str2);
								if (sc_arr.length === 0) {
									sc_arr.push(value);
								} else {
									var i = sc_arr.length - 1;
									while (i >= 0 && sc_arr[i] > value) {
										sc_arr[i + 1] = sc_arr[i];
										$(".scoceitem").eq(i + 1).insertBefore($(".scoceitem").eq(i));
										$(".sdomitem").eq(i + 1).insertBefore($(".sdomitem").eq(i));
										i--;
									}
									sc_arr[i + 1] = value;
								}
								str2.find(".sdomiclose").on("click", function(e) {
									var index = layer.load("删除中...", {time: -1, shade: [0.5, '#999'], scrollbar: false, offset: '40%'});
									var elementId = e.target.id;
									//删除
									$.ajax({
										url: '${pageContext.request.contextPath}/enroll/enEnrollScoreInterval/ajaxDelete',
										type: "post",
										async: false,
										data:{
											projectId: '${projectId}',
											id:elementId,
										},
										dataType: "json",
										success: function (data) {
											layer.close(index);
											var dateCode = data.code;
											if (dateCode == '0') {
												layer.msg("删除成功");
												var target = $(e.target);
												var parel = target.parent();
												for (var i = 0; i < sc_arr.length; i++) {
													if (sc_arr[i] == parel.text()) {
														sc_arr.splice(i, 1);
														$(".scoceitem").eq(i).remove();
														target.parent().remove();
														return
													}
												}
											} else if (dateCode == '1') {
												layer.msg(data.msg);
											}
										},
										error: function (data) {
											layer.close(index);
											layer.msg("请求失败,请稍后重试...");
										}
									});
								})
							} else if (dateCode == '1') {
								layer.close(index);
								layer.msg(data.msg);
							}
						},
						error: function (data) {
							layer.close(index);
							layer.msg("请求失败,请稍后重试...");
						}
					});
				} else {
					layer.close(index);
					layer.msg('请输入“0~' + progress + '”之间的整数');
					return
				}
			} else {
				layer.close(index);
				layer.msg('最多设置9个节点');
				return
			}
		});

17. 点击确定按钮,会调用scoreSts()刷新数据,同时隐藏弹出层

$(".scoobo").on("click", function(e) {
			var target = e.target;
			if (target.tagName == "BUTTON") {
				if (target.className == "scoobobtn btn2") {
					scoreSts();
				}
				$(".scopopcon").hide();
			}
		})

18. 后台代码 : 首先写一个入口,将项目id传递到页面上,然后页面加载时,调用ajax,根据项目id查询数据,如果没有项目id,可以不传参

 @RequestMapping("/toNewLdkb/{projectId}")
    public String doNewLdkb(@PathVariable Long projectId, Model model) throws Exception {
        this.calculatePagedInfo();
        EntityFilter ef = getEntityFilter();
        ef.addFilter("enProject.id", projectId);
        model.addAttribute("projectId", projectId);
        return "admin/ldkb/newLdkb";
    }

19. 查询第一个图表数据,这里的方法需要自己写,查询出来数据以后,组装成map格式,用于页面显示

  @RequestMapping(value = "/getAreaNumSts/{projectId}")
    @ResponseBody
    public JsonObjectResult doGetAreaNumSts(@PathVariable Long projectId) throws ApplicationException, SystemException {
        JsonObjectResult result = new JsonObjectResult();
        if (projectId == null) {
            result.setCode(PlatformConsts.RESULT_CODE_PARAMS_NULL);
            return result;
        }
        EntityFilter ef = getEntityFilter();
        ef.addFilter("enProject.id", projectId);
    	//TODO 这里需要自己查询数据
        List<EnEnrollDomain> resultList = enEnrollService.doGetFilterList(null, null, null, null);
        Map<String, Integer> map = new HashMap<>();
        //统计区域人数
        if (CollectionUtils.isNotEmpty(resultList)) {
            for (EnEnrollDomain enEnrollDomain : resultList) {
                //默认地区展示
                String name = enEnrollDomain.getSchoolArea();
                if (!StringUtils.isNullString(schoolArea)) {
                    //地区不为空,则展示学校
                    name = enEnrollDomain.getSchoolName();
                }
                Integer num = map.get(name);
                if (num == null) {
                    num = 1;
                } else {
                    num++;
                }
                map.put(name, num);
            }

            //排序
            // 将HashMap的键值对转换为List
            List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
            // 使用Collections.sort对List进行排序
            list.sort(Map.Entry.comparingByValue());
            // 创建一个LinkedHashMap,保持排序后的键值对的插入顺序
            Map<String, Integer> sortedMap = new LinkedHashMap<>();
            for (Map.Entry<String, Integer> entry : list) {
                sortedMap.put(entry.getKey(), entry.getValue());
            }
            result.setResult(map);
        }
        return result;
    }

20. 组装分数,查询的数据自己根据实际情况编写,如有需要,可以私信要 源码

这里面组装的逻辑是,如果是没有设置分数段,就按照最高分和最低,平均分成10分,如果设置了分数段,就按照分数段来统计数量。

 @RequestMapping(value = "/getScoreSts/{projectId}")
    @ResponseBody
    public JsonObjectResult doGetScoreSts(@PathVariable Long projectId, String scoreType) throws ApplicationException, SystemException {
        JsonObjectResult result = new JsonObjectResult();
        if (projectId == null) {
            result.setCode(PlatformConsts.RESULT_CODE_PARAMS_NULL);
            return result;
        }
        EntityFilter ef = getEntityFilter();
        ef.addFilter("enProject.id", projectId);
        //TODO 这里需要自己去写查询方法
        List<EnEnrollDomain> resultList = enEnrollService.doGetFilterList(null, null, null, null);
        if (CollectionUtils.isEmpty(resultList)) {
            return result;
        }
        //TODO 这部分就是组装数据,格式是map,key :100-200,value :20 。key是区间,比如100-200,value是这个区间的人数,比如20人,
        //统计分数人数1、先获取最低分、最高分、未登记人数
        Integer notEnrollNum = 0;
        List<Double> scoreList = new ArrayList<>();
        for (EnEnrollDomain enEnrollDomain : resultList) {
            EnEnrollScoreDomain scoreDomain = enEnrollDomain.getScoreDomain();
            if (null == scoreDomain) {
                notEnrollNum++;
                continue;
            }
            //分数类型如果是一模,就获取一模总分,否则获取中考总分
            Double scoreAll = "0".equals(scoreType) ? scoreDomain.getFirstScoreAll() : scoreDomain.getMidtermExamScoreAll();
            if (scoreAll != null) {
                scoreList.add(scoreAll);
            } else {//未登记分数
                notEnrollNum++;
            }
        }
        Map<String, Integer> map = new LinkedHashMap<>();
        if (CollectionUtils.isNotEmpty(scoreList)) {
            //排序
            Collections.sort(scoreList);
            //根据项目id 查询对应的分数区间
            List<EnEnrollScoreIntervalDomain> enEnrollScoreIntervalDomains = enEnrollScoreIntervalService.doGetListByProjectIdAndScore(projectId, null);
            //如果未设置分数段,就保持原来的
            if (CollectionUtils.isEmpty(enEnrollScoreIntervalDomains)) {
                //最小值
                double lowScore = ListUtil.getFirstData(scoreList);
                //向下取整
                int lowScoreInt = (int) Math.floor(lowScore);
                //最大值
                double highScore = scoreList.get(scoreList.size() - 1);
                //最大减去最小
                double interval = BigDecimalUtil.subtractDouble(highScore, lowScoreInt);
                int groupNum = interval > 10 ? 10 : (int) interval;
                if (groupNum < 1) {
                    groupNum = 1;
                }
                double averageNum = interval / groupNum;
                //向上取整
                int averageNumInt = (int) Math.ceil(averageNum);
                for (int i = 0; i < groupNum; i++) {
                    //区间最小值
                    int scoreOld = lowScoreInt;
                    //区间最大值
                    lowScoreInt = lowScoreInt + averageNumInt;
                    map.put(scoreOld + "-" + lowScoreInt, 0);
                }
            } else {
                for (int index = 0; index < enEnrollScoreIntervalDomains.size(); index++) {
                    int size = enEnrollScoreIntervalDomains.size();
                    EnEnrollScoreIntervalDomain enEnrollScoreIntervalDomain = enEnrollScoreIntervalDomains.get(index);
                    String key = "";
                    Long maxScore = 700L;
                    Long score = enEnrollScoreIntervalDomain.getScore();
                    if (index == size - 1) {
                        if (score.equals(maxScore)) {
                            continue;
                        }
                        key = score + "-" + maxScore;
                    } else {
                        key = score + "-" + enEnrollScoreIntervalDomains.get(index + 1).getScore();
                    }
                    map.put(key, 0);
                }
            }
            if (MapUtils.isNotEmpty(map)) {
                int index = 1;
                int allNum = 0;
                for (Map.Entry<String, Integer> entry : map.entrySet()) {
                    String key = entry.getKey();
                    String[] keyArr = key.split("-");
                    double scoreOld = Double.parseDouble(keyArr[0]);
                    double score = Double.parseDouble(keyArr[1]);
                    Integer num = 0;
                    for (int i = 0; i < scoreList.size(); i++) {
                        //modify by chenqian at 2024/4/22 15:16 : 前面的数据是含头不含尾,循环到最后分数区间时,需要前后都包含
                        num = entry.getValue();
                        if (index == map.size()) {
                            if (scoreOld <= scoreList.get(i) && scoreList.get(i) <= score) {
                                num++;
                                entry.setValue(num);
                            }
                        } else {
                            if (scoreOld <= scoreList.get(i) && scoreList.get(i) < score) {

                                num++;
                                entry.setValue(num);
                            }
                        }
                    }
                    index++;
                    allNum += num;
                }
                //判断一下不在分数段内的数据
                if (allNum != scoreList.size()) {
                    map.put("不在分数段内", scoreList.size() - allNum);
                }
            }
        }
        if (notEnrollNum != 0) {
            map.put("未登记分数", notEnrollNum);
        }
        result.setResult(map);
        return result;
    }

21.js日期查询中需要用到的js日期方法,这些方法在其他代码中也可以用到,可以封装成单独的js,以便后面调用

//获取本周一时间(年-月-日)
function getMondayDate() {
	// 获取当前时间
	var currentDate = new Date();

// 获取当前日期的年、月、日
	var year = currentDate.getFullYear();
	var month = currentDate.getMonth();
	var date = currentDate.getDate();

// 获取当前日期的星期几(0表示周日,1表示周一,以此类推)
	var dayOfWeek = currentDate.getDay();

// 计算本周的周一和周日的日期
	var firstDayOfWeek = new Date(year, month, date - dayOfWeek + 1);

// 格式化日期为指定格式
	var formatDate = function (date) {
		var year = date.getFullYear();
		var month = date.getMonth() + 1;
		var day = date.getDate();

		month = month < 10 ? '0' + month : month;
		day = day < 10 ? '0' + day : day;

		return year + '-' + month + '-' + day;
	};

// 获取本周周一的时间
	var monday = formatDate(firstDayOfWeek);
	return monday;
}

//获取本周日时间(年-月-日)
function getSundayDate() {
	// 获取当前时间
	var currentDate = new Date();

// 获取当前日期的年、月、日
	var year = currentDate.getFullYear();
	var month = currentDate.getMonth();
	var date = currentDate.getDate();

// 获取当前日期的星期几(0表示周日,1表示周一,以此类推)
	var dayOfWeek = currentDate.getDay();

// 计算本周的周一和周日的日期
	var lastDayOfWeek = new Date(year, month, date + (7 - dayOfWeek));

// 格式化日期为指定格式
	var formatDate = function (date) {
		var year = date.getFullYear();
		var month = date.getMonth() + 1;
		var day = date.getDate();

		month = month < 10 ? '0' + month : month;
		day = day < 10 ? '0' + day : day;

		return year + '-' + month + '-' + day;
	};

// 获取本周周一的时间
	var sunday  = formatDate(lastDayOfWeek);
	return sunday;
}

// 获取本月的第一天
function getFirstDayOfMonth() {
	var today = new Date();
	var firstToday = new Date(today.getFullYear(), today.getMonth(), 1);
	var formattedDate = `${firstToday.getFullYear()}-${(firstToday.getMonth() + 1).toString().padStart(2, '0')}-${firstToday.getDate().toString().padStart(2, '0')}`;
	return formattedDate;
}

// 获取本月的最后一天
function getLastDayOfMonth() {
	var today = new Date();
	var nextMonth = today.getMonth() + 1;
	var lastDay = new Date(today.getFullYear(), nextMonth, 0);
	var formattedDate = `${lastDay.getFullYear()}-${(lastDay.getMonth() + 1).toString().padStart(2, '0')}-${lastDay.getDate().toString().padStart(2, '0')}`;
	return formattedDate;
}

页面部分代码齐全,后台代码只提供了controller部分,逻辑层需要自己写,有疑问欢迎私信

代码及样式地址 :https://download.csdn.net/download/qq_43690135/89276092

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉梦lm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值