门户定制
用租户管理员登录控制台,打开应用服务管理,点击门户应用的定制管理,打开对话框,点击开启定制
系统提供的门户是可以定制的,但是门户作为基础应用,调试方法不同于其他应用,本文从以下几个方面介绍门户的定制方法
- 调试方式
- 修改登录页
- 修改主页
- 增加组织或人员的扩展字段
- 增加功能页面
1 调试方法
entry ide的调试方法不同于其他应用的调试方式,需要如下的步骤
- 切换到服务管理,点预览,删除原来的entry,重新手工注册
切换到服务管理,点预览
删除原来的entry
点手工注册,选中是否外部系统,显示名称输入entry,服务地址从地址栏里面复制:https://entryhtyw4-htyw-ide.a.xcaas.net,外部系统apisecret输入1,点击添加按钮
注册成功
- 切换到企业移动门户端,输入url:/entry/mobileapp访问移动端
切换到企业移动门户端
打开一个浏览器新的tab页,输入url:https://entryhtyw4-htyw-ide.a.xcaas.net/entry/mobileapp ,显示移动端首页,自动用system登录
system的密码是高级里面的初始密码
- 切换到企业门户端,输入url:/entry/x5/UI2/pc/index.w访问桌面端
切换到企业门户端
打开一个浏览器新的tab页,输入url:https://entryhtyw4-htyw-ide.a.xcaas.net/entry/x5/UI2/pc/index.w ,显示桌面端首页,自动用system登录
- 输入url:/entry/x5/UI2/pc/userDialog/login.w访问桌面端登录页
打开一个浏览器新的tab页,输入url:https://entryhtyw4-htyw-ide.a.xcaas.net/entry/x5/UI2/pc/userDialog/login.w ,显示桌面端首页,这里只用于调整样式,不能登录
2 修改登录页
登录页是model\UI2\pc\userDialog目录下的login.w
2.1 改为旧门户的登录页
用户组件提供两种门户的登录页样式
- 旧门户 UI2/system/components/justep/user/userDialog/login.w
- 新门户 UI2/system/components/justep/user/userDialog/login2.w
系统默认使用新门户,即登录页继承于用户组件的login2.w,如果使用旧门户,将继承于改为login.w即可,切换到代码页,打开model\UI2\pc\userDialog\login.w文件,修改extends属性
使用新门户登录页
<div xmlns:xui="http://www.justep.com/xui" xmlns:xu="http://www.xmldb.org/xupdate" component="$UI/system/components/justep/window/window" xid="window" xmlns="http://www.w3.org/1999/xhtml" extends="$UI/system/components/justep/user/userDialog/login2.w" design="device:m;" sysParam="false" class="window x-full container-fluid c-window_bg">
使用旧门户登录页
<div xmlns:xui="http://www.justep.com/xui" xmlns:xu="http://www.xmldb.org/xupdate" component="$UI/system/components/justep/window/window" xid="window" xmlns="http://www.w3.org/1999/xhtml" extends="$UI/system/components/justep/user/userDialog/login2.w" design="device:m;" sysParam="false" class="window x-full container-fluid c-window_bg">
2.2 增加验证码
以增加验证码为例,介绍修改登录页
登录页是继承页面,继承自用户组件,为了能看到用户组件的代码,需要使用本地ide。
切换到企业门户-桌面经典,打开用户对话框里面的登录页,选择用户名和密码所在的表单组,点击“添加列”
下面改为在w文件的源码中编辑,在资源管理器中打开model\UI2\pc\userDialog\login.w文件,注意在设计器中显示的继承页面的源码是经过处理的,因此不能直接在设计器中修改源码。在新增加的列中添加input和canvas,代码如下:
<div class="input-group" style="margin-top:12px;height:48px;" xid="col2" xui:parent="formgroup1" xui:update-mode="insert">
<input class="form-control captcha-input" component="$UI/system/components/justep/input/input" placeHolder="验证码" xid="captchaCode"/>
<canvas height="34" width="100" class="captcha-code" xid="captchaCanvas"/>
</div>
其中xui:parent="formgroup1" xui:update-mode="insert"是继承代码的写法,表示在被继承页面中的xid=formgroup1的节点中,插入这段代码。
在model\UI2\pc\userDialog目录下,增加login.css文件,添加样式如下:
.captcha-input{
background-color:#f9f9f9;
height:100%;
border-radius:6px;
width:300px;
border:0px solid #000;
padding-right:100px;
}
.captcha-code{
position: absolute;
right: 10px;
top: 7px;
z-index: 999;
}
打开model\UI2\pc\userDialog\login.js文件,在页面加载完成事件中,添加图形验证码,在登录按钮的点击事件中,验证图形验证码。这两个事件的代码在用户组件的登录页的js里面都有,需要完整复制这两段代码,再添加图形验证码的代码。
打开UI2/system/components/justep/user/userDialog/login2.js,复制modelLoad和login方法,在里面添加图形验证码的代码。完整代码如下:
Model.prototype.modelLoad = function (event) {
var comp = this.comp("sendSmsBtn");
User.bindTimmer(comp, 60, "获取验证码", "重新获取");
var comp2 = this.comp("sendSmsBtn2");
User.bindTimmer(comp2, 60, "获取验证码", "重新获取");
var self = this;
this.type.subscribe(function(type){
if("qrcode" == type){
self.comp('barcodeRequestLogin').clearListener('onResponse');
self.comp('barcodeRequestLogin').on('onResponse',function(event){
var token = event.data;
var tokenInfo = token.split("@");
self.userComp['login']({
name:tokenInfo[0],
password:tokenInfo[1]
}).then(function (pretoken) {
self.close();
}).fail(function(error){
self.comp('barcodeRequestLogin').showTimeoutInfo();
});
});
self.comp('barcodeRequestLogin').buildRequestBarcode({content:"",expire:5*60*1000,secret:justep.UUID.createUUID()});
}else{
self.comp('barcodeRequestLogin').clearTimer();
}
});
//图形验证码
this.captchaObj = new Captcha({
lineWidth: 1, //线条宽度
lineNum: 3, //线条数量
dotR: 2, //点的半径
dotNum: 5, //点的数量
preGroundColor: [10, 80], //前景色区间
backGroundColor: [150, 250], //背景色区间
fontSize: 30, //字体大小
fontFamily: ['Georgia', '微软雅黑', 'Helvetica', 'Arial'], //字体类型
fontStyle: 'fill', //字体绘制方法,有fill和stroke
content: 'abcdefghijklmnopqrstuvw', //验证码内容
length: 4 //验证码长度
}); // 传值
this.captchaObj.draw(this.getElementByXid('captchaCanvas'),function(r){
self.captchaCode = r;
});
}
Model.prototype.login = function () {
//图形验证码
if(this.captchaCode){
var userCaptchaCode = this.comp('captchaCode').val();
if(userCaptchaCode != this.captchaCode){
justep.Util.hint('图形验证码不匹配!',{
'type' : 'danger'
});
return;
}
}
var name = this.comp('name');
var password = this.comp('password');
var type = this.type.get();
var params = {};
params.name = name.val() || $("[xid=name]").val();// 为了支持360急速浏览器,
// 自动设置参数的情况
params.password = password.val() || $("[xid=password]").val();// 同上
if (params.name === '') {
justep.Util.hint(type === 'password' ? '请输入登录账号!' : '请输入手机号码!', {
'type': 'danger'
});
return;
}
if (type !== 'password' && !params.password) {
justep.Util.hint('请输入短信验证码!', {
'type': 'danger'
});
return;
}
if (this.userComp) {
var self = this;
var username = params.name;
if (type === 'password') {
if (params.password) {
var isTwoFactorLogin = self.isTwoFactorLogin.get();
if (!isTwoFactorLogin) {
self.loggingStatus();
this.userComp['login'](params).then(function (pretoken) {
self.comp("progress").set("valuenow", 100);
clearInterval(t);
self.type.set("password");
self.close();
}).fail(function(error){
clearInterval(t);
self.type.set("password");
});
} else {
self.getTwoFactorLoginByUsername(username).then(function (isTwoFactorLogin) {
self.userComp[!isTwoFactorLogin ? 'login' : 'prelogin'](params).then(function (pretoken) {
!isTwoFactorLogin ? self.close() : self.showTwofactorlogin(username, pretoken);
});
}, function (err) {
console.error(err);
throw new Error("查询用户[" + username + "]是否双重认证登录状态失败,请刷新浏览器重试");
});
}
} else {
justep.Util.hint("请输入密码", {
type: "danger"
})
}
} else {
User.phoneNumExist(params.name).then(function (exist) {
if (exist) {
self.userComp.login(params).then(function () {
self.close();
});
}else{
justep.Util.hint('校验手机号失败请重试!', {
'type': 'danger'
});
}
}, function () {
justep.Util.hint('校验手机号失败请重试!', {
'type': 'danger'
});
});
}
}
};
3 修改主页
主页是model\UI2\pc目录下的index.w
3.1 改为旧门户的主页
系统提供两种门户的主页样式
- 旧门户 UI2/pc/base/baseIndex.w
- 新门户 UI2/pc/base/baseIndex2.w
系统默认使用新门户,即主页继承于baseIndex2.w,如果使用旧门户,将继承于改为baseIndex.w即可,切换到代码页,打开model\UI2\pc\index.w文件,修改extends属性
使用新门户主页
<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xu="http://www.xmldb.org/xupdate" design="device:pc;"
xmlns:xui="http://www.justep.com/xui" component="$UI/system/components/justep/window/window" extends="$UI/pc/base/baseIndex2.w"
sysParam="false" xid="window" class="window">
使用旧门户主页
<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xu="http://www.xmldb.org/xupdate" design="device:pc;"
xmlns:xui="http://www.justep.com/xui" component="$UI/system/components/justep/window/window" extends="$UI/pc/base/baseIndex.w"
sysParam="false" xid="window" class="window">
3.2 显示天气预报
以显示天气预报为例,介绍修改主页
在云ide的代码中,或本地ide的资源管理器中打开model\UI2\pc\index.w文件,注意在设计器中显示的继承页面的源码是经过处理的,因此不能直接在设计器中修改源码。增加如下代码:
<li class="dropdown " xid="headerWeatherLi" xui:before="headerContactLi" xui:parent="navUl" xui:update-mode="insert">
<a class="dropdown-toggle " style="line-height: 20px;padding-top: 19px;" href="#" title="城市天气">
<iframe frameborder="0" hspace="0" scrolling="no" style="width:142px;height:20px;" xid="weatherIframe"/>
</a>
</li>
其中xui:before="headerContactLi" xui:parent="navUl" xui:update-mode="insert"是继承代码的写法,表示在被继承页面中的xid=navUl的节点中,xid=headerContactLi的节点前插入这段代码。
打开model\UI2\pc\index.js文件,在登录后事件中,访问天气网站。这个事件的代码在被继承的登录页的js里面有,需要完整复制这段代码,再添加显示天气的代码。
打开UI2/pc/base/baseIndex2.js,复制doAfterLogin方法,在里面添加显示天气的代码。完整代码如下:
//登录后,显示标题栏信息
Model.prototype.doAfterLogin = function(event){
var self = this;
//判断有没有头像,打开人员信息窗口
if(this.comp("opmConfigData").getValue("uploadAvatar")==1){
var aUser = this.comp("user").getUser();
if(!!aUser.phone && !aUser.avatarUrl) {
self.openUserInfoDialog();
justep.Util.hint("使用系统前,请先上传您的头像");
}
}
//显示日期
var today = new Date();
var strToday = justep.Date.toString(today,"YYYY年MM月DD日") + " " + justep.Date.getDayForChinese(today);
$(".x-header-date>span").html(strToday);
//显示天气
var iframe = this.getElementByXid("weatherIframe");
$(iframe).attr('src', 'https://i.tianqi.com/?c=code&a=getcode&id=72&color=%23FFFF&icon=1&site=14&py=guiyang1');
//显示/隐藏 功能树
$(".x-header-show-menu").click(function(){
var show = !self.menuIsShow.get();
self.menuIsShow.set(show);
})
//打开通讯录
$(".x-header-contact").click(function(){
var permissionCode = "*:/mobileapp/mobile/dialog/contact.w:get";
var hasPermission = self.comp("context").hasPermission(permissionCode);
if(hasPermission){//有权限才能打开
self.comp("contactDialog").open({src:require.toUrl("$UI/pc/dialog/contact.w")});
}
})
//打开主题色调整
$(".x-header-theme").click(function(){
self.comp("themeDialog").open();
})
//打开个人信息
$(".x-header-userinfo").click(function(){
self.openUserInfoDialog();
})
//首页空白处点击事件
$("body").click(function(){
$('.portal-close').css('display', 'none');
})
//首页调整
$(".x-header-mainpage").click(function(event){
justep.Shell.fireEvent("setMainPageWidget");
$("li.dropdown.user.user-menu.open").removeClass("open");
event.stopPropagation();
})
//修改密码
$(".x-header-changePassword").click(function(){
self.comp("user").showChangePassword({
"showTitle": true,
"status": "normal",
"title": "修改密码",
"height": "620px",
"width": "500px",
"forceRefreshOnOpen": true
});
})
this.initTheme();
$(".wrapper").show();//显示主页
this.loginDatetime = new Date();//记录登录时间
this.initPerson();
this.initPortal();
this.initOpenedFuncNav();
//登录成功后通知spa框架
justep.microService.userinfoResolver.resolve();
}
4 增加组织或人员的扩展字段
切换到组织权限管理端,点击数据页签,在组织扩展表或用户扩展表中添加字段
点击页面页签,打开dialog/组织详情或人员详情,编辑页面
5 增加功能页面
功能页面开发如常,开发后,需要手工修改model\UI2\pc\config\serviceMetaInfo.json文件,分为3个部分:菜单、权限和角色,参照信息发布说明如下。
5.1 定义菜单
- types表示是桌面端pc、移动端mobile的功能func,如果没有移动端页面,去掉mobile
- title设置功能页面名称
url设置功能页面url,信息发布页面是UI2\pc\infoPublish\infoPub.w,写为/entry/mobileapp/mobile/infoPublish/infoPub.w。无论在pc、pcx还是mobile目录下,url中都写mobileapp/mobile
{ "ext": { }, "types": [ "pc","mobile", "func" ], "color": "#3494F8", "icon": "dataControl dataControl-c", "title": "信息发布", "url": "/entry/mobileapp/mobile/infoPublish/infoPub.w", "order": 0 }
5.2 定义权限
code是权限编码,在url前后各加上*:和:get形成
- name是权限名称,和菜单同名即可
id是权限id,自定义,不能重复
{ "code": "*:/entry/mobileapp/mobile/infoPublish/infoPub.w:get", "ui": false, "name": "信息发布", "id": "portal_infopublish_infopub", "type": "menu" }
5.3 定义角色,分配权限
id和code是角色的id和编码,自定义,不能重复
- name是角色名称,在按组织授权和业务角色管理里面的应用角色列表中显示
permissions定义角色包括的权限,对应上面的权限编码
{ "code": "infopub_admin", "permissions": [ "*:/entry/mobileapp/mobile/infoPublish/infoPub.w:get", "*:/entry/mobileapp/mobile/infoPublish/infoColumn.w:get", "*:/entry/mobileapp/mobile/infoPublish/infoView.w:get" ], "name": "信息发布管理员", "id": "infopub_admin" }
5.4 保存、发布
- 保存修改
- 提交git
- 发布到正式环境
- 如果在正式环境的门户中没有看到新建的菜单,可以打开服务注册,点门户右侧的刷新按钮,刷新完成后,刷新浏览器