欢迎,游客
首页 > 培训 > 知识库 > BI@Report > 门户

门户指引

工具箱介绍

1.1布局组件

一个门户或者登录页面的设计,首先从布局设计开始。布局容器的种类有:空白容器、工型容器、T型容器、田型容器、水平容器、垂直容器,布局容器可以嵌套,布局块之间可以合并拆分,从而构建出任意复杂布局模式。
这部分跟报表模板设置布局是极其类似的,不管是布局的种类和操作方式,都差不多,这里就不再对如何使用布局做过多的介绍。
容器的有一个设置,叫布局方式,是需要了解一下的。假设拖入一个田型容器,就将页面分成四块,此时可以在每一块拖入很多组件,这些组件的布局方式有三种可选:流式布局、块式布局、固定布局。即,田型容器的4块区域,每一块区域都可以指定各自的布局方式,且互不干扰。

·        

    • 流式布局:多个组件成队列排放,先放第一排,排满了再开始放第二排,也就是从左往右,从上到下的顺序依次摆放;
    • 块式布局:块式布局是不管有多少组件,每排只放一个组件;
    • 固定布局:也是最常用的,位置任意放,将组件固定到某一个位置,不是系统自动排的。(这种布局方式最常用)

 

1.2基本组件

注:灰色字体是尚未用到过的组件

组件名称

组件标识

作用

文本

text1

用来显示文本内容,例如页面底部显示单位名称地址等信息;

按钮

button1

用来触发点击执行事件,例如登录按钮;

链接

anchor1

用来点击打开链接、也可以用来触发点击执行事件(同按钮),例如点击按钮打开系统个人设置页面;

图片

image1

用来显示图片,例如在页面顶部显示公司logo图片;

单行输入框

input1

用来输入字符数字,例如登录页面的名称密码输入框;

多行输入框

textarea1

用来输入多行字符数字;

单选按钮

radio1

用来做页面上的单选;

复选框

checkbox1

用来做页面上的多选;

简单面板

easypanel1

用来辅助排版布局的,例如登录页底部显示有图片和文本,可以在保持两者相对位置固定的情况下,让两者组合之后的整体对页面居中;

标签页

tabctrl1

标签形式显示展示内容,例如门户模板中的选项卡风格;

面板

panel1

带标题的简单面板,其空白区域可以与简单面板一样拖入容器或组件,标题部分可以设置文本和图标,像内网首页中的各个模块

磁贴

metro1

用来点击打开链接,功能类似于链接组件,但是可以加图标,且大小风格只有两种可选,例如win8风格门户用到的组件就是磁铁;

表单

form1

用于form表单提交,例如在门户上上传一个excel文件;(暂未开发好)

子窗口

iframe1

用来显示链接的内容,例如酷黑风格里面,点击顶部按钮,在下面的子窗口显示子页面的内容;

Flash视频

flash1

用来显示flash视频动画;

 

1.3高级组件

注:灰色字体是尚未用到过的组件

组件名称

组件标识

作用

菜单

menu1

用来在门户上形成菜单,第一层横向平铺,第二层开始都为树形,菜单任何节点都可以设置资源链接;例如门户模板中的酷橙风格顶部标签,就是用的菜单组件;

滚动文本

xslidertext1

用来在门户上滚动播放文字的,例如在门户右上角滚动播放公司信息;

轮换图片

xsliderimg1

用来滚动播放一组图片,并且图片可以设置打开链接;

xtree1

用来显示树形结构,任何树形结构都能设置资源链接,例如门户中树形结构显示报表,就需要用到树组件;

列表

xlist1

用来在门户上,以表格的形式列出一些信息;

可编辑下拉框

xeditcombo1

以下拉的编辑方式来选择要输入的值,如果下拉选项中没有符合条件的,也可以自行输入。可以用在一些条件过滤或搜索的页面中

简单列表框

xlistbox1

同下拉列表框一样也是给出几个选项以供选择的,但这个是始终显示所有选项的那种选择框

下拉列表

xlistcombobox1

功能同可编辑的下拉框,只是只能选下拉选项中提供的值,不能自行输入

带按钮输入框

xeditbrowser1

同单行输入框的功能,且在后面带有一个按钮,用于选择输入

工具条

xcoolbar1

一排工具按钮组成的组件,系统中的很多页面都能看到的那种效果,用于配置类似系统页面的

日历

xcalendar1

日历,选择日期用的,一般不单独使用,最多也会是作为日历下拉框配合使用

日历下拉框

xcalendarcombo1

