5487ece142
- 新增 profile/login.vue 登录页(UnauthLoginPanel) - 新增 profile/setup.vue 完善信息页(头像/昵称/手机号) - profile/index 未登录态显示头像占位+点击登录+菜单列表 - 登录后始终跳转setup页,completeLogin后才持久化token - auth.js 登录后用pendingToken(内存),不检查profile_completed - request.js 401时reLaunch到登录页,不显示toast,防重复跳转 - 约课页移除UnauthLoginPanel,未登录直接显示列表 - session.js 新增needsSetup状态和completeLogin方法
161 lines
4.1 KiB
JavaScript
161 lines
4.1 KiB
JavaScript
const KEY_TOKEN = 'COMPREHENSIVE_VENUE_TOKEN'
|
|
|
|
const API_BASE_URL = import.meta.env.VITE_COMPREHENSIVE_API_BASE_URL || 'http://127.0.0.1:8001'
|
|
|
|
let pendingToken = null
|
|
|
|
const normalizeError = (res, fallbackMessage = '请求服务失败') => {
|
|
const body = res?.data || res || {}
|
|
return {
|
|
code: body.code || res?.statusCode || 50000,
|
|
message: body.message || fallbackMessage,
|
|
errors: body.errors || null,
|
|
statusCode: res?.statusCode
|
|
}
|
|
}
|
|
|
|
export const authStorage = {
|
|
setToken(token) {
|
|
uni.setStorageSync(KEY_TOKEN, token)
|
|
},
|
|
getToken() {
|
|
return uni.getStorageSync(KEY_TOKEN)
|
|
},
|
|
setPendingToken(token) {
|
|
pendingToken = token
|
|
},
|
|
getPendingToken() {
|
|
return pendingToken
|
|
},
|
|
clearPendingToken() {
|
|
pendingToken = null
|
|
},
|
|
clear() {
|
|
uni.removeStorageSync(KEY_TOKEN)
|
|
pendingToken = null
|
|
},
|
|
isLoggedIn() {
|
|
return !!uni.getStorageSync(KEY_TOKEN)
|
|
}
|
|
}
|
|
|
|
let isRedirecting = false
|
|
|
|
function redirectToLogin() {
|
|
if (isRedirecting) return
|
|
const pages = getCurrentPages()
|
|
const current = pages[pages.length - 1]
|
|
const currentRoute = current?.route || ''
|
|
if (currentRoute === 'pages/comprehensive/profile/login' || currentRoute === 'pages/comprehensive/profile/setup') {
|
|
return
|
|
}
|
|
isRedirecting = true
|
|
authStorage.clear()
|
|
uni.reLaunch({ url: '/pages/comprehensive/profile/login', complete: () => { isRedirecting = false } })
|
|
}
|
|
|
|
export function request(options = {}) {
|
|
const token = authStorage.getToken() || authStorage.getPendingToken()
|
|
const header = {
|
|
'Content-Type': 'application/json',
|
|
...(options.header || {})
|
|
}
|
|
|
|
if (token) {
|
|
header.Authorization = `Bearer ${token}`
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
uni.request({
|
|
url: options.url.startsWith('http') ? options.url : `${API_BASE_URL}${options.url}`,
|
|
method: options.method || 'GET',
|
|
data: options.data,
|
|
header,
|
|
success: (res) => {
|
|
const body = res.data
|
|
|
|
if (res.statusCode === 401 || body?.code === 40001) {
|
|
redirectToLogin()
|
|
reject(normalizeError(res, ''))
|
|
return
|
|
}
|
|
|
|
if (res.statusCode >= 200 && res.statusCode < 300 && body?.code === 0) {
|
|
resolve(body.data)
|
|
return
|
|
}
|
|
|
|
const error = normalizeError(res, `请求错误 ${res.statusCode}`)
|
|
uni.showToast({
|
|
title: error.message,
|
|
icon: 'none'
|
|
})
|
|
reject(error)
|
|
},
|
|
fail: (err) => {
|
|
const error = normalizeError(err, '网络连接失败,请检查服务')
|
|
uni.showToast({
|
|
title: error.message,
|
|
icon: 'none'
|
|
})
|
|
reject(error)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
export function uploadFile(options = {}) {
|
|
const token = authStorage.getToken() || authStorage.getPendingToken()
|
|
const header = {
|
|
...(options.header || {})
|
|
}
|
|
|
|
if (token) {
|
|
header.Authorization = `Bearer ${token}`
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
uni.uploadFile({
|
|
url: options.url.startsWith('http') ? options.url : `${API_BASE_URL}${options.url}`,
|
|
filePath: options.filePath,
|
|
name: options.name || 'file',
|
|
formData: options.formData || {},
|
|
header,
|
|
success: (res) => {
|
|
let body = {}
|
|
try {
|
|
body = JSON.parse(res.data || '{}')
|
|
} catch (error) {
|
|
body = {}
|
|
}
|
|
|
|
if (res.statusCode === 401 || body?.code === 40001) {
|
|
redirectToLogin()
|
|
reject(normalizeError({ ...res, data: body }, ''))
|
|
return
|
|
}
|
|
|
|
if (res.statusCode >= 200 && res.statusCode < 300 && body?.code === 0) {
|
|
resolve(body.data)
|
|
return
|
|
}
|
|
|
|
const uploadError = normalizeError({ ...res, data: body }, `上传错误 ${res.statusCode}`)
|
|
uni.showToast({
|
|
title: uploadError.message,
|
|
icon: 'none'
|
|
})
|
|
reject(uploadError)
|
|
},
|
|
fail: (err) => {
|
|
const uploadError = normalizeError(err, '文件上传失败,请检查服务')
|
|
uni.showToast({
|
|
title: uploadError.message,
|
|
icon: 'none'
|
|
})
|
|
reject(uploadError)
|
|
}
|
|
})
|
|
})
|
|
}
|