在一个环境监测的项目中,有这样一下新增+修改+展示+删除+统计的页面,页面中充斥着js代码和ajax代码,业务关系比较复杂。
我首先介绍一下业务的专业词汇:
点位:就是地点或位置的意思,表示一个商店、餐饮店、公园等
页面完成的功能是:选择点位信息,添加到页面;填写点位的蚊蝇鼠蟑监测数据,并对数据进行统计,计算总分;将监测数据和统计数据保存到数据库。
我们看图说话吧。
我总结一下这个页面完成的功能:
1、增加记录
点击《增加记录》按钮,弹出页面,选择增加的点位:
要求已经添加的点位,不能出现在列表中,列表支持查询操作,选择点位后,点击确认,完成选择点位操作。
2、删除记录
在页面中选择点位信息,点击《删除记录》按钮,删除页面数据(逻辑删除),并完成另外两点操作1、将点位对应的问题图片删除,2、修改点位对应的问题数量。
3、点击点位名称,进入问题图片编辑页面
问题图片编辑页面,也是一个非常复杂的页面,这里先不描述了
4、页面数据支持拖拽,调整数据顺序
这个功能需要前台js支持拖拽,我们引入jquery-ui.js,然后为每一个tr添加draggable参数,使之监听拖拽事件。
前台js
js的实现过程:在拖拽开始时,记录操作的tr,在拖拽结束时,记录指向的tr2.让tr添加到tr2的前面。所以这个拖拽只实现了添加到指定位置前的功能。有了此功能已经可以实现任何数据顺序的调整了。
//绑定拖拽事件
$("#dist tr").draggable({
helper: "clone",
start: function (event, ui) {
},
stop: function (event, ui) {
srcObj=$(this);
}
});
//在执行拖拽完成后,鼠标over事件,保存此元素
function f_tr_over(o){
//
if(srcObj!=null){
//异步提交数据到后台,保存顺序()
//console.log((srcObj.find("td:eq(1)").html())+","+( $(o).find("td:eq(1)").html()));
var ord1=srcObj.find("td:eq(1)").html();
var ord2=$(o).find("td:eq(1)").html();
var id=srcObj.find(":checkbox").val();
//将拖拽的行,移动到当前行的前面
$(o).before(srcObj);
//将拖拽行删除,不再执行移动操作
srcObj=null;
// 重排序号
f_order();
//异步提交数据到后台,保存顺序()
$.ajax({
type : "POST",
url : root + "/activity/updateOrd.do",
data : {"activity_id": $("#activity_id").val(),"id": id, "ord1":ord1,"ord2":ord2 },
dataType:"json",
success : function(data, status) {
if (data.success) {
// 操作成功后,提示如下信息
showMsg("修改顺序成功",true);
} else {
//修改顺序失败
swal({
title : "失败!",
text : "操作失败!",
type : "error"
}, function() {
location.reload();
});
}
},
error:function(){
//showMsg("修改顺序失败",false);
swal({
title : "失败!",
text : "操作失败!",
type : "error"
}, function() {
location.reload();
});
}
});
}
}
//为表格编号
function f_order(){
$.each($("#dist tr td:nth-child(2)"), function(i, item) {
$(item).html(i + 1);
});
}
后台逻辑
java后台的处理会更麻烦一些,分为两种情况,一种是向前调整,一种是向后调整,逻辑层的代码如下:
public void updateOrd(String activity_id, String id, int ord1, int ord2) {
Map m = new HashMap();
// 9->4
if (ord1 > ord2) {
// 4-8,向下移动一个位置
// update set ord=ord+1 where ord>=4 and ord<=8 and activity_id=#{activity_id}
m.put("opt", "+");
m.put("ord1", ord2);
m.put("ord2", ord1 - 1);
m.put("activity_id", activity_id);
activityDao.updateOrd1(m);
// 9更改为4
// update set ord=4 where id=#{id}
m.clear();
m.put("id", id);
m.put("ord", ord2);
activityDao.updateOrd2(m);
} else if (ord1 < ord2) {
// 4->9
// 5-8,向上移动一个位置
// update set ord=ord-1 where ord>=5 and ord<=8 and activity_id=#{activity_id}
m.put("opt", "-");
m.put("ord1", ord1 + 1);
m.put("ord2", ord2 - 1);
m.put("activity_id", activity_id);
activityDao.updateOrd1(m);
// 4->8
// update set ord=8 where id=#{id}
m.clear();
m.put("id", id);
m.put("ord", ord2 - 1);
activityDao.updateOrd2(m);
}
}
sql操作
为了实现拖拽排序,我们在数据层提供了以下的sql操作:
拖拽排序:修改排序 向上或向下移动一个位置
update em_data set ord=ord${opt}1 where delFlag=0 and ord>=#{ord1} and ord<=#{ord2} and activity_id=#{activity_id}
拖拽排序:修改排序 指定一个问题的位置
update em_data set ord=#{ord} where id=#{id}
拖拽排序:根据监测活动id取得多个原始数据id
select id from em_data where delFlag=0 and activity_id= #{activity_id} order by ord
拖拽排序:根据监测活动id取得多个原始数据id
select id from em_data where delFlag=0 and activity_id= #{activity_id} order by ord
拖拽排序:自动重新排序
${sql}
拖拽排序:检查排序是否正确
select count(1) as c from
(select ord from em_data where delFlag=0 and activity_id=#{activity_id} and (ord-1) not in (select ord from em_data where delFlag=0 and activity_id=#{activity_id} ) and ord !=1
UNION
select ord from em_data where delFlag=0 and activity_id=#{activity_id} group by ord having count(1)>1)t
超强纠错
因为担心,拖拽过程中可能出现乱序的情况,在每次打开此页面时,加入了验证排序的程序,如果发现乱序,自动生成排序编号,重新排序。
比如当前排序字段的值是1,2,2,3,4,5,6,7;经过自动排序后,第二个2会转变成3,序号为3-7的数据,序号会转换成4-8.
5、table中的数据可编辑
表格中的数据编辑,甲方要求很灵活,主要支持了以下操作
-
表格中的每一个td中,放置着一个输入框input,使用css去掉输入框的边框,使用size定义输入框的大小(可以输入的位数),再配置js的校验,要求只能输入数字。
-
在js中还要进行逻辑的验证,比如:1、阳性房间数,不能超过总房间数,2、阳性勺数,不能大于监测勺数 等
-
当表格中的数据更改时,使用ajax,对数据库数据进行修改。
-
当表格中的数据更改时,统计各项指数,按照逻辑要求,计算分值
-
当光标指向某一个输入框时,要求对应的表格头,显示为红色。这样做的目的,是为了在大显示器,大分辨率下,可以清楚的看到操作的是哪类数据。
第5条的实现代码如下,大家注意看这个jquery的选择器:
//输入框获得焦点事件
function fcs(){
$("#menu th").css("color","");
var index=$(this).parent().index();
$("#menu th:eq("+(index-4)+")").css("color","red");
}
我在这里就不展示其他代码了,大家可以想一想如何实现,都是小功能。
6、固定表格头
一页中展示27个点位信息,为了方便查看数据,甲方要求表格头是固定的,表格尾(展示统计数据)也是固定的,中间展示点位数据,可以使用滚动条,滚动展示。
-
我们通过js,页面加载完成后,动态计算了中间展示数据的高度。$(window).height()取得页面的总高度,表格头和尾,共400像素,$(window).height()-400,就是中间数据div的高度
-
这样表格被分为三个表格,每个表格放在div中,为了保证表格的列对齐,我们为每个列定义了宽度。
-
因为中间数据有滚动条,所以即使定义了列的宽度,表格列还是对不齐的,我们使用css设置把表格头的滚动条也显示出来,这样div都显示了滚动条,列就对齐了。
7、上下左右按键控制光标位置
使用上下左右按键,控制光标在各个输入框中。比如按向下的按键,光标就会从当前的输入框中,跳到下面的输入框中;按向右的按键,光标就会从当前的输入框中,跳到右边相邻的输入框中;如果按回车键,和向右的按键是一样的。
//控制按键
function ctl_key(e){
//console.log($(this)[0].tagName);
switch(e.keyCode){
case 37:
//左
if($(this).parent().prev().find(":first-child")[0].tagName=="INPUT"){
$(this).parent().prev().find(":first-child").focus();
}
break;
case 38:
//上
$(this).parent().parent().prev().find("[name="+ $(this).attr("name")+"]").focus();
break;
case 13:
case 39:
//右
$(this).parent().next().find(":first-child").focus();
break;
case 40:
//下
$(this).parent().parent().next().find("[name="+ $(this).attr("name")+"]").focus();
break;
}
}
8、批量修改页面数据
在编辑数据时,有一种情况,比如蟑螂幼虫的查获只数都是0,甲方希望能够批量设置。
我们设计了最新颖的方式,操作步骤如下:
第一步:双击要复制的单元格,显示黄色背景
第二步:双击最后一个单元格(需要赋值多少,就选择到对应的单元格),弹出对话框,询问是否批量修改
第三步:批量修改完成了
为了避免操作错误,我们还考虑的错误处理,比如两次选择的不是同一列,第二次选择的行号,比第一次选择的行号大,等等问题。
总结:这个页面的功能比较复杂,大家可以把部分功能加入到你的项目中,丰富你的页面功能。
编入自己的项目中,这需要你开动脑筋,想一想如何加入,脑筋转起来,机会就更多。
完成这样的页面,是很花时间的,页面的js调试很费时,后台的业务逻辑也很复杂,开发此页面花费时间是3周。
我写这篇文章花费时间是4个小时,花费时间越多,才会出精品。
|