吉安感知网项目-前端
chenyao
3 days ago 7224851bf14cab706d36f695331488941ed4aba6
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
/**
 * 全站http配置
 *
 * axios参数说明
 * isSerialize是否开启form表单提交
 * isToken是否需要token
 */
import axios from 'axios'
import store from '@/store/'
import router from '@/router/'
import { serialize } from '@/utils/util'
import { getToken, removeRefreshToken, removeToken } from '@/utils/auth'
import { isURL, validatenull } from '@/utils/validate'
import website from '@/config/website'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import crypto from '@/utils/crypto'
import { getStore } from '@/utils/store'
import { showToast } from 'vant'
import { baseUrl, baseUrlJals } from '@/config/env'
 
let { VITE_APP_ENV,VITE_APP_XT_URL,VITE_APP_API } = import.meta.env
// 全局未授权错误提示状态,只提示一次
let isErrorShown = false
// 全局锁机制相关变量
window.isRefreshing = false // 标记当前是否正在刷新token
 
// 创建作用域的 axios 实例
const service = axios.create({
    // 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
    timeout: 600000,
    //返回其他状态码
    validateStatus: function (status) {
        return status >= 200 && status <= 500 // 默认的
    },
    //跨域请求,允许保存cookie
    withCredentials: true,
})
NProgress.configure({
    showSpinner: false,
})
 
//http request拦截
service.interceptors.request.use(
    config => {
        // 初始化错误提示状态
        isErrorShown = false
        // if (VITE_APP_ENV === 'development') {
        //     config.url = VITE_APP_API + config.url
        // } else {
        //     config.url = VITE_APP_XT_URL + config.url
        // }
 
        if (config.isUseJals) {
            if (!isURL(config.url) && !config.url.startsWith(baseUrlJals)) {
                config.url = baseUrlJals + config.url
            }
        }
 
        //地址为已经配置状态则不添加前缀
        if (!isURL(config.url) && !config.url.startsWith(baseUrl) && !config.isUseJals) {
            config.url = baseUrl + config.url
        }
 
        config.headers['areaCode'] = store.state.user.selectedAreaCode
        //安全请求header
        config.headers['Blade-Requested-With'] = 'BladeHttpRequest'
        //headers判断是否需要
        // const authorization = config.authorization === false
        // if (!authorization) {
        //     config.headers['Authorization'] = `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`
        // }
 
        config.headers['Authorization'] = store.state.user.token
        // 根据后端要求,post的data为空的话传{}
        if (config.method === 'post') {
            config.data = config.data || {}
        }
        //headers判断请求是否携带token
        const meta = config.meta || {}
        const isToken = meta.isToken === false
        //headers传递token是否加密
        const cryptoToken = config.cryptoToken === true
        //判断传递数据是否加密
        const cryptoData = config.cryptoData === true
        const token = getToken() || getStore({ name: 'token' })
        if (token && !isToken) {
            config.headers[website.tokenHeader] = cryptoToken
                ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
                : 'bearer ' + token
        }
        // 开启报文加密
        // if (cryptoData) {
        //   if (config.params) {
        //     const data = crypto.encryptAES(JSON.stringify(config.params), crypto.aesKey);
        //     config.params = { data };
        //   }
        //   if (config.data) {
        //     config.text = true;
        //     config.data = crypto.encryptAES(JSON.stringify(config.data), crypto.aesKey);
        //   }
        // }
        //headers中配置text请求
        if (config.text === true) {
            config.headers['Content-Type'] = 'text/plain'
        }
        //headers中配置serialize为true开启序列化
        if (config.method === 'post' && meta.isSerialize === true) {
            config.data = serialize(config.data)
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
)
 
//http response拦截
service.interceptors.response.use(
    res => {
        // NProgress.done()
        //获取配置信息
        const config = res.config
        const cryptoData = config.cryptoData === true
        //解析加密报文
        if (cryptoData) {
            res.data = JSON.parse(crypto.decryptAES(res.data, crypto.aesKey))
        }
        //获取状态信息
        const status = res.data.error_code || res.data.code || res.status
        const statusWhiteList = website.statusWhiteList || []
        const message = res.data.msg || res.data.error_description || res.data.message || '系统错误'
        // 处理没有密钥证书,需登录重新联系运维人员上传证书
        if (status === 511) {
            // 获取当前路由名称
            const currentRoutePath = router.currentRoute.value
            if (currentRoutePath.path !== '/login') {
                store.dispatch('FedLogOut').then(() => router.push({ path: '/login' }))
            }
            return Promise.reject(new Error(message))
        }
        //如果在白名单里则自行catch逻辑处理
        if (statusWhiteList.includes(status)) return Promise.reject(res)
        // 如果是401并且没有重试过,尝试刷新token
        if (status === 401) {
            isErrorShown = true
            showToast('用户令牌不可用,请重新登录');
            const transmitData = { data: { type: 'tokenExpired' } }
 
            wx.miniProgram.reLaunch({url: 'pages/login/index'})
            wx.miniProgram.postMessage(transmitData)
            uni.postMessage(transmitData)
 
            removeToken()
            removeRefreshToken()
            // 重定向到登录页
            store.dispatch('FedLogOut').then(() => router.push({ path: '/login' }))
            return Promise.reject(new Error(message))
        }
 
        // 如果请求为oauth2错误码则首次报错时提示
        if (status > 2000 && !validatenull(res.data.error_description)) {
            if (!isErrorShown) {
                isErrorShown = true
                showToast(message);
            }
            return Promise.reject(new Error(message))
        }
        // 如果请求为非200则默认统一处理
        if (status !== 200) {
            // ElMessage({
            //     message: message,
            //     type: status === -2 ? 'warning' : 'error',
            // })
            showToast(message)
            return Promise.reject(new Error(message))
        }
        return res
    },
    error => {
        // NProgress.done()
        return Promise.reject(new Error(error))
    }
)
window._request = service
export default service