适用版本:V7.0及其以上版本
1. 协同门户开发手册
1.1. 关于门户的定制方式
门户支持三种定制模式:基于门户设计器界面的定制、基于门户模板导入导出的定制和基于代码开发的定制。
- 基于门户界面的定制:这种定制方式,主要通过设计器界面对门户的相关属性进行修改,比如门户模板样式、皮肤样式、栏目外框样式等,这种定制方式无需重启服务即可生效。
- 基于导入导出的定制:这种定制方式,主要通过将门户组成的所有资源导出一个ZIP包,用户可以用WINRAR工具解开这个ZIP包,可以对相关的门户资源进行修改,然后重新打一个ZIP包,再重新导入系统中形成一个新的门户模板,这种定制方式也无需重启服务即可生效。
- 基于代码开发的定制:这种定制方式,主要是开发人员通过遵循门户规范,去开发实现门户的各个组成部分,从而开发出一套新的门户模板。这种定制方式需要重启服务才能生效。
1.2. 本手册包含的内容
本手册主要以具体例子来对第二种【基于导入导出的定制】和第三种【基于代码开发的定制】定制方式进行详细说明,以指导开发人员进行门户的定制开发实战。但可能会顺带介绍一些门户规范和原理,但不会对这块进行专门的介绍。 同时本手册也对门户对外提供的其它API如何使用也进行了说明。
1.3. 对阅读者的要求
本手册主要面向开发人员,你需要熟练掌握如下开发知识和技术:
HTML:超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。您可以使用 HTML 来建立自己的 WEB 站点,HTML 运行在浏览器上,由浏览器来解析。
CSS: 是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力。
JAVASCRIPT:JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。是一种解释性脚本语言(代码不进行预编译)。主要用来向HTML(标准通用标记语言下的一个应用)页面添加交互行为。
JSON:JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),是轻量级的文本数据交换格式。JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
LAYTPL:laytpl 是 JavScript 模板引擎,在字符解析上有着比较出色的表现,laytpl 的模板可与数据分离,集中把逻辑处理放在 View 层,提升代码可维护性,尤其是针对大量模板渲染的情况。
XML:XML 指可扩展标记语言(eXtensible Markup Language)。 XML 被设计用来传输和存储数据。
AJAX:Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
JAVA:Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。Java可运行于多个平台,如Windows, Mac OS,及其他多种UNIX版本的系统。
上面列出来的是一个比较全面的门户开发知识和技术要求,是进行第3种门户定制开发必须具备的,但如果您只是进行第2种门户定制开发,不涉及新增门户后台数据接口,则掌握了上面提到的:HTML、CSS、JAVASCRIPT、JSON、LAYTPL、XML、AJAX即可。
1.4. 开始定制开发
1.4.1. 基于导入导出的定制
我们可以用集团管理员或单位管理员登录系统,进入V-Portal配置平台,分别对下述内容进行导入导出定制。
门户模板定制
门户模板ZIP包介绍
进入【整体样式库】,选择“网站式信息门户”导出,如下图:
导出的ZIP包目录结构如下图所示:
portal/images:该目录存放门户模板用到的所有图片文件;
portal\pagelayout\layout\layout02:该目录存放门户布局相关文件,其中layout02为门户布局代码。这个目录下会存放3个文件:layout02_b.html、layout02_b.css和layout02_b.js。layout02_b.html文件为门户布局html文件,layout02_b.css为门户布局样式文件,layout02_b.js为该门户特有的JavaScript脚本。后面会对门户布局的概念进行专门介绍,在这里记住门户布局由1个html文件、1个css文件和1个js文件组成即可。
对门户布局的解释 产品中自带了常见的门户布局,能够满足大部分需求,详细见《附录1:门户布局规范》。 开发建议:在定义门户布局时尽量使用产品自带的门户布局,在这个基础上在进行扩展,这样的好处是可以在门户设计器中对门户布局的各个区域的属性进行配置定义,例如门户布局中个区域的背景色和背景图片等。 通过门户布局规范可以知道,门户布局是指将门户页面划分为若干区域,如何划分门户区域,这个跟客户对门户的需求有关系,举个例子:比如客户希望单位LOGO和名称放在最上面靠左,退出按钮放在最右上角,菜单摆在单位LOGO和单位名称的下面,菜单内容下面为内容区。根据这个描述,我们可以将门户布局划分如下图所示:
门户布局html文件,只包含html内容,但在html的dom元素上会有致远门户自定义属性,以layout02_b.html为例,内容如下:
注意:主要是红色框中的内容:class=”seeyon-portal-header”标识门户头部区;class=” seeyon-portal-body”标识门户内容区;class=” seeyonElementGroup”标识门户元素分组,门户元素分组中可以包含多个门户元素;class=” seeyonElement”标识门户元素,门户元素中的id和data-tpl两个属性必须指定,其中id的值必须保证唯一性,data-tpl的值必须跟门户元素的文件名相同,门户元素包含哪些内容,后面马上会介绍到。
portal\pagelayout\element:该目录存放门户元素相关文件,每个门户元素包含3个文件:1个html文件、1个js文件、1个css文件。例如幻灯片元素tpl-slideVPortal.html、tpl-slideVPortal.js、tpl-slideVPortal.css。 门户元素的这三个文件要求必须以tpl-开头,除了后缀不通外,文件名称必须相同。 门户元素html文件需要符合laytpl前端模板引擎规范。例如tpl-slideVPortal.html内容如下:
注意:上面文件内容中<script id="tpl-slideVPortal" type="text/html">,id必须跟文件名称保持一致。
门户元素js文件,需要按照门户规范实现,以tpl-slideVPortal.js文件为例,内容如下图所示: 门户元素css文件,主要对门户元素的外观进行配置,需要按照CSS规范实现,且这些css样式只能在tpl-slideVPortal.html文件中用到,以tpl-slideVPortal.css文件为例,内容如下图所示:
portal\pagelayout\skin:该目录存放门户模板样式CSS文件,这个文件内容遵循CSS标准。
portal\sections\skin:该目录存放门户栏目外框样式CSS文件,这个文件内容遵循CSS标准。
skin\dist\components:该目录存放二级页面样式CSS文件,这个文件内容遵循CSS标准。
upload:该目录存放导出的门户模板中包含的图片文件。
import.xml:该文件为导入内容元数据描述文件,内容如下:
从上面的内容可以看出:
(1) 根标签
表示一个门户模板,这个标签下的 标签表示门户模板的名称,注意门户名称不能含有特殊字符, 标签表示门户模板的图标,它的值是一个图片文件名称,这个图片文件必须放到前面提到的portal/images目录下; 为门户模板中CSS、JS和HTML文件中直接引用的图片资源文件路径,它在ZIP压缩包的【需要拷贝到服务器上的图片资源文件夹】目录下。 (2)
:这个标签中定义门户模板使用的布局文件,这个标签包含的定义内容如下:
<layout>
<code>layout02</code>
<styleCode>layout02_b</styleCode>
<icon>layout02_b.jpg</icon>
<name>layout02</name>
</layout>
标签中的内容为门户模板布局唯一标识,这个值必须与ZIP包中的路径portal\pagelayout\layout\layout02中的layout02目录名称保持一致,注意这里layout02只是一个例子,也可以是其它英文标识。
标签中的内容为门户布局特定样式标识,且也必须唯一,这个值必须与ZIP包中的路径portal\pagelayout\layout\layout02目录下的文件名称相同。 标签中的内容为门户模板的示意图标,这个值是一个图片文件名称,,这个图片文件必须放到前面提到的portal/images目录下。 标签中的内容为门户模板的名称,不能含有特殊字符,这里建议使用与 标签中相同的值。
(3)
:标签表示门户模板使用的整体皮肤,这个标签下的 标签表示整体皮肤的名称,注意整体皮肤名称不能含有特殊字符, 标签表示整体皮肤的示意图标,它的值是一个图片文件名称,这个图片文件必须放到前面提到的portal/images目录下。它由mainSkin、sectionSkin、componentSkin、iconSkin、echartStyle五部分内容组成。 - mainSkin标签中的内容为整体皮肤的主皮肤内容,这个标签下的name标签表示主皮肤的名称,注意主皮肤名称不能含有特殊字符。这个标签下的code标签内容标识主皮肤样式文件,必须与ZIP压缩包中portal\pagelayout\skin下的CSS文件名称保持一致。(注意:系统预制的门户模板导出的ZIP包中,这个文件名称跟code可能会不一样,但如果我们想修改这个文件内容,并将这个文件导入,则这个文件名称必须跟code保持一致)
- sectionSkin标签中的内容为整体皮肤的栏目外框样式内容,这个标签下的name标签表示栏目外框样式的名称,注意栏目外框样式名称不能含有特殊字符。这个标签下的code标签内容标识栏目外框样式文件,必须与ZIP压缩包中portal\sections\skin下的CSS文件名称保持一致。(注意:系统预制的门户模板导出的ZIP包中,这个文件名称跟code可能会不一样,但如果我们想修改这个文件内容,并将这个文件导入,则这个文件名称必须跟code保持一致),icon标签表示整体皮肤的示意图标,它的值是一个图片文件名称,这个图片文件必须放到前面提到的portal/images目录下。
- componentSkin标签中的内容为整体皮肤的栏目外框样式内容,这个标签下的name标签表示栏目外框样式的名称,注意栏目外框样式名称不能含有特殊字符。这个标签下的code标签内容标识栏目外框样式文件,必须与ZIP压缩包中portal\sections\skin下的CSS文件名称保持一致。(注意:系统预制的门户模板导出的ZIP包中,这个文件名称跟code可能会不一样,但如果我们想修改这个文件内容,并将这个文件导入,则这个文件名称必须跟code保持一致)
- iconSkin标签中的内容为整体皮肤的图标风格,这个标签下的name标签表示图标风格的名称,注意图标风格名称不能含有特殊字符。这个标签下的code标签内容标识图标风格:0标识线性;1标识面型,目前系统只支持这两种类型的图标风格。(如果输入其他内容,则系统图标风格将出现问题)
echartStyle标签中的内容为整体皮肤的图表风格,这个标签下的name标签表示图表风格的名称。这个标签下的code标签内容标识图表风格。code和name的值要求有对应关系,系统只支持下表中的图表风格(如果输入其他内容,则系统图标风格将出现问题)
(4)< elements/>:标签表示门户模板中的门户元素集合,这个标签下包含一个或多个
标签。每个 标签有code和name两个字标签。code标签的值必须与ZIP压缩包中portal\pagelayout\element下的存在对应的三个文件:code.html、code.js、code.css。 (5)< hotspots/>:标签表示门户模板中的热点数据集合,这个标签下包含一个或多个
标签。每个 标签有key和value两个字标签。key标签的值标识某个热点,value是热点数据,热点数据的格式为JSON,JSON数据中含有的数据跟具体热点有关,这里不做详细说明。 【需要拷贝到服务器上的图片资源文件夹】:这个目录为为门户模板中CSS、JS和HTML文件中直接引用的图片资源文件的存放路径。(注意:只能放到这个目录,否则系统不能识别)
最后附上一个完整的import.xml文件,如下图所示:
可以定制化的内容
- 修改门户模板的布局
- 修改门户模板的主皮肤
- 修改门户模板的栏目外框样式
- 修改门户模板的二级页面组件样式
- 修改门户模板的图标风格
- 修改门户模板的图表风格
- 新增门户元素
去掉门户元素,例如去掉幻灯片元素。
上面列出的可定制化内容,1、2、3、4主要是修改css文件内容或者是热点数据中的某个热点值来实现,这个比较简单,不做详细说明;5和6是指定一个风格即可,也比较简单。对于7这种情况来说稍微复杂点,但代码开发工作也并不大,关键是遵循我们前面介绍的内容进行扩展。
第一个例子
下面以一个具体例子来说明:比如我们要把现有【网站式信息门户】门户模板的幻灯片元素替换为一个新元素,为了降低学习门槛,我们还是以helloworld作为入门例子,假设这个元素我们叫做helloworld,元素代码为tpl-helloworld,这个门户元素的展现效果为只输出一个文本hello world!
开发步骤:
第一步:解压导出的门户ZIP包; 第二步:在目录portal\pagelayout\element中新建门户元素的三个文件:tpl-helloworld.html、tpl-helloworld.js、tpl-helloworld.css。内容分别如下所示:
tpl-helloworld.html文件的内容如下:
<script id="tpl-helloworld" type="text/html">
<div class="helloworld" onclick=” vPortalMainFrameElements.helloworld. showMessage();” title="{{ d.name }}" >{{ d }}</div>
</script>
tpl-helloworld.js文件的内容如下:
vPortalMainFrameElements.helloworld = {
config : false,// 标识该门户元素是否可以在门户设计器中对元素属性进行设置:true标识可以,false标识不可以。
getData : function() {
return "hello world!";
},
afterInit : function() {
//元素在标准渲染流程结束后执行的内容
},
getProp : function(_dataJson) {
window.parent.changeRightTitle('helloworld设置');
return {};
},
onPropChange : function(json, id, key, value) {
// TODO在门户设计器使用,但门户元素属性发生变化时,会调用此方法,但注意此方法不需要对数据进行进行持久化。
},
saveProp : function() {
// TODO 保存门户元素属性值,注意此方法此方法需要对数据进行持久化,例如保存到数据库中。
},
showMessage: function(){
alert("hello!");
}
}
tpl-helloworld.css文件的内容如下:
.helloworld{
color:red;
text-align:center;
}
第三步:修改门户布局html文件layout02_b.html,将helloworld元素绑定到门户模板布局上,内容如下图红框中的内容:
第四步:修改门户布局文件名称,将layout02_b.html修改为layout02_001html,将layout02_b.js修改为layout02_001.js,将layout02_b.css修改为layout02_001.css,修改后的文件如下图所示:
第五步:修改import.xml文件中的下述helloworld相关部分的内容:
<?xml version="1.0" encoding="UTF-8"?>
<portal version="1.0" vendor="www.seeyon.com" type="0">
<theme>
<name>helloworld门户</name>
<icon>helloworld.jpg</icon>
<layout>
<code>layout02</code>
<styleCode>layout02_001</styleCode>
<icon>layout02_b.jpg</icon>
<name>layout02</name>
</layout>
<elements>
<element>
<code>tpl-wideLogo</code>
<name>宽尺寸的单位logo元素</name>
</element>
<element>
<code>tpl-concurrentAccount</code>
<name>兼职单位元素</name>
</element>
<element>
<code>tpl-topRightsystemOperation</code>
<name>顶部系统操作按钮元素</name>
</element>
<element>
<code>tpl-miniNav</code>
<name>顶部极简版导航-包含门户、空间、菜单、第三方系统、项目空间等</name>
</element>
<element>
<code>tpl-helloworld</code>
<name>helloworld</name>
</element>
<element>
<code>tpl-showNavSpaceMenu</code>
<name>导航-空间下的菜单,当鼠标hover至空间时展现</name>
</element>
<element>
<code>tpl-messageBottom</code>
<name>底部弹出的消息盒子</name>
</element>
。。。。。。
注意:helloworld.jpg为我们自己找的一张图片,作为我们这个新的门户模板的示例图标。
第六步:重新打包成ZIP包,文件名称无特殊要求。
第七步:以集团管理员或单位管理员登录系统,将ZIP导入门户模板。
至此,门户模板定制完毕。
栏目布局定制
栏目布局ZIP包介绍
进入【栏目布局库】,选择“网站式信息门户”导出,如下图:
导出的ZIP包目录结构如下图所示:
- portal\decoration\layout\D1-M_T:为栏目布局文件layout.html所在目录,其中D-M_T为栏目布局唯一标识。栏目布局文件layout.html内容如下:
<div class="container">
<div class="row">
<div class="col-12 col">
<div class="fragment" id="fragment_0_0" x="0" y="0" swidth="12" celladd="true" maxsection="-1"></div>
</div>
</div>
</div>
其中, class="row"表示一行,class="col-12 col"标识一列,col-12标识这一列宽度比例(注意:一行的宽度分成12等份),如果用col-12则标识这一列占满了整行。class="fragment" 标识栏目片段集合,可以配置下表中的属性:
属性标识 | 属性名称 | 说明 |
---|---|---|
id | 栏目片段唯一标标识 | 格式必须是fragment_y_x |
x | x坐标 | |
y | y坐标 | |
sWidth | 栏目片段所在盒子容器的宽度 也是用来标识该栏目是宽栏目还是窄栏目 | |
cellAdd | cellAdd属性目前只有默认布局中的模板4用到。 | |
maxSection | 可以显示的最大栏目数 默认为-1,标识不限制。 |
portal\images:为栏目布局预览图标文件所在目录。
import.xml:为栏目布局元数据描述文件,内容如下所示:
1. <?xml version="1.0" encoding="UTF-8"?> <portal version="1.0" vendor="www.seeyon.com" type="decoration"> <decoration> <code>D1-M_T</code> <name>模板1</name> <icon>space_edit_layout_1.png</icon> </decoration> </portal>
可以定制化的内容
1.修改栏目布局示例图标; 2.修改栏目布局名称; 3.修改栏目布局标识; 4.修改栏目布局,比如调整栏目宽度比例,增加一行栏目等。
第二个例子
下面以一个具体的例子来说明如何对栏目布局进行修改。比如我们要做一个下图所示的布局:
开发步骤如下: 第一步:根据前面“栏目布局ZIP包介绍”,我们可以写出这个栏目布局的layout.html文件,如下所示:
<div class="container">
<div class="row">
<div class="col-12 col">
<div class="fragment" id="fragment_0_0" x="0" y="0" swidth="12" celladd="true" maxsection="-1"></div>
</div>
</div>
<div class="row">
<div class="col-3 col">
<div class="fragment" id="fragment_1_0" x="0" y="1" swidth="3" celladd="true" maxsection="-1"></div>
</div>
<div class="col-3 col">
<div class="fragment" id="fragment_1_1" x="1" y="1" swidth="3" celladd="true" maxsection="-1"></div>
</div>
<div class="col-3 col">
<div class="fragment" id="fragment_1_2" x="2" y="1" swidth="3" celladd="true" maxsection="-1"></div>
</div>
<div class="col-3 col">
<div class="fragment" id="fragment_1_3" x="3" y="1" swidth="3" celladd="true" maxsection="-1"></div>
</div>
</div>
<div class="row">
<div class="col-2 col">
<div class="fragment" id="fragment_2_0" x="0" y="2" swidth="2" celladd="true" maxsection="-1"></div>
</div>
<div class="col-4 col">
<div class="fragment" id="fragment_2_1" x="1" y="2" swidth="4" celladd="true" maxsection="-1"></div>
</div>
<div class="col-6 col">
<div class="fragment" id="fragment_2_2" x="2" y="2" swidth="6" celladd="true" maxsection="-1"></div>
</div>
</div>
</div>
第二步:修改import.xml文件中的code和name,假设code我们命名为custom_001,name我们命名为自定义栏目布局01,icon修改为custom_001.png。修改后的内容如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<portal version="1.0" vendor="www.seeyon.com" type="decoration">
<decoration>
<code>custom_001</code>
<name>自定义栏目布局01</name>
<icon>custom_001.png</icon>
</decoration>
</portal>
第三步:将ZIP包中路径portal\decoration\layout\D1-M_T修改为portal\decoration\layout\custom_001。 第四步:将custom_001.png图片放到ZIP包路径portal\images下。 第五步:将修改后的内容重新打一个ZIP包,然后重新导入系统即可。导入系统后,可以对该布局进行编辑,可以查看定制的布局是否显示正确。
栏目外框定制
栏目外框ZIP包介绍
进入【栏目外框库】,选择“栏目外框01”导出,获得门户模板ZIP包。然后解压如下图:
导出的ZIP包的目录结构如下图所示:
portal\images\section_01.png:该图片为栏目外框的预览图片。
portal\sections\skin\01.css:该文件为栏目外框的样式文件。
portal\import.xml:该文件为栏目外框的元数据描述文件,内容如下图所示:
sectionSkin标签中的内容为栏目外框样式内容,这个标签下的name标签表示栏目外框样式的名称,注意栏目外框样式名称不能含有特殊字符。这个标签下的code标签内容标识栏目外框样式文件,必须与ZIP压缩包中portal\sections\skin下的CSS文件名称保持一致。(注意:系统预制的栏目外框模板导出的ZIP包中,这个文件名称跟code可能会不一样,但如果我们想修改这个文件内容,并将这个文件导入,则这个文件名称必须跟code保持一致),icon标签表示栏目外框的示意图标,它的值是一个图片文件名称,这个图片文件必须放到前面提到的portal/images目录下。 栏目外框的热点数据如下表所示:
可以定制化的内容
- 修改栏目外框的code、name和icon
- 修改栏目外框的样式文件内容
- 修改栏目外框的热点数据
第三个例子
例如我们要导入一个栏目外框模板,栏目外框带边框,边框颜色为蓝色,边框圆角为10,栏目内容背景色为黄色,栏目外框标识为custom_001,栏目外框名称为自定栏目外框001,栏目外框示意图修改为custom_001.png,则需要做如下修改: 主要修改下图中import.xml文件中标黄部分的内容:
然后将上述内容达成压缩包,重新导入系统即可。
1.4.2. 基于代码开发的定制
门户模板的组成
门户模板由门户布局(含门户元素)、门户主皮肤样式、栏目外框样式、二级页面样式、图标样式、图表样式组成。
注册门户模板
在安装目录文件/webapps/seeyon /portal/config/portal_themes/portal_themes_pc.xml中注册PC门户模板,添加内容如下所示:
PortalTheme标签表示一个门户模板。
id表示门户模板的唯一标识,PC的门户模板以20开头,移动的门户模板以21开头,登录前门户以22开头,大 屏门户以23开头,必须全为数字,同时要确保唯一性。 code标识门户模板的代码,建议英文字符+数字,确保唯一性。 name标识门户模板的名称,不能含有特殊字符。 acountId预制门户的单位ID,统一设置为0即可。 systeminit:是否为预制,这里填写为1,标识为预制。 sort:标识门户模板的显示顺序。 previewImg:标识为门户模板的预览示意图。 isdelete:标识是否删除,这里一般为0即可。 type:标识门户模板类型:0标识为PC,1标识为移动;2标识为登录前,3标识为大屏 注意:如果是移动门户模板,则需要在文件portal_themes_mobile.xml中注册;如果是登录前门户,则需要在文件portal_themes_loginPre.xml中注册;如果是大屏门户,则需要在文件portal_themes_bigScreen.xml中注册。
注册整体皮肤
在安装目录文件/webapps/seeyon/portal/config/portal_skin_set/portal_skin_set_pc.xml中注册PC门户的整体皮肤,添加内容如下所示:
PortalSkinSet标签标识一套门户整体皮肤; id唯一标识整体皮肤;PC门户整体皮肤从40开始,移动门户整体皮肤从41开始,登录前门户整体皮肤从42开始,大屏门户整体皮肤从43开始;且必须是数字类型。
code表示整体皮肤代码; name表示整体皮肤的名称,不能有特殊字符; msid表示门户主皮肤ID ssid表示门户栏目外框样式ID csid表示二级页面组件样式ID iconid表示门户图标风格ID echartStyleid表示门户图表样式ID deft表示是否为系统默认 sysinit表示是否为系统预制 sort表示整体皮肤排序 imageOrColor表示整体皮肤的预览示意图; type:标识整体皮肤类型:0标识为PC,1标识为移动;2标识为登录前,3标识为大屏 注意:如果是移动门户模板,则需要在文件portal_skin_set _mobile.xml中注册;如果是登录前门户,则需要在文件portal_skin_set_loginPre.xml中注册;如果是大屏门户,则需要在文件portal_skin_set_bigScreen.xml中注册。
注册门户模板与整体皮肤的绑定关系
在安装目录文件/webapps/seeyon /portal/config/portal_skin_choice/portal_skin_choice.xml中注册门户模板与整体皮肤的绑定关系,添加内容如下所示:
PortalSkinChoice标签标识门户模板绑定哪套整体皮肤; id是门户模板与整体皮肤绑定关系的唯一标识;
templateId为门户模板ID; entityType为组织模型类型,这里默认为group; entityId为组织模型I,这里默认为0; currentAccountid为当前单位ID,这里默认为0; skinStyle表示整体皮肤ID;
开发和注册门户皮肤
在安装目录文件/webapps/seeyon /portal/config/portal_skins/portal_skins_pc.xml中注册PC门户的主框架皮肤,添加内容如下所示:
PortalSkin标签标识一个皮肤样式文件; id标识皮肤的唯一标识;PC门户主框架样式皮肤以30开头;PC门户栏目外框样式皮肤以34开头;PC门户二级页面样式皮肤以37开头;移动端门户皮肤以31开头;登录前门户皮肤以32开头;大屏皮肤以33开头;
code标识皮肤的代码; name标识皮肤的名称; path标识皮肤css文件所在的路径,其中文件内容需要遵循CSS规范; stype标识皮肤类型:0为PC普通门户;1为移动门户;2为登录前门户;3为大屏门户; image标识皮肤预览图片; sysinit标识是否系统初始化; sort标识排序; isdelete标识是否删除; accountId标识单位ID,预制的默认都为0。 注意:如果为移动门户皮肤,则需要在portal_skins_mobile.xml文件中注册;如果为大屏门户皮肤,则需要在portal_skins_bigScreen.xml文件中注册;如果为登录前门户,则在portal_skins_loginPre.xml文件中注册。如果为栏目外框皮肤,则在portal_skins_section.xml文件中注册;如果为二级页面组件皮肤,则在portal_skins_section.xml文件中注册。
开发和注册门户布局
在安装目录/webapps/seeyon/portal/pagelayout/layout下新建一个门户布局目录layout_c001,然后在此目录下新建三个文件:layout_c001_a.html、layout_c001_a.css、layout_c001_a.js,并根据需求开发对应内容。 在安装目录文件/webapps/seeyon/portal/config/portal_template/portal_template_pc.xml中注册该门户布局,添加内容如下所示:
新建门户模板图片资源存放位置
在安装目录/webapps/seeyon/portal/pagelayout/layout/ layout_c001下新建一个图片资源目录images,新开发的门户模板中用到的图片资源必须都放到这个目录下,例如html文件中使用的图片文件,css文件中使用的图片文件,js文件中使用的图片文件,所有使用图片文件都必须使用全路径引用/seeyon/portal/pagelayout/layout/ layout_c001/images/xxx.png,图片资源支持gif、png和jpg三种格式。
开发和注册门户元素
在安装目录/webapps/seeyon/portal/pagelayout/element/custom下新建为每个门户元素新建三个文件:tpl-xxx.html、tpl-xxx.css、tpl-xxx.css。 在安装目录文件/webapps/seeyon/portal/config/portal_laytpl_template/elements.xml中注册改门户模板,添加内容如下所示:
开发和注册栏目
第一步:栏目模板开发 栏目模板是指栏目长的是什么样子,例如列表样子、棋盘样式、图片轮播样式等,一个栏目模板由4个文件组成:1个html文件、1个js文件、1个css文件和1个java文件,其中html文件必须遵循laytpl模板引擎语法,1个java文件必须实现com.seeyon.ctp.portal.section.templete. BaseSectionTemplete基类,以目前系统中已有栏目模板横幅模板为例,所包含的内容如下表所示:
模板标识 | 模板名称 | 组成文件 |
---|---|---|
bannerTemplete | 横幅模板 | tpl-bannerTemplete.html |
tpl-bannerTemplete.js | ||
tpl-bannerTemplete.css | ||
com.seeyon.ctp.portal.section.templete.BannerTemplete |
在确定了栏目要显示哪些内容后,就可以按照上面的示例内容进行栏目模板的开发。
在安装目录文件/webapps/seeyon/portal/config/portal_laytpl_template/sections.xml中注册该栏目模板,添加内容如下所示:
第二步:实现栏目后台java接口 PC和移动统一在同一个接口类com.seeyon.ctp.portal.section. BaseSection中定义,同时返回BaseSectionTemplete的栏目模板实例。具体定义如下:
•PC接口
public abstract BaseSectionTemplete projection(Map<String, String> preference);
•移动接口
public abstract BaseSectionTemplete mProjection(Map<String, String> preference);
第三部:在spring xml配置文件中注册栏目接口和配置栏目属性
以横幅栏目实现类BannerSection为例,在spring xml配置文件中的配置信息如下图所示:
一、栏目可以配置的属性如下表所示:
1.一个栏目属性一般通过下面几个方面的信息进行描述清楚:
2.支持的栏目属性数据类型
支持的数据类型如下表所示:
3. 一个具体栏目可以配置1到n个上述栏目属性。
注意:一个属性可以在PC端和移动端同时使用,也可以不同时使用,这个是通过在属性配置增加如下内容来配置区分:
二、栏目的分类和所属空间配置:
开发和注册栏目依赖的第三方js文件
如果栏目有依赖的第三js文件,则需要单独在配置文件中配置,配置文件所在位置为/webapps/seeyon/portal/config/portal_section_jsfiles/pc.xml,内容如下图所示:
thirdJsFiles标签声明一个第三方js文件,它包含jsFileName、jsFilePath和jsFileDescript; sectionTpl标签声明一个栏目模板依赖哪些第三方js文件,其中tplId为栏目模板标识;thirdJsFileNames标签中为所有用到的第三方js文件名称。 注意:如果为移动端栏目一栏的第三方js文件则需要在/webapps/seeyon/portal/config/portal_section_jsfiles/mobile.xml中进行配置注册。
注册门户模板热点
以安装目录文件/webapps/seeyon /portal/config/portal_hotspot/portal_hotspot_theme_pc_01.xml该文件为例进行说明,当我们新增了一个门户模板时,需要在/webapps/seeyon /portal/config/portal_hotspot/目录下新增一个门户默认热点配置xml文件,文件的内容要跟portal_hotspot_theme_pc_01.xml一样,主要是把main要配置好,其它可以不配置,如下图所示:
<?xml version="1.0" encoding="UTF-8"?>
<PortalHotspots>
<PortalHotspot>
<id>4285973905855824829</id>
<templateid>2000000001</templateid>
<name>hotspot.name.style.main</name>
<hotspotkey>main</hotspotkey>
<hotspotvalue>{"tid":"1000000001","msid":"3000000001","ssid":"3400000001","csid":"3700000001","iconid":"1","echartStyleId":"1"}</hotspotvalue>
<module>1</module>
<tiling>0</tiling>
<entityId>0</entityId>
<entityLevel>Group,Account,Member</entityLevel>
<display>1</display>
<ext4>0</ext4>
<ext10>4000000001</ext10>
</PortalHotspot>
</PortalHotspots>
PortalHotspot标识一个热点数据; id为热点数据的唯一标识; templateid为门户模板ID; name为热点名称,一般为国际化资源key; hotspotkey为热点key,这里为main; hotspotvalue为热点值,这里为一个json字符串,tid为门户布局ID,msid为门户主框架皮肤ID,ssid为栏目外框皮肤ID;csid为门户二级页面组件皮肤ID,iconid为门户图标样式风格,echartStyleId为门户图表风格ID。
ext10为整体皮肤的ID。
重启A8服务
重启A8服务后,以集团管理员登录系统,进入【V-Portal配置平台-》整体样式库】中可以看到我们刚才开发好的门户模板,如下图所示:
特别说明
如果导出门户模板ZIP包,有名称为【需要拷贝到服务器上的图片资源文件夹】的目录,且该目录下存在图片文件,在从A系统导入到另B系统中时,如果B系统是集群环境,则需要将该目录下的子目录seeyon拷贝覆盖到B系统所在每台服务器的seeyon目录,否则门户模板引用了图片的地方会显示不正常,严重的,可能会影响系统的正常使用。(注意单机环境不需要手动拷贝,静态资源目录会随着ZIP包一起导入服务器对应目录下)
另外在导入门户资源包之前最好将门户模板ZIP包中所有的html、js和css文件检查一遍,确保对图片资源文件的路径引用是正确的,且import.xml文件中的
1.4.3. 其它API使用说明
第三方菜单接口
接口定义
接口类:com.seeyon.ctp.portal.menu.PortalThirdMenuInterface
接口方法:
/**
* 菜单数据是否有更新
* @param memberId
* @param accountId
* @param isAdmin
* @return
*/
public boolean isNeedUpdate(Long memberId, Long accountId, boolean isAdmin);
/**
* 获取当前人员的菜单列表
* @param memberId
* @param accountId
* @param isAdmin
* @return
* @throws BusinessException
*/
public List<MenuBO> getMenusOfMember(Long memberId, Long accountId, boolean isAdmin) throws BusinessException;
示例
第一步:开发一个实现类,如下所示:
import java.util.ArrayList;
import java.util.List;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.login.bo.MenuBO;
import com.seeyon.ctp.util.UUIDLong;
public class PortalThirdMenuImpl implements PortalThirdMenuInterface {
@Override
public boolean isNeedUpdate(Long memberId, Long accountId, boolean isAdmin) {
return false;
}
@Override
public List<MenuBO> getMenusOfMember(Long memberId, Long accountId, boolean isAdmin) throws BusinessException {
List<MenuBO> list= new ArrayList<MenuBO>();
MenuBO menuBO01= new MenuBO(UUIDLong.longUUID(), 999, "我的菜单01", "", "", "http://www.baidu.com", "");
MenuBO menuBO02= new MenuBO(UUIDLong.longUUID(), 1, "我的菜单02", "", "", "http://www.baidu.com", "");
MenuBO menuBO03= new MenuBO(UUIDLong.longUUID(), 2, "我的菜单03", "", "", "http://www.baidu.com", "");
menuBO01.addItem(menuBO02);
menuBO01.addItem(menuBO03);
list.add(menuBO01);
return list;
}
}
第二步:在spring的XML文件中将实现类注册为一个bean,如下所示:
<bean id="portalThirdMenuImpl" class="com.seeyon.ctp.portal.menu.PortalThirdMenuImpl" />
第三步:重启服务,重新登录后,可以看到如下效果:
指定访问某个空间的接口
接口定义
访问地址:http://ip地址:端口/seeyon/portal/spaceController.do?method=showThemSpace&spaceId=空间ID 其中空间ID,可以从空间管理列表中获得,如下图所示:
示例
指定访问门户下某个空间的接口
接口定义
访问地址http:// ip地址:端口/seeyon/main.do?method=main&portalId=门户ID&spaceId=空间ID 其中portalId为门户ID,spaceId为空间ID。
示例
http://localhost:8999/seeyon/main.do?method=main&portalId=1&spaceId=343537485881493171
注意:7.1版本登录前空间才支持这种方式直接访问。
应用磁贴接口
接口定义
首先,我们先看下应用磁贴的配置界面,如下图:
从上图可以看出,要将指标接入到上面的配置界面,开发者需要实现下面的接口。
数据接口 接口类:com.seeyon.ctp.portal.portlet.manager.BasePortletCategory 接口类的方法定义如下:
/**
* 主分类ID
*/
public String getCategoryId();
/**
* 名称
*/
public String getCategoryName();
/**
* 排序号
*/
public Integer getCategoryOrder();
/**
* 根据spaceType控制是否显示该分类
*/
public boolean isAllowUsed(Map<String, Object> param);
/**
* 二级分类( 展现方式支持:列表/树结构/iframe)
*/
public SubCategory getSubCategory(Map<String, Object> params);
/**
* 获取二级分类下对应磁贴
* @return
*/
public List<ImagePortletLayout> getPortletDeskDatas(String subCategoryKey, Map<String, Object> params);
/**
* 获取指定磁贴
* @param params { "subCategory" : "", "portletId" : "" }
* @return
*/
public ImagePortletLayout getPortletProperty(Map<String, Object> params);
/**
* 获取数据总数
* 不需要统计数据的请返回-1
*/
public int getPortletTipNumber(String portletId);
/**
* 获取数据总数
* 不需要统计数据的请返回-1
*/
public int getPortletTipNumber(Map<String,Object> params);
/**
* 获取个人移动端,待添加磁贴
* 标准应用 - 1,定制应用 - 2,更多应用 - 3
*/
public Map<String, List<ImagePortletLayout>> getMobilePortlets(String string);
/**
* 批量权限校验
*/
public Map<String,ImagePortletLayout> doBatchAuthCheck(PortalCustomizeMenuParam authParam);
样式接口 当系统默认提供的磁贴样式无法满足客户需求时,磁贴栏目就需要扩展出现满足客户个性化的磁贴样式模板。为了实现磁贴样式的扩展,开发人员需要实现下面的接口。
接口定义:
XML配置文件 /seeyon/portal/shortCut/config/Magnettemplete_pc.xml(PC端配置) /seeyon/portal/shortCut/config/Magnettemplete_mobile.xml(移动端配置)
栏目样式配置联动 /seeyon/portal/shortCut/config/iconTypeStyle_pc.json(PC端磁贴样式) /seeyon/portal/shortCut/config/iconTypeStyle_mobile.json(移动端磁贴样式)
示例
数据接口 JAVA类:
public class ThirdPartyCategory implements BasePortletCategory {
private static final Logger log = Logger.getLogger(ThirdPartyCategory.class);
private PortalConfigManager portalConfigManager;
private PortalApi portalApi;
private CipPendingApi cipPendingApi;
private AppManager appManager;
public void setPortalConfigManager(PortalConfigManager portalConfigManager) {
this.portalConfigManager = portalConfigManager;
}
public void setPortalApi(PortalApi portalApi) {
this.portalApi = portalApi;
}
public void setCipPendingApi(CipPendingApi cipPendingApi) {
this.cipPendingApi = cipPendingApi;
}
@Override
public String getCategoryId() {
return "thirdPartyCategory";
}
@Override
public String getCategoryName() {
return ResourceUtil.getString("desk.metro.other");
}
@Override
public Integer getCategoryOrder() {
return 10;
}
@Override
public SubCategory getSubCategory(Map<String, Object> params) {
SubCategory ctgPortlet = new SubCategory();
String spaceType = ParamUtil.getString(params, "spaceType");
if ("m3mobile,weixinmobile".contains(spaceType)) {
ctgPortlet.addSubCategorys(new String[] { "mobileApp", ResourceUtil.getString("shortcut.config.thirdparty.register") });
ctgPortlet.addSubCategorys(new String[] { "singleURL", ResourceUtil.getString("shortcut.config.link.url") });
} else {
if(!"before_login".equals(spaceType)){
ctgPortlet.addSubCategorys(new String[] { "thirdPartyApp", ResourceUtil.getString("shortcut.config.thirdparty.register") });
}
// 指定url
ctgPortlet.addSubCategorys(new String[] { "singleURL", ResourceUtil.getString("shortcut.config.link.url") });
// "关联系统"
ctgPortlet.addSubCategorys(new String[] { PortletCategory.linkSystemSpace.name(), ResourceUtil.getString("link.jsp.more.title") });
}
return ctgPortlet;
}
@Override
public List<ImagePortletLayout> getPortletDeskDatas(String subCategoryKey, Map<String, Object> params) {
List<ImagePortletLayout> layouts = new ArrayList<ImagePortletLayout>();
try {
if ("mobileApp".equals(subCategoryKey)) {
List<ThirdpartyPortalVo> list = portalConfigManager.getThirdpartyPortalByCondition(GuestType.M3);
getThirdPartyLayoutImage(layouts, list, "mobileApp");
} else if ("thirdPartyApp".equals(subCategoryKey)) {
List<ThirdpartyPortalVo> list = portalConfigManager.getThirdpartyPortalByCondition(GuestType.PC);
getThirdPartyLayoutImage(layouts, list, "thirdPartyApp");
} else {
return getLinkSystem(subCategoryKey, params,null);
}
} catch (BusinessException e) {
log.error("", e);
}
return layouts;
}
private String subStrUrl2FileId(String url) {
String fileId = "";
try {
if (Strings.isNotBlank(url)) {
int startIndex1 = url.indexOf("fileId=");
String s1 = url.substring(startIndex1 + 7);
fileId = s1;
int endIndex1 = s1.indexOf("&");
if (endIndex1 > -1) {
fileId = s1.substring(0, endIndex1);
}
}
} catch (Exception e) {
log.error("", e);
return fileId;
}
return fileId;
}
private void getThirdPartyLayoutImage(List<ImagePortletLayout> layouts, List<ThirdpartyPortalVo> list, String subCategoryKey) {
if (Strings.isNotEmpty(list)) {
for (ThirdpartyPortalVo t : list) {
layouts.add(getThirdpartyShorCut(subCategoryKey, t)) ;
}
}
}
/**
* 获取第三方磁贴
* @param subCategoryKey
* @param t
* @return
*/
private ImagePortletLayout getThirdpartyShorCut(String subCategoryKey, ThirdpartyPortalVo t) {
ImagePortletLayout layout = new ImagePortletLayout();
if (t != null) {
if(!CIPUtil.isPrePlugin(String.valueOf(t.getAppCode()))) {
return layout;
}
layout.setNeedNumber(Integer.valueOf(1));
layout.setPortletId(t.getId().toString());
layout.setDisplayName(t.getRegisterName());
layout.setPortletName(t.getRegisterName());
layout.setCategory(getCategoryId());
layout.setSubCategory(subCategoryKey);
layout.setId(t.getId() + "|" + subCategoryKey + "|" + getCategoryId());
layout.setPortletUrl("/thirdpartyController.do?method=show&id=" + t.getRegisterId() + "0&pageUrl=" + t.getPcPageUrl());
layout.setPortletUrlType(UrlType.open.name());
String appType = "";
String entry = "";
try {
if (t.getAccessMethod() == AccessTypeEnum.MobileURL.getKey() || t.getAccessMethod() == AccessTypeEnum.PCAndMobileURL.getKey()) {
appType = AppInfoVO.AppTypeEnums.integration_remote_url.getType();
entry= t.getH5Url();
} else if (t.getAccessMethod() == AccessTypeEnum.LocalApp.getKey() || t.getAccessMethod() == AccessTypeEnum.PCAndLocalApp.getKey()) {
appType =AppInfoVO.AppTypeEnums.integration_native.getType();
String cmd = t.getStartCommand();
if (Strings.isNotBlank(cmd)){
entry = appManager.replaceUserName(cmd, String.valueOf(t.getRegister().getAppCode()), t);
if (Strings.isNotBlank(entry) && entry.startsWith("[") && entry.endsWith("]")) {
Map<String, Object> entryMap = new HashMap<String, Object>();
List<Map<String, Object>> commList = JSONUtil.parseJSONString(entry, List.class);
for (Map<String, Object> commMap : commList) {
String phoneType = String.valueOf(commMap.get("phoneType"));
entryMap.put(phoneType, commMap);
}
entry =JSONUtil.toJSONString(entryMap);
}
}
} else if (t.getAccessMethod() == AccessTypeEnum.LocalH5.getKey() || t.getAccessMethod() == AccessTypeEnum.PCAndLocalH5.getKey()) {
appType = AppInfoVO.AppTypeEnums.integration_local_h5.getType();
M3AppVersion ver = appManager.findNewestVersion(String.valueOf(t.getRegister().getAppCode()));
if (ver != null) {
Map<String, Object> entryMap = new LinkedHashMap<String, Object>();
entryMap.put("bundle_identifier",ver.getBundleIdentifier());
entryMap.put("bundle_name",ver.getBundleName());
entryMap.put("team",ver.getTeam());
entryMap.put("version",ver.getVersion());
entryMap.put("entry",ver.getEntry());
entryMap.put("downloadUrl", "");
entryMap.put("appId", ver.getAppId());
entry =JSONUtil.toJSONString(entryMap);
}
}
Map<String, Object> entryMap = new LinkedHashMap<String, Object>();
entryMap.put("appId", t.getAppCode());
entryMap.put("appType", appType);
entryMap.put("entry", entry);
entryMap.put("appName", t.getRegisterName());
entryMap.put("hasPlugin", "");
layout.setMobileUrl("thirdparty|"+JSONUtil.toJSONString(entryMap));
List<ImageLayout> images = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageTitle(layout.getDisplayName());
image.setImageUrl("vp-application-third-party");
images.add(image);
layout.setImageLayouts(images);
} catch (BusinessException e) {
log.error(e.getMessage(),e);
}
}
return layout;
}
@Override
public boolean isAllowUsed(Map<String, Object> param) {
return true;
}
private ImagePortletLayout transThirdpartySpace2Laout(ThirdpartySpace thirdParty, User user) {
ImagePortletLayout layout = new ImagePortletLayout();
String pageUrl = thirdParty.getPageURL(user.getId(), user.getAccountId());
layout.setNeedNumber(Integer.valueOf(1));
layout.setPortletId(thirdParty.getId() + "");
layout.setDisplayName(thirdParty.getNameOfResouceBundle(user.getLocale()));
layout.setPortletUrl("/thirdpartyController.do?method=show&id=" + thirdParty.getId() + "&pageUrl=" + pageUrl);
layout.setPortletUrlType(UrlType.open.name());
layout.setCategory(getCategoryId());
layout.setSubCategory("sso");
layout.setId(thirdParty.getId() + "|sso|" + getCategoryId());
layout.setSize(PortletConstants.PortletSize.middle.ordinal());
List<ImageLayout> images = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageTitle(layout.getDisplayName());
image.setImageUrl("vp-space");
images.add(image);
layout.setImageLayouts(images);
return layout;
}
@Override
public ImagePortletLayout getPortletProperty(Map<String, Object> params) {
String subCategoryKey = ParamUtil.getString(params, "subCategory", "");
String portletId = ParamUtil.getString(params, "portletId", "");
try {
return getPortletDeskData(subCategoryKey, params, portletId);
} catch (BusinessException e) {
log.error(e.getMessage(), e);
}
return new ImagePortletLayout();
}
@Override
public int getPortletTipNumber(String portletId) {
int num=-1;
try{
num=cipPendingApi.getPendingCount(Long.parseLong(portletId),null);
}catch (Exception e){
log.error(e);
}
return num;
}
@Override
public int getPortletTipNumber(Map<String, Object> params) {
return -1;
}
@Override
public Map<String, List<ImagePortletLayout>> getMobilePortlets(String string) {
Map<String, List<ImagePortletLayout>> result = new HashMap<String, List<ImagePortletLayout>>();
List<ImagePortletLayout> layouts = new ArrayList<ImagePortletLayout>();
// 更多应用
try {
List<ThirdpartyPortalVo> thirds = portalConfigManager.getThirdpartyPortal4M3(AppContext.currentUserId());
getThirdPartyLayoutImage(layouts, thirds, "mobileApp");
} catch (BusinessException e) {
log.error("", e);
}
result.put("3", layouts);
return result;
}
private List<ImagePortletLayout> getLinkSystem(String subCategoryKey, Map<String, Object> params,String portalId) throws BusinessException {
List<ImagePortletLayout> layouts = new ArrayList<ImagePortletLayout>();
if ("singleURL".equals(subCategoryKey)) {
String portletId = "singleURLId";
if (params.containsKey("portletId")) {
portletId = params.get("portletId").toString();
}
ImagePortletLayout layout = new ImagePortletLayout();
layout.setPortletId(portletId);
layout.setDisplayName(ResourceUtil.getString("shortcut.config.link.url"));
layout.setPortletName(ResourceUtil.getString("shortcut.config.link.url"));
layout.setPortletUrl("");
layout.setPortletUrlType(UrlType.open.name());
layout.setId(layout.getPortletId() + "|singleURL|" + getCategoryId());
layout.setCategory(getCategoryId());
layout.setSubCategory(subCategoryKey);
//允许重复添加磁贴
layout.setCanRepeat(1);
layout.setSize(PortletConstants.PortletSize.middle.ordinal());
layout.setNeedNumber(Integer.valueOf(1));
List<ImageLayout> images = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageUrl("vp-favoritelinks");
images.add(image);
layout.setImageLayouts(images);
layouts.add(layout);
} else if ("linkSystemSpace".equals(subCategoryKey)) {
User user = AppContext.getCurrentUser();
List<PortalLinkSystem> linkSpace = null;
if (user.isAdministrator() || user.isGroupAdmin()) {
linkSpace = portalApi.findSysLinkSystem(user.getId());
} else {
linkSpace = portalApi.findSysLinkSystem(user.getId());
}
if (Strings.isNotEmpty(linkSpace)) {
for (PortalLinkSystem link : linkSpace) {
if(null!=portalId) {
if(!portalId.equals(String.valueOf(link.getId()))) {
continue;
}
}
ImagePortletLayout layout = new ImagePortletLayout();
layout.setNeedNumber(Integer.valueOf(1));
layout.setId(link.getId() + "|linkSystemSpace|" + getCategoryId());
layout.setCategory(getCategoryId());
layout.setSubCategory(subCategoryKey);
layout.setPortletId(link.getId().toString());
layout.setDisplayName(Strings.toHTML(link.getLname(),false));
layout.setPortletName(Strings.toHTML(link.getLname(),false));
layout.setPortletUrl("/portal/linkSystemController.do?method=linkConnect&linkId=" + link.getId());
layout.setPortletUrlType(UrlType.open.name());
List<ImageLayout> imageLayouts = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageUrl("vp-related");
String iconUrl = link.getImage();
if(Strings.isNotBlank(iconUrl) && iconUrl.indexOf("defaultLinkSystemImage") == -1){
if(iconUrl.indexOf("/seeyon") > -1){
iconUrl = iconUrl.substring(7);
}
image.setImageUrl(iconUrl);
image.setImageId(this.subStrUrl2FileId(iconUrl));
}
imageLayouts.add(image);
layout.setImageLayouts(imageLayouts);
layouts.add(layout);
}
}
}
return layouts;
}
private ImagePortletLayout getPortletDeskData(String subCategoryKey, Map<String, Object> params,String portletId) throws BusinessException {
ImagePortletLayout layout = new ImagePortletLayout();
User user = AppContext.getCurrentUser();
if ("mobileApp".equals(subCategoryKey) || "thirdPartyApp".equals(subCategoryKey)) {
ThirdpartyPortalVo portavo = portalConfigManager.getThirdpartyPortalShortCut(user.getId(),"mobileApp".equals(subCategoryKey) ? GuestType.M3 : GuestType.PC, portletId);
return getThirdpartyShorCut(subCategoryKey, portavo);
} else {
List<ImagePortletLayout> otherPortlet = getLinkSystem(subCategoryKey, params, portletId);
if (CollectionUtils.isNotEmpty(otherPortlet)) {
return otherPortlet.get(0);
}
}
return layout;
}
public void setAppManager(AppManager appManager) {
this.appManager = appManager;
}
@Override
public Map<String, ImagePortletLayout> doBatchAuthCheck(PortalCustomizeMenuParam authParam) {
String categoryId= authParam.getCategoryId();
Set<String> subCategorySet= authParam.getSubCategorySet();
Set<String> portletIdSet= authParam.getPortletIdSet();
Map<String, Set<String>> subCateGory2PortletIdsMap= authParam.getSubCateGory2PortletIdsMap();
String spaceType= authParam.getSpaceType();
Map<String,ImagePortletLayout> imagePortletLayoutMap = new HashMap<String,ImagePortletLayout>();
if( null!=portletIdSet && !portletIdSet.isEmpty() ){
try {
User user = AppContext.getCurrentUser();
if (subCategorySet.contains("mobileApp")) {
String subCategoryKey= "mobileApp";
Set<String> subCateGory2PortletIds= subCateGory2PortletIdsMap.get("mobileApp");
if(null!=subCateGory2PortletIds && !subCateGory2PortletIds.isEmpty()){
for (String portletId : subCateGory2PortletIds) {
ThirdpartyPortalVo portavo = portalConfigManager.getThirdpartyPortalShortCut(user.getId(),GuestType.M3,portletId);
ImagePortletLayout layout= getThirdpartyShorCut(subCategoryKey, portavo);
imagePortletLayoutMap.put(portletId, layout);
}
}
}
if (subCategorySet.contains("thirdPartyApp")) {
String subCategoryKey= "thirdPartyApp";
Set<String> subCateGory2PortletIds= subCateGory2PortletIdsMap.get("thirdPartyApp");
if(null!=subCateGory2PortletIds && !subCateGory2PortletIds.isEmpty()){
for (String portletId : subCateGory2PortletIds) {
ThirdpartyPortalVo portavo = portalConfigManager.getThirdpartyPortalShortCut(user.getId(),GuestType.PC,portletId);
ImagePortletLayout layout= getThirdpartyShorCut(subCategoryKey, portavo);
imagePortletLayoutMap.put(portletId, layout);
}
}
}
if(subCategorySet.contains("singleURL")){//第三方URL
Set<String> subCateGory2PortletIds= subCateGory2PortletIdsMap.get("singleURL");
if(null!=subCateGory2PortletIds && !subCateGory2PortletIds.isEmpty()){
for (String portletId : subCateGory2PortletIds) {
ImagePortletLayout layout = new ImagePortletLayout();
layout.setPortletId(portletId);
layout.setDisplayName(ResourceUtil.getString("shortcut.config.link.url"));
layout.setPortletName(ResourceUtil.getString("shortcut.config.link.url"));
layout.setPortletUrl("");
layout.setPortletUrlType(UrlType.open.name());
layout.setId(layout.getPortletId() + "|singleURL|" + getCategoryId());
layout.setCategory(getCategoryId());
layout.setSubCategory("singleURL");
//允许重复添加磁贴
layout.setCanRepeat(1);
layout.setSize(PortletConstants.PortletSize.middle.ordinal());
layout.setNeedNumber(Integer.valueOf(1));
List<ImageLayout> images = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageUrl("vp-favoritelinks");
images.add(image);
layout.setImageLayouts(images);
imagePortletLayoutMap.put(portletId, layout);
}
}
}
if(subCategorySet.contains("linkSystemSpace")){//关联系统
Set<String> subCateGory2PortletIds= subCateGory2PortletIdsMap.get("linkSystemSpace");
if(null!=subCateGory2PortletIds && !subCateGory2PortletIds.isEmpty()){
List<PortalLinkSystem> linkSpace = null;
if (user.isAdministrator() || user.isGroupAdmin()) {
linkSpace = portalApi.findSysLinkSystem(user.getId());
} else {
linkSpace = portalApi.findSysLinkSystem(user.getId());
}
if (Strings.isNotEmpty(linkSpace)) {
for (PortalLinkSystem link : linkSpace) {
String portletId= link.getId().toString();
if(subCateGory2PortletIds.contains(portletId)){
ImagePortletLayout layout = new ImagePortletLayout();
layout.setNeedNumber(Integer.valueOf(1));
layout.setId(link.getId() + "|linkSystemSpace|" + getCategoryId());
layout.setCategory(getCategoryId());
layout.setSubCategory("linkSystemSpace");
layout.setPortletId(link.getId().toString());
layout.setDisplayName(Strings.toHTML(link.getLname(),false));
layout.setPortletName(Strings.toHTML(link.getLname(),false));
layout.setPortletUrl("/portal/linkSystemController.do?method=linkConnect&linkId=" + link.getId());
layout.setPortletUrlType(UrlType.open.name());
List<ImageLayout> imageLayouts = new ArrayList<ImageLayout>();
ImageLayout image = new ImageLayout();
image.setImageUrl("vp-related");
String iconUrl = link.getImage();
if(Strings.isNotBlank(iconUrl) && iconUrl.indexOf("defaultLinkSystemImage") == -1){
if(iconUrl.indexOf("/seeyon") > -1){
iconUrl = iconUrl.substring(7);
}
image.setImageUrl(iconUrl);
image.setImageId(this.subStrUrl2FileId(iconUrl));
}
imageLayouts.add(image);
layout.setImageLayouts(imageLayouts);
imagePortletLayoutMap.put(portletId, layout);
}
}
}
}
}
} catch (BusinessException e) {
log.error(e.getMessage(), e);
}
}
return imagePortletLayoutMap;
}
XML配置文件:
<bean name="thirdPartyCategory" class="com.seeyon.ctp.portal.portlet.ThirdPartyCategory"/>
样式接口 在/seeyon/portal/shortCut/config/Magnettemplete_mobile.xml中添加扩展模板,多彩卡片1,如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<MagnetTemplete>
<shortcutStyle>
<style>
<name>多彩1</name>
<value>1</value>
<i18nname>shortcut.config.property.column.style.1</i18nname>
<tpltemplete>mIconTemplete</tpltemplete>
</style>•
<style>
<name>多彩2</name>
<value>2</value>
<i18nname>shortcut.config.property.column.style.2</i18nname>
<tpltemplete>mIconTemplete</tpltemplete>
</style>
<style>
<name>简约1</name>
<value>3</value>
<i18nname>shortcut.config.property.column.style.3</i18nname>
<tpltemplete>mIconTemplete</tpltemplete>
</style>
<style>
<name>简约2</name>
<value>4</value>
<i18nname>shortcut.config.property.column.style.4</i18nname>
<tpltemplete>mIconTemplete</tpltemplete>
</style>
<style>
<name>图片式</name>
<value>5</value>
<i18nname>shortcut.config.property.column.style.5</i18nname>
<tpltemplete>mIconTempletePicture</tpltemplete>
</style>
<style>
<name>多彩卡片1</name>
<value>6</value>
<i18nname>shortcut.config.property.column.style.6</i18nname>
<tpltemplete>mIconTempleteColorfulCard1</tpltemplete>
</style>
</shortcutStyle>
</MagnetTemplete>
在/seeyon/portal/sections/tpl_mobile目录中新创建的模板文件tpl-mIconTempleteColorfulCard1.html、tpl-mIconTempleteColorfulCard1.js和tpl-mIconTempleteColorfulCard1.css。
在/seeyon/portal/shortcut/config/iconTypeStyle_mobile.json配置文件中添加多彩卡片1的样式联动配置,如下:
[{
"tpltemplete": "mobile1",
"propertys": [
{
"name": "iBGCType",
"showConfig": true
},
{
"name": "iconColor",
"showConfig": true,
"default": "#ffffff",
"background":"#ffffff"
},{
"name":"fontColor",
"showConfig":true,
"default":"#666"
}]
},
{
"tpltemplete": "mobile2",
"propertys": [
{
"name": "iBGCType",
"showConfig": true
},
{
"name": "iconColor",
"showConfig": true,
"default": "#ffffff"
},{
"name":"fontColor",
"showConfig":true,
"default":"#666"
}]
},{
"tpltemplete": "mobile3",
"propertys": [
{
"name": "iconColor",
"showConfig": true,
"default": "#64d0c6;#1f85ec;#5246c5;#ff6d68;#26a3ed;#f9b954;#24bde3;#00d58b"
},{
"name":"fontColor",
"showConfig":true,
"default":"#666"
},{
"name": "iBGCType_iconColor",
"showConfig": true,
"default": "#64d0c6;#1f85ec;#5246c5;#ff6d68;#26a3ed;#f9b954;#24bde3;#00d58b"
}]
}, {
"tpltemplete": "mobile4",
"propertys": [
{
"name": "iconColor",
"showConfig": true,
"default": "#64d0c6;#1f85ec;#5246c5;#ff6d68;#26a3ed;#f9b954;#24bde3;#00d58b"
},{
"name":"fontColor",
"showConfig":true,
"default":"#666"
},{
"name": "iBGCType_iconColor",
"showConfig": true,
"default": "#64d0c6;#1f85ec;#5246c5;#ff6d68;#26a3ed;#f9b954;#24bde3;#00d58b"
}]
},
{
"tpltemplete": "mobile5",
"propertys": [
{
"name": "showName",
"showConfig": true,
"default": "1"
},{
"name": "borderRadius",
"showConfig": true,
"default": "5"
},{
"name":"imageShowType",
"showConfig":true,
"default":"scalingAdaptive"
},{
"name":"fontColor",
"showConfig": true,
"default": "#666"
}]
},
{
"tpltemplete": "mobile6",
"propertys": [
{
"name": "iBGCType",
"showConfig": true
},
{
"name": "iconColor",
"showConfig": true,
"default": "#fff"
},{
"name": "borderRadius",
"showConfig": true,
"default": "5"
},{
"name":"fontColor",
"showConfig":true,
"default":"#fff"
}]
}
}]
指标数据接口
接口定义
首先,我们先看下指标数据的配置界面,如下图:
从上图可以看出,要将指标接入到上面的配置界面,开发者需要实现下面的接口。
接口类:com.seeyon.ctp.portal.quota.BaseQuotaCategory 接口类的方法定义如下:
public interface BaseQuotaCategory {
/**
* 主分类ID
* @return
*/
public String getCategoryId();
/**
* 名称
* @return
*/
public String getCategoryName();
/**
* 排序号
* @return
*/
public Integer getCategoryOrder();
/**
* 根据相关参数判断是否可以展示
* @param param
* @return
*/
public boolean isAllowUsed(Map<String, Object> param);
/**
* 二级分类( 展现方式支持:列表/树结构/iframe)
* @param params
* @return
*/
public QuotaSubCategory getSubCategory(Map<String, Object> params) throws BusinessException;
/**
* 获取二级分类所有可以选择的指标内容
* @param subCategoryKey
* @param params
* @return
*/
public List<QuotaContextBo> getAllCanSelectInSubCategory(String subCategoryKey, Map<String, Object> params);
/**
* 获取指定的指标内容
* @param params { "subCategory" : "", "portletId" : "" }
* @return
*/
public QuotaContextBo getQuotaContentByProperty(Map<String, Object> params);
/**
* 无权限数据展示的时候请过滤掉
* 获取展示需要的数据
* element.put("realValue", result.getRealValue());真实的值
* element.put("display", result.getDisplay());格式化展示的值
* element.put("name", result.getName());展示的title
* element.put("designId", result.getDesignId().toString());对应的二级分类id
* @param params
* @return
*/
public List<Map<String, Object>> getShowQuotaData(Map<String,Object> params);
}
实现上面的接口后,需要将实现类作为bean注册Spring的XML配置文件中去即可。
示例
Java实现类
public class CollaborationQuotaCategory implements BaseQuotaCategory {
private static final Log LOGGER = LogFactory.getLog(CollaborationQuotaCategory.class);
private PendingManager pendingManager;
private List<CollabortaionQuotaSubBo> collabortaionQuotaSubBoList;
private MyProcessInformationManager myProcessInformationManager;
private BpmPortalManager bpmPortalManager;
private OrgManager orgManager;
public PendingManager getPendingManager() {
return pendingManager;
}
public void setPendingManager(PendingManager pendingManager) {
this.pendingManager = pendingManager;
}
public List<CollabortaionQuotaSubBo> getCollabortaionQuotaSubBoList() {
return collabortaionQuotaSubBoList;
}
public void setCollabortaionQuotaSubBoList(List<CollabortaionQuotaSubBo> collabortaionQuotaSubBoList) {
this.collabortaionQuotaSubBoList = collabortaionQuotaSubBoList;
}
public MyProcessInformationManager getMyProcessInformationManager() {
return myProcessInformationManager;
}
public void setMyProcessInformationManager(MyProcessInformationManager myProcessInformationManager) {
this.myProcessInformationManager = myProcessInformationManager;
}
public BpmPortalManager getBpmPortalManager() {
return bpmPortalManager;
}
public void setBpmPortalManager(BpmPortalManager bpmPortalManager) {
this.bpmPortalManager = bpmPortalManager;
}
public OrgManager getOrgManager() {
return orgManager;
}
public void setOrgManager(OrgManager orgManager) {
this.orgManager = orgManager;
}
enum CollaborationQuotaCategoryEnum{
PENDINGDATA_QUOTA("pendingDataQuota"), //待办事项
PROCESSMYSUPERVISE_ALL_QUOTA("processMySuperviseAllQuota"), //流程督办监控-我督办的--全部未办结数量
PROCESSMYSUPERVISE_OVERDUE_QUOTA("processMySuperviseOverDueQuota"), //流程督办监控-我督办的--超期数量
PROCESSMYSUPERVISE_SEVENDAYOVERDUE_QUOTA("processMySuperviseSevenDayOverdueQuota"), //流程督办监控-我督办的--七天内超期
PROCESSMYDEPT_ALL_QUOTA("processMyDeptAllQuota"), //程督办监控-我本部门的--全部数量
PROCESSMYDEPT_OVERDUE_QUOTA("processMyDeptOverDueQuota"), //程督办监控-我本部门的--超期数量
PROCESSMYDEPT_SEVENDAYOVERDUE_QUOTA("processMyDeptSevenDayOverdueQuota"), //程督办监控-我本部门的--七天内超期
PROCESSMYTEMPLATE_ALL_QUOTA("processMyTemplateAllQuota"), //流程督办监控-我管理的模板--全部数量
PROCESSMYTEMPLATE_OVERDUE_QUOTA("processMyTemplateOverDueQuota"), //流程督办监控-我管理的模板--超期数量
PROCESSMYTEMPLATE_SEVENDAYOVERDUE_QUOTA("processMyTemplateSevenDayOverdueQuota"), //流程督办监控-我管理的模板--七天内超期
PROCESSMYAUTHORITY_AUDIT_QUOTA("processMyAuthorityAuditQuota"), //流程审批权
PROCESSMYAUTHORITY_DEAL_QUOTA("processMyAuthorityDealQuota"), //流程处理权
PROCESSMYAUTHORITY_INFORM_QUOTA("processMyAuthorityInformQuota"), //流程知会权
PROCESSMYAUTHORITY_SUPERVISE_QUOTA("processMyAuthoritySuperviseQuota"); //流程督办权
private String key;
CollaborationQuotaCategoryEnum( String key) {
this.key = key;
}
public String getKey() {
return key;
}
public static CollaborationQuotaCategoryEnum getEnumByCode(String code){
for(CollaborationQuotaCategoryEnum en : CollaborationQuotaCategoryEnum.values()){
if(code.equals(en.getKey())){
return en;
}
}
return null;
}
}
@Override
public String getCategoryId() {
return "collaborationQuotaCategory";
}
@Override
public String getCategoryName() {
return ResourceUtil.getString("portal.section.quota.collaboration");
}
@Override
public Integer getCategoryOrder() {
return 2;
}
@Override
public boolean isAllowUsed(Map<String, Object> param) {
return true;
}
@Override
public QuotaSubCategory getSubCategory(Map<String, Object> params) throws BusinessException {
QuotaSubCategory quotaSubCategory=new QuotaSubCategory();
for (CollabortaionQuotaSubBo subBo : collabortaionQuotaSubBoList) {
if("processMyDept".equals(subBo.getId())) {
if(!AppContext.hasPlugin("workflowAdvanced") || !checkAuthForQuota("deptAdmin")) {
continue;
}
}
if("processMyTemplate".equals(subBo.getId())) {
if(!AppContext.hasPlugin("workflowAdvanced") || !checkAuthForQuota("formAdmin")) {
continue;
}
}
String spaceType = subBo.getSpaceType();
boolean isAdd=true;
if(Strings.isNotBlank(spaceType)){
Object spaceTypePass = params.get("spaceType");
String spaceTypePassStr=null;
if(spaceTypePass!=null){
spaceTypePassStr=spaceTypePass.toString();
}
if(spaceTypePassStr!=null&&spaceType.indexOf(spaceTypePassStr)>-1){
isAdd=true;
}else {
isAdd=false;
}
}
if(isAdd){
String[] category = {subBo.getId(), ResourceUtil.getString(subBo.getShowName())};
quotaSubCategory.addSubCategorys(category);
}
}
return quotaSubCategory;
}
@Override
public List<QuotaContextBo> getAllCanSelectInSubCategory(String subCategoryKey, Map<String, Object> params) {
List<QuotaContextBo> quotaContextBos=new ArrayList<QuotaContextBo>();
CollabortaionQuotaSubBo selectSubBo=null;
for(CollabortaionQuotaSubBo subBo:collabortaionQuotaSubBoList){
String subBoId = subBo.getId();
if(subBo.getId().equals(subCategoryKey)){
selectSubBo=subBo;
break;
}
}
if(selectSubBo!=null){
quotaContextBos=selectSubBo.getQuotaContextBos();
for(QuotaContextBo bo:quotaContextBos){
bo.setQuotaName(ResourceUtil.getString(bo.getQuotaName()));
if("pendingDataQuota".equals(bo.getQuotaId())){
bo.setQuotaName(ResourceUtil.getString("portal.section.quota.prendData"));
}
}
}
return quotaContextBos;
}
@Override
public QuotaContextBo getQuotaContentByProperty(Map<String, Object> params) {
QuotaContextBo bo=null;
String quotaId = ParamUtil.getString(params, "quotaId", null);
String subCategoryId=ParamUtil.getString(params,"subCategoryId",null);
List<QuotaContextBo> allCanSelectInSubCategory = getAllCanSelectInSubCategory(subCategoryId, null);
for(QuotaContextBo tempBo:allCanSelectInSubCategory){
if(tempBo!=null&"aId.equals(tempBo.getQuotaId())){
bo=tempBo;
}
}
return bo;
}
@Override
public List<Map<String, Object>> getShowQuotaData(Map<String, Object> params) {
List<Map<String, Object>> quotaData=new ArrayList<Map<String, Object>>();
String uuids = ParamUtil.getString(params, "uuids", null);
String quotaIds = ParamUtil.getString(params, "quotaIds", null);
Map<String,QuotaContextBo> quotaPropertyMap = (Map<String,QuotaContextBo>)params.get("quotaPropertyMap");
if(Strings.isNotBlank(uuids)&&Strings.isNotBlank(quotaIds)){
String[] uuidArray = uuids.split(",");
String[] quotaIdsArray=quotaIds.split(",");
if(uuidArray.length==quotaIdsArray.length){
Map<String,String> dataMap = new HashMap<String, String>();
for(int m=0;m<uuidArray.length;m++){
String uuid=uuidArray[m];
QuotaContextBo bo = quotaPropertyMap.get(uuid);
String quotaId=quotaIdsArray[m];
Map<String, Object> data = getQuotaData(quotaId, bo ,dataMap);
if(data!=null){
quotaData.add(data);
}
}
}
}
return quotaData;
}
/**
* 获取展示需要的数据
* element.put("realValue", result.getRealValue());真实的值
* element.put("display", result.getDisplay());格式化展示的值
* element.put("name", result.getName());展示的title
* element.put("designId", result.getDesignId().toString());对应的二级分类id
* @return
*/
private Map<String, Object> getQuotaData(String quotaId,QuotaContextBo bo,Map<String,String> dataMap){
Map<String,String> paramMap=null;//查询参数
String name=bo.getQuotaName();
Map<String, Object> quotaDataMap=new HashMap<String, Object>();//指标相关数据
if(bo!=null&&bo.getSpMap()!=null){
paramMap=transQuotaMap(bo.getSpMap());
name=paramMap.get("columnsName");
}
Long id = bo.getId();
CollaborationQuotaCategoryEnum en = CollaborationQuotaCategoryEnum.getEnumByCode(quotaId);
if(en != null) {
String dataCount = "0";
String quotaMoreUrl = "";
String openType="workspace";
switch (en) {
case PENDINGDATA_QUOTA://待办事项
if(paramMap==null){
paramMap= Collections.emptyMap();
}
int count=pendingManager.getPendingCount(AppContext.currentUserId(),paramMap,false);
dataCount = String.valueOf(count);
quotaMoreUrl = "/collaboration/pending.do?method=morePending&propertyFrom=quota&propertyId="+ id;
quotaDataMap.put("mQuotaMoreUrl","/seeyon/m3/apps/v5/portal/html/morePending.html?openFrom=listPending&propertyFrom=quota&propertyId="+ id);
break;
case PROCESSMYAUTHORITY_AUDIT_QUOTA://流程审批权
dataCount = myProcessInformationManager.processAuthorityCountByType("audit");
quotaMoreUrl = "/myProcessInformationController.do?method=myProcessInformation"aType=" + "audit";
break;
case PROCESSMYAUTHORITY_DEAL_QUOTA://流程处理权
dataCount = myProcessInformationManager.processAuthorityCountByType("deal");
quotaMoreUrl = "/myProcessInformationController.do?method=myProcessInformation"aType=" + "deal";
break;
case PROCESSMYAUTHORITY_INFORM_QUOTA://流程知会权
dataCount = myProcessInformationManager.processAuthorityCountByType("inform");
quotaMoreUrl = "/myProcessInformationController.do?method=myProcessInformation"aType=" + "inform";
break;
case PROCESSMYAUTHORITY_SUPERVISE_QUOTA://流程督办权
dataCount = myProcessInformationManager.processAuthorityCountByType("supervise");
quotaMoreUrl = "/myProcessInformationController.do?method=myProcessInformation"aType=" + "supervisor";
break;
case PROCESSMYSUPERVISE_ALL_QUOTA://流程督办监控-我督办的--全部未办结数量
if(!checkAuthForQuota("mySupervise")) {
return null;
}
Map<String, Object> mySuperviseAllMap= new HashMap<String, Object>();
mySuperviseAllMap.put("managerType", "mySupervise");
mySuperviseAllMap.put("quotaType", "all");
dataCount = bpmPortalManager.getColQuotaForSection(mySuperviseAllMap);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=mySupervise"aType=all";
break;
case PROCESSMYSUPERVISE_OVERDUE_QUOTA://流程督办监控-我督办的--超期数量
if(!checkAuthForQuota("mySupervise")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"mySupervise",0);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=mySupervise"aType=overdue";
break;
case PROCESSMYSUPERVISE_SEVENDAYOVERDUE_QUOTA://流程督办监控-我督办的--七天内超期
if(!checkAuthForQuota("mySupervise")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"mySupervise",1);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=mySupervise"aType=sevenDayOverdue";
break;
case PROCESSMYDEPT_ALL_QUOTA://流程督办监控-我本部门的--全部数量
if(!checkAuthForQuota("deptAdmin")) {
return null;
}
Map<String, Object> myDeptAllMap= new HashMap<String, Object>();
myDeptAllMap.put("managerType", "deptAdmin");
myDeptAllMap.put("quotaType", "all");
dataCount = bpmPortalManager.getColQuotaForSection(myDeptAllMap);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=deptAdmin"aType=all";
break;
case PROCESSMYDEPT_OVERDUE_QUOTA://流程督办监控-我本部门的--超期数量
if(!checkAuthForQuota("deptAdmin")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"deptAdmin",0);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=deptAdmin"aType=overdue";
break;
case PROCESSMYDEPT_SEVENDAYOVERDUE_QUOTA://流程督办监控-我本部门的--七天内超期
if(!checkAuthForQuota("deptAdmin")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"deptAdmin",1);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=deptAdmin"aType=sevenDayOverdue";
break;
case PROCESSMYTEMPLATE_ALL_QUOTA://流程督办监控-我管理的模板--全部数量
if(!checkAuthForQuota("formAdmin")) {
return null;
}
Map<String, Object> myTemplateAllMap= new HashMap<String, Object>();
myTemplateAllMap.put("managerType", "formAdmin");
myTemplateAllMap.put("quotaType", "all");
dataCount = bpmPortalManager.getColQuotaForSection(myTemplateAllMap);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=formAdmin"aType=all";
break;
case PROCESSMYTEMPLATE_OVERDUE_QUOTA://流程督办监控-我管理的模板--超期数量
if(!checkAuthForQuota("formAdmin")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"formAdmin",0);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=formAdmin"aType=overdue";
break;
case PROCESSMYTEMPLATE_SEVENDAYOVERDUE_QUOTA://流程督办监控-我管理的模板--七天内超期
if(!checkAuthForQuota("formAdmin")) {
return null;
}
dataCount = dealWithDataCount(dataMap,"formAdmin",1);
quotaMoreUrl = "/supervise/supervise.do?method=superviseFrame"aManagerType=formAdmin"aType=sevenDayOverdue";
break;
default:
return null;
}
quotaDataMap.put("urlOpenType",openType);
quotaDataMap.put("realValue",dataCount);
quotaDataMap.put("display",dataCount);
quotaDataMap.put("quotaMoreUrl",quotaMoreUrl);
}
quotaDataMap.put("name",ResourceUtil.getString(name));
quotaDataMap.put("designId",bo.getSubCategoryId());
quotaDataMap.put("quotaId",id);
return quotaDataMap;
}
private String dealWithDataCount(Map<String,String> dataMap,String managerType,int index) {
String dataCount = "0";
if(dataMap.get(managerType) != null) {
dataCount = dataMap.get(managerType);
} else {
Map<String, Object> mySuperviseOverDueMap= new HashMap<String, Object>();
mySuperviseOverDueMap.put("managerType", managerType);
dataCount = bpmPortalManager.getColQuotaForSection(mySuperviseOverDueMap);
dataMap.put(managerType,dataCount);
}
if(dataCount.contains(",")) {
dataCount = dataCount.split(",")[index];
}
return dataCount;
}
private Map<String,String> transQuotaMap(Map<String,Object> params){
Map<String,String> map=new HashMap<String, String>();
Set<String> keySet = params.keySet();
for(String key:keySet){
Object valueObj = params.get(key);
if(valueObj!=null&&(valueObj instanceof String)){
if(key.endsWith(":0")){
String newkey=key.substring(0,key.length()-2);
map.put(newkey,valueObj.toString());
}
}
}
return map;
}
private boolean checkAuthForQuota(String managerType) {
User user = AppContext.getCurrentUser();
if("mySupervise".equals(managerType)) {
if(user.hasResourceCode("F01_supervise")) {
return true;
}
} else {
List<MemberRole> memberRoles = null;;
try {
memberRoles = orgManager.getMemberRoles(user.getId(),null);
} catch (BusinessException e) {
LOGGER.error("获取人员角色异常", e);
}
if(Strings.isNotEmpty(memberRoles)) {
if("formAdmin".equals(managerType)) {
for(MemberRole role : memberRoles) {
if("FormAdmin".equals(role.getRole().getName())) {
return true;
} else if("BusinessDesigner".equals(role.getRole().getName())){
return true;
}
}
}else if("deptAdmin".equals(managerType)) {
for(MemberRole role : memberRoles) {
if("DepManager".equals(role.getRole().getName())) {
return true;
}
}
}
}
}
return false;
}
}
XML配置文件:
<bean id="collaborationQuotaCategory" class="com.seeyon.ctp.portal.portlet.CollaborationQuotaCategory">
<property name="collabortaionQuotaSubBoList">
<list>
<bean class="com.seeyon.ctp.portal.portlet.CollabortaionQuotaSubBo">
<property name="showName" value="portal.section.quota.prendData"/>
<property name="id" value="pendingData"/>
<property name="quotaContextBos">
<list>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="pendingDataQuota"/>
<property name="subCategoryId" value="pendingData"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="portal.section.quota.prendData"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="common.my.pending.title" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="common.my.pending.title" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="panel" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="cannel.panel.label" />
<property name="valueType" value="5" />
<property name="defaultValue" value="all" />
<property name="valueRanges">
<list>
<!-- 全部待办 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeImpl">
<property name="subject" value="pending.panel.all.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="readOnly" value="false" />
<property name="value" value="all" />
</bean>
<!-- 指定发起人 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeImpl">
<property name="subject" value="pending.panel.sender.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="sender" />
<property name="backUp" value="true" />
<property name="panelSetUrl" value="/selectPeople.do?ViewPage=SelectPeople4PortalSender&amp;Panels=Department,Team,Post,Outworker,RelatePeople,BusinessDepartment&amp;SelectType=Account,Department,Team,RelatePeople,Post,Member,BusinessDepartment,BusinessAccount&amp;id=portalSender&amp;include=true"></property>
</bean>
<!-- 组合来源 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeImpl">
<property name="subject" value="collaboration.pending.panel.combination.sources" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="sources" />
<property name="backUp" value="true" />
<property name="valueRangeExtraSelects">
<list>
<!-- 流程分类 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="template.section.choose.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="track_catagory" />
<property name="panelSetUrl" value="/portalAffair/portalAffairController.do?method=showPortalCatagory&amp;openFrom=pendingSection" />
</bean>
<!-- 应用或节点权限 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="pending.panel.policy.or.other.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="Policy" />
<property name="panelSetUrl" value="permission/permission.do?method=showPerom4Portal&amp;openFrom=pendingSection" />
</bean>
<!-- 模板分类-->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.template.toolbar.category" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="templete_pending" />
<property name="panelSetUrl" value="template/template.do?method=templateChooseMul&amp;type=-1&amp;isPortal=1&amp;isMul=true&amp;scope=MaxScope&amp;isCanSelectCategory=true&amp;isShowTemplateRecentDeal=true&amp;isAlwaysShowTemplateCommon=true&amp;openFrom=pendingSection" />
</bean>
<!-- 指定重要紧急程度 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="pending.panel.importlevel.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="importLevel" />
<property name="panelSetUrl" value="/portalAffair/portalAffairController.do?method=showPortalImportLevel&amp;openFrom=pendingSection" />
</bean>
<!-- 超期待办 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.overTime.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="overTime" />
</bean>
<!-- 办理状态 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.handlingState.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="handlingState" />
<property name="panelSetUrl" value="collaboration/pending.do?method=handlingState" />
</bean>
<!-- 领导发给我的 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.my.leader.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="myLeader" />
</bean>
<!-- 本部门的 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.my.dept.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="myDept" />
</bean>
<!-- 加签给我的 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.add.to.me.label" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="value" value="addToMe" />
</bean>
<!-- 条件关系 -->
<bean class="com.seeyon.ctp.portal.section.SectionReferenceValueRangeExtraSelectImpl">
<property name="subject" value="collaboration.pending.panel.relation" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="showCheckBox" value="false"/>
<property name="value" value="relation" />
<property name="select">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionExtraDataSelectImpl">
<property name="key" value="1" />
<property name="value" value="and" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionExtraDataSelectImpl">
<property name="key" value="0" />
<property name="value" value="or" />
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- 流程督办监控-我督办的 -->
<bean class="com.seeyon.ctp.portal.portlet.CollabortaionQuotaSubBo">
<property name="showName" value="bpm.portal.quota.processMySupervise"/>
<property name="id" value="processMySupervise"/>
<property name="spaceType" value="personal,cooperation_work"/>
<property name="quotaContextBos">
<list>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMySuperviseAllQuota"/>
<property name="subCategoryId" value="processMySupervise"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.processMySupervise.allQuota"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.processMySupervise.allQuota" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.processMySupervise.allQuota" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMySuperviseOverDueQuota"/>
<property name="subCategoryId" value="processMySupervise"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.overDue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMySuperviseSevenDayOverdueQuota"/>
<property name="subCategoryId" value="processMySupervise"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.sevenDayOverdue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- 流程督办监控-我本部门的 -->
<bean class="com.seeyon.ctp.portal.portlet.CollabortaionQuotaSubBo">
<property name="showName" value="bpm.portal.quota.processMyDept"/>
<property name="id" value="processMyDept"/>
<property name="spaceType" value="personal,cooperation_work"/>
<property name="quotaContextBos">
<list>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyDeptAllQuota"/>
<property name="subCategoryId" value="processMyDept"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.all"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.all" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.all" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyDeptOverDueQuota"/>
<property name="subCategoryId" value="processMyDept"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.overDue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyDeptSevenDayOverdueQuota"/>
<property name="subCategoryId" value="processMyDept"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.sevenDayOverdue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- 流程督办监控-我管理的模板 -->
<bean class="com.seeyon.ctp.portal.portlet.CollabortaionQuotaSubBo">
<property name="showName" value="bpm.portal.quota.processMyTemplate"/>
<property name="id" value="processMyTemplate"/>
<property name="spaceType" value="personal,cooperation_work"/>
<property name="quotaContextBos">
<list>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyTemplateAllQuota"/>
<property name="subCategoryId" value="processMyTemplate"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.all"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.all" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.all" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyTemplateOverDueQuota"/>
<property name="subCategoryId" value="processMyTemplate"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.overDue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.overDue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyTemplateSevenDayOverdueQuota"/>
<property name="subCategoryId" value="processMyTemplate"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.sevenDayOverdue"/>
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.sevenDayOverdue" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- 我的权限数据 -->
<bean class="com.seeyon.ctp.portal.portlet.CollabortaionQuotaSubBo">
<property name="showName" value="bpm.portal.quota.processMyAuthority"/>
<property name="id" value="processMyAuthority"/>
<property name="spaceType" value="personal,cooperation_work,m3mobile"/>
<property name="quotaContextBos">
<list>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyAuthorityAuditQuota"/>
<property name="subCategoryId" value="processMyAuthority"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.processMyAuthority.audit"/><!-- 流程审批权 -->
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.audit" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.audit" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyAuthorityDealQuota"/>
<property name="subCategoryId" value="processMyAuthority"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.processMyAuthority.deal"/><!-- 流程处理权 -->
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.deal" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.deal" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyAuthorityInformQuota"/>
<property name="subCategoryId" value="processMyAuthority"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.processMyAuthority.inform"/><!-- 流程知会权 -->
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.inform" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.inform" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
<bean class="com.seeyon.ctp.portal.quota.QuotaContextBo">
<property name="quotaId" value="processMyAuthoritySuperviseQuota"/>
<property name="subCategoryId" value="processMyAuthority"/>
<property name="categoryId" value="collaborationQuotaCategory"/>
<property name="quotaName" value="bpm.portal.quota.processMyAuthority.supervise"/><!-- 流程督办权 -->
<property name="sectionProperty">
<bean class="com.seeyon.ctp.portal.section.SectionPropertyImpl">
<property name="reference">
<list>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="columnsName" />
<property name="spaceType" value="defaultPC" />
<property name="subject" value="portal.setcion.quota.showName" />
<property name="valueType" value="2" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.supervise" />
</bean>
<bean class="com.seeyon.ctp.portal.section.SectionReferenceImpl">
<property name="name" value="onlyShowName" />
<property name="spaceType" value="defaultPC,m3mobile" />
<property name="subject" value="portal.section.quota.onlyShowName" />
<property name="valueType" value="2" />
<property name="readOnly" value="true" />
<property name="defaultValue" value="bpm.portal.quota.processMyAuthority.supervise" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
最终看到的效果如下图:
栏目样式扩展接口
接口定义
XML配置文件接口
移动端配置文件 /seeyon/portal/config/portal_section_style/sectionStyleConfig_mobile.xml
PC端配置文件 /seeyon/portal/config/portal_section_style/sectionStyleConfig_pc.xml
XML配置文件格式如下
<section>
<sectionBeanId>knowledgeUsedDocCollectSection</sectionBeanId>
<sectionStyle>
<value>add6</value>
<i18nname>图标+文字(双行右滑)</i18nname>
<tpltemplete>mIconFontTwolineRSlideTemplate</tpltemplete>
</sectionStyle>
</section>
sectionBeanId对应的是栏目的ID。 sectionStyle为样式标签,value为样式标识,i18nname为样式名称,tpltemplete为独立的模板名称(假设叫XXX),这个地方配置名称在后面会用到。 在/seeyon/portal/sections/tpl_mobile(移动端)或/seeyon/portal/sections/tpl (PC端)下新建tpl-XXX.js、tpl-XXX.css和tpl-XXX.html三个文件。 修改栏目实现类代码(可选) 如果样式展示的数据与原来已经有的内容数据结构不同需要根据选择的样式内容对栏目进行兼任处理。
示例
例如我们要为栏目knowledgeUsedDocCollectSection扩展一种新的移动端样式,我们首先找到sectionStyleConfig_mobile.xml文件,并在该文件中添加如下配置内容:
<section>
<sectionBeanId>knowledgeUsedDocCollectSection</sectionBeanId>
<sectionStyle>
<value>add6</value>
<i18nname>图标+文字(双行右滑)</i18nname>
<tpltemplete>mIconFontTwolineRSlideTemplate</tpltemplete>
</sectionStyle>
</section>
然后,在移动栏目模板目录/seeyon/portal/sections/tpl_mobile下新增三个文件:tpl-mIconFontTwolineRSlideTemplate.js、tpl-mIconFontTwolineRSlideTemplate.html和tpl-mIconFontTwolineRSlideTemplate.css
最后,样式展示的数据与原来已经有的内容数据结构不同需要根据选择的样式内容对栏目进行兼任处理,对KnowledgeUsedDocCollectSection.java类做如下修改:
if ("add6".equals(columnsStyle)) {
if (Constants.isImgFile(res.getMimeTypeId())) {
row.setIcon("" + res.getSourceId());
} else if (res.getCoverImageId() != null) {
row.setIcon("" + res.getCoverImageId());
} else {
//row.setIcon(SystemEnvironment.getContextPath() + "/portal/images/doc/doc.jpg");
}
} else {
row.setIcon(getIconClassForVjoin(type, mine_type));
}
}
重启服务后,我们在移动端空间设计中会看到此栏目多了一种样式,如下图:
空间事件接口
接口定义
事件类 事件名称 com.seeyon.ctp.portal.space.event.AddSpaceEvent 新增空间事件 com.seeyon.ctp.portal.space.event.UpdateSpaceEvent 修改空间事件 com.seeyon.ctp.portal.space.event.DeleteSpaceEvent 删除空间事件
在进行对应新建、修改、删除时都会触发相关事件内容。如果要对其进行处理可以对事件进行监听。三类事件中都包含PortalSpaceFix(空间的详细信息),List
示例
@ListenEvent(event = AddSpaceEvent.class)
public void onAddSpace(AddSpaceEvent evt) throws Exception {
int spaceType = evt.getSpaceFix().getType();
Long spaceId = evt.getSpaceFix().getId();
String spaceName = evt.getSpaceFix().getSpacename();
int flag = com.seeyon.v3x.news.util.Constants.TYPE_FLAG_NORMAL;
if (evt.getSpaceFix().getSpacePubinfoEnable() != null && evt.getSpaceFix().getSpacePubinfoEnable().intValue() == 0) {
flag = com.seeyon.v3x.news.util.Constants.TYPE_FLAG_DISABLE;
}
if (spaceType == Constants.SpaceType.custom.ordinal()) {
newsTypeManager.saveCustomNewsType(spaceId, spaceName, spaceType, flag);
}
}
图标库接口
第一种调用方式
接口定义
这调用方式如下图所示:
接口方法:iconLibrary(oprate,styleId,saveSelectIconFunction,showType) 接口所在文件路径:/seeyon/common/all-min.js 接口参数说明:
示例
iconLibUploadDialog(function(_icon){
if (_icon && _icon.length > 0) {
var menuicon="";
if (_icon[0] == '1') {
var iconName = _icon[1];
$(".addPicShade .addPic span").attr("class", "vportal " + replaceMagnetIcon(iconName));
$("#portletImg").hide();
$(".addPicShade").show();
menuicon=iconName;
} else {
$("#portletImg").attr("src", _ctxPath + "/fileUpload.do?method=showRTE&type=image&fileId=" + _icon[1] + CsrfGuard.getUrlSurffix());
$(".addPicShade").hide();
$("#portletImg").show();
menuicon="/fileUpload.do?method=showRTE&type=image&fileId=" + _icon[1];
}
var nodes=portalCustomizeMenuzTreeObj.getSelectedNodes();
if(nodes.length>0){
nodes[0].menuicon=menuicon;
if(menuicon.match("vp-")){
$('#'+ nodes[0].tId+"_a").find('span.menuStyleIcon').attr('class',"menuStyleIcon iconstyle vportal "+menuicon);
$('#'+ nodes[0].tId+"_a").find('span.menuStyleIcon1').attr('class',"menuStyleIcon1 iconstyle vportal "+menuicon);
}else{
$('#'+ nodes[0].tId+"_a").find('span.menuStyleIcon').attr('class',"menuStyleIcon").css('backgroundImage','url(/seeyon'+menuicon+')');
$('#'+ nodes[0].tId+"_a").find('span.menuStyleIcon1').attr('class',"menuStyleIcon1").css('backgroundImage','url(/seeyon'+menuicon+')');
}
}
}
}, “line”);
第二种调用方式
接口定义
这调用方式如下图所示:
接口方法:iconLibrary(oprate,styleId,saveSelectIconFunction,showType) 接口所在文件路径:/seeyon/common/all-min.js 接口参数说明:
示例
$("#iconLib").click(function () {
iconLibrary("chooseOne", 1, function (r) {
var img = r;
var imgRef = $(".app-icon");
imgRef.attr("data-bizicontype", "1");
img = img.substr(1);
imgRef.attr("data-bizicon", img);
imgRef.attr("class", "app-icon vportal " + img);
imgRef.css('background-image', '');
}, "1");
});
图片库接口
接口定义
接口方法:selectPicture(msn,catagory,saveSelectImageIdFunction) 接口所在文件路径:/seeyon/common/all-min.js 接口参数说明:
示例
//移动门户设计器新增的上传增加方法
function uploadImg(_this, _tpl, _id) {
currentInput = _this;
currentUploadTpl = _tpl;
currentUploadId = _id;
selectPicture(1, "", mobileUploadImgBack);
}
function mobileUploadImgBack(_returnValue) {
$(currentInput).next().attr("value", "/seeyon/fileUpload.do?method=showRTE&fileId=" + _returnValue + "&type=image" + CsrfGuard.getUrlSurffix());
$(currentInput).next().val("/seeyon/fileUpload.do?method=showRTE&fileId=" + _returnValue + "&type=image" + CsrfGuard.getUrlSurffix());
styleChange(currentUploadTpl, currentUploadId, currentInput);
}
JS/CSS文件压缩混淆接口
接口定义
接口说明:为了提升系统性能,对于多个js文件一般采用压缩成一个js文件的方法进行处理。 之前的处理流程是需要采用第三方工具进行压缩后再整合到系统中,修改js后还需要再调整压缩的js繁琐并且容易出错,为了方便系统进行js和css的压缩。 提供系统级js和css压缩组件。 接口文件所在位置: /seeyon/common/compressconfig/ compressconfig.xml。 接口文件格式:
<compress>
<js>
<inputfile><![CDATA[/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.menu-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.toolbar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<outputfile><![CDATA[/common/summaryDetail-min.js]]></outputfile>
</js>
<css>
<inputfile><![CDATA[/common/css/common-debug.css]]></inputfile>
<inputfile><![CDATA[/common/css/seeyon.ui.layer-debug.css]]></inputfile>
<outputfile><![CDATA[/common/all-min.css]]></outputfile>
</css>
</compress>
XML配置文件标签说明 js标签代表一个压缩js输出,可以配置多个。css标签代表一个压缩css输出,可以配置多个。js和css标签中可以配置的内容及说明如下表所示:
JS文件压缩 多个js文件可以合并压缩成一个js文件输出到指定的文件,可以配置多个inputfile作为输入,一个outputfile作为输出,inputdirectory可以作为文件夹引入改文件夹中所有的对应类型的文件,notinclude已知的不需要引入的情况,一般与inputdirectory配合使用。
CSS文件压缩 多个css文件可以合并压缩成一个css文件输出到指定的文件,可以配置多个inputfile作为输入,一个outputfile作为输出,inputdirectory可以作为文件夹引入改文件夹中所有的对应类型的文件。
系统运行时压缩 配置文件中的信息会在系统启动时自动压缩,另外对于system用户提供系统运行时压缩入口,压缩后清理浏览器缓存可以直接看到效果。
注意:css压缩仅仅是普通的css压缩,sass内容是不包含的,这个需要特别注意。
示例
<?xml version="1.0" encoding="UTF-8"?>
<compress>
<js>
<inputfile><![CDATA[/common/js/ui/calendar/calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/Moo-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/jsonGateway-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.json-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.jsonsubmit-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.hotkeys-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.ajaxgridbar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.code-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/v3x-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/seeyon.ui.core-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp.lbs-debug.js]]></inputfile>
<inputdirectory><![CDATA[/common/js/ui]]></inputdirectory>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.tree-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.autocomplete-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.dd-debug.js]]></inputfile>
<notinclude><![CDATA[/common/js/ui/partaletindev.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/portaletMenu.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/publicinfomenu.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/seeyon.ui.arraylist-debug.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/seeyon.ui.comLanguage-debug.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/seeyon.ui.timeLine-debug.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/seeyon.ui.jcrop-debug.js]]></notinclude>
<notinclude><![CDATA[/common/js/ui/seeyon.ui.print-iframe-debug.js]]></notinclude>
<outputfile><![CDATA[/common/all-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/js/jquery-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/Moo-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/jsonGateway-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.json-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.jsonsubmit-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/v3x-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.checkform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.dialog-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.layout-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.tooltip-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.progress-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.peopleCrad-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/laytpl.js]]></inputfile>
<outputfile><![CDATA[/common/coll-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/workflow/workflowDesigner_api.js]]></inputfile>
<outputfile><![CDATA[/common/workflow/workflowDesigner_api-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/workflow/workflowDesigner.js]]></inputfile>
<outputfile><![CDATA[/common/workflow/workflowDesigner-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/js/ui/calendar/calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.hotkeys-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.code-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/searchBox-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.grid-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.toolbar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<outputfile><![CDATA[/common/colList-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.menu-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.toolbar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<outputfile><![CDATA[/common/summaryDetail-min.js]]></outputfile>
</js>
<!--
<js>
<inputfile><![CDATA[/common/js/ui/scheduler/dhtmlxscheduler-debug.js]]></inputfile>
<outputfile><![CDATA[/common/js/ui/scheduler/dhtmlxscheduler-debug.js]]></outputfile>
</js>
-->
<js>
<inputfile><![CDATA[/common/ckeditor/ckeditor.js]]></inputfile>
<outputfile><![CDATA[/common/ckeditor/ckeditor.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/ckeditor45/ckeditor.js]]></inputfile>
<outputfile><![CDATA[/common/ckeditor45/ckeditor.js]]></outputfile>
</js>
<!--
<js>
<inputfile><![CDATA[/common/ckeditor410/ckeditor.js]]></inputfile>
<outputfile><![CDATA[/common/ckeditor410/ckeditor.js]]></outputfile>
</js>
-->
<js>
<inputfile><![CDATA[/apps_res/show/js/jquery.lazyload-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-praise-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-reply-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-common-util-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/layer-dialog-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-face-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-uploader-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/showpost-edit-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/jquery.waterfall-showlist-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/showbar-list-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/jquery.waterfall-photowall-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/showpost-list-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/jquery.caret-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/jquery.atwho-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-at-util-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-seach-box-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/show-auth-edit-debug.js]]></inputfile>
<inputfile><![CDATA[/apps_res/show/js/showpost-transfer-debug.js]]></inputfile>
<outputfile><![CDATA[/apps_res/show/js/show-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/apps_res/collaboration/atwho/js/jquery.atwho.js]]></inputfile>
<inputfile><![CDATA[/apps_res/collaboration/atwho/js/jquery.caret.js]]></inputfile>
<outputfile><![CDATA[/apps_res/collaboration/atwho/js/atwho-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<outputfile><![CDATA[/common/js/jquery.comp-min.js]]></outputfile>
</js>
<!--cap4表单用精简版js资源引用-->
<js>
<inputfile><![CDATA[/common/js/jquery-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/Moo-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/jsonGateway-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.json-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/v3x-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/calendar/calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.dialog-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.jcrop-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.peopleCrad-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.print-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.print-iframe-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.progress-debug.js]]></inputfile>
<outputfile><![CDATA[/common/cap4-form-min.js]]></outputfile>
</js>
<!--cap3表单用精简版js资源引用-->
<js>
<inputfile><![CDATA[/common/js/ui/calendar/calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/Moo-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/misc/jsonGateway-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.json-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/common/js/jquery.fillform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.jsonsubmit-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.code-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.dd-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/v3x-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/seeyon.ui.core-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp.lbs-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/searchBox-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.calendar-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.checkform-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.common-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.dialog-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.grid-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.layout-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.print-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.progress-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.tooltip-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/ui/seeyon.ui.tree-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.comp-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.tree-debug.js]]></inputfile>
<inputfile><![CDATA[/common/js/jquery.autocomplete-debug.js]]></inputfile>
<outputfile><![CDATA[/common/cap3-flow-min.js]]></outputfile>
</js>
<!-- 门户首页 -->
<js>
<inputfile><![CDATA[/portal/pagelayout/front_common.js]]></inputfile>
<outputfile><![CDATA[/portal/pagelayout/front_common-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/portal/sections/section.js]]></inputfile>
<outputfile><![CDATA[/portal/sections/section-min.js]]></outputfile>
</js>
<js>
<inputfile><![CDATA[/portal/sections/tpl/sectiontpls.js]]></inputfile>
<outputfile><![CDATA[/portal/sections/tpl/sectiontpls-min.js]]></outputfile>
</js>
<css>
<inputfile><![CDATA[/common/css/common-debug.css]]></inputfile>
<inputfile><![CDATA[/common/css/seeyon.ui.layer-debug.css]]></inputfile>
<outputfile><![CDATA[/common/all-min.css]]></outputfile>
</css>
</compress>
门户前端事件接口
门户页面
空间页面
某类栏目
注意:以上三种方式无法监测到框架元素、空间、栏目中有异步回调的情况。
1.5. 附录
1.5.1. 附录1:门户布局规范
产品默认支持的门户主框架布局有下面两种结构: (1)第一种
在这种布局中,seeyonPortalLeft、seeyonPortalRight、seeyonPortalFooter是可选的,我们可以基于上述配置变化,形成其它几种变种的布局。
另外,用户可以设置seeyonPortalHeader的高度、seeyonPortalFooter的高度、seeyonPortalLeft的宽度,seeyonPortalRight的宽度,其中seeyonPortalLeft和seeyonPortalRight不能同时出现。
html代码结构如下: 页面以一个class名为wrapper的div包裹,以便定义整页样式及绑定相关事件,seeyonPortalBody和seeyonPortalFooter用一个seeyonPortalMain包裹,以便布局
(2)第二种 在这种布局中,seeyonPortalLeft、seeyonPortalRight、seeyonPortalFooter是可选的,我们可以基于上述配置变化,形成其它几种变种的布局。 另外,用户可以设置seeyonPortalHeader的高度、seeyonPortalFooter的高度、seeyonPortalLeft的宽度,seeyonPortalRight的宽度,其中seeyonPortalLeft和seeyonPortalRight不能同时出现。 html代码结构如下: 页面以一个class名为wrapper的div包裹,以免定义整页样式及绑定相关事件,seeyonPortalHeadder、seeyonPortalBody、seeyonPortalFooter用一个seeyonPortalMain包裹,以便布局。
1.5.2. 附录2:门户属性配置json数据格式
var json = [{
"groupName": "门户中的登录按钮",
"groupValue": [{
"id": "loginBtnColor",
"name": "loginBtnColor",
"type": "text",
"label": "文字颜色",
"typeShow": "half",
"typeChoose": "color",
"value": loginBtnColor_value,
"click": ""
},
{
"id": "loginBtnBgc",
"name": "loginBtnBgc",
"type": "text",
"label": "背景色",
"typeShow": "half",
"typeChoose": "color",
"value": loginBtnBgc_value,
"click": ""
}
]
},
{
"groupName": "点击【登录】弹出的登录框",
"groupValue": [{
"id": "",
"name": "",
"type": "checkbox",
"label": "",
"typeChoose": "default",
"value": [{
"label": "显示二维码",
"id": "showQrCode",
"name": "showQrCode",
"checked": (showQrCode_value == '1') ? "on" : "off"
}],
"click": "clickFun"
},
{
"id": "",
"name": "",
"type": "checkbox",
"label": "",
"typeChoose": "default",
"value": [{
"label": "显示系统版本和并发数",
"id": "showProductInfo",
"name": "showProductInfo",
"checked": (showProductInfo_value == '1') ? "on" : "off"
}],
"click": "clickFun"
},
{
"id": "loginboxmainbgc",
"name": "loginboxmainbgc",
"type": "text",
"label": "登录框背景色",
"typeShow": "half",
"typeChoose": "color",
"value": loginboxmainbgc_value,
"click": ""
},
{
"id": "loginboxbottombgc",
"name": "loginboxbottombgc",
"type": "text",
"label": "登录框底部色",
"typeShow": "half",
"typeChoose": "color",
"value": loginboxbottombgc_value,
"click": ""
},
{
"id": "loginboxbuttonbgc",
"name": "loginboxbuttonbgc",
"type": "text",
"label": "登录框按钮色",
"typeShow": "half",
"typeChoose": "color",
"value": loginboxbuttonbgc_value,
"click": ""
}
]
}
];
这块返回的内容,会在门户设计器的下述界面可以看到:
1.5.3. 附录3:系统变量获取
用户登录门户后,门户会加载系统和当前人员的相关默认数据,所有默认数据以vPortal.开头,具体见下表说明:
您在开发过程中可以在前端javascript脚本和LAYTPL模板文件中使用上表中的全局变量。
1.5.4. 附录4:PC端模板引擎语法
PC门户和元素使用到了的前端模板引擎为laytpl。laytpl 是 JavScript 模板引擎,在字符解析上有着比较出色的表现,欠缺之处在于异常调试上。语法如下:
1.5.5. 附录5:移动端模板引擎语法
移动端模板引擎语法如下示例:
1.5.6. 附录6:门户模板DEMO获取
您还可以从我们的open.seeyon.com上下载获取一个门户模板ZIP包(请右键另存进行下载),然后导入系统,就可以看到这个demo的效果。