EXT的树中本就有拖拽功能,并且有相应的触发事件,用来获取正在拖动的节点和位置节点等信息。
1、前台页面:
Ext.define('govRegionModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'regionId', type: 'string' },
{ name: 'regionPid', type: 'string' },
{ name: 'regionName', type: 'string' },
{ name: 'regionGrade', type: 'integer' },
{ name: 'pName', type: 'string' },
{ name: 'remark', type: 'string' },
{ name: 'orderId', type: 'integer' }
]
});
var storeGovRegion = Ext.create('Ext.data.TreeStore', {
autoLoad: true,
model: 'govRegionModel',
folderSort: true,
proxy: {
type: 'ajax',
url: 'getAllRegion.json',
reader: {
type: 'json',
root: 'children'
}
}
});
var treePnl = Ext.create('Ext.tree.Panel',{
region: 'west',
width: 600,
store: storeGovRegion,
tbar: tbarTop1,
rootVisible: false,
lines: true,
columns: [
{xtype:'treecolumn', text: '行政区', dataIndex: 'regionName', width: 300, sortable: false},
{text: '备注信息', dataIndex: 'remark', flex:1, sortable: false}
],
listeners: {
//监听点击事件
itemclick: function(view,rec,el,index,e) {
record = null;
record = rec;
addTag (record);
}
},
viewConfig:{ //配置tree.panel的配置项viewConfig,加入拖拽插件儿,实现拖动
plugins :{
ptype:'treeviewdragdrop',
animate:true,//开启动画效果
dragText: "可用鼠标拖拽进行上下排序",
containerScroll: true,
},
listeners:{
beforedrop:function(node,data,overModel,dropPosition,options){
dragSorting(node,data,overModel,dropPosition,options);
}
}
}
});
beforedrop事件相关信息,可以查阅EXT Api了解,主要用到他的data、overModel和dropPosition三个属性。
拖动排序函数的主要编写:
获取由拖动操作产生的所有信息,处理后传递给后台,后台进行存储更新,实现排序
//拖动排序函数->zouwen
function dragSorting(node,data,overModel,dropPosition,options) {
//被移动的行政区id
var mobileid = data.records[0].get('regionId');
//移动到哪个行政区的id
var positionid = overModel.get("regionId");
//被移动的行政区父行政区id
var mobilepid = data.records[0].get('regionPid');
//移动到哪个行政区的父行政区id
var positionpid = overModel.get("regionPid");
//移动位置
var position = dropPosition;
//被移动的行政区排序号
var mobileorderid = data.records[0].get('orderId');
//移动到哪个行政区的排序号
var positionorderid = overModel.get("orderId");
//位移量
var displacement= mobileorderid - positionorderid;
if(position == 'append' || mobilepid != positionpid) {//判断是否跨节点,主要判断是否发生‘append’和拖动后的两个根节点是否相同
showBox('操作提示', '不可跨节点拖动!', Ext.Msg.OK,Ext.Msg.ERROR);
refresh();
return false;
} else if ( (position == 'before' && parseInt(displacement) == -1) || (position == 'after' && parseInt(displacement) == 1) ) {
refresh();//根据位移量判断,符合上两种条件说明虽然拖动了,但位置没有发生改变,可忽略。
} else {
Ext.Ajax.request({//异步传输信息至后台。
url: '<%=path%>/region/changeOrderRegion',
method: 'post',
params: {mobileid : mobileid, positionid : positionid, mobileorderid : mobileorderid,
positionorderid : positionorderid, position : position},
success : function(result){
var res = Ext.decode(result.responseText);
if (res.success) {
showBox('操作提示',res.msg,Ext.Msg.OK,Ext.Msg.INFO);
refresh();
}
else {
showBox('操作提示',res.msg,Ext.Msg.OK,Ext.Msg.ERROR);
refresh();
}
},
failure : function (response) {
showBox('操作提示','当前系统通讯异常,请稍后操作!',Ext.Msg.OK,Ext.Msg.ERROR);
refresh();
}
});
refresh();
}
}
2、java后台调用方法
后台存储需要分四种情况:
- 从下往上移至前方
- 从上往下移至前方
- 从下往上移至后方
- 从上往下移至后方
/**
* 行政区拖动排序
* @author zouwen
* @param mobileid 被移动的行政区id
* @param positionid 移动到哪个行政区的id
* @param mobileorderid 被移动的行政区排序号
* @param positionorderid 移动到哪个行政区的排序号
* @param position 位置
*
*/
@ResponseBody
@RequestMapping("changeOrderRegion")
public Object changeOrderRegion(String mobileid, String positionid, String mobileorderid, String positionorderid, String position) {
String mes = "拖拉排序失败,请重试!";
boolean res=false;
int resone,resany = 0;
System.out.println(mobileid+"|"+positionid+"|"+mobileorderid+"|"+positionorderid+"|"+position);
Map<String, Object> map = new HashMap<String, Object>();
map.put("mobileorderid", mobileorderid);
map.put("positionorderid", positionorderid);
map.put("regionid", mobileid);
if ("before".equals(position)) {
if (Integer.parseInt(mobileorderid) > Integer.parseInt(positionorderid)) {//从下往上移至前方
map.put("orderid", positionorderid);
resany = govRegionService.changeOrderUpBefore(map);
resone = govRegionService.changeMobileOrder(map);
if (resone == 1 && resany > 0){
res = true;
mes = "重新排序成功!";
}
} else {//从上往下移至前方
map.put("orderid", Integer.parseInt(positionorderid) - 1);
resany = govRegionService.changeOrderDownBefore(map);
resone = govRegionService.changeMobileOrder(map);
if (resone == 1 && resany > 0){
res = true;
mes = "重新排序成功!";
}
}
}
if ("after".equals(position)) {//从下往上移至后方
if (Integer.parseInt(mobileorderid) > Integer.parseInt(positionorderid)) {
map.put("orderid", Integer.parseInt(positionorderid) + 1);
resany = govRegionService.changeOrderUpAfter(map);
resone = govRegionService.changeMobileOrder(map);
if (resone == 1 && resany > 0){
res = true;
mes = "重新排序成功!";
}
} else {//从上往下移至后方
map.put("orderid", Integer.parseInt(positionorderid));
resany = govRegionService.changeOrderDownAfter(map);
resone = govRegionService.changeMobileOrder(map);
if (resone == 1 && resany > 0){
res = true;
mes = "重新排序成功!";
}
}
}
feedback.setMsg(mes);
feedback.setSuccess(res);
return feedback;
}
Mybatis sql语句:
主要原理是获得拖动区间,根据相应情况,对区间内的数据的排序号进行统一更新。
每一种情况的sql语句也不同。
<!-- 拖拉排序:更新范围内的数据排序号(从下往上移至前方)——>zouwen -->
<update id="changeOrderUpBefore" parameterType="map">
<![CDATA[ update gov_region
set order_id = order_id + 1
where order_id >= #{positionorderid} and order_id < #{mobileorderid} ]]>
</update>
<!-- 拖拉排序:更新范围内的数据排序号(从上往下移至前方)——>zouwen -->
<update id="changeOrderDownBefore" parameterType="map">
<![CDATA[ update gov_region
set order_id = order_id - 1
where order_id > #{mobileorderid} and order_id < #{positionorderid} ]]>
</update>
<!-- 拖拉排序:更新范围内的数据排序号(从下往上移至后方)——>zouwen -->
<update id="changeOrderUpAfter" parameterType="map">
<![CDATA[ update gov_region
set order_id = order_id + 1
where order_id > #{positionorderid} and order_id < #{mobileorderid} ]]>
</update>
<!-- 拖拉排序:更新范围内的数据排序号(从上往下移至后方)——>zouwen -->
<update id="changeOrderDownAfter" parameterType="map">
<![CDATA[ update gov_region
set order_id = order_id - 1
where order_id > #{mobileorderid} and order_id <= #{positionorderid} ]]>
</update>
<!-- 拖拉排序:更新被移动的行政区排序号——>zouwen -->
<update id="changeMobileOrder" parameterType="map">
update gov_region
set order_id = #{orderid}
where region_id = #{regionid}
</update>
需要注意的是,从数据库中查询出的数据最好按照排序号排序后在传递给前台页面显示,这样在拖动后才能最好地看到效果。