Intraweb之EasyUI篇

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基础)。
  第一步:实现登陆界面。

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

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

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

		function submitForm(){
			$('#ff').form('submit',{//这是EasyUI的Form自带功能,就是提交数据
				url:'Login.php', //需要把数据提交到的页面
				onSubmit:function(){//验证数据是否为空,如果为空就返回。
					return $(this).form('enableValidation').form('validate');
				},
				success: function(data){
//提交成功后的回调函数,data就是返回的数据
					if(parseInt(data)==1)
//我们在这里返回1和0,1表示成功登陆,在后台实现
					{
						window.location='main.html';
//登陆成功后,跳转到主程序
					}
					else
					{
						$.messager.alert('错误','用户名或密码错误!','error');
/*EasyUI消息提示框,就是alert的改进用法,显示警告窗口。
参数(依次调用):
title:在头部面板显示的标题文本。
msg:显示的消息文本。
icon:显示的图标图像。可用值有:error,question,info,warning。
fn: 在窗口关闭的时候触发该回调函数。 */
						$('#ff').form('clear');//清空数据,下同。
					}
				}    

				
			});
		}
		function clearForm(){
			$('#ff').form('clear');
		}

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

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

{新建Login 单元, 从 TContentBase 继承实现一个 TLogin 类}
unit Login;

interface
uses Classes, IW.Content.Base, System.SysUtils,HTTPApp, IWApplication, IW.HTTP.Request, IW.HTTP.Reply, IWMimeTypes;


type
  TLogin = class(TContentBase)
  protected
    function Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean; override;
  public
    constructor Create; override;
  end;

implementation
 uses ServerController,UserSessionUnit;
{ TLogin }

constructor TLogin.Create;
begin
  inherited;
  mFileMustExist := False;
end;

function TLogin.Execute(aRequest: THttpRequest; aReply: THttpReply; const aPathname: string; aSession: TIWApplication; aParams: TStrings): Boolean;
begin
  aReply.ContentType := MIME_HTML;
  aReply.WriteString('这里就是返回到客户端的数据');
  Result := True;
end;

end. 

{在 IWServerControllerBase.OnConfig  映射login.php}
uses
  IWInit, IWGlobal, IW.Content.Handlers, Login;

procedure TIWServerController.IWServerControllerBaseConfig(Sender: TObject);
begin
  THandlers.Add('', 'login.php', TLogin.Create);
//添加虚拟文件名,映射到服务器
end;

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

  第二步:实现主界面
  我们开发的是一个商品信息管理程序,主界面用EasyUI的Layout实现自适应浏览器(记得引入相关js和css):
<div data-options="region:'north',border:false" style="height:60px;background:#B3DFDA;padding:0px 10px;text-align:center">
<h3>商品信息管理系统</h3>
</div>
<div data-options="region:'west',split:true,title:'商品分类'" style="width:200px;padding:10px;">

</div>
<!--<div data-options="region:'east',split:true,collapsed:true,title:'East'" style="width:100px;padding:10px;">east region</div>-->
<div data-options="region:'south',border:false" style="height:50px;background:#A9FACD;padding:10px;">
京ICP证000000号
</div>
<div data-options="region:'center',title:'商品简要信息'">

</div>

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

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

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

<span style="white-space:pre">		</span>function appendn(r){//添加节点
			var t = $('#easyui_tt');
			var node =t.tree('getSelected');
			var pii=node.id;
			$.ajax({  
				type : "post",  
				url : "Treedata.php",  
				data : {Action:'Add',ID:pii,Title:r},  
				async : false,//这里必须用同步  
				success : function(data){  
					pii=data;
				}  
			});
			t.tree('append', {
				parent: (node?node.target:null),
				data: [{id:pii,text:r}]
			});
		}
		function removeit(){//删除节点
			var node = $('#easyui_tt').tree('getSelected');
			var pii=node.id;
			$.post('Treedata.php',{Action:'Del',ID:pii});
			$('#easyui_tt').tree('remove', node.target);
		}
		function collapse(){//树折叠
			var node = $('#easyui_tt').tree('getSelected');
			$('#easyui_tt').tree('collapse',node.target);
		}
		function expand(){//树展开
			var node = $('#easyui_tt').tree('getSelected');
			$('#easyui_tt').tree('expand',node.target);
		}
		function addnode(){//弹出添加节点对话框,用消息框
			$.messager.prompt('添加', '请输入需要添加的名称:', function(r){
				if (r){
				appendn(r);	
				}
			});
		}

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

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

function QueryData(config:string):string;
var
 arrjson:JSONArray;
 ajson:JSONObject;
 i,j:integer;
begin
  arrjson:=JSONArray.Create;
  ajson:=JSONObject.Create;
  with UserSession.FDQuery1 do
   begin
      Open('select*from product where '+config);
      for I :=0 to RecordCount-1 do
       begin
         for j := 0 to Fields.Count-1 do
            ajson.Put(Fields.Fields[j].DisplayName,Fields.Fields[j].AsString);
//形成'{aaa:"BBB",ccc:"DDDD"}'这样的字符串,不需要拼接字符串了。
         arrjson.AddJSON(ajson.ToString(4));
//字面上理解就是JSon数组,即[{},{}];
         ajson.Clear;
//清除ajson内的数据,不然ajson会不停put数据,类似js的push用法		 
         Next;
       end;

    
   end;
  Result:='{"total":'+i.ToString+',"rows":'+arrjson.ToString(4)+'}';
//ToString(4)表示以4个空格缩进,不这样使用json数据会被转义
//datagrid数据多出的total是分页时用到的,表示总行数,rows表示当前显示页面 
//如果不分页,可以直接: Result:=arrjson.ToString(4)'; 
  arrjson.Free;
  ajson.Free;

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

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

  源码


展开阅读全文

没有更多推荐了,返回首页