[转载]ASP.NET MVC 中实现View与Controller分离 - 脑瓜子 - 博客园

mikel阅读(1235)

[转载]ASP.NET MVC 中实现View与Controller分离 – 脑瓜子 – 博客园.

一、开篇题外话

 

我经常会在博客园逛来逛去,看过很多大牛们的Blog,我很少在这块技术天地活动,之前有发表过几篇日志,好像大部分是和电商有 关,作为一个多年的开发人员,很少在这里分享,之前一直在CSDN上活动,因为我的Blog在那上边的排名1000多名,我想好好维护好CSDN,但是我 发现越来越多的同行们都转战博客园。所以我也跟风来到此块宝地,我来了,你在哪?

 

二、分离的优点

1.松耦合:耦合是指一个系统的组件之间的相关程度。越少的组件相互依赖,那么这个系统的重用性和灵活性就越好。

2.更好的团队分工合作,专门的工程师负责Controller

IC376097

三、背景

在看博客园创始人@dudu博客的时候,发现他就是这样做的,这个是他的项目截图:

2012121411510365我想,我的项目中应该也要这样来实现,下面我们一步一步来分解。

四、实战

 

1、新建一个空的MVC 项目,命名为:NaoGuaZi.MvcExample12。如何新建在此不作一一介绍,

如果不分离的话,我们就开始在该项目下的Controllers文件夹添加Controller,但是我们现在的作法是将Controller作为一个单独的项目,这个项目仅仅用来做View的操作,那究竟怎么实现呢?

具体请猛击下载源码

2、新建一个类库,命名为NaoGuaZi.MvcExample12.Controllers 如下图所示

image

3、在此类库中添加System.Web.dll,System.Web.Abstractions.dll,System.Web.Mvc.dll,System.Web.Routing.dl的引用,如下图所示

image

4、新建一个 GlobalRoutesTable类,用来注册路由,通过该类衔接Controler与View,这个类会在View的Global.asax中Application_Start使用到。

按照国际惯例上代码

public static class GlobalRoutesTable
    {
        public static void RegisterRoutes(RouteCollection routes) {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
            //default   routes
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new string[] {"NaoGuaZi.MvcExample12.Controllers"}
            ); 
        }
    }

 

6、新建类HomeController类,该类继承System.Web.Mvc.Controller

    public class HomeController:Controller {
        public ViewResult Index() {
            return View();
        }
    }

7、将现有项目NaoGuaZi.MvcExample12.Controllers.dll添加到NaoGuaZi.MvcExample12项目中,然后在global.asax中的Application_Start中加入代码:

NaoGuaZi.MvcExample12.Controllers.GlobalRoutesTable.RegisterRoutes(RouteTable.Routes);

8、在NaoGuaZi.MvcExample12项目中的Views下新建Home文件夹,home文件夹下建index.cshtml 视图,然后Ctrl+F5运行项目,我们就可以看到成功运行的结果了。如下图所示:

image 在实践过程中可能出现的错误汇总:

错误1:如下图所示

 

 

image 错误原因:View中已经注册了一个Default的路由

解决办法:将Views中的默认的Default路由名称改成Default1或其他,或者将RegisterRoutes(RouteTable.Routes);注释掉。

五、延伸

 

可能大家会想到,如果在Controllers中建文件夹,这样更有利于层次分明,那该怎么实现呢?

博客园创始人@dudu的解决方案中提到了用Area来解决,然后到最后他采纳了评论中的配置路由的方案,经过我的测试,这中方案测试不通过,所以还是采用Area的方式来实现。我们紧接上面的内容

1、在NaoGuaZi.MvcExample12.Controllers项目中新建文件夹Admin

2、在Admin文件夹下新建AdminAreaRegistration类,该类继承AreaRegistration

3、在类中插入如下代码:

public class AdminAreaRegistration : AreaRegistration {
        public override string AreaName {
            get {
                return "Admin";
            }
        }
        public override void RegisterArea(AreaRegistrationContext context) {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new string[] {"NaoGuaZi.MvcExample12.Controllers.Admin"}
            );
        }
    }

4、新建HomeController类继承Controller

public ViewResult Index() {
            return View("~/Views/Admin/Home/Index.cshtml");
        }

5、在NaoGuaZi.MvcExample12项目中的Views下新建Admin/Home文件夹,新建名为Index.cshtml视图。然后Ctrl+F5运行,在浏览器中输入http://localhost:端口号/admin/home/index即可成功访问。

image

完整代码下载 VS2012打开,没有涉及到具体业务的实现,只涉及思想。

[转载]win32进阶之路:程序托盘图标+右键弹出菜单 - 赵大哥 - 博客园

mikel阅读(849)

[转载]win32进阶之路:程序托盘图标+右键弹出菜单 – 赵大哥 – 博客园.

   开场白

本次介绍两个非常棒且实用的技巧:程序托盘图标和右键弹出菜单,效果如下图。

程序托盘图标用了迅雷的图标,右键点击时候会弹出三个选项的菜单。

程序托盘图标设置

我会用尽可能清晰明了的步骤介绍方式来讲述,我假设大家已经动手写了属于自己的windows窗体,刚学习win32的朋友可以看一下我之前的博客,有介 绍如何从头创建属于自己的第一个windows窗口,也可以直接参照本文末尾贴出的完整代码做一些参考。如果大家觉得其他方式更好或者对讲述不理解的可以 评论或者发送给我的邮箱believing_dan@hotmail.com,QQ382128698.

步骤1:声明托盘图标对象并给关键成员赋值。

步骤2:通知windows在右下角区域添加图标。

步骤3:处理托盘图标的左键点击和右键点击消息。

