// 全局变量 let allAlbums = []; let searchTimeout = null; let currentPage = 1; let albumsPerPage = 50; // 减少每页数量,提高加载速度 let isLoadingMore = false; let hasMoreAlbums = true; let lazyLoadObserver = null; // API基础URL const API_BASE = '/api'; // 设备检测 const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0; // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', function () { // 添加设备类到body if (isMobile) { document.body.classList.add('mobile-device'); } if (isTouchDevice) { document.body.classList.add('touch-device'); } loadAlbums(); initSearch(); initInfiniteScroll(); }); // 初始化搜索功能 function initSearch() { const searchInput = document.getElementById('search-input'); // 防抖搜索 searchInput.addEventListener('input', function () { clearTimeout(searchTimeout); // 优化:根据输入长度动态调整延迟 const inputLength = this.value.length; const debounceDelay = inputLength > 3 ? 200 : 500; // 长文本快速搜索,短文本慢速搜索 searchTimeout = setTimeout(debouncedSearch, debounceDelay); }); // 移动端优化:搜索框聚焦时自动滚动到可视区域 if (isMobile) { searchInput.addEventListener('focus', function () { setTimeout(() => { searchInput.scrollIntoView({behavior: 'smooth', block: 'center'}); }, 100); }); } } // 初始化无限滚动 function initInfiniteScroll() { let scrollTimeout; window.addEventListener('scroll', function () { clearTimeout(scrollTimeout); scrollTimeout = setTimeout(handleScroll, 100); }); } // 处理滚动事件 function handleScroll() { if (isLoadingMore || !hasMoreAlbums) return; // 检查是否滚动到底部 const scrollTop = window.scrollY || document.documentElement.scrollTop; const scrollHeight = document.documentElement.scrollHeight; const clientHeight = window.innerHeight; // 当距离底部还有200px时开始加载 if (scrollTop + clientHeight >= scrollHeight - 200) { loadMoreAlbums(); } } // 加载更多相册 async function loadMoreAlbums() { if (isLoadingMore || !hasMoreAlbums) return; isLoadingMore = true; try { await loadAlbums(); } catch (error) { console.error('加载更多相册失败:', error); showLoadMoreError(); } finally { isLoadingMore = false; } } // 显示加载更多错误 function showLoadMoreError() { const container = document.getElementById('albums-container'); const errorElement = document.createElement('div'); errorElement.className = 'load-more-error'; errorElement.innerHTML = `
加载失败,点击重试
`; const existingError = container.querySelector('.load-more-error'); if (existingError) { existingError.remove(); } container.appendChild(errorElement); } // 显示骨架屏 function showSkeleton(count = 6) { const container = document.getElementById('albums-container'); container.innerHTML = Array(count).fill(0).map(() => `
`).join(''); } // 显示详细加载状态 function showLoadingState(message = '加载中...', progress = 0) { const container = document.getElementById('albums-container'); const progressWidth = Math.min(Math.max(progress, 0), 100); container.innerHTML = `

${message}

`; } // 显示加载更多指示器 function showLoadingMore() { const container = document.getElementById('albums-container'); const loadingIndicator = document.createElement('div'); loadingIndicator.id = 'loading-more'; loadingIndicator.className = 'loading-more'; loadingIndicator.innerHTML = `
加载更多相册...
`; container.appendChild(loadingIndicator); } // 隐藏加载更多指示器 function hideLoadingMore() { const loadingIndicator = document.getElementById('loading-more'); if (loadingIndicator) { loadingIndicator.remove(); } } // 追加相册到列表 function appendAlbums(albums) { const container = document.getElementById('albums-container'); const newAlbumsHTML = albums.map(album => { // 处理封面图片URL - 使用懒加载 let coverImageUrl = '/assets/placeholder.svg'; let dataSrc = ''; if (album.cover_image_id) { dataSrc = `/api/thumbnail/${album.cover_image_id}`; coverImageUrl = '/assets/placeholder.svg'; // 初始使用占位图 } // 格式化日期 const createdDate = new Date(album.created_at).toLocaleDateString('zh-CN'); return `
${album.title}

${album.title}

