From 4d9be1e572745750541be8be52a3cb30e1a8408f Mon Sep 17 00:00:00 2001
From: zhangchen <1652267879@qq.com>
Date: 星期五, 12 九月 2025 16:01:07 +0800
Subject: [PATCH] ID1766-封装axios公共模块

---
 src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue |    9 -
 src/store/bedsideAuxiliaryScreen.ts                                |    6 
 src/api/user.ts                                                    |   16 +++
 src/utils/axios.ts                                                 |  230 +++++++++++++++++++++++----------------------
 4 files changed, 138 insertions(+), 123 deletions(-)

diff --git a/src/api/user.ts b/src/api/user.ts
new file mode 100644
index 0000000..f033caf
--- /dev/null
+++ b/src/api/user.ts
@@ -0,0 +1,16 @@
+import request from "@/utils/axios";
+
+/**
+ * 副屏退出登录Api
+ * @returns
+ */
+export function logOutApi(params: string) {
+  return request({
+    url: "/user/info/logoutForSubScreen",
+    method: "post",
+    headers: {
+      "Content-Type": "application/x-www-form-urlencoded",
+    },
+    data: params,
+  });
+}
diff --git a/src/store/bedsideAuxiliaryScreen.ts b/src/store/bedsideAuxiliaryScreen.ts
index edf2057..d40dbc8 100644
--- a/src/store/bedsideAuxiliaryScreen.ts
+++ b/src/store/bedsideAuxiliaryScreen.ts
@@ -15,7 +15,7 @@
 import { ElMessage } from "element-plus/es";
 import { Local } from "@/utils/storage";
 import type { DeviceLoginRecord } from './type/user.type';
