diff --git a/env/.env b/env/.env index bf7e046..9225e17 100644 --- a/env/.env +++ b/env/.env @@ -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 \ No newline at end of file diff --git a/src/http/http.ts b/src/http/http.ts index 88f8508..3f4b24a 100644 --- a/src/http/http.ts +++ b/src/http/http.ts @@ -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(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(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(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 diff --git a/src/http/interceptor.ts b/src/http/interceptor.ts index 9ea1746..7c34bab 100644 --- a/src/http/interceptor.ts +++ b/src/http/interceptor.ts @@ -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 }, } diff --git a/src/http/types.ts b/src/http/types.ts index 9b3d09b..0928666 100644 --- a/src/http/types.ts +++ b/src/http/types.ts @@ -20,17 +20,18 @@ export type IResponse = { [key: string]: any // 允许额外属性 } -// 分页请求参数 -export interface PageParams { - page: number +/** 分页参数 */ +export interface PageParam { + pageNo: number pageSize: number - [key: string]: any + [key: string]: any // 允许额外属性 } -// 分页响应数据 +/** 分页结果 */ export interface PageResult { list: T[] total: number - page: number - pageSize: number } + +/** 加载状态枚举 - 从 wot-design-uni 重新导出 */ +export type { LoadMoreState } from 'wot-design-uni/components/wd-loadmore/types' diff --git a/src/utils/toLoginPage.ts b/src/utils/toLoginPage.ts index de2f8dd..4393115 100644 --- a/src/utils/toLoginPage.ts +++ b/src/utils/toLoginPage.ts @@ -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}`