${album.image_count} 张图片 ${createdDate}
查看相册
`; }).join(''); // 移除加载指示器并添加新相册 hideLoadingMore(); container.insertAdjacentHTML('beforeend', newAlbumsHTML); } // 加载所有相册 async function loadAlbums(reset = false) { try { if (reset) { currentPage = 1; allAlbums = []; hasMoreAlbums = true; const container = document.getElementById('albums-container'); container.innerHTML = ''; } if (!hasMoreAlbums) return; // 显示骨架屏 if (currentPage === 1) { showSkeleton(); } else { showLoadingMore(); } const response = await fetch(`${API_BASE}/albums`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const newAlbums = await response.json(); // 检查是否还有更多数据 if (newAlbums.length < albumsPerPage) { hasMoreAlbums = false; } // 合并到现有相册列表 allAlbums = [...allAlbums, ...newAlbums]; if (currentPage === 1) { displayAlbums(allAlbums); } else { appendAlbums(newAlbums); } updateStats(allAlbums); // 初始化图片懒加载 initLazyLoading(); // 预加载下一批图片 preloadNextBatchImages(); currentPage++; // 隐藏加载更多指示器 hideLoadingMore(); } catch (error) { console.error('加载相册失败:', error); showError('加载相册数据失败,请刷新页面重试'); hideLoadingMore(); } } // 搜索相册 // 防抖搜索函数 async function debouncedSearch() { const searchTerm = document.getElementById('search-input').value.toLowerCase().trim(); if (searchTerm === '') { // 显示所有已加载的相册 displayAlbums(allAlbums); updateStats(); return; } // 直接使用后端搜索API进行全站搜索 await performServerSearch(searchTerm); } // 在当前已加载的数据集中搜索 function searchInLoadedAlbums(searchTerm) { if (!allAlbums.length) return []; return allAlbums.filter(album => { // 搜索标题和描述 const titleMatch = album.title.toLowerCase().includes(searchTerm); const descriptionMatch = album.description && album.description.toLowerCase().includes(searchTerm); return titleMatch || descriptionMatch; }); } // 显示搜索提示 function showSearchHint(searchTerm) { const container = document.getElementById('albums-container'); container.innerHTML = `

未在当前页面找到 "${searchTerm}"

尝试:

`; document.getElementById('stats').innerHTML = `在当前页面中未找到包含 "${searchTerm}" 的相册`; } // 执行服务器端搜索(全站搜索) async function performServerSearch(searchTerm) { try { // 显示搜索中的骨架屏 showSkeleton(4); const response = await fetch(`${API_BASE}/search?q=${encodeURIComponent(searchTerm)}&page=1&limit=${albumsPerPage}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const serverResults = await response.json(); if (serverResults.length === 0) { showError(`没有找到包含 "${searchTerm}" 的相册`); return; } // 显示服务器搜索结果 displayAlbums(serverResults); document.getElementById('stats').innerHTML = `在全站找到 ${serverResults.length} 个包含 "${searchTerm}" 的相册`; // 初始化图片懒加载 initLazyLoading(); } catch (error) { console.error('全站搜索失败:', error); showError('全站搜索失败,请重试'); } } // 显示相册列表 function displayAlbums(albums) { const container = document.getElementById('albums-container'); if (albums.length === 0) { container.innerHTML = '

没有找到匹配的相册
'; return; } container.innerHTML = albums.map(album => { // 处理封面图片URL - 使用懒加载 let coverImageUrl = '/assets/placeholder.svg'; let dataSrc = ''; if (album.cover_image_id) { dataSrc = `/api/thumbnail/${album.cover_image_id}`; coverImageUrl = '/assets/placeholder.svg'; // 初始使用占位图 } // 格式化日期 const createdDate = new Date(album.created_at).toLocaleDateString('zh-CN'); return `
${album.title}

${album.title}

