关于JEECG数据导入的改进完善

来源:互联网 发布:开源地面站 安卓源码 编辑:程序博客网 时间:2024/06/06 07:21
最近在研究JEECG,遇到一个问题,就是数据导入。
官方版本提供的实例中的EXCEL 导入是用的uploadify插件,该插件提供了一系列的好用的方法接口,能够灵活的处理过程中的各个环节,但是有个问题是,uploadify只是负责客户端的上传监控,他检测着要是上传完毕了,就会去执行onUploadSuccess方法和onQueueComplete对应的方法。如果上传的文件小并且导入时间短的话,不会有什么问题,在前台执行这两个方法的时候后台能够返回执行结果,但是如果导入的文件比较大,就有问题了。
如果文件比较大,uploadify上传完成文件之后就会默认为执行完毕可以返回结果了,但是其实后面还要进行复杂的长时间的导入(插入数据库)操作,这样uploadify就不会等你后面的操作了,他会直接就去执行onUploadSuccess方法和onQueueComplete。这样导致的结果是,在前台看来导入完成了,导入界面关闭了,导入列表刷新了,但是其实后台还在执行着导入操作。这样对于用户来讲是很不友好的。用户在前台看到的是执行完毕,但是导入的数据跟自己excel中的数据不一致,但是又没有报错(当然,这种情况官网提供的实例tip提示也不会有任何内容),其实后台还没有执行完毕,并且如果导入出现问题也没法在前台进行展示了。
这个问题纠结了好几天,怎么解决呢!
想到了在工作中做过的数据导入(用的是JSF框架),原理是将数据的上传和数据的导入分开来操作,上传专门上传,导入专门导入。
问题解决设想:
导入分两步完成:
第一步:上传
用uploadify进行上传,上传后将文件保存到服务器的某个临时文件中,返回上传结果,结束本次请求
第二步:导入
上次请求结束后,紧接着利用AJAX的异步性,发起一个请求,该请求专门负责将上一步上传的文件 进行导入操作。这一步就会等到该请求真正返回结果后才会在前台,完成本次请求,关闭上传页面,刷新数据列表。
其实对于用户来讲还是一步完成。
到此为止就能完美的解决以上问题。
问题解决实现:
第一步:上传

上传页面的代码:personUpload.jsp

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" %>    <%@include file="/context/mytags.jsp" %>        <!DOCTYPE html>        <html>                        <head>                <title>                    批量导入                </title>                <t:base type="jquery,easyui,tools">                </t:base>            </head>                        <body style="overflow-y: hidden" scroll="no">                <t:formvalid formid="formobj" layout="div" dialog="true" beforeSubmit="upload"                tiptype="1">                    <fieldset class="step">                        <div class="form">                            <t:upload name="fiels" buttonText="选择要导入的文件" uploader="jformPersonInfoController.do?uploadPersonFile&id=${id}&importType=${importType}"                            extend="*.xls;*.xlsx" id="file_upload" dialog="false" formData="documentTitle"                            multi="false" callback="forbiddenPage(reJsonData)" view="true">                            </t:upload>                        </div>                        <div class="form" id="filediv" style="height: 50px">                        </div>                    </fieldset>                </t:formvalid>                <script type="text/javascript" src="webpage/gwc/db/person/jformPersonInfo.js">                </script>            </body>                </html>

注意:dialog设置为false,因为dialoag的默认值为true,必须明确的设定dialog为false,
那么dialog的作用是什么呢,如果dialog为true,就会执行刷新数据列表,关闭上传页面,并且弹出提示信息,并且callback函数用于没有机会执行。这些在我们没有真正执行完成,我们是不希望这样操作的。
设置callback回调函数,该函数是在执行onQueueComplete(可以看做是upladify最后执行的函数)的时候执行的,这样问题的思路就明确了,就是在第一步执行完成上传之后,不是进行刷新列表,关闭上传页面,弹出信息,而是执行回调函数
注:本人修改了官方的upload标签,增加了reJsonData公共变量, 将onUploadSuccess返回的json数据赋值给reJsonData,然后在回调函数进行传递:
修改UploadTag.java