选择日期用的一个组件,如可以作为参数替代报表模版的参数面板

月历

xmenology1

同日历

月历下拉框

xmenologycombo1

同日历下拉框

数值输入框

xspinner1

后面带增大减小按钮的数值输入框,作为微调数值用

滑块

xslider1

同数值输入框一样也是一种数值型输入组件,但它不是微调,而是从在起止值间拖动调整

编辑滑块

xeditslider1

同滑块,增加手工输入的调整,用于比滑块拖动更精确的调整

 

1.4组件的叠放次序&定位方式

前提:布局块的布局方式设置是"固定布局"
任何一个组件选中后,右键属性中都有两个设置项:叠放次序、定位方式
叠放次序:置于顶层、置于底层、上移一层、下移一层;这个比较好理解,当出现多个组件相互覆盖的时候,可以设置多个组件之间的叠放次序。
定位方式:水平左(中、右)定位,竖直上(中、下)定位,是当分辨率变化的时候,用来指定组件位置的定位标准。例如水平右定位,组件跟外容器的相对位置的以右边距为准,在设计界面,组件与容器右侧距离20个像素的距离,那么水平右定位的话,在预览的时候,不管分辨率如何,组件都跟右侧保持20个像素的距离;门户有右上角的注销按钮,一般情况下都会选择水平右定位。

设计要点剖析

2.1登录页攻略

登录页面是最简单的,要设计一个登录页,4个必备组件+2个脚本,其他就随意发挥。
4
个必备组件:账号输入框、密码输入框、登录按钮、密码不符提示文本
2
个脚本如下:

页面属性/加载完成脚本:
function(){
         getElement = function(nms) {
                   var obj = $p.$(nms);
                   return obj.get("input") || obj.get("widget_div");
         
         };
         _validateLoginElements = function(){//重写这个检查DOM的方法,因为该方法会更改用户名和密码框的样式
                   login_user = getElement("loginUser");                //用户名输入组件标识
                   login_pwd = getElement("loginPwd");                //密码输入组件标识
                   login_bt = getElement("loginButton");                //登录按钮组件标识
                   login_error = getElement("loginError");             //密码错误提示文本组件标识
                   login_error.className += ' form_point';
                   login_verify = null;//暂时不要验证码功能
                   _errortimes = 0;
                   _verifycode = 0;
         };
         setupLoginForm();
}

 

 

页面属性/自定义脚本:
var contextpath = sys.getContextPath();
include(contextpath + 'esmain/main/js/serverfunc.js');
include(contextpath + 'esmain/main/js/login.js');
include('xui/third/md5.js');
 
function showLoginErrorImpl(errormsg){
         var ediv = getElement(["loginError"]);         //密码错误提示文本组件标识
         if(!ediv) return;
         ediv.innerHTML = '';
         ediv.appendChild(doc.createElement("span"));
         ediv.appendChild(doc.createTextNode(errormsg));
         ediv.style.display = "block";
}

 

2.2登录页实战

(最简单的方法,用模板,在模板的基础上换图片,这里为了保证介绍的完整性,所以从空页面开始)

2.2.1step1:需求

在动手开始设置前,首先要有一个需求的草图,这样就可以按照草图去设计页面的布局和组件了

2.2.2step2:新建&布局

新建一个登录页,选择"从空白页面创建",定义一个门户名称:

拖入水平容器组件,并编辑容器分成上中下三个部分。上下两块固定高118,中间块最小高度设置为63%(根据实际情况,调整大小),没有合适的背景图片,可以用容器背景色代替,分别对三块分区设置不同的背景色,如下:

为了方便组件的布局,将上中下三块的布局方式都设置成"固定布局",设置的方法是,在某容器上,右键菜单"布局方式/固定布局"

2.2.3step3logo+文本

需求中的logo、公司名称、公司信息,指需要拖入图片或者文本组件到相应位置即可,只需要注意一下各组件的定位方式,操作非常简单,效果如下:

2.2.4step44个必备组件设置


登录页有4个必备组件:

  • 账号输入框:用单行输入框组件,显示方式为明文,组件标识为:input1
  • 密码输入框:用单行输入框组件,显示方式为密码,组件标识为:input2
  • 登录按钮:用按钮组件,选择一种合适的风格,组件标识为:button1
  • 密码错误提示框:用文本组件,当密码输入错误的时候,给出提示信息,提示内容由系统传递,所以在此处之需要给一个空的文本框即可(文本内容清空),组件标识为:text5


注意:这里还用到了简单面板组件,上图中看到的组件,都是放在简单面板组件内的,做样做的目的是方便排版和布局,设置简单面板定位方式为水平中定位、竖直中定位。