步骤1/2的代码:

 

 

        void NotifySwitch(HWND hWND,TCHAR operation[4])
{
if(!strncmp(operation, TEXT(“MIN”), 3))
{
               //声明变量并初始化
NOTIFYICONDATA nID = {};
                //关联的托盘图标资源,图标需要是16*16或者32*32像素的
nID.hIcon = (HICON)LoadImage(NULL, TEXT(“notify.ico”), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
//托盘图标的提示语,即鼠标放在上面会弹出的提示
                strncpy_s(nID.szTip, TEXT(“自制锁屏软件卖萌中”), sizeof(TEXT(“自制锁屏软件卖萌中”)));
//托盘图标关联的窗口
                nID.hWnd = hWND;
//应用程序只有一个托盘图标的话可以随便设
                nID.uID = 1;
//托盘图标的类型,详解见MSDN
                nID.uFlags = NIF_GUID | NIF_ICON | NIF_MESSAGE | NIF_TIP;
//托盘图标关联的消息ID,托盘的左击和右击消息的消息ID就是它
                nID.uCallbackMessage = WM_MINMAXNotify;
//通知windows添加一个托盘图标,看参数就知道啦
                Shell_NotifyIcon(NIM_ADD, &nID);
}
}

步骤3的代码,即如何处理托盘关联的消息。

再次假设大家已经有了自己的windows窗体,完整代码参考本文最后贴出的代码。    

 

 

case WM_MINMAXNotify:
switch(lparam)
{
case WM_LBUTTONDOWN:
MessageBox(NULL, TEXT(“Recv notify icon message”), TEXT(“notify”), MB_ICONHAND);
break;
case WM_RBUTTONDOWN:
POINT pt;
GetCursorPos(&pt);
HMENU hMenu;
hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING , IDM_FIR, “秘籍”);
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_SEC, TEXT(“打怪”));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_THI, TEXT(“补给”));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, NULL, hwnd, NULL);
break;
}
break;

是 不是太简单了!呵呵,就这么简单,在windows的窗体处理函数中增加一个case处理托盘关联的消息,鼠标对托盘的动作可以通过lparam参数来获 取,这里我处理了左键和右键的单击消息,左键单击弹出一个提示框,右键单击托盘……好嘛,我已经漏题了,没错,右键的处理就是添加一个弹出菜单。

增加右键弹出菜单

步骤1:创建一个PopMenu对象。

步骤2:为新增加的弹出菜单增加菜单项。

步骤3:显示新增加的菜单。

步骤4:处理菜单项的消息。

又用4步就搞定了这么实用的技巧,是不是小激动呢?尽管前面已经漏题了,还是讲一下代码吧。

创建一个弹出菜单的HMENU句柄,菜单分很多种,需要用对应的创建API

HMENU hMenu = CreatePopupMenu();

插入一个菜单项,并给菜单项起一个字符名称,这里必须设置菜单项的类型是MF_STRING,并给菜单项关联一个ID

AppendMenu(hMenu, MF_STRING , IDM_FIR, “秘籍”);

插入一个分隔符,让菜单更好看,啥?没错,就是更好看一点

AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);

 

对比一下前面的截图,不一样的地方就是分隔符在搞鬼了。

获取到当前的鼠标位置并显示刚创建的弹出菜单,这里有一个小技巧,为什么不把弹出菜单和当前窗口关联起来呢,这样点选菜单后就会自动销毁菜单了。

POINT pt;

GetCursorPos(&pt);  

TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, NULL, hwnd, NULL);

弹出菜单的响应消息属于WM_COMMAND命令系列,通过wparam可以区分点击的菜单项。

case WM_COMMAND:

switch (wparam)

{

case IDM_FIR:

MessageBox(NULL, TEXT(“Recv popup menu idm_fir message”), TEXT(“Popup”), MB_ICONINFORMATION);

break;

case IDM_SEC:

MessageBox(NULL, TEXT(“Recv popup menu idm_sec message”), TEXT(“Popup”), MB_ICONASTERISK);

break;

case IDM_THI:

MessageBox(NULL, TEXT(“Recv popup menu idm_thi message”), TEXT(“Popup”), MB_ICONEXCLAMATION);

break;

default:

break;

}

break;

源代码链接说明:完整代码是还在完善中的一个锁屏软件代码,可能要费些功夫去寻找一下本文介绍的功能,当然也可能会对大家有一些额外的帮助,下面是锁屏软件的截图,中间的妹子可是会眨眼卖萌的哟,子窗口会逐渐漂移,碰到屏幕边缘会反弹回来。

锁屏软件持续更新中,欢迎大家关注我的博客。

代码及示例 http://download.csdn.net/detail/hd770c/6920757

[转载]使用HTML 5/CSS3五步快速制作便签贴特效 - 苍狼老贼 - 博客园

mikel阅读(842)

[转载]使用HTML 5/CSS3五步快速制作便签贴特效 – 苍狼老贼 – 博客园.

本篇文字将展示给你的是,如何利用HTML5/CSS3,仅用5步就可以制作便签贴效果的HTML页面,效果图如下:

(注:图里的文字纯属杜撰,搞笑目的,如有雷同,纯属巧合,谢谢!)

 

 

注:该效果可以在Safari, Chrome,Firefox和Opera在看到效果,IE上由于对HTML5的支持不完全,所以看不出效果。

第一步:创建基本HTML和正方形

首先添加基本的HTML结构以及构建基本的正方形,代码如下:

  1. <ul> 
  2.        <li><a href=“#”> 
  3.            <h2>Dudu:</h2> 
  4.            <p>最近咋没有美女发帖呢?我一定给个头条推荐,recommend!recommend!</p> 
  5.        </a></li> 
  6.        <li><a href=“#”> 
  7.            <h2>汤姆大叔:</h2> 
  8.            <p>Team的一个成员去了Microsoft做SDE3,又得hire new member了</p> 
  9.        </a></li> 
  10.        <li><a href=“#”> 
  11.            <h2>技术弟弟:</h2> 
  12.            <p>O2DS和我翻译的书是一样,我一定要比他翻得快, 晚上加班翻,fast! fast! fast!</p> 
  13.        </a></li> 
  14.        <li><a href=“#”> 
  15.            <h2>Artech:</h2> 
  16.            <p>WCF的帖子真是少,看来我得多发点帖子让大家学习呢</p> 
  17.        </a></li> 
  18.        <li><a href=“#”> 
  19.            <h2>吉日嘎拉:</h2> 
  20.            <p>将权限管理、工作流管理做到我能力的极致,一个人只能做好那么很少的几件事情</p> 
  21.        </a></li> 
  22.        <li><a href=“#”> 
  23.            <h2>某武林高手:</h2> 
  24.            <p>低于25000块的面试再也不去了,它grandma的</p> 
  25.        </a></li> 
  26.    </ul> 

