Arco项目实战—1 请求和拦截封装

Arco项目实战—1 请求和拦截封装 一、axios请求器和响应拦截器的封装// 这个是全局有4个验证方式 一个 otp验证、一个登录MFA验证一个是提现MFA验证一个是二级密码验证。 // 这个待补充的有 当响应体状态码为 200 的时候返回的统一的消息提示和数据的处理。 当响应体的状态码不是200的时候 返回统一的消息提示和数据的处理。 import axios from axios import Vue from vue import { Encrypt, Decrypt } from ../utils/secret.js //传参 接参 使用加解密 import router from /router/index.js import sha256 from crypto-js/sha256 // 配置axios默认设置 axios.defaults.withCredentials true // 环境判断 const isLocal window.location.hostname localhost const BASE_URL isLocal ? http://192.168.2.104:8002/admin : /admin // const BASE_URL isLocal ? https://admin.tokensafe.io:81/admin : /admin // 47.236.8.103 // 创建axios实例 const instance axios.create({ baseURL: BASE_URL, withCredentials: true }) // 10001 401 100 423 402 429 // 常量定义 错误状态码 const ERROR_CODES { SUCCESS: 200, REFRESH_REQUIRED: 10001, UNAUTHORIZED: 401, PAYMENT_REQUIRED: 402, FORBIDDEN: 403, LOCKED: 423, RATE_LIMIT: 429, SECOND_PASSWORD_REQUIRED: 1104, // 二级验证 PERMISSION_DENIED: 6006, // otp处理中 NOPERMISSIONS_DENIED: 2003, //权限不足 OTP_DISABLED: 6015, MFA_REQUIRED: 6000 // mfa验证 } // 全局安全验证级别码 const VERIFICATION_TYPES { OTP: 1, LOGIN_MFA: 2, WITHDRAWAL_MFA: 3, SECOND_LEVEL: 4, NO_VERIFICATION: 5 } // 工具函数 const getVerificationType () { // 验证方式为 otp if (localStorage.is_otp 2) return VERIFICATION_TYPES.OTP // 验证方式为 mfa if (localStorage.is_open_google 2) return VERIFICATION_TYPES.LOGIN_MFA // 其余为 二级 return VERIFICATION_TYPES.SECOND_LEVEL } const getAuthHeaders (encryptedUserId, xAppMark) { // 必传 请求头 测试环境 const baseHeaders { timezone: Asia/Shanghai, accept-language: zh-CN, x-app-mark: xAppMark, x-user-id: encryptedUserId } // 本地环境添加额外的认证头: at rt 设备id if (isLocal) { const accessToken localStorage.getItem(access-token) || const refreshToken localStorage.getItem(rt) || const deviceId localStorage.getItem(deviceid) || return { ...baseHeaders, access-token: accessToken, refresh-token: refreshToken, device-id: deviceId } } return baseHeaders } const handleErrorResponse response { const { code, message } response.data switch (code) { case ERROR_CODES.REFRESH_REQUIRED: Vue.prototype.$message.error(请刷新页面) break case ERROR_CODES.UNAUTHORIZED: case ERROR_CODES.FORBIDDEN: Vue.prototype.$message.error(message) clearUserData() router.push(/login) break case ERROR_CODES.LOCKED: case ERROR_CODES.PAYMENT_REQUIRED: if (isLocal) { clearUserData() router.push(/login) } break case ERROR_CODES.SECOND_PASSWORD_REQUIRED: localStorage.setItem(is_open_google, 1) location.reload() break case ERROR_CODES.OTP_DISABLED: Vue.prototype.$message.error(账户已被OTP平台禁用,请联系OTP管理人员) break case ERROR_CODES.NOPERMISSIONS_DENIED: // 2003 权限不足不显示消息 break case ERROR_CODES.PERMISSION_DENIED: // 6006 otp处理中 break case ERROR_CODES.RATE_LIMIT: // 429错误不显示消息避免频繁提示 break default: if (code ! ERROR_CODES.MFA_REQUIRED) { Vue.prototype.$message.error(message || 请求失败, 1) } } return response } // 清除用户信息 const clearUserData () { localStorage.removeItem(access-token) localStorage.removeItem(rt) localStorage.clear() } // 请求拦截器 instance.interceptors.request.use( config { const userId localStorage.getItem(user_id) const encryptedUserId localStorage.getItem(encrypted_user_name) || // 生成请求签名 const requestId user_id${userId} const requestBody JSON.stringify(config.data || {}) const signatureContent ${requestId}${requestBody} const xAppMark sha256(signatureContent).toString() const timestamp Math.floor(Date.now() / 1000) const verifyTypeStatus getVerificationType() // 验证方式工具函数 // 加密请求数据 if (config.data) { const encryptedData Encrypt( JSON.stringify({ ...config.data, timestamp, verify_type_status: verifyTypeStatus }) ) config.data { data: encryptedData } } // 设置请求头 根据环境区分传递标头 在 getAuthHeaders 已处理 config.headers { ...config.headers, ...getAuthHeaders(encryptedUserId, xAppMark) } return config }, error { console.error(请求错误:, error) Vue.prototype.$message.error(error.message || 网络错误) return Promise.reject(error) } ) // 响应拦截器 instance.interceptors.response.use( response { const { code, data } response.data if (code ERROR_CODES.SUCCESS data) { try { response.data.data JSON.parse(Decrypt(data)) } catch (error) { console.error(数据解密失败:, error) Vue.prototype.$message.error(数据处理失败) } } else { handleErrorResponse(response) } return response }, error { console.error(响应错误:, error) if (error.response) { // 服务器返回错误状态码 const { status, data } error.response if (status 401 || status 403) { clearUserData() router.push(/login) } Vue.prototype.$message.error(data?.message || 请求失败: ${status}) } else if (error.request) { // 请求已发出但没有收到响应 Vue.prototype.$message.error(网络错误请检查网络连接) } else { // 其他错误 Vue.prototype.$message.error(error.message || 未知错误) } return Promise.reject(error) } ) export default instance