1019 lines
22 KiB
Vue
1019 lines
22 KiB
Vue
<template>
|
||
<div class="resources-page">
|
||
<!-- 横幅图区域 -->
|
||
<div class="banner-section">
|
||
<div class="banner-container">
|
||
<img src="/images/Featured_resources/精选资源轮播.png" alt="精选资源横幅" class="banner-image" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主要内容区域 -->
|
||
<div class="main-content">
|
||
<div class="container">
|
||
<!-- 精选视频区域 -->
|
||
<section class="featured-videos">
|
||
<h2 class="section-title">精选视频</h2>
|
||
|
||
<!-- 加载状态 -->
|
||
<div v-if="loading" class="loading-container">
|
||
<div class="loading-spinner"></div>
|
||
<p>正在加载精选资源...</p>
|
||
</div>
|
||
|
||
<!-- 错误状态 -->
|
||
<div v-else-if="error" class="error-container">
|
||
<p class="error-message">{{ error }}</p>
|
||
<button @click="fetchFeaturedResources" class="retry-button">重试</button>
|
||
</div>
|
||
|
||
<!-- 精选视频网格 -->
|
||
<div v-else class="featured-grid">
|
||
<div v-for="video in featuredVideos" :key="video.id" class="featured-card" @click="handleVideoClick(video)">
|
||
<div class="card-image">
|
||
<img
|
||
:src="video.thumbnailUrl || video.image"
|
||
:alt="video.name || video.title"
|
||
class="video-thumbnail"
|
||
/>
|
||
<div v-if="video.type === 0 && video.duration" class="duration-badge">
|
||
<img src="/images/Featured_resources/duration.png" alt="时长" class="duration-icon">
|
||
{{ formatDuration(video.duration) }}
|
||
</div>
|
||
<div v-if="video.type === 0" class="play-button">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||
<path d="M8 5V19L19 12L8 5Z" fill="white" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<h3 class="card-title">{{ video.name || video.title }}</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 全部视频区域 -->
|
||
<section class="all-videos">
|
||
<h2 class="section-title">全部视频</h2>
|
||
<!-- 筛选标签 -->
|
||
<div class="filter-tabs">
|
||
<button v-for="tab in videoTabs" :key="tab.id"
|
||
:class="['filter-tab', { active: activeVideoTab === tab.id }]" @click="activeVideoTab = tab.id">
|
||
{{ tab.name }}
|
||
</button>
|
||
</div>
|
||
<!-- 视频网格 -->
|
||
<div class="video-grid">
|
||
<div v-for="video in allVideos" :key="video.id" class="video-card" @click="handleVideoClick(video)">
|
||
<div class="card-image">
|
||
<img :src="video.image" :alt="video.title" class="video-thumbnail" />
|
||
<div class="duration-badge">
|
||
<img src="/images/Featured_resources/duration.png" alt="时长" class="duration-icon">
|
||
42:52
|
||
</div>
|
||
<div class="play-button">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||
<path d="M8 5V19L19 12L8 5Z" fill="white" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<h3 class="card-title">{{ video.title }}</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="load-more">
|
||
<button class="load-more-btn">查看更多</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 全部图片区域 -->
|
||
<section class="all-images">
|
||
<h2 class="section-title">全部图片</h2>
|
||
<!-- 筛选标签 -->
|
||
<div class="filter-tabs">
|
||
<button v-for="tab in imageTabs" :key="tab.id"
|
||
:class="['filter-tab', { active: activeImageTab === tab.id }]" @click="activeImageTab = tab.id">
|
||
{{ tab.name }}
|
||
</button>
|
||
</div>
|
||
<!-- 图片网格 -->
|
||
<div class="image-grid">
|
||
<div v-for="image in allImages" :key="image.id" class="image-card">
|
||
<div class="card-image">
|
||
<img :src="image.image" :alt="image.title" class="image-thumbnail" />
|
||
</div>
|
||
<div class="card-content">
|
||
<h3 class="card-title">{{ image.title }}</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="load-more">
|
||
<button class="load-more-btn">查看更多</button>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 视频播放弹窗 -->
|
||
<div v-if="showVideoModal" class="video-modal-overlay" @click="closeVideoModal">
|
||
<div class="video-modal" @click.stop>
|
||
<div class="video-modal-header">
|
||
<h3 class="video-modal-title">{{ currentVideo?.name || currentVideo?.title || '视频播放' }}</h3>
|
||
<button class="close-btn" @click="closeVideoModal">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="video-modal-body">
|
||
<DPlayerVideo ref="videoPlayerRef" :video-url="currentVideoUrl" :placeholder-image="currentVideo?.thumbnailUrl || currentVideo?.image"
|
||
:placeholder-text="'点击播放视频'" :title="currentVideo?.name || currentVideo?.title || '视频播放'" @play="handleVideoPlay"
|
||
@pause="handleVideoPause" @ended="handleVideoEnded" @error="handleVideoError" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, nextTick, onMounted } from 'vue'
|
||
import DPlayerVideo from '@/components/course/DPlayerVideo.vue'
|
||
import { ResourceApi, type FeaturedResource } from '@/api/modules/resource'
|
||
|
||
// 视频播放弹窗相关状态
|
||
const showVideoModal = ref(false)
|
||
const currentVideo = ref<any>(null)
|
||
const currentVideoUrl = ref('')
|
||
const videoPlayerRef = ref<InstanceType<typeof DPlayerVideo>>()
|
||
|
||
// 视频源配置
|
||
const VIDEO_CONFIG = {
|
||
// 本地视频(当前使用)
|
||
LOCAL: '/video/first.mp4',
|
||
// HLS流(服务器准备好后使用)
|
||
HLS: 'http://110.42.96.65:55513/learn/index.m3u8'
|
||
}
|
||
|
||
// 精选视频数据
|
||
const featuredVideos = ref<FeaturedResource[]>([])
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
|
||
// 视频筛选标签
|
||
const videoTabs = ref([
|
||
{ id: 'all', name: '全部' },
|
||
{ id: 'educational', name: '中小学教育资源' },
|
||
{ id: 'training', name: '师资培训' },
|
||
{ id: 'technology', name: '技术资源' },
|
||
{ id: 'management', name: '管理资源' }
|
||
])
|
||
|
||
const activeVideoTab = ref('all')
|
||
|
||
// 全部视频数据
|
||
const allVideos = ref([
|
||
{
|
||
id: 1,
|
||
title: '北京工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频1.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 2,
|
||
title: '北京工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频2.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 3,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频3.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 4,
|
||
title: '北京工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频4.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 5,
|
||
title: '中国工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频5.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 6,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频6.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 7,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频7.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
},
|
||
{
|
||
id: 8,
|
||
title: '内蒙古工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部视频8.png',
|
||
videoUrl: VIDEO_CONFIG.LOCAL
|
||
}
|
||
])
|
||
|
||
// 图片筛选标签
|
||
const imageTabs = ref([
|
||
{ id: 'all', name: '全部' },
|
||
{ id: 'educational', name: '中小学教育资源' },
|
||
{ id: 'training', name: '师资培训' },
|
||
{ id: 'technology', name: '技术资源' },
|
||
{ id: 'management', name: '管理资源' }
|
||
])
|
||
|
||
const activeImageTab = ref('all')
|
||
|
||
// 全部图片数据
|
||
const allImages = ref([
|
||
{
|
||
id: 1,
|
||
title: '中国工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片1.png'
|
||
},
|
||
{
|
||
id: 2,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片2.png'
|
||
},
|
||
{
|
||
id: 3,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片3.png'
|
||
},
|
||
{
|
||
id: 4,
|
||
title: '内蒙古工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片4.png'
|
||
},
|
||
{
|
||
id: 5,
|
||
title: '北京工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片5.png'
|
||
},
|
||
{
|
||
id: 6,
|
||
title: '北京工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片6.png'
|
||
},
|
||
{
|
||
id: 7,
|
||
title: '西安工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片7.png'
|
||
},
|
||
{
|
||
id: 8,
|
||
title: '内蒙古工业大学内部资源之一',
|
||
image: '/images/Featured_resources/全部图片8.png'
|
||
}
|
||
])
|
||
|
||
// 获取精选资源数据
|
||
const fetchFeaturedResources = async () => {
|
||
try {
|
||
loading.value = true
|
||
error.value = ''
|
||
|
||
const response = await ResourceApi.getFeaturedResources()
|
||
if (response.code === 200 && response.data?.result) {
|
||
featuredVideos.value = response.data.result
|
||
console.log('✅ 精选资源加载成功:', featuredVideos.value)
|
||
} else {
|
||
throw new Error(response.message || '获取精选资源失败')
|
||
}
|
||
} catch (err: any) {
|
||
error.value = err.message || '获取精选资源失败'
|
||
console.error('❌ 获取精选资源失败:', err)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 格式化时长显示
|
||
const formatDuration = (seconds: number): string => {
|
||
const hours = Math.floor(seconds / 3600)
|
||
const minutes = Math.floor((seconds % 3600) / 60)
|
||
const secs = seconds % 60
|
||
|
||
if (hours > 0) {
|
||
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||
} else {
|
||
return `${minutes}:${secs.toString().padStart(2, '0')}`
|
||
}
|
||
}
|
||
|
||
// 解析视频URL(支持多清晰度)
|
||
const parseVideoUrls = (fileUrl: string): string[] => {
|
||
if (!fileUrl) return []
|
||
return fileUrl.split(',').map(url => url.trim()).filter(url => url)
|
||
}
|
||
|
||
// 获取最佳视频URL
|
||
const getBestVideoUrl = (fileUrl: string): string => {
|
||
console.log('🔍 解析视频URL:', fileUrl)
|
||
const urls = parseVideoUrls(fileUrl)
|
||
console.log('🔍 解析后的URL数组:', urls)
|
||
|
||
if (urls.length === 0) {
|
||
console.warn('⚠️ 没有有效的视频URL,使用本地视频作为备用')
|
||
return VIDEO_CONFIG.LOCAL
|
||
}
|
||
|
||
// 优先选择720p,如果没有则选择第一个
|
||
const preferredUrl = urls.find(url => url.includes('720p')) || urls[0]
|
||
console.log('✅ 选择的视频URL:', preferredUrl)
|
||
return preferredUrl
|
||
}
|
||
|
||
// 视频播放相关方法
|
||
const handleVideoClick = async (video: FeaturedResource) => {
|
||
// 只有视频类型才能播放
|
||
if (video.type !== 0) {
|
||
console.log('这是图片资源,不能播放')
|
||
return
|
||
}
|
||
|
||
console.log('🎬 点击视频:', video.name)
|
||
console.log('🔍 视频数据:', {
|
||
id: video.id,
|
||
name: video.name,
|
||
type: video.type,
|
||
fileUrl: video.fileUrl,
|
||
thumbnailUrl: video.thumbnailUrl
|
||
})
|
||
|
||
currentVideo.value = video
|
||
|
||
// 获取最佳视频URL
|
||
const videoUrl = getBestVideoUrl(video.fileUrl)
|
||
currentVideoUrl.value = videoUrl
|
||
|
||
console.log('🎯 最终使用的视频URL:', currentVideoUrl.value)
|
||
|
||
showVideoModal.value = true
|
||
|
||
// 等待弹窗显示后初始化播放器
|
||
await nextTick()
|
||
if (videoPlayerRef.value) {
|
||
console.log('🔧 初始化播放器,URL:', currentVideoUrl.value)
|
||
await videoPlayerRef.value.initializePlayer(currentVideoUrl.value)
|
||
}
|
||
}
|
||
|
||
const closeVideoModal = () => {
|
||
showVideoModal.value = false
|
||
currentVideo.value = null
|
||
currentVideoUrl.value = ''
|
||
|
||
// 销毁播放器实例
|
||
if (videoPlayerRef.value) {
|
||
videoPlayerRef.value.destroy()
|
||
}
|
||
}
|
||
|
||
// 图片加载处理
|
||
const handleImageError = (event: Event) => {
|
||
const img = event.target as HTMLImageElement
|
||
console.error('❌ 图片加载失败:', img.src)
|
||
// 设置默认图片
|
||
img.src = '/images/Featured_resources/default-thumbnail.png'
|
||
}
|
||
|
||
const handleImageLoad = (event: Event) => {
|
||
const img = event.target as HTMLImageElement
|
||
console.log('✅ 图片加载成功:', img.src)
|
||
}
|
||
|
||
// 页面初始化
|
||
onMounted(() => {
|
||
fetchFeaturedResources()
|
||
})
|
||
|
||
// DPlayer 事件处理方法
|
||
const handleVideoPlay = () => {
|
||
console.log('视频开始播放')
|
||
}
|
||
|
||
const handleVideoPause = () => {
|
||
console.log('视频暂停')
|
||
}
|
||
|
||
const handleVideoEnded = () => {
|
||
console.log('视频播放结束')
|
||
}
|
||
|
||
const handleVideoError = (error: any) => {
|
||
console.error('视频播放错误:', error)
|
||
// 可以在这里处理错误,比如自动切换到本地视频
|
||
if (currentVideoUrl.value !== VIDEO_CONFIG.LOCAL) {
|
||
currentVideoUrl.value = VIDEO_CONFIG.LOCAL
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.resources-page {
|
||
min-height: 100vh;
|
||
background: #F5F8FB;
|
||
}
|
||
|
||
/* 横幅图区域 */
|
||
.banner-section {
|
||
position: relative;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.banner-container {
|
||
position: relative;
|
||
height: auto;
|
||
}
|
||
|
||
.banner-image {
|
||
width: 100%;
|
||
height: auto;
|
||
display: block;
|
||
object-fit: cover;
|
||
}
|
||
|
||
/* 主要内容区域 */
|
||
.main-content {
|
||
padding: 0 0 40px 0;
|
||
}
|
||
|
||
.container {
|
||
margin: 0 auto;
|
||
/* padding: 0 20px; */
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 36px;
|
||
color: #333;
|
||
margin: 0 0 30px 0;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 精选视频区域 */
|
||
.featured-videos {
|
||
margin-bottom: 80px;
|
||
}
|
||
|
||
/* 加载和错误状态 */
|
||
.loading-container,
|
||
.error-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 60px 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.loading-spinner {
|
||
width: 40px;
|
||
height: 40px;
|
||
border: 4px solid #f3f3f3;
|
||
border-top: 4px solid #0088D1;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
.error-message {
|
||
color: #ff4757;
|
||
font-size: 16px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.retry-button {
|
||
background: #0088D1;
|
||
color: white;
|
||
border: none;
|
||
padding: 10px 20px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.retry-button:hover {
|
||
background: #0066A1;
|
||
}
|
||
|
||
.featured-grid {
|
||
margin: 0 auto;
|
||
width: 1420px;
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 24px;
|
||
}
|
||
|
||
.featured-card {
|
||
background: white;
|
||
border-radius: 5px;
|
||
overflow: hidden;
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.featured-card:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.card-image {
|
||
position: relative;
|
||
height: 245px;
|
||
background: #f5f5f5;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.video-thumbnail {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
display: block;
|
||
}
|
||
|
||
.image-thumbnail {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
display: block;
|
||
}
|
||
|
||
.image-placeholder {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(135deg, #e0e0e0 0%, #f0f0f0 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.image-placeholder::after {
|
||
content: '图片占位';
|
||
color: #999;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.play-button {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 48px;
|
||
height: 48px;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
z-index: 1;
|
||
}
|
||
|
||
.duration-badge {
|
||
position: absolute;
|
||
top: 14px;
|
||
left: 14px;
|
||
background: #9CAEB8;
|
||
color: white;
|
||
font-size: 16px;
|
||
padding: 2px 8px;
|
||
border-radius: 6px;
|
||
z-index: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.duration-icon {
|
||
width: 16px;
|
||
height: 16px;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.play-button:hover {
|
||
background: rgba(0, 0, 0, 0.8);
|
||
transform: translate(-50%, -50%) scale(1.1);
|
||
}
|
||
|
||
.card-content {
|
||
padding: 20px 15px;
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin: 0;
|
||
line-height: 1.4;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 筛选标签 */
|
||
.filter-tabs {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin: 0 auto 30px auto;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: fit-content;
|
||
}
|
||
|
||
.filter-tab {
|
||
padding: 8px 16px;
|
||
border: none;
|
||
background: #F2F2F2;
|
||
color: #878787;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
transition: all 0.3s;
|
||
white-space: nowrap;
|
||
font-weight: 400;
|
||
border-radius: 30px;
|
||
}
|
||
|
||
.filter-tab:hover {
|
||
color: #4A90E2;
|
||
}
|
||
|
||
.filter-tab.active {
|
||
background: #EEF9FF;
|
||
color: #0088D1;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 全部视频区域 */
|
||
.all-videos {
|
||
width: 100vw;
|
||
padding: 40px 0;
|
||
background-color: #fff;
|
||
margin-bottom: 80px;
|
||
}
|
||
|
||
.video-grid {
|
||
width: 1420px;
|
||
margin: 0 auto;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 20px;
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.video-card {
|
||
background: white;
|
||
border-radius: 5px;
|
||
overflow: hidden;
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.video-card .card-image {
|
||
height: 245px;
|
||
}
|
||
|
||
.video-card .play-button {
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
|
||
/* 全部图片区域 */
|
||
.all-images {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.image-grid {
|
||
margin: auto;
|
||
width: 1420px;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 20px;
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.image-card {
|
||
background: white;
|
||
border-radius: 5px;
|
||
overflow: hidden;
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.image-card:hover {
|
||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.image-card .card-image {
|
||
height: 240px;
|
||
}
|
||
|
||
/* 查看更多按钮 */
|
||
.load-more {
|
||
text-align: center;
|
||
}
|
||
|
||
.load-more-btn {
|
||
padding: 12px 32px;
|
||
background: none;
|
||
border: none;
|
||
color: #292C2E;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 18px;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.load-more-btn:hover {
|
||
background: #f8f9fa;
|
||
border-color: #4A90E2;
|
||
color: #4A90E2;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 1024px) {
|
||
.container {
|
||
padding: 0 16px;
|
||
}
|
||
|
||
.featured-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 20px;
|
||
}
|
||
|
||
.video-grid,
|
||
.image-grid {
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 16px;
|
||
}
|
||
|
||
.banner-title {
|
||
font-size: 28px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.banner-section {
|
||
height: 300px;
|
||
}
|
||
|
||
.banner-title {
|
||
font-size: 24px;
|
||
}
|
||
|
||
.main-content {
|
||
padding: 40px 0;
|
||
}
|
||
|
||
.featured-grid {
|
||
grid-template-columns: 1fr;
|
||
gap: 16px;
|
||
}
|
||
|
||
.video-grid,
|
||
.image-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 12px;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 20px;
|
||
margin-bottom: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.filter-tabs {
|
||
overflow-x: auto;
|
||
gap: 16px;
|
||
justify-content: flex-start;
|
||
padding: 0 20px;
|
||
}
|
||
|
||
.filter-tab {
|
||
padding: 6px 16px;
|
||
font-size: 13px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.featured-videos,
|
||
.all-videos {
|
||
margin-bottom: 60px;
|
||
}
|
||
|
||
.loading-container,
|
||
.error-container {
|
||
padding: 40px 20px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.banner-image {
|
||
max-height: 250px;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.container {
|
||
padding: 0 12px;
|
||
}
|
||
|
||
.video-grid,
|
||
.image-grid {
|
||
grid-template-columns: 1fr;
|
||
gap: 12px;
|
||
}
|
||
|
||
.card-image {
|
||
height: 160px;
|
||
}
|
||
|
||
.video-card .card-image,
|
||
.image-card .card-image {
|
||
height: 120px;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 18px;
|
||
text-align: center;
|
||
}
|
||
|
||
.filter-tabs {
|
||
margin-bottom: 20px;
|
||
gap: 12px;
|
||
}
|
||
|
||
.filter-tab {
|
||
padding: 6px 12px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
/* 视频播放弹窗样式 */
|
||
.video-modal-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 9999;
|
||
padding: 20px;
|
||
}
|
||
|
||
.video-modal {
|
||
background: white;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
max-width: 90vw;
|
||
max-height: 90vh;
|
||
width: 1000px;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||
animation: modalFadeIn 0.3s ease-out;
|
||
}
|
||
|
||
@keyframes modalFadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: scale(0.9);
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
.video-modal-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20px 24px;
|
||
border-bottom: 1px solid #e5e7eb;
|
||
background: #f9fafb;
|
||
}
|
||
|
||
.video-modal-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin: 0;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.close-btn {
|
||
background: none;
|
||
border: none;
|
||
padding: 8px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
color: #666;
|
||
transition: all 0.2s;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.close-btn:hover {
|
||
background: #e5e7eb;
|
||
color: #333;
|
||
}
|
||
|
||
.video-modal-body {
|
||
padding: 0;
|
||
background: #000;
|
||
position: relative;
|
||
height: 60vh;
|
||
min-height: 400px;
|
||
}
|
||
|
||
/* 播放按钮显示样式 */
|
||
.play-button {
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.featured-card:hover .play-button,
|
||
.video-card:hover .play-button {
|
||
opacity: 1;
|
||
}
|
||
|
||
.featured-card .play-button {
|
||
width: 48px;
|
||
height: 48px;
|
||
}
|
||
|
||
.video-card .play-button {
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
|
||
/* 响应式设计 - 弹窗 */
|
||
@media (max-width: 768px) {
|
||
.video-modal {
|
||
width: 95vw;
|
||
max-width: none;
|
||
}
|
||
|
||
.video-modal-header {
|
||
padding: 16px 20px;
|
||
}
|
||
|
||
.video-modal-title {
|
||
font-size: 16px;
|
||
}
|
||
|
||
.video-modal-body {
|
||
height: 50vh;
|
||
min-height: 300px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.video-modal-overlay {
|
||
padding: 10px;
|
||
}
|
||
|
||
.video-modal {
|
||
width: 100%;
|
||
}
|
||
|
||
.video-modal-header {
|
||
padding: 12px 16px;
|
||
}
|
||
|
||
.video-modal-title {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.video-modal-body {
|
||
height: 40vh;
|
||
min-height: 250px;
|
||
}
|
||
}
|
||
</style>
|