needLoginError.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. /**
  2. * Token 失效(code:201 / HTTP 401)错误与登录引导,供 request 复用。
  3. */
  4. import { ROUTE_LOGIN, ROUTE_WORKBENCH } from '@/constants/routes'
  5. /** 弹窗展示文案(不使用后端技术向 Token 提示) */
  6. export const RELOGIN_MODAL_CONTENT = '登录已失效,请重新登录'
  7. /** Token 失效专用错误:业务 catch 中应跳过 toast */
  8. export class NeedLoginError extends Error {
  9. readonly needLogin = true
  10. constructor(message?: string) {
  11. super(message || RELOGIN_MODAL_CONTENT)
  12. this.name = 'NeedLoginError'
  13. }
  14. }
  15. export function isNeedLoginError(error: unknown): boolean {
  16. return Boolean(
  17. error &&
  18. typeof error === 'object' &&
  19. (error as NeedLoginError).needLogin === true
  20. )
  21. }
  22. /** 登录失效类文案:已由弹窗/跳转处理,不再 toast */
  23. export function shouldSuppressAuthErrorToast(errorOrMessage: unknown): boolean {
  24. if (isNeedLoginError(errorOrMessage)) return true
  25. const msg =
  26. typeof errorOrMessage === 'string'
  27. ? errorOrMessage
  28. : errorOrMessage instanceof Error
  29. ? errorOrMessage.message
  30. : ''
  31. if (!msg) return false
  32. return /未能读取到有效Token|请重新登录|登录已失效|登录超时|Token/i.test(msg)
  33. }
  34. let lastTokenExpirePromptAt = 0
  35. /** 清理登录态后直接跳登录页(3s 内只触发一次,防多请求并发重复弹窗) */
  36. export function promptReLogin(): void {
  37. const now = Date.now()
  38. if (now - lastTokenExpirePromptAt < 3000) return
  39. lastTokenExpirePromptAt = now
  40. uni.showToast({ title: RELOGIN_MODAL_CONTENT, icon: 'none' })
  41. uni.reLaunch({
  42. url: ROUTE_LOGIN,
  43. fail: () => uni.switchTab({ url: ROUTE_WORKBENCH })
  44. })
  45. }