文档库 最新最全的文档下载
当前位置:文档库 › 金蝶BOS企业版V6.3.2_开发指南_管理门户_Portlet开发

金蝶BOS企业版V6.3.2_开发指南_管理门户_Portlet开发

EAS门户Portlet制作指南

说明

本指南主要介绍EAS门户Portlet的制作过程。简要阐述了EAS门户的新特性,详细介绍了制作Portlet的过程和步骤,对制作Portlet过程遇到的常见问题进行了说明。

本指南适用于EAS门户Portlet开发人员。

目录

说明 (2)

目录 (3)

第1章EAS门户简介 (4)

1.1 EAS门户新特性 (4)

第2章Portlet制作 (5)

2.1 Portlet制作步骤 (5)

2.2 配置Portlet信息 (5)

2.2.1 配置Portlet定义信息 (5)

2.2.2 配置Portlet业务处理信息 (6)

2.3 向数据库插入相关数据 (6)

2.4 Portlet配置信息与数据库数据的对应关系 (8)

2.5 制作Portlet内容页面,实现业务需求 (9)

2.5.1 Portlet内容页面JSP接口 (10)

2.5.2 Portlet内容页面JS接口 (13)

2.5.3 Portlet内容页面制作规范与约束 (16)

2.5.4 Portlet内容页面制作常见问题 (19)

2.5.5 Portlet内容页面HTC控件的替换 (23)

2.5.6 门户优化合并且删除了部分js (25)

第3章Portlet业务设置 (27)

3.1 关联Portlet业务设置页面 (28)

3.2 Portlet业务设置页面JSP接口 (29)

3.3 Portlet业务设置页面JS接口 (30)

第4章Portlet的使用 (32)

第5章Portlet相关SQL脚本的导出和提交 (35)

5.1 示例SQL (35)

5.2 脚本提交位置 (36)

附录1 Portal配置文件拆分说明 (38)

附录2 PortletUtil API (42)

附录3 Ajax之Buffalo开发指南 (54)

附录4门户Portlet之间通信 (59)

第1章EAS门户简介

1.1 EAS门户新特性

新的EAS门户在上一版本门户的基础上对整体框架进行了优化,实现了相关新特性,包含如下功能:

(1)自定义布局:可自由布局,跨列布局;

(2)页签配置完善:以拖拽方式把Portlet配置到页签上;

(3)展现框架调整:可自由拖拽布局显示,运行期用户可个性化配置界面展示样式;

(4)提供容器Portlet:将多个单一Portlet组合成一个Portlet;

(5)Portlet增加属性设置:支持系统级和业务级属性设置,且同时支持定义期和运行期属性设置;

(6)Portlet异步加载:页签中每个Portlet异步加载,并发运行;

(7)通知和待办可分类设置和授权:分类可由管理员统一建立和分配,同时允许用户自定义分类和管理管理员设置的分类。

第2章Portlet制作

2.1 Portlet制作步骤

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等,详细信息请参考“附录1 Portal配置文件拆分说明”

