jqgird的使用和jquery的ajax请求

上效果图吧
结果图例
Jqgrid框架用于数据展示的纯前端开发
除了查询之外的所有操作。包含
分页,分组,以及模糊查询,汇总等等。这算是上个星期的战绩了。
鉴于我对前端一点都不了解也不会用,用一个星期摸索了一下。先提供两个网页。

一个字典https://www.cnblogs.com/firstcsharp/p/5150552.html

一个示例https://jeesite.gitee.io/front/jqGrid/4.7/jqgridjs/index.html

现在解释一个例子

<% layout('/layouts/default.html', {title: '项目绩效分派管理', libs: ['dataGrid']}){ %>
//前后端不分离 写过jsp应该都知道,固定头部样式。不喜欢直接干掉重启就好了。
<div class="main-content">
	//这些class的样式是啥我也不知道,随便吧。反正前端就是抄抄抄。我暂时写不出什么css和好的js
	<div class="box box-main">
		<div class="box-body">
			//一种特定的控件,可以通过模型访问回指定的数据。
			<#form:form id="searchForm" model="${SearchFpjj}" action="${ctx}/xm/xmFpjj/listAll" method="post"
			class="form-inline hide"
			data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}"
			data-order-by="${parameter.orderBy}">
		</div>
	</div>
<!--	<div class="control-inline width-240">-->
	<div class="box-tools pull-left">
		<div class="form-group">
			<label class="control-label">${text('项目名称')}</label>
				<#form:select id="test" itemLabel="xmName" width='500'  itemValue="id" class="form-control" blankOption="true" />
<!--			<input id="searchstr" class="input-circle-bottom"> </input>-->
<!--			<button id="search_btn" class="buttonFinish" >查找</button>-->
		</div>
	</div>
<!--	<button type="button" class="layui-btn layui-btn-warm layui-btn-radius">暖色按钮</button>-->
		//一个datagrid 和一个 datagridpager用于分页
		<table id="dataGrid" cellpadding="0" cellspacing="0">
		</table>
		<div id="dataGridpager"></div>
</div>
<% }} %>
//这里基本结束了需要的html控件,一下为js的内容。先行百度一下jqgrid
<script>
	//查询测试 用于控件选择自动滑轮到指定的datagridview具体特效自行测试。
	$('#test').change(function () {

		// var div = $('#dataGrid').closest('.ui-jqgrid-bdiv')[0]//
		// 		, scrollHeight = div.scrollHeight, scrollTop = 0;
		// div.scrollTop = 250;

		var serach_name = $("#test :selected").text();
		var xz_obj = $("#dataGrid");
		var i = -1;
		if (xz_obj.length != 0) {
			var name = xz_obj.find("td:eq(3)").html();
			if (name == serach_name) {
				i = xz_obj.index();
			}
		}
		var xzzz_obj = 0;
		var jj = 0;
		$("#dataGrid").find("tr").each(function (key, value) {
			var name = $(this).find("td:eq(3)").html();
			if (name == serach_name) {
				if (xzzz_obj == 0) {
					xzzz_obj = $(this);
					jj++;
				}
			}
			if (name == serach_name && key > i) {
				xzzz_obj = $(this);
				jj++;
				return false;
			}
		});
		 if (jj == 0) {
		 	return false;
		 }
		list_item_postion($("#dataGrid"), xzzz_obj, 'tr', 1);
		just_select(xzzz_obj);
	})

	//测试
	var div = $('#dataGrid').closest('.ui-jqgrid-bdiv')[0]//
			, scrollHeight = div.scrollHeight, scrollTop = 0;
	var timer= setInterval(function () {
		scrollTop += 5;
		div.scrollTop = scrollTop;
		if (scrollTop >= scrollHeight) clearInterval(timer);//滚动到底部,释放计时器
	}, 100);

	//定位移动
	function list_item_postion(parent_e, self_e, e, number) {
		var weizhi = self_e.index();
		var heigth = 0;
		for (var i = 0; i < weizhi; i++) {
			heigth += parent_e.find("" + e + ":eq(" + i + ")").height();
		}
		heigth /= number;
		console.log("number" + heigth)
		 var div = $('#dataGrid').closest('.ui-jqgrid-bdiv')[0]//
				, scrollHeight = div.scrollHeight, scrollTop = 0;
		div.scrollTop = heigth-30;

	//	$('#dataGrid').self_e.index().highlight();
			//parent_e.scrollTop(heigth);
	}
	

	//合并标头单元格函数
	function Merger(gridName, CellName) {

		//得到显示到界面的id集合
		var mya = $("#" + gridName + "").getDataIDs();
		//数据总行数
		var length = mya.length;
		//定义合并行数
		var rowSpanTaxCount = 1;
		var a = "";
		for (var i = 0; i < length; i += rowSpanTaxCount) {
			//从当前行开始比对下面的信息
			var before = $("#" + gridName + "").jqGrid('getRowData', mya[i]);
			rowSpanTaxCount = 1;

			for (j = i + 1; j <= length; j++) {
				//和上边的信息对比 如果值一样就合并行数+1 然后设置rowspan 让当前单元格隐藏
				var end = $("#" + gridName + "").jqGrid('getRowData', mya[j]);
				if (before[CellName] == end[CellName]) {
					rowSpanTaxCount++;
					$("#" + gridName + "").setCell(mya[j], CellName, '', {display: 'none'});
				} else {
					break;
				}
				a = mya[j];
			}
			$("#" + gridName + "").setCell(mya[i], CellName, '', '', {rowspan: rowSpanTaxCount});

			$("#test").append("<option value='Value'>" + before[CellName] + "</option>");
		}
	}
	// 初始化DataGrid对象
	$('#dataGrid').dataGrid({
		searchForm: $("#searchForm"),
		useColSpanStyle: true,
		cellEdit: true,
		cellsubmit: 'remote',
		cellurl: '${ctx}/xm/xmFpjj/save',
		// scroll:true,
		afterSaveCell:function(rowid, cellname, value, iRow, iCol){
			layer.confirm('确认更改参数为'+value, {icon: 3, title:'提示'}, function(index){
				layer.close(index);
			})
		},
		beforeSubmitCell: function (rowid, cellname, value, iRow, iCol) {
			//$('#dataGrid').jqGrid().trigger("reloadGrid");
			return {
				"ProjectId": $("#dataGrid").getCell(rowid, "project_id"),
				"XmRewardnum": value,
				"XmZxr": $("#dataGrid").getCell(rowid, "xm_zxr")
			};
		},
		caption: " 项目绩效分派管理",
//填充数据
		columnModel: [
			{
				header: '${text("项目ID")}',
				name: 'project_id',
				index: 'a.project_id',
				width: 300,
				height: 100,
				align: "Center",
				frozen: true,
				hidden: true
			},
			{
				header: '${text("总得分")}',
				name: 'sum_num',
				index: 'a.sum_num',
				width: 150,
				height: 100,
				align: "Center",
				summaryType: 'sum'
			},
			{header: '${text("参考系数")}', name: 'tj_tj', index: 'a.tj_tj', width: 150, height: 100, align: "Center"},
			{
				header: '${text("分配系数系数")}', name: 'xm_rewardNum',
				editable:true, index: 'a.xm_rewardNum', width: 150, align: "center",
			 formatter: function (value, grid, rows, state) {
					if(value==-1)
					{
						//$("#dataGrid").jqGrid("editRow", grid.rowID,{ keys: true});
						// this.editable=false;
						// grid.editable=false;
						// rows.editable=false;
						// editable=false;
						return " ";
					}
					else
					{
						return value;
					}
				},

				summaryType:function (value, grid, rows, state) {
					//return '<button class=\'btn btn-sm btn-primary\'>    提交 </button>';
					return '<button type=\"button\" class=\"layui-btn layui-btn-warm layui-btn-radius\">提交</button>';
				}
				//,formatter:function(value, grid, rows, state){}
			}

		],
//分页
// 		loadonce: true,
// 		viewrecords: true,
// 		width: 780,
// 		height: 200,
// 		rowNum: 15,
// 		pager: "#dataGridpager",
		//分组
		sortname: 'project_id',
		grouping: true,
		groupingView: {
			groupField: ["xm_name"],
			groupSummary: [true],
			groupColumnShow:[true,true,true,true,true],
			groupText: ['<b>{0}</b> '],
			groupCollapse: false
		},


		gridComplete: function () {
			//在gridComplete调用合并方法
			Merger("dataGrid", 'xm_name'); 
		},//合并项目单元格
		// 加载成功后执行事件
		ajaxSuccess: function (data) {
		},
	
	})
	//确认处理
	function savebtn(date){
		//拼接请求数据,开始发送ajax请求
		var obj = {'ProjectId':date.id,'XmZxr':date.name};
		if(date.name=="1")
		{
			return ;
		}
		layer.confirm('确认提交将无法更改?', {icon: 3, title:'提示'}, function(index){
			layer.close(index);
		})
		//使用ajax将请求发布上去,实现拒不刷新。
		$.ajax({
			type:'post',
			url:'${ctx}/xm/xmFpjj/confirm',
			data:obj,
			cache:false,
			dataType:'json',
			success:function(data){
				var btn='#'+obj['ProjectId'];
				$(btn).text("已设定");
				$(btn).name="1";
				$(btn).click=null;
				$(btn).unbind() ; 
}
		});

	}
	//设置二级表头
	jQuery("#dataGrid").jqGrid('setGroupHeaders', {
		useColSpanStyle: true,
		groupHeaders: [
			{startColumnName: 'source1', numberOfColumns: 5, titleText: '<br>任务完成情况</br>'}
		]
	})
