fix: keep worldcup live cards above tabbar
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
PANEL = ROOT / "uniapp" / "src" / "packages_match" / "components" / "WorldCupPanel.vue"
|
||||
|
||||
|
||||
def extract_style_block(source: str, selector: str) -> str:
|
||||
start = source.find(selector)
|
||||
if start < 0:
|
||||
raise AssertionError(f"missing selector: {selector}")
|
||||
|
||||
brace = source.find("{", start)
|
||||
if brace < 0:
|
||||
raise AssertionError(f"missing style body for: {selector}")
|
||||
|
||||
depth = 0
|
||||
for pos in range(brace, len(source)):
|
||||
char = source[pos]
|
||||
if char == "{":
|
||||
depth += 1
|
||||
elif char == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return source[brace + 1:pos]
|
||||
|
||||
raise AssertionError(f"unterminated style body for: {selector}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
panel = PANEL.read_text(encoding="utf-8")
|
||||
scroll_style = extract_style_block(panel, ".worldcup-scroll")
|
||||
|
||||
required_tokens = [
|
||||
"140rpx",
|
||||
"constant(safe-area-inset-bottom)",
|
||||
"env(safe-area-inset-bottom)",
|
||||
]
|
||||
for token in required_tokens:
|
||||
if token not in scroll_style:
|
||||
raise AssertionError(f"{PANEL} .worldcup-scroll bottom padding should reserve tabbar space: {token}")
|
||||
|
||||
print("worldcup live bottom padding static checks passed")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -34,11 +34,12 @@
|
||||
<block v-if="activeTab === 'live'">
|
||||
<view v-if="liveCards.length" class="worldcup-live-grid">
|
||||
<view v-for="live in liveCards" :key="`live-${live.live_id}`" class="worldcup-live-card"
|
||||
@tap="goMatchDetail(live)">
|
||||
@tap="openWorldCupLiveCard(live)">
|
||||
<view class="worldcup-live-card__player-wrap">
|
||||
<video :id="`worldcup-live-${live.live_id}`" class="worldcup-live-card__player"
|
||||
:src="live.play_url" :poster="live.home_icon || live.away_icon || ''" :autoplay="true"
|
||||
:muted="true" :controls="!hideLiveCardControlsOnAndroid"
|
||||
<video :id="buildWorldCupLiveVideoId(live)" class="worldcup-live-card__player"
|
||||
:src="resolveWorldCupLivePlayUrl(live)"
|
||||
:poster="live.home_icon || live.away_icon || ''" :autoplay="true" :muted="true"
|
||||
:controls="!hideLiveCardControlsOnAndroid"
|
||||
:show-play-btn="!hideLiveCardControlsOnAndroid"
|
||||
:show-fullscreen-btn="!hideLiveCardControlsOnAndroid" object-fit="cover" />
|
||||
</view>
|
||||
@@ -425,6 +426,32 @@ const liveLineTitle = (live: WorldCupLiveCardItem) => {
|
||||
return normalizeLiveText(live.title) || '直播线路'
|
||||
}
|
||||
|
||||
const buildWorldCupLiveVideoId = (live: WorldCupLiveCardItem) => {
|
||||
return `worldcup-live-${live.live_id || live.id || 0}`
|
||||
}
|
||||
|
||||
const resolveWorldCupLivePlayUrl = (live: WorldCupLiveCardItem) => {
|
||||
const urls: string[] = [
|
||||
live.play_url,
|
||||
live.default_play_url,
|
||||
].map(normalizeLiveText).filter(Boolean)
|
||||
|
||||
if (Array.isArray(live.stream_options)) {
|
||||
live.stream_options.forEach((option) => {
|
||||
urls.push(
|
||||
normalizeLiveText(option?.url),
|
||||
normalizeLiveText(option?.play_url),
|
||||
normalizeLiveText(option?.play_url_m3u8),
|
||||
normalizeLiveText(option?.play_url_hd_m3u8),
|
||||
normalizeLiveText(option?.play_url_flv),
|
||||
normalizeLiveText(option?.play_url_hd_flv)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return urls.find((url) => /\.(m3u8|mp4|flv)(\?|$)/i.test(url)) || urls[0] || ''
|
||||
}
|
||||
|
||||
const liveStatusText = (live: WorldCupLiveCardItem) => {
|
||||
if ((live.status ?? 0) === 1) {
|
||||
return normalizeLiveText(live.current_minute) || '进行中'
|
||||
@@ -602,6 +629,24 @@ const goMatchDetail = (match: any) => {
|
||||
uni.navigateTo({ url: `/pages/match_detail/match_detail?id=${id}` })
|
||||
}
|
||||
|
||||
const openWorldCupLiveCard = (live: WorldCupLiveCardItem) => {
|
||||
if (!resolveWorldCupLivePlayUrl(live)) {
|
||||
uni.showToast({ title: '暂无直播链接', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const videoContext = uni.createVideoContext(buildWorldCupLiveVideoId(live))
|
||||
videoContext?.requestFullScreen?.({
|
||||
direction: 90,
|
||||
})
|
||||
videoContext?.play?.()
|
||||
} catch (error) {
|
||||
console.warn('进入世界杯直播全屏失败', error)
|
||||
uni.showToast({ title: '当前设备暂不支持全屏', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const getWorldCupDisplayDate = (timestamp: number) => {
|
||||
return getLocalMatchDate(timestamp, WORLD_CUP_MATCH_CONTEXT)
|
||||
}
|
||||
@@ -888,6 +933,8 @@ onMounted(() => {
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
padding: 0 14rpx 18rpx;
|
||||
padding-bottom: calc(140rpx + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user