(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语句如下:

INSERT INTO

T_Portal_Portlet(FID,FCreatorID,FCreateTime,FLastUpdateUserID,FLastUp dateTime,FControlUnitID,FPortletDefineId,FPortletName_L1,FPortletName _L2,FPortletName_L3,FEnable,FPortletNumber,FDescription_L1,FDescripti on_L2,FDescription_L3, FPortletCategoryID)

VALUES(NEWBOSID('0B344890'),'00000000-0000-0000-0000-00000000000013B7 DE7F',{ts'2009-10-01

12:13:14'},'00000000-0000-0000-0000-00000000000013B7DE7F',{ts'2009-10 -01

12: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) BOS SP3项目任务中加入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.4 Portlet配置信息与数据库数据的对应关系

通常情况下,一条Portlet配置信息(portlets.xml以及tiles-defs.xml中各一个条目)对应数据库表T_Portal_Portlet中的一条数据。

如果多个Portlet使用相同的内容页面(tiles-defs.xml中的

name="portlet_content" value="/html/custom/test.jsp" />),则一条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-1 Portlet内容页面

图2-2 Portlet业务设置页面

Portlet内容页面由相关的各业务部门根据各自的业务需求具体实现。EAS 门户框架在Portlet内容页面上下文中提供了相应的接口以帮助开发人员完成具体业务逻辑的编写。

2.5.1 Portlet内容页面JSP接口

(1)获取EAS上下文(Context)

使用工具类WebContextUtil的getEasContext()方法。示例:

<%@page

import="https://www.wendangku.net/doc/c313475758.html,mon.web.util.WebContextUtil"%> Context userCtx = WebContextUtil.getEasContext(request);

(2)获取上下文中的用户、组织、职员等信息

使用工具类ContextUtil,示例:

<%@page import="com.kingdee.eas.util.app.ContextUtil"%>

...

String name = null;

PersonInfo personInfo =

ContextUtil.getCurrentUserInfo(ctx).getPerson();

if (personInfo != null) {

name = personInfo.getName();

}

(3)调用服务器端方法

EAS6.0打补丁PTM035205之前:

与ControlBean中调用本地方法一样,示例:

Context ctx = WebContextUtil.getEasContext(request);

IMessageCenter iMessageCenter =

MessageCenterFactory.getLocalInstance(ctx);

IRowSet rowset = iMessageCenter.getAcceptedTask();

EAS6.0打补丁PTM035205之后:

IMessageCenter iMessageCenter =

MessageCenterFactory.getRemoteInstance();

IRowSet rowset = 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缓存数据。

示例:

IPortalServiceFacade service =

PortalServiceFacadeFactory.getLocalInstance(ctx);

service.enablePortlet(portletID);

service.refreshPortletCache();

对PortletExtInfo的操作,由于PortletInfo包含PortletExtInfo,因此同样通过接口com.kingdee.eas.portal.IPortalServiceFacade进行,举例如下:

(其中,portletInfo为PortletInfo的实例)

·添加PortletExtInfo

PortletExtInfo portletExtInfo = new PortletExtInfo();

portletExtInfo.setTitle("自定义Portlet标题");

portletExtInfo.setBizDefUrl("/html/portlet/example/demoPortletDef Setting.jsp");

portletExtInfo.setBizInsUrl("/html/portlet/example/demoPortletIns Setting.jsp");

portletInfo.setPortletExt(portletExtInfo);

IPortalServiceFacade psf =

PortalServiceFacadeFactory.getLocalInstance(ctx);

// 如果portletInfo是新增,则

psf.addPortlet(portletInfo);

// 如果portletInfo是修改,则

//psf.update(portletInfo.getId(), portletInfo);

·修改PortletExtInfo

PortletExtInfo portletExtInfo = portletInfo.getPortletExt();

portletExtInfo.setTitle("修改自定义Portlet标题");

IPortalServiceFacade psf =

PortalServiceFacadeFactory.getLocalInstance(ctx);

psf.update(portletInfo.getId(), portletInfo);

·删除PortletExtInfo

portletInfo.setPortletExt(null);

IPortalServiceFacade psf =

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:

<%@ page import="com.kingdee.eas.portal.web.util.PortletUtil"%>

获取Portlet自定义显示名称:

String customizedName = PortletUtil.getCustomizedName(request);

获取Portlet实例高度:

int insHeight = PortletUtil.getInsHeight(request);

高度值单位为像素,如果高度值为0,则表示实例的高度自适应。

关于PortletUtil的接口请参考“附录2 PortletUtil API”。

代码参考:

server/deploy/eas.ear/cp_web.war/html/portlet/example/demoPortlet .jsp

2.5.2 Portlet内容页面JS接口

这些JS接口(变量或者函数)在Portlet内容页面中可直接使用。

(1)Buffalo Ajax

框架定义了两个Buffalo对象:

buffaloAsync:异步方式

buffaloSync:同步方式

使用示例:

buffaloAsync.remoteCall('messageService.getMsgCount', [true], function(reply) {

var arr = 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值:

function afterPortletDrop<%=fp%>(toWidth) {

return true;

}

其中,<%=fp%>是用于避免JS变量或函数命名冲突的标识(关于JS脚本变量和函数命名约束以及该标识如何获得等问题请参考2.5.3节),该标识必须加上,否则框架无法判断需要刷新哪个Portlet。参数toWidth为目标区域的宽度值,由框架传递,在该函数内可用该参数值进行一些必要的处理。不实现该函数或者函数返回true以外的值,则拖动Portlet后,Portlet内容不刷新。

(4)其他

·Portal路径:

https://www.wendangku.net/doc/c313475758.html,mon.portalContextPath;

其值如:http://192.168.33.1:6888/easportal

·Portal当前色彩方案皮肤路径:

https://www.wendangku.net/doc/c313475758.html,mon.portalSkinPath;

其值如:http://192.168.33.1:6888/easportal/skin/01

·添加CSS样式文件到门户的head区域

https://www.wendangku.net/doc/c313475758.html,mon.addStyleSheet(cssFilePath);

其中cssFilePath为CSS文件的路径,用法示例:

https://www.wendangku.net/doc/c313475758.html,mon.addStyleSheet('<%=WebContextUtil.render(req uest, "/html/portlet/example/demoPortlet.css")%>');

注,并不一定要使用WebContextUtil.render方法来获得CSS文件的路径,可以直接如下使用:

https://www.wendangku.net/doc/c313475758.html,mon.addStyleSheet('/html/portlet/example/demoPo rtlet.css');

但是,使用WebContextUtil.render方法获取文件可获得压缩特性,建议使用该方法。

·最大化Portlet

https://www.wendangku.net/doc/c313475758.html,mon.maxizePortlet(windowTitle, servletUrl, params);

其中,windowTitile为最大化Portlet时,窗口的标题,servletUrl为最大化Portlet所使用的url地址,params为需要传递的参数

2.5.3 Portlet内容页面制作规范与约束

(1)业务JSP代码文件放置规范

·二次开发的业务JSP代码

受保护的需要放到server/deploy/eas.ear/cp_web.war/html/custom目录下。

非受保护的需要放到server/deploy/eas.ear/cp_web.war/custom目录下。

·EAS标准产品的业务JSP代码

受保护的需在server/deploy/eas.ear/cp_web.war/html/portlet目录下建立对应的业务系统子目录,并放置对应的业务JSP代码。

非受保护的在server/deploy/eas.ear/cp_web.war/biz目录下建立对应子目录,并放置对应业务JSP代码。

·受保护和非受保护的区别

受保护的JSP页面必须要通过EAS Portal登录后才能访问,非受保护是指不

需要EAS Portal登录就可以访问。

(2)JS代码文件放置规范

JS文件放置到以下目录:

server/deploy/eas.ear/cp_web.war/common/js/

各业务部门请自行在js目录下建立子文件夹,以区分框架和其他部门的JS 代码。该目录下(包括子目录)的所有JS文件在构建时都会自动进行压缩,将JS文件放置在其他目录将不会获得压缩特性。

(3)Portlet内容页面中,JS脚本变量和函数命名约束(重要)

在一个HTML文档内,JavaScript全局变量和函数命名必须唯一,否则会被后定义的覆盖。由于EAS门户中,不同页签,不同Portlet的内容最终将输出到一个HTML文档中,为了避免不同的Portlet内定义相同名称的JS变量或者在不同的页签内包含相同的Portlet定义,必须保证Portlet之间全局JS变量名和函数名唯一。

提示:只有Portlet内容页面(JSP片段)需要考虑命名问题,保证全局变量和函数命名唯一,其他独立的页面(包含完整的HTML标签的页面,如使用iframe 方式嵌入的页面、Portlet业务设置页面等)则不需要考虑该问题。

最佳实践:尽量少使用全局变量。大量地使用全局变量将增加变量命名冲突的几率,应该谨慎使用全局变量。关于如何减少JS全局变量和函数数量的方法请见2.5.4节。

补充知识:在JS函数内,使用var关键字定义变量,变量的作用域为局部作用域,如果不使用var关键字,则为全局作用域。JS函数内的局部变量定义时都应该加上var关键字。

使用以下两种接口之一,均可获得与当前Portlet实例相关的全局唯一标识(“指纹”信息)。为Portlet内容页面中JS脚本的每个全局变量和函数加上该标识,则可保证该Portlet实例的JS全局变量和函数在EAS门户中全局唯一,避免不同Portlet之间以及不同页签相同Portlet不同实例之间的JS变量和函数命名冲突。

接口1:

使用com.kingdee.eas.portal.web.util.PortletUtil

示例:

// fp is short for fingerprint

String fp = PortletUtil.getFingerprint(request);

接口2:

使用com.kingdee.eas.portal.web.util.PortletIndexGenerator

示例:

// fp is short for fingerprint

String fp = PortletIndexGenerator.nextPortletIndex(request);

两种接口的区别:接口1既可以在Portlet内容页面中使用,也可以在Portlet 业务设置页面中使用(见第3章);而接口2只能在Portlet内容页面中使用。

获得“指纹”信息后(示例中为Java变量fp),为每个全局变量和函数加上该标识,代码示例如下:

……

()”>My Link

上面的例子中,一共定义了4个全局变量(包括函数),通常情况下,应尽量控制全局变量的数量,关于如何减少JS全局变量和函数数量的方法请见2.5.4节。

注意:该约束必须严格执行,以避免影响框架和Portlet的功能。

(4)Portlet内容页面中,CSS样式命名规范(重要)

和JS脚本变量和函数命名需要全局唯一一样,CSS中的class和id命名也需要考虑到全局影响的情况。

提示:只有Portlet内容页面(JSP片段)需要考虑命名问题,保证class和id命名唯一,其他独立的页面(包含完整的HTML标签的页面,如使用iframe 方式嵌入的页面、Portlet业务设置页面等)则不需要考虑该问题。

相关文档