| | |
| | | import axios, { InternalAxiosRequestConfig } from 'axios'; |
| | | import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios'; |
| | | import { useUserStore } from '@/store/modules/user'; |
| | | import { getToken } from '@/utils/auth'; |
| | | import { tansParams, blobValidate } from '@/utils/ruoyi'; |
| | |
| | | import { errorCode } from '@/utils/errorCode'; |
| | | import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'; |
| | | import FileSaver from 'file-saver'; |
| | | import { getLanguage } from '@/lang'; |
| | | import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto'; |
| | | import { encrypt, decrypt } from '@/utils/jsencrypt'; |
| | | import router from '@/router'; |
| | | |
| | | const encryptHeader = 'encrypt-key'; |
| | | let downloadLoadingInstance: LoadingInstance; |
| | | // 是否显示重新登录 |
| | | export const isRelogin = { show: false }; |
| | | export const globalHeaders = () => { |
| | | return { |
| | | Authorization: 'Bearer ' + getToken(), |
| | | clientid: import.meta.env.VITE_APP_CLIENT_ID |
| | | }; |
| | | }; |
| | | |
| | | axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'; |
| | | // 对应国际化资源文件后缀 |
| | | axios.defaults.headers['Content-Language'] = 'zh_CN'; |
| | | axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID; |
| | | // 创建 axios 实例 |
| | | const service = axios.create({ |
| | | baseURL: import.meta.env.VITE_APP_BASE_API, |
| | |
| | | // 请求拦截器 |
| | | service.interceptors.request.use( |
| | | (config: InternalAxiosRequestConfig) => { |
| | | const isToken = (config.headers || {}).isToken === false; |
| | | // 对应国际化资源文件后缀 |
| | | config.headers['Content-Language'] = getLanguage(); |
| | | |
| | | const isToken = config.headers?.isToken === false; |
| | | // 是否需要防止数据重复提交 |
| | | const isRepeatSubmit = !(config.headers || {}).repeatSubmit; |
| | | const isRepeatSubmit = config.headers?.repeatSubmit === false; |
| | | // 是否需要加密 |
| | | const isEncrypt = config.headers?.isEncrypt === 'true'; |
| | | |
| | | if (getToken() && !isToken) { |
| | | config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改 |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | if (import.meta.env.VITE_APP_ENCRYPT === 'true') { |
| | | // 当开启参数加密 |
| | | if (isEncrypt && (config.method === 'post' || config.method === 'put')) { |
| | | // 生成一个 AES 密钥 |
| | | const aesKey = generateAesKey(); |
| | | config.headers[encryptHeader] = encrypt(encryptBase64(aesKey)); |
| | | config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey); |
| | | } |
| | | } |
| | | // FormData数据去请求头Content-Type |
| | | if (config.data instanceof FormData) { |
| | | delete config.headers['Content-Type']; |
| | | } |
| | | return config; |
| | | }, |
| | | (error: any) => { |
| | | console.log(error); |
| | | return Promise.reject(error); |
| | | } |
| | | ); |
| | | |
| | | // 响应拦截器 |
| | | service.interceptors.response.use( |
| | | (res) => { |
| | | (res: AxiosResponse) => { |
| | | if (import.meta.env.VITE_APP_ENCRYPT === 'true') { |
| | | // 加密后的 AES 秘钥 |
| | | const keyStr = res.headers[encryptHeader]; |
| | | // 加密 |
| | | if (keyStr != null && keyStr != '') { |
| | | const data = res.data; |
| | | // 请求体 AES 解密 |
| | | const base64Str = decrypt(keyStr); |
| | | // base64 解码 得到请求头的 AES 秘钥 |
| | | const aesKey = decryptBase64(base64Str.toString()); |
| | | // aesKey 解码 data |
| | | const decryptData = decryptWithAes(data, aesKey); |
| | | // 将结果 (得到的是 JSON 字符串) 转为 JSON |
| | | res.data = JSON.parse(decryptData); |
| | | } |
| | | } |
| | | // 未设置状态码则默认成功状态 |
| | | const code = res.data.code || HttpStatus.SUCCESS; |
| | | // 获取错误信息 |
| | |
| | | }).then(() => { |
| | | isRelogin.show = false; |
| | | useUserStore().logout().then(() => { |
| | | location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'; |
| | | }); |
| | | router.replace({ |
| | | path: '/login', |
| | | query: { |
| | | redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/') |
| | | } |
| | | }) |
| | | }); |
| | | }).catch(() => { |
| | | isRelogin.show = false; |
| | | }); |
| | | } |
| | | return Promise.reject('无效的会话,或者会话已过期,请重新登录。'); |
| | | } else if (code === HttpStatus.SERVER_ERROR) { |
| | | console.log(msg); |
| | | ElMessage({ message: msg, type: 'error' }); |
| | | return Promise.reject(new Error(msg)); |
| | | } else if (code === HttpStatus.WARN) { |
| | |
| | | return Promise.resolve(res.data); |
| | | } |
| | | }, |
| | | (error) => { |
| | | (error: any) => { |
| | | let { message } = error; |
| | | if (message == 'Network Error') { |
| | | message = '后端接口连接异常'; |
| | |
| | | // prettier-ignore |
| | | return service.post(url, params, { |
| | | transformRequest: [ |
| | | (params) => { |
| | | (params: any) => { |
| | | return tansParams(params); |
| | | } |
| | | ], |
| | | headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, |
| | | responseType: 'blob' |
| | | }).then(async (resp) => { |
| | | }).then(async (resp: any) => { |
| | | const isLogin = blobValidate(resp); |
| | | if (isLogin) { |
| | | const blob = new Blob([resp as any]); |
| | | const blob = new Blob([resp]); |
| | | FileSaver.saveAs(blob, fileName); |
| | | } else { |
| | | const resText = await resp.data.text(); |
| | |
| | | ElMessage.error(errMsg); |
| | | } |
| | | downloadLoadingInstance.close(); |
| | | }).catch((r) => { |
| | | }).catch((r: any) => { |
| | | console.error(r); |
| | | ElMessage.error('下载文件出现错误,请联系管理员!'); |
| | | downloadLoadingInstance.close(); |