Appearance
自定义登录注册页
在一些企业内没有统一认证系统,但是内部使用系统的成员比较多,收集账号资料的成本比较高,想要通过自定义的登录注册的方式访问系统。可以通过组件设计器开发包含登录注册的页面,替换系统的默认登录页面。
效果图
组件设置
创建一个组件设计器模块,具体的源码可参考功能演示应用中的【其他案例】->【自定义登录注册页】,下文中提供组件核心源码进行说明讲解。该组件依赖了HTML
、织信Web运行时
、Axios网路请求库
等组件库。将组件的访问地址作为登录地址设置到管理后台的登录地址
中,即可替换系统的默认登录页。
html
<div class="container" :class="{'active': type != 'login'}">
<div class="form-container sign-up-container">
<div class="form">
<h2>
注册
</h2>
<input v-model="regForm.userName" type="text" name="username" id="username" placeholder="用户名"></input>
<input v-model="regForm.email" type="email" name="email" id="email" placeholder="邮箱"></input>
<input v-model="regForm.password" type="password" name="password" id="password" placeholder="密码"></input>
<button class="signUp" v-on:click="reg">
注册
</button>
</div>
</div>
<div class="form-container sign-in-container">
<div class="form">
<h2>
登录
</h2>
<input v-model="loginForm.userName" type="text" name="username" id="email" placeholder="用户名/邮箱/手机号"></input>
<input v-model="loginForm.password" type="password" name="password" id="password" placeholder="密码"></input>
<button class="signIn" v-on:click="login">
登录
</button>
</div>
</div>
<div class="overlay_container">
<div class="overlay">
<div class="overlay_panel overlay_left_container">
<h2>
欢迎回来!
</h2>
<p>
为了与我们保持联系,请使用您的个人信息登录
</p>
<button id="sign-in" v-on:click="switchType('login')">
登录
</button>
</div>
<div class="overlay_panel overlay_right_container">
<h2>
你好!
</h2>
<p>
输入您的个人详细信息并开始我们的旅程
</p>
<button v-on:click="switchType('register')">
注册
</button>
</div>
</div>
</div>
</div>
css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: url(bg.jpg) center / cover no-repeat;
}
h2 {
margin-bottom: 10px;
font-size: 32px;
text-transform: capitalize;
}
.container {
position: relative;
width: 768px;
height: 480px;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.2);
border-radius: 10px;
overflow: hidden;
}
.form-container {
position: absolute;
top: 0;
width: 50%;
height: 100%;
background-color: rgba(255,255,255,.8);
transition: all 0.6s ease-in-out;
}
.form {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
padding: 0 50px;
}
input {
width: 100%;
margin: 8px 0!important;
padding: 12px;
background-color: #fff;
border: none;
border-radius: 30px;
}
.forget-password {
display: inline-block;
height: 20px;
text-decoration: none;
color: #bbb;
text-transform: capitalize;
font-size: 12px;
}
.forget-password:hover {
color: lightslategray;
border-bottom: 2px solid #ff4b2b;
}
button {
background: #ff4b2b;
padding: 10px 50px;
border: 1px solid transparent;
border-radius: 20px;
text-transform: uppercase;
color: white;
margin-top: 20px!important;
outline: none;
transition: transform 80;
cursor: pointer;
}
button:active {
transform: scale(0.95);
}
.overlay_container {
position: absolute;
top: 0;
width: 50%;
height: 100%;
z-index: 100;
right: 0;
overflow: hidden;
transition: all 0.6s ease-in-out;
}
.overlay {
position: absolute;
width: 200%;
height: 100%;
left: -100%;
background-color: rgba(255, 75, 43, .8);;
}
.overlay_panel {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 50%;
height: 100%;
color: white;
padding: 0 40px;
text-align: center;
}
.overlay_panel button {
background-color: transparent;
border: 1px solid white;
}
.overlay_panel p {
font-size: 12px;
margin: 10px 0 15px 0;
}
.overlay_right_container {
right: 0;
}
.container .sign-up-container {
opacity: 0;
}
.container .sign-in-container {
opacity: 1;
}
.container.active .sign-up-container {
transform: translateX(100%);
z-index: 5;
opacity: 1;
}
.container.active .sign-in-container {
transform: translateX(100%);
opacity: 0;
}
.container.active .overlay_container {
transform: translateX(-100%);
}
.container.active .overlay {
transform: translateX(50%);
}
js
export default{
data(){
return{
type: 'login',
loginForm: {
userName: null,
password: null,
},
regForm: {
userName: null,
email: null,
password: null,
}
}
},
mounted() {
// 获取登录时的回跳地址,后续登录成功后进行回跳
const params = this.getQueryParams();
this.rdUrl = params.rdUrl || '/';
},
methods:{
switchType(type) {
this.type = type;
},
// 注册
async reg() {
const {userName, email, password} = this.regForm;
try {
const resp = await informatweb.callAutomatic({
automaticId: 'reg',
args:[
userName,
email,
password
]
});
const data = resp.returnValue;
if(data.success) {
alert('注册成功!请登录账号');
this.loginForm.userName = this.regForm.userName;
this.switchType('login');
} else {
alert(data.message || '未知错误')
}
} catch(e) {
alert(e)
}
},
// 密码登录
async login() {
const {userName, password} = this.loginForm;
try {
const resp = await informatweb.callAutomatic({
automaticId: 'login',
args:[
userName,
password,
'index'
]
});
this.loginResult(resp)
} catch(e) {
alert(e)
}
},
// 获取链接参数
getQueryParams() {
let params = {};
let url = window.location.search.substring(1);
let queryString = url.split("&");
queryString.forEach(param => {
let keyValue = param.split("=");
let key = decodeURIComponent(keyValue[0]);
let value = decodeURIComponent(keyValue[1]);
params[key] = value;
});
return params;
},
// 链接追加参数
addURLParam(url, param, value) {
// 如果 URL 中已经有查询参数,使用 & 否则使用 ?
let separator = url.indexOf('?') !== -1 ? '&' : '?';
// 组合新的 URL
return url + separator + param + '=' + encodeURIComponent(value);
},
// 登录成功后拼接token参数并回跳
loginResult(resp) {
const result = resp.returnValue;
if (!result.success) {
alert(`登录失败:${result.message || '未知错误'}`)
return;
}
// 通过在链接上拼接【_token】参数可以实现免密登录
window.location.href = this.addURLParam(this.rdUrl, '_token', result.token);
}
}
}
自动化设置
在登录注册组件的脚本中我们通过织信Web运行时
调用了login
、reg
两个自动化。这两个自动化均只使用了代码片段来完成各自的业务逻辑。下面是具体的源码
TIP
由于组件中使用了织信Web运行时
是通过http调用的,所以自动化需要开启允许通过Http方式调用自动化
通过校验传入的账号密码是否正确来进行鉴权,鉴权成功后通过用户的ID创建Token,返回给前端页面
自动化入参
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
userName | String | 是 | 用户名 |
password | String | 是 | 密码 |
type | String | 是 | 登录类型,一般分为PC端登录: index ,手机端登录: mobile ,也支持自定义类型,同个类型,同个账号的token会相互挤占 |
代码片段
js
const userName = automatic.getVar('userName');
const password = automatic.getVar('password');
const type = automatic.getVar('type');
var accountList = informat.system.queryAccountList({
filter: {
conditionList: [{ 'fieldId': 'userName', 'opt': 'eq', 'value': userName }]
}
});
if(accountList.length < 1) {
informat.app.abort('账号或密码错误')
}
// 平台认证用户名密码并返回结果
var result = informat.system.validateAccount(userName, password);
if (!result) {
informat.app.abort('账号或密码错误')
} else {
// 通过用户ID创建Token
const token = informat.system.createToken(accountList[0].id, type);
automatic.setReturnValue({
success: true,
accountId: accountList[0].id,
token: token
});
}
通过环境变量registerEnable
控制是否开放注册功能。注册成功后将用户添加到当前团队,并设置团队角色为成员
自动化入参
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
userName | String | 是 | 用户名 |
String | 是 | 邮箱 | |
password | String | 是 | 密码 |
代码片段
js
const userName = automatic.getVar('userName');
const email = automatic.getVar('email');
const password = automatic.getVar('password');
const registerEnable = informat.app.appEnvProp('registerEnable');
if(registerEnable != '1') {
automatic.setReturnValue({
success: false,
message: '禁用注册功能。请修改环境变量启动注册功能'
});
} else {
const accountId = addAccount({
userName,
email,
password
})
addCompanyMember(accountId);
automatic.setReturnValue({
success: true,
message: '注册成功'
})
}
// 添加系统用户
function addAccount(item){
let accountList=informat.system.queryAccountList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: 'userName',
opt: 'eq',
value: item.userName
}
]
}
});
if(accountList.length > 0){
informat.app.abort('用户名已存在')
}
accountList=informat.system.queryAccountList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: 'email',
opt: 'eq',
value: item.email
}
]
}
});
if(accountList.length > 0){
informat.app.abort('邮箱已存在')
}
// 添加系统用户
const accountId=informat.system.addAccount({
name: userName,
avatar: 'pic15.png',
...item
});
return accountId;
}
// 添加团队成员
function addCompanyMember(accountId) {
// 获取部门根节点
const rootDeptId = (informat.dept.queryDeptList({
pageSize:1,
filter:{
conditionList:[
{"fieldId":"parentId","opt":"isnull"}
]
}
})[0] || {}).id;
// 添加团队成员
informat.company.addCompanyMember(accountId, [rootDeptId], ['member'])
}