From 49bb95604bf04ef6b061f1c1f2a9c3fea18ee157 Mon Sep 17 00:00:00 2001 From: irony Date: Sat, 6 Dec 2025 20:47:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(auto):=20=E6=8C=89=E4=BD=9C=E8=80=85?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E5=B0=8F=E8=AF=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/css/components.css | 16 +++++ src/main/resources/static/css/pages.css | 48 +++++++++++++ src/main/resources/static/js/app.js | 21 +++++- src/main/resources/static/js/pages.js | 71 +++++++++++++++++--- 4 files changed, 146 insertions(+), 10 deletions(-) diff --git a/src/main/resources/static/css/components.css b/src/main/resources/static/css/components.css index b1f9f52..b88a77e 100644 --- a/src/main/resources/static/css/components.css +++ b/src/main/resources/static/css/components.css @@ -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); diff --git a/src/main/resources/static/css/pages.css b/src/main/resources/static/css/pages.css index 2ebbd05..37d8b5d 100644 --- a/src/main/resources/static/css/pages.css +++ b/src/main/resources/static/css/pages.css @@ -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); diff --git a/src/main/resources/static/js/app.js b/src/main/resources/static/js/app.js index d99988c..4d922ed 100644 --- a/src/main/resources/static/js/app.js +++ b/src/main/resources/static/js/app.js @@ -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); + } + }); } // ========== 搜索功能 ========== diff --git a/src/main/resources/static/js/pages.js b/src/main/resources/static/js/pages.js index 7d3ab1f..03ae2ef 100644 --- a/src/main/resources/static/js/pages.js +++ b/src/main/resources/static/js/pages.js @@ -208,7 +208,7 @@ const Pages = (function() {
${novel.name}
-
${novel.author}
+
${novel.author || '未知'}
`; @@ -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 || '

暂无小说

'); + // 显示筛选信息 + let filterInfo = ''; + if (useAuthor) { + filterInfo = `
作者:${useAuthor}
`; + } else if (useTag) { + filterInfo = `
标签:${useTag}
`; + } + const listHtml = html || '

暂无小说

'; + $('#novel-list').html(filterInfo ? (filterInfo + listHtml) : listHtml); } // 更新加载更多按钮 - if (hasMore) { + if (hasMore && filteredNovels.length > 0) { $('#load-more').html(''); } else { $('#load-more').html('没有更多了'); @@ -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() {
${novel.name}
-
${novel.author}
+
${novel.author || '未知'}
${synopsis}...
${tags.map(t => `${t}`).join('')} @@ -569,7 +605,7 @@ const Pages = (function() {

${novel.name}

-
${novel.author}
+
${novel.author || '未知'}
${novel.chapterCount || 0}
@@ -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 };