request.js
6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import host from '@/utils/ip-config.js';
import {
t
} from '@/plugins/index.js'
import {
getStageObj
} from '@/utils/index.js'
let requestFlag = true
let isRefreshing = false // 是否正在刷新token
let refreshSubscribers = [] // 重试队列
// 添加订阅
function addSubscriber(callback) {
refreshSubscribers.push(callback)
}
// 执行订阅的回调
function executeSubscribers(newToken) {
refreshSubscribers.forEach(callback => callback(newToken))
refreshSubscribers = []
}
// 刷新token的函数
async function refreshToken(hostUrlIp) {
if (isRefreshing) {
// 如果已经在刷新,返回一个Promise等待刷新完成
return new Promise((resolve) => {
addSubscriber(resolve)
})
}
isRefreshing = true
try {
const rtoken = uni.getStorageSync('rtoken')
if (!rtoken) {
throw new Error('No refresh token')
}
const userInfoStage = getStageObj('user')
// 使用原生uni.request,避免使用封装的request导致循环调用
const refreshResult = await new Promise((resolve, reject) => {
uni.request({
url: hostUrlIp + `/report/auth/api/v1/auth/users/${userInfoStage.unid}/atoken`, // 根据你的实际接口调整
method: 'GET',
header: {
'Authorization': rtoken
},
success: (res) => {
if (res.data.atoken) {
resolve(res.data.atoken)
} else {
handleAuthFailure('登录已失效,请重新登录')
reject(new Error(res.data.msg || '刷新token失败'))
}
},
fail: (err) => {
reject(err)
}
})
})
// 存储新的Authorization
uni.setStorageSync('Authorization', refreshResult)
isRefreshing = false
// 执行所有等待的回调
executeSubscribers(refreshResult)
return refreshResult
} catch (error) {
console.error('刷新token失败:', error)
isRefreshing = false
refreshSubscribers = [] // 清空队列
throw error
}
}
// 请求封装
export default function request(options, ipType = 'ip') {
// 根据不同的类型选择不同的ip
const ipTypeMap = {
ip: host.ip,
assetsIp: host.assetsIp
}
const url = ipTypeMap[ipType] + options.url
console.log(url,'=s=s');
return new Promise((resolve, reject) => {
const systemInfo = uni.getSystemInfoSync()
const method = options.method?.toUpperCase() || 'GET';
const headerContentType = method === 'GET' ? 'application/x-www-form-urlencoded' : 'application/json';
const _data = {
...(options.data || {}),
}
const languageObj = {
'mall_CN': 'zh-CN,zh;q=0.9',
'zh_CN': 'zh-CN,zh;q=0.9',
'en_US': 'en-US,en;q=0.5',
'zh_TW': 'zh-TW,zh;q=0.3',
}
const lang = uni.getStorageSync('lang') || host.defaultLang
const createRequestConfig = (authorization = null) => {
const authToken = authorization || uni.getStorageSync('Authorization') || ''
return {
url,
data: _data,
method,
timeout: 60 * 1000,
header: {
'content-type': headerContentType,
'Device-OS': systemInfo.platform || 'unknown',
'Device-Model': systemInfo.model || 'unknown',
'Authorization': authToken,
'Accept-Language': languageObj[lang] || 'zh-CN,zh;q=0.9',
},
}
}
// 执行请求
const executeRequest = (authorization = null) => {
let setting = createRequestConfig(authorization)
if (options.header) {
setting.header = Object.assign(setting.header, options.header);
}
uni.request({
...setting,
success: async (res) => {
// 如果是静态资源,直接返回
if (ipType === 'assetsIp' || ipType === 'StoreAssetsIp') {
resolve(res.data);
return;
}
// 处理401状态码
if (res.data.ecode === 401 && ipType !== 'store.keliuyun') {
// 如果是刷新token的接口本身返回401,直接跳转登录
if (options.url === '/report/auth/api') {
handleAuthFailure(res?.data?.enote || t('Message.authLoginError'));
return;
}
try {
// 尝试刷新token
const newToken = await refreshToken(host.ip)
console.log(newToken);
// 使用新token重试当前请求
executeRequest(newToken)
} catch (error) {
// 刷新token失败,跳转登录
handleAuthFailure(t('Message.authLoginError'));
}
return;
} else if (res.data.code !== 200) {
handleRequestError(res, options, reject);
} else {
resolve(res.data);
}
},
fail(err) {
console.log('err', err);
uni.showToast({
icon: 'none',
title: t(err.errMsg || 'app.login.networkError')
})
reject(err);
},
});
}
// 开始第一次请求
executeRequest();
})
}
// 处理认证失败
function handleAuthFailure(message) {
if (requestFlag) {
requestFlag = false
uni.showModal({
title: t('message.prompt'),
showCancel: false,
content: message,
confirmText: t('app.login.reLogin'),
success: function(resModal) {
if (resModal.confirm) {
requestFlag = true
uni.removeStorageSync('Authorization')
uni.removeStorageSync('rtoken')
// uni.clearStorageSync()
uni.reLaunch({
url: '/pages/login/index'
})
} else if (resModal.cancel) {
console.log('用户点击取消');
}
}
})
}
}
// 处理请求错误
function handleRequestError(res, options, reject) {
const errorMsg = res?.data?.msg || 'Error'
if (!options.hiddenMsg) {
uni.showToast({
icon: 'none',
title: errorMsg
})
}
// 针对登录接口 单独修改报错返回信息
if (options.url === '/report/users/login') {
if (['用户名/密码错误', 'Username/Password Incorrect', '用戶名/密碼錯誤'].includes(errorMsg)) {
reject('U/P Error')
}
// 如果是502 提示默认密码 需要修改 同时传递atoken过去
if (res.data.code === 502) {
reject(`P Reset` + '*$*' + `${res?.data?.data?.atoken || ''}`)
}
}
reject(errorMsg)
}