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'">
|
<block v-if="activeTab === 'live'">
|
||||||
<view v-if="liveCards.length" class="worldcup-live-grid">
|
<view v-if="liveCards.length" class="worldcup-live-grid">
|
||||||
<view v-for="live in liveCards" :key="`live-${live.live_id}`" class="worldcup-live-card"
|
<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">
|
<view class="worldcup-live-card__player-wrap">
|
||||||
<video :id="`worldcup-live-${live.live_id}`" class="worldcup-live-card__player"
|
<video :id="buildWorldCupLiveVideoId(live)" class="worldcup-live-card__player"
|
||||||
:src="live.play_url" :poster="live.home_icon || live.away_icon || ''" :autoplay="true"
|
:src="resolveWorldCupLivePlayUrl(live)"
|
||||||
:muted="true" :controls="!hideLiveCardControlsOnAndroid"
|
:poster="live.home_icon || live.away_icon || ''" :autoplay="true" :muted="true"
|
||||||
|
:controls="!hideLiveCardControlsOnAndroid"
|
||||||
:show-play-btn="!hideLiveCardControlsOnAndroid"
|
:show-play-btn="!hideLiveCardControlsOnAndroid"
|
||||||
:show-fullscreen-btn="!hideLiveCardControlsOnAndroid" object-fit="cover" />
|
:show-fullscreen-btn="!hideLiveCardControlsOnAndroid" object-fit="cover" />
|
||||||
</view>
|
</view>
|
||||||
@@ -425,6 +426,32 @@ const liveLineTitle = (live: WorldCupLiveCardItem) => {
|
|||||||
return normalizeLiveText(live.title) || '直播线路'
|
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) => {
|
const liveStatusText = (live: WorldCupLiveCardItem) => {
|
||||||
if ((live.status ?? 0) === 1) {
|
if ((live.status ?? 0) === 1) {
|
||||||
return normalizeLiveText(live.current_minute) || '进行中'
|
return normalizeLiveText(live.current_minute) || '进行中'
|
||||||
@@ -602,6 +629,24 @@ const goMatchDetail = (match: any) => {
|
|||||||
uni.navigateTo({ url: `/pages/match_detail/match_detail?id=${id}` })
|
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) => {
|
const getWorldCupDisplayDate = (timestamp: number) => {
|
||||||
return getLocalMatchDate(timestamp, WORLD_CUP_MATCH_CONTEXT)
|
return getLocalMatchDate(timestamp, WORLD_CUP_MATCH_CONTEXT)
|
||||||
}
|
}
|
||||||
@@ -888,6 +933,8 @@ onMounted(() => {
|
|||||||
height: 0;
|
height: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0 14rpx 18rpx;
|
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;
|
box-sizing: border-box;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user