您现在的位置:首页 >> 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. ??
  3. ????????????<a?href="javascript:void(0)"?class="easyui-linkbutton"?onclick="clearForm()"?style="width:80px;float:right">取消a>??
  4. ????????div>??
  5. ????????div>??
  6. ????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. ??
  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<>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. <>"white-space:pre">????????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",?false,?null,?false);??
  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",?false,?null,?false);//中文在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. <tr>??
  6. <th?data-options="field:'codeID',width:80,halign:'center',editor:'text'">商品编号th>??
  7. ??
  8. <span>商品编号span>??
  9. <input?id="codeID"?class="easyui-numberbox"?style="line-height:22px;border:1px?solid?#ccc">??
  10. <span>商品名称span>??
  11. <input?id="p_name"?class="easyui-textbox"?style="line-height:22px;border:1px?solid?#ccc">??
  12. <a?href="#"?class="easyui-linkbutton"?plain="true"?onclick="doSearch()">查询a>??
  13. <a?href="javascript:void(0)"?class="easyui-linkbutton"?data-options="iconCls:'icon-add',plain:true"?onclick="appendr();">添加a>??
  14. <a?href="javascript:void(0)"?class="easyui-linkbutton"?data-options="iconCls:'icon-remove',plain:true"?onclick="remover()">删除a>??
  15. <a?href="javascript:void(0)"?class="easyui-linkbutton"?data-options="iconCls:'icon-save',plain:true"?onclick="acceptr()">修改a>??
  16. <a?href="javascript:void(0)"?class="easyui-linkbutton"?data-options="iconCls:'icon-undo',plain:true"?onclick="rejectr()">撤消a>??
  17. 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 来源:转载
共有评论 2相关评论
发表我的评论
  • 大名:
  • 内容:
本类推荐
本类固顶
  • 盒子文章(www.2ccc.com) ? 2019 版权所有 All Rights Reserved.
  • 沪ICP备05001939号