public StringBuffer end() {StringBuffer sb = new StringBuffer();if("pic".equals(extend)){extend="*.jpg;*,jpeg;*.png;*.gif;*.bmp;*.ico;*.tif";}if(extend.equals("office")){extend="*.doc;*.docx;*.txt;*.ppt;*.xls;*.xlsx;*.html;*.htm";}sb.append("<link rel=\"stylesheet\" href=\"plug-in/uploadify/css/uploadify.css\" type=\"text/css\"></link>");sb.append("<script type=\"text/javascript\" src=\"plug-in/uploadify/jquery.uploadify-3.1.js\"></script>");sb.append("<script type=\"text/javascript\" src=\"plug-in/tools/Map.js\"></script>");sb.append("\n<script type=\"text/javascript\">"+"var flag = false;"+"var fileitem=\"\";"+"var fileKey=\"\";"+"var serverMsg=\"\";"+"var m = new Map();"+"var reJsonData;"+ "$(function(){"+"$(\'#"+id+"\').uploadify({"+"buttonText:\'"+buttonText+"\',"//按钮的长度//+"width::\'"+150+"\',"+"auto:"+auto+","+"progressData:\'speed\'," +"multi:"+multi+","+"height:25,"+"overrideEvents:[\'onDialogClose\']," +"fileTypeDesc:\'文件格式:\'," +"queueID:\'"+queueID+"\',"+"fileTypeExts:\'"+extend+"\',"+"fileSizeLimit:\'15MB\',"//增加文件限制+"queueSizeLimit:\'1\',"+"swf:\'plug-in/uploadify/uploadify.swf\',"+"uploader:\'"+getUploader()+"onUploadStart : function(file) { ");if (formData!=null) {String[] paramnames=formData.split(",");for (int i = 0; i < paramnames.length; i++) {String paramname=paramnames[i];sb.append("var "+paramname+"=$(\'#"+paramname+"\').val();");}         sb.append("$(\'#"+id+"\').uploadify(\"settings\", \"formData\", {");        for (int i = 0; i < paramnames.length; i++) {String paramname=paramnames[i];if (i==paramnames.length-1) {sb.append("'"+paramname+"':"+paramname+"");}else{sb.append("'"+paramname+"':"+paramname+",");}}        sb.append("});");};        sb.append("} ,"        //onQueueComplete是最后执行的函数,晚于onUploadSuccess+"onQueueComplete : function(queueData) { ");if(dialog)//默认为true,作用是刷新列表,显示右下角的信息,并且关闭上传页面,dialog为true的话,设置callback函数不起作用{sb.append("var win = frameElement.api.opener;"                +"win.reloadTable();"            +"win.tip(serverMsg);"            +"frameElement.api.close();");}else{//回调函数  if(callback!=null)  //可传递后台传递的json数据reJsonData  sb.append(""+callback+"();");//  sb.append(""+callback+";");}if(view){sb.append("$(\"#viewmsg\").html(m.toString());");sb.append("$(\"#fileKey\").val(fileKey);");}sb.append("},");//onAllComplete:当所有文件都上传结束后sb.append("onAllComplete:function(data){" +//"alert(data.filesUploaded );" +//"alert('全部上传完毕!');" +"},");//上传成功处理函数sb.append("onUploadSuccess : function(file, data, response) {");sb.append("var d=$.parseJSON(data);");sb.append("reJsonData = d;");//sb.append("alert(d);");if(view){sb.append("var fileitem=\"<span id=\'\"+d.attributes.id+\"\'><a href=\'#\' onclick=openwindow(\'文件查看\',\'\"+d.attributes.viewhref+\"\',\'70%\',\'80%\') title=\'查看\'>\"+d.attributes.name+\"</a><img border=\'0\' onclick=confuploadify(\'\"+d.attributes.delurl+\"\',\'\"+d.attributes.id+\"\') title=\'删除\' src=\'plug-in/uploadify/img/uploadify-cancel.png\' widht=\'15\' height=\'15\'>  </span>\";");sb.append("m.put(d.attributes.id,fileitem);");sb.append("fileKey=d.attributes.fileKey;");}if(onUploadSuccess!=null){sb.append(onUploadSuccess+"(d,file,response);");}sb.append("if(d.success){");sb.append("var win = frameElement.api.opener;");//sb.append("tip(d.msg);");sb.append("serverMsg = d.msg;");sb.append("}");sb.append("},");sb.append("onFallback : function(){tip(\"您未安装FLASH控件,无法上传图片!请安装FLASH控件后再试\")},");sb.append("onSelectError : function(file, errorCode, errorMsg){");sb.append("switch(errorCode) {");sb.append("case -100:");sb.append("tip(\"上传的文件数量已经超出系统限制的\"+$(\'#"+id+"\').uploadify(\'settings\',\'queueSizeLimit\')+\"个文件!\");");sb.append("break;");sb.append("case -110:"+"tip(\"文件 [\"+file.name+\"] 大小超出系统限制的\"+$(\'#"+id+"\').uploadify(\'settings\',\'fileSizeLimit\')+\"大小!\");"+"break;"+"case -120:"+"tip(\"文件 [\"+file.name+\"] 大小异常!\");"+"break;"+"case -130:"+"tip(\"文件 [\"+file.name+\"] 类型不正确!\");"+"break;"+"}");       sb.append("},"+"onUploadProgress : function(file, bytesUploaded, bytesTotal, totalBytesUploaded, totalBytesTotal) { "//+"tip('<span>文件上传成功:'+totalBytesUploaded/1024 + ' KB 已上传 ,总数' + totalBytesTotal/1024 + ' KB.</span>');"                 +"}"   +"});"+"});"+"function upload() {"+"$(\'#"+id+"\').uploadify('upload', '*');"+"return flag;"+"}"+"function cancel() {"+"$(\'#"+id+"\').uploadify('cancel', '*');"+"}"+"</script>\n");       sb.append("<span id=\""+id+"span\"><input type=\"file\" name=\""+name+"\" id=\""+id+"\" /></span>");       if(view)       {       sb.append("<span id=\"viewmsg\"></span>");       sb.append("<input type=\"hidden\" name=\"fileKey\" id=\"fileKey\" />");       }        return sb;}

第二步:导入
导入的关键是由callback="forbiddenPage(reJsonData)"发起的。
那么forbiddenPage起什么作用呢,先看一下代码:

/*****************等待中禁用页面功能*****************/  /**  * 禁用页面  */  function forbiddenPage(reJsonData){  //alert('显示遮罩');    $("<div class=\"datagrid-mask\" style=\"background:#666666;\"></div>").css({display:"block",width:$("body")[0].offsetWidth+10,height:$(window).height()}).appendTo("body");       $("<div class=\"datagrid-mask-msg\"></div>").html("正在处理,请稍候……").appendTo("body").css({display:"block",left:($(document.body).outerWidth(true) - 190) / 2,top:($(window).height() - 45) / 2});  toImportExcelToDataBase(reJsonData);}  /**  * 释放页面  * @return  */  function releasePage(){      $(".datagrid-mask,.datagrid-mask-msg").remove();  }  

解释一下forbiddenPage的作用:在上传页面展示一个遮罩层,并且展示正在处理的提示,这样在进行导入操作的时候,就能够给用户一个很友好的提示,看一下效果吧



那么toImportExcelToDataBase(reJsonData);是干什么的呢,先上代码:

//执行将临时文件导入到数据库function toImportExcelToDataBase(jsonD){url="jformPersonInfoController.do?importPersonData&id="+jsonD.attributes.id+"&importType="+jsonD.attributes.importType;$.ajax({async : true,cache : false,url:"jformPersonInfoController.do?importPersonData&id="+jsonD.attributes.id+"&importType="+jsonD.attributes.importType,type:"post",//如果返回数据只是JSON形式,而不是真正的JSON数据的话,就会获得不到值,为NULL,所以最好不要限制//dataType:"json",success:function(data){//解除遮罩releasePage();var dt = $.parseJSON(data);alertShowInfoTip(dt.msg,'操作提示');}});}

解释一下:就是发送一个请求并且传递了参数,一定要是异步请求(async : true,),不要设定dataType:"json",让ajax自己解析
这个请求就是进行导入操作了,这就不用担心出现前台提示成功,后台一直运行的情况了,这次后台不返回,前台就不会提示和刷新了。
接下来就是看看返回以后的操作了。


success:function(data){//解除遮罩releasePage();var dt = $.parseJSON(data);alertShowInfoTip(dt.msg,'操作提示');}

releasePage();的作用是解除遮罩层。

/**  * 释放页面  * @return  */  function releasePage(){      $(".datagrid-mask,.datagrid-mask-msg").remove();  }  

alertShowInfoTip(dt.msg,'操作提示');的作用是什么呢,哒哒哒上代码:

/** * 创建一个锁屏,并且有一个确定按钮的弹出框,展示信息 */function alertShowInfoTip(msg,title) {$.dialog.setting.zIndex = 1980;title = title?title:"提示信息";$.dialog({title:title,//icon:'tips.gif',lock:true,content: msg,width:400,height:300,ok:function(){var wind = frameElement.api.opener; frameElement.api.close();        wind.reloadTable();}});}



看到了吧,就是展示一个提示框,关键是能够显示出导入工程中产生的导入日志信息,让用户明明白白的完成这次导入。这些都完成后,点击确定按钮就会执行关闭上传页面,刷新数据列表。
哒哒哒,到此为止,圆满完成啦。
上图看效果吧:



1 0
原创粉丝点击