-import { logoutForSubScreen } from "@/utils/httpApi";
+import { logOutApi } from "@/api/user";
 
 export const useBedsideAuxiliaryScreenStore = defineStore(
   "bedsideAuxiliaryScreen",
@@ -82,8 +82,8 @@
 
 
     /** 退出登录 */
-    const logout = async (deviceCode: string) => {
-      await logoutForSubScreen(deviceCode);
+    const logout = async (deviceCodeStr: string) => {
+      await logOutApi(deviceCodeStr);
       setUserInfo(null);
     };
 
diff --git a/src/utils/axios.ts b/src/utils/axios.ts
index 2a102d7..9c6a2b4 100644
--- a/src/utils/axios.ts
+++ b/src/utils/axios.ts
@@ -1,132 +1,134 @@
-import axios, {AxiosError, AxiosResponse} from 'axios'
-import {useRouter} from 'vue-router'
+import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
 import Qs from 'qs'
 import { useBedsideAuxiliaryScreenStore } from '@/store/bedsideAuxiliaryScreen'
+import { ElMessage } from 'element-plus/es'
 
-const BASE_URL = import.meta.env.VITE_BASIC_API
+// ====== 配置 ======
+const BASE_URL = import.meta.env.VITE_API_BASE_URL
+const TIME_OUT = 60 * 1 * 1000
 
-const TIME_OUT = 60 * 2 * 1000
-// 正在进行中的请求列表
-let reqList: any[] = [] // 如果某个api存在这个数组里,说明该api暂时无法再次请求
+// 正在进行中的请求列表,避免重复请求
+let reqList: string[] = []
 
-  /**
- * 允许某个请求可以继续进行
- * @param {array} reqList 全部请求列表
- * @param {string} url 请求地址
- */
-const allowRequest = function (reqList: any[], url: any) {
-	for (let i = 0; i < reqList.length; i++) {
-	  if (reqList[i] === url) {
-		reqList.splice(i, 1)
-		break
-	  }
-	}
-  }
 /**
- * 创建axios实例
+ * 允许某个请求再次发送
  */
-const instance = axios.create({
-    baseURL: BASE_URL,
-    timeout: TIME_OUT,
-    paramsSerializer: function(params) {//序列化请求参数,避免get请求参数出现&,空格等识别错误的问题
-        return Qs.stringify(params, {arrayFormat: 'brackets'})
-    },
-})
-
-const errorHandle = (status: number, error:any): void => {
-    // HTTP状态码判断
-    switch (status) {
-        case 401:
-            return alert(`Error Code: ${status}, Message: ${error.msg || '登录失效,请重新登录'}`)
-        case 403:
-            return alert(`Error Code: ${status}, Message: ${error.msg || '你没有访问权限'}`)
-        case 500:
-            return alert(`Error Code: ${status}, Message: ${error.msg || '后台错误,请联系管理员'}`)
-        case 502:
-            return alert(`Error Code: ${status}, Message: ${error.msg || '平台环境异常'}`)
-        default:
-            alert(`Error Code: ${status}, Message: ${error.msg || '未知错误,请刷新重试'}`)
-    }
+const allowRequest = (url?: string) => {
+  if (!url) return
+  const idx = reqList.indexOf(url)
+  if (idx > -1) reqList.splice(idx, 1)
 }
 
-// 前置拦截器(发起请求之前的拦截)
+/**
+ * 创建 axios 实例
+ */
+const instance = axios.create({
+  baseURL: BASE_URL,
+  timeout: TIME_OUT,
+  paramsSerializer: (params) => Qs.stringify(params, { arrayFormat: 'brackets' }),
+})
+
+// ====== 错误处理函数 ======
+const errorHandle = (status: number, error: any): void => {
+  const msg = error?.msg || error?.message || ''
+  switch (status) {
+    case 401:
+      ElMessage.error(`Error Code: 401, Message: ${msg || '登录失效,请重新登录'}`);
+      break
+    case 403:
+      ElMessage.error(`Error Code: 403, Message: ${msg || '你没有访问权限'}`);
+      break
+    case 500:
+      ElMessage.error(`Error Code: 500, Message: ${msg || '后台错误,请联系管理员'}`);
+      break
+    case 502:
+      alert()
+      ElMessage.error(`Error Code: 502, Message: ${msg || '平台环境异常'}`);
+      break
+    default:
+      ElMessage.error(`Error Code: ${status}, Message: ${msg || '未知错误,请刷新重试'}`);
+  }
+}
+
+// ====== 请求拦截 ======
 instance.interceptors.request.use(
-    (response:any) =>{
-        if (useBedsideAuxiliaryScreenStore().userInfo?.token) {
-            response.headers.common['Authorization'] = 'Bearer '+ `${useBedsideAuxiliaryScreenStore().userInfo?.token}`
-        }
-        let cancel
-		// 设置cancelToken对象
-		response.cancelToken = new axios.CancelToken(function(c) {
-		    cancel = c
-		})
-        return response
-    },
-    (error) => Promise.reject(error)
+  (config: InternalAxiosRequestConfig) => {
+    const store = useBedsideAuxiliaryScreenStore()
+
+    // 加 token
+    if (store.userInfo?.token) {
+      config.headers.set('Authorization', `Bearer ${store.userInfo.token}`)
+    }
+
+    // 防止同一接口短时间内重复请求
+    if (config.url) {
+      if (reqList.includes(config.url)) {
+        return Promise.reject(new axios.Cancel(`重复请求:${config.url}`))
+      } else {
+        reqList.push(config.url)
+      }
+    }
+
+    return config
+  },
+  (error) => Promise.reject(error),
 )
 
-// 后置拦截器(获取到响应时的拦截)
+// ====== 响应拦截 ======
 instance.interceptors.response.use(
+  (res: AxiosResponse) => {
 
-    (res: AxiosResponse) => {
-        // 增加延迟,相同请求不得在短时间内重复发送
-		setTimeout(() => {
-			allowRequest(reqList, res.config.url)
-		  }, 1000) // 上一次请求返回后过1s才允许再次请求
-        if (String(res.status).indexOf('2') !== 0) {
-            return {
-                code: res.status,
-                message: res.data.message || '请求异常,请刷新重试',
-                result: false
-            }
-        }
-        if (res.data.code===200){
-            return res.data
-        }
-        // 返回异常
-        else {
-            // Toast(res.data.message)
-            // 白名单,直接返回不提示
-            const whiteList: string[] = ["/patient/hemo/med/record/updateSchemeTool","/patient/hemo/med/monitor/data/prepareAdd"];
-            const requestUrl = res.request.responseURL;
-            const isInWhiteList = whiteList.some(item => requestUrl.includes(item));
-            if(isInWhiteList) return Promise.reject(res.data);
-
-            return Promise.reject(res.data)
-        }
-        // return Promise.reject(instance.interceptors.response)
-    },
-    (error: AxiosError) => {
-        if (axios.isCancel(error)) {
-			console.log(error.message);
-        } 
-        else {
-        setTimeout(() => {
-            allowRequest(reqList, error.config.url)
-            }, 1000) // 请求失败返回后过1s才允许再次请求
-        }
-        if (error && error.response) {
-            // 请求已发出,但是不在2xx的范围
-            errorHandle(error.response.status, error.response)
-            if (error.response.status===401){
-                Dialog.confirm({
-                    title: '提示',
-                    message:
-                        '是否需要退出登录?',
-                })
-                    .then(() => {
-                        Session.clear(); // 清除浏览器全部临时缓存
-			            window.location.href = '/'; // 去登录页
-                    })
-                    .catch(() => {
-                        Toast('取消操作')
-                    })
-            }
-            return Promise.reject(error.response)
-        }
-        Toast('网络请求失败, 请刷新重试')
-        return Promise.reject(error)
+    setTimeout(() => allowRequest(res.config.url), 1000)
+    if (String(res.status).charAt(0) !== '2') {
+      return Promise.reject({
+        code: res.status,
+        message: res.data?.message || '请求异常,请刷新重试',
+      })
     }
+    if (res.data?.code === 200) return res.data
+    const whiteList: string[] = []
+    const requestUrl: string = res?.config?.url || ''
+    const isInWhiteList = whiteList.some((item) => requestUrl.includes(item))
+    ElMessage.error(res.data.message);
+    if (isInWhiteList) return Promise.reject(res.data)
+    return Promise.reject(res.data)
+  },
+
+  
+  (err: unknown) => {
+
+    const anyErr = err as any
+    const configUrl = anyErr?.config?.url
+    // 失败后 1s 允许再次请求
+    setTimeout(() => allowRequest(configUrl), 1000)
+
+    // 先判断是否是取消请求
+    if (axios.isCancel(err as any)) {
+      console.warn('请求被取消:', (err as any)?.message)
+      return Promise.reject(err)
+    }
+
+    // 判断是否为 axios 的错误类型(有 response)
+    if (axios.isAxiosError(err)) {
+      const axErr = err // 现在 TypeScript 知道这是 AxiosError
+      if (axErr.response) {
+        // 使用你现有的错误处理函数
+        errorHandle(axErr.response.status, axErr.response.data)
+
+        if (axErr.response.status === 401) {
+            ElMessage.error('请登录');
+        }
+        return Promise.reject(axErr.response.data || axErr.response)
+      }
+
+      ElMessage.error('网络请求失败, 请刷新重试');
+      return Promise.reject(axErr)
+    }
+
+    //(未知错误)
+    ElMessage.error('网络请求失败, 请刷新重试');
+    return Promise.reject(err)
+  },
 )
 
 export default instance
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
index fe56ba9..a30b281 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
@@ -97,19 +97,16 @@
         .then(async() => {
             state.loading = true
             try {
-              await bedsideAuxiliaryScreenStore.logout(bedsideAuxiliaryScreenStore.deviceCode);
+              await bedsideAuxiliaryScreenStore.logout(`deviceCode=${bedsideAuxiliaryScreenStore.deviceCode}`);
               handleCancel();
               ElMessage.success('退出登录成功')
               handleCancel();
             } catch (error) {
-              ElMessage.success('退出登录失败')
+              console.error('error: ', error)
+              // ElMessage.error('退出登录失败')
             } finally {
               state.loading = false;
             }
-          ElMessage({
-            type: "success",
-            message: "退出成功!",
-          });
         })
         .catch(() => {});
     };

--
Gitblit v1.8.0