每个note都加一个href连接,主要是为了支持键盘访问,CSS代码如下:

  1. *{    
  2.     margin:0;    
  3.     padding:0;    
  4.   }    
  5.   body{    
  6.     font-family:arial,sans-serif;    
  7.     font-size:100%;    
  8.     margin:3em;    
  9.     background:#666;    
  10.     color:#fff;    
  11.   }    
  12.   h2,p{    
  13.     font-size:100%;    
  14.     font-weight:normal;    
  15.   }    
  16.   ul,li{    
  17.     list-style:none;    
  18.   }    
  19.   ul{    
  20.     overflow:hidden;    
  21.     padding:3em;    
  22.   }    
  23.   ul li a{    
  24.     text-decoration:none;    
  25.     color:#000;    
  26.     background:#ffc;    
  27.     display:block;    
  28.     height:10em;    
  29.     width:10em;    
  30.     padding:1em;    
  31.   }    
  32.   ul li{    
  33.     margin:1em;    
  34.     float:left;    
  35.   } 

效果如下:

 

 

第二步:阴影和手写草体字

这一步,是我们要实现正方形的阴影效果,并且将字体改为草体(仅限英文),由于google提供了Font API的支持,所以我们可以直接使用了,首先添加对Google API的调用:

  1. <link href=“http://fonts.googleapis.com/css?family=Reenie+Beanie:regular” rel=“stylesheet” type=“text/css”> 

然后设置引用这个字体:

  1. ul li h2 
  2.        {  
  3.            font-size140%;  
  4.            font-weightbold;  
  5.            padding-bottom10px;  
  6.        }  
  7.        ul li p  
  8.        {  
  9.            font-family“Reenie Beanie” ,arial,sans-serif,微软雅黑;  
  10.            font-size110%;  
  11.        } 

关于阴影,由于各个浏览器还都不完全支持,所以需要分别处理,代码如下:

  1. ul li a  
  2.      {  
  3.          text-decorationnone;  
  4.          color#000;  
  5.          background#ffc;  
  6.          displayblock;  
  7.          height10em;  
  8.          width10em;  
  9.          padding1em/* Firefox */ 
  10.          -moz-box-shadow: 5px 5px 7px rgba(33,33,33,1); /* Safari+Chrome */ 
  11.          -webkit-box-shadow: 5px 5px 7px rgba(33,33,33,.7); /* Opera */ 
  12.          box-shadow: 5px 5px 7px rgba(33,33,33,.7);  
  13.      } 

效果如下:

 

 

第三步:倾斜正方形

为了让正方形倾斜,我们需要在li->a里添加如下代码:

  1. ul li a{    
  2.    -webkit-transform:rotate(-6deg);    
  3.    -o-transform:rotate(-6deg);    
  4.    -moz-transform:rotate(-6deg);    
  5.  } 

但是为了能让正方形随机倾斜,而不是全部都倾斜,我们需要使用新的CSS3选择器,让正方形在每2个倾斜4个deg,每3个倾斜负3个deg,每5个倾斜5个deg:

  1. ul li:nth-child(even) a{    
  2.      -o-transform:rotate(4deg);    
  3.      -webkit-transform:rotate(4deg);    
  4.      -moz-transform:rotate(4deg);    
  5.      position:relative;    
  6.      top:5px;    
  7.    }    
  8.    ul li:nth-child(3n) a{    
  9.      -o-transform:rotate(-3deg);    
  10.      -webkit-transform:rotate(-3deg);    
  11.      -moz-transform:rotate(-3deg);    
  12.      position:relative;    
  13.      top:-5px;    
  14.    }    
  15.    ul li:nth-child(5n) a{    
  16.      -o-transform:rotate(5deg);    
  17.      -webkit-transform:rotate(5deg);    
  18.      -moz-transform:rotate(5deg);    
  19.      position:relative;    
  20.      top:-10px;    
  21.    } 

效果如下:

 

第四步:Hover和Focus时放缩正方形

想在hover和focus的时候达到缩放的效果,我们需要添加如下代码:

  1. ul li a:hover,ul li a:focus{    
  2.   -moz-box-shadow:10px 10px 7px rgba(0,0,0,.7);    
  3.   -webkit-box-shadow: 10px 10px 7px rgba(0,0,0,.7);    
  4.   box-shadow:10px 10px 7px rgba(0,0,0,.7);    
  5.   -webkit-transform: scale(1.25);    
  6.   -moz-transform: scale(1.25);    
  7.   -o-transform: scale(1.25);    
  8.   position:relative;    
  9.   z-index:5;    
  10. }  

设置z-index为5是为了让正方形在放大的时候盖住其它的正方形,同时因为也设置了focus,所以也支持Tab键切换访问,效果如下:

 

 

第五步:平滑过渡和添加颜色

第四步的特效,看起来有些生硬,我们可以添加Transition来达到平滑动画的效果,另外颜色比较单一,我们可以设置一下不同的颜色,首先在ul->li->a里添加Transition:

  1. -moz-transition:-moz-transform .15s linear;    
  2.  -o-transition:-o-transform .15s linear;    
  3.  -webkit-transition:-webkit-transform .15s linear;   

然后在even和3n里定义不同的颜色:

  1. ul li:nth-child(even) a{    
  2.       -o-transform:rotate(4deg);    
  3.       -webkit-transform:rotate(4deg);    
  4.       -moz-transform:rotate(4deg);    
  5.       position:relative;    
  6.       top:5px;    
  7.       background:#cfc;    
  8.     }    
  9.     ul li:nth-child(3n) a{    
  10.       -o-transform:rotate(-3deg);    
  11.       -webkit-transform:rotate(-3deg);    
  12.       -moz-transform:rotate(-3deg);    
  13.       position:relative;    
  14.       top:-5px;    
  15.       background:#ccf;    
  16.     } 

这样,就完成了我们最终的效果:

 

 

总结

至此,我们利用了HTML5和CSS3的基本特性做成了一个还不错的便签贴效果,HTML5/CSS3确实很强大,如果在加一些高级特性,比如和JavaScript结合起来,能实现更加牛逼的效果,从当耐特砖家给大家的HTML5实验室系列文章,就可以看出来了。

[转载]在Visual Studio上开发Node.js程序 - 大魔王mAysWINd - 博客园

mikel阅读(996)

[转载]在Visual Studio上开发Node.js程序 – 大魔王mAysWINd – 博客园.

【题外话】

最近准备用Node.js做些东西,于是找找看能否有Visual Studio上的插件以方便开发。结果还真找到了一个,来自微软的Node.js Tools for Visual Studio(NTVS),虽然现在仅发布了1.0 Alpha版本,但使用起来已经非常方便。而且,其开发团队与Python Tools for Visual Studio(PTVS)是同一个,而PTVS就是Visual Studio 2013中要创建自带的Python项目需要安装的那个程序,所以大可放心的使用NTVS。

 

