完善比赛状态显示

This commit is contained in:
2025-04-22 19:38:08 +08:00
parent 71550c35b5
commit 5f48a8a55e
3 changed files with 205 additions and 111 deletions

View File

@@ -4,6 +4,18 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html, body {
margin: 0;
padding: 0;
/* height: 100%; */
/* overflow: hidden; */
}
#app {
width: 100%;
height: 100%;
}
</style>
<title>NBA在线</title> <title>NBA在线</title>
</head> </head>
<body> <body>

View File

@@ -5,7 +5,7 @@
<div class="team-info away-team"> <div class="team-info away-team">
<img :src="gameData.awayTeam.logo" :alt="gameData.awayTeam.name" /> <img :src="gameData.awayTeam.logo" :alt="gameData.awayTeam.name" />
<div class="team-details"> <div class="team-details">
<h3>{{ gameData.awayTeam.city }}</h3> <!-- <h3>{{ gameData.awayTeam.city }}</h3> -->
<p>{{ gameData.awayTeam.name }}</p> <p>{{ gameData.awayTeam.name }}</p>
<span>{{ gameData.awayTeam.record }}</span> <span>{{ gameData.awayTeam.record }}</span>
</div> </div>
@@ -14,12 +14,13 @@
<div class="vs-circle">VS</div> <div class="vs-circle">VS</div>
<div class="team-info home-team"> <div class="team-info home-team">
<img :src="gameData.homeTeam.logo" :alt="gameData.homeTeam.name" />
<div class="team-details"> <div class="team-details">
<h3>{{ gameData.homeTeam.city }}</h3> <!-- <h3>{{ gameData.homeTeam.city }}</h3> -->
<p>{{ gameData.homeTeam.name }}</p> <p>{{ gameData.homeTeam.name }}</p>
<span>{{ gameData.homeTeam.record }}</span> <span>{{ gameData.homeTeam.record }}</span>
</div> </div>
<img :src="gameData.homeTeam.logo" :alt="gameData.homeTeam.name" />
</div> </div>
</div> </div>
@@ -42,115 +43,169 @@
</div> </div>
<!-- 返回按钮 --> <!-- 返回按钮 -->
<button class="back-button" @click="goBack"> <button class="back-button" @click="goBack"> 返回赛程</button>
返回赛程
</button>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, onBeforeUnmount, computed } from 'vue' import { ref, onMounted, onBeforeUnmount, computed } from "vue";
import { useRouter } from 'vue-router' import { useRouter } from "vue-router";
import { useGameStore } from '@/stores/game' import { useGameStore } from "@/stores/game";
import DPlayer from 'dplayer' import DPlayer from "dplayer";
import Hls from 'hls.js' import Hls from "hls.js";
import Flv from 'flv.js' import Flv from "flv.js";
// 注册全局变量 // 注册全局变量
window.flvjs = Flv window.flvjs = Flv;
window.Hls = Hls window.Hls = Hls;
const router = useRouter() const router = useRouter();
const gameStore = useGameStore() const gameStore = useGameStore();
const dpInstance = ref(null) const dpInstance = ref(null);
// 从store获取数据 // 从store获取数据
const gameData = computed(() => gameStore.currentGame) const gameData = computed(() => gameStore.currentGame);
const allStreams = computed(() => gameStore.allStreams) const allStreams = computed(() => gameStore.allStreams);
const currentStream = computed({ const currentStream = computed({
get: () => gameStore.currentStream, get: () => gameStore.currentStream,
set: (val) => gameStore.currentStream = val set: (val) => (gameStore.currentStream = val),
}) });
// 初始化播放器 // 初始化播放器
// const initPlayer = () => {
// if (dpInstance.value) {
// dpInstance.value.destroy();
// }
// dpInstance.value = new DPlayer({
// container: document.getElementById('dplayer-live'),
// live: true,
// autoplay: true,
// video: {
// url: currentStream.value?.url || '',
// type: 'auto'
// }
// });
// // 强制设置视频尺寸
// setTimeout(() => {
// const container = document.getElementById('dplayer-live');
// const video = container?.querySelector('video');
// if (video) {
// video.style.cssText = `
// width: 100% !important;
// height: 100% !important;
// object-fit: contain !important;
// position: absolute !important;
// top: 0 !important;
// left: 0 !important;
// `;
// // console.log('视频实际尺寸:', video.videoWidth, 'x', video.videoHeight);
// }
// }, 500);
// };
// 改进的播放器初始化(核心修改点)
// 改进的播放器初始化(核心修改点)
const initPlayer = () => { const initPlayer = () => {
if (!currentStream.value?.url) return;
// 销毁旧实例
if (dpInstance.value) { if (dpInstance.value) {
dpInstance.value.destroy(); dpInstance.value.destroy();
} }
dpInstance.value = new DPlayer({ dpInstance.value = new DPlayer({
container: document.getElementById('dplayer-live'), container: document.getElementById("dplayer-live"),
live: true, live: true,
autoplay: true, autoplay: true,
airplay: true,
video: { video: {
url: currentStream.value?.url || '', url: currentStream.value.url,
type: 'auto' type: "custom", // 修改为custom类型
customType: {
custom: function (video, player) {
const url = video.src;
// 自动检测协议类型
if (url.includes(".m3u8") || url.endsWith("/hls")) {
const hls = new Hls();
hls.loadSource(url);
hls.attachMedia(video);
player.on("destroy", () => hls.destroy());
} else if (url.includes(".flv") || url.endsWith("/flv")) {
const flv = Flv.createPlayer({ type: "flv", url });
flv.attachMediaElement(video);
flv.load();
player.on("destroy", () => flv.destroy());
} else {
// 其他协议回退到DPlayer默认处理
video.src = url;
} }
},
},
},
}); });
// 强制设置视频尺寸 // 保持原有尺寸调整逻辑
setTimeout(() => { setTimeout(() => {
const container = document.getElementById('dplayer-live'); const video = document
const video = container?.querySelector('video'); .getElementById("dplayer-live")
?.querySelector("video");
if (video) { if (video) {
video.style.cssText = ` video.style.cssText = `
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
object-fit: contain !important; object-fit: contain !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
`; `;
// console.log('视频实际尺寸:', video.videoWidth, 'x', video.videoHeight);
} }
}, 500); }, 500);
}; };
// 切换直播源 // 切换直播源
const switchStream = (stream) => { const switchStream = (stream) => {
currentStream.value = stream currentStream.value = stream;
initPlayer() initPlayer();
} };
// 获取直播源名称 // 获取直播源名称
const getStreamName = (type) => { const getStreamName = (type) => {
const names = { const names = {
tx: '企鹅体育', tx: "企鹅体育",
wl: '纬来体育', wl: "纬来体育",
mg: '咪咕体育', mg: "咪咕体育",
nba: '高清原声', nba: "高清原声",
zb: '高清直播' zb: "高清直播",
} };
return names[type] || type return names[type] || type;
} };
// 返回赛程页 // 返回赛程页
const goBack = () => { const goBack = () => {
gameStore.clearGameData() gameStore.clearGameData();
router.go(-1) router.go(-1);
} };
onMounted(() => { onMounted(() => {
// 默认选择第一个直播源 // 默认选择第一个直播源
if (allStreams.value.length > 0 && !currentStream.value) { if (allStreams.value.length > 0 && !currentStream.value) {
currentStream.value = allStreams.value[0] currentStream.value = allStreams.value[0];
} }
initPlayer() initPlayer();
}) });
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (dpInstance.value) { if (dpInstance.value) {
dpInstance.value.destroy() dpInstance.value.destroy();
} }
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.live-stream-container { .live-stream-container {
max-width: 1200px; max-width: 1200px;
margin: 0 auto; margin: 0 auto;
padding: 20px; // padding: 20px;
background: #f5f5f5; background: #f5f5f5;
min-height: 100vh; min-height: 100vh;
} }
@@ -161,6 +216,7 @@ onBeforeUnmount(() => {
align-items: center; align-items: center;
gap: 40px; gap: 40px;
margin-bottom: 20px; margin-bottom: 20px;
margin-top: 20px;
background: white; background: white;
padding: 20px; padding: 20px;
border-radius: 8px; border-radius: 8px;
@@ -203,7 +259,7 @@ onBeforeUnmount(() => {
.vs-circle { .vs-circle {
width: 50px; width: 50px;
height: 50px; height: 50px;
background: #e74c3c; background: #f29155;
color: white; color: white;
border-radius: 50%; border-radius: 50%;
display: flex; display: flex;
@@ -281,8 +337,40 @@ onBeforeUnmount(() => {
@media (max-width: 768px) { @media (max-width: 768px) {
.game-header { .game-header {
flex-direction: column; // flex-direction: column;
gap: 20px; gap: 20px;
.team-info {
display: flex;
align-items: center;
gap: 15px;
img {
width: 60px;
height: 60px;
object-fit: contain;
}
.team-details {
text-align: center;
h3 {
margin: 0;
font-size: 1.2rem;
color: #333;
}
p {
margin: 5px 0;
font-size: 1.1rem;
font-weight: bold;
}
span {
font-size: 0.9rem;
color: #666;
}
}
}
} }
.vs-circle { .vs-circle {

View File

@@ -122,10 +122,11 @@
</div> </div>
<div class="live-buttons"> <div class="live-buttons">
<!-- 只有当比赛未结束且是当天比赛时才显示直播区域 --> <!-- 进行中的比赛 -->
<template v-if="game.status !== 3 && shouldShowLiveArea(game)"> <template v-if="game.status === 2">
<!-- 只对当天比赛显示直播按钮 -->
<template v-if="isTodayGame(game)">
<template v-if="hasLiveStreams(game.gameId)"> <template v-if="hasLiveStreams(game.gameId)">
<!-- 直播按钮 -->
<button <button
v-for="stream in getLiveStreams(game.gameId)" v-for="stream in getLiveStreams(game.gameId)"
:key="stream.type" :key="stream.type"
@@ -138,9 +139,16 @@
</template> </template>
<div v-else class="no-live">无直播信号</div> <div v-else class="no-live">无直播信号</div>
</template> </template>
<!-- 非当天进行中比赛理论上不应该存在 -->
<div v-else class="no-live">比赛进行中</div>
</template>
<!-- 已结束的比赛无论是否当天 -->
<div v-else-if="game.status === 3" class="no-live"> <div v-else-if="game.status === 3" class="no-live">
比赛已结束 比赛已结束
</div> </div>
<!-- 未开始的比赛 -->
<div v-else class="no-live">未开始</div> <div v-else class="no-live">未开始</div>
</div> </div>
@@ -175,38 +183,26 @@ const gameStore = useGameStore();
const router = useRouter(); const router = useRouter();
const urlsData = ref([]); const urlsData = ref([]);
const shouldShowLiveArea = (game) => {
// 1. 已结束的比赛不显示
if (game.status === 3) return false;
// 2. 获取今天的日期(北京时间)
const today = new Date();
const todayStr = `${today.getFullYear()}-${(today.getMonth() + 1)
.toString()
.padStart(2, "0")}-${today.getDate().toString().padStart(2, "0")}`;
// 3. 直接比较 startDate已经是北京时间
return game.startDate === todayStr;
};
onMounted(async () => { onMounted(async () => {
try { try {
const response = await urls(); const response = await urls();
urlsData.value = response || []; urlsData.value = response || [];
// console.log("获取的直播URL数据:", urlsData.value); // 检查数据是否正确
} catch (err) { } catch (err) {
console.error("获取直播URL失败:", err); console.error("获取直播URL失败:", err);
urlsData.value = []; urlsData.value = [];
} }
}); });
// 判断是否为当天进行中的比赛 // 判断是否为当天比赛(无论状态如何)
const isLiveGame = (game) => { const isTodayGame = (game) => {
const isLive = game.status === 2; // 假设2表示进行中 // 获取今天的日期(北京时间)
const gameDate = new Date(game.dateTimeUtc);
const today = new Date(); const today = new Date();
const isToday = gameDate.toDateString() === today.toDateString(); const todayStr = `${today.getFullYear()}-${(today.getMonth() + 1)
return isLive && isToday; .toString()
.padStart(2, "0")}-${today.getDate().toString().padStart(2, "0")}`;
// 直接比较 startDate已经是北京时间
return game.startDate === todayStr;
}; };
// 检查比赛是否有直播流 // 检查比赛是否有直播流
@@ -239,7 +235,6 @@ const getStreamName = (type) => {
nba: "高清原声", nba: "高清原声",
mg: "咪咕体育", mg: "咪咕体育",
zb: "高清直播", zb: "高清直播",
// 可以添加更多类型
}; };
return names[type] || type; return names[type] || type;
}; };
@@ -299,7 +294,6 @@ const props = defineProps({
const emit = defineEmits(["dateChange"]); const emit = defineEmits(["dateChange"]);
// 当前显示日期
// 当前显示日期(带星期几) // 当前显示日期(带星期几)
const currentDisplayDate = computed(() => { const currentDisplayDate = computed(() => {
if (!props.scheduleData?.data?.start) return "加载中..."; if (!props.scheduleData?.data?.start) return "加载中...";
@@ -370,7 +364,7 @@ const isWinner = (game, teamType) => {
if (game.status !== 3) return false; if (game.status !== 3) return false;
// 比较比分 // 比较比分
if (teamType === 'away') { if (teamType === "away") {
return game.awayTeamScore > game.homeTeamScore; return game.awayTeamScore > game.homeTeamScore;
} else { } else {
return game.homeTeamScore > game.awayTeamScore; return game.homeTeamScore > game.awayTeamScore;
@@ -754,11 +748,11 @@ const isWinner = (game, teamType) => {
/* 如果希望更明显的效果,可以调整样式 */ /* 如果希望更明显的效果,可以调整样式 */
.team.winner .team-name { .team.winner .team-name {
font-weight: bold; font-weight: bold;
color: #2E7D32; /* 深绿色文字 */ color: #2e7d32; /* 深绿色文字 */
} }
.team.winner .team-score { .team.winner .team-score {
font-weight: bold; font-weight: bold;
color: #2E7D32; /* 深绿色比分 */ color: #2e7d32; /* 深绿色比分 */
} }
</style> </style>