登录优化

jg-waiwang-pro
mhsnet 6 months ago
parent 1c34200d72
commit 95e2c33a2d

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

@ -0,0 +1,420 @@
<template>
<div class="login-container">
<!-- <div class="login-version" v-if="sysConfig && sysConfig.sysVersion">
<p class="login-version-text">{{ sysConfig.sysVersion }}</p>
</div> -->
<div class="login-left">
<div class="login-company-logo">
<img class="login-company-logo-img" src="@/assets/images/login-company-logo.png" alt="">
</div>
<img class="login-banner" src="@/assets/images/login-banner.png" alt="">
<!-- <a class="login-company-logo" target="_blank" href="https://www.jnpfsoft.com">
<img class="login-company-logo-img" src="@/assets/images/login-company-logo.png" alt="">
</a>
<img class="login-banner" src="@/assets/images/login-banner.png" alt=""> -->
<!-- <div class="login-left-txt" v-if="showTxt">
<p class="title1">赋能开发者提速企业数字化零代码实现80%的基础功能</p>
<p class="title2">已帮助<span>20000+</span>家企业完成数字化转型升级</p>
<a class="link" target="_blank" href="https://www.jnpfsoft.com">了解更多</a>
</div> -->
</div>
<div class="login-content">
<div class="login-form">
<el-image class="login-logo" :src="define.comUrl + sysConfig.loginIcon" v-if="sysConfig && sysConfig.loginIcon">
<template slot="error">
<!-- <img class="login-logo" height="80px" src="@/assets/images/login_logo.png" alt=""> -->
</template>
</el-image>
<img class="login-logo" style="width:380px;height:80px;" src="@/assets/images/login_logo.png" alt="" v-else>
<div v-show="!isSso && !ssoLoading">
<div class="login-tab" :class="'active' + active">
<a class="item" :class="{ 'active': active == 1 }" @click="active = 1">{{ $t('login.title') }}</a>
<a class="item" :class="{ 'active': active == 2 }" @click="active = 2">{{ $t('login.scanTitle') }}</a>
</div>
<el-form v-show="active == 1" ref="loginForm" :model="loginForm" :rules="loginRules" autocomplete="on"
label-position="left">
<el-form-item prop="account">
<el-input ref="account" v-model="loginForm.account" :placeholder="$t('login.username')" name="account"
type="text" tabindex="1" autocomplete="on" prefix-icon="el-icon-user" size="large" @change="getConfig">
</el-input>
</el-form-item>
<el-tooltip v-model="capsTooltip" :content="$t('login.upper')" placement="right" manual>
<el-form-item prop="password">
<el-input ref="password" v-model="loginForm.password" show-password :placeholder="$t('login.password')"
name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock"
@blur="capsTooltip = false" prefix-icon="el-icon-lock" size="large"></el-input>
<!-- @keyup.enter.native="handleLogin" -->
</el-form-item>
</el-tooltip>
<el-form-item prop="code" v-if="needCode">
<el-row type="flex" justify="space-between">
<el-col class="sms-input">
<el-input v-model="loginForm.code" :placeholder="$t('login.codeTip')" name="code" autocomplete="on"
prefix-icon="el-icon-key" size="large">
</el-input>
</el-col>
<el-col class="sms-right code-right">
<el-tooltip :content="$t('login.changeCode')" placement="bottom">
<img id="imgcode" :alt="$t('login.changeCode')" :src="define.comUrl + imgUrl" @click="changeImg">
</el-tooltip>
</el-col>
</el-row>
</el-form-item>
<el-button :loading="loading" type="primary" class="login-btn" size="large"
@click.native.prevent="handleLogin">{{
$t('login.logIn') }}</el-button>
<template v-if="socialsList.length">
<el-divider content-position="center" class="divider__text">其他登录方式</el-divider>
<div class="other-list">
<div v-for="(item, i) in socialsList" :key="i">
<el-tooltip class="item" effect="dark" :content='item.name + "登录"' placement="top">
<div class="other-item" @click="otherLogin(item.enname)"><i :class="item.icon" />
</div>
</el-tooltip>
</div>
</div>
</template>
</el-form>
<div v-show="active == 2" class="login-form-QRCode">
<img class="qrcode-img" src="@/assets/images/login_qr.png">
<p class="qrcode-tip">正在测试,稍后上线</p>
</div>
</div>
<el-button type="primary" class="sso-login-btn" size="large" :loading="loading" @click.native.prevent="ssoLogin"
v-show="isSso && !ssoLoading">登录</el-button>
</div>
<div class="copyright"> {{ sysConfig.copyright }}</div>
</div>
<el-dialog title="登录" :close-on-click-modal="false" :visible.sync="visible" :close-on-press-escape="false"
class="JNPF-dialog JNPF-dialog_center JNPF-dialog-sso" lock-scroll width="1000px" @open="onOpen">
<iframe width="100%" height="100%" :src="ssoUrl" frameborder="0" v-if="show"></iframe>
</el-dialog>
<!-- <div class="login-foot">Copyright 引迈信息技术有限公司, All Rights Reserved. 沪ICP备17044791号-1
助力企业和团队快速实现目标</div> -->
<el-dialog :visible.sync="dialogVisible" width="600px"
class="JNPF-dialog JNPF-dialog_center form-script-dialog other-login-dialog" :before-close="handleClose">
<div class="other-main">
<div class="other-title">
<div class="other-icon"><i class="icon-ym icon-ym-user" /></div>
<div class="other-text">请选择登录账号</div>
</div>
<div class="other-body">
<el-row :gutter="20">
<template v-for="(item, i) in tenantSocialList">
<el-col :span="12" :key="i">
<div @click="socailsLogin(item)">
<el-card shadow="hover" class="other-login-card">
<h2>{{ item.socialName }}</h2>
<div class="other-login-des">租户名称{{ item.tenantName }}</div>
<div class="other-login-des">租户ID{{ item.tenantId }}</div>
<div class="other-login-des">账号ID{{ item.accountName }}</div>
</el-card>
</div>
</el-col>
</template>
</el-row>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { getConfig } from '@/api/user'
import { getSocialsLoginList, getLoginConfig, getTicket, getTicketStatus, socialsLogin } from '@/api/permission/socialsUser'
import qs from 'qs'
export default {
name: 'Login',
data() {
return {
loginForm: {
account: '',
password: '',
code: '',
origin: 'password'
},
loginRules: {
account: [
{ required: true, trigger: 'blur', message: this.$t('login.accountTip') }
],
password: [
{ required: true, trigger: 'blur', message: this.$t('login.passwordTip') }
],
code: [
{ required: true, trigger: 'blur', message: this.$t('login.codeTip') }
],
},
imgUrl: "",
timestamp: '',
capsTooltip: false,
loading: false,
showDialog: false,
needCode: false,
codeLength: 4,
redirect: undefined,
showTxt: false,
otherQuery: {},
active: 1,
listenerLoad: false,
visible: false,
show: false,
ssoLoading: true,
isSso: false,
preUrl: '',
ssoUrl: '',
ssoTicket: "",
ticketParams: "",
ssoTimer: null,
socialsList: [],
dialogVisible: false,
tenantSocialList: [],
redirectUrl: '',
}
},
computed: {
sysConfig() {
return this.$store.state.settings.sysConfig
},
loginLoading() {
return this.$store.state.user.loginLoading
}
},
watch: {
loginLoading(val) {
if (!val) this.loading = false
},
visible(val) {
if (!val) {
this.loading = false
this.show = false
this.clearTimer()
}
},
$route: {
handler: function (route) {
const query = route.query
if (query) {
this.redirect = query.redirect
this.otherQuery = this.getOtherQuery(query)
}
},
immediate: true
}
},
created() {
const _this = this
document.onkeydown = function (e) {
const { keyCode } = e
if (keyCode === 13) {
_this.handleLogin()
}
}
if (this.needCode) this.changeImg()
this.getLoginConfig()
},
mounted() {
this.$store.commit('user/SET_LOGIN_LOADING', false)
this.setShowTxt()
window.onresize = () => {
this.setShowTxt()
}
},
destroyed() {
document.onkeydown = function (e) {
const { keyCode } = e
if (keyCode === 13) { }
}
},
methods: {
setShowTxt() {
if (document.documentElement.clientHeight <= 840) {
this.showTxt = false
} else {
this.showTxt = true
}
},
checkCapslock(e) {
const { key } = e
this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z'
},
getConfig(val) {
if (!val) return
getConfig(this.loginForm.account).then(res => {
this.needCode = !!res.data.enableVerificationCode
if (this.needCode) {
this.codeLength = res.data.verificationCodeNumber || 4
this.changeImg()
}
})
},
handleLogin() {
if (this.loading) return
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.commit('user/SET_LOGIN_LOADING', true)
const query = {
...this.loginForm,
timestamp: this.timestamp,
jnpf_ticket: this.ssoTicket
}
this.$store.dispatch('user/login', query).then(res => {
this.$router.push({
path: this.redirect || '/home',
query: this.otherQuery
})
}).catch(() => {
this.$store.commit('user/SET_LOGIN_LOADING', false)
})
} else {
return false
}
})
},
changeImg() {
let timestamp = Math.random()
this.timestamp = timestamp
this.imgUrl = `/api/oauth/ImageCode/${this.codeLength || 4}/${timestamp}`
},
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
},
otherLoginList() {
this.socialsList = []
getSocialsLoginList().then(res => {
this.socialsList = res.data.filter(item => { return item.isLatest == "true" });
})
},
otherLogin(data) {
getTicket().then(res => {
this.ssoTicket = res.data
if (this.winURL && !this.winURL.closed) {
this.winURL.location.replace(this.redirectUrl)
this.winURL.focus()
return
}
this.socialsList.forEach(item => {
if (data == item.enname) {
let renderUrl = item.renderUrl.replace('JNPF_TICKET', this.ssoTicket)
this.redirectUrl = renderUrl
}
})
var iWidth = 750; //;
var iHeight = 500;//;
var iLeft = (window.screen.width - iWidth) / 2;
var iTop = (window.screen.height - iHeight) / 2;//;
this.winURL = window.open(this.redirectUrl, '_blank', 'height=' + iHeight + ',innerHeight=' + iHeight + ',width=' + iWidth + ',innerWidth=' + iWidth + ',top=' + iTop + ',left=' + iLeft + ',toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no')
this.ssoTimer = setInterval(() => {
if (this.winURL.closed) { this.clearTimer() }
this.getTicketStatus()
}, 1000)
})
},
getTicketStatus() {
if (!this.ssoTicket) return
getTicketStatus(this.ssoTicket).then(res => {
if (res.data.status != 2) {
this.winURL && this.winURL.close()
if (res.data.status == 4) {//ticket
clearInterval(this.ssoTimer)
this.ssoTimer = null
} else {
this.clearTimer()
}
switch (res.data.status) {
case 1://
let param = {
theme: res.data.theme,
token: res.data.value
}
this.$store.dispatch('user/setToken', param).then(res => {
this.$router.push({
path: this.redirect || '/home',
query: this.otherQuery
})
})
break;
case 4://
this.$message.error('第三方账号未绑定5分钟内登录本系统账号密码自动绑定该账号')
this.visible = false
this.ssoUrl = ''
break;
case 6://
this.dialogVisible = true
this.tenantSocialList = typeof res.data.value === 'string' ? JSON.parse(res.data.value) : res.data.value;
break;
default:
this.$message.error(res.data.value || '账号异常!')
this.visible = false
this.ssoUrl = ''
this.getLoginConfig()
break
}
}
})
},
clearTimer() {
if (this.ssoTimer) {
clearInterval(this.ssoTimer)
this.ssoTimer = null
this.ssoTicket = ''
}
},
handleClose() {
this.dialogVisible = false
},
socailsLogin(data) {
socialsLogin(qs.stringify({ ...data, tenantLogin: true })).then(response => {
if (response.code == 200) {
this.$store.dispatch('user/setToken', response.data).then(res => {
this.$router.push({
path: this.redirect || '/home',
query: this.otherQuery
})
})
}
})
},
ssoLogin() {
if (this.loading) return
this.loading = true
getTicket().then(res => {
this.ssoTicket = res.data
this.ssoUrl = this.preUrl + '?' + this.ticketParams + '=' + this.ssoTicket
this.visible = true
this.ssoTimer = setInterval(() => {
this.getTicketStatus()
}, 1000)
})
},
getLoginConfig() {
getLoginConfig().then(res => {
this.isSso = res.data.redirect
this.preUrl = res.data.url
this.ticketParams = res.data.ticketParams
this.socialsList = res.data.socialsList || []
localStorage.setItem('useSocials', this.socialsList.length)
this.ssoLoading = false
}).catch(() => {
this.isSso = false
this.ssoLoading = false
})
},
onOpen() {
this.show = true
},
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

