Files
trpic/web/scripts/search/search.js
Hubert Chen 6a58d58737 adjust socials avatar and banner proxy hander
socials search APIno longer return `avatar_url` and `banner_url` field
auto focus search input when loaded
2026-06-25 20:37:36 +08:00

220 lines
6.8 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
const searchInput = document.getElementById('searchInput');
const searchBtn = document.getElementById('searchBtn');
const postsGallery = document.getElementById('postsGallery');
const tagsGallery = document.getElementById('tagsGallery');
const postsTitle = document.getElementById('postsTitle');
const tagsTitle = document.getElementById('tagsTitle');
const socialsGallery = document.getElementById('socialsGallery');
const socialsTitle = document.getElementById('socialsTitle');
const statusIndicator = document.getElementById('statusIndicator');
let currentQuery = '';
let isLoading = false;
let hasLoadedPosts = false;
let hasLoadedTags = false;
let hasLoadedSocials = false;
searchInput.focus()
searchBtn.addEventListener('click', initiateSearch);
searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') initiateSearch();
});
window.addEventListener('scroll', handleScroll);
function initiateSearch() {
const text = searchInput.value.trim();
if (!text) return;
if (isLoading) return;
currentQuery = text;
// 重置页面状态与清空旧数据
postsGallery.innerHTML = '';
tagsGallery.innerHTML = '';
socialsGallery.innerHTML = ''; // 新增
postsTitle.style.display = 'none';
tagsTitle.style.display = 'none';
socialsTitle.style.display = 'none'; // 新增
hasLoadedPosts = false;
hasLoadedTags = false;
hasLoadedSocials = false; // 新增
fetchPosts();
}
async function fetchPosts() {
isLoading = true;
setStatus('正在搜索作品...');
try {
const response = await fetch(`/api/search/posts?text=${encodeURIComponent(currentQuery)}`);
const data = await response.json();
if (data.posts && data.posts.length > 0) {
postsTitle.style.display = 'block';
postsTitle.textContent = `共找到 ${data.posts.length} 个作品,耗时 ${data.time}`;
renderCards(data.posts, postsGallery, 'post');
}
hasLoadedPosts = true;
setStatus('');
setTimeout(checkIfScreenNeedsMoreContent, 100);
} catch (error) {
console.error('获取作品失败:', error);
setStatus('搜索作品时发生错误');
} finally {
isLoading = false;
}
}
async function fetchTags() {
if (hasLoadedTags || isLoading) return;
isLoading = true;
setStatus('正在搜索标签...');
try {
const response = await fetch(`/api/search/tags?text=${encodeURIComponent(currentQuery)}`);
const data = await response.json();
if (data.tags && data.tags.length > 0) {
tagsTitle.style.display = 'block';
tagsTitle.textContent = `共找到 ${data.tags.length} 个标签,耗时 ${data.time}`;
renderCards(data.tags, tagsGallery, 'tag');
}
hasLoadedTags = true;
setStatus(''); // 清空状态,准备接力
setTimeout(checkIfScreenNeedsMoreContent, 100);
} catch (error) {
console.error('获取标签失败:', error);
setStatus('加载标签时发生错误');
} finally {
isLoading = false;
}
}
async function fetchSocials() {
if (hasLoadedSocials || isLoading) return;
isLoading = true;
setStatus('正在加载相关社交账号...');
try {
const response = await fetch(`/api/search/socials?text=${encodeURIComponent(currentQuery)}`);
const data = await response.json();
if (data.socials && data.socials.length > 0) {
socialsTitle.style.display = 'block';
socialsTitle.textContent = `共找到 ${data.socials.length} 个社交账号,耗时 ${data.time}`;
renderCards(data.socials, socialsGallery, 'social');
}
hasLoadedSocials = true;
setStatus('没有更多结果了'); // 最后一项加载完,展示最终提示
} catch (error) {
console.error('获取社交账号失败:', error);
setStatus('加载社交账号时发生错误。');
} finally {
isLoading = false;
}
}
// 屏幕高度检查
function checkIfScreenNeedsMoreContent() {
const isScreenFilled = document.documentElement.scrollHeight > window.innerHeight;
if (!isScreenFilled) {
if (hasLoadedPosts && !hasLoadedTags) {
fetchTags();
} else if (hasLoadedTags && !hasLoadedSocials) {
fetchSocials();
}
}
}
// 滚动事件处理
function handleScroll() {
// 如果全部加载完毕,直接拦截
if (isLoading || hasLoadedSocials) return;
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const windowHeight = window.innerHeight;
const docHeight = document.documentElement.scrollHeight;
if (scrollTop + windowHeight >= docHeight - 150) {
if (hasLoadedPosts && !hasLoadedTags) {
fetchTags();
} else if (hasLoadedTags && !hasLoadedSocials) {
fetchSocials();
}
}
}
function renderCards(items, container, type) {
const fragment = document.createDocumentFragment();
items.forEach(item => {
const card = document.createElement('a');
card.className = 'card';
let titleText = '';
let subText = '';
let imgSrc = '';
let HTML = '';
if (type === 'post') {
card.href = `/artworks/${item.artwork_id}`;
imgSrc = `/thumbnails/${item.file_id}.jpg`;
titleText = item.title;
subText = item.text || '';
HTML = `<h3 class="card-title">${titleText ? titleText : ""}</h3><p class="card-subtitle">${escapeHTML(subText)}</p>`;
} else if (type === 'tag') {
card.href = `/artworks/${item.artwork_id}`;
imgSrc = `/thumbnails/${item.file_id}.jpg`;
HTML = `<span class="badge">#${item.tag}</span><p class="card-subtitle">${item.count} 个作品</p>`;
} else if (type === 'social') {
card.href = `/?socials=${item.id}`;
card.target = '_blank';
imgSrc = `/socials/${item.id}/avatar`;
titleText = item.display_name;
subText = item.platform || '';
if (item.username) {
subText += `/@${item.username}`;
} else if (item.user_id) {
subText += `/${item.user_id}`
}
HTML = `<span class="badge">${titleText}</span><a class="card-subtitle" href=${item.url} target="_blank">${subText}</a>`;
}
card.innerHTML = `
<img src="${imgSrc}" alt="${titleText}" loading="lazy">
<div class="card-info">${HTML}</div>
`;
fragment.appendChild(card);
});
container.appendChild(fragment);
}
function setStatus(text) {
statusIndicator.textContent = text;
}
function escapeHTML(str) {
if (!str) return '';
return str.toString()
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
})