• UniEAP V4 WorkShop用户手册




    版权声明
    《UniEAP V4 WorkShop用户手册》的版权归东软集团(大连)有限公司所有。未经东软集团(大连)有限公司的书面准许,不得将本手册的任何部分以任何形式、采用任何手段(电子的或机械的,包括照相复制或录制)、或为任何目的,进行复制或扩散。
    Copyright© 1997-2011 东软集团(大连)有限公司。版权所有,翻制必究。
    ®是东软软件股份有限公司的注册。

    更改履历
    版本号 更改时间 更改的图表和章节号 状态 更改简要描述 更改申请编号 更改人 批准人
    1.0 2011-07-08 所有 N 于洋
    2.0 2013-01-31 部分 M 颜仲南
    3.0 2013-07-19 部分 M 张冬威



    注:状态可以为N-新建、A-增加、M-更改、D-删除
    目录
    前言 10
    本手册面向的受众 10
    手册的结构 10
    阅读建议 10
    手册约定 11
    第1章 UniEAP V4 简介 11
    1.1 UniEAP V4 简介 11
    1.2 UniEAP V4 的开发模式 12
    1.3 UniEAP V4 WorkShop的定位 12
    第2章 安装与配置 14
    2.1 安装UniEAP V4 Workshop 14
    2.1.1 UniEAP V4 WorkShop运行环境 14
    2.1.2 JDK 以及环境变量配置 14
    2.1.3 Eclipse启动参数的配置 17
    2.1.4 安装WorkShop Eclipse插件 18
    2.1.5 常用第三方插件推荐 19
    2.1.6 插件安装失败的处理方法 20
    2.2 配置UniEAP V4 WorkShop 20
    2.2.1 切换到UniEAP透视图 20
    2.2.2 设置源码默认包路径前缀 22
    2.2.3 设置Web浏览器 23
    2.2.4 校验设置 25
    第3章 快速入门 27
    3.1 开发样例功能描述 27
    3.2 安装及准备工作 29
    3.2.1 准备数据库脚本 29
    3.2.2 导入V4工程 29
    3.2.3 配置数据库连接 35
    3.3 样例开发 36
    3.3.1 建立软件组件(SC)和开发组件(DC) 36
    3.3.2 建立模型 40
    3.3.3 页面开发过程 45
    3.4 部署TOMCAT服务器 75
    第4章 Workshop工具简介 80
    4.1 工具栏 80
    4.2 UniEAP 资源管理器 81
    4.3 Problems视图 82
    4.4 错误日志视图 83
    4.5 特性视图 84
    4.6 控制台视图 84
    4.7 Servers视图 85
    4.8 数据集视图 86
    4.9 工具插件自动升级 86
    第5章 组件化开发使用指南 90
    5.1 UniEAP工程结构简介 90
    5.1.1 UniEAP V4 工程结构一览 90
    5.1.2 UniEAP工程 91
    5.1.3 软件组件 92
    5.1.4 开发组件 93
    5.1.5 Patch工程 95
    5.2 使用UniEAP 工程 97
    5.2.1 新建UniEAP工程 97
    5.2.2 导入UniEAP工程 100
    5.2.3 新建还是导入? 104
    5.3 使用软件组件(SC) 105
    5.3.1 新建软件组件 105
    5.3.2 设置组件描述信息 106
    5.3.3 设置包含的开发组件 108
    5.4 使用开发组件(DC) 112
    5.4.1 新建开发组件 112
    5.4.2 设置组件依赖 114
    5.4.3 设置公共访问包(PP) 117
    5.4.4 设置组件描述信息 120
    5.5 设置组件发布 122
    5.5.1 UniEAP V4组件发布机制 122
    5.5.2 设置组件发布 128
    5.6 设置组件发布Filter顺序 130
    5.7 组件调试设置源 130
    5.8 UniEAP工程部署 135
    5.8.1 开发测试环境 135
    5.8.2 系统上线环境 141
    5.8.3 UniEAP V4兼容应用服务器列表 146
    第6章 模型化开发使用指南 147
    6.1 使用模型开发 147
    6.1.1 Entity模型 147
    6.1.2 DTO模型 159
    6.1.3 DAO模型 172
    6.1.4 BO模型 182
    6.1.5 View模型 199
    6.1.6 View组件 243
    6.2 使用可视化UI设计器 249
    6.2.1 UIDesigner简介 249
    6.2.2 View如何运作? 249
    6.2.3 进行UI设计 252
    6.2.4 模式控件的使用 356
    6.2.5 设置入口信息 381
    6.2.6 设置过程调用 392
    6.2.7 使用脚本编辑器 416
    6.3 异常框架 460
    6.4 国际化 461
    6.4.1 概述 461
    6.4.2 模型文件国际化 462
    6.4.3 撤销模型文件国际化 472
    6.4.4 JS文件国际化 472
    6.4.5 代码表国际化(CodeList) 474
    第7章 组织机构安全使用指南 475
    7.1 组织机构 475
    7.1.1 基本概念 475
    7.1.2 当前登录用户 476
    7.1.3 扩展属性 476
    7.1.4 事件监听 479
    7.2 安全 479
    7.2.1 基本概念 479
    7.2.2 资源权限 481
    7.2.3 帐号锁定踢出 483
    7.2.4 验证码 484
    7.2.5 在线用户 485
    7.2.6 非正常登录请求 485
    7.2.7 Session过期 486
    7.2.8 菜单授权 486
    7.2.9 事件监听 486
    7.3 管理控制台 487
    7.3.1 初始授权 487
    7.3.2 组织单元维护 490
    7.3.3 职位管理 492
    7.3.4 组织单元类型 493
    7.3.5 用户维护 493
    7.3.6 管理角色 494
    7.3.7 业务角色 496
    7.3.8 组织角色授权 497
    7.3.9 页面授权 497

    前言
    本手册面向的受众
    本手册是面向使用UniEAP V4的开发人员专门编写的,对UniEAP V4 WorkShop的使用方法进行了详细的描述。
    阅读本手册的人员需要对如下知识有所了解:
    1 HTML、JavaScript和Ajax基本知识。
    2 UniEAP RIA开发。
    3 UniEAP V4的开发流程。
    4 Eclipse IDE的使用。
    手册的结构
    手册分主要内容包括五章:
    第一章 UniEAP WorkShop简介。本章对UniEAP V4,UniEAP WorkShop的概念,开发模式,定位等进行了简述,帮助您了解UniEAP V4 Workshop的背景知识。
    第二章 安装与配置。本章节描述了正是使用UniEAP V4 WorkShop前,需要进行的安装和必要基本配置的操作和设置方法。
    第三章 快速入门。一个简单的样例,为您展示使用UniEAP V4开发的全过程。
    第四章 WorkShop使用指南。按功能点介绍WorkShop每一个功能的详细使用方法。
    第五章 组织机构和安全。介绍UniEAP V4工程自带的组织机构和安全组件的功能和管理控制台的使用方法。
    阅读建议
    如果您手中没有一个可以正常运行的UniEAP V4 WorkShop,请先阅读第二章,进行安装配置。
    如果您没有使用过UniEAP V4进行过开发,建议您学习第三章快速入门来感受UniEAP V4的开发过程。
    如果您是一个UniEAP V4的开发人员,对WorkShop的功能使用有问题时,可以查阅第四章获得帮助。
    如果您想了解UniEAP V4的组织机构和安全组件的功能以及管理控制台的基本使用方法,请查阅第五章。
    本手册中会出现一些UniEAP V4或和V4相关的概念,如果您不清楚它的含义,请查询附录。
    手册约定
    阅读本手册时,您可能会看到如下标记,其含义如下:
    【提示】:表示某些信息,读者可以参考。
    【技巧】:表示读者可以参考其中介绍的技巧,提高效率。
    【注意】:提醒读者关注某些事项,这些事项对您后续操作造成影响。
    【警告】:请读者千万注意某些事项,否则可能会造成严重错误。
    第1章 UniEAP V4 简介
    1.1 UniEAP V4 简介
    随着业务复杂性的不断提升,软件规模变得更加复杂。在技术层面上,如何降低软件实现的复杂性并可适应业务的快速变化,也衍生出相应的解决方案,典型的如组件化封装和面向服务的功能提供方式,可以显著的促使生产效率的提升;从降低开发成本角度考虑,特别是对于在相关领域积累多年的企业来说,通过基于可复用资产开发,也是一个务实和不可或缺的手段。
    同时,随着当前业界对于SOA、云计算的技术的研究和成功应用,很多企业也逐步认识到了把企业现有的资源作为服务对外提供的重要性和必要性,而体现企业核心智慧的可复用资产作为服务进行提供,对于企业价值的进一步提升尤其具备重要意义。
    从东软内部各个行业事业部来看,它们其中一些行业事业部有着多年的领域经验,也积累一定规模的业务资产,但是在面对一个新的软件系统开发时,并不能够在已有的业务资产中有效的识别和利用可复用的业务资产,因而制约了其快速构件新系统的能力;还有一些行业事业部它们缺乏领域经验是新兴的行业事业部,此类行业线由于还没有在行业经验上积累大量资产,期望通过很强的快速开发能力,迅速把业务需求转变成功能实现,并期望这些功能实现在未来能够作为可复用资产在新的项目中加以重复使用。
    我们期望有一套新的开发方法和开发平台能够提高软件开发的资产复用的能力和快速开发的能力。
    UniEAP V4正是这样一款集合了新的开发方法的业务基础开发平台。软件产品线的开发方法指导软件开发者采用资产复用而非重复开发的方式来进行软件生产的方法。业务基础软件平台是指以业务导向和驱动的、可快速构建应用软件的软件平台。
    UniEAP V4是面向软件产品线的业务基础平台,其核心技术定位是组件化,即基于组件复用和装配的方式来快速构建企业应用。
    1.2 UniEAP V4 的开发模式
    UniEAP V4采用面向软件产品线的开发思想,将开发过程分为核心资产积累(领域工程)与应用开发(应用工程)两个阶段。核心资产积累阶段,通过对所面向领域的业务、已有项目经验,已积累软件资产的不断抽象,总结其差异,形成一套稳定的核心资产以及详细的项目差异点描述(可变点);应用开发阶段,根据核心资产与实际需求的差异,配置可变点的值,实现应用快速组装。软件产品线的开发模式,可以有力推动“解决方案产品化”,持续提升生产率,降低开发成本。
    目前UniEAP V4的开发模式已经在公司部分事业部有过成功应用,如社保,公卫,劳动力,国土,电信,移动等。这些事业部使用UniEAP V4开发其业务基础平台,积累核心资产,在实际项目中,利用装配的方式快速组装出产品。
    1.3 UniEAP V4 WorkShop的定位
    UniEAP V4 WorkShop是UniEAP V4进行模型化开发的核心工具,对于UniEAP V4的各类模型,WorkShop均提供了良好的编辑工具,对于View模型,WorkShop还提供了图形化、高效的编辑工具UIDesigner。此外,WorkShop实现了Web应用的组件化,并提供了一定的管理功能;WorkShop对UniEAP V4的业务模板,功能模板,控件模板提供了全面的支持,各类模板均可方便地生成模型代码;对于产品可变点,Workshop提供了特征树设置工具和基于特征的装配工具,实现了可变点的管理与灵活配置。

    第2章 安装与配置
    本章介绍UniEAP V4 WorkShop安装与配置的方法,如果您手中还没有一个可用的UniEAP V4 WorkShop环境,请仔细按照本章内容操作。
    2.1 安装UniEAP V4 Workshop
    2.1.1 UniEAP V4 WorkShop运行环境
    UniEAP V4 WorkShop的推荐运行环境如下:
    运行环境项目 推荐值
    计算机 CPU:英特尔酷睿2 E4500或以上
    内存:2GB或以上
    硬盘:40G或以上
    操作系统 Windows XP、Windows 7
    Eclipse版本 3.5.2GA
    硬盘空间 40G以上
    2.1.2 JDK 以及环境变量配置
    UniEAP V4 WorkShop推荐使用的JDK版本为1.5。安装JDK后,需要设置环境变量,大致分为以下三个步骤:
    1. 设置JAVA_HOME。具体操作为:右键“我的电脑”> “属性”> “高级”> “环境变量”,在“系统变量”点击 <新建> 按钮,弹出编辑对话框,新增变量名为JAVA_HOME,变量值为JDK的安装路径,点击 <确定> 按钮完成。如下图所示:

    图 1 配置JAVA_HOME
    2. 设置PATH。具体操作为:右键“我的电脑”> “属性”> “高级”> “环境变量”,在“系统变量”点击 <新建> 按钮,弹出编辑对话框,新增变量名为PATH,变量值为JDK的bin路径,点击 <确定> 按钮完成。为了方便,可以直接输入%JAVA_HOME%in,后面用“;”隔开。如下图所示:

    图 2 配置PATH
    3. 设置CLASSPATH。具体操作为:右键“我的电脑”> “属性”> “高级”> “环境变量”,在“系统变量”点击 <新建> 按钮,弹出编辑对话框,新增变量名为CLASSPATH,变量值为JDK的lib路径和tools.jar文件路径,点击 <确定> 按钮完成。为了方便,可以直接输入%JAVA_HOME%lib;%JAVA_HOME%lib ools.jar,后面用“;”隔开。如下图所示:

    图 3 配置CLASSPATH
    【注意】配置环境变量时最好不要带中文。
    2.1.3 Eclipse启动参数的配置
    Eclipse的启动参数是在eclipse.ini文件中进行配置的,主要包括以下三方面:
    1. 虚拟机堆栈参数设置
    参数中-vmargs的意思是设置Java虚拟机的启动参数。
    -Xms80m -Xmx512m,是设置JVM中的堆内存分配,JVM初始分配的内存由-Xms指定,JVM最大分配的内存由-Xmx指定。
    -XX:PermSize=256m -XX:MaxPermSize=512m,是设置JVM中的非堆内存分配,-XX:PermSize设置非堆内存初始值,-XX:MaxPermSize设置最大非堆内存的大小。
    这些配置可能在有些机器上导致eclipse无法启动。出现这种情况的原因是-Xmx的值和-XX:MaxPermSize的总和超过了JVM可用内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。可以根据机器具体的情况,将-Xmx和-XX:MaxPermSize的配置调低。
    2. 用户信息设置
    若想全英文显示Workshop,需在eclipse.ini文件中添加:
    -Duser.language=en
    若想设置默认的用户信息,需在eclipse.ini文件中添加:
    -Duser.name=用户名
    3. 字符集参数设置
    若想设置Java文件的字符集为中文字符,需在eclipse.ini文件中添加:
    -Dfile.encoding=UTF-8
    2.1.4 安装WorkShop Eclipse插件
    启动Workshop后,打开“帮助”菜单,选择“关于UniEAP Workshop”菜单项,如下图所示。

    图 4 关于UniEAP Workshop
    点击 <安装细节> 按钮,会弹出“UniEAP Workshop安装细节”对话框,切换到“插件”页,如下图所示。注意观察红色区域,可以看到安装了哪些Workshop Eclipse插件。这些插件缺一不可,因而要仔细排查。

    图 5 插件列表
    2.1.5 常用第三方插件推荐
    插件名称 简介
    JSEclipse 小巧,免费,功能强大的javascript编辑器。
    Oracle Enterprise Pack for Eclipse(OEPE) Oracle提供的企业编程插件,提供了Weblogic调试功能。
    Propedit 编写国际化properties文件的Eclipse插件。
    Veloeclipse 在Eclipse下编辑Velocity模板的插件,支持语法着色,代码向导等功能。
    Hibernate Tools Hibernate官方插件,其包含的Hibernate Console可以直接执行HQL语句,查看运行结果,极大提高HQL编写效率。
    Subclipse 使用SVN进行代码控制环境下,建议使用的客户端插件。
    2.1.6 插件安装失败的处理方法
    如果发现workshop插件没有正常加载,请先确认本机jdk的版本是否低于插件的编译级别,如果不是这个问题,请尝试以下处理方法:
    1. 启动eclipse时加上 -clean参数
    2. 将eclispe安装目录下configuration目录下的config.ini里加入如下语句即可让eclipse强制搜索插件:osgi.checkConfiguration=true
    3. 删除eclipse安装目录下的configuration目录下的org.eclipse.update目录
    4. 如果以上3种方法均不起作用,则打开eclispe安装目录下configuration目录下的org.eclipse.equinox.simpleconfigurator目录下的bundles.info文件,在里面手动加入插件的信息。
    2.2 配置UniEAP V4 WorkShop
    2.2.1 切换到UniEAP透视图
    启动Workshop后,默认会打开UniEAP透视图,如下图所示。

    图 6 UniEAP透视图
    当打开的透视图非UniEAP透视图时,打开“窗口”菜单,选择“打开透视图”菜单项,点击“其他”会弹出“打开透视图”对话框,选择UniEAP(缺省值)则会切换到UniEAP透视图,如下图所示。

    图 7 打开透视图
    2.2.2 设置源码默认包路径前缀
    为了方便用户使用,我们提供一个统一的入口,来设置源码默认包路径前缀。当用户创建一个BO模型,DAO模型,DTO模型或者View模型时,创建的模型源码文件的包名将由以下部分组成:源码默认包路径前缀+该模型所在SC名称+该模型所在DC名称。

    图 8 默认包路径前缀

    2.2.3 设置Web浏览器
    eclipse内置浏览器在某些情况下会导致jvm异常关闭。所以请用户在使用v4之前务必将eclipse的默认浏览器设置成外部浏览器,操作如下:选择“窗口”>“首选项”,在首选项对话框中选择“常规”>“web 浏览器”,选择“使用外部web浏览器”,点击完成。如下图所示:

    图 9 设置WEB浏览器

    如果选择的是IE,可能在每次预览时,IE会自动弹出如下讨厌的提示:

    图 10 用IE浏览器预览时的提示
    这时选择IE的“工具”>“Internet选项”,选择“高级”tab页,在“安全”下找到“允许活动内容在我的计算机上的文件中运行*”,勾选上点击应用(如下图所示),重启IE,以后就不会再弹出提示了。

    图 11 IE浏览器设置
    2.2.4 校验设置
    如果是新建的工作空间,会看到欢迎界面,关闭掉。找到菜单栏中的“窗口”>“首选项” 在弹出的首选项对话框左侧的列表里选择“Validation”,将“Suspend all validators”勾选上,点击应用按钮。完成后的效果如下图所示:

    图 12 校验设置
    接下来还需要去掉jsp的片段校验,在首选项对话框中选择“Web”>“JSP Files”>“Validation”,将“Validate JSP fragments”勾选去掉,点击应用按钮。完成后的效果如下图所示:

    图 13 JSP校验设置
    第3章 快速入门
    3.1 开发样例功能描述
    本章主要介绍用户在使用UniEAP V4时,如何在Workshop中创建一个新的工程,并开发一些基本的功能。如下图所示。上边为查询条件。下方为查询结果显示。
    图14 开发功能显示界面
    当输入查询条件后点击<查询>按钮。来显示查询的数据。
    点击<修改>按钮,弹出对话框,对话框里显示用户信息。可对其信息进行修改等操作。弹出对话框如下图所示。

    图15 弹出对话框视图
    修改对应信息后点击<保存>按钮。来保存修改后的信息。点击< 重置>按钮来返回原来信息。
    3.2 安装及准备工作
    3.2.1 准备数据库脚本
    将我们提供的oracle数据库脚本导入oracle数据库中。其中包括了UniEAP V4启动所需的所有支撑数据库表。
    3.2.2 导入V4工程
    首先,打开Workshop,建立一个新的Workspace,进入如下界面:


    图16 Workshop主界面
    然后,点击Workshop工具栏上的“项目(P)”选项,在弹出的菜单上取消“自动构建(M)”的勾选,如下图所示:

    图17 取消自动构建
    之后,在“UniEAP资源管理器”透视图内点击鼠标右键,在弹出菜单中点击“导入”选项,如下图所示:

    图18 打开导入工程菜单
    其后,在弹出的“导入”对话框中,点击“现有项目到工作空间中”选项,如下图所示:

    图19 选择导入的方式
    随后,点击“下一步(N)>”按钮,进入“导入”的复选菜单中。点击“浏览(R)…”按钮,选择我们提供的V4工程,如下图所示:

    图20 选择要导入的工程
    最后,点击“完成(F)”按钮,并等待代码生成完毕。此时点击Workshop上的“项目(P)”选项,在弹出的菜单中勾选“自动构建(M)”选项,等待工程构建及发布完成。
    工程发布完成后,再次点击Workshop上的“项目(P)”选项,在弹出的菜单中点击“清理(N)…”选项,如下图所示:

    图21 打开清理项目菜单
    在弹出的“清理”对话框中点击“清理所有项目”选项,如下图所示:

    图22 选择需要清理的项目
    点击“确定”按钮,等待所有项目清理完成后即可。
    3.2.3 配置数据库连接
    首先,打开“打开资源”对话框(快捷键为:Ctrl+Shift+R),在对话框中输入“EAPConfig”,在“匹配项(M)”列表中双击文件名为“EAPConfig”,后方的实际路径为“patch/webroot/WEB-INF/conf/platform/core”的文件,如下图所示:

    图23 选择patch工程中的EAPConfig文件
    然后,在打开的EAPConfig文件中,配置要连接数。如下图所示。

    图24 修改EAPConfig中的数据库链接信息
    最后,保存该文件即可。
    3.3 样例开发
    本节介绍如何使用UniEAP V4快速开发一个样例,该样例包括对数据库单表的查询和修改功能;其中查询功能支持翻页,修改功能涉及到两个页面之间的数据传递。
    3.3.1 建立软件组件(SC)和开发组件(DC)
    首先,在“UniEAP资源管理器”透视图内的根目录上点击右键,在弹出的菜单中点击“新”选项,再在弹出的二级菜单中点击“UniEAP 软件组件”选项,如下图所示:

    图25 打开建立软件组件菜单
    然后,在“新建软件组件”对话框中输入新软件组件的ID和名称,其中ID是必填项;名称一般为中文标识,是在UniEAP 资源管理器上的显示名称,我们这里将软件组件的ID和名称都填写为“demo”,如下图所示:

    图26 输入新软件组件的ID和名称
    之后,点击“完成(F)”按钮以实现软件组件的建立。
    其后,在刚刚新建的软件组件上点击右键,在弹出的菜单中点击“新”选项,再在弹出的二级菜单中点击“UniEAP 开发组件”选项,如下图所示:

    图27 打开建立开发组件菜单
    随后,在“新建开发组件”对话框中,输入新开发组件的ID和名称,其中ID是必填项;名称一般为中文标识,是在UniEAP 资源管理器上的显示名称,我们这里将软件组件的ID和名称都填写为“test”,如下图所示:

    图28输入新开发组件的ID和名称
    最后,点击“完成(F)”按钮以实现开发组件的建立。
    3.3.2 建立模型
    模型是UniEAP V4的一大特点,下面的内容将简要介绍一下entity和view模型的开发过程。
    3.3.2.1 Entity模型
    首先,打开刚刚建立的开发组件,展开“metamodel”文件夹,在其中的“entity”文件夹上点击右键,在弹出的菜单中点击“新”选项,再在弹出的二级菜单中点击“Entity 模型”选项,如下图所示:

    图29 打开建立entity模型菜单
    然后,在弹出的“新建Entity模型”对话框中输入和EAPConfig中相同的数据库链接信息;点击“测试连接”按钮,如果提示“测试连接成功”则点击“下一步(N)”按钮,如下图所示。



    图30 测试数据库链接
    之后,在下一个对话框中,先点击“刷新”按钮,待“表或视图”列表中出现数据库的内容后,勾选需要的表或视图(在此我们以UP_ORG_USER表为例),如下图所示:

    图31 建立entity模型和数据库表的关联关系
    最后,点击“完成(F)”按钮即可完成entity模型的创建。
    3.3.2.2 View模型
    首先,打开刚刚建立的开发组件,展开“metamodel”文件夹,在其中的“view”文件夹上点击右键,在弹出的菜单中点击“新”选项,再在弹出的二级菜单中点击“View 模型”选项,如下图所示:

    图32 打开建立view模型菜单
    然后,在弹出的 “新建页面模型”对话框中输入该view模型的名称,在此我们将其命名为“test”,如下图所示:
    图33 输入view模型的信息
    最后,点击“完成(F)”按钮即可。
    3.3.3 页面开发过程
    这里主要介绍页面开发的简要流程和基本的页面布局及简单的前台JS代码。
    3.3.3.1 建立数据集
    首先,打开“数据集”透视图,点击右上角的“ ”图标,如下图所示:

    图34 打开数据集透视图
    然后,在弹出的“新建DataStore”对话框中双击左侧的entity模型,这时可以在左上方的“名称”输入框中修改该数据集的名称,例如我们建立了一个名为“upOrgUser1”的数据集,如下图所示:

    图35 建立数据集和entity的关联关系
    最后,点击“完成(F)”按钮,再保存view模型即可完成数据集的建立。
    按照上述方法再建立一个不同名但同entity的数据集,例如我们又建立了一个名为“upOrgUser2”的数据集,后面将作为查询条件的数据集为Form模式控件所绑定,如下图所示:

    图36 建立第二个数据集
    3.3.3.2 过程调用
    首先,双击“UniEAP资源管理器”透视图内的view模型,进入“过程调用”tab页。
    然后,点击左上角的“增加”按钮,下方的“基本信息”列表中会出现一个新的方法,这时修改“方法名”中的内容可以为这个过程调用重命名;现在我们以实现分页查询功能为例,建立一个名为“queryProcesser”的方法,如下图所示:

    图37 建立过程调用
    之后,为过程调用选择它要依赖的BO。点击右上角的“增加”按钮,如下图所示:

    图38 过程调用选择依赖BO
    其后,在弹出的“增加依赖BO”对话框中,先将“过滤规则”下拉框的内容选为“当前DC可见的BO”,再双击上方的“commonBO.bo”选项,如下图所示:

    图39 选择依赖BO菜单
    随后,为过程调用选择它要自动调用的bo方法。点击右下角的“选择…”按钮,如下图所示:

    图40 过程调用选择自动调用bo方法
    然后,在弹出的“选择BO方法”对话框中,将“选择依赖的BO”下拉框的内容选为“commonBO – core”,再双击下方列表中的“findByExample(Object,int,int)”方法,如下图所示:

    图41选择BO方法菜单
    接着,为过程调用刚刚选择的bo方法设置参数,点击左下角的“增加”按钮,如下图所示:

    图42 过程调用设置BO方法的参数
    最后,在弹出的“增加参数”对话框中输入一个参数,然后点击“确定”按钮,如此重复三次;每次的输入内容分别如下图所示:

    图43 设置过程调用的参数

    3.3.3.3 模式控件
    首先,双击view模型,进入“设计”tab页,打开左侧的“模式控件”菜单,点击“QueryGrid”选项,如下图所示:

    图44 选择模式控件
    然后,将鼠标移动到右侧的空白区域,这时会发现鼠标的图标有所改变(右下方出现一个虚线的矩形和一个中心带十字花的实线矩形),点击鼠标左键以进入“新建模式控件”对话框;将“Grid数据集”下拉框的内容选为刚刚建立的第一个数据集(UpOrgUser1),将“Grid控件类型”下拉框的内容选为“XGrid”,”Grid选择类型”下拉框的内容选为“single”,“选择过程调用”下拉框的内容选为刚刚建立的过程调用(queryProcesser),如下图所示:

    图45 建立Grid模式控件
    之后,点击“下一步(N)”按钮,进入“新建模式控件”对话框,将“数据查询条件”下拉框的内容选为另一个数据集(UpOrgUser2),在“控件信息列表”中取消不必要的勾选,如下图所示:

    图46 建立Form模式控件
    点击“完成”后,保存view模型即可。
    经过上述的步骤,查询的样例开发基本完成;但还缺少对数据的修改功能及多页面交互的过程,因此下一小节主要介绍通过对话框实现多页面之间的交互过程。
    3.3.3.4 多页面交互
    首先,按照上述过程再开发一个页面,将其命名为“test2”,同样要先建立一个数据集,如下图所示:

    图47 建立数据集
    然后,进入这个view模型的“过程调用”tab页,增加一个新的过程调用,在此我们将其命名为“updateProcesser”,其依赖BO的选择过程和上述相同,“自动调用BO方法”中的选择如下图所示:

    图48 选择BO方法
    “参数列表”的内容如下图所示:

    图49 编辑参数
    之后,进入view模型的“设计”tab页,这次选择一个Form的模式控件,如下图所示:

    图50 选择form模式控件
    其后,进入“新建模式控件”对话框,在这个对话框内可以对form的布局进行修改,例如我们把“Form总列数”修改为4,并且可以勾选“自定义列宽”选项来对form中每一列的大小进行设置,如下图所示:

    图51 Form模式控件修改样式
    随后,点击“下一步(N)>”按钮,在这个对话框中将“选择数据集”下拉框的内容选为刚刚建立的数据集(upOrgUser1),在“控件信息列表”中取消不必要的勾选(例如数据库表的主键字段等),同时将“选择过程调用”下拉框的内容选为刚刚建立的过程调用(updateProcesser),如下图所示:

    图52 Form模式控件选择数据集
    最后,点击“完成(F)”按钮结束form模式控件的建立。
    下面介绍一些页面布局的技巧:
    首先,返回第一个view模型,进入“设计”tab页,选择左侧的“基本控件”菜单,先点击“Button”选项,再点击右侧“查询”按钮前的空白处,如下图所示
    图53 添加button
    然后,点击新增button图标右上角的小三角,如图 ,在弹出的“button快速设置”对话框中可以修改button的ID、显示名称和宽度,在这里我们修改了button的控件名称和控件宽度,如下图所示:

    图54 修改button属性
    这时会发现button的布局并不理想,如下图所示:

    图55 页面button的布局(修改前)
    我们需要修改button所在的toolbar控件来实现布局的合理化。
    首先,在右侧的“大纲”透视图中点击“grid1_ToolBarInfo”控件(同时要保持view模型处于“设计”tab页状态),如下图所示:

    图56 找到toolbar
    然后, view模型的“设计”tab页中会有一个控件被框选中,并且在框选的右上角出现一个 ,点击这个 进入“TableLayout快速设置”对话框,现在我们将“第5列宽度”改为“145px”,如下图所示:

    图57 修改toolbar布局
    最后,保存view模型,这样button的布局就设置完成了,如下图所示:

    图58 页面button的布局(修改后)
    下面介绍如何设置对话框。
    首先,进入view模型的“设计”tab页,打开左侧的“容器”菜单,点击“XDialog”控件,如下图所示:

    图59 选择XDialog控件
    然后,点击右侧的空白区域,将XDialog控件添加进页面,如下图所示:
    图60 添加XDialog控件
    之后,点击XDialog上的 ,打开“XDialog快速设置”对话框,点击 选项,如下图所示:

    其后,在弹出的“增加当前view依赖的view”对话框中选择我们后开发的view模型(test2页面),如下图所示:

    图61 选择XDialog的引用页
    最后,点击“确定”按钮,再保存view模型即可。
    现在,我们需要编写一些JS代码完成两个页面之间的交互过程,共有如下4个步骤:
    打开第一个页面的view模型(test页面),进入“设计”tab页,展开“修改”button的“Button快速设置”对话框,点击“事件”下的“编辑onClick事件”超链接,如下图所示:

    图62 编辑button的onClick事件
    在其中添加如下的JS代码:
    var gridId = view.grid.getPropertyValue("grid1", "id");
    if (gridId != null) {
    var dialog = unieap.byId("xdialog1");
    var gridDS = view.grid.getRow("grid1");
    dialog.dialogData = gridDS;
    dialog.show();
    } else {
    MessageBox.alert( {
    title : '确认框',
    message : '请选择一条记录!'
    });
    }
    1) 打开第二个view模型(test2页面),进入“脚本”tab页,将上方的两个下拉框的内容分别选为“page”和“load()”,如下图所示:

    图63 编辑page的load事件
    var gridDS = unieap.getXDialog().getObject();
    view.form.setDataStore("form1", gridDS);
    在其中添加如下的JS代码:
    这样就实现了将test页面的数据通过对话框传递到test2页面中。
    下面介绍test2页面通过对话框回传数据到test页面:
    2) 打开第二个view模型(test2页面),进入“脚本”tab页,将上方的两个下拉框的内容分别选为“公共方法”和“updateProcesserSuccess(dc)”,如下图所示:

    图64 编辑公共方法的updateProcesserSuccess事件
    在其中添加如下的JS代码:
    var formDS = dc.getDataStore("result");
    unieap.getXDialog().setReturn(unieap.toJson(formDS));
    unieap.getXDialog().close();
    3) 打开第一个view模型(test页面)的“设计”tab页,展开 XDialog的“XDialog快速设置”菜单,点击“事件”下的“编辑onComplete事件”超链接,如下图所示:

    图65 编辑XDialog的onComplete事件
    之后,在其中添加如下的JS代码:
    var gridDS = unieap.fromJson(returnObj);
    view.grid.updateRow("grid1", gridDS);
    如此便完成了整个修改功能。
    3.4 部署TOMCAT服务器
    如果想要访问刚刚开发完成的页面,首先,打开“Servers”透视图,在弹出的菜单中点击“New”选项,再在弹出的二级菜单中点击“Server”选项,如下图所示:

    图66 建立Server
    然后,在弹出的“New Server”对话框中展开“Apache”根目录,选择相应的Tomcat类型,这里以Tomcat6.0版本为例,如下图所示:

    图67 选择Tomcat作为服务器
    之后,点击“下一步(N)”按钮,再下一个对话框中先点击“Browse…”按钮,选择一个本地的Tomcat程序,如下图所示:

    图68 选择一个本地的Tomcat
    其后,先点击“下一步(N)”按钮,再点击“Add All”按钮,如下图所示:

    图69 选择web服务的内容
    最后,点击“完成(F)”按钮即可。
    下面介绍下如何启动Tomcat及访问页面:
    首先,点击“Servers”透视图内的“Tomcat v6.0 Server at localhost [stopped]”选项,再点击右上角的 ,如下图所示:

    图70 启动Tomcat服务
    然后,打开web浏览器,这里以IE 8.0为例进行介绍,在地址栏中输入如下的内容:“http://localhost:8080/framework/demo/test/test-view.jsp”,就可以访问页面并体验查询和修改的功能了。
    第4章 Workshop工具简介
    4.1 工具栏
    UniEAP透视图的工具栏包含 和 两组。前者是与可视化UI设计器紧密相关的,它们依次为“Undo”、“Redo”、“Delete”、“在上方插入行”、“在下方插入行”、“在左侧插入列”、“在右侧插入列”、“删除行”、“删除列”、“合并单元格”、“取消单元格合并”、“预览”和“资源引用”按钮。这13个按钮与可视化UI设计器具有相同的生命周期,随着设计器的打开而出现,关闭而消失。后者依次为“打开及上传模板”、“发布启禁”及“模型升级工具”按钮。具体功能将在以后章节中详细介绍。
    4.2 UniEAP 资源管理器
    UniEAP资源管理器视图位于Workshop的左侧区域,是开发使用UniEAP工程的核心操作区域。这里可以看到层次分明的UniEAP工程目录,如下图所示。

    图 71 UniEAP资源管理器视图
    【提示】:当UniEAP资源管理器消失时,首先确认,当前透视图是否为“UniEAP透视图”。如果不是,请切换至“UniEAP透视图”;如已经为“UniEAP透视图”,则选择 “窗口”>“显示视图”>“其他”菜单项,弹出如下对话框:

    图 72 打开UniEAP资源管理器视图
    选择“UniEAP资源管理器”,点击<确定>按钮,完成视图的打开设置。
    4.3 Problems视图
    Problems(问题)视图是主要用于显示Java代码编译、各类文件校验产生的错误或警告信息。如下图所示。

    图 73 Problems视图
    4.4 错误日志视图
    错误日志(ErrorLog)视图是用来记录Workshop启动、运行和关闭时出现的异常等错误信息,在使用WorkShop时出现问题时,这些信息对排查问题原因帮助很大。如下图所示。

    图 74 Problems视图
    4.5 特性视图
    特性(Properties)视图是用于打开可视化UI设计器时设置控件的属性或事件信息。如下图所示。(UI设计器关闭时,视图无效)

    图 75 特性视图
    4.6 控制台视图
    控制台(Console)视图主要用来显示UniEAP V4模型生成代码和Build相关信息,Tomcat服务启动、运行和关闭信息,以及调试和运行过程中出现的异常堆栈信息。如下图所示。

    图 76 控制台视图
    4.7 Servers视图
    Servers视图用于管理本地用于测试的应用服务器。可以执行新建、调试、启动、清理和删除应用服务器的操作。如下图所示。

    图 77 Servers视图
    4.8 数据集视图
    数据集(DataSet)视图是用来执行新建、删除view模型所使用的Datastore。详细使用方法见“使用可视化UI设计器”章节。(UI设计器关闭时,视图无效)

    图 78 数据集视图
    4.9 工具插件自动升级
    首先用户需要取得UniEAP最新工程,覆盖服务器上原有工程并发布,工程结构如下图所示:

    图 79 工程目录
    此时即可通过配置升级URL来进行插件更新,需要升级的用户需要在首选项——UniEAP——Update中配置更新站点的URL,该URL只需要修改一次,如更新地址不再变动则用户不需要再次进行修改。
    点击“help”菜单——选择“UniEAP 插件更新”,如图所示:

    图 80 插件升级菜单
    系统会自动从网上下载最新的插件feature,对比本地feature版本号,如果相同,则弹出对话框提示不需要升级,如下图所示:

    图 81 插件升级提示
    如网上的版本为较新版本,则弹出确认对话框,如下图所示:

    图 82 异构懒加载树
    【注意】release note暂以Tomcat的版本说明替代。
    点击<升级>按钮后,会自动下载最新版本插件并替换原有插件,同时更新本地feature版本。
    更新结束后会弹出对话框,需要用户确认是否重启workshop,如下图所示:

    图 83 确认视图
    【注意】由于使用eclipse自带的弹出对话框,同时测试版本使用的是英文环境,故该对话框语言为英文,中文环境即为中文对话框。
    第5章 组件化开发使用指南
    5.1 UniEAP工程结构简介
    5.1.1 UniEAP V4 工程结构一览
    典型的UniEAP工程结构如下图,其图标如下。简单介绍以下几个图标的含义:

    图 84 UniEAP工程结构
    1. :UniEAP工程。
    2. :软件组件(Software Component)。
    3. :开发组件(Development Component)。
    4. :补丁工程(Patch)。
    【提示】:上述四种不同的工程的详细内部结构,将在下面章节中详细介绍。
    5.1.2 UniEAP工程
    (原理简介,说明包含的重要文件夹,文件以及其意义)
    5.1.3 软件组件
    软件组件(SC)工程结构如下图所示:

    图 85 SC工程目录结构
    软件组件中通常不包含程序代码,仅包含配置文件和软件组件的描述文件(feature.xml)。
    content文件夹用于存放软件组件的配置文件和页面文件等资源。其中conf文件夹下是配置文件。applicationContext.xml和struts.xml分别为Spring和Struts的配置文件。generated文件夹下的配置文件是由系统自动生成的,请不要直接修改。
    【提示】如果需要在SC中添加自定义的Spring和Struts配置,修改SC下的content/conf/applicationContext.xml和content/conf/struts.xml即可。
    软件组件描述文件feature.xml记录该SC的描述信息,以及包含开发组件(DC)的信息。
    【警告】不要删除“/content/conf/”下的“applicationContext-import.xml”及“struts.xml”文件,会造成Unieap工程无法正常启动。
    5.1.4 开发组件
    开发组件(DC)工程结构如下图所示:

    图 86 DC工程目录结构
    src文件夹为开发组件的源码文件夹,保存开发组件的Java源码。
    content文件夹下存放开发组件的页面文件、资源文件和配置文件。
    其中:
     content/conf保存开发组件的配置文件,包含Spring,Struts和Hibernate的配置文件和缓存配置文件(ehcache.xml)、日志配置(log4j.xml)和Web应用描述文件(web.xml)。ehcache.xml ,log4j.xml ,web.xml 中存放该开发组件缓存,日志和Web应用的配置片段(这些配置文件中仅包含该开发组件的配置,并非整个工程的完整配置,这三个配置文件中的片段将自动合并到UniEAP工程中)。generated文件夹下的内容为系统自动生成,请不要自行修改。
    applicationContext.xml和struts.xml分别为Spring和Struts的配置文件。如果需要在DC中添加自定义的Spring和Struts配置,直接修改这两个文件即可。
     content/tld文件夹用于存放该开发组件包含的标签库定义文件。
     content/view文件夹下用于存放该开发组件View模型生成的页面文件,JS脚本文件。用户可以自行添加一些资源文件,如图片等。generated文件夹下的内容为系统自动生成,请不要直接编辑。

    lib文件夹用于存放该开发组件所包含的JAR包。用户可以自行添加。该文件夹中JAR包将被自动发布到UniEAP工程WebRoot/WEB-INF/lib下。

    META-INF文件夹中包含DC的配置信息,其中只有一个文件MENIFEST.MF。该配置文件记录了DC的基本信息(标识、版本、名称),依赖DC信息和公共部件(PublicPart)的定义。
    metamodel文件夹中包含本开发组件下的各类模型定义文件。按照模型类型放在不同子文件夹中。如下图所示:

    图 87 metamodel文件夹目录结构
    build.properties文件中包含本开发组件构建信息,通常不需要关心。
    features.xml为该开发组件的特征描述文件,用于描述开发组件包含的特征以及可变点。双击即可打开特征建模工具。
    5.1.5 Patch工程
    Patch工程结构如下图所示:

    图 88 Patch工程文件结构目录
    其中:
     src:该文件夹保存待更新的源码文件。
     META-INF:该文件下仅有一个MANIFEST.MF配置文件,记录该Patch工程信息及依赖关系等。
     webroot:一个标准web工程的WebRoot目录(结构与UniEAP工程的WebRoot完全相同)。
     build.properties:包含该Patch工程的构建信息,通常不需要关心。
    5.2 使用UniEAP 工程
    5.2.1 新建UniEAP工程
    在“UniEAP资源管理器”中空白处单击鼠标右键,在弹出菜单中点击“新建”->“UniEAP 工程”菜单项。

    图 89 新建UniEAP工程右键菜单
    新建UniEAP工程向导弹出,如下图:

    图 90 新建UniEAP工程向导
    在“基本信息”中输入“工程名称”和Web应用的“上下文根”。
    默认情况下“保存在默认工作空间中”是勾选的。在这种情况下,默认UniEAP工程的所有组件使用平面结构,保存在工作空间中。如下图所示:

    图 91 默认UniEAP工程存储结构
    这类平面工程存储结构不便于进行版本控制,因此,UniEAP提供了一个树状的工程结构。在新建UniEAP工程向导中取消勾选“保存在默认工作空间中”,指定一个默认工作空间以外的路径,即可使用这种树状工程结构。向导设置如下图:

    图 92 启动树状工程结构的设置
    树状工程结构如下图:

    图 93树状工程存储结构
    完成设置后,点击<完成>,UniEAP工程将被自动创建。
    5.2.2 导入UniEAP工程
    首先,在菜单栏中点击“项目”菜单项,将“自动构建”前面的勾去掉屏蔽该功能。如下图所示:

    图 94 关闭自动构建功能
    在“UniEAP资源管理器”中空白处单击鼠标右键,在弹出菜单中点击“导入”菜单项。如下图所示:

    图 95 “导入”菜单项
    之后导入向导弹出,选择“常规”->“现有项目到工作空间中”,之后点击<下一步>。如下图。

    图 96 选择“导入”类型
    在“选择根目录”处选择要导入UniEAP工程和工程的组件所在的根目录。之后在“项目”区域,勾选要导入的组件,最后点击<完成>。如下图所示:

    图 97 导入工程向导页
    【提示】通常不建议勾选“将项目复制到工作空间中”。
    点击<完成>按钮后,启用“自动构建”功能,执行全Build,如下图所示:

    图 98 自动构建向导页
    5.2.3 新建还是导入?
    在实际项目开发时,UniEAP不建议使用UniEAP WorkShop自带向导创建UniEAP工程,而是使用导入UniEAP工程的方式,主要有如下几个原因:
    1 UniEAP WorkShop自带的核心软件组件(platform和techcomp)的版本是固化在Workshop中的,在实际项目开发时,应该从UniEAP官方渠道获得最新版本的组件。
    2 实际项目开发时,通常是由项目管理员根据实际需要,选择UniEAP工程结构以及适当的软件组件和开发组件,上传至版本控制软件中。开发人员从版本控制软件中下载整个工程,之后使用导入的方式,进行本地开发。
    5.3 使用软件组件(SC)
    5.3.1 新建软件组件
    在“UniEAP资源管理器”视图的右键弹出菜单中点击“新建”>“UniEAP软件组件”菜单项。如下图所示:

    图 99 新建软件组件
    软件组件创建向导页面如下图所示:

    图 100 软件组件创建向导
    【提示】当软件组件为多应用时,勾选“添加子应用”,并设置子应用显示标题。
    点击<完成>按钮,则完成新建软件组件。
    5.3.2 设置组件描述信息
    如需设置组件描述信息,请双击软件组件工程下的“feature.xml”文件,弹出界面如下图所示:

    图 101 配置软件组件信息界面
    在图中标识处可修改软件组件的版本和名称,点击下面tab页切换至“信息”页,可设置该软件组件描述信息,如下图所示:

    图 102 设置软件组件描述信息

    5.3.3 设置包含的开发组件
    如果您想查看或修改当前开发组件所关联的开发组件,请双击软件组件工程下的“feature.xml”文件,如下图所示:

    图 103 概述页面
    切换到“插件”页面,在页面左侧“插件和段”的列表中显示的是当前软件组件关联的开发组件,具体如下图所示:

    图 104 当前软件组件关联的开发组件
    点击<添加>按钮,弹出“选择插件”界面。在“选择插件”输入框中输入要关联的开发组件,在“匹配项”中会快速过滤定位,如下图所示:

    图 105 选择开发组件
    在“匹配项”中选择开发组件后,点击<确定>按钮,“插件”页面如下图所示:

    图 106 软件组件修改后关联的开发组件
    若要删除关联开发组件,您在选择要删除的开发组件后,点击键盘上的“Delete”按键,即可删除关联。
    点击“文件”>“保存”菜单项,完成关联开发组件工作。
    5.4 使用开发组件(DC)
    5.4.1 新建开发组件
    在SC组件的邮件菜单中点击“新建”>“UniEAP开发组件”菜单项。如下图所示:

    图 107 新建开发组件
    在开发组件创建向导页面中,您需要为开发组件设置唯一的ID和选择所属软件组件,同时您可以根据需要为开发组件创建新的启动类,具体如下图所示:

    图 108 新建开发组件
    【注意】必须保证开发组件的ID在当前工作空间中唯一。
    点击<完成>按钮,开发组件创建完成。
    5.4.2 设置组件依赖
    开发组件可能会依赖其他开发组件,比如所有的开发组件都依赖“core”和“ria”组件,但是这个依赖关系在创建开发组件时就自动设置了。如果需要依赖其他开发组件,请双击开发组件工程下的“/META-INF/MANIFEST.MF”文件,并切换到“依赖性”页面,在“必需的插件”列表中列出了当前开发组件所依赖的其他开发组件,如下图所示:


    图 109 开发组件依赖性页面
    点击<添加>按钮,添加依赖的开发组件。弹出“选择插件”界面后,在“选择插件”输入框中输入要依赖的开发组件,在“匹配项”中会快速过滤定位,如下图所示:

    图 110 选择依赖的开发组件
    点击<确定>按钮,便可看到新添加的依赖关系,如下图所示:

    图 111 新增依赖的开发组件
    选择某依赖的开发组件后,点击<删除>按钮,便可取消依赖。
    点击“文件”>“保存”菜单项,完成依赖设置。

    5.4.3 设置公共访问包(PP)
    仅仅设置依赖的开发组件还不能够使用这些开发组件,被依赖的开发组件还需要公开其公共访问包,这样依赖其的开发组件才能使用其提供的公开接口。双击开发组件工程下的“/META-INF/MANIFEST.MF”文件,切换到“运行时”页面,在左侧“已导出的包”列表中列出的是已经设置的公共访问包,如下图所示:

    图 112 设置公共访问包
    点击<添加>按钮,选择要导出的包,可以一次性选择多个导出包,如下图所示:

    图 113 选择导出包
    点击<确定>,在“运行时”页面的“已导出的包”列表中已经列出刚才选择的导出包,如下图所示:


    图 114 新增公共访问包
    选中某导出包后,点击<删除>按钮,便可取消导出。
    点击“文件”>“保存”菜单项,完成公共访问包的设置。

    5.4.4 设置组件描述信息
    如需设置开发组件的描述信息,打开该DC下“/META-INF/MANIFEST.MF”文件,打开界面如下图所示:

    图 115 设置开发组件信息界面
    【注意】请不要修改DC的标识值,该标识值对应DC的ID,在工程中唯一。
    如图标志处可修改该开发组件的版本和名称。
    5.5 设置组件发布
    5.5.1 UniEAP V4组件发布机制
     什么是“发布”?
    UniEAP V4 中将Web应用按组件化拆分,进行按组件开发,每个组件中存储的均是Web应用的一个片段。“发布”则是将分布于各个组件中的Web应用程序片段组合到UniEAP工程中,形成一个完整的Web应用的过程。

     “发布”是如何将组件中的Web应用片段组合成一个完整Web应用的?
    分布于各个组件中的Web应用程序片段有以下几类:
    (1) Java类(模型生成的Java文件和用户自行添加的Java文件)编译而成的class文件。
    (2) Entity模型生成的Hibernate实体定义文件。
    (3) View模型生成的JSP、JS文件。
    (4) BO、DAO模型生成的Spring配置文件。
    (5) View模型生成的Struts2配置文件。
    (6) 用户添加的Web应用页面(JSP,HTML,JS)、图片、文本,压缩包等等文件。
    (7) 用户添加的Web应用所需的JAR包。
    (8) Web应用的web.xml,ehcache.xml,log4j.xml文件片段。

    对于上述(1)-(7)类资源,UniEAP V4会按照一定的规则,将上述资源复制UniEAP工程中的WebRoot指定目录。对于(8)类资源,UniEAP V4会分析其中的内容,与其他组件合并后输出到UniEAP工程WebRoot下对应位置。

     如何进行“发布”,怎么操作?
    “发布”通常情况下不需要手动触发,它会自动在合适的时机进行。
    但当关闭Eclipse的“自动构建”时,“发布”也会停止。
    通常情况下,“自动构建”均应为“启动”状态。

    设置“自动构建”的方法如下图所示(图中状态为“启动”):

    图 116 设置Eclipse的“自动构建”

     “发布”的详细规则是怎样的?
    如前所述“发布”包含两类基本动作:“拷贝”和“合并”。“拷贝”指的是将各个组件中的资源直接拷贝到UniEAP工程WebRoot指定位置,“合并”指的是将组件中的某些配置文件的内容读出,将其合并后,输出到UniEAP工程WebRoot指定位置。
    下面分别介绍两类动作,先以DC为例:
     “拷贝”类型的动作规则如下图:

    图 117 DC“发布”中“拷贝”类动作规则示意图

    图中演示了一个DC组件“DemoDC”的“发布”过程。图中左侧是DemoDC,右侧是其所属的UniEAP工程。

    DC下content文件夹保存除Java类Class文件和JAR包之外所有的需要发布到UniEAP Web工程中的Web应用程序片段。其中的内容大部分是自动生成的,用户也可以自行添加。
    content中包含三个子文件夹:
    conf(保存配置文件)
    tld(保存标签库)
    view(保存JSP页面、JS脚本、CSS和图片等需要在Web端访问的资源)

    conf中的配置文件被拷贝到UniEAP工程WebRoot中WEB-INF/conf/{SC名称}/{DC名称}目录。
    tld中的标签库文件被拷贝到UniEAP工程WebRoot中WEB-INF/tld/{SC名称}/{DC名称}目录。
    view中的文件拷贝到UniEAP工程WebRoot中{SC名称}/{DC名称}目录。

    DC下src文件夹中的Java源码编译而成的class文件会自动拷贝到UniEAP工程WebRoot中WEB-INF/classes文件夹。

    DC下lib文件夹中的JAR包会拷贝到UniEAP工程WebRoot中WEB-INF/lib文件夹。

     “合并”类型的动作规则:
    对于DC下content/conf文件夹下的三个配置文件:
    web.xml
    ehcache.xml
    log4j.xml
    UniEAP V4将分析其内容,根据所有组件内同名文件的内容进行“合并”。合并完毕后,web.xml将被输出到UniEAP工程WebRoot中WEB-INF文件夹。ehcache.xml和log4j.xml将被输出到UniEAP工程WebRoot中WEB-INF/conf文件夹。

    现在介绍SC的“发布”。SC下没有模型文件,Java源码和其他类型文件,仅有配置文件,因此,其“发布”只包含“拷贝”类型的动作。SC下包含的配置文件如下图:

    图 118 SC包含的配置文件

    图中所示的配置文件全部被拷贝到UniEAP工程WebRoot中WEB-INF/conf/{SC名称}目录。如下图所示:

    图 119 SC配置文件发布到UniEAP工程后位置示意图

    最后介绍Patch工程的“发布”。
    Patch工程中的webroot目录,其结构与UniEAP工程的webroot目录完全相同,如下图所示:

    图 120 Patch工程与UniEAP工程结构对比图
    Patch工程进行“发布”时,其src源码文件夹下的Java文件编译成class文件,将被拷贝到UniEAP工程WEB-INF/classes目录,其webroot下的内容(除了web.xml,ehcache.xml和log4j.xml),将按照对应路径拷贝到UniEAP工程webroot下。
    web.xml,ehcache.xml和log4j.xml(其路径参考图中所示),与其他组件进行合并后输出到UniEAP工程的对应位置。
    5.5.2 设置组件发布
    在实际开发过程中,通常需要一边开发一边测试,“发布”保证了在组件内改动的内容可以实时反映到UniEAP工程,也就可以实时看到改动的效果。如果每次“发布”耗时过长,将会影响到开发的速度。从实际情况来看,并非所有组件都是需要频繁发布的。通常我们只需要发布正在进行开发的一个或几个组件,其他组件只需要发布一次就可以了。
    因此,UniEAP V4 WorkShop提供了控制组件发布的功能。
    在WorkShop工具栏上,点击“设置UniEAP组件发布”按钮,启动“设置组件发布”功能。
    如下图:

    图 121 设置UniEAP组件发布按钮

    点击按钮后,会弹出“设置组件发布”功能页面,如下图:

    图 122 “设置组件发布”功能页面
    页面中会列出当前UniEAP工程下所有的组件,默认情况下,所有组件均处于“发布”状态(勾选),我们可以选择不需要“发布”的组件,取消其前方的勾。
    设置完毕后,点击<OK>即可。
    在页面下方,有一个选项“在UniEAP资源管理器中隐藏不发布组件”。如果勾选此项,UniEAP资源管理器中所有不发布的组件将自动隐藏,取消此项,UniEAP资源管理器将显示所有组件。
    5.6 设置组件发布Filter顺序
    在需要调整顺序的filter中加入load-on-startup参数,如下所示:
    <filter>
    <filter-name>loginfilter</filter-name>
    <filter-class>com.neusoft.report.sample.AccountFilter</filter-class>
    <init-param>
    <param-name>load-on-startup</param-name>
    <param-value>1</param-value>
    </init-param>
    </filter>
    load-on-startup参数值为非负数,取值越小顺序越靠前。该参数是在相应组件(包括Patch工程)的web.xml文件中进行修改,在发布到UniEAP工程时自动去掉。
    5.7 组件调试设置源
    由于UniEAP工程中没有java源码文件,只有来自各个组件编译后的class文件。我们在开发组件的java源码中设置断点,调试启动服务后,会出现找不到源码文件的提示,如下图所示:

    图 123 调试时出现找不到源情况
    您可以点击“编辑源查找路径”按钮,在弹出的对话框中进行设置,如下图所示:

    图 124 编辑源查找路径对话框
    点击<添加>按钮,选择“Java 项目”选项,如下图所示:

    图 125 编辑源查找路径对话框
    点击<确定>按钮,在弹出的对话框中选择引用源的项目(可多选,一般为DC或Patch工程),如下图所示:

    图 126 选择项目
    点击<确定>按钮,完成设置。您也可以在“调试”透视图下,从工具栏中的 下拉选项中选择“调试 配置”项,弹出如下对话框,设置过程同前。

    图 127 在调试配置中设置源
    【提示】若采用上述方法仍不可用,则在workshop的eclipse.ini文件中增加如下参数“-Duser.language=en”,重新启动workshop即可。

    5.8 UniEAP工程部署
    5.8.1 开发测试环境
    在开发过程中,经常需要对开发的内容进行测试,因此需要将UniEAP工程部署到应用服务器。建议使用Tomcat 6.0测试环境。
    将UniEAP工程部署到应用服务器的方法如下:
    1 在UniEAP透视图中下方,找到“Servers”视图。在视图空白处鼠标右键单击,在弹出菜单中选择“New”->“Server”。如下图:

    图 128 打开新建Server向导
    在弹出的“New Server”对话框中,选择“Tomcat v6.0 Server”,其他字段如下图,之后点击<Next>。

    图 129 Server设置向导——选择应用服务器
    如果之前没有配置过Tomcat 6.0应用服务器的位置,向导会提示进行配置,如下图。页面中“Name”文本框可以定义应用服务器的名称(通常保持默认即可),“Tomcat Installation directory”文本框中需要输入Tomcat 6.0应用服务器所在目录,点击其右侧的<Browse>按钮可以直接选择。设置完毕后点击<Next>继续。

    图 130 Server设置向导——配置应用服务器
    这一页面中需要配置部署到应用服务器的UniEAP工程,如下图:

    图 131 Server设置向导——设置部署的UniEAP工程

    页面左侧列出了当前工作空间中的UniEAP工程,点击要进行部署的UniEAP工程,单击屏幕中间的<Add>按钮,选中的UniEAP工程会从左侧移动到右侧,表示设置部署成功。之后点击<Finish>按钮。
    配置向导关闭,配置好的应用服务器出现在“Servers”视图,如下图:

    图 132 配置应用服务器后的Servers视图
    现在双击刚配置好的应用服务器。出现如下界面:

    图 133应用服务器设置界面
    勾选“Serve modules without publishing”,之后点击UniEAP透视图左上角的<保存>。至此,应用服务器配置完毕。
    进行测试时,在Server视图中点击配置好的应用服务器,点击<Start the server in debug mode>启动应用服务器,即可进行调试。如下图所示:

    图 134以Debug模式启动应用服务器
    5.8.2 系统上线环境
    通常在系统上线前进行系统测试时,需要将整个UniEAP工程导出为可部署到最终生产环境应用服务器的Web应用,下面介绍操作过程:
    1 首先,确认UniEAP工程中已经引入了所有必要的组件(SC、DC、Patch工程)。
    2 打开“设置组件发布”对话框,确认所有组件均处于“发布”状态(组件前面的CheckBox均为勾选状态)。
    3 重新编译全部组件。操作方法如下:点击“Project”>“Clean”。同时请确认“Build Automatically”选项处于勾选状态。如下图:

    图 135以Clean当前工作空间
    4 在接下来的对话框中,选中“Clean all projects”,之后点击<OK>按钮。

    图 136选择Clean所有工程
    5 不要进行任何操作,等待Build动作全部完成。进行Build时,WorkShop右下角会有正在运行任务的滚动提示。同时Console视图也会不断输出Build信息。如下图:

    图 137等待Build完成
    6 所有操作完成之后,就可以正式导出可部署到最终生产环境的Web应用了。分两种情况:
     生产环境Web应用不使用WAR包。
    直接将UniEAP工程下的webroot文件夹下的内容作为最终部署的Web应用文件即可。
     生产环境需要使用WAR包。
    鼠标右键单击UniEAP工程,选择“Export”。如下图:

    图 138 UniEAP工程右键菜单
    在弹出的“Export”向导中“Select an export destionation”对话框中输入“war”,在下方的树形列表中选中“WAR file”,之后点击<Next>按钮。如下图:

    图 139 选择导出“WAR”类型文件
    在接下来的向导页面中,在“Destination”文本框右侧点击“Browse”,为导出的WAR文件选择一个路径并输入一个名称。之后点击<Finish>按钮。如下图:

    图 140 设置导出“WAR”文件位置以及名称。
    等待导出完成,生产环境使用的Web应用WAR包就生成了。
    5.8.3 UniEAP V4兼容应用服务器列表
    UniEAP V4兼容如下应用服务器:
    Tomcat 5.5、Tomcat 6、WebSphere 6.0、WebSphere6.1、Weblogic 9.0、Weblogic 10。
    第6章 模型化开发使用指南
    6.1 使用模型开发
    6.1.1 Entity模型
     新建Entity模型
    选择当前DC工程下的“metamodel”>“entity”文件夹,点击右键,在右键菜单中选择“New”>“Entity 模型”菜单项。具体如下图所示:

    图 141 Entity显示视图对话框
    点击菜单项后,会打开Entity创建向导,如下图所示:

    图 142 新建Entity文件向导
    【提示】 “数据库类型”目前版本仅支持Oracle数据库。
    6.1.1.1 从数据库表创建
    输入正确的数据库URL、用户名和密码后点击右上角<测试连接>按钮会对所输入的数据库进行连接测试,测试结果会以对话框形式弹出,如下图所示:

    图 143 测试连接失败对话框

    图 144 测试连接成功对话框
    如测试连接成功,则点击<下一步>,页面如下图所示:

    图 145 映射Entity模型向导页
    此时点击上图中标注的<刷新>按钮,即可根据上页输入的数据库连接信息读取到数据库中的表,并提供过滤框支持对表名进行过滤,如下图所示:

    图 146 映射Entity模型向导页过滤框
    【提示】该向导页下方的“ID生成策略”可参考Hibernate主键生成策略,默认为“uuid”。
    该向导支持批量生成Entity,当用户选择好所需要的数据库表之后,点击<完成>,则会在“metamodel”>“Entity”下生成对应“*.entity”文件,并同时在“Unieap工程/当前SC/当前DC/Content/conf/generated/hbm/*.hbm.xml”路径生成相应的Hibernate配置文件。
    除此之外,每个Entity文件将会对应生成java文件,自动生成Entity中属性的“get”和“set”方法,存放于“src”>“com.sc.dc.entity”包下。
    【警告】对于数据库表中没有“id”属性的情况,生成Entity文件时将不生成Hibernate配置文件及对应java文件,仅在“metamodel”>“entity”中生成“*.entity”文件。
    6.1.1.2 从已有Entity模型创建
    选择<从已有Entity模型创建>后,创建界面如下图所示:

    图 147 从已有Entity模型创建框
    在<文件名>中填入即将创建的Entity模型名称,之后点击<继承>按钮,选择需要继承的Entity模型,点击<finish>即可。
    6.1.1.3 删除Entity模型
    选择要删除的Entity模型,单击键盘<delete>键或在右键菜单中选择<删除>选项,弹出对话框,如下图所示:

    图 148 删除Entity模型对话框
    点击<确定>将删除该Entity模型,并自动删除对应Hibernate配置文件。但不会删除对应java文件,需要用户手动删除。
    6.1.1.4 编辑Entity模型
    双击Entity模型,如下图所示:

    图 149 打开Entity模型
    Entity模型文件以XML格式存储,其中<id>节点记录该Entity中的主键信息。
     Name:记录该Entity对应主键ID的属性名。
     Type:id类型,一般为string,如不为常用类型则需使用全路径名。
     Column:记录主键数据库字段,其中name属性对应Class属性名,length属性对应主键数据库列字符串类型字段的长度。
     Generator:为持久化类生成主键,其中class属性记录主键生成算法,默认为“uuid”。
    Entity模型中每个字段对应模型中的一个<property>节点,属性如下:
     Name:对应主键ID属性名,同时对应于java文件中的“get”和“set”方法。
     Label:标识名称。
     Type:类型,如不为常用类型则需使用全路径名。
    每一个<property>所对应数据库字段内容存放于其下的<column>节点中,其属性介绍如下:
     Name:对应于class的属性名。
     Not-null:非空字段,当根据模型自动生成数据库时,需要设置此属性。值为“true”或“false”。
     Length:数据库列字符串类型字段的长度,当根据模型自动生成数据库时,需要设置此属性。
    【提示】当有需要对Entity文件进行修改或更新时,只需修改该模型文件,即修改该模型文件的XML内容,修改完毕使用“ctrl+s”保存后将自动对Hibernate配置文件及java文件进行更新。并且Entity文件支持java文件反向生成到模型,用户可以通过在java文件中增改方法,保存后将自动同步到Entity模型中。
    6.1.1.5 检查更新
    右键点击Entity模型,点击<UniEAP工具>--<检查更新>,如下图所示:

    图 150 Entity模型文件检查更新菜单
    点击后弹出弹出对话框,填入正确URL及用户名和密码,如下图所示:

    图 151 Entity模型文件检查更新界面
    填写完毕后点击下一步,会自动连接数据库检查数据是否有变化,如下图所示:

    图 152 Entity模型文件检查更新结果
    图中所示为数据库更新结果,用户可针对自身需要勾选需要同步更新的属性,点击<finish>与数据库进行同步。
    6.1.1.6 非持久化属性
    当业务数据中某字段不需要持久化到数据库,主要由其他字段或实体计算或推断出来的时候,需要在entity中加入非持久化属性,下面举例说明:
    在研发过程中每个”backlog”需要统计其相应的”实际工作量”,该数据不对应持久化属性,由” COMMON_JOURNAL”数据库表中” timeConsume”(所用时间)计算得到,那么开发人员需要在”backlog”实体中加入对应字段记录”实际工作量”,如下所示:
    <property name="realWorkload" label="实际工作量"
    formula="(select nvl(sum(j.time_consume),0) from COMMON_JOURNAL j,COMMON_TASK t where j.task_id = t.id and t.backlog_id = ID)" type="float" />
    为方便对比,截取一个持久化属性做为参照,如下所示:
    <property name="expectWorkdays" label="估计所需工作的人日。生成启动报告时需要"
    type="string">
    <column name="EXPECT_WORKDAYS" not-null="false" />
    </property>
    可以看到,”实际工作量”对应的property未对应任何”column”节点,即未进行持久化。其中name及label属性由用户自行定义,分别对应数据集界面的名称及标题。用户还需要根据该数据类型定义type属性,其中,formula属性代笔该数据在数据集被调用时会自动去后台发送并执行的sql语句,即图中的:
    "(select nvl(sum(j.time_consume),0) from COMMON_JOURNAL j,COMMON_TASK t where j.task_id = t.id and t.backlog_id = ID)"
    通过该sql语句可以看出该字段由表”COMMON_JOURNAL”及”COMMON_TASK”控制并获取数据,所以该字段不需要进行持久化,否则会造成数据的冗余。
    在生成数据集时,该属性与其他持久化属性相同,如下图所示:

    图 153 Entity模型文件检查更新菜单
    【注意】类型为”real”表示该属性为number类型,会通过工具自动将float等类型转化为”real”属性。

    6.1.2 DTO模型
    6.1.2.1 应用场景
    DTO模型的主要应用场景如下:
     对Entity模型进行扩展,增加新属性但并不需要持久到数据库中,示例如下:

    图 154 DTO应用场景示例1
     需要在一个数据集中同时使用多个实体模型,此时可以使用DTO模型将所需要的Property加入进来,示例如下:

    图 155 DTO应用场景示例2
    6.1.2.2 新建DTO模型
    选择当前DC工程下的“metamodel”>“dto”文件夹,点击右键,在右键菜单中选择“New”>“DTO 模型”菜单项。具体如下图所示:


    图 156 显示视图对话框
    点击菜单项后,会打开DTO创建向导,如下图所示:

    图 157 创建DTO文件向导
    点击<下一步>可选择依赖的entity模型,如下图所示:

    图 158 创建DTO文件向导中选择依赖entity
    选择一个entity后点击<下一步>,选择依赖该entity中的属性选择界面,如下图所示:

    图 159 创建DTO文件向导中根据entity选择依赖属性
    之后点击<完成>,会自动打开并切换到该DTO文件视图界面,所生成的DTO文件为XML格式文件,如下图所示:

    图 160 DTO模型界面
    其中,<baseInfo>节点中存储该DTO的基本信息,包括“作者”、“创建时间”、“修改时间”、“版本号”及“描述信息”。
    如果在新建时选择依赖entity中的部分属性,则DTO文件中会存在<dependence>节点,标识该DTO依赖特定entity中的属性。下面简单介绍<dependence>节点的属性含义。
     type:标识该DTO对象所依赖的数据类型,目前只支持entity。
     name:标识该DTO对象的属性值。
     ref:标识该DTO对象所依赖的entity模型名称。
     property:标识所依赖entity模型的对应属性名称,对应entity中property节点下的name属性。
     dc:标识该DTO对象所依赖entity所在的开发组件(dc)名称。
    目前DTO模型不支持图形化修改,只能通过手动编辑XML文件进行增加、删除或修改操作,下面对在DTO文件中增加属性的操作进行介绍。
    对不依赖entity属性的DTO对象,在DTO模型中以<property>节点标识,该节点用来定义DTO对象成员变量,其下共有三个属性:
     name:该DTO对象的属性名称。
     type:java中的常用类型,或特殊类型的全路径,如:“string”、“java.util.List”等。
     label:DTO对象属性概述,为前台显示所用。
    例如对DTO模型增加一个名为“spState”的节点,其显示名称为“审批状态”,类型为“string”。如下图所示:

    图 161 增加DTO对象
    【提示】DTO可以依赖多个entity,由于新建DTO向导中只可绑定一个entity模型,若依赖其他entity模型则需要用户手动添加XML节点,添加方式如上所述,格式同单一entity依赖情况,如下图所示:

    图 162 增加依赖entity的DTO对象
    6.1.2.3 删除DTO模型
    选择要删除的DTO模型,单击键盘<delete>键或在右键菜单中选择<删除>选项,弹出对话框,如下图所示:

    图 163 删除DTO模型
    点击<确定>后即可删除该DTO文件。
    6.1.2.4 使用示例
    当业务上需要在同一数据集中使用多个表中的数据时,可以使用DTO作为数据对象,新建DTO方法参考用户手册DTO相关章节,新建后效果如下所示:

    当用户需要使用该DTO时首先需要根据该DTO构建数据集,如下图所示:

    图 164 新建数据集
    建完数据集后即可通过该数据集新建模式控件等,以下图Grid为例:

    图 165 Grid模式控件
    该Grid通过其他按钮的查询操作来返回数据,查询所对应的DAO后台方法如下,该方法也常用来构造DTO对象:
    public List getUnitsByUserId(String userId) {
    String dimensionId = OrgConstant.DEFAULT_DIMENSION_ID;
    // 对DTO每个属性进行查询并拼成一个DTO对象的List返回
    String sql = "select dimUnit.ALIAS_NAME as aliasName, dimUnit.UNIT_PATH as unitPath,dimUnit.UNIT_ID as unitId,unit.CODE as unitCode,unit.DESCRIPTION as unitDescription "
    + "from UP_ORG_DIMENSION_UNIT dimUnit,UP_ORG_UNIT unit,UP_ORG_UNIT_USER unitUser "
    + "where dimUnit.UNIT_ID = unit.ID "
    + "and unit.ID = unitUser.UNIT_ID "
    + "and unitUser.USER_ID = ? " + "and dimUnit.DIMENSION_ID= ?";
    SQLQuery query = super.getSessionFactory().getCurrentSession()
    .createSQLQuery(sql);
    query.setParameter(0, userId);
    query.setParameter(1, dimensionId);
    // 各属性的存放类型
    query.addScalar("aliasName", Hibernate.STRING);
    query.addScalar("unitPath", Hibernate.STRING);
    query.addScalar("unitId", Hibernate.STRING);
    query.addScalar("unitCode", Hibernate.STRING);
    query.addScalar("unitDescription", Hibernate.STRING);
    // 返回结果为键值队(map)
    query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
    // 得到查询结果,为List<Map(propName,value)>的形式
    List<UnitDTO> lists = query.list();

    ……

    return results;
    }
    其中,query的构造也可写作如下形式:
    Query q = super.getSessionFactory().getCurrentSession().createSQLQuery(
    sql).setResultTransformer(
    Transformers.aliasToBean(UnitDTO.class));
    List list = q.list();

    6.1.3 DAO模型
    6.1.3.1 新建DAO模型
    选择当前DC工程下的“metamodel”>“dao”文件夹,点击右键,在右键菜单中选择“New”>“DAO 模型”菜单项。具体如下图所示:

    图 166 DAO显示视图对话框
    点击菜单项后,会打开DAO创建向导,如下图所示:

    图 167 新建DAO向导页
     配置数据源
    该向导最下方可以选择数据源,其中多数据源的具体配置存放在”webroot/WEB-INF/conf/platform/core/applicationContext-datasource.xml”中:
    <!-- 定义系统数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName">
    <value>${unieap.datasource.driverClass}</value>
    </property>
    <property name="url">
    <value>${unieap.datasource.jdbcUrl}</value>
    </property>
    <property name="username">
    <value>${unieap.datasource.user}</value>
    </property>
    <property name="password">
    <value>${unieap.datasource.password}</value>
    </property>
    <property name="initialSize">
    <value>${unieap.datasource.initialSize}</value>
    </property>
    <property name="maxActive">
    <value>${unieap.datasource.maxActive}</value>
    </property>
    <property name="maxIdle">
    <value>${unieap.datasource.maxIdle}</value>
    </property>
    <property name="maxWait">
    <value>${unieap.datasource.maxWait}</value>
    </property>
    </bean>

    输入文件名后点击<完成>按钮,即完成创建DAO模型。与此同时,将同时创建该DAO模型对应接口类(当选择已有接口时不创建接口类,具体细节参见6.1.4.2)和实现类,当创建完成后会自动打开该DAO实现类,如下图所示:

    图 168 DAO实现类
    6.1.3.2 删除DAO模型
    选择要删除的DAO模型,单击键盘<delete>键或在右键菜单中选择<删除>选项,弹出对话框,如下图所示:

    图 169 删除DAO文件对话框
    点击<确定>后将会自动删除DAO模型文件,并更新spring配置文件,但不会删除对应实现类和接口,可在当前DC下的“src”文件夹中对其进行手动删除。
    6.1.3.3 使用自动注入
    DAO有时需要调用其他DAO,这种场景下会使用spring依赖注入特性。UniEAP V4提供了自动注入功能,只需要用户在DAO实现类中提供“set”方法,UniEAP WorkShop会自动帮用户生成注入相关的spring配置。用户不需要自行修改配置文件。
    下面提供一个简单的自动注入的例子来说明这一点:
    某DAO(为保证描述清晰,该DAO文件以下简称为“D”),需要调用另一个DAO中的部分方法,按照Spring的规范,在D中增加另一个DAO的私有成员变量,并提供对应的set方法,并在Spring配置文件中增加相应的注入片段,由Spring实现自动依赖注入。在UniEAP V4中,我们只需要在D中增加另一个DAO的私有成员变量,和set方法即可,UniEAP WorkShop将自动生成相应的Spring注入片段。
    增加私有成员与set方法示例,如下图所示:

    图 170 在DAO文件中添加“set”方法
    保存DAO后,UniEAP WorkShop会自动为DAO(图中所示为“myDAO”)生成Spring注入片段。如下图所示(“<property name=”myDAO” ref=”planManagement_myDAO_dao”>”):

    图 171 DAO文件对应spring配置文件内容
    【注意】使用DAO自动注入特性的私有成员变量,必须以“DAO”结尾。
    6.1.3.4 使用存储过程
    【提示】在阅读本节前,首先要了解存储过程的基础知识和使用方法。
    在V4中推荐在DAO(该DAO需继承默认的BaseHibernateDAO基类或其他以BaseHibernateDAO为基类的子类)中调用存储过程,调用方法示例如下,具体细节及用法在代码注释中给出:
    public void callProcedure(User user) {
    // 存储过程名称由存储过程在数据库中的“包名.存储过程名”定义,即以下调用PKG_TEST_FEEAUDIT包中的prc_a_commAuditing存储过程
    String procedurename = "PKG_TEST_FEEAUDIT.prc_a_commAuditing";
    int i = 0;
    // ProcPara为V4为存储过程提供的参数对象
    // 创建格式为:new ProcPara(序号,参数为输入或输出<分别对应: ProcPara.IN 和ProcPara.OUT>,输入的参数值<当该参数为输出时不需要该属性>,参数类型<一般由java.sql.Types定义>)
    ProcPara[] paras = new ProcPara[] {
    // 五个输入参数
    new ProcPara(++i, ProcPara.IN, "", Types.VARCHAR), // 缴费类型
    new ProcPara(++i, ProcPara.IN, "", Types.VARCHAR), // 缴费主体
    new ProcPara(++i, ProcPara.IN, 201211, Types.DECIMAL), // 结算期
    new ProcPara(++i, ProcPara.IN, "", Types.VARCHAR), // 缴费对象
    new ProcPara(++i, ProcPara.IN, "", Types.VARCHAR), // 款项
    // 两个输出参数
    new ProcPara(++i, ProcPara.OUT, Types.VARCHAR),
    new ProcPara(++i, ProcPara.OUT, Types.VARCHAR) };
    // 执行存储过程
    super.callStoredProcedure(procedurename, paras);
    //输出参数可以直接通过paras[5].getValue()或paras[6].getValue()取得
    Object value = paras[5].getValue();
    }


    6.1.3.5 使用HibernateTemplate模板
    在V4环境中,(DAO模型的实现)需要用户使用Spring的HibernateTemplate模板,将Hibernate 的持久层访问模板化。
    HibernateTemplate模板可以满足用户的绝大部分需求,查询和保存的使用方法示例如下:
    /**
    * {@inheritDoc}
    */

    public List getDirectAdminRoles(String roleId, String roleType) {
    String hql = "from AdminRole adminRole where adminRole.parentRoleId=? and adminRole.roleType=?";
    return getHibernateTemplate().find(hql,
    new Object[] { roleId, roleType });
    }

    /**
    * {@inheritDoc}
    */
    public AdminRole saveAdminRole(AdminRole adminRole) {
    getHibernateTemplate().save(adminRole);
    return adminRole;
    }
    当用户需要对复杂的持久层访问或使用SQL语句时,需要使用HibernateTemplate提供的doInHibernate方法,示例如下:
    /**
    * {@inheritDoc}
    */
    public List getUsersByUnitIdExceptAdminRoleId(final String unitId,
    final String adminRoleId, final int pageNumber, final int pageSize) {
    List result = (List) getHibernateTemplate().execute(
    new HibernateCallback() {
    public Object doInHibernate(Session session)
    throws HibernateException, SQLException {
    String sql = "select unitUser.* from Unit_User unitUser where unitUser.UNITID = ? ";
    SQLQuery query = session.createSQLQuery(sql).addEntity(UnitUser.class);
    query.setParameter(0, unitId);
    query.setFirstResult((pageNumber - 1) * pageSize);
    query.setMaxResults(pageSize);
    return query.list();
    }
    });
    return result;
    }

    6.1.4 BO模型
     新建BO模型
    选择当前DC工程下的“metamodel”>“BO”文件夹,点击右键,在右键菜单中选择“New”>“BO 模型”菜单项。具体如下图所示:

    图 172 BO显示视图对话框
    点击菜单项后,会打开BO创建向导,如下图所示:

    图 173 新建BO向导页
    6.1.4.1 新建BO模型
    当新建的BO模型接口为已有接口时,在新建BO对话框中点击<选择已有接口>,在弹出的对话框中选择已有的接口类,该接口类可以选择本DC或依赖DC中的BO接口类,如下图所示:

    图 174 BO模型选择已有接口

    如不选择已有接口则不需要上述操作,输入文件名后点击<完成>按钮即完成创建BO模型。与此同时,将同时创建该BO模型对应实现类(及接口类,取决于是否基于已有接口创建),当创建完成后会自动打开BO实现类的视图,如下图所示:

    图 175 BO编辑器
    其中implements的类名即为之前选定的接口名。
    6.1.4.2 新建BO实现类(多实现)
    当需要BO模型的多实现功能时,右键点击需要实现的接口类对应的BO模型,依次点击<New>-<BO模型>,弹出对话框如下图所示:

    图 176新建BO多实现类
    在<实现类名>一栏填入新实现类名,点击完成,即可对该BO添加新的实现类,添加后BO模型在视图中的效果如下图所示:

    图 177 BO多实现类结构图
    对多实现的BO模型,可以指定其中一个实现类为默认实现类,如不指定则以新建时间先后为准,指定默认实现类的操作如下图所示:

    图 178 BO模型设置默认实现类
    当所选实现类变为粗体则表明成功设置该实现类为默认实现。
    6.1.4.3 删除BO模型
    选择要删除的BO模型,单击键盘<delete>键或在右键菜单中选择<删除>选项,弹出对话框,如下图所示:

    图 179 删除BO文件对话框
    点击<确定>后将会自动删除BO模型文件,并更新spring配置文件,但不会删除对应实现类和接口,可在当前DC下的“src”文件夹中对其进行手动删除。
    6.1.4.4 事务管理
     BO事务控制
    当BO模型需要事务控制时,BO方法要满足applicationContext-datasource.xml文件中事务代理所定义的前缀命名规范。
    platform/core/content/conf/applicationContext-datasource.xml文件定义了事务控制相关配置。当用户需要修改事务控制相关信息时,需要使用patch工程,在相同路径patch/webroot/WEB-INF/conf/platform/core/,创建同名文件。该文件在发布时将覆盖原core组件下的对应文件,前缀的命名规范定义如下:
    <bean id="baseTxProxy" lazy-init="true"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
    <ref bean="transactionManager" />
    </property>
    <property name="transactionAttributes">
    <props>
    <prop key="add*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="create*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="update*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="config*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="delete*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="save*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="do*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="register*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="remove*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="start*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="pause*">PROPAGATION_REQUIRED,-DataAccessException,-HibernateException,-PersistenceException
    </prop>
    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
    </property>
    </bean>
    即在该事务代理下用户的BO方法命名需要满足以上定义的(如:add/create/update等)前缀命名规范,当用户需要添加前缀时可在patch工程中复写该配置文件。
     事务代理
    UniEAPV4工程,默认提供的是基于JDBC的事务管理,是面向一个连接的。如果想在多个数据库连接之间控制事务,就需要使用JTA事务管理。根据用户的使用场景不同,主要可以分为两种情况:
    1通过第三方的jar包来支持JTA事务。
    2使用应用服务器提供的JTA事务管理功能。
    当用户需要使用JTA事务管理时,需要在新建BO对话框下方<事务代理>中选择<jtaTxAdvisor>。
    6.1.4.5 使用自动注入
    BO开发时,经常需要调用DAO和其他BO,这种场景下会使用spring依赖注入特性。UniEAP V4提供了自动注入功能,只需要用户在BO实现类中提供“set”方法,UniEAP WorkShop会自动帮用户生成注入相关的spring配置。用户不需要自行修改配置文件。
    下面提供一个简单的自动注入的例子来说明这一点:
    某BO,需要调用DAO完成数据持久化操作。这时,需要在BO的实现类中提供DAO的私有成员变量与对应的set方法,如下图所示。

    图 180 在BO文件中添加“set”方法
    添加完私有成员变量与对应的set方法后,保存BO模型,UniEAP WorkShop会自动为“myDAO”(图中所示)生成对应的Spring注入片段。如下图所示:

    图 181 BO文件对应spring配置文件内容
    【注意】使用BO自动注入时,BO私有成员名称必须以“BO”结尾,DAO私有成员变量必须以“DAO”结尾。
    6.1.4.6 多返回值处理
    当业务逻辑需要多返回值时,需要使用到BOContext对象,后台构造并返回该对象代码如下所示:
    public BOContext getManagedAdminRoleUnits() {
    BOContext bc = new BOContextImpl();
    // 根据管理角色类型获得当前登录用户相应的管理角色id和超级管理角色id
    User user = UniEAPContextHolder.getContext().getCurrentUser();
    String roleType = user.getAdminRoleType();
    if (roleType==null)
    return bc;
    List<String> roleIds = user.getRoleIds(roleType);
    if (roleIds==null||roleIds.size()==0)
    return bc;
    if (roleIds.get(0).equalsIgnoreCase("adminRole")){
    bc.put("isSuperAdminRole", true);
    return bc;
    }
    List<AdminRoleUnit> l = unitDAO.getAdminRoleById(roleIds.get(0));
    if(l != null && l.size() > 0){
    List<Boolean> cascadeStatus = new ArrayList<Boolean>();
    for(AdminRoleUnit aru : l){
    cascadeStatus.add(aru.getIsCascade());
    }
    bc.put("cascadeStatus",cascadeStatus);
    }
    return bc;
    }
    后台构造该对象时可以将该对象看做Map进行处理,将多返回值遵守KEY-VALUE的方式放入。数据传回前台后,根据数据类型前台又不同的取值方式,具体如下:
     当返回值为简单类型时,即:Number、String、Boolean、Character、BigDecimal,前台通过dc.getParameter(key)方法取值。
     当返回值为List(Array)时,分为两种情况:
     List(Array)中为简单类型,此种情况List(Array)通过dc.getParameter(key)方法取值。
     List(Array)中为复杂类型时,此种情况BoContext将该List(Array)转为DataStore,用户在前台通过dc.getDataStore(key)取得该返回值
     当返回值为QueryResult或其他复杂对象时,该返回值将被转为DataStore,通过dc.getDataStore(key)取值
    6.1.4.7 一键发布WebService
    【注意】可以通过CXFServlet的映射地址,使用浏览器访问查看已发布的WebService列表。本例中访问地址为http://主机名 + 应用名 +“/unieapServices”即可查看服务列表。
    按以下步骤进行操作:
    1. 右键点击Bo模型,在菜单中选择“UniEAP 工具”-> “一键发布Webservice”。
    2.在该dc的content/conf文件夹下会自动生成名为applicationContext-ws.xml的文件。
    3. 需要手动在该dc的content/conf/applicationContext.xml中,添加“<import resource="applicationContext-ws.xml" /> ”。
    4. 客户端代码编写:举例说明,假设需要调用TestBO的print方法来打印用户列表,BO代码如下:
    public interface TestBO
    {
    public void print(List<User> userList);
    }

    @ModelFile(value = "testBO.bo")
    public class TestBOImpl implements TestBO
    {
    @Override
    public void print(List<User> userList)
    {
    if (userList != null && userList.size() > 0)
    {
    for (User user : userList)
    {
    System.out.println("User name is :" + user.getName());
    }
    }
    }
    }

    public class User
    {
    private String name;

    public String getName()
    {
    return name;
    }

    public void setName(String name)
    {
    this.name = name;
    }
    }
    调用该BO被发布的WebService的代码为如下:
    public static void main(String[] args)
    {
    ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
    factory.setServiceClass(TestBO.class);
    factory.setAddress("http://localhost:8090/framework/ unieapServices/demoSC/demoAF/test?eap_username=admin&eap_password=1");
    /*注:需要注意的是,客户端调用的地址配置为:主机名 + 应用名 + CXFServlet的映射地址 + 相对地址(可在applicationContext-ws中的对应address属性)。*/
    factory.getServiceFactory().setDataBinding(new AegisDatabinding());// 指定aegis绑定
    TestBO service = (TestBO) factory.create();
    List<User> userList = new ArrayList<User>();
    User user1 = new User();
    user1.setName("aa");
    User user2 = new User();
    user2.setName("bb");
    userList.add(user1);
    userList.add(user2);
    service.print(userList);
    }
    【注意】客户端调用地址后面必须拼接上用户名密码,调用请求才能通过安全认证。
    附applicationContext-ws配置文件内容简要说明:

    图 182配置文件说明

    6.1.5 View模型
    6.1.5.1 新建View模型
    选择当前DC工程下的“metamodel”>“view”文件夹,在右键菜单中点击“New”>“View模型”菜单项,如下图所示:

    图 183 新建View模型菜单
    点击菜单项后,会打开新建view模型的向导,如下图所示:

    图 184 新建View模型向导
    在向导中输入View模型的相关信息后,点击< Finish >按钮,完成新建view模型。
    完成新建后,会打开view模型的UIDesigner编辑器,并默认切换到UIDesigner编辑器的概要页面如下图所示:

    图 185 View模型编辑器
    【提示】UIDesigner编辑器中其它页面的使用将在后面的章节中介绍。
    6.1.5.2 View模型编辑器
    作者输入域中可以编辑View模型的作者信息。
    【技巧】作者输入域的默认值为Eclipse启动参数配置中所设置的用户信息。
    版本号输入域中可以编辑View模型的版本号信息。
    描述输入域中可以编辑View模型的描述信息。
    标题输入域中可以填写View模型的标题属性,即页面的标题。
    勾选支持脚本国际化,页面即可支持脚本国际化。
    勾选支持页面授权,页面即可在管理控制台进行页面控件权限设置。
    点击入口信息链接可以切换到UIDesigner编辑器的入口信息页面。
    点击过程调用链接可以切换到UIDesigner编辑器的过程调用页面。
    点击设计链接可以切换到UIDesigner编辑器的设计页面。
    点击脚本链接可以切换到UIDesigner编辑器的脚本页面。
    点击源码链接可以切换到UIDesigner编辑器的源码页面。
    点击数据集链接可以打开数据集视图。
    完成view模型创建后,会自动生成模型相关的代码文件,包括2个Javascript文件和一个Jsp文件,点击对应的代码链接将用新的编辑器打开这些代码文件,如下图所示:

    图 186 打开View模型相关代码文件
    【提示】Javascript文件和Jsp文件的路径为:当前DC工程/content/view/generated。
    6.1.5.3 删除View模型
    选择要删除的View模型文件,在右键菜单中点击“Delete”菜单项,如下图所示:

    图 187 删除View模型文件
    点击菜单项后,会弹出确认删除对话框,如下图所示:

    图 188 确认删除对话框
    点击< OK >后,该View模型文件被删除并且弹出是否自动删除创建View模型自动生成的Javascript文件和Jsp文件的确认对话框,如下图所示:

    图 189 删除View模型文件对应源码文件确认对话框
    点击< Yes >后,创建该View模型文件自动生成的Javascript文件和Jsp文件被删除。
    【注意】删除View模型文件不会删除创建该View模型文件自动生成的Java文件,需要用户手动删除。
    6.1.5.4 View模型继承
     View模型继承简介
    通过View模型的继承,可以复用原有模型的控件,公共方法,控件事件,并且支持方法的覆盖和追加达到减少页面开发重复工作的目的。
     创建继承的View模型
    打开新建View模型向导时,勾选<继承>选项,如下图所示:

    图 190 新建继承的View模型向导
    点击与<继承>选项同行的<浏览>按钮,选择要继承的View模型,如下图所示:

    图 191 选择要继承View模型对话框
    选择要继承的View模型后,点击<确定>按钮后,回到创建View模型的向导,此时与<继承>选项同行的文本框中将会显示刚才选择要继承View模型的完整路径名,如下图所示:

    图 192新建继承的View模型向导
    点击<Finish>按钮后,会打开view组件的UIDesigner编辑器,并默认切换到UIDesigner编辑器的页面组件概要页面。
     公共方法的追加与覆盖
    将UIDesigner编辑器切换到设计页面,可以看到父View模型的控件已经被继承到当前View模型中,如下图所示:

    图 193 继承父View模型的控件
    将UIDesigner编辑器切换到脚本页面,通过左上角下拉框选择<公共方法>选项,再选择右上角下拉框,可以看到父View模型的公共方法已经被继承到当前View模型中,继承的公共方法后都有“继承”字样,如下图所示:

    图 194 继承父View模型的公共方法
    选择其中一个继承自父View模型的公共方法,默认该方法内容是灰显状态,在脚本编辑器中按下键盘上任意按键,弹出是否覆盖该方法的询问对话框,如下图所示:

    图 195 覆盖继承自父View模型的公共方法
    点击<OK>按钮后,脚本编辑器中的代码立刻出现语法着色,此时就可以编写覆盖的方法体,完成对继承自父View模型公共方法的覆盖。
    如果想要删除覆盖方法,只需简单点击脚本编辑器右上角的 ,在弹出的询问对话框中选择<OK>按钮后,覆盖方法就被删除,还原为父View模型中的继承方法。
    通过左上角下拉框选择<公共方法>选项,再选择右上角下拉框中的<新建方法>,输入方法名后,在脚本编辑器就可以对追加方法进行编辑。
     控件事件的覆盖和追加
    对于控件事件的覆盖和追加,操作方法参参照共方法的覆盖和追加。

    6.1.5.5 View常用API简介
    V4的view模型会将部分的源码翻译成RIA的代码,可以方便的完成JSP静态代码部分的转换,而动态的js脚本可以在脚本编辑器中来进行编写。在脚本编辑器中编写js代码的过程中,会使用大量的RIA代码。考虑到RIA的API组织稍显凌乱,故V4在其基础上对一些常用的API进行了封装,现通过使用场景依次对其进行介绍:
    1) view.form.setDataStore(id,store)
    解释:设置form对应的DataStore
    参数说明: id:对应Form控件的id
    store:用于初始化控件的dataStore
    场景举例: 修改人员列表中的某个人员信息时,需要把Grid当行的数据取出来并放入到对应的Form中,如下所示:

    图 196 点击Grid中的超链接

    图 197 将Grid选中行的数据放入到Form中
    要实现上述功能,可以通过如下的代码来实现:
    //获得Grid当前选中行的数据,以dataStore的格式进行封装
    var ds = view.grid.getRow("user_grid");
    //将Grid选中的数据绑定到Form上
    view.form.setDataStore("user_form",ds);
    可见,当想清空某个Form绑定的dataStore中的数据时,可采取如下方式:
    view.form.setDataStore("user_form",null);
    2) view.form.getDataStore(id)
    解释:设置form对应的DataStore
    参数说明: id:对应form控件的id
    场景举例:新增一个人员的时候,要把其Form的所有信息传递到后台,如下所示:

    图 198 Form中的相关人员信息
    当点击“保存”按钮时,要获取Form绑定的dataStore的内容,并向后台发送processor请求,代码如下:
    var ds = view.form.getDataStore("user_form");
    view.processor.saveUser(ds);
    3) view.form. setPropertyValue(id, propertyName, propertyValue)
    解释:设置form对应的DataStore的某个属性值
    参数说明: id: 对应form的id
    propertyName: 属性的名称
    propertyValue:属性值
    场景举例:当新增一个组织单元时,会为其Form中的名称字段设置一个初始值,如下所示:

    图 199 点击“新增”项为销售公司增加下级部门

    图 200 Form中“名称”项会默认添加一个值
    要修改Form中某个属性的值的代码功能如下所示:
    view.form.setPropertyValue("unit_form", "name", randomName);
    4) view.form.getPropertyValue(id,propertyName)
    解释: 获得form对应的DataStore的某个属性值
    参数说明: id:对应form的id
    propertyName:属性的名称
    返回值: 对应的属性值
    场景举例:新增一个用户的时候,需要判断Form中输入的账户是否已经存在,若存在则不允许持久化到数据库中。如下所示:

    图 201 对Form中“帐号”项进行校验
    此时需要向后台发送该属性的值校验数据库中是否已经存在,则要在“保存”按钮的事件中添加如下代码:
    var account = view.form.getPropertyValue("user_form", "account");
    view.processor.validateAccount(account);
    5) view.grid.setDataStore(id,store)
    解释: 设置Grid的绑定的dataStore的数据值
    参数: id :Grid控件的id
    store :绑定的dataStore的值
    场景举例: 在查询了所有用户后,要在用户列表中显示出来,如下所示:

    图 202 对Form中“帐号”项进行校验
    要实现该功能,在查询processor的成功回调中添加如下代码即可:
    var ds = dc.getDataStore("result");
    view.grid.setDataStore("user_grid",ds);
    可见,如果想清空Grid中的内容,可通过如下方式实现:
    view.grid.setDataStore("user_grid",null);
    6) view.grid.getDataStore(id)
    解释: 获得Grid控件绑定的DataStore
    参数: id:Grid控件的id
    返回值: Grid控件绑定的DataStore
    场景举例:在弹出的Dialog中,要将主页面的Grid中的内容原封不动的显示出来则需要获得主页面的Grid绑定的dataStore,代码如下所示:
    var gridDs = view.grid.getDataStore("user_grid");
    然后将gridDs作为参数传递给Dialog即可。
    7) view.grid.insertRows(id, store, index)
    解释: 向Grid中插入行(可插入多行数据)(单选和多选Grid均适用)
    参数: id: Grid控件对应id
    store : 插入行数据对应的store
    index: 插入的位置(从0开始),当不传该参数时,默认插入到表格末尾
    场景举例: 当新增了一个用户后,会将该用户自动的插入到用户列表的最后一行,如下所示:

    图 203 新增一个用户

    图 204 新增的用户自动插入到Grid的最后一行
    为实现该功能,在新增用户processor对应的成功回调中,添加如下代码即可:
    var ds = dc.getDataStore('result');
    view.grid.insertRows("user_grid",ds);
    8) view.grid.deleteRow(id,index)
    解释:删除Grid的选中行(适用于单选Grid)
    参数:id: Grid控件的id
    index: 待删除的行的下标(从0开始),当不传入此参数时,默认选择删除选中的行.
    场景举例:当删除Grid列表中的一个用户的时候,会首先选中它所在的行,然后点击删除,删除成功后,要在Grid中将这行数据也删除,如下所示:

    图 205 删除Grid中的选中行

    图 206 删除成功后的效果
    要实现该功能,只需在删除人员的processor的成功回调中加入如下代码即可:
    view.grid.deleteRow("user_grid");
    9) view.grid.deleteRows(id,indexs)
    解释:删除Grid中选中的多行(适用于多选Grid)
    参数:id: Grid控件对应的id
    indexs: 待删除的Grid的行的下标构成的数组,不传递此参数时默认删除所有选中的行
    场景举例:当为某个管理角色删除多个对应的人员时,需要用到多选的Grid,如下所示:

    图 207 为管理角色删除多个对应人员

    图 208 删除成功后的效果图
    要实现这个功能,需要在删除人员对应的processor的成功回调中执行下面的语句:
    view.grid.deleteRows("user_grid");
    这样就会删除所有选中的行的数据。
    如果想删除指定的某些行,可以这样实现:
    //删除第1行、第3行和第4行
    view.grid.deleteRows("user_grid",[0,2,3]);
    10) view.grid.updateRow(id,store,index)
    解释:更新Grid中的某一行
    参数:id : Grid控件对应的id
    store: 用来更新行的数据(以dataStore的方式封装)
    index: 待更新的行的下标(当不传时,默认更新选中的第一行)
    场景举例: 当需要修改某个用户的信息时,可以通过如下方式:

    图 209 点击超链接更新人员信息

    图 210 修改性别信息


    图 211 修改后的数据信息
    要实现这个功能,在修改用户信息的成功回调中,添加如下代码:
    var ds = dc.getDataStore('result');
    view.grid.updateRow('user_grid',ds);
    11) view.grid.getRow(id)
    解释: 获得Grid选中行的数据,并封装成dataStore的格式(适用于单选Grid)
    参数: id :Grid控件对应的id
    index: 待获取的行的下标(不传的时候默认获取当前选中行)
    返回值:Grid选中行的数据(dataStore格式)
    场景举例:要修改某个用户的信息的时候,点击超链接会将该行对应的数据设置到一个Form控件上,如下所示:

    图 212 点击超链接弹出修改页面

    图 213 修改页面
    为了实现这个功能,只需要在点击超链接的事件里添加如下代码:
    var ds = view.grid.getRow("user_grid");
    得到这个ds将其设置为Form绑定的dataStore即可(调用view.form.setDataStore()方法)。
    12) view.grid.getRows(id,indexs)
    解释: 获得Grid选中行的数据,并封装成dataStore的格式(适用于多选Grid)
    参数: id :Grid控件对应的id
    indexs : 待获取的行的下标构成的数组
    返回值:Grid选中行的数据(dataStore格式)
    场景举例:在多选的Grid中,如果想获取第1行、第3行和第4行对应的值,可通过如下方法:
    view.grid.getRows("user_grid",[0,2,3]);
    13) view.grid.getPropertyValue(id, propertyName, index)
    解释: 获得Grid中某指定行的某个属性值
    参数: id: Grid控件对应的id
    prpertyName :属性名
      index : 指定行的下标(不传时,默认为选中的行)
    返回值: 属性的值
    场景举例: 当要删除一个用户的时候,会获得该用户对应的id并传递到后台进行删除,其操作流程如下所示:

    图 214 选中一个用户并删除

    图 215 删除成功的页面
    在“删除”事件中,需要获得当前选中行的id属性值,并向后台发送processor请求,代码如下:
    var userId = view.grid.getPropertyValue("user_grid", "id");
    view.processor.deleteUserById(userId);
    14) view.grid.setPropertyValue(id, propertyName, propertyValue, index)
    解释: 设定Grid某行中某个属性的值
    参数: id: Grid控件对应的id
    propertyName: 属性名称
    propertyValue: 属性值
    index: 要设置属性值的行的索引,如不传的话默认修改当前选中行
    场景举例:当需要将Grid选中行的“帐号”属性值改为”wang-fan”时,可通过添加下面的代码实现:
    view.grid.setPropertyValue("user_grid", "account", "wang-fan");
    15) view.tree.setDataStore(id,store)
    解释: 为Tree控件绑定数据(注意:此方法只适用于全加载的Tree)
    参数: id: Tree控件的id
    store: Tree所需绑定的dataStore,需要符合树形结构
    场景举例:对于组织单元类型这样的一棵树,它是全加载的,在page-load发送完请求取得所有的数据后,在成功回调中只需要调用如下方法,树中的所有数据均会被绑定上:
    var ds = dc.getDataStore('result');
    view.tree.setDataStore("unitType_tree",ds);
    数据被绑定后,其显示效果如下所示:

    图 216 组织类型树的页面展示效果
    16) view.tree.deleteNode(id,node)
    解释:删除Tree控件中的node节点
    参数:id: Tree控件的id
    node: 待删除的树中的节点
    场景举例: 在组织机构树中,可以删除某个节点,如下所示:

    图 217 删除“国际事业部9”这个树节点

    图 218 删除成功后的效果
    在删除节点的成功回调中,需要在Tree控件中将该结点删除,调用如下方法即可:
    //删除右键选中的节点node
    view.tree.deleteNode("unit_tree",node);
    17) view.tree.deleteNodes(id,nodes)
    解释: 删除Tree中的多个节点
    参数: id: Tree控件的id
    nodes: 待删除的节点构成的数组
    场景举例: 对于一个复选树控件,如果选中了多个节点后要将这些节点删除,即可通过如下代码实现:
    //得到所有复选框中选中的节点
    var selectedNodes = unieap.byId("unit_tree").getSelectedNodes();
    //删除这些选中的节点
    view.tree.deleteNodes("unit_tree",selectedNodes);
    18) view.tree.updateNode(id,node,store)
    解释: 更新Tree中的某个节点
    参数: id: Tree控件的id
    node: 待更新的节点
    store: 用于更新节点的dataStore
    场景举例:更新组织机构树中的某个节点,如下所示:

    图 219 修改前的组织单元信息

    图 220 修改后的组织单元信息
    点击保存按钮后,选中节点所对应的数据也会发生变化,如下所示:

    图 221 修改后节点的数据值发生了变化
    要实现修改节点的功能,只需要在processor对应的成功回调中添加如下代码即可:
    //获得修改后的数据
    var ds = dc.getDataStore("result");
    //获得当前Tree中选中节点
    var node = unieap.byId("unit_tree").getCurrentNode();
    //修改Tree中对应的节点
    view.tree.updateNode("unit_tree", node, ds);
    19) view.tree.getPropertyValue(id,node,propertyName)
    解释: 获得Tree中某一节点对应的属性值
    参数: id: Tree控件的id
    node: 待获取属性值的节点
    propertyName: 待获取的属性值
    返回值: 属性值
    场景举例: 当要删除某个组织单元的时候,需要获取待删除节点的id属性传到后台,其效果如下:

    图 222 右键删除树中某一节点

    图 223 删除成功后的效果
    在点击“删除”菜单项的事件中,需要获取当前选中节点的id属性,代码如下:
    //获得待删除节点的id属性
    var nodeId = view.tree.getPropertyValue("unit_tree",currentNode,"id");
    view.processor.deleteUnitById(nodeId);
    20) view.tree.setPropertyValue(id, node, propertyName, propertyValue)
    解释: 设置Tree中某个节点的某个属性的值
    参数: id: Tree控件的id
    node: 待修改属性的节点
    propertyName: 待修改的属性名
    propertyValue: 待修改的属性值
    场景举例: 当修改了某个组织单元节点的属性值后,要在树中对其进行更新,如仅修改了一个组织单元节点的name属性值,则可通过如下代码同步更新树中相应的显示内容:
    view.tree.setPropertyValue("unit_tree", currentNode, "name", "事业部");
    21) view.tree.getAllNodes(id,isContainRoot,node)
    解释:获得node下的所有已经渲染出的所有子孙后代节点(即获得以node为根的子树的所有节点)
    参数:id: Tree控件的id
    isContainRoot: 返回的结果集中是否包含当前node节点,true代表包含,false代表不包含
    node: 当前节点
    返回值:所有node子孙节点构成的数组
    场景举例:当在程序要获得以node为根的所有子孙节点时,可调用如下方法:
    //获得当前节点的全部已渲染出的子孙节点
    var nodes = view.tree.getAllNodes("menuTree",false,node);
    22) view.tree.addChildren(id,node,store,configMap)
    解释: 为node节点添加相应的子节点(适用于懒加载的树)
    参数: id: Tree控件的id
    node: 要添加子节点的节点
    store: 待添加的子节点
    configMap: 配置参数Map,如不传此参数默认使用树中配置的参数。
    这里需要对configMap参数进行详细的解释,此参数适用于异构懒加载树的场景。在配置树的相关属性时,要制定Tree的相关属性对应的dataStore的属性名,如下所示:

    图 224 Tree控件的id、label、parent属性的配置
    但如果树中不同层次的节点来自于不同的dataStore的时候,无法为其设置一个统一的名字,此时需要在程序中动态切换这几个参数的配置,用来指定这几个关键属性的名称,如下所示:
    configMap = {
    id : 'id',
    label : 'title',
    parent : 'parentId'
    });
    此时即代表树的id为dataStore中id属性,label为dataStore中的title属性,parent为dataStore中的parentId属性。
    需要注意的是,只有在异构切换树中节点的dataStore时才需要使用该参数,否则在Tree的属性视图中进行相应的配置即可。
    场景举例:异构懒加载树
    有的时候,树的不同层次的节点可能来自于不同的dataStore,如下图所示:

    图 225 异构懒加载树
    这是一棵懒加载的树,其中“迭代”为虚根,第一层节点绑定的是sprint dataStore,而第二层节点绑定的是backlog dataStore。在sprint的dataStore中,几个关键属性的名称为id、title、parentId,而在backlog的dataStore中,几个关键属性的名称为id,name和sprintId。在Tree控件中配置的相应属性为id,label,parentId,可见,如何将不同的dataStore的相关属性统一是能否实现异构加载树功能的关键,此时方法中的参数configMap就起到了至关重要的作用。
    在查询sprint节点的成功回调中,编写如下代码实现加载出第一层节点的功能:
    //得到查询返回的dataStore
    var ds = dc.getDataStore('result');
    //得到当前Tree的虚根节点
    var root = unieap.byId("isomerismTree").getRootNode();
    //为Tree添加第一层节点
    view.tree.addChildren("isomerismTree", root, ds, {
    id : 'id',
    label : 'title',
    parent: 'parentId'
    });
    当展开第一层的某个节点的时候,会去加载该sprint节点下的所有backlog节点,在该查询方法的成功回调中,需要编写如下代码:
    //得到查询返回的dataStore
    var ds = dc.getDataStore('result');
    //为当前展开节点添加第二层节点
    view.tree.addChildren("isomerismTree", currExpandNode, ds, {
    id : 'id',
    label : 'name',
    parent: 'sprintId'
    });
    这样即可成功的构造出一棵异构的懒加载树。
    6.1.5.6 工具类JS开发
    【注意】该工具类js只能在view模型对应的js中调用。
    在单帧环境下开发工具类js需要注意以下几点:
     如果工具类js的function参数为某一控件的id,需要在调用处通过getRealId方法得到真实的id再传入,如下所示:
    //demoTool.js
    function demoFunction(id){
    alert(id);
    }
    //demo.view
    dojo.require("unieap.view.View");

    unieap.define("demo", function () {

    dojo.declare("_demoDC.demo.View", unieap.view.View, {
    ...... ,
    page_load: function () {
    demoFunction(getRealId(“grid1”));
    }
    });
    var view = new _demoDC.demo.View();
    view.init();
    return view;
    })
     该工具类js中,避免定义变量,只能定义function。
    6.1.5.7 引用第三方JS库
    我们在引用第三方js库的时候,常常会用到其实现的DOMContentLoaded事件,在window.onload之前加入许多初始化的动作,来增强用户体验,比如在Jquery中有如下代码:
    $(document).ready(function() {
    // put all your init code in here.
    });
    在单帧环境下,需要使用dojo对于DOMContentLoaded事件的实现,如下所示:
    dojo.addOnLoad(function() {
    // put all your init code in here.
    });
    请将带有选择器的代码写在“unieap.define”的闭包中,比如通过view模型脚本编辑器编写的代码最后就会生成到一个“unieap.define”的闭包中;并且如果用到id的选择器,需要调用getRealId方法得到真实的id,如下所示:
    unieap.define("demo", function () {
    function demoFunction() {
    var demoObj = $(“#” + getRealId(“demoElement”));
    }
    demoFunction();
    })

    6.1.6 View组件
    6.1.6.1 新建View组件
    选择当前DC工程下的“metamodel”>“view”文件夹,在右键菜单中点击“New”>“View组件”菜单项,如下图所示:

    图 226 新建View组件菜单
    点击菜单项后,会打开新建view组件的向导,如下图所示:

    图 227 新建View组件向导
    在向导中输入View组件的相关信息后,点击<Finish>按钮,完成新建view组件。
    完成新建后,会打开view组件的UIDesigner编辑器,并默认切换到UIDesigner编辑器的页面组件概要页面如下图所示:

    图 228 View组件编辑器
    【提示】UIDesigner编辑器中其它页面的使用将在后面的章节中介绍。
    6.1.6.2 View组件编辑器
    作者输入域中可以编辑View组件的作者信息。
    【技巧】作者输入域的默认值为Eclipse启动参数配置中所设置的用户信息。
    版本号输入域中可以编辑View组件的版本号信息。
    描述输入域中可以编辑View组件的描述信息。
    标题输入域中可以填写View组件的标题属性,即页面的标题。
    点击入口信息链接可以切换到UIDesigner编辑器的入口信息页面。
    点击过程调用链接可以切换到UIDesigner编辑器的过程调用页面。
    点击设计链接可以切换到UIDesigner编辑器的设计页面。
    点击脚本链接可以切换到UIDesigner编辑器的脚本页面。
    点击源码链接可以切换到UIDesigner编辑器的源码页面。
    点击数据集链接可以打开数据集视图。
    完成view组件创建后,会自动生成组件相关的代码文件,包括2个Java文件,2个Javascript文件和一个Jsp文件,点击对应的代码链接将用新的编辑器打开这些代码文件,如下图所示:

    图 229 打开View组件相关代码文件
    【提示】 Java文件的包路径为:首选项中配置的Java类默认包名前缀 + 当DC所属SC工程名 + 当前DC工程名 + “.action”;Javascript文件和Jsp文件的路径为:当前DC工程/content/view/generated。

     删除View组件
    选择要删除的View模型文件,在右键菜单中点击“Delete”菜单项,如下图所示:

    图 230 删除View组件文件
    点击菜单项后,会弹出确认删除对话框,如下图所示:

    图 231 确认删除对话框

    点击< OK >后,该View模型文件被删除并且弹出是否自动删除创建View组件自动生成的Javascript文件和Jsp文件的确认对话框,如下图所示:

    图 232 删除View组件文件对应源码文件确认对话框

    点击< Yes >后,创建该View组件文件自动生成的Javascript文件和Jsp文件被删除。
    【注意】删除View组件文件不会删除创建该View组件文件自动生成的Java文件,需要用户手动删除。
    6.1.6.3 与View模型的差异
    从概念上说,View模型代表可独立发布访问的页面,View组件代表页面上可复用的一块可视化区域,不能独立发布访问。
    从生成代码上说,View模型生成完整JSP页面应有的结构,包括<DOCTYPE>、<html>、<head>、<body>等,view组件只生成可视化元素,最后以JSP标准动作<jsp:include>引入到View模型生成的JSP页面中。
    6.1.6.4 View组件通信
    6.1.6.5 使用页面组件闭包名
    如果使用Grid的列格式化,该列的formatter方法中指定html代码中需要使用该页面组件的公共方法,就需要首先获取页面组件对应的闭包名,如下所示:
    return "<a href="#" onclick="javascript:” + getViewcContext() + ”.componentIdOnClick()">" + inValue + "</a>";

    6.2 使用可视化UI设计器
    6.2.1 UIDesigner简介
    UIDesigner是UniEAP V4 WorkShop为View模型和View组件提供的可视化编辑工具。UIDesigner提供了所有UniEAP RIA的控件,常用HTML控件以及控件模板。无需编写复杂的HTML标签与JS代码,拖拽鼠标即可完成RIA风格页面开发。UIDesigner还具备用户自行扩展控件的能力,可以无限增加可视化设计的控件。针对RIA页面JS代码编写复杂的问题,UIDesigner脚本编辑器提供了强大的代码提示、代码高亮、对象自动识别等特性,更加入了贴心的快捷键支持,大幅提高了JS代码的编写效率。
    6.2.2 View如何运作?
    本节为您介绍View模型与服务器进行交互,完成业务逻辑的流程。首先我们来了解一下View模型中包含了哪些信息的定义:
    1 View模型基本信息。
    2 引用外部资源信息。
    3 页面布局、控件定义。
    4 页面、控件响应事件的JS脚本。
    5 全局变量、方法JS脚本。
    6 Processor定义。
    可见,View模型包含了Web应用程序页面所有的信息,以及Web应用程序页面与服务端交互所需的必要信息。在实际运行时,View模型会被转换为运行在浏览器端的HTML页面,JS脚本以及运行在服务端的Java类。
    HTML页面运行在浏览器中,为完成某些业务逻辑,必须与服务器交互。在UniEAP V4中,所有的业务逻辑都实现在BO模型中,也就是说,HTML页面要完成业务逻辑,必须调用BO。
    从实现上看,HTML页面在浏览器端运行,可以调用的只有JS脚本,而BO是运行在服务端的Java类。显然,实现二者的交互是需要一个媒介的,这个媒介要负责将浏览器端JS调用转发到服务端,并将服务端的返回信息传递给浏览器端的JS。
    Processor就是这个媒介。Processor实现了浏览器端JS透明调用在服务端的BO。在View模型转换为实际可执行程序代码时,Processor被转换为两部分:浏览器端一部分,服务器端一部分。在浏览器端,Processor是JS代码,供页面中其他JS脚本调用;在服务器端,Processor是Struts2 Action,用于和BO进行交互。Processor 的 JS代码通过发送Ajax请求和服务器端的Processor交互。这种Ajax交互使用了统一的数据格式——DataCenter,每一次Ajax请求浏览器端发送给服务器的都是DataCenter对象的JSON串,返回的也是DataCenter的JSON串。
    下图是一个完整的View完成与服务器交互的示例:


    图 233 View完成与服务器交互示意图

    如图所示,在浏览器端,用户通过操作页面控件,触发一个控件的事件,响应控件事件的JS脚本会调用JS脚本中的Processor(图中标号1),Processor会向服务器发起一个Ajax请求(图中标号2,数据格式是DataCenter),服务器端的Processor接收到请求,调用相应的BO 图中标号3),BO中执行业务逻辑,调用DAO完成数据的持久化(图中标号4),DAO则会与数据库交互(图中标号5),数据库将持久化的结果返回给DAO(图中标号6),DAO将结果返回给BO(图中标号7),BO再将数据返回给服务器端Action(图中标号8),服务器端Action将Ajax请求结果返回给浏览器端(图中标号9,数据格式是DataCenter),浏览器端JS脚本Processor根据返回结果更新页面控件(图中标号10),将交互结果反馈给用户。
    6.2.3 进行UI设计
    6.2.3.1 控件添加、选择、布局
    设计页面提供以图形化的方式定义Web页面,通过设计页面可以对控件进行如下操作:
     添加和删除控件
     对控件的属性进行修改
     对控件进行布局,改变控件的位置
    设计页面如下图所示:

    图 234 设计页面
    设计页面主要分为以下两个部分,左侧为控件工具箱,右侧的空白区域为设计区,如下图所示:

    图 235 设计页面结构图
    “控件工具箱”区域主要提供选择控件的功能,该区域中提供的控件有两类,分别为“基本控件”和“容器控件”,其中容器控件能够容纳其他的控件,而基本控件不能。点击“控件工具箱”中的“select”选项,就可以对“控件工具箱”中的控件进行选择,例如选择一个“TitlePane”控件,并将“TitlePane”控件添加到“设计区”中。操作步骤如下,首先鼠标左键点击“select”区域,然后点击“TitlePane”区域,此时鼠标形状多了一个加号,将鼠标移动到“设计区”中,点击鼠标左键,此时设计区中显示出了“TitlePane”控件。如下图所示:

    图 236 TitlePane控件
    “设计区”区域用来显示控件,通过“设计区”可以选择控件来对相应控件进行各种操作。在设计区中选择显示的“TitlePane”控件,“TitlePane”控件的图形显示如下图所示:

    图 237 选中后的TitlePane控件
    “TitlePane”控件被选中后,控件的上下左右及四个拐角出多出了黑点图标,左上角多出了移动图标及右上角多出了三角箭头图标。通过上述图标可以对控件进行如下操作:
     黑点图标
    将鼠标移动到黑点图标上,此时鼠标的图形形状变为更改图形大小的形状,此时按住鼠标左键并拖动,控件就会相应改变自身大小。
     移动图标
    将鼠标移动到移动图标上,此时鼠标的图形形状变为更改图形位置的形状,此时按住鼠标左键并拖动,控件就会相应改变自身位置。
     三角箭头图标
    鼠标左键点击三角箭头图标,此时控件会弹出快捷菜单,通过快捷菜单对控件的属性进行更改,如下图所示:

    图 238 控件弹出的快捷菜单

    6.2.3.2 使用属性视图
    属性视图用于显示设计页面中被选择控件的各种属性,并且提供更改属性的功能。如果属性视图没有出现在eclipse中,可以通过以下方式显示出属性视图。在eclipse中点击“窗口”>“显示视图”>“其他”菜单项,弹出对话框如下图所示:

    图 239 显示视图对话框
    在“常规”分类下选择“特性”选项就可以显示出属性视图。在设计页面选中“TitlePane”控件,属性视图就会显示控件的相应属性,如下图所示:

    图 240 属性视图
    以“TitlePane”控件为例,属性视图可以显示该控件的标识(id)、高度(height)、宽度(width)、标题(title)等属性,并且可以在属性视图中对控件的属性进行修改来更改控件。例如更改“TitlePane”控件的标题属性,首先在属性视图中点击值为“TitlePane”的区域,如下图所示:

    图 241 编辑属性视图
    将“TitlePane”控件的标题由“TitlePane”更改为“TitlePane控件”,然后鼠标左键点击设计页面,此时“TitlePane”控件的标题发生了变化,如下图所示:

    图 242 更改标题后的TitlePane控件
    通过上述方式可以对控件的其它属性进行修改。

    6.2.3.3 使用控件快捷菜单
    除了通过属性视图可以更改控件的属性外,我们还可以通过快捷菜单来对控件的属性进行修改,相比于属性视图,该方式简单、易用。以“TitlePane”控件为例,鼠标左键选中该控件,点击控件右上角的三角箭头图标,此时控件会弹出相应快捷菜单,如下图所示:

    图 243 TitlePane控件的快捷菜单
    通过弹出的快捷菜单可以对控件的属性进行修改,例如更改控件的标题,步骤如下:首先在弹出的快捷菜单中鼠标左键点击“标题文本框”,在文本框中写入控件的标题,如下图所示:

    图 244 通过快捷菜单更改控件属性
    在快捷菜单中更改完控件属性后,鼠标左键点击相应控件,此时快捷菜单关闭,控件的标题由“TitlePane控件”更改为“TitlePane”,如下图所示:

    图 245 更改属性后的TitlePane控件
    通过上述方式可以对控件的其它属性进行修改。

    6.2.3.4 使用大纲视图辅助选择控件
    当设计页面中含有较多控件,特别是容器控件中嵌入其他控件的情况下,如果想选中某个控件会很不方便, 而大纲视图能够展现出设计页面中众多控件层次明确、结构清晰的图形显示,进而通过大纲视图可以很方便的选择控件。如果大纲视图没有显示在eclipse上,可以通过如下方式来显示出大纲视图,首先点击“窗口”>“显示视图”>“其他”菜单项,在弹出的“显示视图”对话框中选择“大纲”选项即可,如下图所示:

    图 246 选择大纲视图
    鼠标左键点击设计页面,此时大纲视图便可以显示出设计页面上所有控件,如下图所示:

    图 247 大纲视图展示控件
    通过大纲视图可以很方便的选择控件,以上图为例,如果想选中“grid1”控件下的“cell4”控件,由于设计页面的长度显示,“cell4”控件并没有在设计页面中显示出来,无法在设计页面中进行选择,但是通过大纲视图仍然可以选择“cell4”控件,通过鼠标左键点击“cell4”选项便可以选中“cell4”控件,此时设计页面的“cell4”控件处于选中状态,属性视图会显示出“cell4”的相应属性,如下图所示:

    图 248 cell控件的属性
    通过大纲视图可以选择设计页面中的任意控件。
    6.2.3.5 使用大纲视图进行控件拖拽
    当设计视图布局复杂,拖拽控件困难时,可以通过大纲视图直接对控件进行拖拽,其中拖拽操作包括:源控件拖拽为目标控件的上节点,源控件拖拽为目标控件的下节点和源控件拖拽为目标控件的子节点,效果如下图所示:

    图 249源控件拖拽为目标控件的上节点

    图 250源控件拖拽为目标控件的下节点

    图 251源控件拖拽为目标控件的子节点
    6.2.3.6 使用大纲视图实现局部显示
    当设计视图的控件过多且部分控件发生被遮挡的情况,或者需要调整这些控件的布局等属性时,可以使用局部显示功能。

    如上图adaptivePane中的QueryGrid部分被遮挡,这时可以选择adaptivePane,点击 来局部显示其内部的布局,如下图所示:

    图 252 局部显示效果图
    当希望继续进入容器内部时,可以继续右键点击控件,选择“进入”,如下图所示:
    图 253 进入容器内部

    图 254 进入容器内部效果图
    当需要退出局部显示时,只需再次点击 ,同时保存局部显示时的修改数据。
    6.2.3.7 使用大纲视图进行控件拷贝粘贴
    当需要进行控件的拷贝粘贴操作时,可通过大纲视图来实现;大纲视图的拷贝粘贴支持多选以及跨view之间的操作。
    【注意】模式控件不支持拷贝粘贴,所复制的控件中如含有模式控件将自动忽略。
    在大纲视图选中需要拷贝的控件,然后使用快捷键Ctrl+C,如下图所示:

    图 255 选中并使用快捷键Ctrl+C拷贝
    在粘贴的大纲视图上使用快捷键Ctrl+V进行粘贴,自动弹出“命名冲突”对话框,可进行控件id的修改或者使用默认生成的id,如下图所示:

    图 256使用快捷键Ctrl+V粘贴

    图 257粘贴后的效果图
    6.2.3.8 使用数据集
    数据集的概念,数据集即数据的来源,它的作用是为web页面的各种控件提供数据,控件显示出的内容来源于数据集,如数据表格Grid控件,表单Form控件等的数据都来自于数据集。定义数据集可按如下方式:首先需要打开“数据集”视图,如果eclipse没有显示出数据集视图,可以点击“窗口”>“显示视图”>“其他”,此时弹出“显示视图”对话框,如下图所示:

    图 258 显示数据集视图
    点击“数据集”选项,eclipse显示出“数据集”视图,如下图所示:

    图 259 数据集视图
    如果想增加一个名称为“entityDataStore”的数据集,点击上图所示的加号图标,弹出“新建DataStore”的对话框,如下图所示:

    图 260 新建数据集对话框
    新建数据集对话框包含如下内容:
     “名称”文本框
    表示数据集的名称。
     “类型”下拉列表
    类型下拉列表中包含两条数据,分别为实体对象“yEntit”和数据传输对象“DTO”,当选择“Entity”时,下面的对象列表中会显示出所有类型为“Entity”的实体对象,当选择“DTO”时,下面的对象列表中会显示出所有类型为“DTO”的数据传输对象,
     过滤文本框
    当对象列表中显示的数据较多时,可以通过文本框来过滤出自己想要的对象数据,在文本框中输入过滤文本,对象列表会列出所有名称开始部分与过滤文本相同的对象数据。
     对象列表
    用于显示对象数据,当“类型”下拉列表中为“Entity”时,对象列表显示实体对象,当“类型”下拉列表中为“DTO”时,对象列表显示数据传输对象。
     列信息表格
    显示当前数据集所包含的列
    定义一个新的数据集步骤如下:首先在“名称”文本框中填写数据集的名称“entityDataStore”,如果数据集的列信息来源于ENTITY对象,那么“类型”下拉列表中需要选择“Entity”,如果数据集的列信息来源于DTO对象,那么“类型”下拉列表中需要选择“DTO”,如果数据集的列信息来源于pojo对象,那么“类型”下拉列表中需要选择“pojo”。以数据集的列信息来源于Entity对象为例,双击需要选择的对象数据,如下图所示:

    图 261 导入Entity文件
    双击相应的Entity文件后,数据集的列表格会显示相应的列信息,其中的列信息来源于Entity文件。
    点击<下一步>按钮,如下图所示。

    图 262 操作符设置
    对操作符进行设置。单击操作符显示如下图所示:

    图 263 操作符设置
    双击一条数据,添加到排序设置里。可以对数据进行排序。点击 , 来来调整排序的优先顺序。点击 来删除排序的字段。点击排序对应的字段来选择排序方法。

    图 264 设置查询信息
    点击<完成>按钮,便完成了新建数据集的操作,此时数据集视图会显示刚刚新建的数据集,如下图所示:

    图 265 数据集在视图中的显示
    数据集视图还提供了对数据集删除、修改和刷新功能。
     删除数据集
    在数据集视图中选中相应的数据集,点击右上角的差号图标,便可将相应数据集删除。
     修改数据集
    在数据集视图中选中相应的数据集,点击右上角的文本图标,此时弹出“编辑DataStore”对话框,如下图所示:

    图 266 编辑数据集
    在“编辑DataStore”对话框中可以对现有数据集进行编辑操作,包括更改数据集的名称,数据集的列信息和记录数。
     刷新数据集
    数据集的列信息来源于Entity、DTO或pojo文件,当相应的文件发生更改时,点击数据集视图右上角的刷新图标,此时数据集的列信息会与发生改变的文件进行同步,更新相应的列信息。

    6.2.3.9 绑定控件事件
    事件的概念,事件可以理解为发生了什么事情,定义事件,就是控件触发了该事件时能够执行的操作,即定义一个响应该事件的方法。以“TitlePane”控件为例,如果想在打开“TitlePane”控件时弹出一个“您打开了一个TitlePane控件”提示框,便可以按照如下方式进行定义:首先在设计页面选中“TitlePane”控件,然后打开属性视图,点击属性视图中的“事件”选项,便可以看到“TitlePane”控件的所有事件了,如下图所示:

    图 267 TitlePane控件的事件
    如果想在显示“TitlePane”控件时弹出提示框,只须增加事件名称为“onShow”的方法即可,鼠标左键点击相应的“方法”列,如下图所示:

    图 268 增加事件方法
    鼠标左键点击上图所示的加号图标,此时设计页面自动跳转到脚本页面,如下图所示:

    图 269 定义事件方法
    如上图所示,如果想在显示“TitlePane”控件时弹出提示框,便可在“事件响应方法内容”区域填写“alert(‘您打开了一个TitlePane控件’)”,如下图所示:

    图 270 定义事件方法内容
    到此为止,便定义完成了一个显示“TitlePane”控件的事件方法,切换回设计页面,此时属性视图的“事件”标签页会显示刚刚定义的方法,如下图所示:

    图 271 定义完成的事件方法
    点击上图所示的加号图标,可以对已经定义的事件方法内容进行修改,点击上图所示的减号图标,可以将已经定义的事件方法删除。
    6.2.3.10 设置页面init,load,unload事件
    打开脚本编辑器页,在左侧下拉条中选择“page”,此时点开右侧下拉条会出现三个事件:init,load,unload。如下图所示:

    图 272 定义init,load,unload方法
    其中init事件将在页面渲染之前进行,用于对页面进行初始化。页面渲染结束后将执行load事件,用于加载用户的一些操作。而unload事件则在页面关闭后或刷新页面时进行,用来销毁页面中所有UI控件。
    6.2.3.11 预览页面效果
    使用UI设计器完成控件的开发后,设计页面并不能精确反映出控件在web页面中的效果,针对这一情况UniEAP V4提供了页面的“预览”功能,用于在view文件未部署到web服务器时预览页面的实际效果。
    在完成控件的绘制后,设计页面效果如下图所示:

    图 273 控件在设计页面的显示效果
    <预览>按钮位置如下图所示:

    图 274 预览功能
    鼠标左键点击设计页面的某一区域,此时eclipse工具栏上的<预览>按钮处于亮显状态,点击<预览>按钮,控件在浏览器中的显示效果如下图所示:

    图 275 控件在浏览器中的显示效果
    通过预览功能可以直接查看定义好的控件在浏览器中的显示效果,而不必将开发组件运行起来后查看控件的显示效果。
    【警告】由于eclipse的原因,在使用预览功能前请先配置首选项的web浏览器部分,详情请参阅2.2.3节。

    6.2.3.12 设置资源引用
    为了在view模型中能够引用css、js、jsp文件,UniEAP V4提供了便捷的“资源引用”工具,打开按钮如下图所示:

    图 276 资源引用功能
    单击<资源引用>按钮后弹出对话框,该对话框中会显示当前view文件所引用的js、jsp和css文件,并且可对其进行增加和删除。如下图所示:

    图 277 资源引用功能
    该对话框左边部分列出了当前view文件所引用的全部外部资源以“文件名-存放地址”的格式显示。该对话框支持对所引用外部资源的增加、删除以及对该列表的上移和下移,如右侧按钮所示。点击<增加>按钮后将弹出对话框,如下图所示:

    图 278 资源引用功能
    该对话框将显示当前工程中存放的所有css、jsp或js文件,并支持过滤功能。选择文件后点击<确定>键则将所选定文件添加进引用列表中。如需要对引用资源的列表进行删除操作,则只需选择指定文件后点击<删除>按钮即可。
    6.2.3.13 基本控件的使用
    本节为您介绍UIDesigner提供的基本控件中各个控件的使用方法。
    向UIDesigner绘图区中添加控件的方法是:在View模型文件的“设计”页面,从左侧“Palette”中单击选择控件,在右侧设计区域放置控件的位置单击鼠标左键。请参看下图:

    图 279向View设计视图中添加控件(以Button控件为例)
    1. 按钮(Button)
    Button控件和普通HTML中的button标签类似,可以像使用普通按钮一样来使用。支持数据绑定,可以绑定数据源中的值作为按钮的标签。上图即是以Button控件为例显示了如何定义一个基本控件。您可以通过点击右侧大纲视图中对应的控件后,点击下方的“特性”,显示出Button控件的相关属性信息并对其进行修改,这里我们修改了该控件的“label”和“width”属性,如下图所示:

    图 280 修改Button控件的相关属性
    此外,我们提供了一种更加简便的修改控件属性的方法——快捷属性菜单。在设计区中选中该Button控件,点击上方出现的 ,会弹出如下图所示的快捷属性菜单,通过该快捷属性菜单可以修改该控件的一些常用信息(如ID、名称等),还可以编辑相关的事件信息,如下图所示:


    图 281 Button控件的属性快捷菜单
    Button控件所对应的常用属性及其描述如下表所示:
    属性名 描述
    accessKey
    设置或获取对象的快捷键。
    height
    设置控件的高度,支持数字或者百分比。
    iconClass
    通过改变css样式来设置按钮上的图标。
    label
    按钮上显示的文本值。
    width
    设置控件的宽度,支持数字或者百分比。
    表 1 Button控件的常用属性及其描述
    Button控件所对应的常用事件及其描述如下表所示:

    事件名 描述
    onClick
    按钮的点击事件。
    表 2 Button控件的常用事件及其描述
    2. 复选按钮(CheckBox)
    CheckBox控件支持数据绑定,下图中显示了CheckBox控件设计区中的位置及样式:

    图 282 CheckBox控件
    您可通过快捷属性菜单或属性视图定义CheckBox控件的相关属性和事件,双击可编辑CheckBox显示的内容信息。例如用快捷属性菜单来修改CheckBox控件的选中状态以及状态值的设置,如下图所示:

    图 283 CheckBox快捷属性菜单
    3. 复选按钮组(CheckBoxGroup)
    CheckBoxGroup控件具有以下的功能:
    1) 依靠unieap.ds.DataStore类型的数据源构造一个复选按钮组。
    2) 复选按钮组本身作为一个FormWidget支持数据绑定,可通过getBinding()方法取得绑定对象。
    3) 用户可通过设置cols值来控制按钮组的布局。
    4) 支持对组内按钮状态变化的监听。
    5) 支持组内按钮反选。
    6) 支持组内按钮的获取。
    下图中显示了CheckBoxGroup控件在设计区中的位置及样式:

    图 284 CheckBoxGroup控件
    CheckBoxGroup控件的dataProvider属性可以用来设置数据源的相关信息。
    您可通过快捷属性菜单或属性视图定义CheckBoxGroup控件的相关属性和事件,双击可编辑CheckBoxGroup控件显示的内容信息。
    4. 普通下拉框(ComboBox)
    ComboBox控件具有以下的功能:
    1) 支持的数据源包括unieap.ds.DataStore和html的option节点。
    2) 输入框支持模糊匹配,支持拼音查询。
    3) 支持根据指定数据列排序。
    4) 支持ComboBox组件间的级联。
    5) 支持多种展现风格,包括列表、表格、多选列表。
    6) 支持数据过滤。
    7) 支持自定义下拉框的显示内容(见popup属性)。
    下图中显示了ComboBox控件的在设计区中的位置及样式:

    图 285 ComboBox控件
    ComboBox控件所对应的主要属性及其描述如下表所示:

    属性名 描述
    autoCompleter
    设置自动下拉相关信息
    cascade
    设置级联相关信息
    dataFilter
    设置数据源的过滤查询信息
    dataProvider
    设置数据源相关的信息
    dataType
    设置控件(绑定)值的数据类型
    decoder
    设置下拉框转码相关的信息
    editFormatter
    设置编辑格式化信息
    popup
    设置弹出控件控制器
    表 3 Button控件的常用事件及其描述
    您可通过快捷属性菜单或属性视图定义ComboBox控件的相关属性和事件,例如您可以通过快捷属性菜单设置下拉列表的转码显示值和实际值,如下图所示:

    图 286设置ComboBox转码值
    5. 下拉树控件(ComboBoxTree)
    从外观上来看,ComboBoxTree和ComboBox控件类似。但后者下拉的是列表,而前者是一棵树形结构。当用户需要展现带有层次结构的数据时,可以考虑使用ComboBoxTree控件。下图中显示了ComboBoxTree控件在设计区中的位置及样式:

    图 287 ComboBoxTree控件
    ComboBoxTree控件所对应的常见属性及其描述如下表所示:
    属性名 描述
    dataProvider
    数据提供对象。
    expandTree
    设置是否点击下拉按钮就根据树的id来展开树。
    treeJson
    动态创建一棵树,传入树的属性即可。
    表 4 ComboBoxTree控件的常用事件及其描述
    您可通过快捷属性菜单或属性视图定义ComboBoxTree控件的相关属性和事件,双击可编辑ComboBoxTree显示的内容信息。
    用户需要使用ComboBoxTree展现数据时,最重要的是配置ComboBoxTree中的Tree部分属性,该部分属性如下:

    图 288 ComboBoxTree属性页
    其中binding属性记录tree的绑定信息,为Json串格式,类似tree属性,下面举例说明binding的配置方法:
    leaf:'leaf', store:'menuTree', parent:’parent’,query:{ name: 'parent', relation: '=', value:''}
    即对于该ComboBoxTree绑定了名为“menuTree”的dataStore,并绑定leaf属性为该dataStore的leaf字段,query属性类似于tree的query,“{ name: 'parent', relation: '=', value:''}”表示第一层节点是由“parent字段数值为空”的节点构成。
    checkLogic属性定义了该下拉树的复选逻辑,一般写为:
    model:'single'
    其中multiple为可多选且没有复选逻辑;cascade关联所有的父子节点;parentCascade关联所有父节点;childCascade关联所有子节点;single只能选择一个节点;halfChecked当某节点的子节点未完全选中时,该节点处于半选状态。
    【注意】如不需要出现复选框图标,则不要配置该属性。
    Label属性为虚拟根节点名称,配置该属性会产生名为该属性值的虚拟根节点,不需要的时候则不配置该属性。
    如果下拉树需要配置懒加载,类似于Tree控件,在下拉树控件的loader-rpc方法中调用processor去后台取数据,并在成功回调中将下层节点数据放入树的dataStore中并展现。具体可参考树的实现方法一节。

    6. 页面组件控件(Component)
    通过Component控件,可以实现在当前页面中引用其他页面组件的功能,从而达到页面组件复用的目的。下图中显示了Component控件在设计区中的位置及样式:

    图 289 Component控件
    Component控件中最重要的属性是ref属性,通过该属性可以选择所要包含的页面片段,如下图所示:

    图 290 Component控件的ref属性
    当然,您也可以通过快捷属性菜单来设置引用的页面组件,如下图所示:

    图 291设置Component的组件引用
    7. 日期文本框(DataTextBox)
    通过DataTextBox控件,可以进行日期的选择。下图中显示了DataTextBox控件的在设计区中的位置及样式:

    图 292 DataTextBox控件
    DataTextBox控件所对应的常见属性及其描述如下表所示:

    属性名 描述
    autoDate
    当输入文本框内容为空并且鼠标焦点置入时,设置文本框是否显示当前时间。
    range
    设置日期的选择范围。
    表 5 DataTextBox控件的常用属性及其描述
    您可通过快捷属性菜单或属性视图定义DataTextBox控件的相关属性和事件,双击可编辑DataTextBox显示的内容信息。
    8. 文本上传控件(FileInput)
    FileInput控件相当于HTML标签中的<input type="file" name="uploadFile" />。下图中显示了FileInput控件在设计区中的位置及样式:

    图 293 FileInput控件
    FileInput控件所对应的常用属性及其描述如下表所示:

    属性名 描述
    cancelText
    设置清空控件值的按钮名称。
    fileFilter
    设置只允许上传特定后缀名的文件。
    表 6 FileInput控件的常用属性及其描述
    您可以通过快捷属性菜单修改文本上传控件的按钮标题,如下图所示:

    图 294设置FileInput控件的浏览按钮和取消按钮的标题
    9. 数据表格控件(Grid)
    通过Grid控件可自动的生成数据表格。下图中显示了Grid控件的在设计区中的位置及样式:

    图 295 Grid控件
    您可通过快捷属性菜单或属性视图定义Grid控件的相关属性和事件,双击可编辑Grid显示的内容信息。例如您可以通过快捷属性菜单选择需要绑定的DataStore,如下图所示:

    图 296在Grid控件中绑定DataStore
    10. Hr控件(Hr)
    使用Hr控件相当于在页面中加入了HTML代码片段:<hr></hr>。下图中显示了Hr控件的在设计区中的位置及样式:

    图 297 Hr控件
    您可通过快捷属性菜单或属性视图定义Hr控件的相关属性和事件,双击可编辑Hr控件显示的内容信息。例如您可以通过快捷属性菜单设置Hr标签的宽度和高度,如下图所示:

    图 298修改Hr控件的高度和宽度
    11. HTML控件(HTML)
    通过使用HTML控件,可以直接在页面中写入HTML代码片段。当基本控件和容器无法满足用户的需求时,我们可以借助HTML控件,在HTML控件中填入HTML源码,添加到页面的相应位置。下图中显示了HTML控件的在设计区中的位置及样式:

    图 299 HTML控件
    您可通过快捷属性菜单或属性视图定义HTML控件的相关属性和事件,双击可编辑HTML控件显示的内容信息。例如在快捷属性菜单中,您可以直接编辑需要写入的HTML代码,如下图所示:

    图 300为HTML控件添加内容
    12. 图像(Image)
    通过Image控件可以方便的插入一张图片。下图中显示了Image控件的在设计区中的位置及样式:

    图 301 Image控件
    您可通过快捷属性菜单或属性视图定义Image控件的相关属性和事件,双击可编辑Image控件显示的内容信息。在属性快捷菜单,可以通过图片的URL路径来选择要展示的图片,如下图所示:

    图 302设置Image控件所显示图片的URL路径
    13. InlineEditBox控件(InlineEditBox)
    从外表上看,InlineEditBox控件是一个只读文本,当点击只读文本时,会弹出一个编辑器,它可以对文本进行编辑。编辑器失去焦点后,编辑器消失,文本的值发生改变。下图中显示了InlineEditBox控件的在设计区中的位置及样式:

    图 303 InlineEditBox控件
    InlineEditBox控件所对应的常见属性及其描述如下表所示:

    属性名 描述
    decoder
    设置InlineEditBox的转码,例如将数字3转码成辽宁省等。
    displayFormatter
    对InlineEditBox控件的显示值进行格式化。
    editor
    设置InlineEditorBox控件的编辑器,默认编辑器为unieap.form.TextBox。
    showUnderLine
    设置是否在只读文本下显示下划线。
    表 7 InlineEditBox控件的常用属性及其描述
    您可通过快捷属性菜单或属性视图定义InlineEditBox控件的相关属性和事件,双击可编辑InlineEditBox控件显示的内容信息。
    14. 标签(Label)
    通过Label控件,可以直接生成相应的标签。下图显示了Label控件的在设计区中的位置及样式:

    图 304 Label控件
    您可通过快捷属性菜单或属性视图定义Label控件的相关属性和事件,双击可编辑Label控件显示的内容信息。
    15. 链接(Link)
    通过使用Link控件可以直接建立一个链接。下图中显示了Link控件的在设计区中的位置及样式:

    图 305 Link控件
    您可通过快捷属性菜单或属性视图定义Link控件的相关属性和事件,双击可编辑Link控件显示的内容信息。例如通过属性快捷菜单,您可以编辑Link控件的控件内容和链接地址,如下图所示:

    图 306编辑Link控件的控件内容和链接地址
    16. 数字文本框控件(NumberTextBox)
    使用NumberTextBox控件,在文本框中只能输入负号、数字和小数点。默认情况下,数字文本框会对输入的字符进行及时校验,您可以设置validator="{realTime:false}"来关闭,关闭后,只有在数字文本框失去焦点时才进行校验。下图中显示了NumberTextBox控件的在设计区中的位置及样式:

    图 307 NumberTextBox控件
    NumberTextBox控件所对应的常见属性及其描述如下表所示:

    属性名 描述
    precision
    设置控件中数字的精度限制。
    range
    设置控件能输入的最大值和最小值。
    scale
    设置控件中数字的小数精度。
    表 8 NumberTextBox控件的常用属性及其描述
    您可通过快捷属性菜单或属性视图定义NumberTextBox控件的相关属性和事件,双击可编辑NumberTextBox控件显示的内容信息。
    17. 进度条控件(ProgressBar)
    通过使用ProgressBar控件,可以在界面中生成一个进度条。下图中显示了ProgressBar控件的在设计区中的位置及样式:

    图 308 ProgressBar控件
    ProgressBar控件所对应的常见属性及其描述如下表所示:

    属性名 描述
    maximum 设置控件的进度最大值。
    progress 设置控件已经完成的进度。
    places 设置控件中进度值的显示精度。
    表 9 ProgressBar控件的常用属性及其描述
    您可以通过属性视图定义ProgressBar控件的相关属性和事件。
    18. 查询控件(Query)
    通过使用Query控件,可以在界面中生成一套用于查询的控件组合。下图中显示了Query控件的在设计区中的位置及样式:

    图 309 Query控件
    您可通过快捷属性菜单或属性视图定义Query控件的相关属性和事件,例如您可以设置属性控制是否显示“查询”、“清空”、“增加”和“删除”图标,如下图所示:

    图 310 设置Query控件的显示内容
    19. 单选按钮(RadioButton)
    通过使用RadioButton控件,可以在页面中生成一个单选按钮。下图中显示了RadioButton控件的在设计区中的位置及样式:


    图 311 RadioButton控件
    您可通过快捷属性菜单或属性视图定义RadioButton控件的相关属性和事件,例如您可通过快捷属性菜单设置单选按钮是否选中状态、以及不同状态对应的值,如下图所示:

    图 312设置RadioButton状态和对应值
    20. 单选按钮组(RadioButtonGroup)
    通过RadioButtonGroup控件可以直接在页面中生成多个单选按钮。下图中显示了RadioButtonGroup控件的在设计区中的位置及样式:

    图 313 RadioButtonGroup控件
    您可通过快捷属性菜单或属性视图定义RadioButtonGroup控件的相关属性和事件,例如您可以通过快捷属性菜单设置单选RadioButtonGroup控件的列数和控件转码的值,如下图所示:

    图 314设置RadioButtonGroup按钮组的列数和转码值
    21. TextArea控件(TextArea)
    TextArea控件相当于HTML中的textarea标签。下图中显示了TextArea控件在设计区中的位置及样式:

    图 315 TextArea控件
    您可通过快捷属性菜单或属性视图定义TextArea控件的相关属性和事件,双击可编辑TextArea控件显示的内容信息。
    22. 普通文本框控件(TextBox)
    TextBox控件相当于HTML中的input标签。该控件支持文本的正则校验、编辑格式化、显示格式化、保存值格式化。下图中显示了TextBox控件的在设计区中的位置及样式:

    图 316 TextBox控件
    您可通过快捷属性菜单或属性视图定义TextBox控件的相关属性和事件,双击可编辑TextBox控件显示的内容信息。
    23. 带图标的文本框控件(TextBoxWithIcon)
    通过使用TextBoxWithIcon控件,可以在页面上生成一个带图标的文本框,并且可以定义图标的样式。下图中显示了TextBoxWithIcon控件在设计区中的位置及样式:


    图 317 TextBoxWithIcon控件
    您可通过快捷属性菜单或属性视图定义TextBoxWithIcon控件的相关属性和事件,双击可编辑TextBoxWithIcon控件显示的内容信息。
    24. 树控件(Tree)
    Tree控件主要实现了以下功能:
    1) 支持根据RowSet行集结构构造树结构,同时支持原生的jsontree结构(目前只支持只读功能)。
    2) 可以实现复选、拖拽、编辑等功能。
    3) 支持懒加载数据。
    4) 支持对节点进行增删操作。
    5) 支持对节点重新设置数据源。
    6) 支持键盘导航功能,具体为:点击上下键将选中当前节点的上一个或下一个可见节点;点击Home键选中第一个可见节点,点击End键选中最后一个可见节点;点击右键将会展开当前节点,或者选中当前节点的第一个子节点;点击左键将会收起当前节点,或者选中当前节点的父节点。
    7) 支持根据路径、层级等展开节点。
    下图中显示了Tree控件在设计区中的位置及样式:

    图 318 Tree控件
    Tree控件所对应的常见属性及其描述如下表所示:

    属性名 描述
    checkLogic
    设置树的复选信息。
    checkLogicClass
    设置树的复选逻辑所使用的类名,用户一般只需使用默认值就可以。
    dndSourceClass
    设置树的拖拽所使用的类名,用户一般只需使用默认值就可以。
    expandRoot
    是否展开根结点,不能同时不配置label属性而将expandRoot属性设置为false。
    loader
    在树的数据是懒加载的情况下,设置懒加载树的请求配置。
    pathSeparator
    得到节点路径时的分隔符。
    treeDnd
    设置树的拖拽信息,目前树支持对非懒加载且数据格式为RowSet的树进行拖拽。
    treeEditor
    设置树的编辑信息,若不进行设置,默认是不支持编辑。
    treeEditorClass
    设置树的编辑所使用的类名,用户一般只需使用默认值就可以。
    treeLoaderClass
    设置树加载子节点所使用的类名,用户一般只需使用默认值就可以。
    表 10 Tree控件的常用属性及其描述
    Tree控件所对应的常见方法及其描述如下表所示:

    事件名 描述
    setChecked
    在支持复选的情况下,将指定节点设置为选中或非选中状态。
    setCurrentNode
    将指定节点设置为当前节点,并更改样式。
    showNodesById
    按照节点的id展开并显示节点。
    表 11 Tree控件的常用事件及其描述
    您可通过快捷属性菜单或属性视图定义Tree控件的相关属性和事件,双击可编辑Tree控件显示的内容信息。

    6.2.3.14 容器控件的使用
    6.2.3.14.1 TitlePane
    TitlePane控件是一个可以进行收缩/展开操作的容器控件,在TitlePane中可以放置其它子控件。
    在设计页面的调色板中选择TitlePane控件,在设计区域需要添加TitlePane的区域单击鼠标左键,会在相应位置增加一个TitlePane控件,如下图所示:

    图 319 TitlePane
    新建的TitlePane控件的高度和宽度默认均为“auto”。此时,该TitlePane控件的宽度为100%,即与其所在容器的宽度相等(若没有外层容器,宽度为页面大小的100%),高度为自动适应其内部子控件的高度。
    在调色板中选择其它控件,在设计区域的一个TitlePane上单击鼠标左键,会在该TitlePane内部增加一个相应的控件。此时,如果该TitlePane 的高度属性为“auto”,它的高度会被撑大,并自动适应其内部子控件的高度,如下图所示:

    图 320 TitlePane适应内容大小
    TitlePane的“view”复合属性用于配置该TitlePane所引用的页面,该属性包含两个子属性:“ref”和“para”。其中,“ref”属性用于指定该TitlePane所引用的页面,“para”属性用于配置页面参数。
    为TitlePane指定一个引用页面的方法如下:
    在页面中选择一个TitlePane,在属性视图中选择“ref”属性,“属性值”区域会出现“增加引用”( )和“删除引用”( )两个按钮,如下图所示:

    图 321 TitlePane引用view
    单击“增加引用”按钮,会弹出“增加引用的view” 对话框,对话框中会列出当前view所依赖的所有其它view页面。
    如果需要为TitlePand指定的页面存在于列表中,可以在列表中选择该页面,单击“确定”按钮,完成指定页面操作。

    图 322 添加依赖的view
    单击“删除引用”按钮,会将该TitlePane的引用属性删除。
    6.2.3.14.2 表单(Form)
    Form控件和HTML中的form标签类似,可以内嵌其他表单控件。
    在设计页面的调色板中选择Form控件,在设计区域需要添加Form的区域单击鼠标左键,会在相应位置增加一个Form控件,如下图所示:

    图 323 Form
    可以通过在调色板中选择其它控件,添加到Form中。Form没有高度和宽度属性,其在页面中所展示的高度取决于其所包含的内容,随着其嵌套的控件的高度而增加,宽度则始终是100%。,如图所示:

    图 324 Form适应内容大小
    Form控件的binding复合属性用于设置From的数据绑定,包括bindIndex和store两个子属性。有关From数据绑定的操作方式请参见“数据绑定”章节的相关内容。
    6.2.3.14.3 FormList
    FormList控件是一种类似于Form的控件,但是会根据其绑定的DataStore的内容同时显示多个Form。
    在设计页面的调色板中选择FormList控件,在设计区域需要添加FormList的区域单击鼠标左键,会在相应位置增加一个FormList控件,如下图所示:

    图 325 FormList
    新建的FormList默认宽度为“100%”,FormList没有高度属性,其在页面中所展示的高度取决于其所包含的内容,随着其嵌套的控件的高度而增加。
    FormList控件的binding复合属性用于设置FormList的数据绑定,包括一个store子属性,用于设置控件绑定的dataStore。有关FromList数据绑定的操作方式请参见“数据绑定”章节的相关内容。
    6.2.3.14.4 TableLayout
    TableLayout控件用于在页面中形成表格布局的效果,table中的每个cell可以放置一个子控件。
    在设计页面的调色板中选择TableLayout控件,在设计区域需要添加TableLayout的区域单击鼠标左键,会弹出“新建TableLayout”对话框,如下图所示:

    图 326 创建TableLayout
    该对话框可以用于设置新建Table的行数和列数,默认值为2行4列。按照需要设置新Table的行列数之后,单击<确定>按钮,会页面设计区域中增加一个Table,如下图所示:

    图 327 TableLayout
    在设计区域中选择一个Table控件,工具栏中的“Grid工具栏”会亮显,如下图所示:

    图 328 TableLayout操作按钮
    “Grid工具栏”中按钮的名称和作用如下:
    在上方插入行:在当前cell所在行的上方插入一行,新插入行的列布局方式与当前cell所在行的上一行相同。
    在下方插入行:在当前cell所在行的下方插入一行,新插入行的列布局方式与当前cell所在行相同。
    在左侧插入列:在当前cell所在列的左侧插入一列,新插入列的行布局方式与当前cell所在列的上一左侧列相同。
    在右侧插入列:在当前cell所在列的右侧插入一列,新插入列的行布局方式与当前cell所在列相同。
    删除行:删除当前cell所在行,当前cell所在行下方的所有单元格上移。
    删除列:删除当前cell所在列,当前cell所在列的右侧所有单元格左移。
    合并单元格:合并所选中的多个cell,如果所选的cell不在同一行或不在同一列,合并单元格按钮灰显。
    取消合并单元格:将当前cell拆分为合并之前的状态。
    在调色板中选择需要放置在Table中的控件,在Table中相应的cell中单击鼠标左键,会将控件增加到Table中的相应位置,如下图所示:

    图 329 添加内容

    图 330 单元格内布局
    在一个空cell中双击,可以弹出一个文本编辑区域,可以在该区域中输文字并做为cell中的内容,如下图所示:

    图 331 单元格直接编辑文字
    6.2.3.14.5 Dialog
    Dialog控件用于实现模态对话框效果,可以为其指定一个引用的页面,或在Dialog中放置其它控件,作为弹出时显示的内容。
    在设计页面的调色板中选择Dialog控件,在设计区域需要添加Dialog的区域单击鼠标左键,会在相应位置增加一个Dialog控件,如下图所示:
    新建的Dialog默认尺寸为428px*400px,设计页面中的所有Dialog均出现在页面的左下角。可以通过单击Dialog右上角的“收缩/展开”按钮,将Dialog置为收缩或展开状态。如下图所示:

    图 332 最小化对话框

    图 333 最大化对话框
    Dialog的“view”复合属性用于配置该Dialog所引用的页面,该属性包含两个子属性:“ref”和“para”。其中,“ref”属性用于指定该Dialog所引用的页面,“para”属性用于配置页面参数。设置Dialog的“view”属性的方法参见TitlePane中设置“view”属性的相关部分。
    6.2.3.14.6 BorderLayout
    BorderLayout控件提供对页面的方位布局,将页面分为上、下、左、右、中五个面板,中面板是自适应面板且必须配置,其他面板是否出现可选。
    在设计页面的调色板中选择BorderLayout控件,在设计区域需要添加BorderLayout的区域单击鼠标左键,会弹出“新建BorderLayout”对话框,如下图所示:

    图 334 创建BorderLayout
    在对话框中可以选择BorderLayout控件的布局方式和哪些区域出现在BorderLayout中,单击<确定>按钮,会在相应位置增加一个BorderLayout控件,如下图所示:

    图 335 BorderLayout
    完成新建操作后,可通过BorderLayout的快捷菜单对容器的布局重新进行配置。可以通过设置BorderLayout中每个区域的尺寸对BorderLayout的样式进行调整,其中region为“left”和“right”的两个区域可以设置宽度,高度为BorderLayout整体的高度减去region为“top”和“bottom”的两个区域的高度,不可手动设置;region为“top”和“bottom”的两个区域可以设置高度,宽度为BorderLayout整体的高度减去region为“left”和“right”的两个区域的宽度,不可手动设置;region为“center”的区域不可设置尺寸,其宽高为BorderLayout整体的尺寸减去四周区域的尺寸所剩余的值。
    6.2.3.14.7 HBoxContainer
    HBoxContainer控件是一种水平排列其内部控件的容器,其内部的控件无论多少均按一行排列。
    在设计页面的调色板中选择HBoxContainer控件,在设计区域需要添加HBoxContainer的区域单击鼠标左键,会在相应位置增加一个HBoxContainer控件,控件默认尺寸为100%*100%。
    在调色板中选择需要放置在HBoxContainer中的控件,在HBoxContainer中相应的位置单击鼠标左键,会将控件增加到HBoxContainer中。所有放置在HBoxContainer中的均会排列在同一行,如下图所示:

    图 336 HBox控件
    在属性视图中修改控件的“pack”(水平对齐)和“align”(垂直对齐)属性,容器中的控件对齐方式发生相应改变。
    其中“pack”(水平对齐)属性用于设置HBoxContainer容器所嵌套的组件在其水平方向上的布局;“align”(垂直对齐)属性用于设置HBoxContainer容器所嵌套的组件在其垂直方向的布局,属性可供选择的值及意义如下表所示:
    pack属性 start 表示从父容器内左侧开始定位
    center 表示从父容器内中间开始定位
    end 表示从父容器内右侧开始定位
    align属性 top 表示子控件居上显示
    middle 表示子控件居中显示
    bottom 表示子控件居下显示
    修改控件的“margins”属性和“paddings”属性,容器中的控件边界发生相应改变。其中,“margins”属性的作用是设置HBoxContainer容器所嵌套的各个组件之间的间距,默认四个方向值均为0。“paddings”属性的作用是将HBoxContainer容器所嵌套的组件当成一个整体,设置其与HBoxContainer之间的间距,默认四个方向值均为0。
    在属性视图中,在属性视图中选择“margins”属性或“paddings”属性,属性值区域会出现“编辑属性”按钮( ),如下图所示:

    图 337 设置margins
    单击<编辑属性>按钮,会弹出“编辑边界尺寸”对话框,如下图所示:

    图 338 边界尺寸设置
    修改四个方向的边界尺寸,单击<确定>按钮,相应的属性值会发生改变。
    6.2.3.14.8 FieldSet
    FieldSet容器相当于HTML中fieldset标签, FieldSet控件的高度和宽度值是随着FieldSet内容的增多而增大的,所以高度和宽度值不必设置。
    在设计页面的调色板中选择FieldSet控件,在设计区域需要添加FieldSet的区域单击鼠标左键,会在相应位置增加一个FieldSet控件,如下图所示:

    图 339 FieldSet
    在调色板中选择需要放置在FieldSet中的控件,在FieldSet相应的位置中单击鼠标左键,会将控件增加到FieldSet中的相应位置,如下图所示:

    图 340 在FieldSet中添加内容
    在FieldSet的属性页中我们可以对FieldSet的属性进行设置。修改flexible属性,可以设置flexible容器是否支持展开关闭;修改open属性,可以设置flexible容器的初始状态是展开还是关闭。

    6.2.3.14.9 AdaptiveContainer和AdaptivePane
    AdaptiveContainer控件是AdaptivePane控件的容器,它们用于实现自适应容器的效果。即当某些控件收缩后,自适应容器会自动填满该控件收缩后所留下的空间。
    在设计页面的调色板中选择AdaptiveContainer控件,在设计区域需要添加AdaptiveContainer的区域单击鼠标左键,会在相应位置增加一个AdaptiveContainer控件,如下图所示:

    图 341 AdaptiveContainer
    新建的AdaptiveContainer控件的高度为“100%”,宽度为“auto”。在调色板中选择AdaptivePane控件,在设计区域的AdaptiveContainer控件上单击鼠标左键,可以在AdaptiveContainer中增加多个AdaptivePane,如下图所示:

    图 342 AdaptivePane
    AdaptiveContainer中的AdaptivePane长度为“120px”,宽度为“auto”,AdaptivePane的宽度和高度都是可以改变的。
    设置AdaptivePane的autoHeight属性,可以设置该AdaptivePane容器是否为自适应容器;只有当autoHeight设置为true的时候,adaptiveHeight属性才允许被用户设置,并且该属性只允许被用户设置为百分比的形式,该属性的具体含义是:设置该自适应容器占据某些控件收缩后留下空间的百分比。
    6.2.3.14.10 TabContainer和TabPane
    TabContainer控件是Tab控件的容器,TabPane控件的作用是放置在TabContioner中,它们用于实现在页面中显示出多个Tab页的效果。
    在设计页面的调色板中选择TabContainer控件,在设计区域需要添加TabContainer的区域单击鼠标左键,会在相应位置增加一个TabContainer控件,如下图所示:

    图 343 TabContainer
    新建的TabContainer控件的高度为“400px”,宽度为“auto”。在调色板中选择TabPane控件,在设计区域的TabContainer控件上单击鼠标左键,可以在TabContainer中增加多个TabPane,如下图所示:

    图 344 TabPane
    TabContainer中的TabPane长宽均为“100%”,即与其所在的TabContainer尺寸相等,且无法通过修改其长宽属性改变其大小。
    在默认情况下,TabContainer容器中的Tab标签位于容器的上方,可以通过修改TabContainer容器的tabPosition属性调整标签出现的位置,如下图所示:

    图 345 Tab位置
    如果在一个TabContainer中存在多个TabPane,可以通过单击某个TabPane右上角的方向箭头,选择该TabPane的上一个或下一个TabPane,如下图所示:

    图 346切换Tab页
    TabPane的“view”复合属性用于配置该TabPane所引用的页面,该属性包含两个子属性:“ref”和“para”。其中,“ref”属性用于指定该TabPane所引用的页面,“para”属性用于配置页面参数。设置TabPane的“view”属性的方法参见TitlePane中设置“view”属性的相关部分的内容。
    6.2.3.14.11 StackContanier和StackPane
    StackContainer控件是StackPane控件的容器,它们用于实现在页面中显示出相互覆盖的多层容器的效果。
    在设计页面的调色板中选择StackContainer控件,在设计区域需要添加StackContainer的区域单击鼠标左键,会在相应位置增加一个StackContainer控件,如下图所示:

    图 347 StackContainer
    新建的StackContainer控件的高度为“400px”,宽度为“auto”。在调色板中选择StackPane控件,在设计区域的StackContainer控件上单击鼠标左键,可以在StackContainer中增加多个StackPane,如下图所示:

    图 348 StackPane
    StackContainer中的StackPane长宽均为“100%”,且无法通过修改其长宽属性改变其大小。
    为便于在多个StackPane中进行选择,StackContainer中的每个StackPane均有一个标签,位于StackContainer的上方,该标签在实际页面中不会显示出来。
    如果在一个StackContainer中存在多个StackPane,可以通过单击某个StackPane右上角的方向箭头,选择该StackPane的上一个或下一个StackPane,如下图所示:

    图 349 切换StackPane
    StackPane的“view”复合属性用于配置该StackPane所引用的页面,该属性包含两个子属性:“ref”和“para”。其中,“ref”属性用于指定该StackPane所引用的页面,“para”属性用于配置页面参数。设置StackPane的“view”属性的方法参见TitlePane中设置“view”属性的相关部分的内容。
    6.2.3.14.12 Div
    Div控件是一个可以在其内部放置其他控件的容器,其主要功能是生成HTML中Div标签,
    并通过修改class和style属性来实现特定的布局;而width和height属性只用于UI设计界面,并不生成对应的代码。

    在设计页面的调色板中选择Div控件,在设计区域需要添加Div的区域单击鼠标左键,会在相应位置增加一个Div控件,如下图所示:


    新建的Div默认高度为120px,宽度为auto,这两个属性只用于UI设计界面,并不生成对应JSP的代码。

    选中需要修改属性的Div,查看属性视图,如下图所示:

    可以通过修改class和style来实现需要的特定布局样式。
    6.2.4 模式控件的使用
    6.2.4.1 AdaptiveLayout
    6.2.4.1.1 简介
    通过AdaptiveLayout模式控件可快速生成自适应布局,并提供六种常用布局方便用户快速复用。
    该模式控件为无实例控件,用户在生成后不能再次打开该控件向导。
    6.2.4.1.2 使用方法
    打开AdaptiveLayout模式控件向导,如下图所示:

    图 350 AdaptiveLayout模式控件向导
    如图所示,该向导页上方可选择控件高度,下拉框可选择“默认”和“超长”,分别对应右侧数值的“100%”和“auto”,同时该控件高度允许用户手动修改。
    下方窗口显示了六种常用的自适应布局,分别为:
    1. 单锁定分区单缩放区域A
    2. 多锁定分区单缩放区域A
    3. 多锁定分区双缩放区域A
    4. 单锁定分区单缩放区域B
    5. 多锁定分区单缩放区域B
    6. 多锁定分区双缩放区域B
    每种常用格式都由示例图片显示,用户可通过选择其中某种布局直接点击finish生成AdaptiveLayout布局。也可点击下一步进行对该模式的自定义修改,例如,选择“多锁定分区双缩放区域A”,之后点击下一步打开自定义设置的向导页,如下图所示:

    图 351 AdaptiveLayout模式控件详细设置向导
    如图所示,该页详细列出所选布局的布局信息,该向导页上方可更改“区域数量”,即布局所使用的AdaptivePane数量。对于每个AdaptivePane,点击图片 或 可相互切换,其中:
    :表示锁定的AdaptivePane,即拥有特定高度并无法通过自适应改变高度,但可以通过TitlePane等收起。
    :表示可自适应的AdaptivePane,即该部分控件可根据可用空间的大小,根据用户向导设置的“自适应高度”的%数值(图中皆为50%),自动调整控件高度,达到自适应的需求。
    对每个AdaptivePane用户可定义其中放置的容器控件,该向导提供了几个常用控件供用户选择 ,该选项框右侧可设置title属性(类似titlePane的title属性,暂不支持自动生成ToolBar,如有需求用户可在AdaptiveLayout生成后手动添加ToolBar模式控件)。
    设置完成后点击finish则完成该布局控件的创建,在UI设计器中效果如下图所示:


    图 352 AdaptiveLayout模式控件生成效果
    6.2.4.2 TableLayout
    6.2.4.2.1 简介
    通过TableLayout模式控件可快速生成表格布局,提供可视化的表格合并和拆分功能,并提供六种常用布局方便用户快速复用。
    该模式控件为无实例控件,用户在生成后不能再次打开该控件向导。
    6.2.4.2.2 使用方法
    打开TableLayout模式控件向导,如下图所示:

    图 353 TableLayout模式控件向导页
    如图所示,向导页上方可设置布局控件的ID和后缀,保证该控件在模型中ID唯一。
    向导页中间区域包含六组常用表格布局,直接使用时通过选中对应布局,点击finish即可。如需要较复杂表格布局,则点击下一步进行详细布局设置,如下图所示:

    图 354 TableLayout模式控件详细设置向导页
    首先,该向导页上半部分用来规划整体布局及全局参数,各主要属性介绍如下:
     整体高度:生成的table的高度,通常设为100%,主要根据table外层容器确定。
     整体宽度:生成的table的宽度,通常设为100%,主要根据table外层容器确定。
     默认统一行高:用户可通过设置该属性统一调整table每行高度,当需要对行高进行单独设置时,可通过点击下方“布局信息列表”中对应行高进行单独设置。
     默认统一列宽:同上,可通过设置该属性统一调整table每列宽度。
     水平对齐方式:table中控件的水平对齐方式,一般为left或center。
     垂直对齐方式:table中控件的垂直对齐方式,一般为top或middle。
    用户更改“行数”、“列数”后点击“生成布局”,在下方可视界面则可生成相应布局效果,例如,行数为5、列数为3的情况下,点击“生成布局”如下图所示:

    图 355 TableLayout模式控件5行4列布局图示
    在该可视界面中,可进行对Cell的合并和拆分操作,允许用户选择相邻或合法的Cell区块进行合并和拆分,例如,需要将第一行所有Cell合并为一列,则首先选中第一行所有Cell,如下图所示:

    图 356 TableLayout模式控件合并第一行图示
    如图,当所选Cell组为可合并的,右侧“合并”按钮就会点亮,允许用户进行合并操作,点击“合并”按钮,第一行成功合并。拆分同理。当用户对布局的修改结束后,点击“finish”,在UI设计器上则形成Table布局,如下图所示:

    图 357 TableLayout模式控件生成控件效果
    6.2.4.2.3 Toolbar
    6.2.4.2.4 简介
    通过Toolbar模式控件可快速生成工具栏控件,提供通用布局及常用工具栏按钮方便用户快速复用,并可统一工程中工具栏按钮属性。
    该模式控件为有实例控件,用户在生成后可通过再次打开该控件向导进行修改。
    6.2.4.2.5 使用方法
    打开Toolbar模式控件向导,如下图所示:

    图 358 Toolbar模式控件向导页
    该向导页上部分为Toolbar控件的基本信息设置,包括:控件ID、后缀、工具栏高度、工具栏总列数、对齐方式及统一默认宽度。在下方“工具栏信息列表”中可进行工具栏按钮的设置,其中常用按钮可通过点击“默认”按钮,弹出菜单如下图所示:

    图 359 Toolbar模式控件选择默认按钮
    如图所示,可选择需要的按钮,之后点击“确定”,则模式控件会自动生成该按钮,如下图所示:

    图 360 Toolbar模式控件工具栏信息
    除常用按钮外,用户也可通过点击“增加”按钮添加自定义控件,对每一个控件,用户可以通过改变“控件类型”来更改控件,目前支持Button、CheckBox、ComboBox等十个控件。
    控件宽度可以通过修改每个控件的宽度,或通过上方“统一默认宽度”设定。
    对齐方式指的是控件在工具栏容器中的对齐方式,一般默认为“右对齐”。
    设置完成后点击“finish”在UI设计器上生成工具栏控件,如下图所示:

    图 361 Toolbar模式控件生成后效果
    6.2.4.3 Tree
    6.2.4.3.1 简介
    通过Tree模式控件可快速生成树控件,由于树控件的属性配置较为繁琐,不熟悉该控件的开发人员很难正确配置树的信息,由于该控件的重要性,故开发该模式控件方便配置,并给予“binding-query”类似属性以具象化效果。出于脚本的不可控性,该控件不生成初始化脚本,需要用户手动初始化数据(推荐在Entry中,或page_init方法)。
    该模式控件为有实例控件,用户在生成后可通过再次打开该控件向导进行修改。
    6.2.4.3.2 使用方法
    打开Tree模式控件后弹出向导框,如下图所示:

    图 362 Tree模式控件生成后效果
    其中,“复选逻辑”选框未选中时,复选逻辑为单选,当选中“复选逻辑”框时,在右侧下拉框可选择复选逻辑,包括多选、级联等。
    “数据绑定”栏中定义了树所绑定的数据集和常用绑定属性,分别对应:ID、LABEL、PARENTID和LEAF属性。下拉框中可选择数据集中属性,允许重复。
     节点ID字段(binding-id树的节点对应数据的标识字段)
     节点显示字段(binding-label树的节点对应数据的显示字段)
     父节点字段(binding-parent数据中标识父节点的字段名)。
     叶子节点字段(binding-leaf数据中标识叶子节点的字段名)。
    当选择数据集后,用户需要定义构建树第一层节点的查询条件,用来确定树的第一层节点。如需添加虚拟根节点,即在第一层节点前增加一个单独的虚拟根节点,此时勾选“添加虚拟根节点”并在右侧文本框中输入文字,如下图所示:

    图 363 Tree模式控件第一层节点查询条件及虚拟根节点
    在向导下方,用户可以选择“全加载”方式及“懒加载”方式,其中初始化数据的阶段统一由用户手动操作,推荐在Entry或page_init方法中初始化数据,保证在树渲染之前将数据初始化完毕。
    当选择懒加载时,加载每层节点的事件将通过loader-rpc方法完成,而在该向导中需要用户填入每次加载时所调用的bo方法,如下图所示:

    图 364 Tree模式控件懒加载
    选择“懒加载”后点击<选择>按钮,弹出对话框如下图所示:

    图 365 Tree模式控件懒加载选择依赖BO
    通过选择BO中的具体方法会在树的loader-rpc方法里生成相应脚本文件。
    6.2.4.4 Form
    6.2.4.4.1 简介
    模式控件Form是一种能够快速生成表单、绑定数据集、选择过程调用的表单生成控件。
    6.2.4.4.2 使用方法
     快速生成表单
    在控件工具箱中选择模式控件Form,在设计区域需要添加Form的区域单击鼠标左键,会在相应的位置添加一个Form控件,如下图所示。


    图366模式控件Form—创建表单

    通过编辑框可以设置Form的ID,Form控件的后缀,Form的总列数等,通过设置Form控件后缀是为了避免Form控件的ID冲突。Form总列数提供了最常使用的6列和8列模式,初始默认选择6列模式。列模式下拉列表中的数据表示label和控件各占的百分比大小,例如“13%-20%”表示label占整行宽度的13%,控件占整行宽度的20%。
    此外,本着方便、高效和易用的原则,Form控件支持用户进行列宽的自定义设置。可以根据需要灵活的设置每列宽度所占的比值。
     绑定数据集
    通过选择已经创建的数据集,快速选择需要绑定的数据,如下图所示。左侧区域为控件信息列表,右侧为按钮操作区。通过首列选择框选择需要绑定和显示的数据。

    图367模式控件Form—绑定数据集
    控件信息列表列出了数据集中对应的所有数据,控件信息列表各列功能如下所述:
    1) 显示标题:通过编辑“显示标题”属性列可以改变控件显示的标题。
    2) 标题绑定:提供对标题绑定方式的选择,包括 right,left,none三个可选项。
    3) 编辑类型:提供了各种控件形式的编辑类型,例如,可以选择单位空,空位,testBox,comboBox等。
    4) 跨列数:指定控件所占的列数。
    5) 跨行数:指定控件所占的行数。
    6) 常数代码:控件对应的codeList的名字。
    7) 是否伪列:标识当前属性是否是伪列,伪列是指不在所选择的数据集中的属性,只是为了方便数据显示。
    8) 是否必填:标识是否必选属性。
    9) 是否只读:标识是否只读属性。
    10) 是否禁用:标识是否禁用属性。
    按钮操作区列出了对左侧控件信息列表中的相关操作,按钮操作区功能如下所述:
    1) 置顶:通过置顶按钮可以将选中行置顶,以改变控件的显示顺序。
    2) 置底:通过置底按钮可以将选中行置底。
    3) 上移:通过上移按钮可以将选中行位置上移。
    4) 下移:通过下移按钮可以将选中行位置下移,控件信息列表中的排列顺序对应Form的从左向右依次排列的顺序。
    5) 全选:选中所有行。
    6) 全不选:取消选中所有行。
    7) 新增伪列:增加伪列显示。
    8) 删除伪列:删除伪列显示。
    9) 检查更新:检查当前数据集是否有变化,以便进行表单更新。
    “是否生成form”选择框,当选中此选项时可以生成Form,当取消选择时,只生成对应的table,没有生成Form。
     选择过程调用
    通过“选择过程调用”下拉列表框,可以选择添加已有的过程调用方法,实现快速配置和执行processor请求。
    通过以上三个过程的操作,就可以完成一个Form的创建,如下图所示,Form表单自动生成了保存和重置按钮,可以非常方便的进行数据保存和重置。

    图368模式控件Form—表单生成
    6.2.4.5 Grid
    6.2.4.5.1 简介
    通过模式控件Grid可以快速生成数据表格、绑定数据集。
    6.2.4.5.2 使用方法
     快速生成表格
    如下图所示为Grid在控件工具箱中的位置,选择模式控件Grid,在设计区单击鼠标左键即可。

    图369模式控件Grid—创建Grid
     绑定数据集
    如下图所示,可以编辑Grid控件ID、Grid控件后缀,选择Grid类型以及Grid的数据集。
    4) Grid类型:提供了Grid和XGrid两种类型的表格。XGrid是一种性能更高的表格生成控件。
    5) Grid选择类型:none,single(单选),multiple(多选)。
    6) 显示行数:勾选以显示行数。
    7) 显示工具栏:勾选以显示工具栏。

    图370新建模式控件Grid
    1) Grid数据集:通过选择已经创建的数据集,并勾选数据集中的属性字段,设置Grid的显示列。属性信息列表提供了数据集中属性的显示,右侧为按钮操作。
    2) 属性名称:数据集中对应的属性名称。
    3) 显示标题:Grid标题列的显示名称。
    4) 显示类型:设置属性字段的显示类型。
    5) 显示格式:用于设置Grid上数据的显示格式。
    6) 常数代码:控件对应的codeList的名字。
    7) 属性列宽:设置Grid属性的列宽,默认为100px。
    8) 是否固定列:选择固定列,Grid对应列将被锁定,当移动左右滚动条时,被锁定的列将保持固定状态。


    按钮操作包括上、下移、置顶、置底、全选、全不选、新增、删除、检查更新,单选按钮操作包括只读、行可编辑、单元格可编辑。下面给出简要叙述:
    1) 新增:新增属性列,仅用于在Grid中显示信息。
    2) 删除:删除由新增操作增加的属性列,对于数据集中原有的属性字段不能删除。
    3) 检查更新:检查数据集是否发生变化。
    4) 只读:设置Grid的可编辑权限为只读。
    5) 行可编辑:提供Grid整行的可编辑功能。
    6) 单元格可编辑:只提供单元格的可编辑属性。
     生成Grid数据表格
    下图所示为生成的Grid表格,单击序号1的小三角图标,可以快速设置Cell的属性以及编辑事件。单击序号2的template1模板进行数据集绑定以及Grid控件信息的修改。如序号3所示,选择Properties属性可以编辑Grid控件对应的属性信息。

    图371模式控件Grid—生成表格

    6.2.5 设置入口信息
    入口信息页面提供设置“入口信息”方法的可视化页面,其中包含:“基本信息”“依赖BO”“参数列表”和“自动调用BO方法”,如下图所示:

    图 372 过程调用可视化页面
    Entry作为页面跳转的入口,UniEAP V4通过在入口信息页面的设置将自动生成代码并分别与前后台进行关联。

    下面对入口信息页面做具体的介绍:
     基本信息
    基本信息包含:“方法名”、“标题”和“描述信息”,如下图所示:

    图 373 请求方法定义
    其中“方法名”为只读信息。
     参数列表设置
    参数列表中存放通过Entry传输的参数,点击<增加>后弹出对话框,如下图所示:

    图 374选择自动调用的BO方法
    目前支持参数类型为:“Pojo”,“PojoList”和“string”三种类型,其中“string” 类型并不需要设置“来源”。当选择“Pojo”或“PojoList”时则需要开发人员选择“来源”(即当前view文件所绑定的数据集,具体参见4.7.3中“数据集”部分),以“pojo”为例,如下图所示:

    图 375 增加Processor参数
    点击<确定>则会保存在参数列表中,如下图所示:

    图 376 Processor参数列表
    此时切换到脚本编辑器页面后即可在方法中通过“view.forward”调用该Entry,如下图所示:

    图 377 Entry在脚本编辑器中的使用
    其中“viewPath”跳转View的所在dc下view目录下的路径结构,如“test/demoView”;“dc”为含有参数设置中Pojo或者PojoList的DataCenter;“parameter”为Entry参数设置中的需要传递的参数,格式为Json数据结构。
    6.2.5.1 业务逻辑调用
    在UniEAP V4中,后台的方法主要是通过BO来实现。当设置入口信息关联某BO方法时,首先在依赖BO部分,点击<增加>,在弹出的窗口中,选择需要依赖的BO,具体操作如下图所示:

    图 378增加过程调用依赖的BO
    【注意】上图中“按来源过滤”包括“当前DC的BO”和“当前DC可见的BO”,这里做下说明,“当前DC可见对象”包括:当前DC可见的对象和当前DC所依赖的DC中可见的对象。关于如何设置DC依赖,请参见4.9.2小节内容。

    图 379增加过程依赖的BO
    选中依赖的BO列表中的内容,点击<删除>按钮,在弹出的窗口中选择<OK>,可以删除依赖的BO,如下图所示:

     图 380删除过程依赖的BO

     图 381删除过程依赖的BO

     增加BO方法
    点击“自动调用BO中的方法”中的“BO方法”的“选择按钮”,在弹出的窗口中,选择依赖的BO,在下拉列表下方的列表中选择依赖的BO方法,具体操作如下所示:

    图 382选择自动调用的BO方法

    图 383选择BO的方法
    选择方法后点击<确定>键即可,此时V4将通过所设定的BO方法自动生成关联。
    【注意】:当选择BO方法时,该方法的参数请务必和参数列表中的参数保持一致,否则会提示校验失败,如下图所示:

    图 384 BO方法与参数列表保持一致
    6.2.5.2 URL传参数
    在view模型的入口信息中定义需要使用的参数名,如下图所示:

    图 385 入口信息设置
    如图定义了两个参数:”a”和”b”,类型为String(由于通过url传参,参数类型一般都为String类型),这两个参数将会作为页面dataCenter的参数。
    此时在url中即可通过:“.../*.jsp?a=1&b=2/”的方式来传参,JS获取所传参数时通过dataCenter的getParameter()方法:
    //取得通过url传入的参数a和b的值
    var a = dataCenter.getParameter("a");
    var b = dataCenter.getParameter("b");

    6.2.6 设置过程调用
    过程调用页面提供设置“过程调用”方法的可视化页面,其中包含:“请求方法定义”“依赖BO”“参数列表”和“自动调用BO方法”,如下图所示:

    图 386 过程调用可视化页面
    如前所述,Processor作为前后台通讯的媒介,UniEAP V4通过在过程调用页面的设置将自动生成代码并分别与前后台进行关联。
    其中,前台对应的js文件将生成在 “/sc/dc/content/view/generate/*-processor.js”中,可从“概要”页面通过超链接进入,如下图所示:

    图 387 前台processor自动生成的js文件
    而后台java相关将使用统一的Processor来进行处理。

    下面对过程调用页面做具体的介绍:
    6.2.6.1 定义请求方法
    请求方法定义包含:“选择方法”、“基本信息”,定义Processor的主要信息,如下图所示:

    图 388 请求方法定义
    您可以在请求方法定义栏目下进行增加、修改和删除过程调用的请求方法。
     增加请求方法
    点击<增加>,在“基本信息”栏目中编辑方法名、标题、描述信息,以及定义成功和失败的回调方法等,具体操作如下所示:

    图 389定义过程调用请求方法
    点击“打开脚本页面”链接,选择“公共方法”和“新建方法”,定义新建方法名称,如下图所示:

    图 390定义回调的方法
    点击<编辑>,在弹出的对话框中点击<增加>,编辑JS方法的参数,双击参数可编辑参数名称,如下图所示:

    图 391编辑回调方法的参数
    选择参数列表中的一个参数,点击<删除>,删除该参数,如下图所示:

    图 392删除回调方法的参数
    其中<同步>和<显示进度条>按键分别代表Processor在传输过程中的参数配置,默认为“异步”和“显示进度条”。
     删除请求方法
    点击<删除>,在弹出的确认框中选择<确定>,即可删除已有的请求方法,如下图所示:

    图 393删除过程调用请求方法
     参数列表设置
    参数列表中存放通过Processor传输的参数,点击<增加>后弹出对话框,如下图所示:

    图 394选择自动调用的BO方法
    目前支持参数类型为:“pojo”,“pojoList”和“string”三种类型,其中“string” 类型默认“是否入参”的默认选项为“是”,并不需要设置“来源”。当选择“pojo”或“pojoList”时则需要开发人员选择“是否入参”(即是否将其作为参数手动通过Processor传输,一般选择“是”)和“来源”(即当前view文件所绑定的数据集,具体参见4.7.3中“数据集”部分),以“pojo”为例,如下图所示:

    图 395 增加Processor参数
    点击<确定>则会保存在参数列表中,如下图所示:

    图 396 Processor参数列表
    此时切换到脚本编辑器页面后即可在方法中通过“view.processor”调用该Processor,如下图所示:

    图 397 Processor在脚本编辑器中的使用
     依赖BO
    在UniEAP V4中,后台的方法主要是通过BO来实现。当设置过程调用关联某BO方法时,首先在依赖BO部分,点击<增加>,在弹出的窗口中,选择需要依赖的BO,具体操作如下图所示:

    图 398增加过程调用依赖的BO
    【注意】上图中“按来源过滤”包括“当前DC的BO”和“当前DC可见的BO”,这里做下说明,“当前DC可见对象”包括:当前DC可见的对象和当前DC所依赖的DC中可见的对象。关于如何设置DC依赖,请参见4.9.2小节内容。

    图 399增加过程依赖的BO
    选中依赖的BO列表中的内容,点击<删除>按钮,在弹出的窗口中选择<OK>,可以删除依赖的BO,如下图所示:

     图 400删除过程依赖的BO

     图 401删除过程依赖的BO

     增加BO方法
    点击“自动调用BO中的方法”中的“BO方法”的“选择按钮”,在弹出的窗口中,选择依赖的BO,在下拉列表下方的列表中选择依赖的BO方法,具体操作如下所示:

    图 402选择自动调用的BO方法

    图 403选择BO的方法
    选择方法后点击<确定>键即可,此时V4将通过所设定的BO方法自动生成关联。
    【注意】:当选择BO方法时,该方法的参数请务必和参数列表中的参数保持一致,否则会提示校验失败,如下图所示:

    图 404 BO方法与参数列表保持一致
    6.2.6.2 设置自动分页
     功能简介
    当请求为查询请求且要分页、计算总记录数时,无需再写分页查询的代码。如下图,勾选自动分页,可输入起始页数、每页数量,勾选是否要计算总记录数。配置完成后,就能够完成自动分页了。

    图 405 自动分页设置
     多数据源自动分页示例
    在实际项目开发过程中,经常用到分页查询。UniEAP V4提供了自动分页查询的功能。下面将以Grid为例介绍如何简单快速地实现自动分页查询。
    【注意】在项目中需要使用多数据源或分布式数据源的场景下还需要设置动态数据源,否则无法实现自动分页。打开patch中的applicationContext-dataSource.xml文件,具体设置如下:
    // 动态数据源Bean配置(id必须sessionFactory引用的dataSource保持一致)
    <bean id="dataSource" class="com.neusoft.unieap.core.dataSource.DynamicDataSource">
    //有几个数据源就配置几个
    <property name="targetDataSources">
    <map key-type="java.lang.String">
    <entry key="unieap" value-ref="UNIEAP" />
    <entry key="business" value-ref="BUSINESS" />
    </map>
    </property>
    //默认数据源
    <property name="defaultTargetDataSource" ref="UNIEAP" />
    </bean>
    // UniEAP自带的数据源
    <bean id="UNIEAP"
    class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    …………
    </bean>
    // 业务数据源配置
    <bean id="BUSINESS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    …………
    </bean>
     查询单个Grid
    假设要实现分页查询所有用户的功能。首先新建一个页面模型,使用组织机构中的用户表创建数据集,然后基于该数据集创建Grid控件。如下图所示。

    图 406创建Grid 控件
    编写DAO方法,关键代码如下:
    //DAO方法的返回值必须为QueryResult
    public QueryResult query() {
    String hql = "from User user";
    //如果是hql查询,请调用super.queryObjectsByPage方法
    //如果是sql查询,请调用super.query方法。
    //关于这两个api的详细介绍见本小节最后的附录。
    return super.queryObjectsByPage(hql, null);
    }
    编写BO方法,关键代码如下:
    //BO方法的返回值必须为QueryResult
    public QueryResult query() {
    return this.queryDAO.query();
    }
    定义分页查询的Processor方法,勾选自动分页,默认的起始页数为1,每页数量为10。可以根据业务需求自定义修改。本例使用默认值。

    图 407 定义分页查询请求方法
    编写查询回调方法,如下所示:
    //回调方法要使用view.grid.setDataStore方法给查询的Grid绑定DataStore
    view.grid.setDataStore("demoGrid",dc.getDataStore("result"));
    最后在页面的page load方法中调用该请求即可。如下所示:
    //在调用query方法前还可以通过设置view.processor.method.pageNumber和//view.processor.method.pageSize修改pageNumber和pageSize。method
    //为processor方法名。
    //例如:对于本例,可以设置view.processor.query.pageSize = 20
    view.processor.query();
    至此为止,分页查询所有用户的功能已开发完成,启动服务即可看到最终效果。
    【附录】API简介
    queryObjectsByPage
    说明:自动分页hql查询,无需传递页号和每页个数。(需在页面模型过程调用页勾选自动分页)
    参数:
    {String} queryString HQL查询语句
    { Object[ ]} parameters参数数组,若无参数,可传空值
    返回值:{ QueryResult } 查询结果
    例:
    String hql = “from User u where u.sex= ? and u.name like ?”;
    QueryResult queryResult = super.queryObjectsByPage (hql, new Object[ ]{“男”, “张三”});
    query
    说明:自动分页sql查询,无需传递页号和每页个数。(需在页面模型过程调用页勾选自动分页)
    参数:
    {String} sql SQL语句
    { Object[ ]} args 参数数组,若无参数,可传空值
    {Class} clazz 指定查询结果转换的Pojo类(可为Entity或DTO生成的Pojo类),若无法指定,可传空值,查询结果为map的list
    返回值:{ QueryResult } 查询结果
    例:
    // 无参数无class的情况
    String sql = “from user u”;
    QueryResult queryResult = super.query(sql);
    // 无参数有class的情况
    String sql = “from user u”;
    QueryResult queryResult = super.query(sql, User.class);
    // 有参数无class的情况
    String sql = “from user u where u.id= ?”;
    QueryResult queryResult = super.query(sql, new Object[ ] {“100”});
    // 有参数有class的情况
    String sql = “from user u where u.id= ?”;
    QueryResult queryResult = super.query(sql, new Object[ ] {“100”},User.class);
     查询多个Grid
    实际开发过程中有时会遇到一次查询获取多个Grid的场景,若多个Grid的分页信息完全一致(起始页数和每页显示数量相同),只需将BO方法的返回值改为BOContext(存放多个DAO方法返回的QueryResult对象),在成功回调方法中分别使用view.grid.setDataStore给每个Grid绑定DataStore。
    当多个Grid的分页信息不一致,例如一个每页显示10条记录,另外一个每页显示20条记录。这时,需要改造一下BO方法,如下所示:
    //BO方法的返回值为BOContext
    public BOContext query() {
    //通过PageUtil类提供的setPageNumber方法设置起始页数
    //通过PageUtil类提供的setPageSize方法设置每页显示记录数
    PageUtil.setPageSize(10);
    QueryResult userResult = this.queryDAO.queryUser();
    PageUtil.setPageSize(20);
    QueryResult unitResult = this.queryDAO.queryUnit();
    BOContext bc = new BOContextImpl();
    bc.put("user", userResult);
    bc.put("unit", unitResult);
    return bc;
    }


    6.2.7 使用脚本编辑器
    JavaScript脚本是组成前端页面的重要组成部分,因此,在UniEAP V4 Workshop的UI设计器中,我们提供了功能强大的脚本编辑器功能。脚本编辑器的界面如下图所示:
    图 408 脚本编辑器界面
    为了表述方便,我们可以将脚本编辑器界面粗略的分为四部分,上方的列表区,方法区,和功能区,以及下方的代码区。具体分布如下图所示:

    图 409 脚本编辑器界面区域分布
    在列表区中,我们可以选择公共方法,全局变量,page,引用的外部JS文件,以及该view(或viewc)下的所有控件。在列表区中,如果我们选中公共方法或者控件时,方法区中会有新建方法和已有方法的选项,供用户操作;如果我们选中全局变量,方法区中会出现编辑按钮供用户对全局变量进行编辑。功能区中有删除,查找和查看引用的外部JS文件三个按钮。删除按钮用来删除当前选中并且已经编辑过的方法,其它两个按钮会在后面的小节中介绍。
    6.2.7.1 快捷键的使用
    快捷键是脚本编辑器中实现快捷功能的一种方式,我们提供了多种快捷键,来方便用户使用,绝大部分快捷键的设置遵循Eclipse中Java编辑器的快捷键设置,使得用户不仅使用方便,而且不会改变用户原有的开发习惯。脚本编辑器中提供的快捷键有:
    1) Ctrl + O 快速大纲
    2) Alt + / 代码提示
    3) Shift + Ctrl + F 快速格式化
    4) Alt + 左/右 前进/后退
    5) Alt + 上/下 选中行上移/下移
    6) Ctrl + Z undo
    7) Ctrl + Y redo
    8) Ctrl + D 删除选中行
    9) Ctrl + / 将当前选中代码注释
    10)Ctrl + 鼠标左键 代码跳转
    11)Ctrl + A 全选
    12)Ctrl + C 复制
    13)Ctrl + V 粘贴
    14)Ctrl + X 剪贴
    15)Ctrl + S 保存
    16)Ctrl + F 查找
    17)鼠标双击 选中单词
    18)鼠标三击 选中行
    19)F11 关闭View文件
    6.2.7.2 自动代码提示
    脚本编辑器实现了强大的代码提示功能,通过“Alt + /”可以触发该功能。通过该方式,代码提示内容包括:
     全局变量(图标为 )
     公共方法(图标为 )
     JS,RIA内置对象(图标为 )
     外部JS方法(图标为 )
     命名空间(包括该页面和引用页面组件的命名空间,图标为 )
     代码自动完成模板中的内容(图标为 )
    在脚本编辑器代码区中,按下代码提示快捷键会出现如下图代码提示框:

    图 410 Alt + / 的代码提示功能
    另外我们还提供所有JS和RIA 内置对象的所有属性(图标为 )和方法(图标为 ),以及一些用法的说明,来方便用户使用。具体用法如下图所示:
    图 411 内置对象的代码提示

    对于命名空间,我们还提示该命名空间的全局变量和公共方法。当用户在脚本编辑器中输入某个命名空间时,会提示该命名空间下的全局变量和公共方法,具体用法如下图所示:

    图 412 页面主键的代码提示
    脚本编辑器还提供了一个相当强大的功能,就是对控件ID的自动提示。当我们在脚本编辑器中通过unieap.byId(String id)来操作控件的时候,脚本编辑器会提示该view(或viewc)下所有控件的id。具体用法如下图所示:

    图 413 控件id的代码提示
    不仅如此,脚本编辑器还支持对控件类型的智能识别。当用户通过unieap.byId(String id)方法,并选择了一个具体的控件时,脚本编辑器会根据用户选择的控件ID,自动判断控件类型,并给出相应的代码提示。具体用法如下图所示:

    图 414 智能判断控件类型的代码提示
    另外,脚本编辑器还支持对复杂控件内部对象的提示。例如对Grid控件的Manager进行提示,具体用法如下图所示:

    图 415 控件Manager的代码提示
    脚本编辑器还会对过程调用的方法进行代码提示。具体用法如下图所示( 为过程调用方法):

    图 416 过程调用的代码提示
    6.2.7.3 设置代码自动完成模板
    该脚本编辑器有自己的代码自动完成模板,帮助用户快速完成代码。在eclipse中点击“窗口”>“首选项”>“UniEAP Workshop”>“JS Template”菜单项,会出现如下对话框:

    图 417 代码自动完成模板
    在代码自动完成模板中,我们可以对现有模板进行添加,修改,删除,恢复到删除前状态,恢复到修改前状态,导入导出等操作。
    6.2.7.4 在脚本中搜索
    脚本编辑器支持对全局变量,公共方法的方法体,控件,page方法的方法体进行搜索。首先要将UI设计界面切换到脚本编辑器界面,点击功能区的 按钮,会弹出如下图的对话框,并进行搜索:

    图 418 搜索界面

    6.2.7.5 引用和查看外部JS文件
    脚本编辑器支持引用外部JS文件,并对符合代码注释规范的外部JS文件中的方法提供代码提示功能,对于不符合代码注释规范的外部JS文件中的方法不提供代码提示功能。下图列举出一个含有正确方法注释的外部JS文件:

    图 419 符合注释规范的外部JS文件
    下面就来介绍,如何将这个外部的test.js文件引入到项目中来。首先,我们要打开一个view(或viewc)模型,点击工具栏中的 按钮,就会弹出“资源引用”的对话框,点击“增加”按钮,选择引入的外部JS文件的正确路径,并且保存模型文件,就可以轻松的将外部JS文件引入到工程中来。然后打开脚本编辑器,在列表区中选择引用的外部JS文件,并在方法区中选择引用的外部JS文件的某个方法,那么该方法的方法体就会显示在脚本编辑器的代码区中,具体效果如下图所示:

    图 420 引用的外部JS文件在脚本编辑器中的展现
    为方便用户批量引用外部JS文件,脚本编辑器还支持对外部JSP文件的引用(在引入该JSP文件时,我们只读取<script>标签的内容,只要<script>标签的内容符合下图规范,就可以批量引入多个外部JS文件)。引用外部JSP文件的方法同引用外部JS文件,下图列举一个符合引用规范的外部JSP文件:

    图 421 符合引用规范的外部JSP文件

    脚本编辑器还支持对引用的外部JS文件进行查看。具体方法是:在脚本编辑器的列表区中选择引用的外部JS文件,此时点击功能区中“黄色铅笔”按钮 ,页面会自动跳转到引用的外部JS文件中。
    6.2.7.6 模型继承在脚本编辑器中的体现
    当用户新建一个view模型继承一个原有的view模型时,子模型会继承父模型中公共方法和page中的所有方法以及父模型的所有控件,并在脚本编辑器的方法区中出现“继承”的字样。当用户修改子模型继承父模型的方法后,子模型的该方法在方法区中会将原来的“继承”字样改为“覆盖”字样。对于子模型中新建的方法,该方法在方法区会出现“追加”的字样。下图,我们举了一个简单的例子,其中testView.view继承demoView.view:

    图 422 模型的公共方法显示效果
    6.2.7.7 全显示模式
    脚本编辑器支持全显示模式,所谓“全显示模式”即在脚本编辑器视图下可直接查看view或viewc文件生成的js脚本,在有即时查看js代码的需求下,不需要在view模型与js之间频繁切换,方便开发人员查看代码。并可通过点击“黄色铅笔”按钮 ,直接跳转到当前编辑方法所对应的js文件中的位置,如下图所示:

    图 423 脚本编辑器全显示模式按钮
    点击“黄色铅笔”按钮 后,跳转到全显示模式并定位到该方法,如下图所示:

    图 424 脚本编辑器全显示模式
    全显示模式仅提供展示功能,不能对该视图中的数据进行修改,并且全显示模式下支持“ctrl+鼠标左键”进行方法的跳转,通过点击方法名可重新跳回到脚本编辑器的对应方法或事件中。
    全显示模式也可通过直接点击左侧下拉框进入,如下图所示:

    图 425 通过下拉菜单进入脚本编辑器全显示模式
    6.2.7.8 常用API简介
    V4的view模型会将部分的源码翻译成RIA的代码,可以方便的完成JSP静态代码部分的转换,而动态的js脚本可以在脚本编辑器中来进行编写。在脚本编辑器中编写js代码的过程中,会使用大量的RIA代码。考虑到RIA的API组织稍显凌乱,故V4在其基础上对一些常用的API进行了封装,现通过使用场景依次对其进行介绍:
    23) view.form.setDataStore(id,store)
    解释:设置form对应的DataStore
    参数说明: id:对应Form控件的id
    store:用于初始化控件的dataStore
    场景举例: 修改人员列表中的某个人员信息时,需要把Grid当行的数据取出来并放入到对应的Form中,如下所示:

    图 426 点击Grid中的超链接

    图 427 将Grid选中行的数据放入到Form中
    要实现上述功能,可以通过如下的代码来实现:
    //获得Grid当前选中行的数据,以dataStore的格式进行封装
    var ds = view.grid.getRow("user_grid");
    //将Grid选中的数据绑定到Form上
    view.form.setDataStore("user_form",ds);
    可见,当想清空某个Form绑定的dataStore中的数据时,可采取如下方式:
    view.form.setDataStore("user_form",null);
    24) view.form.getDataStore(id)
    解释:设置form对应的DataStore
    参数说明: id:对应form控件的id
    场景举例:新增一个人员的时候,要把其Form的所有信息传递到后台,如下所示:

    图 428 Form中的相关人员信息
    当点击“保存”按钮时,要获取Form绑定的dataStore的内容,并向后台发送processor请求,代码如下:
    var ds = view.form.getDataStore("user_form");
    view.processor.saveUser(ds);
    25) view.form. setPropertyValue(id, propertyName, propertyValue)
    解释:设置form对应的DataStore的某个属性值
    参数说明: id: 对应form的id
    propertyName: 属性的名称
    propertyValue:属性值
    场景举例:当新增一个组织单元时,会为其Form中的名称字段设置一个初始值,如下所示:

    图 429 点击“新增”项为销售公司增加下级部门

    图 430 Form中“名称”项会默认添加一个值
    要修改Form中某个属性的值的代码功能如下所示:
    view.form.setPropertyValue("unit_form", "name", randomName);
    26) view.form.getPropertyValue(id,propertyName)
    解释: 获得form对应的DataStore的某个属性值
    参数说明: id:对应form的id
    propertyName:属性的名称
    返回值: 对应的属性值
    场景举例:新增一个用户的时候,需要判断Form中输入的账户是否已经存在,若存在则不允许持久化到数据库中。如下所示:

    图 431 对Form中“帐号”项进行校验
    此时需要向后台发送该属性的值校验数据库中是否已经存在,则要在“保存”按钮的事件中添加如下代码:
    var account = view.form.getPropertyValue("user_form", "account");
    view.processor.validateAccount(account);
    27) view.grid.setDataStore(id,store)
    解释: 设置Grid的绑定的dataStore的数据值
    参数: id :Grid控件的id
    store :绑定的dataStore的值
    场景举例: 在查询了所有用户后,要在用户列表中显示出来,如下所示:

    图 432 对Form中“帐号”项进行校验
    要实现该功能,在查询processor的成功回调中添加如下代码即可:
    var ds = dc.getDataStore("result");
    view.grid.setDataStore("user_grid",ds);
    可见,如果想清空Grid中的内容,可通过如下方式实现:
    view.grid.setDataStore("user_grid",null);
    28) view.grid.getDataStore(id)
    解释: 获得Grid控件绑定的DataStore
    参数: id:Grid控件的id
    返回值: Grid控件绑定的DataStore
    场景举例:在弹出的Dialog中,要将主页面的Grid中的内容原封不动的显示出来则需要获得主页面的Grid绑定的dataStore,代码如下所示:
    var gridDs = view.grid.getDataStore("user_grid");
    然后将gridDs作为参数传递给Dialog即可。
    29) view.grid.insertRows(id, store, index)
    解释: 向Grid中插入行(可插入多行数据)(单选和多选Grid均适用)
    参数: id: Grid控件对应id
    store : 插入行数据对应的store
    index: 插入的位置(从0开始),当不传该参数时,默认插入到表格末尾
    场景举例: 当新增了一个用户后,会将该用户自动的插入到用户列表的最后一行,如下所示:

    图 433 新增一个用户

    图 434 新增的用户自动插入到Grid的最后一行
    为实现该功能,在新增用户processor对应的成功回调中,添加如下代码即可:
    var ds = dc.getDataStore('result');
    view.grid.insertRows("user_grid",ds);
    30) view.grid.deleteRow(id,index)
    解释:删除Grid的选中行(适用于单选Grid)
    参数:id: Grid控件的id
    index: 待删除的行的下标(从0开始),当不传入此参数时,默认选择删除选中的行
    场景举例:当删除Grid列表中的一个用户的时候,会首先选中它所在的行,然后点击删除,删除成功后,要在Grid中将这行数据也删除,如下所示:

    图 435 删除Grid中的选中行

    图 436 删除成功后的效果
    要实现该功能,只需在删除人员的processor的成功回调中加入如下代码即可:
    view.grid.deleteRow("user_grid");
    31) view.grid.deleteRows(id,indexs)
    解释:删除Grid中选中的多行(适用于多选Grid)
    参数:id: Grid控件对应的id
    indexs: 待删除的Grid的行的下标构成的数组,不传递此参数时默认删除所有选中的行
    场景举例:当为某个管理橘色删除多个对应的人员时,需要用到多选的Grid,如下所示:

    图 437 为管理角色删除多个对应人员

    图 438 删除成功后的效果图
    要实现这个功能,需要在删除人员对应的processor的成功回调中执行下面的语句:
    view.grid.deleteRows("user_grid");
    这样就会删除所有选中的行的数据。
    如果想删除指定的某些行,可以这样实现:
    //删除第1行、第3行和第4行
    view.grid.deleteRows("user_grid",[0,2,3]);
    32) view.grid.updateRow(id,store,index)
    解释:更新Grid中的某一行
    参数:id : Grid控件对应的id
    store: 用来更新行的数据(以dataStore的方式封装)
    index: 待更新的行的下标(当不传时,默认更新选中的第一行)
    场景举例: 当需要修改某个用户的信息时,可以通过如下方式:

    图 439 点击超链接更新人员信息

    图 440 修改性别信息


    图 441 修改后的数据信息
    要实现这个功能,在修改用户信息的成功回调中,添加如下代码:
    var ds = dc.getDataStore('result');
    view.grid.updateRow('user_grid',ds);
    33) view.grid.getRow(id)
    解释: 获得Grid选中行的数据,并封装成dataStore的格式。(适用于单选Grid)
    参数: id :Grid控件对应的id
    index: 待获取的行的下标(不传的时候默认获取当前选中行)
    返回值:Grid选中行的数据(dataStore格式)
    场景举例:要修改某个用户的信息的时候,点击超链接会将该行对应的数据设置到一个Form控件上,如下所示:

    图 442 点击超链接弹出修改页面

    图 443 修改页面
    为了实现这个功能,只需要在点击超链接的事件里添加如下代码:
    var ds = view.grid.getRow("user_grid");
    得到这个ds将其设置为Form绑定的dataStore即可(调用view.form.setDataStore()方法)。
    34) view.grid.getRows(id,indexs)
    解释: 获得Grid选中行的数据,并封装成dataStore的格式。(适用于单选Grid)
    参数: id :Grid控件对应的id
    indexs : 待获取的行的下标构成的数组
    返回值:Grid选中行的数据(dataStore格式)
    场景举例:在多选的Grid中,如果想获取第1行、第3行和第4行对应的值,可通过如下方法:
    view.grid.getRows("user_grid",[0,2,3]);
    35) view.grid.getPropertyValue(id, propertyName, index)
    解释: 获得Grid中某指定行的某个属性值
    参数: id: Grid控件对应的id
    prpertyName :属性名
      index : 指定行的下标(不传时,默认为选中的行)
    返回值: 属性的值
    场景举例: 当要删除一个用户的时候,会获得该用户对应的id并传递到后台进行删除,其操作流程如下所示:

    图 444 选中一个用户并删除

    图 445 删除成功的页面
    在“删除”事件中,需要获得当前选中行的id属性值,并向后台发送processor请求,代码如下:
    var userId = view.grid.getPropertyValue("user_grid", "id");
    view.processor.deleteUserById(userId);
    36) view.grid.setPropertyValue(id, propertyName, propertyValue, index)
    解释: 设定Grid某行中某个属性的值
    参数: id: Grid控件对应的id
    propertyName: 属性名称
    propertyValue: 属性值
    index: 要设置属性值的行的索引,如不传的话默认修改当前选中行
    场景举例:当需要将Grid选中行的“帐号”属性值改为”wang-fan”时,可通过添加下面的代码实现:
    view.grid.setPropertyValue("user_grid", "account", "wang-fan");
    37) view.tree.setDataStore(id,store)
    解释: 为Tree控件绑定数据(注意:此方法只适用于全加载的Tree)
    参数: id: Tree控件的id
    store: Tree所需绑定的dataStore,需要符合树形结构
    场景举例:对于组织单元类型这样的一棵树,它是全加载的,在page-load发送完请求取得所有的数据后,在成功回调中只需要调用如下方法,树中的所有数据均会被绑定上:
    var ds = dc.getDataStore('result');
    view.tree.setDataStore("unitType_tree",ds);
    数据被绑定后,其显示效果如下所示:

    图 446 组织类型树的页面展示效果
    38) view.tree.deleteNode(id,node)
    解释:删除Tree控件中的node节点
    参数:id: Tree控件的id
    node: 待删除的树中的节点
    场景举例: 在组织机构树中,可以删除某个节点,如下所示:

    图 447 删除“国际事业部9”这个树节点

    图 448 删除成功后的效果
    在删除节点的成功回调中,需要在Tree控件中将该结点删除,调用如下方法即可:
    //删除右键选中的节点node
    view.tree.deleteNode("unit_tree",node);
    39) view.tree.deleteNodes(id,nodes)
    解释: 删除Tree中的多个节点
    参数: id: Tree控件的id
    nodes: 待删除的节点构成的数组
    场景举例: 对于一个复选树控件,如果选中了多个节点后要将这些节点删除,即可通过如下代码实现:
    //得到所有复选框中选中的节点
    var selectedNodes = unieap.byId("unit_tree").getSelectedNodes();
    //删除这些选中的节点
    view.tree.deleteNodes("unit_tree",selectedNodes);
    40) view.tree.updateNode(id,node,store)
    解释: 更新Tree中的某个节点
    参数: id: Tree控件的id
    node: 待更新的节点
    store: 用于更新节点的dataStore
    场景举例:更新组织机构树中的某个节点,如下所示:

    图 449 修改前的组织单元信息

    图 450 修改后的组织单元信息
    点击保存按钮后,选中节点所对应的数据也会发生变化,如下所示:

    图 451 修改后节点的数据值发生了变化
    要实现修改节点的功能,只需要在processor对应的成功回调中添加如下代码即可:
    //获得修改后的数据
    var ds = dc.getDataStore("result");
    //获得当前Tree中选中节点
    var node = unieap.byId("unit_tree").getCurrentNode();
    //修改Tree中对应的节点
    view.tree.updateNode("unit_tree", node, ds);
    41) view.tree.getPropertyValue(id,node,propertyName)
    解释: 获得Tree中某一节点对应的属性值
    参数: id: Tree控件的id
    node: 待获取属性值的节点
    propertyName: 待获取的属性值
    返回值: 属性值
    场景举例: 当要删除某个组织单元的时候,需要获取待删除节点的id属性传到后台,其效果如下:

    图 452 右键删除树中某一节点

    图 453 删除成功后的效果
    在点击“删除”菜单项的事件中,需要获取当前选中节点的id属性,代码如下:
    //获得待删除节点的id属性
    var nodeId = view.tree.getPropertyValue("unit_tree",currentNode,"id");
    view.processor.deleteUnitById(nodeId);
    42) view.tree.setPropertyValue(id, node, propertyName, propertyValue)
    解释: 设置Tree中某个节点的某个属性的值
    参数: id: Tree控件的id
    node: 待修改属性的节点
    propertyName: 待修改的属性名
    propertyValue: 待修改的属性值
    场景举例: 当修改了某个组织单元节点的属性值后,要在树中对其进行更新,如仅修改了一个组织单元节点的name属性值,则可通过如下代码同步更新树中相应的显示内容:
    view.tree.setPropertyValue("unit_tree", currentNode, "name", "事业部");
    43) view.tree.getAllNodes(id,isContainRoot,node)
    解释:获得node下的所有已经渲染出的所有子孙后代节点(即获得以node为根的子树的所有节点)
    参数:id: Tree控件的id
    isContainRoot: 返回的结果集中是否包含当前node节点,true代表包含,false代表不包含
    node: 当前节点
    返回值:所有node子孙节点构成的数组
    场景举例:当在程序要获得以node为根的所有子孙节点时,可调用如下方法:
    //获得当前节点的全部已渲染出的子孙节点
    var nodes = view.tree.getAllNodes("menuTree",false,node);
    22. view.tree.addChildren(id,node,store,configMap)
    解释: 为node节点添加相应的子节点(适用于懒加载的树)
    参数: id: Tree控件的id
    node: 要添加子节点的节点
    store: 待添加的子节点
    configMap: 配置参数Map,如不传此参数默认使用树中配置的参数。
    这里需要对configMap参数进行详细的解释,此参数适用于异构懒加载树的场景。在配置树的相关属性时,要制定Tree的相关属性对应的dataStore的属性名,如下所示:

    图 454 Tree控件的id、label、parent属性的配置
    但如果树中不同层次的节点来自于不同的dataStore的时候,无法为其设置一个统一的名字,此时需要在程序中动态切换这几个参数的配置,用来指定这几个关键属性的名称,如下所示:
    configMap = {
    id : 'id',
    label : 'title',
    parent : 'parentId'
    });
    此时即代表树的id为dataStore中id属性,label为dataStore中的title属性,parent为dataStore中的parentId属性。
    需要注意的是,只有在异构切换树中节点的dataStore时才需要使用该参数,否则在Tree的属性视图中进行相应的配置即可。
    场景举例:异构懒加载树
    有的时候,树的不同层次的节点可能来自于不同的dataStore,如下图所示:

    图 455 异构懒加载树
    这是一棵懒加载的树,其中“迭代”为虚根,第一层节点绑定的是sprint dataStore,而第二层节点绑定的是backlog dataStore。在sprint的dataStore中,几个关键属性的名称为id、title、parentId,而在backlog的dataStore中,几个关键属性的名称为id,name和sprintId。在Tree控件中配置的相应属性为id,label,parentId,可见,如何将不同的dataStore的相关属性统一是能否实现异构加载树功能的关键,此时方法中的参数configMap就起到了至关重要的作用。
    在查询sprint节点的成功回调中,编写如下代码实现加载出第一层节点的功能:
    //得到查询返回的dataStore
    var ds = dc.getDataStore('result');
    //得到当前Tree的虚根节点
    var root = unieap.byId("isomerismTree").getRootNode();
    //为Tree添加第一层节点
    view.tree.addChildren("isomerismTree", root, ds, {
    id : 'id',
    label : 'title',
    parent: 'parentId'
    });
    当展开第一层的某个节点的时候,会去加载该sprint节点下的所有backlog节点,在该查询方法的成功回调中,需要编写如下代码:
    //得到查询返回的dataStore
    var ds = dc.getDataStore('result');
    //为当前展开节点添加第二层节点
    view.tree.addChildren("isomerismTree", currExpandNode, ds, {
    id : 'id',
    label : 'name',
    parent: 'sprintId'
    });
    这样即可成功的构造出一颗异构的懒加载树。

    6.3 异常框架
    用户需要自定义业务异常码,该文件存放在SC或DC的“content/exception/”(如该文件夹不存在则需要用户手动新建)文件夹中,为”*.properties”格式。该文件命名由用户决定,并支持国际化。如下图所示:

    图 456 异常码存放位置
    其中该文件的”_zh_CN”标识该文件的国际化信息。该文件的内容为“key=value”格式,示例如下:
    ……
    EAPTECHSECURITY0001=业务角色名称{0}已经存在,请重新输入。
    ……
    [注意]:示例中的”{0}”代表第一个参数的位置,该参数将通过构造异常对象时传入。
    当用户需要抛出业务异常时,仅需在需要弹出异常的地方加入如下代码:
    throw new UniEAPBusinessException("EAPTECHSECURITY0001",new Object[]{busiRole.getName()});
    即代表在此处抛出业务异常码为EAPTECHSECURITY0001的异常,并且参数为” busiRole.getName()”。效果如下所示:

    图 457 异常码存放位置
    当用户需要拓展异常框架类时需要继承UniEAP业务异常框架的实现基类:UniEAPBusinessException。
    6.4 国际化
    6.4.1 概述
    国际化是创建适合于国际市场的软件过程,它能支持多个国家和地区的本地化应用,使得应用软件能够适应多个地区的语言、数字、货币、日期等习惯。在编码和用户界面设计时,使用适当的 API 来处理本地语言数据,确保产品是为本地语言功能设计的。
    设计一个国际化的应用软件应考虑下面这些特性:
    1.对于程序中本地信息敏感的数据(日期、货币等)能够根据当前所在的国家或地区的文化习惯进行显示;
    2.对于文本元素(错误提示信息,状态信息等)不是直接写在应用程序中,而是存储在应用程序外部的资源文件中,在应用程序中通过程序代码来动态获得这些数据;
    3.无需修改和重新编译程序就能支持新的国家或地区的用户。
    6.4.2 模型文件国际化
    6.4.2.1 配置及抽取国际化数据
    首先对将要使用的实体模型(Entity)进行国际化,保证多个view使用同一实体模型生成数据集时,国际化资源文件相同。
    6.4.2.1.1 Entity模型文件国际化
    Entity模型文件的国际化可以看作对View模型数据集以及后台校验信息的国际化,可保证应用同一Entity模型文件的数据集(模式控件)采用相同的国际化数据,以此来保证国际化数据的统一性。
    用户需要在Entity模型上右键-<国际化>-<抽取国际化>即可对实体模型中的Label及校验信息进行抽取,如下图所示:

    图 458 Entity模型文件国际化抽取
    与view模型文件不同的是抽取后的key将直接显示在Entity模型文件中,不对其进行转义,抽取后Entity文件如下图所示:

    图 459 Entity模型文件国际化结果
    国际化文件存放在当前DC的国际化文件中,具体目录如下图所示:

    图 460 国际化文件存放目录
    对已国际化的Entity生成的数据集,使用该数据集生成的模式控件不再需要再次进行国际化。使用同一Entity文件生成的数据集采用同一套国际化数据。
    【注意】:Entity模型文件的国际化需要优先于View模型文件,保证View模型使用该 Entity文件生成的数据集(主要服务于模式控件)是已国际化形式。
    6.4.2.1.2 抽取view模型国际化数据
    抽取指的是将view中可能需要国际化的部分抽取到国际化文件中,value为设计页面设定的控件属性值(例如:button的label属性),key首先由工具生成全局唯一的key,允许用户在2.3.1图中显示的页面进行修改(但由于要尽可能保证key在全局中的唯一性此做法并不推荐)。

     抽取模型国际化数据
    右键点击需要抽取的view文件,点击<国际化>-<抽取国际化>,如下图所示:

    图 461 View模型国际化文件抽取
    弹出dialog中对待抽取控件属性进行选择,并可根据用户需要修改可抽取的key,但对已经存在的key不允许进行修改,如下图所示:

    图 462 国际化抽取对话框(1)
    点击<OK>后会自动对选中的信息进行国际化。
    【注意】如果国际化信息图标为 即表示该条数据已被抽取,不能再次抽取,如下图所示:

    图 463 国际化抽取对话框(2)

    国际化成功后,结果将保存在当前DC -<content>-<i18n>-<package_zh_CN.properties>中,如下图所示:

    图 464 国际化文件存放目录
    package_zh_CN.properties文件内容如下图所示:

    图 465 国际化文件内容

     批量抽取模型国际化数据
    右键点击view模型文件夹,点击<国际化>-<抽取国际化>,自动将所有view模型中可抽取的属性进行抽取,并根据首选项配置语言放置在view所在DC对应的国际化文件中,文件存放位置见上节:

    图 466 国际化文件批量抽取
     配置模型中控件的国际化数据
    当用户需要引用已有的国际化文件时,可对控件单独配置国际化信息,以Button为例,点击需要国际化的属性(Button控件只有label属性支持国际化):

    点击label属性后,属性框内出现放大镜图标,点击后如图所示:


    图 467 选择国际化信息
    第一个Combo如下图所示:

    图 468 国际化文件引用位置
    用户可通过选择对应的国际化文件来指定不同的国际化数据,即该Button可使用当前DC、当前SC、依赖的DC和依赖的SC中存放的已有国际化数据(.properties文件中已有数据),以当前DC为例,选择<当前DC>时,用户可在下方的Table中选择需要指定的国际化数据,例如,需要指定该Button为<编辑>所对应的国际化数据,则选择Table中<编辑>所在行,如下图所示:

    图 469 选择国际化信息
    点击<确定>则该按钮将使用<编辑>的国际化数据,如下图所示:

    图 470 国际化后效果
    6.4.3 撤销模型文件国际化
    对于已经国际化的模型文件,在对应右键菜单中提供撤销国际化的功能,类似于上节的抽取操作,在模型文件(或文件夹)上右键-<国际化>-<撤销国际化>,即可撤销该模型的所有国际化信息,还原到未国际化状态,如下图所示:

    图 471 撤销国际化
    [注意]:请在撤销国际化前确认该模型文件中的KEY存在于所在工程(DC/PATCH)中的“content/i18n/properties_zh_CN.properties”(以中文举例,国际化资源文件后缀取决于使用语言)。
    6.4.4 JS文件国际化
    该国际化方案应用了dojo的国际化功能,通过dojo封装的方法对控件进行国际化。
    对于需要进行脚本国际化的view模型文件,请在view的概要视图勾选<支持脚本国际化>,如下图所示:

    图 472 支持脚本国际化
    该属性会在抽取国际化的同时自动勾选,类似的,在撤销国际化时自动取消勾选,防止生成冗余代码。
    国际化资源文件配置结束后,可在View模型的JS脚本中输入相应国际化代码,对于key为”I18N_KEY”的国际化片段以view.i18n(“I18N_KEY”)进行转换,如下图所示:

    图 473 JS脚本国际化

    6.4.5 代码表国际化(CodeList)
    Codelist表中的LANGUAGE字段负责保存代码的国际化信息,一个代码有几种语言的信息就在表中对应几条记录。用户对代码表做国际化时仅需对已有数据进行复制,并修改新数据的“LANGUAGE”字段即可,如下图所示:

    图 474 代码表
    图中英文数据即通过复制中文数据并修改LANGUAGE字段为“en_US”来达到CodeList的国际化。


    第7章 组织机构安全使用指南
    7.1 组织机构
    7.1.1 基本概念
    7.1.1.1 用户
    用户包括业务用户和管理员。在用户管理中不做区分,当一个用户属于业务角色时,这个用户就属于业务用户,当一个用户属于管理角色时,这个用户就是管理员。一个用户既可以属于业务角色也可以属于管理角色。一个用户可以同时属于多个业务角色,但最多只能属于一个管理角色。
    另外,用户还可以隶属于组织单元和职位。
    7.1.1.2 组织单元
    目前组织机构只支持单维度组织机构树。组织单元支持分级管理,分为两种情况,一种是类似于V3的做法,支持管理角色可管理的组织单元是离散的;另外一种情况,是支持管理角色可管理的组织单元可以级联下级。
    7.1.1.3 职位
    职位隶属于组织单元。职位不分上下级。隶属于职位下的用户必须隶属于其所属组织单元。
    7.1.1.4 组织单元类型
    组织单元类型是一个树形结构的数据,该数据根据业务的不同需要对其进行维护。用于组织单元信息维护。
    7.1.2 当前登录用户
    在业务系统中,需要动态获取当前登录用户信息,获取方法如下:
    com.neusoft.unieap.core.context.properties.User currUser = UniEAPContextHolder.getContext().getCurrentUser();
    通过当前登录用户可以获取到用户帐号、名称等用户信息。另外还可以获取用户所属的角色。其中,角色包含id、name和type属性,type属性的值有几种,分别是“busiRole”、“superAdminRole”、“secAdminRole”、“orgAdminRole”、“unit”、“station”等。
    具体接口及参数可以参看javadoc。
    另外,通过UniEAPContextHolder还可以存放业务系统中线程相关的上下文数据,调用方式如下:
    UniEAPContextHolder.getContext().addCustomProperty(key,value);
    数据获取方式如下:
    String value= UniEAPContextHolder.getContext().getCustomProperty(key,value);
    7.1.3 扩展属性
    在v3中扩展属性在extinfo.xml文件定义,在v4中扩展属性的定义是通过数据库表来实现的,表的名称为UP_EXT_ATTR_DEFINE。在这个表建库脚本中中有一些样例数据供参考,可以参照着进行配置。
    在业务系统中,增加扩展属性(可以是针对用户和组织单元),只需要如下几个步骤:
    在UP_EXT_ATTR_DEFINE表中维护扩展属性数据;
    在扩展属性表中增加对应的字段;
    重启服务,进入对应的管理界面就能看到效果。
    为了方便配置,对表中定义的属性做下简单的描述。
    表格 1 UP_EXT_ATTR_DEFINE
    名称 类型 可为空 注释
    ID VARCHAR2(32) N Id,目前手动输入,确保唯一
    ATTR_NAME VARCHAR2(32) N 属性名称,可以根据业务含义任意定义
    CONTROL_TYPE VARCHAR2(32) N 显示控件类型,对应于ria的form控件类型
    LABLE VARCHAR2(64) N 显示标签,在页面上显示的label
    READ_ONLY CHAR(1) N 是否只读
    REQUIRED CHAR(1) N 是否必填
    MAX_LENGTH NUMBER(3) Y 显示最大长度,控制页面上输入域中最大的输入长度
    MIN_LENGTH NUMBER(3) Y 显示最小长度,控制页面上输入域中最小的输入长度
    DECIMAL_PRECISION NUMBER(1) Y 浮点类型精度
    OBJ_TYPE VARCHAR2(16) N user、unit、station等
    ROW_SPAN NUMBER(1) N 跨行数
    LABEL_COL_SPAN NUMBER(1) N 标签跨列数
    SORT NUMBER(2) N 显示顺序
    CODE_TYPE VARCHAR2(64) Y datastore名称,用户codelist
    ICON_CLASS VARCHAR2(32) Y 图标CSS类,用于TextBoxWithIcon
    COLUMN_NAME VARCHAR2(64) N 扩展属性字段名,与数据库表中的定义要一致
    COLUMN_TYPE VARCHAR2(32) N 扩展属性字段类型,包括“Date”、“String”以及“Number”等
    TABLE_NAME VARCHAR2(32) N 扩展属性表名
    VALUE_COL_SPAN NUMBER(1) N 输入域跨列数
    DISPLAY_STYLE VARCHAR2(16) Y 显示风格,有两种应用场景:一是用于下拉框,默认值为“list”,另外还可以配置成“multi”或者“table”;第二种情况是用于TextBoxWithIcon的隐藏域,这时该属性对应的值为“none”
    DIALOG_WIDTH NUMBER(4) Y dialog宽度,单位为px,用于TextBoxWithIcon
    DIALOG_HEIGHT NUMBER(4) Y dialog高度,单位为px,用于TextBoxWithIcon
    CREATED_BY VARCHAR2(32) Y 创建人
    CREATION_DATE DATE Y 创建时间
    LAST_UPDATED_BY VARCHAR2(32) Y 修改人
    LAST_UPDATE_DATE DATE Y 修改时间
    7.1.4 事件监听
    业务系统根据业务需要,可以监听的事件目前只有一个:UserDeleteEvent。用于监听用户删除操作,监听的方式可以参照安全中相关内容。
    7.2 安全
    7.2.1 基本概念
    7.2.1.1 业务类角色
    具有业务职能的人员集合。
    业务类角色包括业务角色、组织单元、职位。
     业务角色
    业务角色间不具有上下级关系,管理角色可以对其进行分级管理。
     组织单元
    作为一个人员的集合,也可以对其进行授权,管理角色可以对其进行分级管理。
     职位
    作为一个人员的集合,也可以对其进行授权。
    7.2.1.2 管理角色
    具有管理职能的人员集合,管理角色间具有上下级关系。对于一个系统,所有的管理角色可以构成一棵管理角色树。
    管理角色主要分为三类:超级管理角色、安全管理角色和组织管理角色。
     超级管理角色
    即“adminRole”,类型为“superAdminRole”,它是整个管理角色树的树根,是顶级管理角色。
     安全管理角色
    是管理角色树的一个分支,顶级安全管理角色是“adminRole”的子节点。其角色类型为“securityAdminRole”,负责菜单授权等权限相关操作。
     组织管理角色
    是管理角色树的一个分支,顶级安全管理角色是“adminRole”的子节点。其角色类型为“orgAdminRole”,负责组织机构管理相关操作。这个管理角色类型当业务系统中管理角色职责划分不是特别细的情况下,可以去掉。相关操作有安全管理角色来担当。
    7.2.1.3 可管理
    “可管理”是针对操作人员属于管理角色来说的,在阅读本章过程中您经常会看到类似于“可管理的组织单元”、 “可管理的业务角色”这样的短语,在这里解释一下其中“可管理”一词的含义:
    当用户以管理角色身份登录系统后,不同权限的管理角色看到的组织机构数据不同,能够管理的组织机构数据也是不同。“可管理”是指可以对组织机构数据进行增加、删除和修改操作。
    7.2.1.4 分级管理
    分级管理”是针对操作人员属于管理角色来说的,“分级管理”的对象包括组织机构、业务角色以及管理角色本身。含义是一个管理角色只能管理他可管理的组织机构、业务角色以及管理角色数据,不能越级管理。
    为了说明分级管理的含义,以管理角色管理为例:假设当前操作的管理角色为A,A的一个直接下级管理角色为B,B的一个直接下级管理角色为C。当以A身份登录系统并进入管理角色管理页面后,能够看到B,但不能看到C。能看到既能管理,即A可以对B其进行删除和修改操作。A也可以创建新的管理角色,新创建的管理角色对于A来讲是可管理的。
    7.2.1.5 级联回收
    级联回收功能是针对操作人员属于管理角色来说的。
    为了说明级联回收的含义,假设当前操作的管理角色为A,A的一个直接下级管理角色为B,B的一个直接下级管理角色为C,系统中存在一个资源为D。假设A已经把D的管理权限分配给B,B也已经把D的管理权限分配给C。
    当A删除B对D的可管理权限时,C对D的管理权限也同时被删除,这就是级联回收的含义。
    7.2.2 资源权限
    7.2.2.1 菜单权限
    菜单作为用户进行业务操作的入口是系统中最普遍、最重要的资源。由于不同的用户在实际工作中有不同的职责,所以他们使用系统进行的业务操作也各有异同。对菜单进行授权不仅能确保每个业务功能仅能被合适的用户操作,而且能降低用户使用系统的复杂度。
    菜单权限有两种类型,分别是“可使用”和“可分配”。
     可使用
    “可使用”即可访问,用户登录系统以后可以在菜单导航条或菜单树上看到相应的菜单项,并且可以通过点击该菜单项进入相应的页面进行业务操作。这种权限类型适用于各种角色。“可使用”的菜单对象对于管理角色来说是管理菜单,对于业务类角色来说是业务菜单。
     可分配
    “可分配”权限只针对管理角色,即可以分配给下级管理角色的菜单权限。用户登录系统以后可以在指定的操作页面上将菜单分配给下级角色。“可分配”的菜单对象是业务菜单。
    “可使用”和“可分配”是两种不同的权限类型,它们之间没有必然的联系。一个管理角色对于菜单A有“可分配”权限,但不一定有“可使用”权限,反之亦然。
    7.2.2.2 页面权限
    用户对某一菜单用“可使用”权限之后,就可以到菜单对应的页面进行业务操作,但是往往还会存在粒度更细的资源控制需求。例如,在一个输入个人信息的页面中,除了包含人员的基本信息外,还包含工资信息。可以操作这个页面的用户包括业务角色A和业务角色B。其中业务角色A,可以管理用户的基本信息,但工资作为敏感信息,只有业务角色B才能对其进行维护。在这种应用场景下,“工资”作为页面上的一个输入域就需要对其进行权限控制。
    页面权限只适用于业务类角色。
    7.2.2.3 权限类型
    作用在输入组件上的权限类型包括:
     只读
    只读权限可以作用于ria的所有form控件类型以及Grid(含xGrid)控件类型,还包含html中的image控件类型。
     隐藏
    隐藏权限可以作用于所有的ria控件类型。
    在对用户不做页面控件授权的默认认情况下,用户拥有对控件的完全控制权限。
    7.2.2.4 特性说明
    页面权限有两个特性需要做下说明:
     权限取最小
    对于一个用户来说,如果分别属于业务角色A和业务角色B,其中业务角色A对某个页面上的控件X被授予只读权限,业务角色B对该页面上的控件X被授予隐藏权限,那么这个用户访问该页面的时候,对控件X 的页面权限是隐藏,也就是取最小权限。
     支持分级
    页面资源权限与菜单资源权限类似,对于管理角色来说也支持分级管理。分级管理规则与菜单类似,暂不做详细描述。
    7.2.3 帐号锁定踢出
    在我们默认的组件中,通过修改security dc的applicationContext-security.xml文件中的accountPolicyService bean中的属性改变设置。
    表格 2 accountPolicyService bean属性介绍
    属性 值类型 说明
    accountLocked true/false 是否启用帐号锁定。
    ipLocked true/false 是否启用IP锁定。
    failedCount 整数 帐号/IP锁定前,可以错误登录的次数。
    lockedTimeInterval 整数 帐号锁定的时间间隔,值为整数,单位是分钟。
    accountKicked true/false 是否启用帐号踢出。
    7.2.4 验证码
    在我们默认的组件中,通过修改security dc的applicationContext-security.xml文件中的jcaptchaConfig bean中的属性改变设置。
    表格 3 jcaptcha节点属性及子元素
    属性/子元素 值类型 说明
    enabled true/false 是否启用验证码。
    acceptedChars true/false 自定义配置是否生效。默认“true”,表示自定义配置生效,false表示自定义配置无效,继续使用默认实现。
    minWordLength 整数 验证码最小长度
    maxWordLength 整数 验证码最大长度
    minFontSize 整数 验证码最小字号
    maxFontSize 整数 验证码最大字号
    bgWidth 整数 验证码背景图片宽度
    bgHeight 整数 验证码背景图片高度
    textColor java.awt.Color的常量(WHITE、YELLOW等)或者
    RGB值(211, 229,243) 验证码字体颜色
    bgColor 同上 验证码背景基色,真正的背景色是基于该基色混淆出来的。
    7.2.5 在线用户
    在默认的组件中,通过修改在security dc中的applicationContext-security.xml文件中的onlineUserConfig bean中的属性改变设置,对于在线用户功能来说只有一个是否启用的设置。配置如下所示:
    <bean id="onlineUserConfig" class="com.neusoft.unieap.techcomp.security.onlineuser.OnlineUserConfig">
    <property name="enabled" value="true"/>
    </bean>
    在线用户信息保存在UP_SEC_ONLINE_USER表中。
    另外,通过管理控制台应用中的“安全管理”-》“在线用户查看”菜单可以查看在线用户信息。
    7.2.6 非正常登录请求
    在某些应用场景下,在没有输入用户名、密码进行登录情况下,向应用服务器发送请求。常见的有web service、跨应用访问页面。在这种场景下,需要在请求后面拼上用户名和密码,样例如下:
    http://10.4.46.16:8080/framework/techcomp/org/user-view.jsp? eap_username=YWRtaW4.&eap_password=MQ..
    其中,eap_username和eap_password就是用户的帐号和密码,在这里,用户名(admin)和密码(1)是经过转码处理之后的。
    7.2.7 Session过期
    当用户Session过期后,如果继续访问页面系统默认会弹出登录dialog。Session过期对应的页面是/techcomp/security/relogin.jsp,可以通过patch工程对该页面进行修改。
    7.2.8 菜单授权
     菜单投票类:当一个用户通过角色授权对某个菜单A没有访问权限,如果该用户在浏览器的地址栏中输入菜单A的URL地址。
    7.2.9 事件监听
    业务系统根据业务需要,可以监听的事件包括如下几个:
     登录成功;
     登录失败;
     用户登出;
    首先在Spring配置文件中增加事件监听的bean,类似于下面的形式:
    <bean id="applicationListener" class="com.neusoft.unieap.***.ApplicationListener"/>
    监听器中的代码实现,类似于如下形式:
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    public class ApplicationListener implements ApplicationListener {
    public void onApplicationEvent(ApplicationEvent event) {
    if(event instanceof SuccessfulAuthenticationEvent) {
    SuccessfulAuthenticationEvent successfulAuthenticationEvent = (SuccessfulAuthenticationEvent)event;
    System.out.println("Received:================successful!!!!");
    }
    if(event instanceof UnsuccessfulAuthenticationEvent){
    ……
    }
    if(event instanceof LogoutEvent){
    ……
    }
    }
    }
    业务系统中,需要监听哪个事件就增加对哪个事件的判断,并加上对应的处理。
    7.3 管理控制台
    7.3.1 初始授权
    初次启动应用,用admin/1登录系统后显示如下页面:

    图 475 初次登陆后的页面
    此时,系统中admin用户对管理控制台只有对“安全角色”-》“安全管理角色”菜单有权限。
    点击“安全管理角色”页面中的“可用菜单”tab页,为“超级管理员”角色授予可使用的菜单权限,如下图所示:

    图 476 “安全管理角色页面
    一般情况下,选中管理控制台中的所有菜单,然后点击保存。这样,超级管理角色将对管理控制台中的所有菜单有访问权限。
    用admin/1重新登录系统,页面如下所示:

    图 477 再次登陆后的页面
    7.3.2 组织单元维护
    点击“组织机构-》组织单元管理”菜单,当初次访问这个页面时,没有组织机构树,此时显示的页面如下:

    图 478 组织单元管理页面
    点击“组织单元树”titlepane中的“新增”按钮,增加根组织单元。然后,显示的页面如下:

    图 479 增加组织单元
    一个组织机构树只有一个根节点,如果想增加下级组织单元,选中父组织单元,右键,点击菜单中“新增”按钮,增加下级组织单元。
    7.3.3 职位管理
    点击“职位管理”,页面如下所示:

    图 480 职位管理页面
    选中要增加的组织单元,在右侧“职位列表”区域新增职位,在“用户列表”区域为职位关联用户。
    7.3.4 组织单元类型
    如果系统中需要有组织单元类型,需要先在“组织单元类型”页面维护组织单元类型数据,然后用于在组织机构维护做选择。
    7.3.5 用户维护
    点击“用户管理”菜单,显示的页面如下:

    图 481 用户管理页面
    系统默认带“admin”用户,可以通过“用户列表”titlePane区域的“新增”按钮增加用户,修改用户通过grid中“帐号”中的超链接对用户信息进行修改。
    7.3.6 管理角色
    在v4中的管理角色分为安全管理角色和组织管理角色,如果没有特别需求通常情况只要有安全管理角色就可以。组织管理角色是在业务系统需要支持三员分离的情况下才行。在不需要组织管理角色的场景下,管理控制台“安全管理”中的“组织管理角色”菜单可以删除。
    下面针对“安全管理角色”的用法做下简单的说明。
    点击“安全管理”-》“安全管理角色”菜单,显示如下页面:

    图 482 安全角色管理页面
    默认情况下存在一条“超级管理员”的安全管理角色数据,这个管理角色也默认关联一个帐号为“admin”的用户。
    安全管理角色的设计思想与v3中的管理角色基本相同,都是分级管理,每一层只能管理它的直接下级。“超级管理员”角色略有特殊,它除了能管理其直接 管理角色外,还可以管理它自己,可以对其本身及其关联的用户进行维护。不同的是,在v4下显示的安全管理角色树是一棵完整的树,但对于不可管理的数据在树上是灰显的。
    安全管理角色的增加和删除操作,都是通过右键管理角色菜单来进行。
    在“角色维护”tab页可以维护管理角色数据,并为其关联用户和删除用户。
    在“可用菜单”tab页可以为选中的管理角色授予菜单可使用权限(与v3类似)。
    在“可分配菜单”tab页可以为选中的管理角色授予菜单可分配权限(与v3类似)。
    在“可授权组织范围”tab页中,为管理角色授予其可管理的组织范围,这里通过双checkbox来实现,除了可以通过树节点后面的checkbox为管理角色分配离散的可管理组织单元,也可以通过选择树节点的前面的复选框进行级联下级的选择。
    在“可管理业务角色”tab页中,为管理角色分配可管理的业务角色(与v3类似)。
    7.3.7 业务角色
    点击“安全管理”-》“业务角色管理”菜单,进入业务角色管理页面,页面如下所示:

    图 483 业务角色管理页面
    默认情况下,没有业务角色数据。
    在“业务角色列表”中可以为增加、删除和修改业务角色数据。增加和删除通过titlePane上的按钮来进行,修改操作通过点击“角色名称”上超链接来做。
    通过在右侧的“用户列表”tab页为业务角色关联用户。
    通过在右侧的“应用菜单授权”tab页为选中的业务角色授予菜单的访问权限。
    在“应用菜单授权”tab页中支持页面授权。
    7.3.8 组织角色授权
    组织角色授权是指对组织单元、职位进行授权,如果业务系统中需要支持对组织单元和职位授权则需要通过访问“安全管理”-》“组织角色授权”菜单来做。
    在这里支持页面授权。
    7.3.9 页面授权
    以业务角色为例,对页面授权的大致用法做下简单的说明。
    在workshop中打开需要做页面授权的view模型,并切换到“概要”页面,选中“支持页面授权”复选框,然后保存view模型。
    然后,点击“安全管理”-》“业务角色管理”菜单,选中要授权的角色,并选中“应用菜单授权”tab页,选中要做页面授权的菜单,然后点击页面右上角的“页面授权”按钮,然后弹出授权页面,如下图所示:

    图 484 页面权限管理页面
    可以对页面上的控件进行页面授权。
    授权之后,更换登录用户,并访问相应菜单,即可以看到页面授权的效果。
    另外,在我们默认的组件中,通过修改在security dc的applicationContext-security.xml文件中的pageAuthConfig bean中的属性改变可以进行页面权限设置的控件类型,默认情况下所有类型。具体情况可以根据业务需要进行修改。
    需要说明的是,业务中如有对applicationContext-security.xml的扩展则需要修改扩展后的对应bean的配置。
    需要说明一下,不要拿组织机构和安全的页面做页面授权的试验,因为组织机构和安全页面没有配置支持页面授权。上面的截图只是个示例图。具体的授权要针对业务的页面。

  • 相关阅读:
    软件架构师如何工作(即架构漫谈读后感)
    寒假学习记录22
    寒假学习记录21
    寒假学习记录20
    实验四 LL(1)语法分析
    大学生熬夜情况调查结果分析
    大学生熬夜情况调查计划
    实验三 递归下降分析分析法
    实验一 根据状态转换图手工构造词法扫描器
    《软件需求工程》阅读笔记06
  • 原文地址:https://www.cnblogs.com/Jeely/p/11471363.html
Copyright © 2020-2023  润新知