diff --git a/common/http.api.js b/common/http.api.js index 996822e..1d02815 100644 --- a/common/http.api.js +++ b/common/http.api.js @@ -20,12 +20,15 @@ let StoreDetailUrl = 'mp-api/hhrsStore/detail'; let WinnerDatesUrl = 'mp-api/hhrsWinner/dates'; let WinnerListUrl = 'mp-api/hhrsWinner/list'; let AppointUrl = 'zhy-api/cardBag/appoint'; +let TokenDecodeUrl = 'open-api/hhService/tokenDecode'; // 此处第二个参数vm,就是我们在页面使用的this const install = (Vue, vm) => { let checkerLogin = (params = {}) => vm.$u.post(LoginUrl, params); let sendLoginVerifyCode = (params = {}) => vm.$u.post(SendVerifyCodeUrl, params); + // xuchao: 云闪付入口 token 解码 + let tokenDecode = (params = {}) => vm.$u.post(TokenDecodeUrl, params); // 文旅场馆 let getVenueList = (params = {}) => vm.$u.get(VenueListUrl, params); @@ -57,6 +60,7 @@ const install = (Vue, vm) => { vm.$u.api = { checkerLogin, sendLoginVerifyCode, + tokenDecode, getVenueList, getVenueDetail, getMerchantList, diff --git a/common/http.interceptor.js b/common/http.interceptor.js index 11bac9e..0f824c3 100644 --- a/common/http.interceptor.js +++ b/common/http.interceptor.js @@ -2,7 +2,7 @@ // 同时,我们也可以在此使用getApp().globalData,如果你把token放在getApp().globalData的话,也是可以使用的 const install = (Vue, vm) => { Vue.prototype.$u.http.setConfig({ - baseUrl: 'https://dscp-dev.hn12301.net', + baseUrl: 'https://dscp-uat.hn12301.net', // loadingText: '努力加载中~', // loadingTime: 18800, // 如果将此值设置为true,拦截回调中将会返回服务端返回的所有数据response,而不是response.data diff --git a/pages/index/index.vue b/pages/index/index.vue index 67de28b..1376cc6 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -59,10 +59,56 @@ ] } }, - onLoad() { + onLoad(options) { + if (options.token) { + this.handleTokenLogin(options.token) + } this.getLocation() }, methods: { + // xuchao: 云闪付入口 token 自动登录 + handleTokenLogin(token) { + this.$u.api.tokenDecode({ token }).then(res => { + if (res.errcode === 0 && res.data && res.data.mobile) { + uni.setStorageSync('phone', res.data.mobile) + this.$u.api.getEligibility({ phone: res.data.mobile, identityNo: res.data.idNo || '', name: res.data.name || '' }).then(eRes => { + if (eRes.errcode === 0) { + uni.setStorageSync('isAuth', eRes.data.isAuth) + uni.setStorageSync('hasWin', eRes.data.hasWin) + uni.setStorageSync('cardNumber', eRes.data.cardNumber) + uni.setStorageSync('expiresTime', eRes.data.expiresTime) + } + }) + // xuchao: 清除地址栏 token,防止分享泄露 + this.clearUrlToken() + } else { + this.degradeToPhoneLogin() + } + }).catch(() => { + this.degradeToPhoneLogin() + }) + }, + // xuchao: 解码失败兜底,提示并跳手机号登录 + degradeToPhoneLogin() { + uni.showToast({ title: '登录凭证已失效,请使用手机号登录', icon: 'none' }) + setTimeout(() => { + uni.navigateTo({ url: '/pages/index/login' }) + }, 800) + }, + // xuchao: 从 URL hash 中移除 token 参数 + clearUrlToken() { + try { + const hash = window.location.hash || '' + const qIndex = hash.indexOf('?') + if (qIndex === -1) return + const params = new URLSearchParams(hash.substring(qIndex + 1)) + if (!params.has('token')) return + params.delete('token') + const rest = params.toString() + const base = hash.substring(0, qIndex) + window.history.replaceState(null, '', rest ? `${base}?${rest}` : base) + } catch (e) {} + }, getLocation() { import('@/common/location.js').then(module => { module.default.getLocation().then(({ lng, lat }) => { @@ -83,8 +129,10 @@ } const isAuth = uni.getStorageSync('isAuth') const hasWin = uni.getStorageSync('hasWin') + // xuchao: 最近发起过认证流程(含取消)时忽略旧认证缓存,一律回认证页 + const authFlowStarted = uni.getStorageSync('authFlowStarted') let status = 'auth' - if (isAuth) { + if (isAuth && !authFlowStarted) { status = hasWin ? 'info' : 'noWin' } uni.navigateTo({ url: `/pages/rights/rights?status=${status}` }) diff --git a/pages/rights/rights.vue b/pages/rights/rights.vue index 8935493..0e09c30 100644 --- a/pages/rights/rights.vue +++ b/pages/rights/rights.vue @@ -212,11 +212,46 @@ this.lat = loc.lat } this.checkAuthResult() + // xuchao: 本地无认证缓存时自动查询后端恢复已认证状态 + this.autoRecoverStatus() if (this.status === 'info') { this.loadRightsList() } }, methods: { + // xuchao: 已登录但本地无认证缓存时,仅传手机号查询资格以恢复状态(不带证件号,避免触发被动认证) + autoRecoverStatus() { + if (this.status !== 'auth') return + // xuchao: 用户主动发起过认证流程时,取消后应停留在认证页,不自动恢复 + if (uni.getStorageSync('authFlowStarted')) return + const phone = uni.getStorageSync('phone') + if (!phone) return + this.$u.api.getEligibility({ + phone: phone + }).then(res => { + if (res.errcode !== 0 || !res.data) return + uni.setStorageSync('isAuth', res.data.isAuth) + uni.setStorageSync('hasWin', res.data.hasWin) + uni.setStorageSync('cardNumber', res.data.cardNumber) + uni.setStorageSync('expiresTime', res.data.expiresTime) + // xuchao: 自动恢复成功,清除流程标记 + uni.removeStorageSync('authFlowStarted') + if (res.data.isAuth) { + this.status = res.data.hasWin ? 'info' : 'noWin' + if (this.status === 'info') { + this.loadRightsList() + } + } + }) + }, + // xuchao: 认证取消/未通过:清理旧认证缓存并标记流程已发起,取消后应停留认证页 + markAuthCanceled() { + uni.removeStorageSync('isAuth') + uni.removeStorageSync('hasWin') + uni.removeStorageSync('cardNumber') + uni.removeStorageSync('expiresTime') + uni.setStorageSync('authFlowStarted', true) + }, checkAuthResult() { const url = new URL(window.location.href) let responseStr = url.searchParams.get('response') @@ -261,6 +296,8 @@ uni.setStorageSync('hasWin', eRes.data.hasWin) uni.setStorageSync('cardNumber', eRes.data.cardNumber) uni.setStorageSync('expiresTime', eRes.data.expiresTime) + // xuchao: 认证成功,清除流程标记 + uni.removeStorageSync('authFlowStarted') if (eRes.data.isAuth) { this.status = eRes.data.hasWin ? 'info' : 'noWin' if (this.status === 'info') { @@ -270,6 +307,8 @@ } }) } else { + // xuchao: 实名未通过视为取消认证,清理缓存并标记 + this.markAuthCanceled() uni.showToast({ title: '认证未通过', icon: 'none' @@ -288,6 +327,8 @@ }) }) } else { + // xuchao: 未返回认证回调视为取消认证,清理缓存并标记 + this.markAuthCanceled() uni.showToast({ title: '认证未通过', icon: 'none' @@ -324,6 +365,8 @@ } uni.setStorageSync('authName', this.form.realName) uni.setStorageSync('authIdNo', this.form.idNumber) + // xuchao: 标记已发起认证流程,取消后停留在认证页,不自动恢复 + uni.setStorageSync('authFlowStarted', true) this.loadAliyunSDK().then(() => { const metaInfo = JSON.stringify(window.getMetaInfo()) const returnUrl = window.location.origin + window.location.pathname + @@ -467,7 +510,13 @@ }) }, goBack() { - uni.navigateBack() + // xuchao: 直接通过链接进入(无历史栈)时回到首页 + const pages = getCurrentPages() + if (pages.length > 1) { + uni.navigateBack() + } else { + uni.reLaunch({ url: '/pages/index/index' }) + } } } }