|
|
@@ -3,6 +3,7 @@ import config from '@/config.js'
|
|
|
const BASE_URL = config.API_BASE_URL
|
|
|
|
|
|
var _redirectingToLogin = false
|
|
|
+var _reloginLock = false
|
|
|
|
|
|
function _clearAuthAndRedirect() {
|
|
|
if (_redirectingToLogin) return
|
|
|
@@ -21,6 +22,76 @@ function _clearAuthAndRedirect() {
|
|
|
}, 1500)
|
|
|
}
|
|
|
|
|
|
+// 静默续期成功后回写登录态(token/角色/familyId/openid),保持与 App.vue saveLoginInfo 一致
|
|
|
+function _applyLoginData(data) {
|
|
|
+ uni.setStorageSync('token', data.token)
|
|
|
+ uni.setStorageSync('userId', data.userId)
|
|
|
+ uni.setStorageSync('role', data.role)
|
|
|
+ uni.setStorageSync('currentRole', data.role)
|
|
|
+ uni.setStorageSync('isSwitchedChild', false)
|
|
|
+ uni.setStorageSync('isSwitchedTeacher', false)
|
|
|
+ if (data.openid) {
|
|
|
+ uni.setStorageSync('openid', data.openid)
|
|
|
+ }
|
|
|
+ uni.setStorageSync('userInfo', {
|
|
|
+ nickname: data.nickname,
|
|
|
+ userId: data.userId,
|
|
|
+ familyId: data.familyId
|
|
|
+ })
|
|
|
+ try {
|
|
|
+ var app = typeof getApp === 'function' ? getApp() : null
|
|
|
+ if (app && app.$store) {
|
|
|
+ app.$store.commit('setToken', data.token)
|
|
|
+ app.$store.commit('setUserInfo', {
|
|
|
+ userId: data.userId,
|
|
|
+ role: data.role,
|
|
|
+ familyId: data.familyId,
|
|
|
+ nickname: data.nickname
|
|
|
+ })
|
|
|
+ app.$store.commit('setFamilyId', data.familyId)
|
|
|
+ }
|
|
|
+ } catch (e) { /* 非页面环境无 Vuex,静默忽略 */ }
|
|
|
+}
|
|
|
+
|
|
|
+// 401 处理:优先用缓存 openid 静默续期并重放原请求;续期失败或无 openid 时回退跳登录页
|
|
|
+function _handle401(url, method, data, options, resolve, reject, resData) {
|
|
|
+ // 续期接口自身 401 / 重试仍 401 时,避免递归续期死循环
|
|
|
+ if (_reloginLock) {
|
|
|
+ _clearAuthAndRedirect()
|
|
|
+ reject(resData)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var openid = uni.getStorageSync('openid')
|
|
|
+ if (!openid) {
|
|
|
+ _clearAuthAndRedirect()
|
|
|
+ reject(resData)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _reloginLock = true
|
|
|
+ autoLogin(openid).then(function(res) {
|
|
|
+ if (res && res.data && res.data.token) {
|
|
|
+ console.warn('[API] 401 静默续期成功,重放原请求 ' + url)
|
|
|
+ _applyLoginData(res.data)
|
|
|
+ // 重放原请求;重试期间保持锁,防止重试仍 401 时再次触发续期
|
|
|
+ request(url, method, data, options).then(function(r) {
|
|
|
+ _reloginLock = false
|
|
|
+ resolve(r)
|
|
|
+ }, function(e) {
|
|
|
+ _reloginLock = false
|
|
|
+ reject(e)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ _reloginLock = false
|
|
|
+ _clearAuthAndRedirect()
|
|
|
+ reject(resData)
|
|
|
+ }
|
|
|
+ }).catch(function() {
|
|
|
+ _reloginLock = false
|
|
|
+ _clearAuthAndRedirect()
|
|
|
+ reject(resData)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
const request = (url, method = 'POST', data = {}, options = {}) => {
|
|
|
// Append query params from options to URL if provided (e.g., { guideId } for GET requests)
|
|
|
if (options && Object.keys(options).length > 0) {
|
|
|
@@ -63,8 +134,7 @@ const request = (url, method = 'POST', data = {}, options = {}) => {
|
|
|
success: (res) => {
|
|
|
if (res.statusCode === 401 || res.data.code === 401) {
|
|
|
console.warn('[API] 401 ' + method + ' ' + fullUrl)
|
|
|
- _clearAuthAndRedirect()
|
|
|
- reject(res.data)
|
|
|
+ _handle401(url, method, data, options, resolve, reject, res.data)
|
|
|
return
|
|
|
}
|
|
|
// 5001: 用户无家庭 — resolve 带标记,不 reject;由组件层各自渲染 FamilyEmptyState
|