mirror of
https://gitee.com/bootx/dax-pay-h5
synced 2026-08-11 07:05:34 +08:00
fix(h5/code-pay): 合并码牌路由至 CodePay 父级修复首屏白屏
码牌入口 /h/:code 跳转 /h/alipay/:code 等环境页是跨顶层路由跳转, 触发 App.vue transition mode=out-in 整页 remount Layout, 与 onMounted 内 router.replace 竞争导致首次扫码白屏、刷新才正常 (支付宝 webview 尤为明显)。 与聚合支付同源 bug (commitsda82489/8138d93), 照搬修复范式。 - paths.ts: 新增 CODE_PAY_GROUP='/h' (PC 仍用各 CODE_PAY_* 顶层路由) - modules.ts: 入口 + wechat/alipay/union-pay/douyin 合并到 CodePay 父级 下作子路由, 静态段在 :code 之前避免被吞; matched[0].name 恒为 CodePay - router-guards.ts: ENV name 改子路由名 (CodePayAlipayPage 等); 守卫检查 CodePayPage → CodePayEntry - code-pay/index.vue: 组件名 CodePayDispatch → CodePayEntry; onMounted → onBeforeMount; ENV_ROUTE_NAME 改子路由名 - 4 个环境页 defineOptions name 对齐路由名 (CodePayAlipayPage 等) URL 契约不变: /h/:code、/h/{env}/:code
This commit is contained in:
@@ -100,82 +100,49 @@ const routeModuleList: Array<RouteRecordRaw> = [
|
||||
},
|
||||
],
|
||||
},
|
||||
// 码牌支付-微信端(静态段须在 /h/:code 之前注册)
|
||||
// 码牌支付:入口 + 各宿主环境页 统一在 CodePay 父级下作为子路由
|
||||
// 让 App.vue 顶层 transition key(matched[0].name)在 entry → 环境页跳转时保持不变(都是 CodePay),
|
||||
// 避免整页 remount 与 Entry 的 onBeforeMount router.replace 竞争导致白屏
|
||||
// (曾发生在支付宝 webview:跨顶层 replace 与 <transition mode="out-in" appear> 的 enter 死锁,
|
||||
// 与聚合 Aggregate 同源 bug,修复范式见 commits da82489 / 8138d93)
|
||||
// 注意:静态段(wechat/alipay/union-pay/douyin)必须排在 :code 之前,否则会被当 code 吞掉
|
||||
// URL 契约不变,仍是 /h/:code、/h/{env}/:code
|
||||
{
|
||||
path: RoutePath.CODE_PAY_WECHAT,
|
||||
name: 'CodePayWechat',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'route.codePay', // 码牌支付
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'CodePayWechatPage',
|
||||
component: () => import('@/mobile/views/code-pay/wechat/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
// 码牌支付-支付宝端
|
||||
{
|
||||
path: RoutePath.CODE_PAY_ALIPAY,
|
||||
name: 'CodePayAlipay',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'route.codePay', // 码牌支付
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'CodePayAlipayPage',
|
||||
component: () => import('@/mobile/views/code-pay/alipay/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
// 码牌支付-云闪付端(静态段须在 /h/:code 之前注册)
|
||||
{
|
||||
path: RoutePath.CODE_PAY_UNION,
|
||||
name: 'CodePayUnion',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'route.codePay', // 码牌支付
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'CodePayUnionPage',
|
||||
component: () => import('@/mobile/views/code-pay/union-pay/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
// 码牌支付-抖音端
|
||||
{
|
||||
path: RoutePath.CODE_PAY_DOUYIN,
|
||||
name: 'CodePayDouyin',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'route.codePay', // 码牌支付
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'CodePayDouyinPage',
|
||||
component: () => import('@/mobile/views/code-pay/douyin/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
// 码牌支付入口分发(跨端:PC 为扫码引导页)
|
||||
{
|
||||
path: RoutePath.CODE_PAY,
|
||||
path: RoutePath.CODE_PAY_GROUP,
|
||||
name: 'CodePay',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'route.codePay', // 码牌支付
|
||||
},
|
||||
children: [
|
||||
// 微信环境页
|
||||
{
|
||||
path: '',
|
||||
name: 'CodePayPage',
|
||||
path: 'wechat/:code',
|
||||
name: 'CodePayWechatPage',
|
||||
component: () => import('@/mobile/views/code-pay/wechat/index.vue'),
|
||||
},
|
||||
// 支付宝环境页
|
||||
{
|
||||
path: 'alipay/:code',
|
||||
name: 'CodePayAlipayPage',
|
||||
component: () => import('@/mobile/views/code-pay/alipay/index.vue'),
|
||||
},
|
||||
// 云闪付环境页
|
||||
{
|
||||
path: 'union-pay/:code',
|
||||
name: 'CodePayUnionPage',
|
||||
component: () => import('@/mobile/views/code-pay/union-pay/index.vue'),
|
||||
},
|
||||
// 抖音环境页
|
||||
{
|
||||
path: 'douyin/:code',
|
||||
name: 'CodePayDouyinPage',
|
||||
component: () => import('@/mobile/views/code-pay/douyin/index.vue'),
|
||||
},
|
||||
// 入口:UA 探测后 replace 到环境页(静态段已注册完毕,:code 兜底匹配编码)
|
||||
{
|
||||
path: ':code',
|
||||
name: 'CodePayEntry',
|
||||
component: () => import('@/mobile/views/code-pay/index.vue'),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -20,12 +20,12 @@ const AGGREGATE_ENV_ROUTE_NAME: Record<string, string> = {
|
||||
douyin: 'AggregateDouyinPage',
|
||||
}
|
||||
|
||||
/** 码牌 clientEnv → 路由 name */
|
||||
/** 码牌 clientEnv → 路由 name(指向 CodePay 父级下的环境页子路由,避免跨顶层触发 transition remount) */
|
||||
const CODE_PAY_ENV_ROUTE_NAME: Record<string, string> = {
|
||||
wechat: 'CodePayWechat',
|
||||
alipay: 'CodePayAlipay',
|
||||
union_pay: 'CodePayUnion',
|
||||
douyin: 'CodePayDouyin',
|
||||
wechat: 'CodePayWechatPage',
|
||||
alipay: 'CodePayAlipayPage',
|
||||
union_pay: 'CodePayUnionPage',
|
||||
douyin: 'CodePayDouyinPage',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,8 +59,8 @@ function resolveEntryRedirect(to: RouteLocationNormalized): RouteLocationNormali
|
||||
}
|
||||
}
|
||||
}
|
||||
// 码牌分发入口 → 各宿主端页(非钱包宿主留在 CodePayPage 显示扫码提示)
|
||||
if (to.name === 'CodePayPage') {
|
||||
// 码牌分发入口 → 各宿主端页(非钱包宿主留在 CodePayEntry 显示扫码提示)
|
||||
if (to.name === 'CodePayEntry') {
|
||||
const code = to.params.code as string
|
||||
if (code) {
|
||||
const env = detectClientEnv()
|
||||
@@ -68,7 +68,7 @@ function resolveEntryRedirect(to: RouteLocationNormalized): RouteLocationNormali
|
||||
if (routeName) {
|
||||
return { name: routeName, params: { code }, replace: true }
|
||||
}
|
||||
// browser 等非钱包宿主:留在 CodePayPage(onMounted 显示"请用钱包扫码")
|
||||
// browser 等非钱包宿主:留在 CodePayEntry(onBeforeMount 显示"请用钱包扫码")
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
@@ -9,7 +9,7 @@ import InitLoadingMask from '@/shared/components/pay/InitLoadingMask.vue'
|
||||
import CodePayShell from '../shared/CodePayShell.vue'
|
||||
import { useCodePayPage } from '../shared/useCodePayPage'
|
||||
|
||||
defineOptions({ name: 'CodePayAlipay' })
|
||||
defineOptions({ name: 'CodePayAlipayPage' })
|
||||
|
||||
// 支付宝品牌色
|
||||
const BRAND_COLOR = '#1677ff'
|
||||
|
||||
@@ -9,7 +9,7 @@ import InitLoadingMask from '@/shared/components/pay/InitLoadingMask.vue'
|
||||
import CodePayShell from '../shared/CodePayShell.vue'
|
||||
import { useCodePayPage } from '../shared/useCodePayPage'
|
||||
|
||||
defineOptions({ name: 'CodePayDouyin' })
|
||||
defineOptions({ name: 'CodePayDouyinPage' })
|
||||
|
||||
// 抖音黑白主视觉
|
||||
const BRAND_COLOR = '#161823'
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
* 二维码恒为 /h/:code; 按 UA replace 到微信/支付宝/云闪付/抖音端页,
|
||||
* 其它环境(browser 等)提示用钱包扫码。
|
||||
* 不支持页:四钱包图标 + 加粗标题 + 小号副文案(与聚合 unsupported 一致)。
|
||||
*
|
||||
* 注:跳转须用 onBeforeMount(不用 onMounted),与 App.vue <transition mode="out-in" appear>
|
||||
* 的 enter 动画竞争(onMounted 跳转曾导致首屏白屏、刷新才正常,与聚合 unsupported 同源 bug)。
|
||||
* 同时各环境页须与入口同属 CodePay 父级子路由(见 modules.ts),保证 matched[0].name 不变。
|
||||
*/
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onBeforeMount, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import alipaySvg from '@/shared/assets/icons/channel/alipay.svg'
|
||||
@@ -15,7 +19,7 @@ import unionPaySvg from '@/shared/assets/icons/channel/union_pay.svg'
|
||||
import wechatSvg from '@/shared/assets/icons/channel/wechat.svg'
|
||||
import { detectClientEnv } from '@/shared/utils/client-env'
|
||||
|
||||
defineOptions({ name: 'CodePayDispatch' })
|
||||
defineOptions({ name: 'CodePayEntry' })
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
@@ -33,15 +37,15 @@ const walletIcons = [
|
||||
{ src: douyinSvg, altKey: 'codePay.wallet.douyin' },
|
||||
]
|
||||
|
||||
/** clientEnv → 码牌分端路由 name */
|
||||
/** clientEnv → 码牌分端路由 name(指向 CodePay 父级下的环境页子路由,不跨顶层以避免 transition 竞争) */
|
||||
const ENV_ROUTE_NAME: Record<string, string> = {
|
||||
wechat: 'CodePayWechat',
|
||||
alipay: 'CodePayAlipay',
|
||||
union_pay: 'CodePayUnion',
|
||||
douyin: 'CodePayDouyin',
|
||||
wechat: 'CodePayWechatPage',
|
||||
alipay: 'CodePayAlipayPage',
|
||||
union_pay: 'CodePayUnionPage',
|
||||
douyin: 'CodePayDouyinPage',
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onBeforeMount(() => {
|
||||
const env = detectClientEnv()
|
||||
const routeName = ENV_ROUTE_NAME[env]
|
||||
if (routeName) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import InitLoadingMask from '@/shared/components/pay/InitLoadingMask.vue'
|
||||
import CodePayShell from '../shared/CodePayShell.vue'
|
||||
import { useCodePayPage } from '../shared/useCodePayPage'
|
||||
|
||||
defineOptions({ name: 'CodePayUnion' })
|
||||
defineOptions({ name: 'CodePayUnionPage' })
|
||||
|
||||
// 云闪付品牌红
|
||||
const BRAND_COLOR = '#e21836'
|
||||
|
||||
@@ -9,7 +9,7 @@ import InitLoadingMask from '@/shared/components/pay/InitLoadingMask.vue'
|
||||
import CodePayShell from '../shared/CodePayShell.vue'
|
||||
import { useCodePayPage } from '../shared/useCodePayPage'
|
||||
|
||||
defineOptions({ name: 'CodePayWechat' })
|
||||
defineOptions({ name: 'CodePayWechatPage' })
|
||||
|
||||
// 微信品牌色
|
||||
const BRAND_COLOR = '#07c160'
|
||||
|
||||
@@ -43,6 +43,16 @@ export const RoutePath = {
|
||||
AGGREGATE_GROUP: '/aggregate',
|
||||
/** 聚合-不支持的宿主环境提示(Mobile + PC 注册用) */
|
||||
AGGREGATE_UNSUPPORTED: '/aggregate/unsupported',
|
||||
/**
|
||||
* 码牌支付父级分组(仅 Mobile 路由注册用)
|
||||
* Mobile 把入口 + 各宿主环境页(wechat/alipay/union-pay/douyin)全部合并到此父级下作为
|
||||
* 子路由,让 App.vue 顶层 transition key(matched[0].name)在 entry → 环境页跳转时保持不变
|
||||
* (都是 CodePay),避免整页 remount 与 Entry 的 onBeforeMount router.replace 竞争导致白屏
|
||||
* (曾发生在支付宝 webview:跨顶层 replace 与 <transition mode="out-in" appear> 的 enter 死锁)。
|
||||
* URL 契约不变:/h/{code}、/h/{env}/{code}。
|
||||
* PC 仍用各 CODE_PAY_*(/h/:code、/h/wechat/:code 等)作为单层顶层路由。
|
||||
*/
|
||||
CODE_PAY_GROUP: '/h',
|
||||
/** 码牌支付入口(跨端:Mobile 分发/收款,PC 扫码引导;path 与后端 getCodeLink /h/{code} 一致) */
|
||||
CODE_PAY: '/h/:code',
|
||||
/** 码牌支付-微信端(Mobile 收款;PC 同入口扫码引导) */
|
||||
|
||||
Reference in New Issue
Block a user