${album.image_count} 张图片 ${createdDate}
查看相册
`; }).join(''); } // 初始化图片懒加载 function initLazyLoading() { if (!lazyLoadObserver) { lazyLoadObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; if (img.dataset.src) { img.src = img.dataset.src; img.classList.remove('lazy'); lazyLoadObserver.unobserve(img); } } }); }, { rootMargin: '50px', // 优化:提前50px开始加载 threshold: 0.1 // 优化:降低触发阈值 }); } const lazyImages = document.querySelectorAll('img.lazy'); lazyImages.forEach(img => { lazyLoadObserver.observe(img); }); } // 预加载下一批图片 function preloadNextBatchImages() { const imagesToPreload = []; const visibleImages = document.querySelectorAll('img.lazy'); // 预加载前10张可见图片 visibleImages.forEach((img, index) => { if (index < 10 && img.dataset.src) { imagesToPreload.push(img.dataset.src); } }); // 使用link预加载 imagesToPreload.forEach(src => { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'image'; link.href = src; document.head.appendChild(link); }); } // 更新统计信息 function updateStats(albums) { if (!albums) { albums = allAlbums; } const totalImages = albums.reduce((sum, album) => sum + album.image_count, 0); document.getElementById('stats').innerHTML = `共发现 ${albums.length} 个相册,包含 ${totalImages} 张图片`; } // 显示错误信息 function showError(message) { const container = document.getElementById('albums-container'); container.innerHTML = `

${message}
`; document.getElementById('stats').innerHTML = ''; } // 搜索相册函数 async function searchAlbums() { await debouncedSearch(); } // 性能监控 function logPerformance() { if ('performance' in window) { // 使用更可靠的方式获取页面加载时间 const calculateLoadTime = () => { const navigationTiming = performance.getEntriesByType('navigation')[0]; if (navigationTiming && navigationTiming.loadEventEnd > 0 && navigationTiming.navigationStart > 0) { const loadTime = navigationTiming.loadEventEnd - navigationTiming.navigationStart; console.log('页面加载时间:', loadTime, 'ms'); } else { // 备用方案:使用DOMContentLoaded时间 const domContentLoadedTime = performance.timing?.domContentLoadedEventEnd - performance.timing?.navigationStart; if (domContentLoadedTime && domContentLoadedTime > 0) { console.log('DOM加载时间:', domContentLoadedTime, 'ms'); } else { console.log('页面加载时间: 无法计算'); } } }; // 如果页面已经加载完成,直接计算 if (document.readyState === 'complete') { calculateLoadTime(); } else { // 否则等待页面加载完成 window.addEventListener('load', calculateLoadTime); } } } // 移动端优化:防止双击缩放 function preventDoubleTapZoom() { if (isTouchDevice) { let lastTouchEnd = 0; document.addEventListener('touchend', function (event) { const now = (new Date()).getTime(); if (now - lastTouchEnd <= 300) { event.preventDefault(); } lastTouchEnd = now; }, false); } } // 预加载关键资源 function preloadCriticalResources() { // 预加载字体文件(CSS文件不应该预加载,因为已经在HTML中引用了) const fontResources = [ '/assets/webfonts/fa-solid-900.woff2', '/assets/webfonts/fa-brands-400.woff2', '/assets/webfonts/fa-regular-400.woff2' ]; fontResources.forEach(resource => { const link = document.createElement('link'); link.rel = 'preload'; link.href = resource; link.as = 'font'; link.crossOrigin = 'anonymous'; document.head.appendChild(link); }); // 预加载第一屏可能需要的图片 setTimeout(() => { const firstScreenImages = [ '/assets/placeholder.svg' ]; firstScreenImages.forEach(img => { const preload = document.createElement('link'); preload.rel = 'preload'; preload.href = img; preload.as = 'image'; document.head.appendChild(preload); }); }, 100); } // 优化滚动性能 function optimizeScrollPerformance() { // 使用requestAnimationFrame优化滚动 let ticking = false; function updateOnScroll() { // 在滚动时暂停非关键任务 if (!ticking) { requestAnimationFrame(() => { // 延迟加载非关键图片 delayNonCriticalImages(); ticking = false; }); ticking = true; } } window.addEventListener('scroll', updateOnScroll, {passive: true}); } // 延迟加载非关键图片 function delayNonCriticalImages() { const nonCriticalImages = document.querySelectorAll('img[data-delayed]'); nonCriticalImages.forEach(img => { if (isElementInViewport(img)) { const src = img.getAttribute('data-delayed'); if (src) { img.src = src; img.removeAttribute('data-delayed'); } } }); } // 检查元素是否在视口中 function isElementInViewport(el) { const rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } // 初始化性能监控和移动端优化 logPerformance(); preventDoubleTapZoom(); // 预加载关键资源 preloadCriticalResources(); // 优化滚动性能 optimizeScrollPerformance(); // 随机打开相册 function openRandomAlbum() { // 添加随机动画效果 const randomButton = document.querySelector('.random-button'); randomButton.style.transform = 'scale(0.95)'; randomButton.disabled = true; // 显示加载状态 const originalText = randomButton.textContent; randomButton.textContent = '随机加载中...'; // 调用新的随机相册API fetch(`${API_BASE}/album/random`) .then(response => { if (!response.ok) { if (response.status === 404) { throw new Error('暂无相册数据,请稍后再试'); } throw new Error('获取随机相册失败'); } return response.json(); }) .then(randomAlbum => { // 恢复按钮状态 setTimeout(() => { randomButton.style.transform = ''; randomButton.disabled = false; randomButton.textContent = originalText; }, 200); // 跳转到随机相册 window.location.href = `/album?id=${randomAlbum.id}`; }) .catch(error => { // 恢复按钮状态 setTimeout(() => { randomButton.style.transform = ''; randomButton.disabled = false; randomButton.textContent = originalText; }, 200); alert(error.message); }); } // 显示收藏夹 function showFavorites() { // 从后端API获取收藏列表 fetch(`${API_BASE}/favorites`) .then(response => { if (!response.ok) { throw new Error('获取收藏列表失败'); } return response.json(); }) .then(favoriteImages => { if (favoriteImages.length === 0) { alert('收藏夹为空,快去收藏一些喜欢的图片吧!'); return; } // 创建收藏夹页面或跳转到收藏夹视图 displayFavorites(favoriteImages); }) .catch(error => { console.error('获取收藏列表失败:', error); alert('获取收藏列表失败,请稍后重试'); }); } // 显示收藏夹内容 function displayFavorites(favoriteImages) { const container = document.getElementById('albums-container'); container.innerHTML = ` ${favoriteImages.length === 0 ? `

收藏夹空空如也

快去收藏一些喜欢的图片吧!

` : `${favoriteImages.map((fav, index) => `
${fav.image.title || '收藏的图片'}
${formatDate(fav.favorite.created_at)} ${fav.image.width}×${fav.image.height}
`).join('')} `} `; // 更新统计信息 - 显示收藏数量 document.getElementById('stats').innerHTML = `

