Files
ScanCodeLogin/VueQRCode/index.html
2024-09-27 01:09:14 +08:00

278 lines
8.3 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="js/socket.io.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
html,
body,
#app {
width: 100%;
height: 100%;
}
#app {
margin: 0 auto;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.title {
margin-top: 10px;
}
.QRcode {
margin-top: 20px;
width: 240px;
height: 240px;
position: relative;
}
.QRcode_overtime {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.68);
color: #fff;
text-align: center;
z-index: 2;
font-size: 18px;
cursor: pointer;
}
.QRcode_overtime img {
width: 40px;
height: 40px;
margin-top: 15px;
}
.QRcode_success {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.68);
color: #fff;
text-align: center;
z-index: 3;
font-size: 18px;
}
.QRcode_success img {
width: 40px;
height: 40px;
margin-bottom: 15px;
}
.QRcode_img {
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
left: 0;
top: 0;
}
.info {
color: #8d8d8d;
margin-top: 10px;
}
.tips {
margin-top: 10px;
background: #8d8d8d;
border-radius: 24px;
padding: 4px 14px;
font-size: 13px;
color: #fff;
}
.WapEmpower button {
margin-top: 20px;
}
.tips {
margin-top: 20px;
}
</style>
</head>
<body>
<div id="app">
<a href='https://gitee.com/bmycode/ScanCodeLogin'>
<img src='https://gitee.com/bmycode/ScanCodeLogin/widgets/widget_3.svg' alt='Fork me on Gitee'></img>
</a>
<h2 class="title">扫码登录 案例</h2>
<p class="info">Nodejs + Redis + Socket + Mysql + Vue + Uni-app</p>
<br>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="移动端扫码登录" name="ScanCode">
<div class="QRcode">
<!--扫码成功的样式-->
<div class="QRcode_success" v-if="successShow">
<img src="./img/success.png" alt="success">
<p>扫码成功</p>
</div>
<!--二维码失效的样式-->
<div class="QRcode_overtime" @click="AgainScanCode" v-if="overtimeShow">
<p>二维码失效,点击重新获取</p>
<img src="./img/reload.png" alt="reload.png">
</div>
<!--真正让用户扫的二维码-->
<img class="QRcode_img" :src="base64QRcode.QRcode">
</div>
<p class="tips">{{ tipsText }}</p>
</el-tab-pane>
<el-tab-pane label="移动端授权登录" name="WapEmpower">
<div class="WapEmpower">
<p>请点击【登录】按钮</p>
<p>在移动端弹窗的页面中授权本次登录</p>
<p class="tips" v-if="WapSuccess.length != 0">{{WapSuccess}}</p>
<el-button type="success" @click="RequestLogin"> 登 录 </el-button>
</div>
</el-tab-pane>
</el-tabs>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data: {
socket: null, // 保存 socket链接
socketURL: 'http://192.168.0.133:9080', // socket 服务的地址
base64QRcode: '', // 保存后端给的二维码和uuid
timerCheck: null, // 保存定时器
tipsText: '请扫码', // 提示文字
overtimeShow: false, // 是否显示二维码失效
successShow: false, // 是否显示扫码成功
ScanCodeShow: false, // 如果用户扫码了,那么不显示 等待用户扫码中 的提示文字
activeName: 'ScanCode',// 保存当前tab的类型
WapSuccess: '' // 授权登录成功后的提示信息
},
created() {
// 创建 Socket 链接
this.socket = io.connect(this.socketURL);
this.handleClick();
},
methods: {
// 判断点击的是哪个tabs默认激活调用 【移动端扫码登录】
handleClick() {
switch (this.activeName) {
case "ScanCode":
this.getQRcode();
this.ScanCodeOvertime();
this.ScanCodeing();
break;
case "WapEmpower":
this.DoNotRepeatRequest();
this.AuthorizedWebSuccess()
break;
}
},
// 请求移动端登录按钮被点击检查用户是否已经扫码登录有发送emit没有提示
RequestLogin() {
localStorage.getItem("id") !== null
? this.socket.emit('WebRequestLogin', localStorage.getItem("id"))
: this.$notify.error({ title: '提示', message: '请先扫码登录哦!' });
},
// 监听后端 emit 重复点击 登录 按钮的提示
DoNotRepeatRequest() {
this.socket.on('DoNotRepeatRequest', res => {
this.$notify.error({
title: '提示',
message: res
});
});
},
// 移动端成功授权web端登录的监听
AuthorizedWebSuccess() {
this.socket.on('AuthorizedWebSuccess', res => {
this.WapSuccess = res
console.log("移动端授权登录成功,用户信息为:", res)
});
},
getQRcode() {
// 向服务器要uuid和二维码
this.socket.emit('getQRcode');
this.sendQRcode();
},
// 接受服务器给的uuid和二维码
sendQRcode() {
this.socket.on('sendQRcode', res => this.base64QRcode = res);
this.checkScanCode();
},
checkScanCode() {
// 等待扫码
this.socket.on('waitScanCode', res => {
if (!this.ScanCodeShow) {
this.tipsText = '等待用户扫码'
}
});
// 扫码成功
this.socket.on('SuccessScanCode', (res) => {
localStorage.setItem("id", JSON.parse(res).id);
//this.tipsText = `扫码成功用户信息为:${res}`; // 提示信息
this.successShow = true; // 显示扫码成功的样式
clearInterval(this.timerCheck); // 扫码成功,清除定时器,不再询问服务器
});
// 每1秒询问一次服务器用户App端是否扫码
this.timerCheck = setInterval(() => this.socket.emit("checkScanCode", this.base64QRcode.uuid),1000);
},
// 如果二维码超时
ScanCodeOvertime() {
this.socket.on('ScanCodeOvertime', () => {
// 如果二维码已经失效,并且用户还未扫码的话,那么才去显示二维码失效的样式
// 之所以在这判断一次的原因,因为如果用户扫码成功之后,二维码才失效
// 页面上会显示二维码失效的样式,体验不好。
if(!this.successShow) {
console.log("【Vue端】二维码超时");
clearInterval(this.timerCheck); // 二维码失效,不再询问服务器
this.overtimeShow = true; // 显示二维码失效的样式
this.tipsText = "二维码失效"; // 清空等待扫码文字
}
})
},
// 已扫码但未确认
ScanCodeing() {
this.socket.on('ScanCodeing', () => {
this.ScanCodeShow = true;
this.tipsText = "您已扫码,请在手机上确认登录!"
})
},
// 二维码失效后,用户点击二维码重新获取二维码的事件
AgainScanCode() {
this.overtimeShow = false;
this.ScanCodeShow = false;
this.socket.emit('getQRcode');
this.sendQRcode();
}
}
})
</script>
</html>