【文章索引】

  1. NTVS介绍与安装
  2. NTVS项目创建和使用
  3. NTVS项目的调试
  4. NTVS项目的包管理

 

【一、NTVS介绍与安装】

从其官网(http://nodejstools.codeplex.com) 上可以找到其介绍,NTVS是一个使Visual Studio成为Node.js集成开发环境的免费、开源的插件,NTVS支持编辑、Intellisense、Profiling、npm包管理器、本 地以及远程调试(Windows、MacOS及Linux),同时其支持Windows Azure网站及云服务。

总之,该有的都有了。如果要安装NTVS的话,需要VS 2013或2012 Update4的Professional(或Test Professional)、Premium或Ultimate版本,同时需要安装有Node.js的0.10.20或以上的版本,有了这些准备后,就可 以去官网下载安装包进行安装了,需要注意的是,VS 2013和2012的安装包是各自独立的。

安装完成后,就会在Visual Studio的JavaScript类型中多出以下的项目类型:

 

【二、NTVS项目创建和使用】

对于Node.js而言,项目类型并不像.NET项目有这么多不同的类型,每种之间的开发环境等还有差异。对于上面的Blank Node.js Console Application和Web Application两个项目而言,无非就是前者模板的代码只提供了在控制台输出Hello World的代码;而后者则用Node.js创建了一个Http服务器,并为每个请求都输出Hello World罢了,即实现了一个简单的Web应用程序。而Express Application则是使用Node.js上的Express框架+Jade模板引擎+Stylus实现了一个小的Web应用程序。而剩下的第一个项 目则是从已有的Node.js项目中创建,后两个与其他的类似,只不过已经配置好了脚本和配置文件等可以直接部署到Windows Azure中。

项目创建后与Visual Studio的C#等项目没有太大区别,Intellisense功能也非常强大,敲入require的时候会提示所有的模块名称,同时选择每个模块的时 候会提示这个模块的作用和说明(如下图),并且键入回车可以直接补齐单引号等等,都非常方面。而对于每个模块,其所有方法和成员变量也都能自动显示出来, 只不过不像require那样会显示说明信息。

 

【三、NTVS项目的调试】

NTVS项目调试的方式与C#一样,都是F5运行并调试和Ctrl+F5只运行不调试,其会自动运行已安装的Node程序执行当前项目的代码。对于 Web Application项目并且使用了使用了http模块的话,还会自动打开浏览器访问指定的端口(可以在项目属性中关闭)。需要说明的是,对于 Node.js项目,有且仅有一个启动文件(相当于程序的Main()函数),程序从这个文件的开始执行,默认情况下项目创建后第一个创建的js文件为启 动文件,启动文件用粗体表示。如果需要设置其他文件为启动文件,右键单击选择设置就可以了(如下图) 。

在调试过程中,与其他项目一样,都可以设置断点、单步执行以及监视什么的都是可以用的,同时如果在程序代码中抛出了异常,在调试过程中也会提示出来(如下图)。

默认情况下,所有异常都将提示,当然也可以自己选择哪些异常不提示。可以在提示了异常之后选择“打开异常设置”,或者选择“调试”菜单,选择“异常”,如下图:

 

【四、NTVS项目的包管理】

NTVS还提供了非常方便的包管理方式,就如同在C#项目中添加引用一样方便的添加其他包。当然也可以自己使用npm安装相应的包,然后在项目中使 用,虽然调试运行没有问题,不过这样是没有Intellisense提示的。所以,如果项目中需要其他的包,可以右键单击npm,选择“Manage npm Modules…”(如下图),在npm包管理器中右侧的包名称中输入包的名称,然后点击下方的本地安装(为当前项目安装)就可以了,完成后会在左侧 出现已安装的包,然后在项目中require也会出现相应的包名,在使用包的时候也会有方法成员的提示等等。

安装完包后就会在解决方案管理器的npm下出现相应的包名,与C#项目添加引用类似。同时,与执行npm ls命令一样,也是可以查看包的依赖关系的(如下图)。

【相关链接】

  1. Introducing node.js Tools for Visual Studio:http://www.hanselman.com/blog/IntroducingNodejsToolsForVisualStudio.aspx
  2. [Visual Studio]NTVS – Node.js Tools For Visual Studio Bootcamp:http://www.dotblogs.com.tw/blackie1019/archive/2013/12/27/136557.aspx
  3. Microsoft Joins Forces with RedGate and Clickberry to Offer Node.js Tools for Visual Studio:http://www.infoq.com/news/2013/12/NTVS

[转载]用node-webkit把web应用打包成桌面应用 - 无双 - 博客园

mikel阅读(1104)

[转载]用node-webkit把web应用打包成桌面应用 – 无双 – 博客园.

node-webkit是 一个Chromium和node.js上的结合体,通过它我们可以把建立在chrome浏览器和node.js上的web应用打包成桌面应用,而且还可以 跨平台的哦。很显然比起传统的桌面应用,在某些特定领域用html5+css3+js开发的web应用更加简单和高效,而且还可以使用node.js的功 能,所以node-webkit还是很有用处的。

下面我通过一个简单的demo来介绍怎么样把一个web应用打包成一个可执行文件(这里只介绍windows环境)

首先新建一个index.html文件,作为我们这个demo的入口页面,我们暂且就把这个页面当成一个完整的web应用吧。内容随便写点什么,比如:

QQ截图20140210135428

然后创建配置文件 package.json,内容如下:

QQ截图20140210135428

其中的main属性就是用来指定入口文件的,这个属性的值可以是本地文件,也可以是远程网址,这样就相当于可以把一个远程的web应用直接变为一个桌面应用了。

除了name与main这两个属性外,还有很多其他有用的属性可以配置,比如指定应用的图标,显不显示浏览器的工具栏,指定浏览器的初始大小等等,具体的配置参数文档可看这里https://github.com/rogerwang/node-webkit/wiki/Manifest-format

 

现在我们有了两个文件了。

QQ截图20140210135428

 

然后将index.html和package.json这两个文件压缩到一个zip压缩包里,命名为app.zip

QQ截图20140210135428

 

现在app.zip这个压缩包里的内容应该是这样的:

QQ截图20140210135428

 

然后把app.zip这个文件的扩展名改为nw,变为 app.nw

QQ截图20140210135428

 

然后下载一个windows版本的node-webkit,解压后得到一个文件夹:

QQ截图20140210135428

 

之后我们之前得到的app.nw这个文件就可以用nw.exe来执行了,直接把app.nw拖到nw.exe上就可以了。运行结果如下:

QQ截图20140210135428

跟在chrome中打开index.html这个页面的效果差不多,当然你可以通过配置package.json这个文件,来隐藏浏览器的工具栏或边框,来使它更像是一个桌面软件。

 

因为nw文件的运行需要node-webkit环境的支持,所以我们还需要把app.nw这个文件跟node-webkit的环境文件一起打包成一个可执行文件。

首先打开windows的cmd,然后输入如下命令:

copy /b nw.exe+app.nw app.exe

注意文件路径要根据你的实际情况进行变动,这里假设app.nw放在了node-webkit的主文件夹里,然后输出的app.exe也会在这个文件夹里。

执行命令后我们得到了 app.exe 这个可执行文件。

QQ截图20140210135428

 

到了这步,我们已经得到了app.exe这个文件,但如果只有app.exe这个文件还是不够的,这个可执行文件的运行还需要几个dll文件的支持。

其中 nw.pak 与 icudt.dll 这个两个文件是必须要的。

ffmpegsumo.dll 文件是媒体支持文件,如果你的html页面中用到了<video>或<audio>或其它与媒体相关的东西,则必须带上这个文件。

libEGL.dll 和 libGLESv2.dll 这个两个文件则是使用webGL或GPU必须要的

 

最后我们得到的就是这样一个文件夹:

QQ截图20140210135428

执行app.exe就可以运行我们的demo了。

 

但我们大多数人想的是给用户一个exe文件,用户就可以使用了,不用再附带一些其他文件。

嗯,所以我们还可以把app.exe跟其他的文件再打包一次,把上图中的所有文件变成一个可执行文件,用户只要得到这个文件,就能运行我们的应用了。

做这步我们需要一个软件叫Enigma Virtual Box,首先下载和安装这个软件,然后打开它。

然后在Enter Input File Name那里输入我们的app.exe的路径,在Enter Output File Name那里填写我们要把打包出来的可执行文件输出到哪里。最后是把除app.exe外的其它文件拖入到Files那里,遇到提示的话默认就可以了。

QQ截图20140210135428

 

最后点击右下角的Process按钮,就大功告成了。

QQ截图20140210135428

 

最后我们得到了一个 app_boxed.exe 的文件,只要把这个文件交给用户,用户就可以运行了。

node-webkit虽然方便,但有个很大的缺点是得到的可执行文件有点大,大家在可以在衡量利弊后决定使不使用。

[转载]Android SQLite编程详解 - IF_ONLY - 博客园

mikel阅读(1064)

[转载]Android SQLite编程详解 – IF_ONLY – 博客园.

数据库功能非常强大,使用起来也非常方便,SQLite数据库的一般操作包括:创建数据库、打开数据库、创建表、向表中添加数据、从表中删除数据、修改表中的数据、关闭数据库、删除指定表、删除数据库和查询表中的某条数据。下面我们分别来学习这些基本操作。

1.创建和打开数据库

Android 中创建和打开一个数据库都可以使用openOrCreateDatabase 方法来实现,因为它会自动去检测是否存在这个数据库,如果存在则打开,不过不存在则创建一个数据库;创建成功则返回一个 SQLiteDatabase对象,否则抛出异常FileNotFoundException。下面我们来创建一个名 为”Examples_06_05.db”的数据库,并返回一个SQLiteDatabase对象 mSQLiteDatabase。

1
mSQLiteDatabase = this.openOrCreateDatabase("Example_06_05.db", MODE_PRIVATE, null);

2.创建表

一个数据库中可以包含多个表,我们的每一条数据都保存在一个指定的表中,要创建表可以通过execSQL 方法来执行一条SQL语句。execSQL能够执行大部分的SQL语句,下面我们来创建一个名为table1 且包含3个字段的表。 具体代码如下:

1
2
String CREATE_TABLE = "CREATE TABLE table1 (_id INTEGER PRIMARY KEY, num INTEGER,  data TEXT)";
mSQLiteDatabase.execSQL(CREATE_TABLE);

3.向表中添加一条数据

可以使用insert 方法来添加数据,但是 insert 方法要求把数据都打包到 ContentValues 中, ContentValues 其实就是一个Map, key值是字段名称, Value值是字段的值。通过 ContentValues 的 put 方法就可以把数据放到ContentValues中,然后插入到表中去。具体实现如下:

1
2
3
4
5
6
7
8
ContentValues  cv  =  new ContentValues();
cv.put(TABLE_NUM, 1);
cv.put(TABLE_DATA, "测试数据");
mSQLiteDatabase.insert(TABLE_NAME, null, cv);

  //这样同样可以使用execSQL方法来执行一条“插入”的SQL语句,代码如下:
String  INSERT_DATA = "INSERT INTO table1 (_id, num, data) values (1, 1, '通过SQL语句插入')" ;
mSQLiteDatabase.execSQL(INSERT_DATA);

4.从表中删除数据

要删除数据可以使用delete 方法,下面我们删除字段 “_id” 等于1的数据,具体代码如下:

1
2
3
4
mSQLiteDatabase.delete("Examples_06_05.db", " where_id="+0, null);
通过 execSQL方法执行SQL语句删除数据如下:
String  DELETE_DATA = "DELETE FROM table1 WHERE _id=1";
mSQLiteDatabase.execSQL(DELETE_DATA);

5.修改表中的数据

如果添加了数据后发现数据有误,这时需要修改这个数据,可以使用updata方法来更新一条数据。下面我们来修改 “num” 值为0的数据,具体代码如下:

1
2
3
4
ContentValues cv = new ContentValues();
cv.put(TABLE_NUM, 3);
cv.put(TABLE_DATA, "修改后的数据");
mSQLiteDatabase.update("table1" cv, "num " + "=" + Integer.toString(0), null);

6.关闭数据库

关闭数据库很重要,也是大家经常容易忘记的。关闭的方法很简单,直接使用SQLiteDatabase 的 close 方法。具体代码如下:

1
mSQLiteDatabase.close();

7.删除指定表

这里我们使用execSQL方法来实现,具体代码如下:

1
 mSQLiteDatabase.execSQL("DROP TABLE table1");

8.删除数据库

要删除一个数据库,直接使用deleteDatabase 方法即可,具体代码如下:

1
     this.deleteDatabase("Examples_06_05.db");

9.查询表中的某条数据

Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:

方法 说明
move 以当前的位置为参考,将Cursor移动到指定的位置,成功返回true, 失败返回false

moveToPosition 将Cursor移动到指定的位置,成功返回true,失败返回false

moveToNext 将Cursor向前移动一个位置,成功返回true,失败返回false

moveToLast 将Cursor向后移动一个位置,成功返回true,失败返回 false。

movetoFirst 将Cursor移动到第一行,成功返回true,失败返回false

isBeforeFirst 返回Cursor是否指向第一项数据之前

isAfterLast 返回Cursor是否指向最后一项数据之后

isClosed 返回Cursor是否关闭

isFirst 返回Cursor是否指向第一项数据

isLast 返回Cursor是否指向最后一项数据

isNull 返回指定位置的值是否为null

getCount 返回总的数据项数

getInt 返回当前行中指定的索引数据

下面我们就是用Cursor来查询数据库中的数据,具体代码如下:

1
2
3
4
5
6
7
8
9
Cursor cur = mSQLiteDatabase.rawQuery("SELECT * FROM table", null);
if( cur != null ){
   if( cur.moveToFirst() ){
       do{
                  int numColumn = cur.getColumnIndex("num");
                  int num            = cur.getInt(numColumn);
            }while( cur.moveToNext());
      }
 }

[转载]LuManager中的Nginx让支持pathinfo - 帮助中心 - LuManager(LUM)官方授权代理商[双赢网络]

mikel阅读(1016)

[转载]LuManager中的Nginx让支持pathinfo – 帮助中心 – LuManager(LUM)官方授权代理商[双赢网络].

1、网站管理中找到要支持PATHINFO的网站,然后点击右边的“修改”。
2、找到 Nginx扩展设置(location段).
3、在location中填入下列:


    location ~* \.(php[3-9]?|phtm[l]?)(\/.*)*$ {
    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:8999;
    include      fastcgi_params;
    set $path_info "";
    set $real_script_name $fastcgi_script_name;
    if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
    set $real_script_name $1;
    set $path_info $2;
    }
    fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
    fastcgi_param SCRIPT_NAME $real_script_name;
    fastcgi_param PATH_INFO $path_info;
    }

