// API基础地址
const API_BASE = '';
// 状态
let articles = [];
let currentPage = 1;
let pageSize = 20;
let totalCount = 0;
let selectedIds = new Set();
let currentArticleId = null;
// 页面加载
document.addEventListener('DOMContentLoaded', () => {
loadArticles();
loadCategories();
// 搜索防抖
let searchTimeout;
document.getElementById('search-input').addEventListener('input', (e) => {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
currentPage = 1;
loadArticles();
}, 300);
});
// 分类筛选
document.getElementById('category-filter').addEventListener('change', () => {
currentPage = 1;
loadArticles();
});
});
// 加载文章列表
async function loadArticles() {
const keyword = document.getElementById('search-input').value.trim();
const category = document.getElementById('category-filter').value;
const params = new URLSearchParams({
limit: pageSize,
offset: (currentPage - 1) * pageSize
});
if (keyword) {
const response = await fetch(`${API_BASE}/api/articles/search?q=${encodeURIComponent(keyword)}${category ? '&category=' + encodeURIComponent(category) : ''}`);
const data = await response.json();
if (data.success) {
articles = data.articles;
totalCount = data.count;
}
} else {
const response = await fetch(`${API_BASE}/api/articles?${params.toString()}`);
const data = await response.json();
if (data.success) {
articles = data.articles;
totalCount = data.count;
}
}
displayArticles();
updatePagination();
updateStats();
}
// 加载分类列表
async function loadCategories() {
try {
const response = await fetch(`${API_BASE}/api/articles?limit=1000`);
const data = await response.json();
if (data.success) {
const categories = new Set();
data.articles.forEach(a => {
if (a.category) categories.add(a.category);
});
const select = document.getElementById('category-filter');
select.innerHTML = '' +
Array.from(categories).map(c => ``).join('');
}
} catch (error) {
console.error('加载分类失败:', error);
}
}
// 显示文章列表
function displayArticles() {
const container = document.getElementById('articles-list');
if (articles.length === 0) {
container.innerHTML = '
${article.search_title && article.search_title !== productNames.join(', ') ? `
搜索标题: ${escapeHtml(article.search_title)}
` : ''}
${article.category ? `${escapeHtml(article.category)}` : ''}
${escapeHtml(article.source || '未知来源')}
${formatDate(article.fetch_date)}
${escapeHtml(article.summary || '')}
${keywords.length > 0 ? `
${keywords.slice(0, 5).map(k => `${escapeHtml(k)}`).join('')}
` : ''}
`;
}).join('');
}
// 更新分页
function updatePagination() {
const totalPages = Math.ceil(totalCount / pageSize);
document.getElementById('page-info').textContent = `第 ${currentPage} / ${totalPages || 1} 页`;
document.getElementById('prev-btn').disabled = currentPage <= 1;
document.getElementById('next-btn').disabled = currentPage >= totalPages;
}
// 更新统计
function updateStats() {
document.getElementById('total-count').textContent = `${totalCount} 篇文章`;
}
// 上一页
function prevPage() {
if (currentPage > 1) {
currentPage--;
loadArticles();
}
}
// 下一页
function nextPage() {
const totalPages = Math.ceil(totalCount / pageSize);
if (currentPage < totalPages) {
currentPage++;
loadArticles();
}
}
// 刷新列表
function refreshList() {
loadArticles();
}
// 全选/取消全选
function toggleSelectAll() {
const checked = document.getElementById('select-all').checked;
if (checked) {
articles.forEach(a => selectedIds.add(a.id));
} else {
selectedIds.clear();
}
displayArticles();
updateBatchActions();
}
// 切换单个选择
function toggleSelect(id) {
if (selectedIds.has(id)) {
selectedIds.delete(id);
} else {
selectedIds.add(id);
}
updateBatchActions();
}
// 更新批量操作按钮
function updateBatchActions() {
const batchActions = document.getElementById('batch-actions');
if (selectedIds.size > 0) {
batchActions.style.display = 'flex';
document.getElementById('selected-count').textContent = `已选 ${selectedIds.size} 篇`;
} else {
batchActions.style.display = 'none';
}
}
// 显示详情
async function showDetail(id) {
currentArticleId = id;
const article = articles.find(a => a.id === id);
if (!article) {
const response = await fetch(`${API_BASE}/api/articles/${id}`);
const data = await response.json();
if (data.success) {
Object.assign(article, data.article);
}
}
const productNames = safeParseJSON(article.product_names, []);
const keywords = safeParseJSON(article.keywords, []);
const body = document.getElementById('detail-body');
body.innerHTML = `