feat(login): 增强扫码登录功能与会话管理

- 登录接口增加 loading 与超时配置,改善请求体验
- 根据服务端返回处理二维码过期,并动态设置有效时长
- 重构二维码刷新逻辑,改用 setTimeout 控制过期
- 合并会话管理与错误处理,简化扫码登录流程
- 移除多余 watch,精简组件行为
This commit is contained in:
田香琪
2026-09-15 09:46:45 +08:00
parent f4a50cd854
commit 8d18f05085
2 changed files with 48 additions and 22 deletions

View File

@@ -124,6 +124,7 @@ export function getSCLoginCode(params) {
url: `/buyer/passport/member/pc_session`, url: `/buyer/passport/member/pc_session`,
method: Method.POST, method: Method.POST,
needToken: false, needToken: false,
loading: false,
params params
}); });
} }
@@ -132,6 +133,10 @@ export function sCLogin(token,params) {
url: `/buyer/passport/member/session_login/`+token, url: `/buyer/passport/member/session_login/`+token,
method: Method.POST, method: Method.POST,
needToken: false, needToken: false,
loading: false,
skipMessage: true,
// 长轮询后端最长挂起 20s需大于该值避免 axios 10s 默认超时把二维码请求掐断
timeout: 25000,
params params
}); });
} }

View File

@@ -184,6 +184,8 @@ export default {
scannerCodeLoginFLag: false, scannerCodeLoginFLag: false,
scannerCodeLoginStatus: 0, scannerCodeLoginStatus: 0,
qrCodeTimer:null, qrCodeTimer:null,
qrExpireMs: 20000,
qrCreateSeq: 0,
config, config,
type: true, // true 账号登录 false 验证码登录 type: true, // true 账号登录 false 验证码登录
formData: { formData: {
@@ -220,12 +222,6 @@ export default {
year: new Date().getFullYear(), year: new Date().getFullYear(),
}; };
}, },
watch:{
scannerCodeLoginFLag(val){
!val ? this.clearInterval() : ''
}
},
methods: { methods: {
hideVerify() { hideVerify() {
this.$refs.verify?.close?.(); this.$refs.verify?.close?.();
@@ -374,43 +370,62 @@ export default {
}, },
async createPCLoginSession() { async createPCLoginSession() {
getSCLoginCode({}).then(response=>{ const requestId = ++this.qrCreateSeq;
this.clearQRLoginInfo(); this.clearQRLoginInfo();
if (response.code == 200) { getSCLoginCode({}).then(response=>{
if (requestId !== this.qrCreateSeq) return;
if (response.code == 200 && response.result) {
this.qrCodeStatus = 'success' this.qrCodeStatus = 'success'
let session = response.result; let session = response.result;
this.qrSessionToken = session.token; this.qrSessionToken = session.token;
this.qrExpireMs = Number(session.duration) > 0 ? Number(session.duration) : 20000;
if (session.status === 0) { if (session.status === 0) {
this.qrCode = session.token; this.qrCode = session.token;
this.refreshQrCode(); this.refreshQrCode();
} }
this.qrLogin(); this.qrLogin();
} else {
this.markQrExpired();
} }
}).catch(() => {
if (requestId !== this.qrCreateSeq) return;
this.markQrExpired();
}); });
}, },
async refreshQrCode() { refreshQrCode() {
if (!this.qrCodeTimer) { this.clearQrTimer();
this.qrCodeTimer = setInterval(() => { this.qrCodeTimer = setTimeout(() => {
this.qrCodeStatus = 'fail';
this.clearQrTimer();
}, this.qrExpireMs);
},
this.qrCodeStatus = 'fail' // 如果过期将二维码转为失效状态 clearQrTimer() {
}, 10 * 1000); if (this.qrCodeTimer) {
clearTimeout(this.qrCodeTimer);
} }
this.qrCodeTimer = null;
},
markQrExpired() {
this.qrCodeStatus = 'fail';
this.scannerCodeLoginStatus = 0;
this.qrSessionToken = '';
this.clearQrTimer();
}, },
clearQRLoginInfo(){ clearQRLoginInfo(){
this.scannerCodeLoginStatus=0; this.scannerCodeLoginStatus=0;
this.qrSessionToken=''; this.qrSessionToken='';
if (this.qrCodeTimer) { this.clearQrTimer();
clearInterval(this.qrCodeTimer)
}
this.qrCodeTimer= null;
}, },
async qrLogin() { async qrLogin() {
if(!this.qrSessionToken) return; const token = this.qrSessionToken;
sCLogin(this.qrSessionToken,{beforeSessionStatus:this.scannerCodeLoginStatus}).then(response=>{ if(!token) return;
sCLogin(token,{beforeSessionStatus:this.scannerCodeLoginStatus}).then(response=>{
if (token !== this.qrSessionToken) return;
if (response.success) { if (response.success) {
this.scannerCodeLoginStatus = response.result.status; this.scannerCodeLoginStatus = response.result.status;
switch (response.result.status) { switch (response.result.status) {
@@ -418,22 +433,27 @@ export default {
case 1: case 1:
this.qrLogin();break; this.qrLogin();break;
case 2: case 2:
this.clearQRLoginInfo();
this.loginSuccess(response.result.token.accessToken,response.result.token.refreshToken); this.loginSuccess(response.result.token.accessToken,response.result.token.refreshToken);
break; break;
case 3: case 3:
this.createPCLoginSession(); this.createPCLoginSession();
break; break;
default: default:
this.clearQRLoginInfo(); this.markQrExpired();
break break
} }
} else{ } else{
this.clearQRLoginInfo(); this.markQrExpired();
} }
}).catch(() => {
if (token !== this.qrSessionToken) return;
this.markQrExpired();
}); });
}, },
}, },
beforeUnmount() { beforeUnmount() {
this.qrCreateSeq++;
this.clearQRLoginInfo(); this.clearQRLoginInfo();
}, },
mounted() { mounted() {
@@ -454,6 +474,7 @@ export default {
console.log("二维码登录"); console.log("二维码登录");
}else{ }else{
console.log("取消二维码登录"); console.log("取消二维码登录");
this.qrCreateSeq++;
this.clearQRLoginInfo(); this.clearQRLoginInfo();
} }
}, },