208 lines
6.8 KiB
Handlebars
208 lines
6.8 KiB
Handlebars
|
{{/* 引入微信公众号二维码扫码注册、登录错误信息一次性提示信息 ctx.Flash.Error() 显示容器 */}}
|
|||
|
{{template "base/alert" .}}
|
|||
|
|
|||
|
|
|||
|
{{if .wechatQRScanSuccess}}
|
|||
|
<!-- 扫码成功只做提示 -->
|
|||
|
<div class="ui info message">
|
|||
|
<p class="text center">{{ctx.Locale.Tr "settings.wechat_update_success"}}</p>
|
|||
|
</div>
|
|||
|
|
|||
|
{{else}}
|
|||
|
|
|||
|
{{/* ============================================================= 扫码失败,需要扫码 - 开始 ============================================================= */}}
|
|||
|
{{if .PageIsSignIn}}
|
|||
|
<h4 class="ui top attached header center">
|
|||
|
{{ctx.Locale.Tr "settings.wechat_qr_prompt"}}
|
|||
|
</h4>
|
|||
|
{{end}}
|
|||
|
|
|||
|
<div class="ui attached segment">
|
|||
|
<form class="ui form tw-max-w-2xl tw-m-auto" method="post">
|
|||
|
<div class="wechat-qr-container">
|
|||
|
<img id="idWechatQr" class="wechat-qr-image" src="{{.wechatQrCodeUrl}}" alt="Wechat Official Accout QR Code Ticket {{.wechatQrTicket}}" />
|
|||
|
</div>
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<style>
|
|||
|
.wechat-qr-container {
|
|||
|
text-align: center; /* 将文本内容居中 */
|
|||
|
position: relative; /* 添加相对定位 */
|
|||
|
}
|
|||
|
|
|||
|
.wechat-qr-container {
|
|||
|
text-align: center;
|
|||
|
position: relative;
|
|||
|
width: 100%;
|
|||
|
padding: 20px 0;
|
|||
|
}
|
|||
|
|
|||
|
.wechat-qr-image {
|
|||
|
display: inline-block;
|
|||
|
vertical-align: middle;
|
|||
|
width: 50%;
|
|||
|
height: 50%;
|
|||
|
}
|
|||
|
|
|||
|
.expire-mask {
|
|||
|
position: absolute;
|
|||
|
top: 0;
|
|||
|
left: 0;
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
background: rgba(0, 0, 0, 0.7); /* 半透明黑色遮罩 */
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
font-size: 150%;
|
|||
|
color: white;
|
|||
|
text-shadow: 2px 2px 4px #000; /* 添加字体阴影效果 */
|
|||
|
cursor: pointer;
|
|||
|
/* 确保边框和内边距不会影响宽高 */
|
|||
|
box-sizing: border-box;
|
|||
|
}
|
|||
|
|
|||
|
.expire-mask .refresh-text {
|
|||
|
color: #4183c4; /* 链接蓝色 */
|
|||
|
text-decoration: underline;
|
|||
|
margin-top: 10px;
|
|||
|
}
|
|||
|
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
<script>
|
|||
|
|
|||
|
let timeoutQrTicketPolling = {{.wechatQrExpireSeconds}} * 1000 // 微信带参数临时二维码过期时间毫秒值
|
|||
|
let isQrTicketWaitingPolling = true
|
|||
|
|
|||
|
document.addEventListener('DOMContentLoaded', () => {
|
|||
|
|
|||
|
// 提示微信二维码已经过期,停止轮询,并对二维码进行高斯模糊处理
|
|||
|
const idTimeoutWechatQrExpires = setTimeout(
|
|||
|
() => {
|
|||
|
if (isQrTicketWaitingPolling){
|
|||
|
/* 停止轮询 */
|
|||
|
isQrTicketWaitingPolling = false;
|
|||
|
|
|||
|
/* 创建遮罩层 */
|
|||
|
const qrContainer = document.querySelector('.wechat-qr-container');
|
|||
|
const expireMask = document.createElement('div');
|
|||
|
expireMask.className = 'expire-mask';
|
|||
|
expireMask.innerHTML = `
|
|||
|
<div>{{ctx.Locale.Tr "settings.wechat_qr_expired"}}</div><br/>
|
|||
|
{{svg "octicon-sync" 36}}
|
|||
|
`;
|
|||
|
expireMask.addEventListener('click', () => window.location.reload());
|
|||
|
qrContainer.appendChild(expireMask);
|
|||
|
}
|
|||
|
},
|
|||
|
timeoutQrTicketPolling
|
|||
|
);
|
|||
|
|
|||
|
// 定时查询微信二维码扫描状态
|
|||
|
const idIntervalWechatQrPolling = setInterval(() => {
|
|||
|
if (isQrTicketWaitingPolling) {
|
|||
|
checkWechatQrTicketStatus( "{{ .wechatQrTicket }}" );
|
|||
|
} else {
|
|||
|
// 当不再需要轮询时,清除定时器
|
|||
|
clearInterval(idIntervalWechatQrPolling);
|
|||
|
}
|
|||
|
},
|
|||
|
1000); // 每秒执行一次
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* 查询后台二维码扫描状态
|
|||
|
*
|
|||
|
* GET https://${window.location.host}/api/wechat/login/qr/check-status?ticket=${ticket}&_=${currentTimestamp}
|
|||
|
* 请求参数:
|
|||
|
* - ticket:微信公众号带参数二维码兑换凭证
|
|||
|
* - _ : 携带时间戳作为随机值,保证每次请求都能到达后端服务器,防止HTTP GET请求被浏览器缓存
|
|||
|
* 响应:
|
|||
|
* - 若用户未扫码,返回结果:{
|
|||
|
code: 10001,
|
|||
|
msg: "用户未扫码"
|
|||
|
}
|
|||
|
* - 若用户完成扫码,返回结果:{
|
|||
|
code: 0,
|
|||
|
msg:"扫码登录成功",
|
|||
|
data: {
|
|||
|
FromUserName: `${WechatQrScannerName}`
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
function checkWechatQrTicketStatus(qrTicket) {
|
|||
|
const urlCheckWechatQrTicketStatus = `${window.location.origin}/api/wechat/login/qr/check-status?` +
|
|||
|
`ticket=${qrTicket}&` + `_=${Date.now()}`
|
|||
|
|
|||
|
if (!isQrTicketWaitingPolling)
|
|||
|
return
|
|||
|
|
|||
|
fetch(urlCheckWechatQrTicketStatus)
|
|||
|
.then(response => {
|
|||
|
if (!response.ok) {
|
|||
|
throw new Error('Network response was not ok');
|
|||
|
}
|
|||
|
return response.json();
|
|||
|
})
|
|||
|
.then(data => {
|
|||
|
if (data.code === 0 && data.data.is_scanned) { // 标识扫码成功
|
|||
|
console.log(data);
|
|||
|
onLoginSuccess(qrTicket, data.data);
|
|||
|
}
|
|||
|
})
|
|||
|
.catch(error => {
|
|||
|
console.error('There was a problem with the fetch operation:', error);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function onLoginSuccess(qrTicket, qrStatus) {
|
|||
|
|
|||
|
// 1. 停止微信二维码轮询和过期判断
|
|||
|
isQrTicketWaitingPolling = false;
|
|||
|
|
|||
|
// 2. 移除二维码 img 标签
|
|||
|
const qrImageElement = document.getElementById('idWechatQr')
|
|||
|
if (qrImageElement) {
|
|||
|
qrImageElement.parentNode.removeChild(qrImageElement);
|
|||
|
}
|
|||
|
|
|||
|
// 3. 处理用户登录凭证 跳转到后端
|
|||
|
switch (window.location.pathname) {
|
|||
|
case '/user/login/wechat':
|
|||
|
// 登录页面扫码成功
|
|||
|
if (qrStatus.is_binded) {
|
|||
|
// 已绑定用户跳转登录成功页面 /user/login/wechat/success?ticket=${qrTicket}
|
|||
|
window.location.href = `${window.location.origin}/user/login/wechat/success?ticket=${qrTicket}&_=${Date.now()}`;
|
|||
|
} else {
|
|||
|
// 未绑定用户跳转到注册页 /user/sign_up?ticket=${qrTicket}
|
|||
|
alert(`微信用户 ${qrStatus.openid} 未注册!\n\n请点击确定继续注册账号,或者改用密码登录后进入用户设置页面扫码绑定微信`)
|
|||
|
window.location.href = `${window.location.origin}/user/sign_up?ticket=${qrTicket}&_=${Date.now()}`;
|
|||
|
}
|
|||
|
break;
|
|||
|
case '/user/settings/account':
|
|||
|
const confirmPrompt = '{{ctx.Locale.Tr "settings.wechat_bind_confirm" "${openid}" }}'.replace("${openid}", qrStatus.openid);
|
|||
|
if (window.confirm(confirmPrompt)) {
|
|||
|
// 绑定微信页面扫码成功:绑定成功页面 /user/settings/account/wechat/success?ticket=${qrTicket}
|
|||
|
window.location.href = `${window.location.origin}/user/settings/account/wechat/bind-success?ticket=${qrTicket}&_=${Date.now()}`
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
console.log(`尚未支持的扫码页面 ${window.location.pathname}`);
|
|||
|
alert(`微信用户 ${qrStatus.openid} 已成功扫码,但本页面不支持进一步操作,请联系管理员`);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
</script>
|
|||
|
|
|||
|
{{/* ============================================================= 扫码失败,需要扫码 - 结束 ============================================================= */}}
|
|||
|
{{end}}
|