4、保存并重启Nginx服务即可。
测试代码:


    正常情况下,你可以看到it works

    如果您点击下面的链接还是可以看到上面的文字而不是404,说明支持pathinfo

    index.php/home

    PATH_INFO:
            echo $_SERVER['PATH_INFO'];
    ?>

[转载]让Nginx支持ThinkPHP的URL重写和PATHINFO - 潺莪 - 博客园

mikel阅读(930)

[转载]让Nginx支持ThinkPHP的URL重写和PATHINFO – 潺莪 – 博客园.

ThinkPHP支持通过PATHINFO和URL rewrite的方式来提供友好的URL,只需要在配置文件中设置 ‘URL_MODEL’ => 2 即可。在Apache下只需要开启mod_rewrite模块就可以正常访问了,但是Nginx中默认是不支持PATHINFO的,所以我们需要修改 nginx.conf文件。

网上搜了很多方法都不奏效,研究了一天,发现通过以下的配置可以完美支持 ‘URL_MODEL’ => 2 的情况了

location /project/ {
    index  index.php;
    if (!-e $request_filename) { 
        rewrite  ^/project/(.*)$  /project/index.php/$1  last;
        break;
    }
}

location ~ .+\.php($|/) {
    set $script    $uri;
    set $path_info  "/";
    if ($uri ~ "^(.+\.php)(/.+)") {
        set $script     $1;
        set $path_info  $2;
     }
         
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index  index.php?IF_REWRITE=1;
    include /APMServ/nginx/conf/fastcgi_params;
    fastcgi_param PATH_INFO $path_info;
    fastcgi_param SCRIPT_FILENAME  $document_root/$script;
    fastcgi_param SCRIPT_NAME $script;
}

