343 lines
11 KiB
JavaScript
343 lines
11 KiB
JavaScript
// 全局变量
|
|
let videos = [];
|
|
let currentCategory = '全部';
|
|
|
|
// DOM 元素
|
|
const searchInput = document.querySelector('.search-input');
|
|
const searchBtn = document.querySelector('.search-btn');
|
|
const searchResults = document.querySelector('.search-results');
|
|
const searchResultsContent = document.querySelector('.search-results-content');
|
|
const videoGrid = document.querySelector('.video-grid');
|
|
const shortsGrid = document.querySelector('.shorts-grid');
|
|
const categoryBtns = document.querySelectorAll('.category-btn');
|
|
const subscriptionsList = document.querySelector('.subscriptions-list');
|
|
|
|
// 初始化
|
|
async function init() {
|
|
// 加载视频数据
|
|
await loadVideos();
|
|
|
|
// 渲染视频
|
|
renderVideos();
|
|
|
|
// 渲染 Shorts
|
|
renderShorts();
|
|
|
|
// 渲染订阅内容
|
|
renderSubscriptions();
|
|
|
|
// 绑定事件
|
|
bindEvents();
|
|
}
|
|
|
|
// 加载视频数据
|
|
async function loadVideos() {
|
|
try {
|
|
const response = await fetch('src/media.json');
|
|
videos = await response.json();
|
|
} catch (error) {
|
|
console.error('加载视频数据失败:', error);
|
|
// 使用默认数据
|
|
videos = [];
|
|
}
|
|
}
|
|
|
|
// 渲染视频
|
|
function renderVideos() {
|
|
const filteredVideos = filterVideosByCategory(currentCategory);
|
|
|
|
videoGrid.innerHTML = '';
|
|
|
|
filteredVideos.forEach(video => {
|
|
if (video.type === 'video') {
|
|
const videoCard = createVideoCard(video);
|
|
videoGrid.appendChild(videoCard);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 渲染 Shorts
|
|
function renderShorts() {
|
|
const filteredVideos = filterVideosByCategory(currentCategory);
|
|
|
|
shortsGrid.innerHTML = '';
|
|
|
|
filteredVideos.forEach(video => {
|
|
if (video.type === 'short') {
|
|
const shortsCard = createShortsCard(video);
|
|
shortsGrid.appendChild(shortsCard);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 根据分类过滤视频
|
|
function filterVideosByCategory(category) {
|
|
if (category === '全部') {
|
|
return videos;
|
|
}
|
|
|
|
// 简单的分类映射
|
|
const categoryMap = {
|
|
'音乐': ['音乐'],
|
|
'游戏': ['游戏'],
|
|
'直播': ['直播'],
|
|
'合辑': ['合辑'],
|
|
'动画': ['动画'],
|
|
'手工艺品': ['手工艺品'],
|
|
'最近上传': videos.filter(v => v.uploadDate.includes('天前')),
|
|
'已观看': [],
|
|
'发现新视频': videos
|
|
};
|
|
|
|
if (categoryMap[category]) {
|
|
if (Array.isArray(categoryMap[category]) && categoryMap[category].length > 0 && typeof categoryMap[category][0] === 'string') {
|
|
return videos.filter(v => categoryMap[category].includes(v.category));
|
|
} else if (Array.isArray(categoryMap[category])) {
|
|
return categoryMap[category];
|
|
}
|
|
}
|
|
|
|
return videos;
|
|
}
|
|
|
|
// 创建视频卡片
|
|
function createVideoCard(video) {
|
|
const card = document.createElement('div');
|
|
card.className = 'video-card';
|
|
|
|
card.innerHTML = `
|
|
<div class="video-thumbnail">
|
|
<img src="${video.thumbnail}" alt="${video.title}">
|
|
<span class="video-duration">${video.duration}</span>
|
|
</div>
|
|
<div class="video-info">
|
|
<div class="video-channel-avatar">
|
|
<i class="fas fa-user"></i>
|
|
</div>
|
|
<div class="video-details">
|
|
<h3 class="video-title">${video.title}</h3>
|
|
<div class="video-meta">
|
|
<div class="video-channel">${video.channel}</div>
|
|
<div class="video-stats">
|
|
<span>${video.views} 次观看</span>
|
|
<span>${video.uploadDate}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="video-menu">
|
|
<button class="menu-toggle">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</button>
|
|
<div class="menu-dropdown">
|
|
<div class="menu-item">
|
|
<i class="fas fa-plus"></i>
|
|
<span>添加到待播列表</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-clock"></i>
|
|
<span>保存到"稍后再看"</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-list"></i>
|
|
<span>保存到播放列表</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-download"></i>
|
|
<span>下载</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-share"></i>
|
|
<span>分享</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-thumbs-down"></i>
|
|
<span>不感兴趣</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-ban"></i>
|
|
<span>不推荐此频道</span>
|
|
</div>
|
|
<div class="menu-item">
|
|
<i class="fas fa-flag"></i>
|
|
<span>举报</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// 绑定菜单事件
|
|
const menuToggle = card.querySelector('.menu-toggle');
|
|
const menuDropdown = card.querySelector('.menu-dropdown');
|
|
|
|
menuToggle.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
menuDropdown.classList.toggle('show');
|
|
});
|
|
|
|
// 点击其他地方关闭菜单
|
|
document.addEventListener('click', () => {
|
|
menuDropdown.classList.remove('show');
|
|
});
|
|
|
|
return card;
|
|
}
|
|
|
|
// 创建 Shorts 卡片
|
|
function createShortsCard(video) {
|
|
const card = document.createElement('div');
|
|
card.className = 'shorts-card';
|
|
|
|
card.innerHTML = `
|
|
<div class="shorts-thumbnail">
|
|
<img src="${video.thumbnail}" alt="${video.title}">
|
|
</div>
|
|
<div class="shorts-info">
|
|
<h3 class="shorts-title">${video.title}</h3>
|
|
<div class="shorts-stats">
|
|
<span><i class="fas fa-eye"></i>${video.views}</span>
|
|
<span><i class="fas fa-clock"></i>${video.uploadDate}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
return card;
|
|
}
|
|
|
|
// 渲染订阅内容
|
|
function renderSubscriptions() {
|
|
const subscriptions = [
|
|
{ name: '编程大师', avatar: 'https://picsum.photos/id/100/48/48' },
|
|
{ name: '前端开发', avatar: 'https://picsum.photos/id/101/48/48' },
|
|
{ name: '数据科学', avatar: 'https://picsum.photos/id/102/48/48' },
|
|
{ name: 'AI 研究', avatar: 'https://picsum.photos/id/103/48/48' },
|
|
{ name: '设计达人', avatar: 'https://picsum.photos/id/104/48/48' }
|
|
];
|
|
|
|
subscriptionsList.innerHTML = '';
|
|
|
|
subscriptions.forEach(sub => {
|
|
const item = document.createElement('div');
|
|
item.className = 'subscription-item';
|
|
|
|
item.innerHTML = `
|
|
<div class="subscription-avatar">
|
|
<img src="${sub.avatar}" alt="${sub.name}">
|
|
</div>
|
|
<div class="subscription-name">${sub.name}</div>
|
|
`;
|
|
|
|
subscriptionsList.appendChild(item);
|
|
});
|
|
}
|
|
|
|
// 执行搜索
|
|
function performSearch(query) {
|
|
if (!query.trim()) {
|
|
searchResults.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
const results = videos.filter(video =>
|
|
video.title.toLowerCase().includes(query.toLowerCase()) ||
|
|
video.channel.toLowerCase().includes(query.toLowerCase())
|
|
);
|
|
|
|
renderSearchResults(results, query);
|
|
}
|
|
|
|
// 渲染搜索结果
|
|
function renderSearchResults(results, query) {
|
|
searchResultsContent.innerHTML = '';
|
|
|
|
if (results.length === 0) {
|
|
searchResultsContent.innerHTML = '<p>没有找到相关视频</p>';
|
|
searchResults.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
results.forEach(video => {
|
|
const item = document.createElement('div');
|
|
item.className = 'search-result-item';
|
|
|
|
// 高亮关键词
|
|
const highlightedTitle = video.title.replace(new RegExp(`(${query})`, 'gi'), '<span class="highlight">$1</span>');
|
|
const highlightedChannel = video.channel.replace(new RegExp(`(${query})`, 'gi'), '<span class="highlight">$1</span>');
|
|
|
|
item.innerHTML = `
|
|
<div class="search-result-thumbnail">
|
|
<img src="${video.thumbnail}" alt="${video.title}">
|
|
</div>
|
|
<div class="search-result-details">
|
|
<h4 class="search-result-title">${highlightedTitle}</h4>
|
|
<div class="search-result-channel">${highlightedChannel}</div>
|
|
<div class="search-result-stats">${video.views} 次观看 · ${video.uploadDate}</div>
|
|
</div>
|
|
`;
|
|
|
|
searchResultsContent.appendChild(item);
|
|
});
|
|
|
|
searchResults.style.display = 'block';
|
|
}
|
|
|
|
// 绑定事件
|
|
function bindEvents() {
|
|
// 搜索事件
|
|
searchInput.addEventListener('input', (e) => {
|
|
performSearch(e.target.value);
|
|
});
|
|
|
|
searchBtn.addEventListener('click', () => {
|
|
performSearch(searchInput.value);
|
|
});
|
|
|
|
// 点击其他地方关闭搜索结果
|
|
document.addEventListener('click', (e) => {
|
|
if (!e.target.closest('.search-container') && !e.target.closest('.search-results')) {
|
|
searchResults.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// 分类按钮事件
|
|
categoryBtns.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
// 移除所有活动状态
|
|
categoryBtns.forEach(b => b.classList.remove('active'));
|
|
// 添加当前活动状态
|
|
btn.classList.add('active');
|
|
// 更新当前分类
|
|
currentCategory = btn.textContent;
|
|
// 重新渲染视频
|
|
renderVideos();
|
|
renderShorts();
|
|
});
|
|
});
|
|
|
|
// 侧边栏导航按钮事件
|
|
const navBtns = document.querySelectorAll('.nav-btn');
|
|
navBtns.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
navBtns.forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
});
|
|
});
|
|
|
|
// 订阅板块展开/收起
|
|
const subscriptionTitle = document.querySelector('.nav-section-title');
|
|
subscriptionTitle.addEventListener('click', () => {
|
|
const subscriptionsList = document.querySelector('.subscriptions-list');
|
|
const chevron = subscriptionTitle.querySelector('i');
|
|
|
|
if (subscriptionsList.style.display === 'none') {
|
|
subscriptionsList.style.display = 'block';
|
|
chevron.style.transform = 'rotate(0deg)';
|
|
} else {
|
|
subscriptionsList.style.display = 'none';
|
|
chevron.style.transform = 'rotate(-90deg)';
|
|
}
|
|
});
|
|
}
|
|
|
|
// 页面加载完成后初始化
|
|
window.addEventListener('DOMContentLoaded', init); |