2.2.5step52个脚本修改


根据上面步骤中拖入组件的组件标识,去修改相应的脚本参数,然后将脚本粘贴到页面属性中的加载完成和自定义脚本,脚本如下:

页面属性/加载完成脚本:
function(){
         getElement = function(nms) {
                   var obj = $p.$(nms);
                   return obj.get("input") || obj.get("widget_div");
         
         };
         _validateLoginElements = function(){//重写这个检查DOM的方法,因为该方法会更改用户名和密码框的样式
                   login_user = getElement("input1");                //用户名输入组件标识
                   login_pwd = getElement("input2");                //密码输入组件标识
                   login_bt = getElement("button1");                //登录按钮组件标识
                   login_error = getElement("text5");             //密码错误提示文本组件标识
                   login_error.className += ' form_point';
                   login_verify = null;//暂时不要验证码功能
                   _errortimes = 0;
                   _verifycode = 0;
         };
         setupLoginForm();
}
页面属性/自定义脚本:
var contextpath = sys.getContextPath();
include(contextpath + 'esmain/main/js/serverfunc.js');
include(contextpath + 'esmain/main/js/login.js');
include('xui/third/md5.js');
 
function showLoginErrorImpl(errormsg){
         var ediv = getElement(["text5"]);          //密码错误提示文本组件标识
         if(!ediv) return;
         ediv.innerHTML = '';
         ediv.appendChild(doc.createElement("span"));
         ediv.appendChild(doc.createTextNode(errormsg));
         ediv.style.display = "block";
}

 

2.2.6step6:设置缩略图

最后还需要设置一个门户的缩略图,可以在设计界面截图,将该图上传服务器,并通过"门户配置/预览图片"指定为缩略图:

设置之后,在门户预览里面,就可以华丽丽的变身啦!

一切设置搞定之后,就选中该登录页面,作为服务器登录页面,哈哈,是不是很有趣呀~~

2.3门户页攻略

展示报表的组件有两个:标签组件、子窗口组件;BI门户是用来展示报表的,这两个组件的重要性,你懂的~
常见报表展示的结构:树形、标签、菜单、标签+树、菜单+树;
(注意这列之列出到报表展示结构,隐含的任何一种结构都需要子窗口或者标签来显示报表内容)
另说明:建议在模板基础上去设计门户,如果从空页面开始制作门户,你会发现门户是脚本的天下,慎用!

2.3.1菜单+子页面,设置子页面在指定的区域展示


在上图中就做了一个很简单的菜单+子页面的的门户,第一页page0.esp是默认的门户主页,第二页page1.esp是一个子页面
page0.esp设计成上下结构的布局,上面拖入一个菜单组件(双击即可编辑菜单内容),下面拖入一个子窗口组件,组件标识为iframe1
首页就展示一个kpi报表,配置链接如下(报表链接可以拾取):
../../resource/EBI$12$4IKKVTRUO0T4C0UIY5U5O4IL76ISSCTQ$1$MINFKBSK4UVMUUIITZXTSEF5YKIQ9PDI.rpttpl
第二页就展示page1.esp的内容,配置链接如下(子页面链接可以拾取):
../../esmain/portal/portal.do?filepath=/root/portals/pages/esp/CDS/page1.esp
还有一个关键步骤:菜单的两个节点的"打开方式"设置都需要输入子窗口的组件标识iframe1,这样才能让展示内容指定在该子窗口显示;

2.3.2 菜单组件默认第一个为选中状态

顶部的标签用菜单组件实现,希望初次刷新菜单第一项默认为选中状态,如下图所示:

在菜单组件的"属性/事件/加载完成"设置脚本如下:

function(bar, iseditstatus) {
if (!iseditstatus) {
bar.doClick(bar._property["itemnames"][0]);
}
}

 注意:bi最新版中,该设置无须在借助脚本,可以在菜单属性中设置了

2.3.3 树型+标签(子窗口),设置树上点击资源在标签区域展示


如上图所示,左侧树,右侧为展示区域,展示区域可以是标签组件也可以是子窗口组件,但是如何点击树上的节点,让展示的内容在指定的区域去展示呢? 还是需要在一段脚本来支持的。
脚本写在树组件的"属性/事件/鼠标单击".
如果是树+TAB标签,脚本内容如下:

function(item){
         if(!item) return;
         var url = item.url;
         if(!url) return;
         var pagetab = $p.$("tabctrl2").getComponent();    //tabctrl2为标签组件标识,脚本只需要改动这个参数即可
         var index = pagetab.getIndex("url", url);
         if(index !== -1) {
                   pagetab.setActive(index);
         } else {
                   pagetab.add(item.getItemText(), item.imageLeaf || item.imageOpen || item.imageClose, {data : {url : url, urlparams : item.urlparams, refreshcaption : true}});
         }
}


 
如果是树+子窗口组件,脚本:

function(item){
         if(!item) return;
         var url = item.url;
         if(!url) return;
         $p.$("iframe1").setUrl(url);     //iframe1是子窗口的组件标识
}

2.3.4标签组件添加标签页自动该页添加树

门户模板中有一种是:选项卡组合导航树风格,这个模板主要用到的就是标签组件+树组件,其中有一个重要的特点就是标签组件每增加一个标签,系统将自动为该标签添加树组件和子标签
在标签组件的"属性/事件/加载完成"设置脚本如下,就能自动实现上述效果: 

function(xtab, iseditstatus, widget){
         if(!iseditstatus) return;
         var sheet = widget.get("widget_sheet");
         xtab.setOnAdded(function(index, tab){//添加标签
                   if(tab.getData(index, "isdragadd")) return;
                   var bodyDom = tab.getBodyDom(index);
                   sheet.bindDroppable(bodyDom,
'container');//绑定扩拖拽容器属性,否则会不让添加容器
                   var layout = sheet.addContainer({parent: bodyDom, row: 1, col: 2});
                   layout.setColFixed(0, true);
                   layout.setColWidth(0, 200);
                   layout.setColWidth(1, 100);
                   layout.getGridDom().setAttribute(PortalConstants.NAME_DATA_RELAYOUT, "true");
                   
                   sheet.addWidget("widget_tabctrl", {
                            parent: layout.getCellDom(0, 1),
                            callback: function(sheet, widget) {
                                     var id = widget.getProperty("id");
                                     widget.set("widget_editor", null);
                                     sheet.setWidgetProperty(id, "hideheader", true);
                                     sheet.addWidget("widget_xui_xtree", {
                                               parent: layout.getCellDom(0, 0),
                                               callback: function(sheet, widget){
                                                        //设置click属性
                                                        widget.setProperty("evt_click", 'function(item){\r\n'
                                                                 +'\tif(!item) return;\r\n'
                                                                 +'\tvar url = item.url;\r\n'
                                                                 +'\tif(!url) return;\r\n'
                                                                 +'\tvar pagetab = $p.$("' + id + '").getComponent();\r\n'
                                                                 +'\tvar index = pagetab.getIndex("url", url);\r\n'
                                                                 +'\tif(index !== -1) {\r\n'
                                                                 +'\t\tpagetab.setActive(index);\r\n'
                                                                 +'\t} else {\r\n'
                                                                 +'\t\tpagetab.add(item.getItemText(), item.imageLeaf || item.imageOpen || item.imageClose, {data : {url : url, urlparams : item.urlparams, refreshcaption : true}});\r\n'
                                                                 +'\t}\r\n'
                                                                 +'}');
                                                        widget.setProperty(widget.setStyle("green"), "green");
                                               }
                                     });
                            }
                   });
         });
}



Q
:为什么每个标签页下面自动加载的组件是树组件+标签(隐藏头部),而不是树组件+子窗口呢?用标签有什么好处呢?
A:
子窗口组件是每次设置显示的页面时,之前的页面是被丢了的,新页面需要重新下载显示,如果来回切换标签,每一次切换都需要重新下载显示;而标签页,每个标签里面其实是有一个类似于子窗口组件的东西,我切换树节点的页面时,只有第一次显示这个页面时需要下载,切到其它页面时我先不丢,只是隐藏起来,等下次再切过来的时候直接显示,这样就不需要重新下载显示了

2.3.5标签组件右键菜单脚本

在树形结构的门户中,右侧展示报表的标签组件,每点击一个新的节点,就会在右侧新增一个标签页,也就是以新增标签页的形式来展示报表,那么这个标签组件上可以配置邮件菜单,在标签上鼠标右键就弹出菜单选项"关闭/关闭其他/关闭所有",如下图所示:

这个右键菜单的功能,也是通过脚本实现的。实现的方法:在标签组件的"属性/事件/加载完成"配置脚本如下:

function(xtab, iseditstatus, widget) {
         if (iseditstatus) return;
         if (!window["XPopupMenu"]) include("xui/ctrls/xmenu.js");
         var menu = new XPopupMenu();
         menu.addXMenuItem("关闭", null, function() {