|
@@ -1,33 +1,89 @@
|
|
|
<template>
|
|
<template>
|
|
|
<view>
|
|
<view>
|
|
|
- <web-view :src="url"></web-view>
|
|
|
|
|
|
|
+ <web-view v-if="url" :src="url" />
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref } from 'vue'
|
|
import { ref } from 'vue'
|
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
|
|
|
+
|
|
|
|
|
+const FALLBACK_PAGE = '/pages/invoice-entry/index'
|
|
|
|
|
+const MAX_DECODE_TIMES = 3
|
|
|
|
|
+
|
|
|
const url = ref('')
|
|
const url = ref('')
|
|
|
-onLoad((e) => {
|
|
|
|
|
- const option = uni.getLaunchOptionsSync()
|
|
|
|
|
- console.log('onLoad res', option)
|
|
|
|
|
- // 判断如果不是走短链进入 重定向到发票信息确认页
|
|
|
|
|
- if (option.scene != 1194) {
|
|
|
|
|
- uni.redirectTo({
|
|
|
|
|
- url: `/pages/invoice-entry/index`,
|
|
|
|
|
|
|
+
|
|
|
|
|
+const redirectToFallback = (): void => {
|
|
|
|
|
+ uni.redirectTo({
|
|
|
|
|
+ url: FALLBACK_PAGE,
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const getRedirectFromQuery = (query: Record<string, unknown>): string => {
|
|
|
|
|
+ return typeof query.redirect === 'string' ? query.redirect : ''
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const safeDecode = (value: string, maxTimes = MAX_DECODE_TIMES): string => {
|
|
|
|
|
+ let result = value
|
|
|
|
|
+
|
|
|
|
|
+ for (let i = 0; i < maxTimes; i += 1) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const decoded = decodeURIComponent(result)
|
|
|
|
|
+
|
|
|
|
|
+ if (decoded === result) {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result = decoded
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('decode redirect failed:', error)
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const isHttpUrl = (value: string): boolean => {
|
|
|
|
|
+ return /^https?:\/\//i.test(value)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const resolveRedirectUrl = (query: Record<string, unknown>): string => {
|
|
|
|
|
+ const redirectRaw = getRedirectFromQuery(query)
|
|
|
|
|
+
|
|
|
|
|
+ if (!redirectRaw) {
|
|
|
|
|
+ return ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const redirectUrl = safeDecode(redirectRaw)
|
|
|
|
|
+
|
|
|
|
|
+ if (!isHttpUrl(redirectUrl)) {
|
|
|
|
|
+ console.error('非法 redirect 参数:', {
|
|
|
|
|
+ redirectRaw,
|
|
|
|
|
+ redirectUrl,
|
|
|
})
|
|
})
|
|
|
|
|
+ return ''
|
|
|
}
|
|
}
|
|
|
- const redirect = typeof option.query?.redirect === 'string' ? option.query.redirect : ''
|
|
|
|
|
- if (!redirect) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ console.log('redirectRaw:', redirectRaw)
|
|
|
|
|
+ console.log('redirectUrl:', redirectUrl)
|
|
|
|
|
+
|
|
|
|
|
+ return redirectUrl
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+onLoad((query) => {
|
|
|
|
|
+ const redirectUrl = resolveRedirectUrl(query as Record<string, unknown>)
|
|
|
|
|
+
|
|
|
|
|
+ if (!redirectUrl) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '链接参数错误',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ redirectToFallback()
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- const redirectUrl = decodeURIComponent(redirect)
|
|
|
|
|
|
|
+
|
|
|
url.value = redirectUrl
|
|
url.value = redirectUrl
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
-
|
|
|
|
|
-<style>
|
|
|
|
|
-.input {
|
|
|
|
|
- border: 1px solid #ccc;
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|