在没有框架源码的情况下修改框架中的功能——DataGrid导出Excel功能修改示例

作者:  最后修改:2014年10月31日  浏览数:583
     当实施人员在外面作项目实施时可能要对框架的功能作修改,通常泽元框架类库都以jar包的形式存在于UI\WEB-INF\plugins\lib目录,并不对项目实施人员提供源代码,这时的修改工作相对有框架源码的情况下要繁琐一些。
          下面以一个简单的示例演示在没有框架源代码的情况下怎么完成框架功能的修改。
             
           需求背景:
              如下图所示,我们的DataGrid点击右键时,有"导出选中行成Excel"、"导出本页成Excel"、"导出全部成Excel"三个与导出有关的功能按钮。

          

TIM图片20171103171745

              马大哈商城项目客户提出,DataGrid一页通常只显示几十条记录,在商城中总订单或某类商品通常数以万记,常常需要导出其中几百或几千条记录,上面三个选选项并不能满足需求,所以需要改进,可以选择要导出的条数。
             
           实现目标:
             解决方案,右键菜单上的三个导出按钮合并为一个,然后在弹出的对话框里,再列三个选择项供选择。
            1、导出选中行,
           2、导出本页起[多少]页,
            3、导出全部
              我们预期是需要修改datagrid.js里导出excel相关方法,和相关的dialog的页面。
            以及对应的后台导出方法。都是逻辑上的调整修改修改,没有新的功能实现,工作量应该不大。
             
           实现步骤:
           一、找到datagrid相关的js,并重新引入。
              首先,我们要找到与这个功能相关的前后端代码的位置。DataGrid是js控件,
            在zcms的代码库主干上,这个js源码存在于 UI\framework\_source\components\dataGrid2.1.js
             然后和其他js控件一起压缩合并到 UI\framework\components.min.js,
           并被泽元开发工具打包到jar包中,这个jar包一般位于 UI\WEB-INF\plugins\lib\com.zving.framework.ui.jar,
            所以我们可以从 UI\WEB-INF\plugins\lib\com.zving.framework.ui.jar 解压出 main.js 和 components.min.js。
              main.js 放置到 UI\framework\ 目录(这个目录不存在,则新建之)。
           从 components.min.js 中搜索 DataGrid 字样,应该很快能找到被压缩成一行的 DataGrid 组件相关的js代码,
           把这行js代码复制出来,另存为 UI\framework\dataGrid.js。
           我们等下要对这个js作修改,并且希望这个被修改过的 dataGrid.js 中对 DataGird 的类定义能够覆盖默认的DataGrid类。
           所以我们还要在 main.js 里查找
           z.importJs('components.min.js');
            在这一行的下面添加
           z.importJs('datagrid.js');
            这样dataGrid.js中对DataGird的类定义能够覆盖默认的DataGrid类。
             
           二、格式化dataGrid.js
             现在dataGrid.js里的代码是被压缩过的,很难阅读,我们需要使用js代码格式化工具对其进行格式化,
            我推荐的js编辑器如 Sublime Text 及 Notepad++ 都有js代码格式化插件,
            如果你的编辑器没有js格式化插件,可以使用在线js代码格式化工具 http://www.jsbeautifier.org/ 对js代码进行格式化,
           你还可以使用chrome浏览器的js代码格式化功能。
             
           三、定位右键菜单及导出Excel相关js代码位置
              我们可以在dataGrid.js中搜索“excel”(不区分大小写)字样,很快就能在代码中找到定义右键菜单的地方。

                       this.contextMenuItems.push({

                           icon: CONTEXTPATH + 'icons/icon003a2.png',

                           text: Lang.get("DataGrid.SelectedRowToExcel"),

                           handler: function(btn, e) {

                               me.selectedRowToExcel(id);

                           }

                       });

                       this.contextMenuItems.push({

                           icon: CONTEXTPATH + 'icons/icon003a4.png',

                           text: Lang.get("DataGrid.ToExcel"),

                           handler: function(btn, e) {

                               DataGrid.toExcel(id, true);

                           }

                       });

                       this.contextMenuItems.push({

                           icon: CONTEXTPATH + 'icons/icon003a3.png',

                           text: Lang.get("DataGrid.AllToExcel"),

                           handler: function(btn, e) {

                               DataGrid.toExcel(id);

                           }

                       });

              阅读了上面的代码后,发现一个按钮点击后会调用selectedRowToExcel方法,查看这个方法的代码,发现里面也调用到了DataGrid.toExcel,所以推断这三个菜单项功能合并后对代码的改动应该不会很多。
            上面的代码精简为

                       this.contextMenuItems.push({

                           icon: CONTEXTPATH + 'icons/icon003a4.png',

                           text: Lang.get("DataGrid.ToExcel"),

                           handler: function(btn, e) {

                               DataGrid.toExcel(id);

                           }

                       });

                  还需要修改js中的语言字符串“导出本页成Excel”为“导出为Excel...”,在这儿就不赘述了。
           四、对DataGrid.toExcel方法调用的弹出框进行修改
              在DataGrid.toExcel方法的定义中,我看到代码中打开了一个对话框的逻辑,

                   var dlg = new z.Dialog(Lang.get("DataGrid.SelectCol"), z.JSLIBPATH + "resources/dataGridToExcelDialog.html?DataGridID=" + el.id, 500, 150);

           对话框中的页面为 dataGridToExcelDialog.html。在前文到的实现目标中要提供三个数据导出选项,我们可以把选项放到这个页面中。

                 

                 从com.zving.framework.ui.jar中解压出 dataGridToExcelDialog.html 放到目录UI\framework\resources下,

               查看html源码,有下面html代码所示的的表格:

               <table width="90%" height="100%" border="0" align="center">

                 <tr>

                   <td height="40"><fieldset>

                       <legend>

                       <input type="checkbox" name="all" id="all" checked onClick="onAllClick()">

                       <label for="all"><strong><span id="All">全部列</span></strong></label>

                       </legend>

                       <div id="tdNames"> </div>

                     </fieldset></td>

                 </tr>

               </table>

            我们要给这个表格,添加一行(tr):

                 <tr>

                   <td><fieldset>

                       <legend>

                       <strong><span>导出行</span></strong>

                       </legend>

               <table width="100%">

                  <tr>

                  <td height="25" width="30%"><label for="Row0"><input type="radio" name="Row" checked id="Row0" value="1">

               选中行</label></td>

                  <td height="25" width="50"><label for="Row2"><input type="radio" name="Row" id="Row2" value="2">

               当前页起共 <input id="pageLimit" ztype="Number" type="text" value=1 style="width:50px;" /> 页</label></td>

                  <td height="25" width="20%"><label for="Row3"><input type="radio" name="Row" id="Row3" value="3">

               全部记录</label></td>

                  </tr>

               </table>

                     </fieldset></td>

                 </tr>

                 

               五、对DataGrid.toExcel方法中弹出框回调部分进行修改

  DataGrid.toExcel方法原来传入三个参数(girdId, isCurrentPage, selectedRows)分别指datagird的id、是否仅导出当前页、要导出的行。
              现在这三个参数的后面两个参数不再传入,这两个参数要根据dataGridToExcelDialog.html页面中的单选项来初始化,toExcel方法中的关键修改如下:

                   var r=DataGrid.getSelectedRows(q.id);

                   var v=s.innerWin.Zving.getValues('Row')[0];

                   if(v==1){

                       var arr = [];

                       for (var i = 0; i < r.length; i++) {

                           arr.push(r[i].rowIndex);

                       }

                       o.toExcelSubmit(q, false, t, u, arr);

                   }else if(v==2){

                       r=Number(s.innerWin.Zving.getDom('pageLimit').value);

                       o.toExcelSubmit(q, true, t, u, r);

                   }else if(v==3){

                       o.toExcelSubmit(q, false, t, u);

                   }

              这段代码修改后,&ldquo;导出选中行&rdquo;、&ldquo;导出本页&rdquo;、&ldquo;导出全部&rdquo;等不同条件下,会传给DataGrid.toExcelSubmit方法不同的参数。
              接下来我们要修改后台java方法来接受新的参数,用于后台逻辑里的条件判断。
            查看DataGrid.toExcelSubmit方法,我们发现里面逻辑为构建一个form表单,并提交到后台方法
            com.zving.framework.ui.control.DataGridUI.toExcel.zaction
            所以我们应该找出 com.zving.framework.ui.control.DataGridUI.toExcel.zaction 对应的java类的位置,并作出修改。
             
           六:查找com.zving.framework.ui.control.DataGridUI.toExcel.zaction类。
              在 UI\WEB-INF\plugins\lib\com.zving.framework.plugin.jar 中找到 class 文件 !com\zving\framework\ui\control\DataGridUI.class,
            使用jd-gui反编译这个class文件并保存到 JAVA\com\zving\framework\ui\control\DataGridUI.java。
           

