优化页面、修复BUG
This commit is contained in:
@@ -18,24 +18,68 @@
|
||||
<template v-else-if="video">
|
||||
<h1 class="font-serif text-3xl md:text-4xl text-white mb-6">{{ video.title }}</h1>
|
||||
|
||||
<!-- 有视频地址时挂载 DPlayer 容器 -->
|
||||
<div
|
||||
v-if="video.videoUrl"
|
||||
ref="playerRef"
|
||||
class="w-full aspect-video rounded-xl overflow-hidden bg-black mb-8"
|
||||
class="w-full aspect-video rounded-xl overflow-hidden bg-black mb-6"
|
||||
></div>
|
||||
<!-- 无视频地址时的占位提示 -->
|
||||
<div
|
||||
v-else
|
||||
class="w-full aspect-video rounded-xl overflow-hidden bg-black/40 border border-white/10 flex items-center justify-center mb-8"
|
||||
class="w-full aspect-video rounded-xl overflow-hidden bg-black/40 border border-white/10 flex items-center justify-center mb-6"
|
||||
>
|
||||
<p class="text-art-muted text-sm">暂无视频地址</p>
|
||||
</div>
|
||||
|
||||
<!-- 专辑内前后导航:前 2 + 后 2 -->
|
||||
<div v-if="video.albumContext" class="mb-8">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<p class="text-sm text-art-muted">
|
||||
来自专辑 <span class="text-white">{{ video.albumContext.albumName }}</span>
|
||||
</p>
|
||||
<router-link
|
||||
:to="`/videos/albums/${video.albumContext.albumId}`"
|
||||
class="text-xs text-art-accent hover:underline"
|
||||
>返回专辑</router-link>
|
||||
</div>
|
||||
<div class="flex gap-3 overflow-x-auto pb-2">
|
||||
<!-- 前序视频 -->
|
||||
<div
|
||||
v-for="pv in video.albumContext.prevVideos"
|
||||
:key="'prev-' + pv.id"
|
||||
class="shrink-0 w-36 cursor-pointer group"
|
||||
@click="router.push(`/videos/${pv.id}`)"
|
||||
>
|
||||
<div class="aspect-video rounded-lg overflow-hidden border border-white/10 group-hover:border-art-accent/50 transition-colors bg-black/40">
|
||||
<img v-if="pv.cover" :src="pv.cover" class="w-full h-full object-cover opacity-80 group-hover:opacity-100" alt="" />
|
||||
</div>
|
||||
<p class="text-xs text-art-muted mt-1 line-clamp-2 group-hover:text-white">{{ pv.title }}</p>
|
||||
</div>
|
||||
<!-- 当前视频高亮 -->
|
||||
<div class="shrink-0 w-36">
|
||||
<div class="aspect-video rounded-lg overflow-hidden border-2 border-art-accent bg-black/40">
|
||||
<img v-if="video.cover" :src="video.cover" class="w-full h-full object-cover" alt="" />
|
||||
</div>
|
||||
<p class="text-xs text-art-accent mt-1 line-clamp-2 font-medium">正在播放</p>
|
||||
</div>
|
||||
<!-- 后续视频 -->
|
||||
<div
|
||||
v-for="nv in video.albumContext.nextVideos"
|
||||
:key="'next-' + nv.id"
|
||||
class="shrink-0 w-36 cursor-pointer group"
|
||||
@click="router.push(`/videos/${nv.id}`)"
|
||||
>
|
||||
<div class="aspect-video rounded-lg overflow-hidden border border-white/10 group-hover:border-art-accent/50 transition-colors bg-black/40">
|
||||
<img v-if="nv.cover" :src="nv.cover" class="w-full h-full object-cover opacity-80 group-hover:opacity-100" alt="" />
|
||||
</div>
|
||||
<p class="text-xs text-art-muted mt-1 line-clamp-2 group-hover:text-white">{{ nv.title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-3xl">
|
||||
<div class="flex gap-4 text-sm text-art-muted mb-4">
|
||||
<span v-if="video.categoryName">{{ video.categoryName }}</span>
|
||||
<span>{{ video.createdAt }}</span>
|
||||
<span v-if="video.createdAt">发布于 {{ video.createdAt }}</span>
|
||||
</div>
|
||||
<p v-if="video.description" class="text-white/80 leading-relaxed whitespace-pre-wrap">{{ video.description }}</p>
|
||||
</div>
|
||||
@@ -46,25 +90,26 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import DPlayer from 'dplayer'
|
||||
import 'dplayer/dist/DPlayer.min.css'
|
||||
import { fetchVideo, type VideoItem } from '../services/api'
|
||||
import { fetchVideo, type VideoDetailItem } from '../services/api'
|
||||
import Icon from '../components/Icon.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
const video = ref<VideoItem | null>(null)
|
||||
const video = ref<VideoDetailItem | null>(null)
|
||||
const playerRef = ref<HTMLElement | null>(null)
|
||||
let dp: DPlayer | null = null
|
||||
|
||||
/** 销毁 DPlayer 实例,避免内存泄漏 */
|
||||
/** 销毁 DPlayer 实例 */
|
||||
const destroyPlayer = () => {
|
||||
if (dp) { dp.destroy(); dp = null }
|
||||
}
|
||||
|
||||
/** 在容器与视频 URL 就绪后创建 DPlayer */
|
||||
/** 创建 DPlayer 播放器 */
|
||||
const initPlayer = async () => {
|
||||
destroyPlayer()
|
||||
if (!playerRef.value || !video.value?.videoUrl) return
|
||||
@@ -77,7 +122,7 @@ const initPlayer = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
/** 加载视频详情数据 */
|
||||
/** 加载视频详情 */
|
||||
const load = async () => {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
@@ -92,7 +137,6 @@ const load = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 监听 video、容器 DOM、loading 状态,在 DOM 挂载后再初始化播放器
|
||||
watch([video, playerRef, loading], async ([v, el, isLoading]) => {
|
||||
if (isLoading || !v?.videoUrl || !el) return
|
||||
await nextTick()
|
||||
|
||||
Reference in New Issue
Block a user