</script>

很长的一个例子是我这个星期用这个控件去做的一个效果
然后现在我要一一解说这些效果
先说数据填充,这里使用的jeesite框架
先说说为啥用jeesite吧,就一个字快。
再说说为啥用jqgrid吧,还是一个字快。你自己去实现这些效果试试,尤其是对一个后端熟悉前端比较懵逼的程序员。还是差不多能用就好。这个好看,换个数据源什么的好得多。
知识点如下:
数据来源于一个叫
Form表单 取得方式是通过form表单得到指定数据。
后端代码

/**
	 * 查询列表数据
	 */
	@RequiresPermissions("xm:xmFpjj:view")
	@RequestMapping(value = "listAll")
	@ResponseBody
	public List<Map<String, Object>> listData(SearchFpjj searchFpjj, HttpServletRequest request, HttpServletResponse response) {
		List<Map<String, Object>> page = xmFpjjService.findPage(UserUtils.getUser().getId());
		return page;
	}

返回的是一个json的page
当然由于比较生疏,这里直接查了所有的数据,强行进行了前端的分页分组分项目。做了一个假定位。
功能需求,统计,汇总,判断,插入删除等等。
数据库语句上文有提及。
解封之后的数据,直接用于datagridview的填充。效果一目了然。

jQuery("#dataGrid").jqGrid('setGroupHeaders', {
		useColSpanStyle: true,
		groupHeaders: [
			{startColumnName: 'source1', numberOfColumns: 5, titleText: '<br>任务完成情况</br>'}
		]
	})

先讲讲这个 意思是从第几行开始,一共几行,给头填上效果
效果如图。