to

              阅读该java类中的toExcel方法,发现还需要反编译类com.zving.framework.data.DataTableUtil,
              这个类的class文件处于 UI\WEB-INF\plugins\required\com.zving.framework\ext\framework-ext.2.0.jar 中。
           注意 jd-gui反编译出的java文件可能会存在一些语法错误,根据错误提示进行修改即可。
             
           七、修改DataTableUtil.java中的prepareHtmlTableToExcel方法
              我们给 prepareHtmlTableToExcel 方法再添加一个参数(strPageLimit),表示要导出的页数,还要跟据这个参数的值对导出逻辑进行调整。
           下面只列出关键的一处代码逻辑:
           &hellip;&hellip;

               if ("1".equals(excelPageFlag)) {

                   tmpPageIndex = (StringUtil.isEmpty(pageIndex)) ? 0 : Integer.parseInt(pageIndex);

                   if (StringUtil.isNotEmpty(strPageLimit)) {

                       pageTotal = tmpPageIndex + Integer.parseInt(strPageLimit);

                   else {

                       pageTotal = tmpPageIndex + 1;

                   }

                   tmpPageSize = (StringUtil.isEmpty(pageSize)) ? 0 : Integer.parseInt(pageSize);

               }

               &hellip;&hellip;

             
           八、测试,调整
             启动工程,打开有datagrid的页面(在我写文章时的环境下是访问http://localhost:8080/zshop/search/wordList.zhtml)进行测试。 
             
           九、打包,反馈给产品组。
              针对框架的修改,如果有必要更新到框架代码库的主干上,请把修改过的文件按目录组织好,并附上一个简要的说明,说明修改了哪些方法,然后 打包提交给产品组。使产品组能够及时的更新到框架代码库的主干上。
             
              如果不需要反馈给产品组,可以在项目工作文档里记一条备忘,说明对哪些框架的js、java文件有修改。通知其他同事修改同一个文件时,注意不要覆盖了你的修改。
             
              此外,刚才修改过的js及java文件,都可以再次打包到jar包里,供其他版本相近的项目更新。
            java文件会在WEB-INF目录下生成class文件,覆盖jar包里旧的class文件即可。
              js文件打包到jar里稍微复杂一点:
            修改过的dataGrid.js打包到jar包里先要压缩,在我们推荐的js编辑器如Sublime Text及Notepad++都有js代码压缩插件,
                如果你的编辑器没有js格式化插件,可以使用在线js代码压缩工具 http://tool.oschina.net/jscompress 对js代码进行压缩;
然后把压缩后得到的js代码覆盖掉components.min.js中DataGrid组件对应的js代码,最后用 components.min.js 覆盖 com.zving.framework.ui.jar 中的 components.min.js,并删除掉UI\framework目录下我们刚才新添加的js。
             
             至此,我们在没有框架源码的情况下修改了框架中的表格数据导出Excel功能。