我的收藏夹

共收藏了 ${favoriteImages.length} 张图片

`; } // 格式化日期 function formatDate(dateString) { const date = new Date(dateString); return date.toLocaleDateString('zh-CN', { year: 'numeric', month: 'short', day: 'numeric' }); } // 全局变量存储收藏列表和当前预览索引 let currentFavorites = []; let currentPreviewIndex = -1; // 预览收藏的图片 function previewFavorite(index) { // 获取收藏列表 fetch(`${API_BASE}/favorites`) .then(response => { if (!response.ok) { throw new Error('获取收藏列表失败'); } return response.json(); }) .then(favorites => { if (favorites && favorites.length > index) { currentFavorites = favorites; currentPreviewIndex = index; showPreviewModal(index); } else { alert('图片不存在或已被删除'); } }) .catch(error => { console.error('预览图片失败:', error); alert('预览图片失败,请稍后重试'); }); } // 显示预览模态框 function showPreviewModal(index) { const favorite = currentFavorites[index]; // 构建模态框HTML const modalHtml = `
来自: ${favorite.album_title}
${index + 1} / ${currentFavorites.length}
${favorite.image.title || '预览图片'}
`; // 添加到页面 document.body.insertAdjacentHTML('beforeend', modalHtml); // 显示模态框 setTimeout(() => { const modal = document.getElementById('previewModal'); modal.classList.add('active'); }, 10); // 监听键盘事件 document.addEventListener('keydown', handlePreviewKeydown); } // 关闭预览模态框 function closePreviewModal() { const modal = document.getElementById('previewModal'); if (modal) { modal.classList.remove('active'); setTimeout(() => { modal.remove(); }, 300); } // 移除键盘事件监听 document.removeEventListener('keydown', handlePreviewKeydown); } // 导航预览图片 function navigatePreview(direction) { const newIndex = currentPreviewIndex + direction; if (newIndex >= 0 && newIndex < currentFavorites.length) { updatePreviewContent(newIndex); } } // 更新预览内容(不关闭面板) function updatePreviewContent(newIndex) { const favorite = currentFavorites[newIndex]; currentPreviewIndex = newIndex; // 更新标题和相册信息 const titleElement = document.querySelector('.preview-title h3'); const infoElement = document.querySelector('.preview-info'); if (titleElement) titleElement.textContent = favorite.image.title || '未命名图片'; if (infoElement) infoElement.textContent = `来自: ${favorite.album_title}`; // 更新计数器 const counterElement = document.querySelector('.preview-counter'); if (counterElement) counterElement.textContent = `${newIndex + 1} / ${currentFavorites.length}`; // 更新导航按钮状态 const prevButton = document.querySelector('.preview-prev'); const nextButton = document.querySelector('.preview-next'); if (prevButton) prevButton.disabled = newIndex === 0; if (nextButton) nextButton.disabled = newIndex === currentFavorites.length - 1; // 更新元数据 const metaElements = document.querySelectorAll('.preview-meta .meta-item'); if (metaElements.length >= 3) { metaElements[0].innerHTML = ` ${formatDate(favorite.favorite.created_at)}`; metaElements[1].innerHTML = ` ${favorite.image.width} × ${favorite.image.height}`; } // 更新操作按钮 const openAlbumButton = document.querySelector('.preview-action:first-child'); const removeButton = document.querySelector('.preview-remove'); if (openAlbumButton) { openAlbumButton.onclick = () => openFavoriteImage(favorite.favorite.album_id); } if (removeButton) { removeButton.onclick = () => removeFavoriteFromPreview(favorite.favorite.id); } // 更新图片 const imageElement = document.getElementById('preview-image'); if (imageElement) { // 显示加载状态 imageElement.style.opacity = '0'; // 加载新图片 const newImage = new Image(); newImage.src = `${API_BASE}/original/${favorite.image.id}`; newImage.alt = favorite.image.title || '预览图片'; newImage.className = 'preview-image'; newImage.onload = function () { // 替换图片 if (imageElement.parentNode) { imageElement.parentNode.replaceChild(newImage, imageElement); // 重新设置ID newImage.id = 'preview-image'; } newImage.style.opacity = '1'; }; newImage.onerror = function () { // 图片加载失败 imageElement.innerHTML = '图片加载失败'; }; } } // 处理键盘事件 function handlePreviewKeydown(event) { if (event.key === 'Escape') { closePreviewModal(); } else if (event.key === 'ArrowLeft') { navigatePreview(-1); } else if (event.key === 'ArrowRight') { navigatePreview(1); } } // 从预览中移除收藏 function removeFavoriteFromPreview(favoriteId) { if (confirm('确定要从收藏夹移除这张图片吗?')) { fetch(`${API_BASE}/favorites/${favoriteId}`, { method: 'DELETE' }) .then(response => { if (!response.ok) { throw new Error('取消收藏失败'); } return response.json(); }) .then(() => { closePreviewModal(); // 重新显示收藏夹 showFavorites(); }) .catch(error => { console.error('取消收藏失败:', error); alert('取消收藏失败,请稍后重试'); }); } } // 从收藏夹移除图片 function removeFavorite(event, favoriteId) { event.stopPropagation(); // 阻止事件冒泡 if (confirm('确定要从收藏夹移除这张图片吗?')) { fetch(`${API_BASE}/favorites/${favoriteId}`, { method: 'DELETE' }) .then(response => { if (!response.ok) { throw new Error('取消收藏失败'); } return response.json(); }) .then(() => { // 重新显示收藏夹 showFavorites(); }) .catch(error => { console.error('取消收藏失败:', error); alert('取消收藏失败,请稍后重试'); }); } } // 打开收藏的图片 function openFavoriteImage(favoriteId) { // 这里可以跳转到对应的相册页面 // 在实际实现中,我们需要根据favoriteId获取相册信息 window.location.href = `/album?id=${favoriteId}`; } // 导出函数供全局使用 window.searchAlbums = searchAlbums; window.openRandomAlbum = openRandomAlbum; window.showFavorites = showFavorites;