这里先把project下的请求都转发到index.php来处理,亦即ThinkPHP的单一入口文件;然后把对php文件的请求交给fastcgi来处理,并且添加对PATH_INFO的支持。

重启Nginx以后,http://localhost/project/Index/insert, http://localhost/project/index.php/Index/delete 这样的URL都可以正确访问了。

还有一个地方需要注意的是,Nginx配置文件里 if 和后面的括号之间要有一个空格,不然会报unknown directive错误。

[转载]android ExpandableListView实现不同的布局 - 上风华 - 博客园

mikel阅读(876)

[转载]android ExpandableListView实现不同的布局 – 上风华 – 博客园.

最近有一个需求要实现listview的不同布局!因为有好几上header,就想到了ExpandableListView!

这个是我的需求模型:看图(自己画的)

然后百度~google~发帖~总算有点效果了!其他的就不多说了。直接主要代码讲解–

 

主要是适配器的部分:ExpandableListAdapter.jave

 

public class ExpandableListAdapter extends BaseExpandableListAdapter {
    // Client Status
    private String mClient_id;
    private String mClient_name;
    private String mClient_realid;
    private String mClient_totally;
    // Stocks's product
    private String mStocks;
    private String mStocks_name;
    private String mStocks_counts;
    private String mStocks_cost;
    private String mStocks_now;
    private String mStocks_mark;
    // Moreprofit's product
    private String mMoreprofit;
    private String mMoreprofit_name;
    private String mMoreprofit_counts;
    private String mMoreprofit_rate;
    private String mMoreprofit_years;
    private String mMoreprofit_mark;
 
    // Pes's product
    private String mPes;
    private String mPes_projects;
    private String mPes_invest_amount;
    private String mPes_mark;
 
    private Context mContext;
 
    private final int VIEW_TYPE = 3;
    private final int TYPE_1 = 0;
    private final int TYPE_2 = 1;
    private final int TYPE_3 = 2;
 
    private LayoutInflater mLayoutInflater;
 
    // private HandleClick mHandleClick;
    private String[] mProduct_what = new String[] { "xx类产品", "xx收益类产品", "xx类投资" };
    private String[][] mProduct_what_items = {
            { "产品名称", "持有数量", "买入成本", "当前净值", "备注" },
            { "产品名称", "持有数量", "年收益率", "期限", "备注" }, { "项目", "投资金额", "备注" } };
 
    public ExpandableListAdapter(Context mContext) {
        mLayoutInflater = LayoutInflater.from(mContext);
        this.mContext = mContext;
    }
 
