2022-11-29 18:27:14 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<el-form ref="loginForm" :model="sign" class="signIn">
|
|
|
|
|
|
<el-form-item class="ai-sign__header">
|
|
|
|
|
|
<el-tabs v-model="currentWay" v-if="!isScan">
|
|
|
|
|
|
<el-tab-pane label="账号登录"></el-tab-pane>
|
|
|
|
|
|
<el-tab-pane label="短信登录" v-if="showPhoneLogin"></el-tab-pane>
|
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
<h2 class="scan-title" v-if="isScan">手机扫码,安全登录</h2>
|
|
|
|
|
|
<div class="ai-scan" @click="changeLoginType" v-if="showScanLogin">
|
|
|
|
|
|
<div class="poptip-arrow">
|
|
|
|
|
|
<span>{{ tipContent }}</span>
|
|
|
|
|
|
<a/>
|
|
|
|
|
|
<em/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<i class="iconfont" :class="[isScan ? 'iconAccount_Login' : 'iconQR_code']"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<div class="qrcode" id="qrcode" v-show="isScan"/>
|
|
|
|
|
|
<template v-if="!isScan">
|
|
|
|
|
|
<el-form-item v-if="isAccountSignIn" prop="username"
|
2023-11-01 08:42:22 +08:00
|
|
|
|
:rules="[{required: true, message: '请输入您的账号', trigger: 'change'}]">
|
|
|
|
|
|
<el-input v-model="sign.username" placeholder="请输入您的账号" clearable
|
2022-11-29 18:27:14 +08:00
|
|
|
|
@keyup.enter.native="$refs.validInput.focus()">
|
|
|
|
|
|
<i slot="prefix" class="iconfont iconProlife"></i>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</el-form-item>
|
2023-11-01 08:47:20 +08:00
|
|
|
|
<el-form-item v-else prop="mobile" :rules="[{required: true, message: '请输入您的手机号', trigger: 'change'}]">
|
|
|
|
|
|
<el-input v-model="sign.mobile" placeholder="请输入您的手机号" clearable
|
2022-11-29 18:27:14 +08:00
|
|
|
|
@keyup.enter.native="$refs.validInput.focus()">
|
|
|
|
|
|
<i slot="prefix" class="iconfont iconPhone"></i>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item v-if="isAccountSignIn" prop="password"
|
|
|
|
|
|
:rules="[{required: true, message: '请输入您的密码', trigger: 'change'}]">
|
|
|
|
|
|
<el-input ref="validInput" type="password" placeholder="请输入您的密码" show-password
|
|
|
|
|
|
v-model="sign.password" @keyup.enter.native="handleClick" clearable>
|
|
|
|
|
|
<i slot="prefix" class="iconfont iconPassword"></i>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item v-else prop="code" :rules="[{required: true, message: '请输入短信验证码', trigger: 'change'}]">
|
|
|
|
|
|
<el-input ref="validInput" placeholder="请输入短信验证码" v-model="sign.code" clearable
|
|
|
|
|
|
@keyup.enter.native="handleClick">
|
|
|
|
|
|
<i slot="prefix" class="iconfont iconMessage"></i>
|
|
|
|
|
|
<el-button slot="suffix" style="padding-right: 14px" type="text" :disabled="verCodeTimer>0"
|
|
|
|
|
|
@click="sendMessage">
|
|
|
|
|
|
{{ verCodeTimer ? verCodeTimer + "秒" : "获取验证码" }}
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<el-button type="primary" class="login-btn" @click="handleClick">登录</el-button>
|
|
|
|
|
|
<div class="reset-password-row">
|
|
|
|
|
|
<el-button type="text" class="reset-password" @click="$emit('resetPwd')">忘记密码?</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import VueQr from 'vue-qr'
|
|
|
|
|
|
import identify from './identify'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: "signIn",
|
|
|
|
|
|
inject: ["actions"],
|
|
|
|
|
|
props: {
|
|
|
|
|
|
instance: Function,
|
|
|
|
|
|
showPhoneLogin: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: true
|
|
|
|
|
|
},
|
|
|
|
|
|
showScanLogin: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: true
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
currentWay: 0,
|
|
|
|
|
|
verCodeTimer: 0,
|
|
|
|
|
|
sign: {
|
|
|
|
|
|
username: "",
|
|
|
|
|
|
password: "",
|
|
|
|
|
|
mobile: "",
|
|
|
|
|
|
code: "",
|
|
|
|
|
|
randomStr: ""
|
|
|
|
|
|
},
|
|
|
|
|
|
code: {
|
|
|
|
|
|
src: "/code",
|
|
|
|
|
|
value: "",
|
|
|
|
|
|
len: 4,
|
|
|
|
|
|
type: "image"
|
|
|
|
|
|
},
|
|
|
|
|
|
isScan: true,
|
|
|
|
|
|
validFocus: false,
|
|
|
|
|
|
QRkey: '',
|
|
|
|
|
|
timer: null,
|
|
|
|
|
|
isInvalid: false,
|
|
|
|
|
|
isLoginSuccess: false,
|
|
|
|
|
|
identifyCodes: '1234567890',
|
|
|
|
|
|
identifyCode: '',
|
|
|
|
|
|
errorNum: 0,
|
|
|
|
|
|
appid: '',
|
|
|
|
|
|
agentid: ''
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
components: {
|
|
|
|
|
|
VueQr,
|
|
|
|
|
|
identify
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
isAccountSignIn() {
|
|
|
|
|
|
return this.currentWay == 0
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
tipContent() {
|
|
|
|
|
|
return this.isScan ? '返回账号登录' : '扫码登录更安全'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
currentWay() {
|
|
|
|
|
|
this.sign = {
|
|
|
|
|
|
username: "",
|
|
|
|
|
|
password: "",
|
|
|
|
|
|
mobile: "",
|
|
|
|
|
|
code: "",
|
|
|
|
|
|
randomStr: ""
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
created() {
|
|
|
|
|
|
localStorage.removeItem('ui-token')
|
|
|
|
|
|
localStorage.removeItem('token')
|
|
|
|
|
|
localStorage.removeItem('vuex')
|
|
|
|
|
|
if (this.showScanLogin) {
|
|
|
|
|
|
this.getLoginInfo()
|
|
|
|
|
|
this.isScan = true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.isScan = false
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
changeLoginType() {
|
|
|
|
|
|
if (!this.isScan) {
|
|
|
|
|
|
this.isScan = true
|
|
|
|
|
|
this.getQRkey()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.isScan = false
|
|
|
|
|
|
clearInterval(this.timer)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getLoginInfo() {
|
|
|
|
|
|
this.instance.post(`/app/wxcp/portal/getCpParams`).then(res => {
|
|
|
|
|
|
if (res && res.data) {
|
|
|
|
|
|
this.agentid = res.data.agentid
|
|
|
|
|
|
this.appid = res.data.corpid
|
|
|
|
|
|
this.getQRkey()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getErrorNum(phone) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
this.instance.post(this.actions.failTimes, null, {
|
|
|
|
|
|
params: {phone}
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
resolve(Number(res.data.status) || 0)
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
reject('error')
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
handleInput() {
|
|
|
|
|
|
},
|
|
|
|
|
|
handleClick() {
|
|
|
|
|
|
this.$refs.loginForm.validate((valid) => {
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
if (this.currentWay == 0) {
|
|
|
|
|
|
this.$emit("signIn", this.sign, this.actions.login)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$emit("signIn", this.sign, this.actions.mobile)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
sendMessage() {
|
|
|
|
|
|
if (this.currentWay == 1) {
|
|
|
|
|
|
if (this.sign.mobile) {
|
|
|
|
|
|
this.$emit("sendMessage", this.sign.mobile)
|
|
|
|
|
|
this.verCodeTimer = 60
|
|
|
|
|
|
const timer = setInterval(() => {
|
|
|
|
|
|
this.verCodeTimer--
|
|
|
|
|
|
if (this.verCodeTimer == 0) {
|
|
|
|
|
|
clearInterval(timer)
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 1000)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.error("请输入手机号!")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getQRkey() {
|
|
|
|
|
|
this.$injectLib('https://rescdn.qqmail.com/node/ww/wwopenmng/js/sso/wwLogin-1.0.0.js', () => {
|
|
|
|
|
|
window.WwLogin({
|
|
|
|
|
|
id: 'qrcode',
|
|
|
|
|
|
appid: this.appid,
|
|
|
|
|
|
agentid: this.agentid,
|
2023-03-02 17:32:51 +08:00
|
|
|
|
redirect_uri: location.origin + location.pathname,
|
2022-11-29 18:27:14 +08:00
|
|
|
|
state: '',
|
|
|
|
|
|
href: 'https://cdn.cunwuyun.cn/dvcp/wechat-login.css',
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.signIn {
|
|
|
|
|
|
.imgcode {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
|
|
|
|
.el-input {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.imgcode-img {
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.scan-success {
|
|
|
|
|
|
padding-top: 64px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
|
font-size: 64px;
|
|
|
|
|
|
color: #2EA222;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h2 {
|
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
color: #666666;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.qrcode {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.qrlogin-bottom {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
span {
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
a {
|
|
|
|
|
|
color: $primaryColor;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ai-sign__header {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 17:32:51 +08:00
|
|
|
|
:deep(.el-tabs__nav-wrap::after ) {
|
2022-11-29 18:27:14 +08:00
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 17:32:51 +08:00
|
|
|
|
:deep(.el-tabs__header ) {
|
2022-11-29 18:27:14 +08:00
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 17:32:51 +08:00
|
|
|
|
:deep(.el-tabs__item ) {
|
2022-11-29 18:27:14 +08:00
|
|
|
|
padding-right: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 17:32:51 +08:00
|
|
|
|
:deep(.el-form-item ) {
|
2022-11-29 18:27:14 +08:00
|
|
|
|
margin-bottom: 32px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-tabs__item {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-btn {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 48px;
|
|
|
|
|
|
line-height: 48px;
|
|
|
|
|
|
margin: 16px auto;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
|
padding-left: 7px;
|
|
|
|
|
|
padding-right: 7px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.reset-password-row {
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.qrcode {
|
|
|
|
|
|
height: 296px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|