feat(auto): 按作者筛选小说
This commit is contained in:
parent
db1208b981
commit
49bb95604b
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 搜索功能 ==========
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user