您现在的位置:首页 >> Web开发 >> IntraWeb >> 内容

Intraweb之EasyUI篇

时间:2015/5/5 15:29:47 点击:

  核心提示:Intraweb一直是Delphi快速开发web应用的首选工具,但自带的控件较少,样式比较难看,TMS与IW倒是可用,可是要收费,对于我们这些习惯用免费的用户来说,想找个破解也比较费劲。EasyUI是基于JQuery开发的框架,内置的控件完全可以满足我们开发一般web程序的需求,而且是免费的,用起来...
Intraweb一直是Delphi快速开发web应用的首选工具,但自带的控件较少,样式比较难看,TMS与IW倒是可用,可是要收费,对于我们这些习 惯用免费的用户来说,想找个破解也比较费劲。EasyUI是基于JQuery开发的框架,内置的控件完全可以满足我们开发一般web程序的需求,而且是免 费的,用起来也心安理得。下面我就IW如何结合EasyUI开发程序谈谈自己的一些心得,与大家交流一下。主要有以下几种方法:
  一、使用模板
  在IWForm内使用模板引入做好的html文件,结合IW自身的控件进行操控。这种方法虽说比较方便,但模板也有自身的缺点,内部不支持中文引用是 一大Bug,目前IW都没有要解决的迹像。如果一定要用模板,也有方法规避,即汉字全部用网页转义“&#”加汉字的十进制编码。模板的使用有很多 文章可供参考,也不是本章的重点,不做具体讲解。
  二、MVC设计模式
  IW使用MVC方式结合EasyUI设计程序,是本文的重点。我们知道IW与HTML静态页面的交互,可以通过javascript接口来实现,可以 使用AddToInitProc('alert("欢迎")')这样的语句,也可以在控件的JavascriptEvent属性内添加js语句。本文介绍 的方法完全将界面与数据处理分开,一律使用EasyUI来实现界面(完全不用IW的可视控件,数据库控件还是需要的),数据处理交给IW后台做。我们以开 发一个简单的应用程序来一步步实现这些功能,同时会使用一定篇幅介绍EasyUI部分控件的使用(本文必须要有一定的javascript基础)。
  第一步:实现登陆界面。

  首先引入以下文件,后面其它页面也一样这样引用,直接贴代码:

  1. <span style="white-space:pre">    </span><link rel="stylesheet" type="text/css" href="easyui/themes/default/easyui.css">  
  2. <link rel="stylesheet" type="text/css" href="easyui/themes/icon.css">  
  3. <script type="text/javascript" src="easyui/jquery.min.js"></script>  
  4. <script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>  
  5. <script type="text/javascript" src="easyui/locale/easyui-lang-zh_CN.js"></script>  
   这些文件是必须引用的,easyui.css是自带的样式,icon.css是使用中的各种图标,easyui-lang-zh_CN.js是汉化文件(EasyUI对中文支持还是很不错的,如果觉得汉化得不够好,可以打开这个文件自行修改)。界面部分:

  1. <form id="ff" class="easyui-form" method="post" data-options="novalidate:true">  
  2. <!--form提供了各种方法来操作执行表单字段,比如:ajax提交, load, clear等等。当提交表单的时候可以调用validate方法检查表单是否有效。  
  3. “data-options”控件的各种属性,form有以下属性:  
  4. 属性名 类型  描述  默认值  
  5. novalidate  boolean     定义是否验证表单的字段,true:验证,false:不验证。  false  
  6. ajax    boolean     定义是否使用ajax提交表单,true:使用,false:不使用。   true  
  7. queryParams     object      当表单被提交到服务器的时候增加的额外参数列表。 {}  
  8. url string      提交表单动作的URL地址    null  
  9. -->  
  10.             <table cellpadding="5">  
  11.                 <tr>  
  12.                     <td>用户名:</td>  
  13.                     <td><input class="easyui-textbox" type="text" name="username" data-options="required:true" style="width:150px"/></td>  
  14.  <!--  
  15. TextBox(文本框)是一个增强的输入字段组件, 它允许用户非常简单的创建一组表单。它是一个用于构建其他组合控件的基础组件,如:combo,databox、spinner等  
  16.  required:true表示文本框不能为空,下同。  
  17. -->  
  18.                 </tr>  
  19.                 <tr>  
  20.                     <td>密 码:</td>  
  21.                     <td><input class="easyui-textbox" type="password" name="passw" data-options="required:true" style="width:150px"/></td>  
  22.                 </tr>  
  23.             </table>  
  24.         </form>  
  25.         <div style="width:216px;padding:5px 0px;height:30px">  
  26.             <a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()" style="width:80px;float:left">登陆</a>  
  27. <!--easyui-linkbutton按钮组件,使用超链接按钮创建,提示:不要将它改为button类别,IE9以下浏览器会不正常,submitForm()提交数据,clearForm()清空数据-->  
  28.             <a href="javascript:void(0)" class="easyui-linkbutton" onclick="clearForm()" style="width:80px;float:right">取消</a>  
  29.         </div>  
  30.         </div>  
  31.     </div>  
  登陆界面基本完成,有些简陋,当然可以自行修改。下面实现提交数据和清空数据,用Javascript:

