337 lines
9.6 KiB
JavaScript
337 lines
9.6 KiB
JavaScript
|
|
/**
|
|||
|
|
* 网络请求封装
|
|||
|
|
*/
|
|||
|
|
import { useUserStore } from '@/store/user'
|
|||
|
|
|
|||
|
|
// 根据环境自动切换API地址
|
|||
|
|
// 开发环境:统一使用本地服务器
|
|||
|
|
// 生产环境:使用线上服务器
|
|||
|
|
|
|||
|
|
// 开发模式标志(手动切换)
|
|||
|
|
const IS_DEV = false // 改为 false 则使用生产环境
|
|||
|
|
|
|||
|
|
// 根据开发模式选择BASE_URL
|
|||
|
|
const BASE_URL = IS_DEV
|
|||
|
|
? 'http://localhost:8089' // 开发环境 - 本地服务器
|
|||
|
|
: 'https://px.ddn-ai.cloud' // 生产环境 - 线上服务器
|
|||
|
|
|
|||
|
|
console.log('[Request] 当前环境:', IS_DEV ? '开发环境' : '生产环境')
|
|||
|
|
console.log('[Request] BASE_URL:', BASE_URL)
|
|||
|
|
|
|||
|
|
const LOGIN_EXCLUDE_URLS = [
|
|||
|
|
'/api/auth/login',
|
|||
|
|
'/api/auth/wx-login',
|
|||
|
|
'/api/user/login/wechat',
|
|||
|
|
'/api/auth/register',
|
|||
|
|
'/api/auth/reapply',
|
|||
|
|
'/api/auth/send-code',
|
|||
|
|
'/api/auth/refresh-token'
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
let isHandlingAuthExpired = false
|
|||
|
|
|
|||
|
|
function buildAuthHeader(token) {
|
|||
|
|
if (!token) return ''
|
|||
|
|
return token.startsWith('Bearer ') ? token : `Bearer ${token}`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function normalizeToken(token) {
|
|||
|
|
return buildAuthHeader(token)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function shouldHandleAuthExpired(url) {
|
|||
|
|
return !LOGIN_EXCLUDE_URLS.includes(url)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 发送请求
|
|||
|
|
*/
|
|||
|
|
function request(options) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// 获取租户ID
|
|||
|
|
const tenantId = uni.getStorageSync('currentTenantId')
|
|||
|
|
|
|||
|
|
// 获取token
|
|||
|
|
const token = uni.getStorageSync('token')
|
|||
|
|
const requestToken = token
|
|||
|
|
|
|||
|
|
// 设置请求头
|
|||
|
|
const header = {
|
|||
|
|
'Content-Type': 'application/json;charset=UTF-8',
|
|||
|
|
...options.header
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加租户ID到请求头
|
|||
|
|
if (tenantId) {
|
|||
|
|
header['X-Tenant-Id'] = tenantId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加token到请求头
|
|||
|
|
if (token) {
|
|||
|
|
const authHeader = buildAuthHeader(token)
|
|||
|
|
header['Authorization'] = authHeader
|
|||
|
|
console.log('[Request] 发送请求,token:', token)
|
|||
|
|
console.log('[Request] Authorization头:', authHeader)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理 GET 请求参数(拼接到 URL)
|
|||
|
|
let url = BASE_URL + options.url
|
|||
|
|
if (options.method === 'GET' && options.params) {
|
|||
|
|
const queryString = Object.keys(options.params)
|
|||
|
|
.filter(key => options.params[key] !== null && options.params[key] !== undefined && options.params[key] !== '')
|
|||
|
|
.map(key => {
|
|||
|
|
const value = options.params[key]
|
|||
|
|
const encodedValue = (value !== null && typeof value === 'object')
|
|||
|
|
? encodeURIComponent(JSON.stringify(value))
|
|||
|
|
: encodeURIComponent(value)
|
|||
|
|
return `${encodeURIComponent(key)}=${encodedValue}`
|
|||
|
|
})
|
|||
|
|
.join('&')
|
|||
|
|
if (queryString) {
|
|||
|
|
url += (url.includes('?') ? '&' : '?') + queryString
|
|||
|
|
}
|
|||
|
|
console.log('[Request] GET URL:', url)
|
|||
|
|
console.log('[Request] GET Params:', options.params)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 发送请求
|
|||
|
|
uni.request({
|
|||
|
|
url: url,
|
|||
|
|
method: options.method || 'GET',
|
|||
|
|
data: options.method === 'GET' ? undefined : (options.data || options.params),
|
|||
|
|
header: header,
|
|||
|
|
success: (res) => {
|
|||
|
|
console.log('[Request] Response:', res)
|
|||
|
|
|
|||
|
|
// 处理401未登录
|
|||
|
|
if (res.statusCode === 401) {
|
|||
|
|
if (!shouldHandleAuthExpired(options.url)) {
|
|||
|
|
reject({ code: 401, message: '未登录', data: res })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const latestToken = uni.getStorageSync('token')
|
|||
|
|
if (latestToken && normalizeToken(requestToken) !== normalizeToken(latestToken)) {
|
|||
|
|
reject({ code: 401, message: '未登录', data: res })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isHandlingAuthExpired) {
|
|||
|
|
reject({ code: 401, message: '未登录', data: res })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
isHandlingAuthExpired = true
|
|||
|
|
console.log('[Request] 401 未登录,清除token')
|
|||
|
|
uni.removeStorageSync('token')
|
|||
|
|
uni.removeStorageSync('userInfo')
|
|||
|
|
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '登录已过期',
|
|||
|
|
content: '请重新登录',
|
|||
|
|
showCancel: false,
|
|||
|
|
success: () => {
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url: '/pages/login/index'
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
complete: () => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isHandlingAuthExpired = false
|
|||
|
|
}, 500)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
reject({ code: 401, message: '未登录', data: res })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (res.statusCode === 200) {
|
|||
|
|
if (res.data && typeof res.data === 'object' && res.data.code === 401) {
|
|||
|
|
if (!shouldHandleAuthExpired(options.url)) {
|
|||
|
|
reject({ code: 401, message: '未登录', data: res.data })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const latestToken = uni.getStorageSync('token')
|
|||
|
|
if (latestToken && normalizeToken(requestToken) !== normalizeToken(latestToken)) {
|
|||
|
|
reject({ code: 401, message: '未登录', data: res.data })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!isHandlingAuthExpired) {
|
|||
|
|
isHandlingAuthExpired = true
|
|||
|
|
console.log('[Request] 业务码401 未登录,清除所有登录信息')
|
|||
|
|
uni.removeStorageSync('token')
|
|||
|
|
uni.removeStorageSync('userInfo')
|
|||
|
|
uni.removeStorageSync('currentRole') // 🔥 关键修复:也清除角色信息
|
|||
|
|
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '登录已过期',
|
|||
|
|
content: '请重新登录',
|
|||
|
|
showCancel: false,
|
|||
|
|
success: () => {
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url: '/pages/login/index'
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
complete: () => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isHandlingAuthExpired = false
|
|||
|
|
}, 500)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reject({ code: 401, message: '未登录', data: res.data })
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
// 返回完整的响应对象,让调用方自己处理
|
|||
|
|
resolve(res.data)
|
|||
|
|
} else if (res.statusCode === 404) {
|
|||
|
|
console.error('[Request] 404 Not Found:', url)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '接口不存在',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject({ code: 404, message: '接口不存在', data: res })
|
|||
|
|
} else if (res.statusCode === 500) {
|
|||
|
|
console.error('[Request] 500 Server Error:', res)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '服务器错误',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject({ code: 500, message: '服务器错误', data: res })
|
|||
|
|
} else {
|
|||
|
|
console.error('[Request] Error:', res.statusCode, res)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: `网络错误(${res.statusCode})`,
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(res)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('[Request] Fail:', err)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '网络连接失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(err)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导出便捷方法
|
|||
|
|
request.get = function(url, params) {
|
|||
|
|
return request({
|
|||
|
|
url: url,
|
|||
|
|
method: 'GET',
|
|||
|
|
params: params
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.post = function(url, data, params) {
|
|||
|
|
// 如果有 params,拼接到 URL
|
|||
|
|
if (params && typeof params === 'object') {
|
|||
|
|
const queryString = Object.keys(params)
|
|||
|
|
.filter(key => params[key] !== null && params[key] !== undefined && params[key] !== '')
|
|||
|
|
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|||
|
|
.join('&')
|
|||
|
|
if (queryString) {
|
|||
|
|
url += (url.includes('?') ? '&' : '?') + queryString
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return request({
|
|||
|
|
url: url,
|
|||
|
|
method: 'POST',
|
|||
|
|
data: data,
|
|||
|
|
params: params
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.put = function(url, data, params) {
|
|||
|
|
// 如果有 params,拼接到 URL
|
|||
|
|
if (params && typeof params === 'object') {
|
|||
|
|
const queryString = Object.keys(params)
|
|||
|
|
.filter(key => params[key] !== null && params[key] !== undefined && params[key] !== '')
|
|||
|
|
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|||
|
|
.join('&')
|
|||
|
|
if (queryString) {
|
|||
|
|
url += (url.includes('?') ? '&' : '?') + queryString
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return request({
|
|||
|
|
url: url,
|
|||
|
|
method: 'PUT',
|
|||
|
|
data: data,
|
|||
|
|
params: params
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.delete = function(url, params) {
|
|||
|
|
return request({
|
|||
|
|
url: url,
|
|||
|
|
method: 'DELETE',
|
|||
|
|
params: params
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.upload = function(url, filePath) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const token = uni.getStorageSync('token')
|
|||
|
|
const tenantId = uni.getStorageSync('currentTenantId')
|
|||
|
|
|
|||
|
|
const header = {
|
|||
|
|
'Authorization': token ? `Bearer ${token}` : ''
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (tenantId) {
|
|||
|
|
header['X-Tenant-Id'] = tenantId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const uploadTask = uni.uploadFile({
|
|||
|
|
url: BASE_URL + url,
|
|||
|
|
filePath: filePath,
|
|||
|
|
name: 'file',
|
|||
|
|
header: header,
|
|||
|
|
timeout: 60000, // 60秒超时
|
|||
|
|
success: (res) => {
|
|||
|
|
try {
|
|||
|
|
const data = JSON.parse(res.data)
|
|||
|
|
if (data.code === 200) {
|
|||
|
|
resolve(data.data)
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: data.message || '上传失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(data)
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('解析上传响应失败:', res.data)
|
|||
|
|
reject({ message: '服务器响应异常' })
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('上传失败:', err)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: err.errMsg || '上传失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(err)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 监听上传进度
|
|||
|
|
uploadTask.onProgressUpdate((res) => {
|
|||
|
|
console.log('上传进度:', res.progress + '%')
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default request
|
|||
|
|
|