    public ExpandableListAdapter(Context mContext, String mClient_id,
            String mClient_name, String mClient_realid, String mClient_totally,
            String mStocks, String mStocks_name, String mStocks_counts,
            String mStocks_cost, String mStocks_now, String mStocks_mark,
            String mMoreprofit, String mMoreprofit_name,
            String mMoreprofit_counts, String mMoreprofit_rate,
            String mMoreprofit_years, String mMoreprofit_mark, String mPes,
            String mPes_projects, String mPes_invest_amount, String mPes_mark) {
        // super();
        this.mClient_id = mClient_id;
        this.mClient_name = mClient_name;
        this.mClient_realid = mClient_realid;
        this.mClient_totally = mClient_totally;
        this.mStocks = mStocks;
        this.mStocks_name = mStocks_name;
        this.mStocks_counts = mStocks_counts;
        this.mStocks_cost = mStocks_cost;
        this.mStocks_now = mStocks_now;
        this.mStocks_mark = mStocks_mark;
        this.mMoreprofit = mMoreprofit;
        this.mMoreprofit_name = mMoreprofit_name;
        this.mMoreprofit_counts = mMoreprofit_counts;
        this.mMoreprofit_rate = mMoreprofit_rate;
        this.mMoreprofit_years = mMoreprofit_years;
        this.mMoreprofit_mark = mMoreprofit_mark;
        this.mPes = mPes;
        this.mPes_projects = mPes_projects;
        this.mPes_invest_amount = mPes_invest_amount;
        this.mPes_mark = mPes_mark;
        this.mContext = mContext;
 
        mLayoutInflater = LayoutInflater.from(mContext);
    }
 
    @Override
    public Object getChild(int arg0, int arg1) {
        return null;
    }
 
    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return 0;
    }
 
    public int getItemViewType(int groupPosition) {
        int p = groupPosition;
        if (p == 0) {
            return TYPE_1;
        } else if (p == 1) {
            return TYPE_2;
        } else if (p == 2) {
            return TYPE_3;
        } else {
            return TYPE_1;
        }
    }
 
    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        int type = getItemViewType(groupPosition);
        switch (type) {
        case TYPE_1:
            convertView = mLayoutInflater.inflate(R.layout.item_table, null);
            TextView mProduct_name_1 = (TextView) convertView
                    .findViewById(R.id.product_name);
            TextView mProduct_counts_1 = (TextView) convertView
                    .findViewById(R.id.product_count);
            TextView mProduct_cost_1 = (TextView) convertView
                    .findViewById(R.id.product_cost);
            TextView mProduct_status_1 = (TextView) convertView
                    .findViewById(R.id.product_status);
            TextView mProduct_mark_1 = (TextView) convertView
                    .findViewById(R.id.product_mark);
            //这里是自定义一个子item的,当position==0时显示标题栏
            switch (childPosition) {
            case 0:
                mProduct_name_1.setText(mProduct_what_items[0][0]);
                mProduct_counts_1.setText(mProduct_what_items[0][1]);
                mProduct_cost_1.setText(mProduct_what_items[0][2]);
                mProduct_status_1.setText(mProduct_what_items[0][3]);
                mProduct_mark_1.setText(mProduct_what_items[0][4]);
                break;
 
            default:
                mProduct_name_1.setText("888");
                mProduct_counts_1.setText("888");
                mProduct_cost_1.setText("888");
                mProduct_status_1.setText("888");
                mProduct_mark_1.setText("888");
                break;
 
            }
            break;
 
        case TYPE_2:
            convertView = mLayoutInflater.inflate(R.layout.item_table, null);
            TextView mProduct_name_2 = (TextView) convertView
                    .findViewById(R.id.product_name);
            TextView mProduct_counts_2 = (TextView) convertView
                    .findViewById(R.id.product_count);
            TextView mProduct__rate_2 = (TextView) convertView
                    .findViewById(R.id.product_cost);
            TextView mProduct__years_2 = (TextView) convertView
                    .findViewById(R.id.product_status);
            TextView mProduct_mark_2 = (TextView) convertView
                    .findViewById(R.id.product_mark);
            //这里是自定义一个子item的,当position==0时显示标题栏
            switch (childPosition) {
            case 0:
                mProduct_name_2.setText(mProduct_what_items[1][0]);
                mProduct_counts_2.setText(mProduct_what_items[1][1]);
                mProduct__rate_2.setText(mProduct_what_items[1][2]);
                mProduct__years_2.setText(mProduct_what_items[1][3]);
                mProduct_mark_2.setText(mProduct_what_items[1][4]);
                break;
 
            default:
                mProduct_name_2.setText("888");
                mProduct_counts_2.setText("888");
                mProduct__rate_2.setText("888");
                mProduct__years_2.setText("888");
                mProduct_mark_2.setText("888");
                break;
            }
 
            break;
        case TYPE_3:
            convertView = mLayoutInflater.inflate(R.layout.item_table_p, null);
            TextView mProject_name_3 = (TextView) convertView
                    .findViewById(R.id.project_name);
            TextView mProject_invest_amount_3 = (TextView) convertView
                    .findViewById(R.id.project_invest_amount);
            TextView mProject_mark = (TextView) convertView
                    .findViewById(R.id.project_mark);
             
            //这里是自定义一个子item的,当position==0时显示标题栏
            switch (childPosition) {
            case 0:
                mProject_name_3.setText(mProduct_what_items[2][0]);
                mProject_invest_amount_3.setText(mProduct_what_items[2][1]);
                mProject_mark.setText(mProduct_what_items[2][2]);
                break;
            default:
 
                mProject_name_3.setText("888");
                mProject_invest_amount_3.setText("888");
                mProject_mark.setText("888");
                break;
            }
 
            break;
        }
 
        return convertView;
    }
 
    @Override
    public int getChildrenCount(int groupPosition) {
        return 1;
    }
 
    @Override
    public Object getGroup(int groupPosition) {
        return null;
    }
 
    @Override
    public int getGroupCount() {
        return mProduct_what.length;
        // return 0;
    }
 
    @Override
    public long getGroupId(int groupPosition) {
        return 0;
    }
 
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        int type = getItemViewType(groupPosition);
        switch (type) {
        case TYPE_1:
            convertView = mLayoutInflater.inflate(R.layout.header_table, null);
            TextView mProduct_what_1 = (TextView) convertView
                    .findViewById(R.id.product_what_1);
 
            mProduct_what_1.setText(mProduct_what[groupPosition]);
 
            break;
 
        case TYPE_2:
            convertView = mLayoutInflater
                    .inflate(R.layout.header_table_f, null);
            TextView mProduct_what_2 = (TextView) convertView
                    .findViewById(R.id.product_what_2);
 
            mProduct_what_2.setText(mProduct_what[groupPosition]);
 
            break;
        case TYPE_3:
            convertView = mLayoutInflater
                    .inflate(R.layout.header_table_p, null);
            TextView mProject_what_3 = (TextView) convertView
                    .findViewById(R.id.project_what_3);
 
            mProject_what_3.setText(mProduct_what[groupPosition]);
 
            break;
        }
        return convertView;
    }
 
    @Override
    public boolean hasStableIds() {
        return false;
    }
 
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }
 
}