[javascript] view plaincopy
  1.         function submitForm(){  
  2.             $('#ff').form('submit',{//这是EasyUI的Form自带功能,就是提交数据  
  3.                 url:'Login.php'//需要把数据提交到的页面  
  4.                 onSubmit:function(){//验证数据是否为空,如果为空就返回。  
  5.                     return $(this).form('enableValidation').form('validate');  
  6.                 },  
  7.                 success: function(data){  
  8. //提交成功后的回调函数,data就是返回的数据  
  9.                     if(parseInt(data)==1)  
  10. //我们在这里返回1和0,1表示成功登陆,在后台实现  
  11.                     {  
  12.                         window.location='main.html';  
  13. //登陆成功后,跳转到主程序  
  14.                     }  
  15.                     else  
  16.                     {  
  17.                         $.messager.alert('错误','用户名或密码错误!','error');  
  18. /*EasyUI消息提示框,就是alert的改进用法,显示警告窗口。 
  19. 参数(依次调用): 
  20. title:在头部面板显示的标题文本。 
  21. msg:显示的消息文本。 
  22. icon:显示的图标图像。可用值有:error,question,info,warning。 
  23. fn: 在窗口关闭的时候触发该回调函数。 */  
  24.                         $('#ff').form('clear');//清空数据,下同。  
  25.                     }  
  26.                 }      
  27.   
  28.                   
  29.             });  
  30.         }  
  31.         function clearForm(){  
  32.             $('#ff').form('clear');  
  33.         }  

  文件另存为“index.html”,即首页,放在wwwroot下(注意easyui的相关文件也要放在这个目录下),启动程序后,就是直接访问这个页面了,没有“$”这个标志。
  登陆界面基本完成,数据需要提交到“Login.php”这个页面,按一般的做的法,新建一个IWForm,使用模板加载文件,本文用另一种思路,也是本文的关键:
用delphi新建一个Unit,命名Login单元,加入IW工程。

直接贴出代码(参考万一博客):

