first commit
This commit is contained in:
1
VueQRCode/.pydio
Normal file
1
VueQRCode/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
5871485d-34e9-410d-b06c-e5b04078fa6d
|
||||
1
VueQRCode/img/.pydio
Normal file
1
VueQRCode/img/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
16eac697-009f-45a6-b5de-63e2dddc5f59
|
||||
BIN
VueQRCode/img/reload.png
Normal file
BIN
VueQRCode/img/reload.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
VueQRCode/img/success.png
Normal file
BIN
VueQRCode/img/success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
278
VueQRCode/index.html
Normal file
278
VueQRCode/index.html
Normal file
@@ -0,0 +1,278 @@
|
||||
<!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>
|
||||
1
VueQRCode/js/.pydio
Normal file
1
VueQRCode/js/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
5603e8bb-6ec9-4f4b-89f5-b99e50f0be03
|
||||
9
VueQRCode/js/socket.io.js
Normal file
9
VueQRCode/js/socket.io.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user