feat(古尔邦节): 调整页面
This commit is contained in:
parent
918bd1b484
commit
5885424dbf
@ -97,7 +97,7 @@ function handleAndroidPlatform(renderFun) {
|
||||
// 等待Flutter注入完成
|
||||
const waitForFlutterInterface = () => {
|
||||
let attempts = 0
|
||||
const maxAttempts = 50 // 最多等待5秒
|
||||
const maxAttempts = 150 // 最多等待15秒
|
||||
|
||||
const checkInterface = () => {
|
||||
attempts++
|
||||
@ -118,19 +118,29 @@ function handleAndroidPlatform(renderFun) {
|
||||
errorLog('调用 getAccessOrigin 出错:', error)
|
||||
}
|
||||
} else if (attempts < maxAttempts) {
|
||||
if (
|
||||
(attempts === 1 || attempts % 20 === 0) &&
|
||||
window.FlutterPageControl &&
|
||||
window.FlutterPageControl.postMessage
|
||||
) {
|
||||
window.FlutterPageControl.postMessage('requestAccessOrigin')
|
||||
}
|
||||
// 没找到,继续查询
|
||||
setTimeout(checkInterface, 100)
|
||||
} else {
|
||||
// 查询次数用完
|
||||
errorLog('Flutter接口注入超时,使用默认数据')
|
||||
// 使用默认的开发数据
|
||||
const mockAccess = JSON.stringify({
|
||||
Authorization: 'Bearer FLUTTER_MOCK_TOKEN',
|
||||
'Req-Lang': 'en',
|
||||
'Req-App-Intel': 'build=1.0;version=2.1;channel=flutter;Req-Imei=flutter-device',
|
||||
'Req-Sys-Origin': 'origin=LIKEI;originChild=LIKEI',
|
||||
})
|
||||
renderFun(mockAccess)
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const mockAccess = JSON.stringify({
|
||||
Authorization: 'Bearer FLUTTER_MOCK_TOKEN',
|
||||
'Req-Lang': 'en',
|
||||
'Req-App-Intel': 'build=1.0;version=2.1;channel=flutter;Req-Imei=flutter-device',
|
||||
'Req-Sys-Origin': 'origin=LIKEI;originChild=LIKEI',
|
||||
})
|
||||
renderFun(mockAccess)
|
||||
} else if (window.FlutterPageControl && window.FlutterPageControl.postMessage) {
|
||||
window.FlutterPageControl.postMessage('requestAccessOrigin')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import { getUserId, setUserInfo } from '@/utils/userStore.js'
|
||||
import { getUserIdentity, getMemberProfile } from '@/api/wallet.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
const APP_CONNECTION_TIMEOUT = 18000
|
||||
|
||||
/**
|
||||
* 默认的连接失败处理函数
|
||||
@ -108,7 +109,20 @@ export const connectToApp = async (onConnected, onFailed = defaultOnFailed) => {
|
||||
console.debug('📱 Establishing new APP connection...')
|
||||
|
||||
const connectionResult = await new Promise((resolve, reject) => {
|
||||
let connectionTimer = null
|
||||
const clearConnectionTimer = () => {
|
||||
if (connectionTimer) {
|
||||
clearTimeout(connectionTimer)
|
||||
connectionTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const connectionPromise = new Promise((connectResolve, connectReject) => {
|
||||
connectionTimer = setTimeout(() => {
|
||||
appConnectionManager.reset()
|
||||
connectReject(new Error('APP connection timeout'))
|
||||
}, APP_CONNECTION_TIMEOUT)
|
||||
|
||||
connectApplication(async (access) => {
|
||||
try {
|
||||
const result = parseAccessOrigin(access)
|
||||
@ -142,7 +156,15 @@ export const connectToApp = async (onConnected, onFailed = defaultOnFailed) => {
|
||||
// 设置连接状态
|
||||
appConnectionManager.setConnecting(connectionPromise)
|
||||
|
||||
connectionPromise.then(resolve).catch(reject)
|
||||
connectionPromise
|
||||
.then((value) => {
|
||||
clearConnectionTimer()
|
||||
resolve(value)
|
||||
})
|
||||
.catch((error) => {
|
||||
clearConnectionTimer()
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
|
||||
console.debug('✅ Connection completed successfully')
|
||||
|
||||
@ -1009,10 +1009,12 @@
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-if="gift.giftPhoto"
|
||||
:src="gift.giftPhoto"
|
||||
alt=""
|
||||
style="width: 70%; aspect-ratio: 1/1; object-fit: contain; display: block"
|
||||
/>
|
||||
<div v-else style="width: 70%; aspect-ratio: 1/1"></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -1742,7 +1744,7 @@ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { setDocumentDirection } from '@/locales/i18n'
|
||||
import { useLangStore } from '@/stores/lang'
|
||||
import { getPngUrl, getWebpUrl } from '@/config/imagePaths.js'
|
||||
import { getWebpUrl } from '@/config/imagePaths.js'
|
||||
import { preloadImages, preloadImagesIdle } from '@/utils/image/imagePreloader.js'
|
||||
import { showError } from '@/utils/toast.js'
|
||||
import { viewUserInfo } from '@/utils/appBridge.js'
|
||||
@ -1812,15 +1814,15 @@ const Minutes = ref('00')
|
||||
const Seconds = ref('00')
|
||||
const weeklyGifts = ref([
|
||||
{
|
||||
giftPhoto: getPngUrl(pageConfig.assetPath, 'redeemR2001'),
|
||||
giftPhoto: '',
|
||||
giftCandy: 0,
|
||||
},
|
||||
{
|
||||
giftPhoto: getPngUrl(pageConfig.assetPath, 'redeemSR2011'),
|
||||
giftPhoto: '',
|
||||
giftCandy: 0,
|
||||
},
|
||||
{
|
||||
giftPhoto: getPngUrl(pageConfig.assetPath, 'redeemSSR2021'),
|
||||
giftPhoto: '',
|
||||
giftCandy: 0,
|
||||
},
|
||||
])
|
||||
@ -1989,7 +1991,7 @@ const currentLangType = computed(() => {
|
||||
|
||||
const isRtlLayout = computed(() => currentLangType.value === 'ar')
|
||||
|
||||
const imageUrl = (filename) => getPngUrl(pageConfig.assetPath, filename)
|
||||
const imageUrl = (filename) => getWebpUrl(pageConfig.assetPath, filename)
|
||||
const webpUrl = (filename) => getWebpUrl(pageConfig.assetPath, filename)
|
||||
|
||||
// 多语言图片:只在 page.config.js 声明已有阿语图时切换 `_ar`,没有就继续使用原图。
|
||||
@ -2563,17 +2565,38 @@ const changeCardDrawResultIndex = (step) => {
|
||||
cardDrawResultIndex.value = (cardDrawResultIndex.value + step + resultCount) % resultCount
|
||||
}
|
||||
|
||||
// 弹窗互斥:打开某个弹窗前先关闭其它弹窗,避免多个内容同时挂在同一遮罩层中。
|
||||
const closeOtherPopups = (activePopup = '') => {
|
||||
if (activePopup !== 'rule') {
|
||||
ruleShow.value = false
|
||||
}
|
||||
|
||||
if (activePopup !== 'history') {
|
||||
historyShow.value = false
|
||||
if (historyObserver) {
|
||||
historyObserver.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
if (activePopup !== 'result') {
|
||||
cardDrawResultShow.value = false
|
||||
cardDrawResultList.value = []
|
||||
cardDrawResultIndex.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
const showCardDrawAnimationThenResult = (animationUrl, actionMode = 'draw') => {
|
||||
if (cardDrawAnimationTimer) {
|
||||
window.clearTimeout(cardDrawAnimationTimer)
|
||||
}
|
||||
|
||||
closeOtherPopups()
|
||||
cardResultActionMode.value = actionMode
|
||||
cardDrawAnimationUrl.value = animationUrl
|
||||
cardDrawAnimationShow.value = Boolean(animationUrl)
|
||||
cardDrawResultShow.value = false
|
||||
|
||||
if (!animationUrl) {
|
||||
closeOtherPopups('result')
|
||||
cardDrawResultShow.value = true
|
||||
return
|
||||
}
|
||||
@ -2581,6 +2604,7 @@ const showCardDrawAnimationThenResult = (animationUrl, actionMode = 'draw') => {
|
||||
cardDrawAnimationTimer = window.setTimeout(() => {
|
||||
cardDrawAnimationShow.value = false
|
||||
cardDrawAnimationTimer = null
|
||||
closeOtherPopups('result')
|
||||
cardDrawResultShow.value = true
|
||||
}, 1500)
|
||||
}
|
||||
@ -3227,6 +3251,7 @@ const handleLotteryDrawRequest = async (drawCount = 1) => {
|
||||
|
||||
const resultIndex = getLotteryResultIndex(drawResult)
|
||||
await startLotteryAnimation(resultIndex)
|
||||
closeOtherPopups('result')
|
||||
cardResultActionMode.value = 'rewardDraw'
|
||||
cardDrawResultImageUrl.value = getLotteryRewardResultImageUrl(drawResult)
|
||||
cardDrawResultList.value = getLotteryRewardResultList(drawResult)
|
||||
@ -3302,6 +3327,7 @@ const changeChildTab = (value) => {
|
||||
|
||||
// 规则弹窗:参考 LuckyDollars Season5,点击规则入口打开,点击遮罩关闭。
|
||||
const openRulePopup = () => {
|
||||
closeOtherPopups('rule')
|
||||
ruleShow.value = true
|
||||
}
|
||||
|
||||
@ -3310,6 +3336,7 @@ const closeRulePopup = () => {
|
||||
}
|
||||
|
||||
const openHistoryPopupRequest = async () => {
|
||||
closeOtherPopups('history')
|
||||
historyShow.value = true
|
||||
historyPage.value = 1
|
||||
historyHasMore.value = true
|
||||
|
||||
@ -2,7 +2,7 @@ export const pageConfig = {
|
||||
name: 'Gulben Festival',
|
||||
routePath: '/activities/gulben-festival',
|
||||
routeName: 'gulben-festival',
|
||||
assetPath: 'Activities/GulbenFestival/',
|
||||
assetPath: 'Activities/GulbenFestivalWebp/',
|
||||
|
||||
activity: {
|
||||
activityId: '1001',
|
||||
|
||||
@ -18,8 +18,8 @@
|
||||
|
||||
## 3. OSS 图片目录
|
||||
|
||||
- OSS 相对路径:`Activities/GulbenFestival/`
|
||||
- 本地开发目录:`public/oss/h5/Azizi/Activities/GulbenFestival/`
|
||||
- OSS 相对路径:`Activities/GulbenFestivalWebp/`
|
||||
- 本地开发目录:`public/oss/h5/Azizi/Activities/GulbenFestivalWebp/`
|
||||
- 是否需要 Codex 自动创建本地开发目录:是
|
||||
- 图片是否已放入本地目录:是
|
||||
|
||||
@ -976,7 +976,7 @@
|
||||
- 补充 Personal Rank / Ranking 预览结构:活动礼物模块使用 `giftBg` 的 3 个预设空位直接展示 giftPhoto / giftCandy,不额外套参考页的 `gift` 单项背景;排行榜布局参考 LuckyDollars Season5,数据改用 `/activity/week-star/ranking` 和 `/activity/week-star/my-rank`;前三名使用 GulbenFestival 私有 `components/topUser.vue` + `top1/top2/top3`,布局为第二名/第一名/第三名左中右排列且第一名稍宽;贡献值参考 WeeklyStar 使用金币图标,前三名贡献值外观在私有组件内参考 GamesKing 的 `topUserDaily.vue` 圆角渐变底;排行榜排名和贡献值文字统一使用白色;第四名以后和我的排名使用 `RankingItem` 承载,名称下方新增 vip 等级图、userLevelBg、wealthLevelBg 等级行,vip 图片根据 `vipLevelName` 按 `VISCOUNT->vip1`、`EARL->vip2`、`MARQUIS->vip3`、`DUKEI->vip4`、`KING->vip5`、`EMPEROR->vip6` 映射展示,没有 `vipLevelName` 时不展示;userLevel 背景图根据 `charmLevel` 按 1-10/11-20/21-30/31-40/41-50 对应 `userLevel1Bg~userLevel5Bg`,wealthLevel 背景图根据 `wealthLevel` 按同样分段对应 `wealthLevel1Bg~wealthLevel5Bg`,内部居中展示对应等级文字,文字白色且 `font-size:1em`;切换到该标签时贴底展示我的排名,并通过底部 `rankingLoadmore` 上拉加载更多
|
||||
- `Personal Rank / Reward` 和 `Personal Rank / Ranking` 的活动奖励、活动礼物都来自 `/activity/king-queen/effective?templateId=2057676469390872578`;页面内必须通过共享缓存方法读取,避免进入 Reward 和 Ranking 时重复请求同一个 effective 接口。
|
||||
- 补充 Room Rank / Reward 和 Ranking:Reward 直接 100vw 展示 `ruleActivity`;Ranking 复用 Personal Rank 的排行榜展示和 weekly-star 上拉分页,但不展示活动礼物模块,头像统一 `border-radius:4px`,列表和我的排名只展示名称、ID、金币数量,不展示 `vip1`、`userLevel1Bg`、`wealthLevel1Bg` 三个等级图片
|
||||
- 创建本地 OSS 目录 `public/oss/h5/Azizi/Activities/GulbenFestival/`
|
||||
- 创建本地 OSS 目录 `public/oss/h5/Azizi/Activities/GulbenFestivalWebp/`
|
||||
- 添加路由 `/activities/gulben-festival`
|
||||
- 添加安全白名单和活动页权限片段
|
||||
|
||||
@ -998,7 +998,7 @@
|
||||
|
||||
构建结果:`npm run build` 通过;保留项目既有的 Vite 运行时图片引用和动态导入提示。
|
||||
|
||||
本地图片目录:`public/oss/h5/Azizi/Activities/GulbenFestival/`
|
||||
本地图片目录:`public/oss/h5/Azizi/Activities/GulbenFestivalWebp/`
|
||||
|
||||
路由 path:`/activities/gulben-festival`
|
||||
|
||||
@ -1012,7 +1012,7 @@
|
||||
|
||||
## 本次同步:图片扫描与预加载
|
||||
|
||||
- 已重新扫描 `public/oss/h5/Azizi/Activities/GulbenFestival/` 下的图片,并同步 `src/views/Activities/GulbenFestival/page.config.js` 的 `preload`。
|
||||
- 已重新扫描 `public/oss/h5/Azizi/Activities/GulbenFestivalWebp/` 下的图片,并同步 `src/views/Activities/GulbenFestival/page.config.js` 的 `preload`。
|
||||
- `blocking` 保持首屏关键图片:`bg`、`ruleBtBg`、`timeBg`、`tagActiveBg`、`tagBg`、`lotteryBg`、`collectGameBg`。
|
||||
- `background` 已补齐当前目录中除首屏关键图外的全部 `.png` 图片:`barrageBg`、`cardBackBg`、`draw1Bt`、`draw5BtBg`、`GameDrawBtBg`、`Gameticket`、`gameTitleR`、`gameTitleSR`、`gameTitleSSR`、`giftBg`、`helpBt`、`leftBt`、`lotteryPrizeActiveBg`、`lotteryPrizeBg`、`moduleActiveBg`、`moduleBg`、`RankingItem`、`redeemR2001~redeemR2005`、`redeemSR2011~redeemSR2013`、`redeemSSR2021~redeemSSR2022`、`RewardTop1~RewardTop3`、`ruleActivity`、`ruleInfoBg`、`taskBtGo`、`taskBtReceive`、`taskBtReceived`、`taskItemBg`、`ticketHandleBtBg`、`ticketR`、`ticketSR`、`ticketSSR`、`top1~top3`、`vip1~vip6`、`userLevel1Bg~userLevel5Bg`、`wealthLevel1Bg~wealthLevel5Bg`。
|
||||
- 已移除 `page.config.js` 预加载中不存在于本地目录的旧素材名:`redeemRGift`、`redeemRGoat`、`redeemRLamp`、`redeemRLight`、`redeemRMoon`、`redeemSRLamb`、`redeemSRScroll`、`redeemSRTurkey`、`redeemSSRGoat`、`redeemSSRLamb`。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user