ui库和web端产品库合并版本(还需修复细节)
This commit is contained in:
231
ui/packages/common/AiSign/AiSign.vue
Normal file
231
ui/packages/common/AiSign/AiSign.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<section class="ai-sign" v-if="visible">
|
||||
<el-row type="flex">
|
||||
<el-card :class="{'sign-in-hidden':!signInState}">
|
||||
<ai-sign-in
|
||||
v-if="!sassLogin"
|
||||
ref="signIn"
|
||||
@signIn="SignIn"
|
||||
:showPhoneLogin="showPhoneLogin"
|
||||
:showScanLogin="showScanLogin"
|
||||
:instance="instance"
|
||||
@qrlogin="onQRlogin"
|
||||
@sendMessage="sendMsg"
|
||||
@resetPwd="signInState=false"/>
|
||||
<h2 class="scan-title sassLogin" v-else>手机扫码,安全登录</h2>
|
||||
<template v-if="tpLoginList.length>0">
|
||||
<div class="divider" v-text="`第三方账号登录`"/>
|
||||
<el-row class="tpLogin" type="flex" align="middle">
|
||||
<el-tooltip v-for="(tp,i) in tpLoginList" :key="i" :content="tp.label" placement="top">
|
||||
<ai-icon class="item" v-bind="tp" @click.native.stop="tp.click"/>
|
||||
</el-tooltip>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-card>
|
||||
<el-card class="change-password" :class="{'change-password-hidden':signInState}">
|
||||
<ai-change-pwd @signUp="ChangePwd" :instance="instance" @toLogin="signInState=true"/>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AiSignIn from "./signIn";
|
||||
import AiChangePwd from "./changePwd";
|
||||
|
||||
export default {
|
||||
name: "AiSign",
|
||||
components: {AiChangePwd, AiSignIn},
|
||||
props: {
|
||||
/**
|
||||
* 是否展示
|
||||
*/
|
||||
visible: Boolean,
|
||||
/**
|
||||
* 显示手机号登陆模块
|
||||
*/
|
||||
showPhoneLogin: {default: true},
|
||||
/**
|
||||
* 显示扫码登录
|
||||
*/
|
||||
showScanLogin: {default: true},
|
||||
/**
|
||||
* 接口工具类
|
||||
*/
|
||||
instance: {required: true, type: Function},
|
||||
/**
|
||||
* 请求接口类
|
||||
* login :手机密码登录;mobile:手机验证码登录;
|
||||
* qr:手机扫码登录 qrStatus:扫码状态
|
||||
* changePwd:更换密码 verification:验证码验证
|
||||
*/
|
||||
action: Object,
|
||||
/**
|
||||
* 第三方登录列表: wxwork:企业微信
|
||||
*/
|
||||
tps: {default: () => []},
|
||||
/**
|
||||
* 是否是sass版本登录
|
||||
*/
|
||||
sassLogin: Boolean
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
actions: this.actions,
|
||||
sassLogin: this.sassLogin
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
actions() {
|
||||
let action = {
|
||||
login: "/auth/oauth/token",
|
||||
mobile: "/auth/mobile/token",
|
||||
qr: "/auth/qr-con/token",
|
||||
qrStatus: "/admin/user/getQrStatus",
|
||||
qrKey: "/admin/user/getQrKey",
|
||||
code: "/auth/token/code",
|
||||
failTimes: "/admin/user/getloginFailNum",
|
||||
changePwd: "/admin/user/update-pwd",
|
||||
verification: "/admin/user/checkPhone"
|
||||
}
|
||||
return {...action, ...this.action}
|
||||
},
|
||||
tpLoginList() {
|
||||
let list = [
|
||||
{
|
||||
label: "企微登录", icon: "iconqiwei", key: 'wxwork', type: 'svg', click: () => {
|
||||
location.href = `https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=ww596787bb70f08288&redirect_uri=${encodeURIComponent(location.href)}&usertype=member`
|
||||
}
|
||||
}
|
||||
]
|
||||
return list.filter(e => this.tps.includes(e.key)) || []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
signInState: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
ChangePwd(params) {
|
||||
this.instance.post(this.actions.changePwd, null, {
|
||||
params: {
|
||||
phone: params.account,
|
||||
code: params.verifictCode,
|
||||
newPwd: params.password
|
||||
}
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
this.$message.success("修改成功!")
|
||||
this.signInState = true
|
||||
}
|
||||
})
|
||||
},
|
||||
SignIn(params, url) {
|
||||
let password = this.$encryption(params)
|
||||
this.instance.post(url, null, {
|
||||
auth: {
|
||||
username: 'villcloud',
|
||||
password: "villcloud"
|
||||
},
|
||||
params: {
|
||||
grant_type: 'password',
|
||||
scope: 'server',
|
||||
...params,
|
||||
password
|
||||
}
|
||||
}).then(data => {
|
||||
if (!data) {
|
||||
this.$refs.signIn.handleInput()
|
||||
} else {
|
||||
this.$emit("login", data)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$refs.signIn.handleInput()
|
||||
})
|
||||
},
|
||||
getNowDate() {
|
||||
const date = new Date()
|
||||
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate()
|
||||
},
|
||||
sendMsg(phone) {
|
||||
this.instance.post(this.actions.verification, null, {
|
||||
auth: {},
|
||||
params: {phone}
|
||||
}).then(() => this.$message.success("发送成功!"))
|
||||
},
|
||||
onQRlogin(data) {
|
||||
this.$emit('login', data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ai-sign {
|
||||
width: 400px;
|
||||
display: inline-block;
|
||||
transition: 2s;
|
||||
|
||||
.el-row {
|
||||
width: 200%;
|
||||
}
|
||||
|
||||
.sign-in-hidden {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.change-password {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.change-password-hidden {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.el-card {
|
||||
width: 400px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin: 12px 0;
|
||||
|
||||
&:before, &:after {
|
||||
content: "——";
|
||||
margin: 0 11px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.tpLogin {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
cursor: pointer;
|
||||
margin: 8px;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
font-size: 28px;
|
||||
border-radius: 50%;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.scan-title {
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
|
||||
&.sassLogin {
|
||||
margin-bottom: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
185
ui/packages/common/AiSign/changePwd.vue
Normal file
185
ui/packages/common/AiSign/changePwd.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<el-form class="changePwd" ref="form" :model="signUpForm" :rules="rules">
|
||||
<div class="backLogin" type="text" @click="$emit('toLogin')"><i class="el-icon-caret-left"/> 重置密码</div>
|
||||
<el-form-item prop="account" style="white-space: nowrap">
|
||||
<el-input placeholder="请输入您的手机号" v-model="signUpForm.account" clearable>
|
||||
<i slot="prefix" class="iconfont iconPhone"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="verifictCode">
|
||||
<el-input class="code" placeholder="请输入短信验证码" maxlength="6" v-model="signUpForm.verifictCode" clearable>
|
||||
<el-button slot="suffix" style="padding-right: 14px" type="text" @click="getVerifictCode"
|
||||
:disabled="verify.disable">{{ verify.btnLabel }}
|
||||
</el-button>
|
||||
<i slot="prefix" class="iconfont iconMessage"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input class="form-item-width" type="password" show-password placeholder="密码(8-16个字符,区分大小写)"
|
||||
v-model="signUpForm.password" clearable>
|
||||
<i slot="prefix" class="iconfont iconPassword"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="confirmPassword">
|
||||
<el-input class="form-item-width" type="password" show-password placeholder="再次输入密码"
|
||||
v-model="signUpForm.confirmPassword" clearable>
|
||||
<i slot="prefix" class="iconfont iconPassword"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button class="form-item-width" type="primary" @click.native="submitChangePwd">重置密码</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "changePwd",
|
||||
inject: ["actions"],
|
||||
props: {
|
||||
instance: Function
|
||||
},
|
||||
computed: {
|
||||
rules() {
|
||||
const _ = this
|
||||
return {
|
||||
account: [
|
||||
{required: true, message: "请输入您的手机号", trigger: 'blur'},
|
||||
{pattern: /^1[345789]\d{9}$/, message: "手机号格式有误", trigger: 'blur'},
|
||||
],
|
||||
verifictCode: [{
|
||||
trigger: 'blur', validator(r, v, cb) {
|
||||
if (/^\d{6}$/.test(v)) {
|
||||
cb()
|
||||
} else {
|
||||
cb(new Error("请输入6位验证码"))
|
||||
}
|
||||
}
|
||||
}],
|
||||
password: [
|
||||
{required: true, message: "请输入新密码", trigger: 'blur'},
|
||||
{
|
||||
pattern: /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*,.?_-])[\da-zA-Z~!@#$%^&*,.?_-]{8,16}$/,
|
||||
message: "数字和字母及特殊字符(~!@#$%^&*,.?_-)组合,长度8到16位"
|
||||
}
|
||||
],
|
||||
confirmPassword: [
|
||||
{required: true, message: "请再次输入新密码", trigger: 'blur'},
|
||||
{
|
||||
trigger: 'blur', validator(r, v, cb) {
|
||||
if (v == _.signUpForm.password) {
|
||||
cb()
|
||||
} else {
|
||||
cb(new Error("两次填写的密码不一致"))
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
signUpForm: {
|
||||
account: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
verifictCode: "",
|
||||
},
|
||||
verify: {
|
||||
disable: false,
|
||||
timer: 0,
|
||||
btnLabel: "获取验证码",
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getVerifictCode() {
|
||||
this.$refs.form.validateField("account", v => {
|
||||
if (!v) {
|
||||
this.verify.disable = true
|
||||
this.verify.timer = 60
|
||||
this.verify.btnLabel = this.verify.timer + "秒"
|
||||
const timer = setInterval(() => {
|
||||
if (this.verify.timer === 0) {
|
||||
this.verify.btnLabel = "获取验证码"
|
||||
this.verify.disable = false
|
||||
clearInterval(timer)
|
||||
} else {
|
||||
this.verify.timer--
|
||||
this.verify.btnLabel = this.verify.timer + "秒"
|
||||
}
|
||||
}, 1000)
|
||||
this.instance.post(this.actions.verification, null, {
|
||||
auth: {},
|
||||
params: {
|
||||
phone: this.signUpForm.account
|
||||
}
|
||||
}).then(() => this.$message.success("短信发送成功!"))
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
submitChangePwd() {
|
||||
this.$refs.form.validate(v => {
|
||||
if (v) {
|
||||
this.$emit("signUp", this.signUpForm)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.changePwd {
|
||||
// margin: 0 20px;
|
||||
|
||||
::v-deep .code {
|
||||
.el-button {
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.backLogin {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
height: 40px;
|
||||
color: $primaryColor;
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
margin-bottom: 46px;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.el-icon-caret-left {
|
||||
padding: 0;
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep.el-form-item {
|
||||
margin-bottom: 24px;
|
||||
|
||||
i {
|
||||
padding-left: 7px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-width {
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
132
ui/packages/common/AiSign/identify.vue
Normal file
132
ui/packages/common/AiSign/identify.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="s-canvas">
|
||||
<canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'SIdentify',
|
||||
props: {
|
||||
identifyCode: {
|
||||
type: String,
|
||||
default: '1234'
|
||||
},
|
||||
fontSizeMin: {
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
fontSizeMax: {
|
||||
type: Number,
|
||||
default: 40
|
||||
},
|
||||
backgroundColorMin: {
|
||||
type: Number,
|
||||
default: 180
|
||||
},
|
||||
backgroundColorMax: {
|
||||
type: Number,
|
||||
default: 240
|
||||
},
|
||||
colorMin: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
colorMax: {
|
||||
type: Number,
|
||||
default: 160
|
||||
},
|
||||
lineColorMin: {
|
||||
type: Number,
|
||||
default: 40
|
||||
},
|
||||
lineColorMax: {
|
||||
type: Number,
|
||||
default: 180
|
||||
},
|
||||
dotColorMin: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
dotColorMax: {
|
||||
type: Number,
|
||||
default: 255
|
||||
},
|
||||
contentWidth: {
|
||||
type: Number,
|
||||
default: 160
|
||||
},
|
||||
contentHeight: {
|
||||
type: Number,
|
||||
default: 40
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 生成一个随机数
|
||||
randomNum (min, max) {
|
||||
return Math.floor(Math.random() * (max - min) + min)
|
||||
},
|
||||
// 生成一个随机的颜色
|
||||
randomColor (min, max) {
|
||||
let r = this.randomNum(min, max)
|
||||
let g = this.randomNum(min, max)
|
||||
let b = this.randomNum(min, max)
|
||||
return 'rgb(' + r + ',' + g + ',' + b + ')'
|
||||
},
|
||||
drawPic () {
|
||||
let canvas = document.getElementById('s-canvas')
|
||||
let ctx = canvas.getContext('2d')
|
||||
ctx.textBaseline = 'bottom'
|
||||
// 绘制背景
|
||||
ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax)
|
||||
ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
|
||||
// 绘制文字
|
||||
for (let i = 0; i < this.identifyCode.length; i++) {
|
||||
this.drawText(ctx, this.identifyCode[i], i)
|
||||
}
|
||||
this.drawLine(ctx)
|
||||
this.drawDot(ctx)
|
||||
},
|
||||
drawText (ctx, txt, i) {
|
||||
ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
|
||||
ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
|
||||
let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
|
||||
let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
|
||||
var deg = this.randomNum(-45, 45)
|
||||
// 修改坐标原点和旋转角度
|
||||
ctx.translate(x, y)
|
||||
ctx.rotate(deg * Math.PI / 180)
|
||||
ctx.fillText(txt, 0, 0)
|
||||
// 恢复坐标原点和旋转角度
|
||||
ctx.rotate(-deg * Math.PI / 180)
|
||||
ctx.translate(-x, -y)
|
||||
},
|
||||
drawLine (ctx) {
|
||||
// 绘制干扰线
|
||||
// for (let i = 0; i < 8; i++) {
|
||||
// ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
|
||||
// ctx.beginPath()
|
||||
// ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
|
||||
// ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
|
||||
// ctx.stroke()
|
||||
// }
|
||||
},
|
||||
drawDot (ctx) {
|
||||
// 绘制干扰点
|
||||
// for (let i = 0; i < 100; i++) {
|
||||
// ctx.fillStyle = this.randomColor(0, 255)
|
||||
// ctx.beginPath()
|
||||
// ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
|
||||
// ctx.fill()
|
||||
// }
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
identifyCode () {
|
||||
this.drawPic()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.drawPic()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
333
ui/packages/common/AiSign/signIn.vue
Normal file
333
ui/packages/common/AiSign/signIn.vue
Normal file
@@ -0,0 +1,333 @@
|
||||
<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"
|
||||
:rules="[{required: true, message: '请输入您的手机号', trigger: 'change'}]">
|
||||
<el-input v-model="sign.username" placeholder="请输入您的手机号" clearable
|
||||
@keyup.enter.native="$refs.validInput.focus()">
|
||||
<i slot="prefix" class="iconfont iconProlife"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-else prop="mobile" :rules="[{required: true, message: '请输入您的手机号', trigger: 'change'}]">
|
||||
<el-input v-model="sign.mobile" placeholder="请输入您的手机号" clearable
|
||||
@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,
|
||||
redirect_uri: `${location.origin}/login`,
|
||||
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;
|
||||
}
|
||||
|
||||
::v-deep.el-tabs__nav-wrap::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep.el-tabs__header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::v-deep.el-tabs__item {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
::v-deep.el-form-item {
|
||||
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>
|
||||
Reference in New Issue
Block a user