| | |
| | | */ |
| | | const showToast = (message) => { |
| | | if (uni.$u?.toast) { |
| | | uni.$u.toast(message) |
| | | uni.$u.toast(message); |
| | | } else { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | icon: "none", |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 基础配置 - 从环境变量中获取baseURL |
| | | const config = { |
| | | baseURL: '/api', // 使用环境变量中的配置 |
| | | baseURL: "/api", // 使用环境变量中的配置 |
| | | timeout: 60000, |
| | | header: { |
| | | 'Content-Type': 'application/json', |
| | | 'X-Business-System': 'medical-system', |
| | | |
| | | "Content-Type": "application/json", |
| | | "X-Business-System": "medical-system", |
| | | }, |
| | | // 新增配置项 |
| | | loginPage: '/pages/login/Login', // 登录页路径 |
| | | loginPage: "/pages/login/Login", // 登录页路径 |
| | | tokenExpiredCode: 401, // 后端返回的Token过期状态码 |
| | | noPermissionCode: 403, // 无权限状态码 |
| | | // 添加白名单配置(不需要校验token的接口) |
| | | whiteList: [ |
| | | '/login', // 登录接口 |
| | | "/login", // 登录接口 |
| | | // '/dingtalk/auth/login', // 钉钉授权登录接口 |
| | | // '/dingtalk/auth/bind' // 钉钉授权登录绑定接口 |
| | | ] |
| | | } |
| | | ], |
| | | }; |
| | | |
| | | /** |
| | | * 检查请求是否在白名单中 |
| | |
| | | */ |
| | | const isInWhiteList = (url) => { |
| | | // 提取相对路径(移除baseURL)并忽略查询参数 |
| | | const relativeUrl = url.replace(config.baseURL, '').split('?')[0]; |
| | | return config.whiteList.some(path => { |
| | | const relativeUrl = url.replace(config.baseURL, "").split("?")[0]; |
| | | return config.whiteList.some((path) => { |
| | | // 处理通配符情况 |
| | | if (path.endsWith('/')) { |
| | | return relativeUrl.startsWith(path) |
| | | if (path.endsWith("/")) { |
| | | return relativeUrl.startsWith(path); |
| | | } |
| | | // 精确匹配路径 |
| | | return relativeUrl === path |
| | | }) |
| | | } |
| | | return relativeUrl === path; |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 跳转到登录页 |
| | | */ |
| | | const navigateToLogin = () => { |
| | | uni.redirectTo({ |
| | | url: config.loginPage + '?redirect=' + encodeURIComponent(getCurrentPagePath()) |
| | | }) |
| | | } |
| | | url: |
| | | config.loginPage + |
| | | "?redirect=" + |
| | | encodeURIComponent(getCurrentPagePath()), |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 获取当前页面路径(用于登录后跳回) |
| | | */ |
| | | const getCurrentPagePath = () => { |
| | | const pages = getCurrentPages() |
| | | return pages[pages.length - 1]?.route || '' |
| | | } |
| | | const pages = getCurrentPages(); |
| | | return pages[pages.length - 1]?.route || ""; |
| | | }; |
| | | |
| | | /** |
| | | * 检查Token是否过期 |
| | |
| | | */ |
| | | const checkTokenExpired = (statusCode) => { |
| | | if (statusCode === config.tokenExpiredCode) { |
| | | showToast('登录已过期,请重新登录') |
| | | navigateToLogin() |
| | | return true |
| | | showToast("登录已过期,请重新登录"); |
| | | navigateToLogin(); |
| | | return true; |
| | | } |
| | | return false |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | /** |
| | | * 请求拦截器 |
| | | */ |
| | | const requestInterceptor = (options) => { |
| | | const token = uni.getStorageSync('token') |
| | | |
| | | const token = uni.getStorageSync("token"); |
| | | |
| | | // 如果请求在白名单中,直接放行 |
| | | if (isInWhiteList(options.url)) { |
| | | return options |
| | | return options; |
| | | } |
| | | |
| | | // 如果未登录且不是白名单接口,跳转登录 |
| | | // console.log(token,'token'); |
| | | |
| | | |
| | | if (!token) { |
| | | navigateToLogin() |
| | | throw new Error('未登录') |
| | | navigateToLogin(); |
| | | throw new Error("未登录"); |
| | | } |
| | | |
| | | // 添加Token到Header |
| | | options.header = { |
| | | ...options.header, |
| | | 'Authorization': `Bearer ${token}` |
| | | } |
| | | |
| | | return options |
| | | } |
| | | Authorization: `Bearer ${token}`, |
| | | }; |
| | | |
| | | return options; |
| | | }; |
| | | |
| | | /** |
| | | * 响应拦截器 |
| | | */ |
| | | const responseInterceptor = (response) => { |
| | | const { statusCode, data } = response |
| | | |
| | | const { statusCode, data } = response; |
| | | |
| | | // Token过期处理 |
| | | if (checkTokenExpired(statusCode)) { |
| | | return Promise.reject(data) |
| | | return Promise.reject(data); |
| | | } |
| | | |
| | | // 无权限处理 |
| | | if (statusCode === config.noPermissionCode) { |
| | | showToast('无权限访问') |
| | | return Promise.reject(data) |
| | | showToast("无权限访问"); |
| | | return Promise.reject(data); |
| | | } |
| | | |
| | | // 其他错误状态码 |
| | | if (statusCode !== 200) { |
| | | showToast(`请求失败: ${statusCode}`) |
| | | return Promise.reject(data) |
| | | showToast(`请求失败: ${statusCode}`); |
| | | return Promise.reject(data); |
| | | } |
| | | |
| | | // 接口自定义错误码处理(假设data.code为0表示成功) |
| | | if (data?.code !== 200) { |
| | | showToast(data?.msg || '操作失败') |
| | | return Promise.reject(data) |
| | | showToast(data?.msg || "操作失败"); |
| | | return Promise.reject(data); |
| | | } |
| | | |
| | | return data.data || data // 返回实际业务数据 |
| | | } |
| | | return data; // 返回实际业务数据 |
| | | }; |
| | | |
| | | /** |
| | | * 核心请求方法 |
| | |
| | | ...config, |
| | | ...options, |
| | | url: config.baseURL + options.url, |
| | | header: { ...config.header, ...options.header } |
| | | } |
| | | header: { ...config.header, ...options.header }, |
| | | }; |
| | | |
| | | // 请求拦截 |
| | | options = await requestInterceptor(options) |
| | | |
| | | options = await requestInterceptor(options); |
| | | |
| | | // 发起请求 |
| | | return new Promise((resolve, reject) => { |
| | | uni.request({ |
| | | ...options, |
| | | success: (res) => { |
| | | resolve(responseInterceptor(res)) |
| | | resolve(responseInterceptor(res)); |
| | | }, |
| | | fail: (err) => { |
| | | showToast('网络错误,请重试') |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | showToast("网络错误,请重试"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | }); |
| | | } catch (err) { |
| | | return Promise.reject(err) |
| | | return Promise.reject(err); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 快捷方法封装 |
| | | const http = { |
| | | get(url, data = {}, options = {}) { |
| | | return request({ url, data, method: 'GET', ...options }) |
| | | return request({ url, data, method: "GET", ...options }); |
| | | }, |
| | | post(url, data = {}, options = {}) { |
| | | return request({ url, data, method: 'POST', ...options }) |
| | | return request({ url, data, method: "POST", ...options }); |
| | | }, |
| | | put(url, data = {}, options = {}) { |
| | | return request({ url, data, method: 'PUT', ...options }) |
| | | return request({ url, data, method: "PUT", ...options }); |
| | | }, |
| | | delete(url, data = {}, options = {}) { |
| | | return request({ url, data, method: 'DELETE', ...options }) |
| | | return request({ url, data, method: "DELETE", ...options }); |
| | | }, |
| | | // 新增:上传文件方法 |
| | | upload(url, filePath, name = 'file', formData = {}) { |
| | | upload(url, filePath, name = "file", formData = {}) { |
| | | return request({ |
| | | url, |
| | | method: 'POST', |
| | | method: "POST", |
| | | filePath, |
| | | name, |
| | | formData, |
| | | header: { 'Content-Type': 'multipart/form-data' } |
| | | }) |
| | | } |
| | | } |
| | | header: { "Content-Type": "multipart/form-data" }, |
| | | }); |
| | | }, |
| | | }; |
| | | |
| | | // 挂载到全局 |
| | | uni.$uapi = http |
| | | uni.$uapi = http; |
| | | |
| | | export default http |
| | | export default http; |