$.ajax({
			type:'post',
			url:'${ctx}/xm/xmFpjj/confirm',
			data:obj,
			cache:false,
			dataType:'json',
			success:function(data){
				var btn='#'+obj['ProjectId'];
				$(btn).text("已设定");
				$(btn).name="1";
				$(btn).click=null;
				$(btn).unbind() ; 
}

这段是去修改该段的数据,效果是,单单元格编辑完成,就去修改该库内容。

@RequiresPermissions("xm:xmFpjj:edit")
	@PostMapping(value = "confirm")
	@ResponseBody
	public String confirm(String ProjectId,String XmZxr) {

		XmFpjj xmFpjj=new XmFpjj(ProjectId,XmZxr);
		xmFpjj.setXmYtj(1);
		long  x=xmFpjjService.selectExist(xmFpjj);
		if(x!=1)
		{
			return renderResult(Global.FALSE, text("此项不存在,请先输入分配系数!"));
		}
		if(xmFpjjService.selectDefine(xmFpjj)>0)
		{
			return renderResult(Global.FALSE, text("无法更改已确认项!"));
		}
		xmFpjjService.save(xmFpjj);

		return renderResult(Global.TRUE, text("保存xm_fpjj成功!"));
	}

这是修改的返回示意。
不用AJAX确实很难实现页面的灵活交互。
用如下两段说明colmodel这里的东西怎么用

{
				header: '${text("总得分")}',
				name: 'sum_num',//通过名字访问到json的指定键
				index: 'a.sum_num',
				width: 150,
				height: 100,
				align: "Center",
				summaryType: 'sum'//汇总统计的时候该列显示的数据,有count,sum,ave等,具体参考上文
			},
			{header: '${text("参考系数")}', name: 'tj_tj', index: 'a.tj_tj', width: 150, height: 100, align: "Center"},
			{
				header: '${text("分配系数系数")}', name: 'xm_rewardNum',
				editable:true,//需要注意这个属性,必须配合头部的editcell一起使用。

这就是这个空间神奇的地方。如editable:true需要配合头属性cellEdit: true,使用summaryType必须配合grouping来使用,如果没有分组,该字段毫无意义。
index: ‘a.xm_rewardNum’, width: 150, align: “center”,
//这个formatter属性可以使function作为返回字段,便提供了无数可能,可以写事件,可以写控件,你能想到的都可以。返回内容直接显示在单元格中。

	 formatter: function (value, grid, rows, state) {
					if(value==-1)
					{
						
						return " ";
					}
					else
					{
						return value;
					}
				},

				summaryType:function (value, grid, rows, state) {
					//return '<button class=\'btn btn-sm btn-primary\'>    提交 </button>';
					return '<button type=\"button\" class=\"layui-btn layui-btn-warm layui-btn-radius\">提交</button>';
				}
				//,formatter:function(value, grid, rows, state){}
			}

然后jqgridview控件,前文中主要使用了三个功能。
比较复杂的一个是联动滚轮,用下拉框去选择指定的项目,自然滑动到该项目,代码见上文。
实现部分需要自行抽离。
然后还有自带的分页,分组。
sortname: 'project_id',
		grouping: true,
		groupingView: {
			groupField: ["xm_name"],
			groupSummary: [true],
			groupColumnShow:[true,true,true,true,true],
			groupText: ['<b>{0}</b> '],
			groupCollapse: false
		},分组。
分页配置头属性就自行分页了。当然这是前段的伪分页,和后端一点关系没有。
loadonce: true,
 		viewrecords: true,
 		width: 780,
 		height: 200,
 		rowNum: 15,
		pager: "#dataGridpager"

只有有必要的是讲一下这个生命周期的概念。就是从表格生产,渲染,呈现,结束的整个过程作为一个生命周期,任何类,包括数据库都拥有这个一个过程,如果无法理解生命周期这个概念,那么真的只是搬运工了。
在指定的生命周期,生产代码,代码的意义才有充分体现。

layer.confirm('确认提交将无法更改?', {icon: 3, title:'提示'}, function(index){
			layer.close(index);

这是一个layer的控件的内容,一个确认框。很多东西借助前端框架就很舒服了,程序员懂点定位,然后知道ajax基本啥都能写了。至于什么设计,其实老实说,不是每个人都是画家,对光和色的掌握很深刻,大多数人包括我,对于前端,就是看看,知道有这么个颜色在,有一天想用,去瞅瞅,看见啥好看就用啥。我就是这样对待前段的。

在这里顺便提及一下前后端分离,和前后端不分离这个概念。

以下都是个人理解,可能网上有雷同的部分,毕竟大家理解相差不大才对。
根据本质不同,应该会有两种理解,一种理解是,将
M层交给后端去控制,VC层交给前端去控制。这样去实现这个前后端分离。
这样的分离,指代的是代码员责任的分离,对于一个项目,或者一个工程,可以有利于后期的维护,运行。这样的结构,基本都是基于一些jsp,asp,或者新的引擎类似于beetl等。而我用的这个就用到了beetl严格意义上来说,这种都算是伪分离,只是从责任块进行了区分,但是没有从技术块进行区分 ,无法解决代码混乱,无法维护的问题。
举个例子,今天后端的哥们不舒服,跟负责前端的兄弟说,兄弟,我就查出来,sevice层我就不写了,你去搞一下。然后这就是某个例子。接下来项目的问题只会越来越多。如果公司是一个规模不大,管生不管养,管用不管维护的公司,这么做其实问题一点都没有。而我就在一个这样的公司,可能管养,不行就请人,做不来就换人,再不行,就这里补补哪里贴贴,你后人想用,门都没有。源码就是一堆没有用的垃圾,写得越久,项目越垃圾。不是说代码架构有问题,而是举个例子,我今天发现前端有一个架构能够帮助我快速实现一个功能,我就侧重前段去写,今天我发现后端有一个模式比较符合我的开发,我就去干了一个后端。而这样的代码,无论是纯前端,纯后端都看不懂,而且会把代码员引入前不通,后不通的境地,写来写去,啥规范都没了,还有一个名称,叫面对项目的攻城狮。我其实是非常反感这种形式。所以我打算以后尽可能自己去进行前后端分离,哪怕进度慢,吵我鱿鱼,我也要保证,我的代码在control层改一个接入,完全可以当resful用。
恰巧我也是一个用过,并比较热衷于前后端分离的人。 <%

if(hasPermi('project:xmlx:projectType:edit')){ %>
				actions.push('<a href="${ctx}/project/xmlx/projectType/form?treeCode='+row.treeCode+'" class="btnList" title="${text("编辑项目类型")}"><i class="fa fa-pencil"></i></a>&nbsp;');
				if (row.status == Global.STATUS_NORMAL){
					actions.push('<a href="${ctx}/project/xmlx/projectType/disable?treeCode='+row.treeCode+'" class="btnList" title="${text("停用项目类型")}" data-confirm="${text("确认要停用该项目类型吗?")}"><i class="glyphicon glyphicon-ban-circle"></i></a>&nbsp;');
				}

就看这段代码,无论你是前段还是后端,你其实都只能看懂一半。至于原理,甚至涵盖在两层。改良很虚,就更别提优化了。
然后说说真正的前后端从技术点上分离。
可以看另一段代码

  #region 插入申请清单 pgsql
        /// <summary>
        /// 插入共享清单逻辑
        /// username + uid
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        // POST: api/TaskList
        [HttpPost("insert")]
        public string PostInsert(object value)
        {
            var v = (JObject)value;
            string uid = v["uid"].ToString();
            string lid = v["lid"].ToString();
            string touid = v["touid"].ToString();
            string str = String.Format("select * from api.applylist where uid ='{0}' and lid ='{1}'and touid ='{2}'", uid, lid, touid);
            DataSet uds1 = new myPQSQL().ExecuteQuery(str);
            if (uds1.Tables[0].Rows.Count < 1)
            {
                string str2 = String.Format("INSERT INTO api.applylist( uid, lid, touid) " +
                     $"  VALUES('{uid}','{lid}','{touid}' ) ");
                int uds = new myPQSQL().ExecuteNonQuery(str2);
                return new string("[{\"result\":\"分享成功\"}]");

            }
            else
            {
                return new string("[{\"result\":\"分享失败\"}]");
            }
        }
        #endregion

        #region 删除申请清单 pgsql
        /// <summary>
        /// 删除共享清单
        /// username + uid
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        // POST: api/TaskList
        [HttpPost("delete")]
        public string PostDelete(object value)
        {
            var v = (JObject)value;
            string uid = v["uid"].ToString();
            string lid = v["lid"].ToString();
            string touid = v["touid"].ToString();
            string str = $"DELETE FROM api.applylist WHERE uid = {uid} and lid = {lid} and touid = {touid};";
            int uds1 = new myPQSQL().ExecuteNonQuery(str);
            if (uds1 <= 0)
            {
                return new string("[{\"result\":\"删除失败\"}]");
            }
            else
            {
                return new string("[{\"result\":\"删除成功\"}]");
            }
        }
        #endregion

将所有数据以统一的方式发给前端,这一个iis结合vue的项目,部署的时候也没用到IIS用的.net core 2.0的机制,打包成.exe直接运行了。
在任意一个前后端的项目中,前端或者后端的程序员都有相对足够多的时间,去讨论自己部分的源码复用性和性能问题。更有充足的时间让自己专业化,而不是停留在数据卡在那里,哪里的模型有问题等等。前端基本上来说不需要关注后端的任何一点点事。
我认为所谓的全栈,不应该是借助某种快捷通道的三脚猫,而是真正理解前后端的人,只有这样他才真正知道,代码需要的是理念和逻辑,而不是复制和黏贴。
虽然很反感这种不专业变更不专业的路线,但是为了一口饭,我决定两个月之内,吃下它,真香。
而我认为以后业界的方向,必然是真正的前后端分离。不要觉着现在的快是快,那是因为市场还是很混乱。真正的快一定是维护快,基本无错。
因为以后后端可能需要的不仅仅是关注程序本身,重要的是关注接入点,数据处理等等。前端也不仅仅关注前端本身,还需要关注,数据加载,数据可视化,缓存,以及自适应处理。技术越到后期,所要求的的脑子,永远是比双手多得多的。如果没法子自行优化自己的架构,那么其实我们都是指接几个一两万的单子,一直到死的人。不如护眼转行。做个啥,不能混口饭吃,何必拼命。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值