mp-webview.vue 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <template>
  2. <view class="mp-wv-page">
  3. <view v-if="errorText" class="mp-wv-error">{{ errorText }}</view>
  4. <web-view v-else-if="src" :src="src" />
  5. <view v-else class="mp-wv-error">加载中…</view>
  6. </view>
  7. </template>
  8. <script setup>
  9. import { ref } from 'vue'
  10. import { onLoad } from '@dcloudio/uni-app'
  11. import { AUTH_API, PAGE_PATHS } from '@/config/api'
  12. import { WEB_ORIGIN } from '@/config/env'
  13. import { request, parseResponseJson } from '@/utils/request'
  14. import { useUserStore } from '@/stores/user'
  15. const src = ref('')
  16. const errorText = ref('')
  17. function isAllowedPath(path) {
  18. return typeof path === 'string' && path.startsWith('/m/')
  19. }
  20. onLoad(async (query) => {
  21. const path = decodeURIComponent(String(query?.path || '').trim())
  22. if (!isAllowedPath(path)) {
  23. errorText.value = '无效地址'
  24. uni.showToast({ title: '无效地址', icon: 'none' })
  25. setTimeout(() => {
  26. uni.navigateBack({
  27. fail: () => uni.reLaunch({ url: PAGE_PATHS.workbench })
  28. })
  29. }, 400)
  30. return
  31. }
  32. const userStore = useUserStore()
  33. userStore.checkLoginStatus()
  34. if (!userStore.isLoggedIn) {
  35. uni.reLaunch({ url: PAGE_PATHS.login })
  36. return
  37. }
  38. try {
  39. const res = await request({
  40. url: AUTH_API.MP_WEBVIEW_TICKET,
  41. method: 'POST'
  42. })
  43. const result = parseResponseJson(res)
  44. const ticket = result && result.code === 200 ? result.data?.ticket : ''
  45. if (!ticket) {
  46. throw new Error((result && result.message) || '无法打开内嵌页')
  47. }
  48. const origin = String(WEB_ORIGIN || '').replace(/\/$/, '')
  49. src.value = `${origin}/#${path}?mpTicket=${encodeURIComponent(ticket)}`
  50. } catch (error) {
  51. errorText.value = (error && error.message) || '无法打开内嵌页'
  52. uni.showToast({ title: errorText.value, icon: 'none' })
  53. }
  54. })
  55. </script>
  56. <style scoped>
  57. .mp-wv-page {
  58. min-height: 100vh;
  59. background: #f5f8f7;
  60. }
  61. .mp-wv-error {
  62. padding: 48px 16px;
  63. color: #6b7b74;
  64. font-size: 14px;
  65. text-align: center;
  66. }
  67. </style>