金蝶BOS企业版V开发指南管理门户ortlet开发.docx
《金蝶BOS企业版V开发指南管理门户ortlet开发.docx》由会员分享,可在线阅读,更多相关《金蝶BOS企业版V开发指南管理门户ortlet开发.docx(54页珍藏版)》请在冰点文库上搜索。
金蝶BOS企业版V开发指南管理门户ortlet开发
EAS门户Portlet制作指南
说明
本指南主要介绍EAS门户Portlet的制作过程。
简要阐述了EAS门户的新特性,详细介绍了制作Portlet的过程和步骤,对制作Portlet过程遇到的常见问题进行了说明。
本指南适用于EAS门户Portlet开发人员。
第1章EAS门户简介
1.1EAS门户新特性
新的EAS门户在上一版本门户的基础上对整体框架进行了优化,实现了相关新特性,包含如下功能:
(1)自定义布局:
可自由布局,跨列布局;
(2)页签配置完善:
以拖拽方式把Portlet配置到页签上;
(3)展现框架调整:
可自由拖拽布局显示,运行期用户可个性化配置界面展示样式;
(4)提供容器Portlet:
将多个单一Portlet组合成一个Portlet;
(5)Portlet增加属性设置:
支持系统级和业务级属性设置,且同时支持定义期和运行期属性设置;
(6)Portlet异步加载:
页签中每个Portlet异步加载,并发运行;
(7)通知和待办可分类设置和授权:
分类可由管理员统一建立和分配,同时允许用户自定义分类和管理管理员设置的分类。
第2章Portlet制作
2.1Portlet制作步骤
Portlet制作过程包含以下几个步骤:
(1)配置Portlet信息
(2)向数据库插入相关数据
(3)制作Portlet内容页面,实现业务需求
(4)制作Portlet业务设置页面(可选)
最后一个步骤并不是必须的,在Portlet的业务需求需要业务设置时,才进行此步骤。
下面将分小节详细介绍Portlet制作的各个步骤,关于Portlet业务设置的内容将单独在第3章中介绍。
2.2配置Portlet信息
2.2.1配置Portlet定义信息
(1)配置文件路径
EAS5.4版本:
server/profiles/server1/config/portalConfig/portlets.xml
EAS6.0版本:
server/deploy/eas.ear/cp_web.war/WEB-INF/portlets_xxx.xml
其中,xxx表示具体的业务领域名称,如bos、eas等,详细信息请参考“附录1Portal配置文件拆分说明”
(2)配置说明
1001
testPortlet
view
portlet.test
各配置参数值说明如下:
1001:
Portlet定义ID,全局唯一,不能重复。
取值范围具体约定如下:
BOS为1-199,EAS为200-999,二次开发为1000以后;
testPortlet:
Portlet定义信息,无特别要求,一般使用英文字符标识。
注意该标题信息仅用于在配置文件中区分不同的Portlet,与Portlet在运行时显示的标题无关,Portlet在运行时显示的标题信息由数据库中的内容决定,2.3小节有详细说明;
portlet.test:
对应于“Portlet业务处理信息”的配置信息,具体见下一小节。
2.2.2配置Portlet业务处理信息
(1)配置文件路径
server/deploy/eas.ear/cp_web.war/WEB-INF/tiles-defs_xxx.xml
其中,xxx表示具体的业务领域名称,如bos、eas等,详细信息请参考2.2.1节中的附件《Portal配置文件拆分说明.doc》。
(2)配置说明
extends="portlet_default_eas50"
controllerUrl="/PortletAssembleAction.do">
各配置参数值说明如下:
portlet.test:
tiles定义名称,和上一节Portlet定义信息的配置保持一致;
1001:
对应的Portlet定义ID,和上一节Portlet定义信息的配置保持一致;
/html/custom/test.jsp:
业务处理页面(即2.5节将提到的“Portlet内容页面”)地址,如果是Struts,则还需要在struts-config.xml中进行配置,具体可以参考Struts官方文档。
2.3向数据库插入相关数据
通过EAS管理控制台执行如下脚本,在数据库中插入一条记录,KSQL语句如下:
INSERTINTOT_Portal_Portlet(FID,FCreatorID,FCreateTime,FLastUpdateUserID,FLastUpdateTime,FControlUnitID,FPortletDefineId,FPortletName_L1,FPortletName_L2,FPortletName_L3,FEnable,FPortletNumber,FDescription_L1,FDescription_L2,FDescription_L3,FPortletCategoryID)VALUES(NEWBOSID('0B344890'),'00000000-0000-0000-0000-00000000000013B7DE7F',{ts'2009-10-0112:
13:
14'},'00000000-0000-0000-0000-00000000000013B7DE7F',{ts'2009-10-0112:
13:
14'},'00000000-0000-0000-0000-000000000000CCE7AED4',N'104',NULL,N'周江测试1',N'周江测试1',1,N'PN-104',NULL,N'周江测试1',N'周江测试1','XkGI/dDGlkWJhX5ZEW9lOEPH2a4=');
说明与注意事项:
(1)插入字段FID的值请务必使用函数NEWBOSID,其中'0B344890'为Portlet实体元数据编码,该值不能更改为其他值,否则程序获取Portlet信息时将出错。
函数NEWBOSID('0B344890')每次执行会产生新的ID值,如果作为脚本提交,请注意修改为一个确定的ID值,且一定要支持可重复升级。
(2)字段FPortletDefineId的值一定要和Portlet定义信息配置文件(2.2.1节)中定义的值保持一致。
(3)繁体字段一定要使用繁体文字,否则和语言不匹配。
(4)字段FPortletNumber的值为Portlet编码,其值不做硬性要求,但建议使用“PN-”+Portlet定义ID的形式,如PN-1001。
注:
(2010-11-16)BOSSP3项目任务中加入Portlet分类管理,因此新增了字段FPortletCategoryID
相关默认分类ID如下:
基础系统:
'FZIyxl8gLUmP15IW8klEnUPH2a4='
基础资料:
'VTh25HxPQEKvvaIWWecTGEPH2a4='
财务会计:
'VFcHBNjYQ0qfzqDnSOOmMkPH2a4='
资产管理:
'90O4cecHikiMJoEHN5Pg8kPH2a4='
人力资源:
'5ZE/Jdo9XkGqY38v30oQXkPH2a4='
管理会计:
'4M141/5vlU6fPGEOu+pG7UPH2a4='
资金管理:
'hLg/8i2uPkmQOAKsHt88f0PH2a4='
商业分析:
'IbLhLRrJxUyZgDXwsRDKR0PH2a4='
协同平台:
'm6AWen4UD0SBnZ2qs/Dn5kPH2a4='
供应链管理:
'm6AWen4UD0SBnZ2qs/Dn5kPH2a4='
成本管理:
'R2IPXjFfWEKCFO8i99+bJEPH2a4='
数据仓库:
'cXvgkmCk+0Wf9OTQKtkG3UPH2a4='
房地产:
'kY+l8pEiI0mtkcUNsF/+uUPH2a4='
产业链协同:
'Q+Y2omUEm0ClpF1FbQAlEUPH2a4='
其他:
'XkGI/dDGlkWJhX5ZEW9lOEPH2a4='
因此新增Portlet时需要明确你的Portlet要放在哪个分类下,并将对应的分类id插入到Portlet表中。
如果不插入该字段,Portlet会默认显示在根节点分类下
Portlet类别可以在Portlet管理里面新增,因此你可以新建一个自己的类别,同时需要查询“t_portal_portletCategory”表,获取到你新建类别的id,再来插入你的Portlet到刚刚新建的类别中
2.4Portlet配置信息与数据库数据的对应关系
通常情况下,一条Portlet配置信息(portlets.xml以及tiles-defs.xml中各一个条目)对应数据库表T_Portal_Portlet中的一条数据。
如果多个Portlet使用相同的内容页面(tiles-defs.xml中的),则一条Portlet配置信息将对应数据库表T_Portal_Portlet中的多条数据。
一条Portlet配置信息对应数据库表T_Portal_Portlet中的多条数据的使用场景:
内容管理定义了一个Portlet内容页面,每个栏目可以分别对应一个Portlet定义,不同的Portlet定义通过参数进行区分,参数中记录栏目ID。
可以通过程序动态创建,也可以采用实体提交的方式。
对应实体:
com.kingdee.eas.portal.PortletInfo//Portlet定义
com.kingdee.eas.portal.PortletParameterInfo//Portlet参数
使用程序创建完后,需要刷新缓存才能起作用,相关API见2.5.1节第(4)点。
2.5制作Portlet内容页面,实现业务需求
EAS门户中的Portlet可能具有多个页面,如用于展现业务逻辑的主页面、业务设置页面以及帮助说明页面等。
用于展现业务逻辑的主页面我们称之为“Portlet内容页面”,它是一个JSP页面,但并不是完整的,其最终输出为HTML片段,不能包含、
以及标签。
以下是错误写法示例,Portlet内容页面不应该包含蓝色部分的标签:
EAS下图展示了Portlet内容页面以及Portlet业务设置页面。
图2-1Portlet内容页面
图2-2Portlet业务设置页面
Portlet内容页面由相关的各业务部门根据各自的业务需求具体实现。
EAS门户框架在Portlet内容页面上下文中提供了相应的接口以帮助开发人员完成具体业务逻辑的编写。
2.5.1Portlet内容页面JSP接口
(1)获取EAS上下文(Context)
使用工具类WebContextUtil的getEasContext()方法。
示例:
<%@pageimport="mon.web.util.WebContextUtil"%>
ContextuserCtx=WebContextUtil.getEasContext(request);
(2)获取上下文中的用户、组织、职员等信息
使用工具类ContextUtil,示例:
<%@pageimport="com.kingdee.eas.util.app.ContextUtil"%>
...
Stringname=null;
PersonInfopersonInfo=ContextUtil.getCurrentUserInfo(ctx).getPerson();
if(personInfo!
=null){
name=personInfo.getName();
}
(3)调用服务器端方法
EAS6.0打补丁PTM035205之前:
与ControlBean中调用本地方法一样,示例:
Contextctx=WebContextUtil.getEasContext(request);
IMessageCenteriMessageCenter=MessageCenterFactory.getLocalInstance(ctx);
IRowSetrowset=iMessageCenter.getAcceptedTask();
EAS6.0打补丁PTM035205之后:
IMessageCenteriMessageCenter=MessageCenterFactory.getRemoteInstance();
IRowSetrowset=iMessageCenter.getAcceptedTask();
(4)Portlet操作
使用接口com.kingdee.eas.portal.IPortalServiceFacade,该接口提供以下方法:
·禁用Portlet(含批量处理):
disablePortlet
·启用Portlet(含批量处理):
enablePortlet
·作废Portlet:
deletePortlet
·新增Portlet(无返回值):
addPortlet
·新增Portlet(返回新建ID):
addPortletReturnId
·更新Portlet:
update
·刷新Portlet缓存:
refreshPortletCache
·获取Portlet:
getPortlet
注意:
·所有与Portlet相关的操作,如添加、删除、更新等,都必须使用该接口,不要直接调用IPortlet接口对Portlet进行操作;
·进行Portlet操作(获取Portlet除外)后,在最后务必使用refreshPortletCache来刷新Portlet缓存数据。
示例:
IPortalServiceFacadeservice=PortalServiceFacadeFactory.getLocalInstance(ctx);
service.enablePortlet(portletID);
service.refreshPortletCache();
对PortletExtInfo的操作,由于PortletInfo包含PortletExtInfo,因此同样通过接口com.kingdee.eas.portal.IPortalServiceFacade进行,举例如下:
(其中,portletInfo为PortletInfo的实例)
·添加PortletExtInfo
PortletExtInfoportletExtInfo=newPortletExtInfo();
portletExtInfo.setTitle("自定义Portlet标题");
portletExtInfo.setBizDefUrl("/html/portlet/example/demoPortletDefSetting.jsp");
portletExtInfo.setBizInsUrl("/html/portlet/example/demoPortletInsSetting.jsp");
portletInfo.setPortletExt(portletExtInfo);
IPortalServiceFacadepsf=PortalServiceFacadeFactory.getLocalInstance(ctx);
//如果portletInfo是新增,则
psf.addPortlet(portletInfo);
//如果portletInfo是修改,则
//psf.update(portletInfo.getId(),portletInfo);
·修改PortletExtInfo
PortletExtInfoportletExtInfo=portletInfo.getPortletExt();
portletExtInfo.setTitle("修改自定义Portlet标题");
IPortalServiceFacadepsf=PortalServiceFacadeFactory.getLocalInstance(ctx);
psf.update(portletInfo.getId(),portletInfo);
·删除PortletExtInfo
portletInfo.setPortletExt(null);
IPortalServiceFacadepsf=PortalServiceFacadeFactory.getLocalInstance(ctx);
psf.update(portletInfo.getId(),portletInfo);
(5)获取Portlet相关信息
包括Portlet定义和实例信息,如Portlet在配置文件中的定义ID,在数据库中的定义ID、实例ID以及Portlet的个性化信息(自定义标题、高度、颜色配置等)等。
使用工具类com.kingdee.eas.portal.web.util.PortletUtil可以在Portlet内容页面以及业务设置页面(后续将提及)上获取Portlet的相关信息,包括Portlet的个性化信息(如果存在的话)。
以Portlet内容页面为例,假设需要在此页面获得Portlet的自定义显示名称以及Portlet实例的高度。
首先引入PortletUtil:
<%@pageimport="com.kingdee.eas.portal.web.util.PortletUtil"%>
获取Portlet自定义显示名称:
StringcustomizedName=PortletUtil.getCustomizedName(request);
获取Portlet实例高度:
intinsHeight=PortletUtil.getInsHeight(request);
高度值单位为像素,如果高度值为0,则表示实例的高度自适应。
关于PortletUtil的接口请参考“附录2PortletUtilAPI”。
代码参考:
server/deploy/eas.ear/cp_web.war/html/portlet/example/demoPortlet.jsp
2.5.2Portlet内容页面JS接口
这些JS接口(变量或者函数)在Portlet内容页面中可直接使用。
(1)BuffaloAjax
框架定义了两个Buffalo对象:
buffaloAsync:
异步方式
buffaloSync:
同步方式
使用示例:
buffaloAsync.remoteCall('messageService.getMsgCount',[true],function(reply){
vararr=reply.getResult();
...
}
在Portlet内容页面中使用Buffalo时请直接使用以上两个对象,不必重新创建Buffalo对象。
在上一版本中,框架提供的Buffalo对象名称分别为:
buffalo:
异步方式
buffalo1:
同步方式
这两个对象在门户框架新版本中仍然保留,但不建议使用。
请使用buffaloAsync和buffaloSync。
注意,如果需要创建新的Buffalo对象,请避免使用buffaloAsync、buffaloSync、buffalo、buffalo1这4个变量命名,否则将会覆盖这些框架提供的Buffalo对象。
(2)打开客户端GUI界面
invokeFunction(uiClass,uiClassParam,uiOprt,openMethod);
createModelUI(uiClass);
createNewWinUI(uiClass);
createNewTabUI(uiClass);
openEasMainMenu();
其中uiOprt可设置为字符串:
ADDNEW、VIEW、EDIT
ADDNEW:
新增
VIEW:
查看
EDIT:
编辑
openMethod可设置为数字:
50、80、及其他数字
50:
模态窗口
80:
新开窗口
其他值:
新开页签
单据查看GUI界面接口:
viewBill(billId);
参数为单据ID(单据的UUID,非单据编号),EAS门户页面在不同帧下调用方式略有不用,门户各页签Portlet(比如我的日历,我的工作台等)标准调用方式为直接调用:
viewBill('63fYLq2CTOCwsBgFdet+6Qneydw=');
而各自页签加入了帧(frame)的情况下(如流程中心加入了newMessage
Frame),需要如下调用:
parent.viewBill('63fYLq2CTOCwsBgFdet+6Qneydw=');
其他多层帧的情况以此类推,需要通过parent或者top等方式获取上层的JS函数来调用。
更多关于打开GUI界面的函数请参考以下文件:
server/deploy/eas.ear/cp_web.war/common/js/easHandler.js
(3)拖动Portlet后刷新Portlet内容
该功能常用于Portlet宽度需要自适应的场景,如“通知Portlet”和“待办事项Portlet”,由于这两个Portlet的宽度由JS动态计算而得,所以当他们移动到其他不同宽度的区域时,需要重新计算宽度,这时候就需要刷新Portlet内容以触发宽度的重新计算。
在Portlet内容页面中实现以下函数,并返回true值:
functionafterPortletDrop<%=fp%>(toWidth){
returntrue;
}
其中,<%=fp%>是用于避免JS变量或函数命名冲突的标识(关于JS脚本变量和函数命名约束以及该标识如何获得等问题请参考2.5.3节),该标识必须加上,否则框架无法判断需要刷新哪个Portlet。
参数toWidth为目标区域的宽度值,由框架传递,在该函数内可用该参数值进行一些必要的处理。
不实现该函数或者函数返回true以外的值,则拖动Portlet后,Portlet内容不刷新。
(4)其他
·Portal路径: