feat:请求封装的接入
This commit is contained in:
21
env/.env
vendored
21
env/.env
vendored
@@ -1,4 +1,4 @@
|
||||
VITE_APP_TITLE = 'unibest'
|
||||
VITE_APP_TITLE = '芋道管理系统'
|
||||
VITE_APP_PORT = 9000
|
||||
|
||||
VITE_UNI_APPID = '__UNI__D1E5001'
|
||||
@@ -10,7 +10,8 @@ VITE_WX_APPID = 'wxa2abb91f64032a2b'
|
||||
VITE_APP_PUBLIC_BASE=/
|
||||
|
||||
# 后台请求地址
|
||||
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
VITE_SERVER_BASEURL = 'http://localhost:48080/admin-api'
|
||||
VITE_UPLOAD_BASEURL = 'http://localhost:48080/upload'
|
||||
# 备注:如果后台带统一前缀,则也要加到后面,eg: https://ukw0y1.laf.run/api
|
||||
|
||||
# 注意,如果是微信小程序,还有一套请求地址的配置,根据 develop、trial、release 分别设置上传地址,见 `src/utils/index.ts`。
|
||||
@@ -18,13 +19,25 @@ VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
# h5是否需要配置代理
|
||||
VITE_APP_PROXY_ENABLE = false
|
||||
# 下面的不用修改,只要不跟你后台的统一前缀冲突就行。如果修改了,记得修改 `nginx` 里面的配置
|
||||
VITE_APP_PROXY_PREFIX = '/fg-api'
|
||||
VITE_APP_PROXY_PREFIX = '/admin-api'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
|
||||
# 第二个请求地址 (目前alova中可以使用)
|
||||
VITE_SERVER_BASEURL_SECONDARY = 'https://ukw0y1.laf.run'
|
||||
|
||||
# 认证模式,'single' | 'double' ==> 单token | 双token
|
||||
VITE_AUTH_MODE = 'single'
|
||||
VITE_AUTH_MODE = 'double'
|
||||
|
||||
# 原生插件资源复制开关,控制是否启用 copy-native-resources 插件
|
||||
VITE_COPY_NATIVE_RES_ENABLE = false
|
||||
|
||||
# 租户开关
|
||||
VITE_APP_TENANT_ENABLE=true
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
# 默认账户密码
|
||||
VITE_APP_DEFAULT_LOGIN_TENANT_ID = 1
|
||||
VITE_APP_DEFAULT_LOGIN_USERNAME = admin
|
||||
VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123
|
||||
@@ -2,7 +2,7 @@ import type { IDoubleTokenRes } from '@/api/types/login'
|
||||
import type { CustomRequestOptions, IResponse } from '@/http/types'
|
||||
import { nextTick } from 'vue'
|
||||
import { useTokenStore } from '@/store/token'
|
||||
import { isDoubleTokenMode } from '@/utils'
|
||||
import { getLastPage, isDoubleTokenMode } from '@/utils'
|
||||
import { toLoginPage } from '@/utils/toLoginPage'
|
||||
import { ResultEnum } from './tools/enum'
|
||||
|
||||
@@ -55,11 +55,12 @@ export function http<T>(options: CustomRequestOptions) {
|
||||
refreshing = false
|
||||
nextTick(() => {
|
||||
// 关闭其他弹窗
|
||||
uni.hideToast()
|
||||
uni.showToast({
|
||||
title: 'token 刷新成功',
|
||||
icon: 'none',
|
||||
})
|
||||
// 注释 by 芋艿:刷新 token 成功,是后台静默操作,没必要提示用户
|
||||
// uni.hideToast()
|
||||
// uni.showToast({
|
||||
// title: 'token 刷新成功',
|
||||
// icon: 'none',
|
||||
// })
|
||||
})
|
||||
// 将任务队列的所有任务重新请求
|
||||
taskQueue.forEach(task => task())
|
||||
@@ -80,7 +81,14 @@ export function http<T>(options: CustomRequestOptions) {
|
||||
await tokenStore.logout()
|
||||
// 跳转到登录页
|
||||
setTimeout(() => {
|
||||
toLoginPage()
|
||||
// 优化 by 芋艿:跳转登录页时,携带上次浏览的页面地址,登录成功后可以跳回去
|
||||
const lastPage = getLastPage()
|
||||
let queryString = ''
|
||||
if (lastPage) {
|
||||
const fullPath = lastPage.$page?.fullPath || `/${lastPage.route}`
|
||||
queryString = `?redirect=${encodeURIComponent(fullPath)}`
|
||||
}
|
||||
toLoginPage({ queryString })
|
||||
}, 2000)
|
||||
}
|
||||
finally {
|
||||
@@ -96,10 +104,14 @@ export function http<T>(options: CustomRequestOptions) {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
// 处理业务逻辑错误
|
||||
if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) {
|
||||
uni.showToast({
|
||||
// add by 芋艿:后端返回的 msg 提示
|
||||
!options.hideErrorToast
|
||||
&& uni.showToast({
|
||||
icon: 'none',
|
||||
title: responseData.msg || responseData.message || '请求错误',
|
||||
})
|
||||
// add by 芋艿:reject 替代原本的 resolve,避免调用的地方以为请求成功
|
||||
return reject(responseData)
|
||||
}
|
||||
return resolve(responseData.data)
|
||||
}
|
||||
@@ -191,9 +203,3 @@ http.get = httpGet
|
||||
http.post = httpPost
|
||||
http.put = httpPut
|
||||
http.delete = httpDelete
|
||||
|
||||
// 支持与 alovaJS 类似的API调用
|
||||
http.Get = httpGet
|
||||
http.Post = httpPost
|
||||
http.Put = httpPut
|
||||
http.Delete = httpDelete
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import type { CustomRequestOptions } from '@/http/types'
|
||||
import { useTokenStore } from '@/store'
|
||||
import { useTokenStore, useUserStore } from '@/store'
|
||||
import { getEnvBaseUrl } from '@/utils'
|
||||
import { stringifyQuery } from './tools/queryString'
|
||||
|
||||
// 请求基准地址
|
||||
const baseUrl = getEnvBaseUrl()
|
||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||
|
||||
const whiteList: string[] = [
|
||||
'/login',
|
||||
'/refresh-token',
|
||||
'/system/tenant/get-id-by-name',
|
||||
] // 白名单列表,不需要传递 token 字段
|
||||
|
||||
// 拦截器配置
|
||||
const httpInterceptor = {
|
||||
// 拦截前触发
|
||||
invoke(options: CustomRequestOptions) {
|
||||
// 如果您使用了alova,则请把下面的代码放开注释
|
||||
// alova 执行流程:alova beforeRequest --> 本拦截器 --> alova responded
|
||||
// return options
|
||||
|
||||
// 非 alova 请求,正常执行
|
||||
// 接口请求支持通过 query 参数配置 queryString
|
||||
if (options.query) {
|
||||
const queryStr = stringifyQuery(options.query)
|
||||
@@ -51,10 +53,23 @@ const httpInterceptor = {
|
||||
// 3. 添加 token 请求头标识
|
||||
const tokenStore = useTokenStore()
|
||||
const token = tokenStore.validToken
|
||||
|
||||
if (token) {
|
||||
let isToken = (options!.header || {}).isToken === false
|
||||
whiteList.some((v) => {
|
||||
if (options.url && options.url.indexOf(v) > -1) {
|
||||
return (isToken = false)
|
||||
}
|
||||
})
|
||||
if (!isToken && token) {
|
||||
options.header.Authorization = `Bearer ${token}`
|
||||
}
|
||||
|
||||
// 4. 添加租户标识
|
||||
if (tenantEnable && tenantEnable === 'true') {
|
||||
const tenantId = useUserStore().tenantId
|
||||
if (tenantId) {
|
||||
options.header['tenant-id'] = tenantId
|
||||
}
|
||||
}
|
||||
return options
|
||||
},
|
||||
}
|
||||
|
||||
@@ -20,17 +20,18 @@ export type IResponse<T = any> = {
|
||||
[key: string]: any // 允许额外属性
|
||||
}
|
||||
|
||||
// 分页请求参数
|
||||
export interface PageParams {
|
||||
page: number
|
||||
/** 分页参数 */
|
||||
export interface PageParam {
|
||||
pageNo: number
|
||||
pageSize: number
|
||||
[key: string]: any
|
||||
[key: string]: any // 允许额外属性
|
||||
}
|
||||
|
||||
// 分页响应数据
|
||||
/** 分页结果 */
|
||||
export interface PageResult<T> {
|
||||
list: T[]
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
}
|
||||
|
||||
/** 加载状态枚举 - 从 wot-design-uni 重新导出 */
|
||||
export type { LoadMoreState } from 'wot-design-uni/components/wd-loadmore/types'
|
||||
|
||||
@@ -23,7 +23,12 @@ const LOGIN_PAGE = '/pages/login/index'
|
||||
* 如果要立即跳转,不做延时,可以使用 `toLoginPage.flush()` 方法
|
||||
*/
|
||||
export const toLoginPage = debounce((options: ToLoginPageOptions = {}) => {
|
||||
const { mode = 'navigateTo', queryString = '' } = options
|
||||
let { mode = 'navigateTo', queryString = '' } = options
|
||||
// add by 芋艿:如果有查询参数,强制使用 reLaunch 模式。
|
||||
// 原因:携带 redirect 参数,登录成功后可以跳回去。避免使用 navigateTo 导致页面数据不会刷新
|
||||
if (queryString) {
|
||||
mode = 'reLaunch'
|
||||
}
|
||||
|
||||
const url = `${LOGIN_PAGE}${queryString}`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user