navigation.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import appSettings from '@/core/config/app-settings'
  2. import store from '@/store'
  3. const TAB_ROUTES = new Set([
  4. '/pages/index/index',
  5. '/pages/feed/index',
  6. '/pages/live/hall',
  7. '/pages/dynamics/index',
  8. '/pages/mine/index',
  9. '/pages/index',
  10. '/pages/category',
  11. '/pages/feed',
  12. '/pages/cart',
  13. '/pages/user'
  14. ])
  15. export function isExternalHttpUrl(url) {
  16. const raw = String(url || '').trim()
  17. return /^https?:\/\//i.test(raw) || /^\/\//.test(raw)
  18. }
  19. export function buildWebViewPageUrl(targetUrl, title = '') {
  20. const encoded = encodeURIComponent(targetUrl)
  21. let path = `/pages/common/webview?url=${encoded}`
  22. if (title) path += `&title=${encodeURIComponent(title)}`
  23. return path
  24. }
  25. /**
  26. * 跳转应用内原生页面(非 H5 WebView)
  27. * @param {string} jumpUrl 如 /pages/index/scenic-list 或 pages/foo/bar?id=1
  28. * @returns {boolean} 是否识别为有效应用内路径
  29. */
  30. export function openInAppRoute(jumpUrl) {
  31. const raw = String(jumpUrl || '').trim()
  32. if (!raw || isExternalHttpUrl(raw)) return false
  33. let path = raw
  34. if (!path.startsWith('/')) {
  35. if (path.startsWith('pages/')) path = `/${path}`
  36. else return false
  37. }
  38. const qIdx = path.indexOf('?')
  39. const basePath = qIdx >= 0 ? path.slice(0, qIdx) : path
  40. if (TAB_ROUTES.has(basePath)) {
  41. uni.switchTab({
  42. url: basePath,
  43. fail: () => uni.reLaunch({ url: basePath })
  44. })
  45. return true
  46. }
  47. uni.navigateTo({
  48. url: path,
  49. fail: () => {
  50. uni.showToast({ title: '页面不存在', icon: 'none' })
  51. }
  52. })
  53. return true
  54. }
  55. /**
  56. * 根据后端 jump_url 跳转:应用内页面 或 应用内 WebView 打开 H5
  57. * @param {string} jumpUrl
  58. * @param {{ title?: string }} [opts]
  59. */
  60. export function openJumpUrl(jumpUrl, opts = {}) {
  61. const raw = String(jumpUrl || '').trim()
  62. if (!raw) return
  63. if (isExternalHttpUrl(raw)) {
  64. const href = raw.startsWith('//') ? `https:${raw}` : raw
  65. uni.navigateTo({
  66. url: buildWebViewPageUrl(href, opts.title || ''),
  67. fail: () => openExternalUrl(href)
  68. })
  69. return
  70. }
  71. openInAppRoute(raw)
  72. }
  73. export function openPage(url, animationType = 'pop-in', animationDuration = 300) {
  74. uni.navigateTo({
  75. url,
  76. animationType,
  77. animationDuration,
  78. success: (res) => appSettings.debug && console.log(res),
  79. fail: (err) => appSettings.debug && console.log(err)
  80. })
  81. }
  82. export function popPages(delta = 1) {
  83. uni.navigateBack({ delta })
  84. }
  85. export function openWithLogin(url) {
  86. const target = store.state.user.isLogin ? url : '/pages/passport/lobby'
  87. openPage(target)
  88. }
  89. export function openAnyLink(rawUrl) {
  90. const url = decodeURIComponent(rawUrl)
  91. if (TAB_ROUTES.has(url)) {
  92. uni.switchTab({ url })
  93. } else {
  94. openPage(url)
  95. }
  96. }
  97. /** 在系统默认浏览器中打开 https 链接(App / H5) */
  98. export function openExternalUrl(url) {
  99. if (!url || !/^https?:\/\//i.test(url)) return
  100. // #ifdef H5
  101. window.open(url, '_blank')
  102. return
  103. // #endif
  104. // #ifdef APP-PLUS
  105. plus.runtime.openURL(url, () => {
  106. uni.showToast({ title: '無法打開連結', icon: 'none' })
  107. })
  108. return
  109. // #endif
  110. if (typeof plus !== 'undefined' && plus.runtime && plus.runtime.openURL) {
  111. plus.runtime.openURL(url, () => {
  112. uni.showToast({ title: '無法打開連結', icon: 'none' })
  113. })
  114. } else {
  115. uni.setClipboardData({
  116. data: url,
  117. success: () => uni.showToast({ title: '連結已複製', icon: 'none' })
  118. })
  119. }
  120. }
  121. export function previousPageVm() {
  122. const stack = getCurrentPages()
  123. const prior = stack[stack.length - 2]
  124. // #ifdef H5
  125. return prior
  126. // #endif
  127. return prior ? prior.$vm : null
  128. }
  129. export function setNavTitle(text = '', barStyle = {}) {
  130. if (text) uni.setNavigationBarTitle({ title: text })
  131. if (Object.keys(barStyle).length) uni.setNavigationBarColor(barStyle)
  132. }
  133. /** 评论/动态等场景:从评论行解析用户标识(优先 user_no) */
  134. export function resolveCommentUserId(row) {
  135. if (!row) return ''
  136. const user = row.user
  137. const rowUserNo = row.user_no != null && String(row.user_no).trim() !== ''
  138. ? String(row.user_no).trim()
  139. : ''
  140. if (rowUserNo) return rowUserNo
  141. const userUserNo = user && user.user_no != null && String(user.user_no).trim() !== ''
  142. ? String(user.user_no).trim()
  143. : ''
  144. if (userUserNo) return userUserNo
  145. return String((user && user.id) || row.user_id || '').trim()
  146. }
  147. /** 打开用户主页 pages/profile/show?id= */
  148. export function openUserProfile(rowOrId) {
  149. const id = (rowOrId && typeof rowOrId === 'object')
  150. ? resolveCommentUserId(rowOrId)
  151. : String(rowOrId || '').trim()
  152. if (!id) return false
  153. uni.navigateTo({
  154. url: `/pages/profile/show?id=${encodeURIComponent(id)}`,
  155. fail: () => {
  156. uni.showToast({ title: '无法打开主页', icon: 'none' })
  157. }
  158. })
  159. return true
  160. }