@ -1,75 +1,145 @@
<template> <template>
<div class="login-container"> <div class="login-container">
<!-- <div class="login-version" v-if="sysConfig && sysConfig.sysVersion">
<p class="login-version-text">{{ sysConfig.sysVersion }}</p>
</div> -->
<div class="login-left"> <div class="login-left">
<div class="login-company-logo"> <div class="login-company-logo">
<img class="login-company-logo-img" src="@/assets/images/login-company-logo.png" alt=""> <img
class="login-company-logo-img"
src="@/assets/images/login/LOGO.png"
alt=""
/>
</div> </div>
<img class="login-banner" src="@/assets/images/login-banner.png" alt=""> <!-- <img class="login-banner" src="@/assets/images/login-banner.png" alt="" /> -->
<!-- <a class="login-company-logo" target="_blank" href="https://www.jnpfsoft.com">
<img class="login-company-logo-img" src="@/assets/images/login-company-logo.png" alt="">
</a>
<img class="login-banner" src="@/assets/images/login-banner.png" alt=""> -->
<!-- <div class="login-left-txt" v-if="showTxt">
<p class="title1">赋能开发者提速企业数字化零代码实现80%的基础功能</p>
<p class="title2">已帮助<span>20000+</span>家企业完成数字化转型升级</p>
<a class="link" target="_blank" href="https://www.jnpfsoft.com">了解更多</a>
</div> -->
</div> </div>
<div class="login-content"> <div class="login-content">
<div>
<img src="@/assets/images/login/image-01.png" alt="" />
</div>
<div class="login-form"> <div class="login-form">
<el-image class="login-logo" :src="define.comUrl + sysConfig.loginIcon" v-if="sysConfig && sysConfig.loginIcon"> <el-image
<template slot="error"> class="login-logo"
<!-- <img class="login-logo" height="80px" src="@/assets/images/login_logo.png" alt=""> --> :src="define.comUrl + sysConfig.loginIcon"
</template> v-if="sysConfig && sysConfig.loginIcon"
>
<template slot="error"> </template>
</el-image> </el-image>
<img class="login-logo" style="width:380px;height:80px;" src="@/assets/images/login_logo.png" alt="" v-else> <img
class="login-logo"
style="width:380px;height:80px;"
src="@/assets/images/login/title1.png"
alt=""
v-else
/>
<div v-show="!isSso && !ssoLoading"> <div v-show="!isSso && !ssoLoading">
<div class="login-tab" :class="'active' + active"> <div class="login-tab" :class="'active' + active">
<a class="item" :class="{ 'active': active == 1 }" @click="active = 1">{{ $t('login.title') }}</a> <a
<a class="item" :class="{ 'active': active == 2 }" @click="active = 2">{{ $t('login.scanTitle') }}</a> class="item"
:class="{ active: active == 1 }"
@click="active = 1"
>{{ $t("login.title") }}</a
>
<a
class="item"
:class="{ active: active == 2 }"
@click="active = 2"
>{{ $t("login.scanTitle") }}</a
>
</div> </div>
<el-form v-show="active == 1" ref="loginForm" :model="loginForm" :rules="loginRules" autocomplete="on" <el-form
label-position="left"> v-show="active == 1"
ref="loginForm"
:model="loginForm"
:rules="loginRules"
autocomplete="on"
label-position="left"
>
<el-form-item prop="account"> <el-form-item prop="account">
<el-input ref="account" v-model="loginForm.account" :placeholder="$t('login.username')" name="account" <el-input
type="text" tabindex="1" autocomplete="on" prefix-icon="el-icon-user" size="large" @change="getConfig"> ref="account"
v-model="loginForm.account"
:placeholder="$t('login.username')"
name="account"
type="text"
tabindex="1"
autocomplete="on"
prefix-icon="el-icon-user"
size="large"
@change="getConfig"
>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-tooltip v-model="capsTooltip" :content="$t('login.upper')" placement="right" manual> <el-tooltip
v-model="capsTooltip"
:content="$t('login.upper')"
placement="right"
manual
>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input ref="password" v-model="loginForm.password" show-password :placeholder="$t('login.password')" <el-input
name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock" ref="password"
@blur="capsTooltip = false" prefix-icon="el-icon-lock" size="large"></el-input> v-model="loginForm.password"
<!-- @keyup.enter.native="handleLogin" --> show-password
:placeholder="$t('login.password')"
name="password"
tabindex="2"
autocomplete="on"
@keyup.native="checkCapslock"
@blur="capsTooltip = false"
prefix-icon="el-icon-lock"
size="large"
></el-input>
</el-form-item> </el-form-item>
</el-tooltip> </el-tooltip>
<el-form-item prop="code" v-if="needCode"> <el-form-item prop="code" v-if="needCode">
<el-row type="flex" justify="space-between"> <el-row type="flex" justify="space-between">
<el-col class="sms-input"> <el-col class="sms-input">
<el-input v-model="loginForm.code" :placeholder="$t('login.codeTip')" name="code" autocomplete="on" <el-input
prefix-icon="el-icon-key" size="large"> v-model="loginForm.code"
:placeholder="$t('login.codeTip')"
name="code"
autocomplete="on"
prefix-icon="el-icon-key"
size="large"
>
</el-input> </el-input>
</el-col> </el-col>
<el-col class="sms-right code-right"> <el-col class="sms-right code-right">
<el-tooltip :content="$t('login.changeCode')" placement="bottom"> <el-tooltip
<img id="imgcode" :alt="$t('login.changeCode')" :src="define.comUrl + imgUrl" @click="changeImg"> :content="$t('login.changeCode')"
placement="bottom"
>
<img
id="imgcode"
:alt="$t('login.changeCode')"
:src="define.comUrl + imgUrl"
@click="changeImg"
/>
</el-tooltip> </el-tooltip>
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-button :loading="loading" type="primary" class="login-btn" size="large" <el-button
@click.native.prevent="handleLogin">{{ :loading="loading"
$t('login.logIn') }}</el-button> type="primary"
class="login-btn"
size="large"
@click.native.prevent="handleLogin"
>{{ $t("login.logIn") }}</el-button
>
<template v-if="socialsList.length"> <template v-if="socialsList.length">
<el-divider content-position="center" class="divider__text">其他登录方式</el-divider> <el-divider content-position="center" class="divider__text"
>其他登录方式</el-divider
>
<div class="other-list"> <div class="other-list">
<div v-for="(item, i) in socialsList" :key="i"> <div v-for="(item, i) in socialsList" :key="i">
<el-tooltip class="item" effect="dark" :content='item.name + "登录"' placement="top"> <el-tooltip
<div class="other-item" @click="otherLogin(item.enname)"><i :class="item.icon" /> class="item"
effect="dark"
:content="item.name + '登录'"
placement="top"
>
<div class="other-item" @click="otherLogin(item.enname)">
<i :class="item.icon" />
</div> </div>
</el-tooltip> </el-tooltip>
</div> </div>
@ -77,23 +147,48 @@
</template> </template>
</el-form> </el-form>
<div v-show="active == 2" class="login-form-QRCode"> <div v-show="active == 2" class="login-form-QRCode">
<img class="qrcode-img" src="@/assets/images/login_qr.png"> <img class="qrcode-img" src="@/assets/images/login_qr.png" />
<p class="qrcode-tip">正在测试,稍后上线</p> <p class="qrcode-tip">正在测试,稍后上线</p>
</div> </div>
</div> </div>
<el-button type="primary" class="sso-login-btn" size="large" :loading="loading" @click.native.prevent="ssoLogin" <el-button
v-show="isSso && !ssoLoading">登录</el-button> type="primary"
class="sso-login-btn"
size="large"
:loading="loading"
@click.native.prevent="ssoLogin"
v-show="isSso && !ssoLoading"
>登录</el-button
>
</div> </div>
<div class="copyright"> {{ sysConfig.copyright }}</div> <div class="copyright">{{ sysConfig.copyright }}</div>
</div> </div>
<el-dialog title="登录" :close-on-click-modal="false" :visible.sync="visible" :close-on-press-escape="false" <el-dialog
class="JNPF-dialog JNPF-dialog_center JNPF-dialog-sso" lock-scroll width="1000px" @open="onOpen"> title="登录"
<iframe width="100%" height="100%" :src="ssoUrl" frameborder="0" v-if="show"></iframe> :close-on-click-modal="false"
:visible.sync="visible"
:close-on-press-escape="false"
class="JNPF-dialog JNPF-dialog_center JNPF-dialog-sso"
lock-scroll
width="1000px"
@open="onOpen"
>
<iframe
width="100%"
height="100%"
:src="ssoUrl"
frameborder="0"
v-if="show"
></iframe>
</el-dialog> </el-dialog>
<!-- <div class="login-foot">Copyright 引迈信息技术有限公司, All Rights Reserved. 沪ICP备17044791号-1 <!-- <div class="login-foot">Copyright 引迈信息技术有限公司, All Rights Reserved. 沪ICP备17044791号-1
助力企业和团队快速实现目标</div> --> 助力企业和团队快速实现目标</div> -->
<el-dialog :visible.sync="dialogVisible" width="600px" <el-dialog
class="JNPF-dialog JNPF-dialog_center form-script-dialog other-login-dialog" :before-close="handleClose"> :visible.sync="dialogVisible"
width="600px"
class="JNPF-dialog JNPF-dialog_center form-script-dialog other-login-dialog"
:before-close="handleClose"
>
<div class="other-main"> <div class="other-main">
<div class="other-title"> <div class="other-title">
<div class="other-icon"><i class="icon-ym icon-ym-user" /></div> <div class="other-icon"><i class="icon-ym icon-ym-user" /></div>
@ -101,15 +196,20 @@
</div> </div>
<div class="other-body"> <div class="other-body">
<el-row :gutter="20"> <el-row :gutter="20">
<template v-for="(item, i) in tenantSocialList"> <template v-for="(item, i) in tenantSocialList">
<el-col :span="12" :key="i"> <el-col :span="12" :key="i">
<div @click="socailsLogin(item)"> <div @click="socailsLogin(item)">
<el-card shadow="hover" class="other-login-card"> <el-card shadow="hover" class="other-login-card">
<h2>{{ item.socialName }}</h2> <h2>{{ item.socialName }}</h2>
<div class="other-login-des">租户名称{{ item.tenantName }}</div> <div class="other-login-des">
<div class="other-login-des">租户ID{{ item.tenantId }}</div> 租户名称{{ item.tenantName }}
<div class="other-login-des">账号ID{{ item.accountName }}</div> </div>
<div class="other-login-des">
租户ID{{ item.tenantId }}
</div>
<div class="other-login-des">
账号ID{{ item.accountName }}
</div>
</el-card> </el-card>
</div> </div>
</el-col> </el-col>
@ -122,33 +222,47 @@
</template> </template>
<script> <script>
import { getConfig } from '@/api/user' import { getConfig } from "@/api/user";
import { getSocialsLoginList, getLoginConfig, getTicket, getTicketStatus, socialsLogin } from '@/api/permission/socialsUser' import {
import qs from 'qs' getSocialsLoginList,
getLoginConfig,
getTicket,
getTicketStatus,
socialsLogin
} from "@/api/permission/socialsUser";
import qs from "qs";
export default { export default {
name: 'Login', name: "Login",
data() { data() {
return { return {
loginForm: { loginForm: {
account: '', account: "",
password: '', password: "",
code: '', code: "",
origin: 'password' origin: "password"
}, },
loginRules: { loginRules: {
account: [ account: [
{ required: true, trigger: 'blur', message: this.$t('login.accountTip') } {
required: true,
trigger: "blur",
message: this.$t("login.accountTip")
}
], ],
password: [ password: [
{ required: true, trigger: 'blur', message: this.$t('login.passwordTip') } {
required: true,
trigger: "blur",
message: this.$t("login.passwordTip")
}
], ],
code: [ code: [
{ required: true, trigger: 'blur', message: this.$t('login.codeTip') } { required: true, trigger: "blur", message: this.$t("login.codeTip") }
], ]
}, },
imgUrl: "", imgUrl: "",
timestamp: '', timestamp: "",
capsTooltip: false, capsTooltip: false,
loading: false, loading: false,
showDialog: false, showDialog: false,
@ -163,258 +277,323 @@ export default {
show: false, show: false,
ssoLoading: true, ssoLoading: true,
isSso: false, isSso: false,
preUrl: '', preUrl: "",
ssoUrl: '', ssoUrl: "",
ssoTicket: "", ssoTicket: "",
ticketParams: "", ticketParams: "",
ssoTimer: null, ssoTimer: null,
socialsList: [], socialsList: [],
dialogVisible: false, dialogVisible: false,
tenantSocialList: [], tenantSocialList: [],
redirectUrl: '', redirectUrl: ""
} };
}, },
computed: { computed: {
sysConfig() { sysConfig() {
return this.$store.state.settings.sysConfig return this.$store.state.settings.sysConfig;
}, },
loginLoading() { loginLoading() {
return this.$store.state.user.loginLoading return this.$store.state.user.loginLoading;
} }
}, },
watch: { watch: {
loginLoading(val) { loginLoading(val) {
if (!val) this.loading = false if (!val) this.loading = false;
}, },
visible(val) { visible(val) {
if (!val) { if (!val) {
this.loading = false this.loading = false;
this.show = false this.show = false;
this.clearTimer() this.clearTimer();
} }
}, },
$route: { $route: {
handler: function (route) { handler: function(route) {
const query = route.query const query = route.query;
if (query) { if (query) {
this.redirect = query.redirect this.redirect = query.redirect;
this.otherQuery = this.getOtherQuery(query) this.otherQuery = this.getOtherQuery(query);
} }
}, },
immediate: true immediate: true
} }
}, },
created() { created() {
const _this = this const _this = this;
document.onkeydown = function (e) { document.onkeydown = function(e) {
const { keyCode } = e const { keyCode } = e;
if (keyCode === 13) { if (keyCode === 13) {
_this.handleLogin() _this.handleLogin();
} }
} };
if (this.needCode) this.changeImg() if (this.needCode) this.changeImg();
this.getLoginConfig() this.getLoginConfig();
}, },
mounted() { mounted() {
this.$store.commit('user/SET_LOGIN_LOADING', false) this.$store.commit("user/SET_LOGIN_LOADING", false);
this.setShowTxt() this.setShowTxt();
window.onresize = () => { window.onresize = () => {
this.setShowTxt() this.setShowTxt();
} };
}, },
destroyed() { destroyed() {
document.onkeydown = function (e) { document.onkeydown = function(e) {
const { keyCode } = e const { keyCode } = e;
if (keyCode === 13) { } if (keyCode === 13) {
} }
};
}, },
methods: { methods: {
setShowTxt() { setShowTxt() {
if (document.documentElement.clientHeight <= 840) { if (document.documentElement.clientHeight <= 840) {
this.showTxt = false this.showTxt = false;
} else { } else {
this.showTxt = true this.showTxt = true;
} }
}, },
checkCapslock(e) { checkCapslock(e) {
const { key } = e const { key } = e;
this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z' this.capsTooltip = key && key.length === 1 && key >= "A" && key <= "Z";
}, },
getConfig(val) { getConfig(val) {
if (!val) return if (!val) return;
getConfig(this.loginForm.account).then(res => { getConfig(this.loginForm.account).then(res => {
this.needCode = !!res.data.enableVerificationCode this.needCode = !!res.data.enableVerificationCode;
if (this.needCode) { if (this.needCode) {
this.codeLength = res.data.verificationCodeNumber || 4 this.codeLength = res.data.verificationCodeNumber || 4;
this.changeImg() this.changeImg();
} }
}) });
}, },
handleLogin() { handleLogin() {
if (this.loading) return if (this.loading) return;
this.$refs.loginForm.validate(valid => { this.$refs.loginForm.validate(valid => {
if (valid) { if (valid) {
this.loading = true this.loading = true;
this.$store.commit('user/SET_LOGIN_LOADING', true) this.$store.commit("user/SET_LOGIN_LOADING", true);
const query = { const query = {
...this.loginForm, ...this.loginForm,
timestamp: this.timestamp, timestamp: this.timestamp,
jnpf_ticket: this.ssoTicket jnpf_ticket: this.ssoTicket
} };
this.$store.dispatch('user/login', query).then(res => { this.$store
this.$router.push({ .dispatch("user/login", query)
path: this.redirect || '/home', .then(res => {
query: this.otherQuery this.$router.push({
path: this.redirect || "/home",
query: this.otherQuery
});
}) })
}).catch(() => { .catch(() => {
this.$store.commit('user/SET_LOGIN_LOADING', false) this.$store.commit("user/SET_LOGIN_LOADING", false);
}) });
} else { } else {
return false return false;
} }
}) });
}, },
changeImg() { changeImg() {
let timestamp = Math.random() let timestamp = Math.random();
this.timestamp = timestamp this.timestamp = timestamp;
this.imgUrl = `/api/oauth/ImageCode/${this.codeLength || 4}/${timestamp}` this.imgUrl = `/api/oauth/ImageCode/${this.codeLength || 4}/${timestamp}`;
}, },
getOtherQuery(query) { getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => { return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') { if (cur !== "redirect") {
acc[cur] = query[cur] acc[cur] = query[cur];
} }
return acc return acc;
}, {}) }, {});
}, },
otherLoginList() { otherLoginList() {
this.socialsList = [] this.socialsList = [];
getSocialsLoginList().then(res => { getSocialsLoginList().then(res => {
this.socialsList = res.data.filter(item => { return item.isLatest == "true" }); this.socialsList = res.data.filter(item => {
}) return item.isLatest == "true";
});
});
}, },
otherLogin(data) { otherLogin(data) {
getTicket().then(res => { getTicket().then(res => {
this.ssoTicket = res.data this.ssoTicket = res.data;
if (this.winURL && !this.winURL.closed) { if (this.winURL && !this.winURL.closed) {
this.winURL.location.replace(this.redirectUrl) this.winURL.location.replace(this.redirectUrl);
this.winURL.focus() this.winURL.focus();
return return;
} }
this.socialsList.forEach(item => { this.socialsList.forEach(item => {
if (data == item.enname) { if (data == item.enname) {
let renderUrl = item.renderUrl.replace('JNPF_TICKET', this.ssoTicket) let renderUrl = item.renderUrl.replace(
this.redirectUrl = renderUrl "JNPF_TICKET",
this.ssoTicket
);
this.redirectUrl = renderUrl;
} }
}) });
var iWidth = 750; //; var iWidth = 750; //;
var iHeight = 500;//; var iHeight = 500; //;
var iLeft = (window.screen.width - iWidth) / 2; var iLeft = (window.screen.width - iWidth) / 2;
var iTop = (window.screen.height - iHeight) / 2;//; var iTop = (window.screen.height - iHeight) / 2; //;
this.winURL = window.open(this.redirectUrl, '_blank', 'height=' + iHeight + ',innerHeight=' + iHeight + ',width=' + iWidth + ',innerWidth=' + iWidth + ',top=' + iTop + ',left=' + iLeft + ',toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no') this.winURL = window.open(
this.redirectUrl,
"_blank",
"height=" +
iHeight +
",innerHeight=" +
iHeight +
",width=" +
iWidth +
",innerWidth=" +
iWidth +
",top=" +
iTop +
",left=" +
iLeft +
",toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no"
);
this.ssoTimer = setInterval(() => { this.ssoTimer = setInterval(() => {
if (this.winURL.closed) { this.clearTimer() } if (this.winURL.closed) {
this.getTicketStatus() this.clearTimer();
}, 1000) }
}) this.getTicketStatus();
}, 1000);
});
}, },
getTicketStatus() { getTicketStatus() {
if (!this.ssoTicket) return if (!this.ssoTicket) return;
getTicketStatus(this.ssoTicket).then(res => { getTicketStatus(this.ssoTicket).then(res => {
if (res.data.status != 2) { if (res.data.status != 2) {
this.winURL && this.winURL.close() this.winURL && this.winURL.close();
if (res.data.status == 4) {//ticket if (res.data.status == 4) {
clearInterval(this.ssoTimer) //ticket
this.ssoTimer = null clearInterval(this.ssoTimer);
this.ssoTimer = null;
} else { } else {
this.clearTimer() this.clearTimer();
} }
switch (res.data.status) { switch (res.data.status) {
case 1:// case 1: //
let param = { let param = {
theme: res.data.theme, theme: res.data.theme,
token: res.data.value token: res.data.value
} };
this.$store.dispatch('user/setToken', param).then(res => { this.$store.dispatch("user/setToken", param).then(res => {
this.$router.push({ this.$router.push({
path: this.redirect || '/home', path: this.redirect || "/home",
query: this.otherQuery query: this.otherQuery
}) });
}) });
break; break;
case 4:// case 4: //
this.$message.error('第三方账号未绑定5分钟内登录本系统账号密码自动绑定该账号') this.$message.error(
this.visible = false "第三方账号未绑定5分钟内登录本系统账号密码自动绑定该账号"
this.ssoUrl = '' );
this.visible = false;
this.ssoUrl = "";
break; break;
case 6:// case 6: //
this.dialogVisible = true this.dialogVisible = true;
this.tenantSocialList = typeof res.data.value === 'string' ? JSON.parse(res.data.value) : res.data.value; this.tenantSocialList =
typeof res.data.value === "string"
? JSON.parse(res.data.value)
: res.data.value;
break; break;
default: default:
this.$message.error(res.data.value || '账号异常!') this.$message.error(res.data.value || "账号异常!");
this.visible = false this.visible = false;
this.ssoUrl = '' this.ssoUrl = "";
this.getLoginConfig() this.getLoginConfig();
break break;
} }
} }
}) });
}, },
clearTimer() { clearTimer() {
if (this.ssoTimer) { if (this.ssoTimer) {
clearInterval(this.ssoTimer) clearInterval(this.ssoTimer);
this.ssoTimer = null this.ssoTimer = null;
this.ssoTicket = '' this.ssoTicket = "";
} }
}, },
handleClose() { handleClose() {
this.dialogVisible = false this.dialogVisible = false;
}, },
socailsLogin(data) { socailsLogin(data) {
socialsLogin(qs.stringify({ ...data, tenantLogin: true })).then(response => { socialsLogin(qs.stringify({ ...data, tenantLogin: true })).then(
if (response.code == 200) { response => {
this.$store.dispatch('user/setToken', response.data).then(res => { if (response.code == 200) {
this.$router.push({ this.$store.dispatch("user/setToken", response.data).then(res => {
path: this.redirect || '/home', this.$router.push({
query: this.otherQuery path: this.redirect || "/home",
}) query: this.otherQuery
}) });
});
}
} }
}) );
}, },
ssoLogin() { ssoLogin() {
if (this.loading) return if (this.loading) return;
this.loading = true this.loading = true;
getTicket().then(res => { getTicket().then(res => {
this.ssoTicket = res.data this.ssoTicket = res.data;
this.ssoUrl = this.preUrl + '?' + this.ticketParams + '=' + this.ssoTicket this.ssoUrl =
this.visible = true this.preUrl + "?" + this.ticketParams + "=" + this.ssoTicket;
this.visible = true;
this.ssoTimer = setInterval(() => { this.ssoTimer = setInterval(() => {
this.getTicketStatus() this.getTicketStatus();
}, 1000) }, 1000);
}) });
}, },
getLoginConfig() { getLoginConfig() {
getLoginConfig().then(res => { getLoginConfig()
this.isSso = res.data.redirect .then(res => {
this.preUrl = res.data.url this.isSso = res.data.redirect;
this.ticketParams = res.data.ticketParams this.preUrl = res.data.url;
this.socialsList = res.data.socialsList || [] this.ticketParams = res.data.ticketParams;
localStorage.setItem('useSocials', this.socialsList.length) this.socialsList = res.data.socialsList || [];
this.ssoLoading = false localStorage.setItem("useSocials", this.socialsList.length);
}).catch(() => { this.ssoLoading = false;
this.isSso = false })
this.ssoLoading = false .catch(() => {
}) this.isSso = false;
this.ssoLoading = false;
});
}, },
onOpen() { onOpen() {
this.show = true this.show = true;
}, }
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './index.scss'; @import "./index.scss";
.login-container .login-left {
background-image: url("../../assets/images/login/image_b.jpg");
background-position: center center;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
height: 100%;
}
.login-container .login-left .login-company-logo {
top: 30px;
}
.login-container .login-left .login-company-logo .login-company-logo-img {
top: 35px;
left: 60px;
height: 60px;
}
.login-container .login-content {
position: absolute;
background-color: #fff;
border-radius: 20px;
width: 1050px;
height: 500px;
margin: auto;
}
.login-container .login-form .login-logo {
margin-bottom: 25px;
}
</style> </style>
Loading…
Cancel
Save