[转载]把JSON数据载入到页面表单的两种思路(对easyui自带方法进行改进) - p2227 - 博客园

mikel阅读(1240)

[转载]把JSON数据载入到页面表单的两种思路(对easyui自带方法进行改进) – p2227 – 博客园.

背景

项目中经常需要把JSON数据填充到页面表单,一开始我使用easyui自带的form load方法,觉得效率很低,经常在载入数据的时候有假死现象(实际项目中的表单一般都100-200个字段以上),而且不能处理 radio/checkbox的情况。(easyui的思路是把它们都用combo去处理)

思路

问题可以转化为,现在有一堆JSON数据,有一个表单,可能是一一对应的,要把这个数据填写到表单上,一般说来有两种思路

  1. 方案一针对数据,一个个选择元素进行填充
  2. 方案二先选择所有的元素,再针对数据进行填充

到底哪种比较优呢?

测试验证

可能也有人大概想到较优方案,但是对于实事求是的我,还是要写些代码去测试验证

我的测试例子

效果截图:

效果截图

结果

方案二的思路明显要比方案一的优,而且查看原代码后发现,easyui自带的form load方案是以方案一为基准去处理的,再加上一些细节的处理,效率非常的慢.

改进

实际上我们还要处理radio/checkbox的情况,以及处理其他一些细节,故最后整理封装的代码如下

    !function($){
    $.fn.extend({
    /*
    把JSON数据填充进表单,兼容easyui渲染过的表单
    * 20140203 reconstructed by p2227
    * 参数:
    * relateTable:关系表,key-value对象,即JSON数据与表单有不对应时的另外对照表
    * data:要填充的JSON数据
    * callBack:填充完数据后的回调函数,一般说来填充完数据要进行表单验证
    *
    * 用法:
    * $('form').loadForm({data:{key,value}});
    * */
    loadForm:function(conf){
    conf = conf || {};
    conf.relateTable = conf.relateTable || {};
    var rt = conf.relateTable;
    var formObj = this;
    var jsonData = conf.data;
    var newData = {};
    function fill1EasyUI(dom,data1){ //填充值到一个easyUI表单对象上
    //目测针对combobox和datebox,其他表单对象 建议调用 easyUI本身的 form.load方法
    var eDom = $("[comboName='" + dom.name + "']",formObj); //找到easyUI起作用的dom元素(不带name)
    if(eDom.length<=0) return;
    var type = eDom[0].className.match(/(\w*?)-f/); //该dom的类上第一个带 "任意字母-f"的类
    if(type && type.length>0){
    type = type[1];
    if(/datebox/i.test(type)){
    data1 = flitDate(data1);
    }
    if (eDom[type]("options").multiple){
    eDom[type]("setValues", data1.replace(/\s*,\s*/g,",").split(","));
    } else {
    eDom[type]("setValue", data1);
    }
    }else{
    if(eDom.next("span.datebox").length>0){ //for IE7 IE6
    eDom.datebox("setValue", flitDate(data1));
    }
    }
    }
    /* 输入:2012-04-04 00:00:00,2012.2.2,2012/4/7
    * 输出:2012-04-04
    * */
    function flitDate(dStr){
    if(dStr){
    var dreg = /(\d{4})([-\/.])(\d{1,2})\2(\d{1,2})/;
    var sval = dStr.match(dreg)[0].replace(dreg,"$1-$3-$4");
    return sval;
    }else{
    return dStr;
    }
    }
    function fill1Simple(dom,data1){
    if(dom == undefined){ return;}
    if(dom.className.match(/combo-value/i)){
    fill1EasyUI(dom,data1); //按照easyUI的法则填充数据
    }else{
    var $dom = $(dom);
    if($dom.is("span.om-combo>input")){
    $dom.omCombo('value',data1)
    }else{
    dom.value = data1; //普通的html元素赋值
    }
    }
    }
    //把网页上需要额外对照的数据也加到填充数据中
    $.each(rt,function(key,value){
    if(jsonData[key]){
    jsonData[value.replace(/\\*/g,'')]=jsonData[key];
    }
    });
    /* 填充数据的主函数
    *
    * 是用表单为主循环还是数据为主循环快???要做测试。
    * 测试结果:以表单为主循环,必需将EasyUI和一般表单项分开处理
    *
    * 必须要把radio,checkbox放在同一起处理,因为你也不清楚对照表里面的项目是text还是radio
    * */
    var nameflag="";//name标记 如果找到有name相同的 data,那就设置标记,以便循环只运行一次
    $("input[name],textArea[name],select[name]",formObj).each(function(){
    //在实际项目中,有这样的需要:JSON数据key总是大写,也要填充到页面;按表单中属性为fillBack的去填充,故在此进行扩充
    var filldata1 = jsonData[this.name] || jsonData[this.name.toUpperCase()] || jsonData[this.getAttribute("fillBack")];
    if(jsonData[this.name] === 0 || jsonData[this.name.toUpperCase()] === 0 || jsonData[this.getAttribute("fillBack")] === 0){
    filldata1 = 0;
    }
    if(filldata1 === undefined || filldata1 === "" || filldata1 === null|| filldata1 === "null"){
    return;
    }else{
    if(/radio/i.test(this.getAttribute("type"))){
    if(this.name==nameflag){ return; }
    nameflag = this.name;
    $("input[name='"+ nameflag +"'][value=" + $.trim(filldata1) + "]").prop("checked",true);
    }else if(/checkbox/i.test(this.getAttribute("type"))){
    if(this.name==nameflag){ return; }
    nameflag = this.name;
    $("input[name='"+ nameflag +"']").prop("checked",false)//首先要清空原有数据
    $.each(filldata1.split(','),function(k,v){
    $("input[name='"+ nameflag +"'][value='" + $.trim(v) + "']").prop("checked",true);
    })
    }else{
    this.value = "";//首先要清空原有数据
    fill1Simple(this,filldata1);
    }
    }
    });
    if(typeof conf.callBack == "function"){
    conf.callBack(jsonData);
    }
    }
    });
    }(jQuery);