feat(auto): 按作者筛选小说

This commit is contained in:
irony 2025-12-06 20:47:45 +08:00
parent db1208b981
commit 49bb95604b
4 changed files with 146 additions and 10 deletions

View File

@ -467,6 +467,22 @@ body:has(.reader-mode) #toast {
color: var(--text-secondary);
}
.clickable-author {
cursor: pointer;
color: var(--primary);
transition: color var(--transition-fast);
display: inline-block;
position: relative;
padding: 2px 4px;
margin: -2px -4px;
border-radius: var(--radius-sm);
}
.clickable-author:active {
color: var(--primary-dark);
background: var(--bg-hover);
}
.novel-synopsis {
font-size: var(--font-size-sm);
color: var(--text-muted);

View File

@ -169,6 +169,49 @@
color: var(--bg-primary);
}
/* 筛选信息 */
.filter-info {
display: flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-sm) var(--spacing-md);
margin-bottom: var(--spacing-md);
background: var(--bg-hover);
border-radius: var(--radius-md);
font-size: var(--font-size-sm);
}
.filter-label {
color: var(--text-secondary);
}
.filter-value {
color: var(--primary);
font-weight: 500;
}
.clear-filter-btn {
margin-left: auto;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
color: var(--text-muted);
font-size: 20px;
line-height: 1;
cursor: pointer;
border-radius: var(--radius-full);
transition: all var(--transition-fast);
}
.clear-filter-btn:active {
background: var(--bg-card);
color: var(--text-primary);
}
/* 小说列表 */
.novel-list {
display: flex;
@ -465,6 +508,11 @@
color: var(--text-secondary);
}
.detail-author.clickable-author {
color: var(--primary);
font-weight: 500;
}
.detail-stats {
display: flex;
gap: var(--spacing-lg);

View File

@ -231,7 +231,7 @@ const App = (function() {
$('.tag-btn').removeClass('active');
$(this).addClass('active');
const tag = $(this).data('tag');
Pages.loadNovels(0, tag);
Pages.loadNovels(0, tag, null); // 清除作者筛选,只按标签筛选
});
// 加载更多(追加模式,保持当前筛选条件)
@ -255,10 +255,22 @@ const App = (function() {
}
});
// 点击作者名字,筛选该作者的作品
$(document).on('click', '.clickable-author', function(e) {
e.preventDefault();
e.stopPropagation();
const author = $(this).data('author');
if (author) {
Pages.searchByAuthor(author);
}
});
// 其他页面的小说卡片点击
$(document).on('click', '.novel-card, .novel-grid-card, .shelf-item', function(e) {
// 如果是搜索结果中的,上面的事件已处理,这里跳过
if ($(this).closest('#search-results').length) return;
// 如果点击的是作者名字,跳过(上面的事件已处理)
if ($(e.target).hasClass('clickable-author') || $(e.target).closest('.clickable-author').length) return;
e.preventDefault();
if ($(e.target).closest('button').length) return;
@ -386,6 +398,13 @@ const App = (function() {
$text.toggleClass('text-clamp-3');
$(this).text($text.hasClass('text-clamp-3') ? '展开' : '收起');
});
// 加载更多按钮使用事件委托在pages.js中也有绑定这里作为备用
$(document).on('click', '.load-more-btn', function() {
if (Pages.hasMore()) {
Pages.loadNovels(Pages.currentPage() + 1);
}
});
}
// ========== 搜索功能 ==========

View File

@ -208,7 +208,7 @@ const Pages = (function() {
</div>
<div class="novel-info">
<div class="novel-title text-ellipsis">${novel.name}</div>
<div class="novel-author text-ellipsis">${novel.author}</div>
<div class="novel-author text-ellipsis clickable-author" data-author="${novel.author || ''}">${novel.author || '未知'}</div>
</div>
</div>
`;
@ -262,31 +262,42 @@ const Pages = (function() {
}
}
async function loadNovels(page, tag = null, append = false) {
let currentAuthor = null; // 保存当前选择的作者
async function loadNovels(page, tag = null, author = null, append = false) {
if (isLoadingMore) return;
isLoadingMore = true;
// 如果不是追加加载,保存当前标签
// 如果不是追加加载,保存当前筛选条件
if (!append) {
currentPage = 0;
hasMore = true;
currentTag = tag; // 保存当前选择的标签
currentAuthor = author; // 保存当前选择的作者
$('#novel-list').html(renderSkeletonList(5));
}
// 追加加载时使用已保存的标签
// 追加加载时使用已保存的筛选条件
const useTag = append ? currentTag : tag;
const useAuthor = append ? currentAuthor : author;
try {
const params = { page, size: 20 };
if (useTag) params.tag = useTag;
if (useAuthor) params.keyword = useAuthor; // 使用keyword参数搜索作者
const data = await API.searchNovels(params);
const novels = data.content || [];
hasMore = !data.last;
// 如果有作者筛选,只保留该作者的作品
let filteredNovels = novels;
if (useAuthor) {
filteredNovels = novels.filter(novel => novel.author === useAuthor);
}
let html = '';
novels.forEach(novel => {
filteredNovels.forEach(novel => {
const isInShelf = Store.isInShelfCache(novel.id);
html += renderNovelCard(novel, isInShelf);
});
@ -294,11 +305,19 @@ const Pages = (function() {
if (append) {
$('#novel-list').append(html);
} else {
$('#novel-list').html(html || '<div class="empty-state"><p>暂无小说</p></div>');
// 显示筛选信息
let filterInfo = '';
if (useAuthor) {
filterInfo = `<div class="filter-info"><span class="filter-label">作者:</span><span class="filter-value">${useAuthor}</span><button class="clear-filter-btn" data-type="author">×</button></div>`;
} else if (useTag) {
filterInfo = `<div class="filter-info"><span class="filter-label">标签:</span><span class="filter-value">${useTag}</span><button class="clear-filter-btn" data-type="tag">×</button></div>`;
}
const listHtml = html || '<div class="empty-state"><p>暂无小说</p></div>';
$('#novel-list').html(filterInfo ? (filterInfo + listHtml) : listHtml);
}
// 更新加载更多按钮
if (hasMore) {
if (hasMore && filteredNovels.length > 0) {
$('#load-more').html('<button class="load-more-btn">加载更多</button>');
} else {
$('#load-more').html('<span style="color:var(--text-muted);font-size:14px;">没有更多了</span>');
@ -311,6 +330,23 @@ const Pages = (function() {
handleCoverError(this);
});
// 重新绑定清除筛选按钮事件(只在非追加模式下绑定,避免重复绑定)
if (!append) {
$(document).off('click', '.clear-filter-btn').on('click', '.clear-filter-btn', function(e) {
e.preventDefault();
e.stopPropagation();
const filterType = $(this).data('type');
if (filterType === 'author') {
currentAuthor = null;
loadNovels(0, currentTag, null);
} else if (filterType === 'tag') {
currentTag = null;
$('.tag-btn').removeClass('active');
loadNovels(0, null, currentAuthor);
}
});
}
} catch (error) {
console.error('加载小说失败:', error);
Toast.show('加载失败,请重试');
@ -332,7 +368,7 @@ const Pages = (function() {
</div>
<div class="novel-info">
<div class="novel-title text-ellipsis">${novel.name}</div>
<div class="novel-author">${novel.author}</div>
<div class="novel-author clickable-author" data-author="${novel.author || ''}">${novel.author || '未知'}</div>
<div class="novel-synopsis text-clamp-2">${synopsis}...</div>
<div class="novel-tags">
${tags.map(t => `<span class="tag">${t}</span>`).join('')}
@ -569,7 +605,7 @@ const Pages = (function() {
</div>
<div class="detail-meta">
<h1 class="detail-title">${novel.name}</h1>
<div class="detail-author">${novel.author}</div>
<div class="detail-author clickable-author" data-author="${novel.author || ''}">${novel.author || '未知'}</div>
<div class="detail-stats">
<div class="detail-stat">
<div class="detail-stat-value">${novel.chapterCount || 0}</div>
@ -750,6 +786,22 @@ const Pages = (function() {
return html;
}
// 按作者搜索(公开函数)
function searchByAuthor(author) {
if (!author) return;
// 切换到发现页面
if (window.location.hash !== '#/explore') {
window.location.hash = '#/explore';
// 等待页面渲染完成后加载该作者的作品
setTimeout(() => {
loadNovels(0, null, author);
}, 300);
} else {
// 如果已经在发现页面,直接加载
loadNovels(0, null, author);
}
}
// 公开API
return {
renderShelf,
@ -760,6 +812,7 @@ const Pages = (function() {
renderSearchResults,
renderSearchByTag,
loadNovels,
searchByAuthor,
currentPage: () => currentPage,
hasMore: () => hasMore
};