Files
rust-imager/assets/js/app.js
2026-03-25 14:06:49 +08:00

1005 lines
34 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 全局变量
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);
searchTimeout = setTimeout(debouncedSearch, 300);
});
// 移动端优化:搜索框聚焦时自动滚动到可视区域
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 = `
<div class="error-content">
<i class="fas fa-exclamation-triangle"></i>
<span>加载失败,<a href="javascript:void(0)" onclick="loadMoreAlbums()">点击重试</a></span>
</div>
`;
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(() => `
<div class="skeleton-card">
<div class="skeleton-cover skeleton"></div>
<div class="skeleton-content">
<div class="skeleton-title skeleton"></div>
<div class="skeleton-meta">
<div class="skeleton-meta-item skeleton"></div>
<div class="skeleton-meta-item skeleton"></div>
</div>
<div class="skeleton-button skeleton"></div>
</div>
</div>
`).join('');
}
// 显示加载更多指示器
function showLoadingMore() {
const container = document.getElementById('albums-container');
const loadingIndicator = document.createElement('div');
loadingIndicator.id = 'loading-more';
loadingIndicator.className = 'loading-more';
loadingIndicator.innerHTML = `
<div class="loading-spinner">
<i class="fas fa-spinner fa-spin"></i>
<span>加载更多相册...</span>
</div>
`;
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 `
<div class="album-card" data-album-id="${album.id}">
<div class="album-cover">
<img
src="${coverImageUrl}"
${dataSrc ? `data-src="${dataSrc}"` : ''}
alt="${album.title}"
class="lazy"
onerror="this.src='/assets/placeholder.svg'"
>
</div>
<div class="album-info">
<h3>${album.title}</h3>
<div class="album-meta">
<span><i class="fas fa-images"></i> ${album.image_count} 张图片</span>
<span><i class="fas fa-calendar"></i> ${createdDate}</span>
</div>
<a href="/album?id=${album.id}" class="view-button">
<i class="fas fa-eye"></i> 查看相册
</a>
</div>
</div>
`;
}).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 = `
<div class="search-hint">
<i class="fas fa-search"></i>
<h3>未在当前页面找到 "${searchTerm}"</h3>
<p>尝试:</p>
<ul>
<li>继续滚动加载更多相册</li>
<li>使用更精确的搜索词</li>
<li><button class="btn-primary" onclick="performServerSearch('${searchTerm}')">在全站搜索 "${searchTerm}"</button></li>
</ul>
</div>
`;
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 = '<div class="no-results"><i class="fas fa-search"></i><br>没有找到匹配的相册</div>';
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 `
<div class="album-card" data-album-id="${album.id}">
<div class="album-cover">
<img
src="${coverImageUrl}"
${dataSrc ? `data-src="${dataSrc}"` : ''}
alt="${album.title}"
class="lazy"
onerror="this.src='/assets/placeholder.svg'"
>
</div>
<div class="album-info">
<h3>${album.title}</h3>
<div class="album-meta">
<span><i class="fas fa-images"></i> ${album.image_count} 张图片</span>
<span><i class="fas fa-calendar"></i> ${createdDate}</span>
</div>
<a href="/album?id=${album.id}" class="view-button">
<i class="fas fa-eye"></i> 查看相册
</a>
</div>
</div>
`;
}).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: '100px 0px', // 提前100px开始加载
threshold: 0.01
});
}
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 = `<div class="no-results"><i class="fas fa-exclamation-triangle"></i><br>${message}</div>`;
document.getElementById('stats').innerHTML = '';
}
// 搜索相册函数
async function searchAlbums() {
await debouncedSearch();
}
// 性能监控
function logPerformance() {
if ('performance' in window) {
window.addEventListener('load', () => {
setTimeout(() => {
const navigationTiming = performance.getEntriesByType('navigation')[0];
if (navigationTiming && navigationTiming.loadEventEnd && navigationTiming.navigationStart) {
const loadTime = navigationTiming.loadEventEnd - navigationTiming.navigationStart;
console.log('页面加载时间:', loadTime, 'ms');
} else {
console.log('页面加载时间: 无法计算');
}
}, 0);
});
}
}
// 移动端优化:防止双击缩放
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和字体
const criticalResources = [
'/assets/css/font-awesome.css',
'/assets/css/style.css',
'/assets/webfonts/fa-solid-900.woff2'
];
criticalResources.forEach(resource => {
const link = document.createElement('link');
link.rel = 'preload';
link.href = resource;
link.as = resource.endsWith('.css') ? 'style' : '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 ? `
<div class="empty-favorites">
<div class="empty-icon">
<i class="fas fa-heart-broken"></i>
</div>
<h3>收藏夹空空如也</h3>
<p>快去收藏一些喜欢的图片吧!</p>
<button class="explore-button" onclick="loadAlbums()">
<i class="fas fa-compass"></i> 探索相册
</button>
</div>
` : `${favoriteImages.map((fav, index) => `
<div class="favorite-card" onclick="openFavoriteImage('${fav.favorite.album_id}')">
<div class="card-image">
<img src="${API_BASE}/thumbnail/${fav.image.id}"
alt="${fav.image.title || '收藏的图片'}"
loading="lazy">
<div class="card-overlay">
<div class="overlay-content">
<button class="quick-view" onclick="event.stopPropagation(); previewFavorite(${index})">
<i class="fas fa-expand"></i>
</button>
<button class="remove-favorite" onclick="removeFavorite(event, '${fav.favorite.id}')">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="favorite-badge">
<i class="fas fa-heart"></i>
</div>
</div>
<div class="card-content">
<div class="image-meta">
<span class="meta-item">
<i class="fas fa-calendar"></i>
${formatDate(fav.favorite.created_at)}
</span>
<span class="meta-item">
<i class="fas fa-ruler-combined"></i>
${fav.image.width}×${fav.image.height}
</span>
</div>
</div>
</div>
`).join('')}
`}
`;
// 更新统计信息 - 显示收藏数量
document.getElementById('stats').innerHTML = `<div class="favorites-header">
<div class="header-content">
<div class="header-left">
<div class="favorites-icon">
<i class="fas fa-heart"></i>
</div>
<div class="header-info">
<h1>我的收藏夹</h1>
<p class="favorites-count">共收藏了 <span class="count-number">${favoriteImages.length}</span> 张图片</p>
</div>
</div>
<div class="header-right">
<div class="action-buttons">
<button class="back-button" onclick="loadAlbums()">
<i class="fas fa-arrow-left"></i> 返回首页
</button>
</div>
</div>
</div>
</div>`;
}
// 格式化日期
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 = `
<div class="preview-modal" id="previewModal">
<div class="preview-overlay" onclick="closePreviewModal()"></div>
<div class="preview-container">
<div class="preview-header">
<div class="preview-title">
<span class="preview-info">来自: ${favorite.album_title}</span>
</div>
<div class="preview-actions">
<button class="preview-nav preview-prev" onclick="navigatePreview(-1)" ${index === 0 ? 'disabled' : ''}>
<i class="fas fa-chevron-left"></i>
</button>
<span class="preview-counter">${index + 1} / ${currentFavorites.length}</span>
<button class="preview-nav preview-next" onclick="navigatePreview(1)" ${index === currentFavorites.length - 1 ? 'disabled' : ''}>
<i class="fas fa-chevron-right"></i>
</button>
<button class="preview-close" onclick="closePreviewModal()">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="preview-content">
<div class="preview-image-container">
<img src="${API_BASE}/original/${favorite.image.id}"
alt="${favorite.image.title || '预览图片'}"
class="preview-image"
id="preview-image"
loading="eager">
</div>
</div>
<div class="preview-footer">
<div class="preview-meta">
<span class="meta-item">
<i class="fas fa-calendar"></i>
${formatDate(favorite.favorite.created_at)}
</span>
<span class="meta-item">
<i class="fas fa-ruler-combined"></i>
${favorite.image.width} × ${favorite.image.height}
</span>
<span class="meta-item">
<i class="fas fa-heart"></i>
已收藏
</span>
</div>
<div class="preview-controls">
<button class="preview-action" onclick="openFavoriteImage('${favorite.favorite.album_id}')">
<i class="fas fa-folder-open"></i> 打开相册
</button>
<button class="preview-action preview-remove" onclick="removeFavoriteFromPreview('${favorite.favorite.id}')">
<i class="fas fa-trash"></i> 取消收藏
</button>
</div>
</div>
</div>
</div>
`;
// 添加到页面
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 = `<i class="fas fa-calendar"></i> ${formatDate(favorite.favorite.created_at)}`;
metaElements[1].innerHTML = `<i class="fas fa-ruler-combined"></i> ${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 = '<i class="fas fa-exclamation-triangle"></i><span>图片加载失败</span>';
};
}
}
// 处理键盘事件
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 sortFavorites(mode) {
// 这里可以实现排序功能
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;