[delphi] view plaincopy
  1. {新建Login 单元, 从 TContentBase 继承实现一个 TLogin 类}  
  2. unit Login;  
  3.   
  4. interface  
  5. uses Classes, IW.Content.Base, System.SysUtils,HTTPApp, IWApplication, IW.HTTP.Request, IW.HTTP.Reply, IWMimeTypes;  
  6.   
  7.   
  8. type  
  9.   TLogin = class(TContentBase)  
  10.   protected  
  11.     function Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean; override;  
  12.   public  
  13.     constructor Create; override;  
  14.   end;  
  15.   
  16. implementation  
  17.  uses ServerController,UserSessionUnit;  
  18. { TLogin }  
  19.   
  20. constructor TLogin.Create;  
  21. begin  
  22.   inherited;  
  23.   mFileMustExist := False;  
  24. end;  
  25.   
  26. function TLogin.Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean;  
  27. begin  
  28.   aReply.ContentType := MIME_HTML;  
  29.   aReply.WriteString('这里就是返回到客户端的数据');  
  30.   Result := True;  
  31. end;  
  32.   
  33. end.   
  34.   
  35. {在 IWServerControllerBase.OnConfig  映射login.php}  
  36. uses  
  37.   IWInit, IWGlobal, IW.Content.Handlers, Login;  
  38.   
  39. procedure TIWServerController.IWServerControllerBaseConfig(Sender: TObject);  
  40. begin  
  41.   THandlers.Add('''login.php', TLogin.Create);  
  42. //添加虚拟文件名,映射到服务器  
  43. end;  

  直接列出代码大家可以不太清楚怎么回事,这里说明一下流程:
  客户端通过Form提交用户名和密码到“Login.php”,“Login.php”是通过服务器添加的一个虚拟文件,映射到从 TContentBase继承实现的TLogin类,用THttpRequest接收提交的数据,并进行处理,用 THttpReply.writestring写入返回客户端数据。这样登陆过程前台与后台代码均完成。

  第二步:实现主界面
  我们开发的是一个商品信息管理程序,主界面用EasyUI的Layout实现自适应浏览器(记得引入相关js和css):
  1. <div data-options="region:'north',border:false" style="height:60px;background:#B3DFDA;padding:0px 10px;text-align:center">  
  2. <h3>商品信息管理系统</h3>  
  3. </div>  
  4. <div data-options="region:'west',split:true,title:'商品分类'" style="width:200px;padding:10px;">  
  5.   
  6. </div>  
  7. <!--<div data-options="region:'east',split:true,collapsed:true,title:'East'" style="width:100px;padding:10px;">east region</div>-->  
  8. <div data-options="region:'south',border:false" style="height:50px;background:#A9FACD;padding:10px;">  
  9. 京ICP证000000号  
  10. </div>  
  11. <div data-options="region:'center',title:'商品简要信息'">  
  12.   
  13. </div>  

  很好理解,即左西右东,上北下南加上中央的布局,右边不需要,我把它注释掉。

  页面设计思路是这样的,左边放一个Tree,用来显示商品分类,中央放GridData,用来显示商品信息列表,通过两个控件实现删除、添加、修改功能。
  west这个DIV内加入Tree:
  1. <ul id="easyui_tt" class="easyui-tree"   
  2. data-options="  
  3. animate:true,//动画  
  4. lines:true,//显示树线  
  5. url:'Treedata.php',//上面有解释,需要提交的页面  
  6. method:'post',//提交方式Post,再强调一下必须用Post  
  7. onClick: function(node){//鼠标单击事件  
  8. QueryByID(node.id);//通过node.id来查询数据,讲DataGrid时再说  
  9. },  
  10. onContextMenu: function(e, node){//右键菜单  
  11. e.preventDefault();//必须用的  
  12. $(this).tree('select', node.target);//选择的Node  
  13. $('#mm').menu('show', {//EasyUI的菜单,非常简单  
  14. left: e.pageX,//弹出菜单的位置  
  15. top: e.pageY  
  16. });  
  17. }">  
  18. </ul>  
  Tree的属性很多,其中一个比较重要的是node,即Tree的节点每个节点都具备以下属性:
  id:节点ID,对加载远程数据很重要。
  text:显示节点文本。
  state:节点状态,'open' 或 'closed',默认:'open'。
  如果为'closed'的时候,将不自动展开该节点。
  checked:表示该节点是否被选中。
  attributes: 被添加到节点的自定义属性。
  children: 一个节点数组声明了若干节点
  Tree的节点是通过url提交请求到服务器接收返回数据加载的,形成
  树的数据是JSon格式,我们可以分析一下:
[javascript] view plaincopy
  1. [{      
  2.     "id": 1,//对应node的ID,其他也是一一对应的      
  3.     "text""Node 1",      
  4.     "state""closed",      
  5.     "children": [{ //子node     
  6.         "id": 11,      
  7.         "text""Node 11"     
  8.     },{      
  9.         "id": 12,      
  10.         "text""Node 12"     
  11.     }]      
  12. },{      
  13.     "id": 2,      
  14.     "text""Node 2",      
  15.     "state""closed" //不展开节点   
  16. }]}    
  同 上面的“登陆”,我们从TContentBase继承实现一个 TTreeData 类直接复制模板,修改一个即可,注意加入IW工程,并在ServerController内映射“TreeData.php”。我们现在需要通过 delphi来实现树,Tree的层越多就越复杂,我发现
不管通过什么语言动态实现Tree,都是非常麻烦的一件事,EasyUI的例子只能实现两层树。从数据库读取Tree数据,在数据库设计的时候有一个技 巧,不知道大家是怎样处理的,我这里说一个我的方法:树的上下级之间用代码表示,2位数字代表根,4位数字代表下一级,依此类推,代码不能用纯数字,这样 不好排序,我在数字前加个字母,这样通过“select*from Tree order by id”就可以把上下级排列在一起,而不是按代码大小排序。数据库就不多讲了,不在本文的范围,大家看一下我的源码里的数据库就知道了。建树代码如下(本想 用JSon,无奈学不到家,只能用字符串拼接):
[delphi] view plaincopy
  1. function BuildTree:string;  
  2. var  
  3.  i,j,old_ln,new_ln:Integer;  
  4.  id,s,title,ft:string;  
  5. begin  
  6. ft:='{"id":"%s","text":"%s"},';//Json格式  
  7. with UserSession.FDQuery1 do  
  8. begin  
  9.   Open('select*from Tree order by id'); //按id排序可以将父子节点正好罗列在一起  
  10.   s:='[';  
  11.   old_ln:=0;//初始化开始节点ID的长度  
  12.   for i := 0 to RecordCount-1 do  
  13.     begin  
  14.        id:=Fields.Fields[0].AsString;  
  15.        title:=Fields.Fields[1].AsString;  
  16.        new_ln:=id.Length-3;//新节点ID的长度,减去3除去了根节点的长度,方便计算  
  17.        //通过比较与上一节点ID的长度来判断节点的上下级关系  
  18.        if (new_ln=old_ln) then//与上一节点同等级  
  19.           s:=s+Format(ft,[id,title]);  
  20.        if new_ln>old_ln then //上一节点为父节点  
  21.           begin  
  22.             s:=s.Substring(0,s.Length-2);  
  23.             s:=s+Format(',"state":"closed","children":['+ft,[id,title]);  
  24.           end;  
  25.        if (new_ln<old_ln) then //上一节点为子节点  
  26.           begin  
  27.             s:=s.Substring(0,s.Length-1);  
  28.             for j :=1 to (old_ln-new_ln) div 2 do  
  29.               s:=s+']}';  
  30.             s:=s+Format(','+ft,[id,title]);  
  31.           end;  
  32.       Next;  
  33.       old_ln:=new_ln;//将当前节点ID长度赋予旧节点  
  34.     end;  
  35. end;  
  36.    s:=s.Substring(0,s.Length-1);  
  37.    for i := 1 to new_ln div 2 do //结束时需要判断是否为子节点,有几层  
  38.      s:=s+']}';  
  39.    result:=s+']';  
  40. end;  
  以上代码已经注释,有什么不明白的地方我们再交流,可以实现N多级树,只要客户端支持,有的控件是不支持多级树的。Tree实现了,我们再实现右键菜单,onContextMenu:
[javascript] view plaincopy
  1. onContextMenu: function(e, node){  
  2. e.preventDefault();  
  3. $(this).tree('select', node.target);  
  4. $('#mm').menu('show', {  
  5. left: e.pageX,  
  6. top: e.pageY  
  7. });  
  注意$('#mm')这个就是右键菜单的JQuery标识,我们做一个删除、添加功能,代码如下:
  1. <div id="mm" class="easyui-menu" style="width:120px;">  
  2. <div onclick="addnode()" data-options="iconCls:'icon-add'">添加</div>  
  3. <div onclick="removeit()" data-options="iconCls:'icon-remove'">删除</div>  
  4. </div>  

  提示:EasyUI很多情况下只需要引用$('')类似的标识就可以将其他控件加进去。实现addnode()、removeit()以及其他功能:

[javascript] view plaincopy
  1. <span style="white-space:pre">        </span>function appendn(r){//添加节点  
  2.             var t = $('#easyui_tt');  
  3.             var node =t.tree('getSelected');  
  4.             var pii=node.id;  
  5.             $.ajax({    
  6.                 type : "post",    
  7.                 url : "Treedata.php",    
  8.                 data : {Action:'Add',ID:pii,Title:r},    
  9.                 async : false,//这里必须用同步    
  10.                 success : function(data){    
  11.                     pii=data;  
  12.                 }    
  13.             });  
  14.             t.tree('append', {  
  15.                 parent: (node?node.target:null),  
  16.                 data: [{id:pii,text:r}]  
  17.             });  
  18.         }  
  19.         function removeit(){//删除节点  
  20.             var node = $('#easyui_tt').tree('getSelected');  
  21.             var pii=node.id;  
  22.             $.post('Treedata.php',{Action:'Del',ID:pii});  
  23.             $('#easyui_tt').tree('remove', node.target);  
  24.         }  
  25.         function collapse(){//树折叠  
  26.             var node = $('#easyui_tt').tree('getSelected');  
  27.             $('#easyui_tt').tree('collapse',node.target);  
  28.         }  
  29.         function expand(){//树展开  
  30.             var node = $('#easyui_tt').tree('getSelected');  
  31.             $('#easyui_tt').tree('expand',node.target);  
  32.         }  
  33.         function addnode(){//弹出添加节点对话框,用消息框  
  34.             $.messager.prompt('添加''请输入需要添加的名称:'function(r){  
  35.                 if (r){  
  36.                 appendn(r);   
  37.                 }  
  38.             });  
  39.         }  

  这段代码是用JQuery实现向IW提交数据,即把data以JSon格式提交到服务器$.post('Treedata.php',{Action:'Del',ID:pii});提交删除功能,是$.ajax的简单实现,顺便说一下,万一的博客提到
[javascript] view plaincopy
  1. function TestPost(){  
  2.     var mydata="TestMYPost测试一下";  
  3.     executeAjaxEvent("&data="+mydata, null"DoCallBack1"falsenullfalse);  
  4.     //中文在IE下乱码  
  5. }  
  这样提交数据,用WebApplication.RegisterCallBack('IWCallBack1', DoCallBack1) 注册回调接收数据,我觉得用JQuery的post实现更简单,IWForm内用$.post需要这样:
[javascript] view plaincopy
  1. $.post(GURLBase+"callback?",  
  2.          {callback:"DoCallBack1",data:"测试一下可以吗-----?"},  
  3.          function(data){processAjaxResponse(data);},"xml");//必须是xml格式  
  4. }//效果是一样的,也需要注册回调函数  
  注:GURLBase等于'/$/'(看着非常不爽的美元符号),修改一下万一的代码:
[javascript] view plaincopy
  1. function TestPost(){  
  2. var mydata=escape("TestMYPost测试一下");  
  3. executeAjaxEvent("&data="+mydata, null"DoCallBack1"falsenullfalse);//中文在IE下乱码,需要escape  
  4. }  
这样也支持中文了。
  服务器如何处理数据,登陆界面已经详解,基本类似,添加删除也不再列代码,大家可以直接看我的源码,用delphi实现真的很简易。
  Tree讲完,我们接着讲DataGrid:
  center这个DIV内加入:
  1. <table class="easyui-datagrid" style="width:100%;height:400px"   
  2. data-options="singleSelect:true,collapsible:true,fitColumns:true,url:'GridData.php',  
  3. method:'post',pageSize:10,pagination:true,onDblClickRow:onDClickRow"   
  4. <!--  
  5. 相同的属性不再说明,  
  6. singleSelect选择单行  
  7. collapsible定义是否显示可折叠按钮,EasyUI大部分控件继承自panel,一般可折叠  
  8. fitColumns列宽自适应  
  9. pageSize分页时每页显示的行数  
  10. pagination是否分布  
  11. -->  
  12. toolbar="#dg_tb"//工具栏,EasyUI可以这种方式嵌入其他控件  
  13. id="easyui_tb">  
  14. <thead><!--头部-->  
  15. <tr>  
  16. <th data-options="field:'codeID',width:80,halign:'center',editor:'text'">商品编号</th>  
  17. <!--field对应数据库字段  
  18.    halign标题居中  
  19. editor:'text'编辑样式为文本框  
  20. align:'center'整列居中  
  21. -->  
  22. <th data-options="field:'p_name',width:100,halign:'center',editor:'text'">名称</th>  
  23. <th data-options="field:'p_type',width:80,halign:'center',align:'center',editor:'text'">型号</th>  
  24. <th data-options="field:'p_tid',width:80,halign:'center',align:'center',editor:'text'">类别</th>  
  25. <th data-options="field:'p_pinpai',halign:'center',width:250,editor:'text'">品牌</th>  
  26. <th data-options="field:'p_price',halign:'center',width:60,align:'center',editor:'text'">价格</th>  
  27. <th data-options="field:'p_discount',halign:'center',width:60,align:'center',editor:'text'">折扣</th>  
  28. </tr>  
  29. </thead>  
  30. </table>  
  31. <div id="dg_tb" style="padding:3px"><!--工具栏-->  
  32. <span>商品编号</span>  
  33. <input id="codeID" class="easyui-numberbox" style="line-height:22px;border:1px solid #ccc">  
  34. <span>商品名称</span>  
  35. <input id="p_name" class="easyui-textbox" style="line-height:22px;border:1px solid #ccc">  
  36. <a href="#" class="easyui-linkbutton" plain="true" onclick="doSearch()">查询</a>  
  37. <a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" onclick="appendr();">添加</a>  
  38. <a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" onclick="remover()">删除</a>  
  39. <a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-save',plain:true" onclick="acceptr()">修改</a>  
  40. <a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-undo',plain:true" onclick="rejectr()">撤消</a>  
  41. </div>  
DataGrid功能强大,也很复杂,本文只讲基本应用,大家可以看我上传的EasyUI帮助文件。从服务器端获取表格数据同上,数据也是JSon格式的,建一个MyGridData,上面讲Tree时留下一下函数未讲解QueryByID(node.id),JS如下:
[javascript] view plaincopy
  1. function QueryByID(id){//以节点ID查询  
  2. var tb=$('#easyui_tb');  
  3. tb.datagrid({queryParams:{Action:'Q_ID',ID:id}});  
  4. /*queryParams是DataGrid提交数据时的参数, 
  5. 也可以直接:tb.datagrid('load',:{Action:'Q_ID',ID:id}}); 
  6. 但是在测试中发现,这样提交后数据为空时,表仍然显示有数据, 
  7. 也许是Bug,也许是我不会用。load即是post数据到服务器,同时 
  8. 接收返回数据,GridData全部封闭好了。 
  9. */  
  10. tb.datagrid('load');  
  11. }  

  以ID查询数据在服务器端这样实现:

[delphi] view plaincopy
  1. function QueryData(config:string):string;  
  2. var  
  3.  arrjson:JSONArray;  
  4.  ajson:JSONObject;  
  5.  i,j:integer;  
  6. begin  
  7.   arrjson:=JSONArray.Create;  
  8.   ajson:=JSONObject.Create;  
  9.   with UserSession.FDQuery1 do  
  10.    begin  
  11.       Open('select*from product where '+config);  
  12.       for I :=0 to RecordCount-1 do  
  13.        begin  
  14.          for j := 0 to Fields.Count-1 do  
  15.             ajson.Put(Fields.Fields[j].DisplayName,Fields.Fields[j].AsString);  
  16. //形成'{aaa:"BBB",ccc:"DDDD"}'这样的字符串,不需要拼接字符串了。  
  17.          arrjson.AddJSON(ajson.ToString(4));  
  18. //字面上理解就是JSon数组,即[{},{}];  
  19.          ajson.Clear;  
  20. //清除ajson内的数据,不然ajson会不停put数据,类似js的push用法          
  21.          Next;  
  22.        end;  
  23.   
  24.       
  25.    end;  
  26.   Result:='{"total":'+i.ToString+',"rows":'+arrjson.ToString(4)+'}';  
  27. //ToString(4)表示以4个空格缩进,不这样使用json数据会被转义  
  28. //datagrid数据多出的total是分页时用到的,表示总行数,rows表示当前显示页面   
  29. //如果不分页,可以直接: Result:=arrjson.ToString(4)';   
  30.   arrjson.Free;  
  31.   ajson.Free;  
  32.   
  33. end;  

  我是直接以查询条件为参数的,以便于扩展,这里用到了yxdJson,在我上传的控件中有,比较好用,其实就是形成 '{aaa:"BBB",ccc:"DDDD"}'这样的语句,特别简洁,不用拼接字符串(拼接字符串是很痛苦的)。Tree的数据我也想用的,但死活不 行,只好放弃。GridData是用服务器实现分页的,也特简单,即提交page和rows这个两个参数到服务器,代码大家自已下载,delphi实现也 非常简单,sql查询时加入limit (page-1)*rows,rows条件即可。注意字符串与整数的变换。实现查询、删除、添加、修改功能,客户端js:
[javascript] view plaincopy
  1. function doSearch(){//查询功能  
  2. $('#easyui_tb').datagrid('load',{  
  3. Action:'Q_DN',  
  4. id: $('#codeID').val(),  
  5. p_name: $('#p_name').val()  
  6. });}//load参数即可,上面有讲解  
  7. var editIndex = undefined;  
  8. var ExecType='';  
  9. function endEditing(){//结束编辑  
  10. if (editIndex == undefined){return true}  
  11. if ($('#easyui_tb').datagrid('validateRow', editIndex)){  
  12. var ed = $('#easyui_tb').datagrid('getEditor', {index:editIndex,field:'codeID'});  
  13. $('#easyui_tb').datagrid('endEdit', editIndex);  
  14. editIndex = undefined;  
  15. return true;  
  16. else {  
  17. return false;  
  18. }  
  19. }  
  20. function onDClickRow(index){//双击编辑整行数据  
  21. if (editIndex != index){  
  22. if (endEditing()){  
  23. var  tt=$('#easyui_tb').datagrid('selectRow', index);  
  24. var EditID=tt.datagrid('getSelected')['codeID'];//选择行的codeID值  
  25. tt.datagrid('beginEdit', index);  
  26. editIndex = index;  
  27. ExecType='update,'+EditID;//提交到服务器update  
  28. else {  
  29. $('#easyui_tb').datagrid('selectRow', editIndex);  
  30. //数据库必须依靠主键为标志来更新。  
  31. }  
  32. }  
  33. }  
  34. function appendr(){//添加  
  35. if (endEditing()){  
  36. $('#easyui_tb').datagrid('appendRow',{p_discount:'1.0'});  
  37. editIndex = $('#easyui_tb').datagrid('getRows').length-1;  
  38. $('#easyui_tb').datagrid('selectRow', editIndex)  
  39. .datagrid('beginEdit', editIndex);  
  40. //添加一行空行   
  41. ExecType='insert into,';//提交到服务器insert  
  42. }  
  43. }  
  44. function remover(){//删除  
  45. var  tt=$('#easyui_tb').datagrid('getSelected');//找到选择行  
  46. if (tt==undefined) return;  
  47. //没有选择就退出  
  48. var Delindex=$('#easyui_tb').datagrid('getRowIndex',tt);  
  49. //选择行的行号  
  50. var DelID=tt['codeID'];//主键,用于删除  
  51. $.messager.confirm('删除','您确认想要删除记录吗?',  
  52. function(r){ if (r){  
  53. $('#easyui_tb').datagrid('deleteRow', Delindex);  
  54. $.post('GridData.php',{Action:'delete',id:DelID});  
  55. //提交delete  
  56. }});    
  57. editIndex = undefined;//这个本程序没用上,是单击时用的  
  58. }  
  59. function acceptr(){//修改编辑的数据,添加或编辑后,需要修改数据,提交到服务器  
  60. //不修改只是客户端更新,服务器端数据库没变  
  61. if (endEditing()){  
  62. $('#easyui_tb').datagrid('acceptChanges');  
  63. if (ExecType==''return;  
  64. var selrow=$('#easyui_tb').datagrid('getSelected');  
  65. var row=new Array();  
  66. if(selrow!=undefined)  
  67. row.push(selrow['codeID'],selrow['p_name'],selrow['p_type'],selrow['p_tid'],  
  68.         selrow['p_pinpai'],selrow['p_price'],selrow['p_discount']);  
  69. //push就是将数据压入数组  
  70. var param=ExecType.split(',');//分割字符串为数组,delphi的用法类似  
  71. if(param[0]=='update')  
  72. {  
  73. $.post('GridData.php',{Action:param[0],id:param[1],Rowdata:row.toString()},function(data){alert(data)});  
  74. //update时要提交动作、codeID和更新后的数据,  
  75. //post的参数function(data){alert(data)就是服务器返回数据。  
  76. }  
  77. if(param[0]=='insert into')  
  78. {  
  79. $.post('GridData.php',{Action:param[0],Rowdata:row.toString()},function(data){alert(data)});  
  80. //insert时要提交动作和插入后的数据  
  81. }  
  82. ExecType='';  
  83. }  
  84. }  
  85. function rejectr(){//取消  
  86. $('#easyui_tb').datagrid('rejectChanges');  
  87. ExecType='';  
  88. editIndex = undefined;  
  89. }  
  90. function getChanges(){  
  91. var rows = $('#easyui_tb').datagrid('getChanges');  
  92. return rows;  
  93. }  
  服务器实现这些功能用下面这个函数:
function Exec_SQL(act,id,row:string):string;
  源码自己去看,很简单,就是操作数据库。本文基本完成,最后讲一下这种 方式未完成的功能:直接使用http://xxx.xxx.xxx/main.html可以不用登陆就能进入主界面,显然不是我们所期望的,可以在主界面 加入验证登陆的功能,也很简单,可以在页面加载之前$.post提交验证信息到login.php,里面代码已经写了,只是客户端没有添加。还有第三大 点。
  三、动态加载
  动态加载简单说就是,客户端还是单独做出来,不用放在wwwroot下面,引用js和css时需要在路径前面多加一个“/”即可。仍然从TContentBase 继承实现一个类,在函数中这样实现 :
[delphi] view plaincopy
  1. function TMyIndex.Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean;  
  2. var  
  3.  ss:Tstrings;  
  4. begin  
  5.   aReply.ContentType := MIME_HTML;  
  6.   ss:=TstringList.create;  
  7.   ss.loadformfile('做好静态页面');  
  8.   aReply.WriteString(ss.text);  
  9.   ss.free;  
  10.   Result := True;  
  11. end;  
  这样显而易见是比较安全的,可以在加载主界面前先验证有无登陆,还可以在加载页面中加一些类似模板替换标识,动态加载时,将这些标识替换成本页面需要展示的内容,实现header、body、footer共用。

  本文所需要工具:delphiXE7+Intraweb 14.0.38

 

源码 见   http://bbs.2ccc.com/topic.asp?topicid=479014

作者:zhang_y_b 录入:142857 来源:转载
共有评论 8相关评论
发表我的评论
  • 大名:
  • 内容:
本类推荐
本类固顶
  • 盒子文章 技术支持:深圳市麟瑞科技有限公司(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 粤ICP备10103342号-1