feat(古尔邦节): 调整页面

This commit is contained in:
hzj 2026-05-23 19:37:03 +08:00
parent 918bd1b484
commit 5885424dbf
6 changed files with 81 additions and 22 deletions

View File

@ -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')
}
}
}

View File

@ -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')

View File

@ -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

View File

@ -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',

View File

@ -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 和 RankingReward 直接 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`