重构课外书;修复异常;优化体验

This commit is contained in:
2026-07-26 06:55:48 +08:00
parent 711cff953b
commit 03e5e2f529
7 changed files with 336 additions and 607 deletions
+1
View File
@@ -6,6 +6,7 @@
1. 修复导航栏居中显示失效、分享海报高度、页码更新异常 1. 修复导航栏居中显示失效、分享海报高度、页码更新异常
2. 优化上一页动画效果 2. 优化上一页动画效果
3. 新增页面底部页码跳转功能 3. 新增页面底部页码跳转功能
4. 重构课外书(依赖豆瓣插件v1.2.2-3,模板端处理)
#### v1.2.5-8 #### v1.2.5-8
1. 重写作文目录、置顶样式 1. 重写作文目录、置顶样式
+118 -80
View File
@@ -584,42 +584,7 @@
} }
} }
#douban_pagination { .douban_page #post_item {
display: none;
padding: 30px;
text-align: center;
align-items: center;
justify-content: center;
border-top: 1px solid var(--pix-background);
}
#douban_pagination .post-paging {
display: flex;
align-items: center;
justify-content: center;
min-height: 38px;
}
#douban_pagination a {
padding: 10px 15px;
background: var(--pix-theme);
color: #fff;
border-radius: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
width: auto;
text-align: center;
}
#douban_pagination .douban-more-loading {
display: inline-flex;
align-items: center;
justify-content: center;
}
.douban_page #douban_item {
padding: 0; padding: 0;
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -628,25 +593,34 @@
align-items: center; align-items: center;
} }
.douban_page #douban_item .loading_box { .douban_page #post_item .loading_box {
text-align: center; text-align: center;
grid-column: 1 / -1; grid-column: 1 / -1;
} }
.douban_page #douban_item .douban_card_item { .douban_page #post_item > .no-results {
grid-column: 1 / -1;
width: 100%;
}
.douban_page #post_item > #prev_pagination {
grid-column: 1 / -1;
}
.douban_page #post_item .douban_card_item {
width: 100%; width: 100%;
margin: 0; margin: 0;
padding: 0 40px; padding: 0 20px;
border-right: 1px solid #e5e7eb; border-right: 1px solid #e5e7eb;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
} }
.douban_page #douban_item .douban_card_item:nth-child(2n) { .douban_page #post_item .douban_card_item:nth-child(2n) {
border-right: none; border-right: none;
} }
.douban_page #douban_item .douban_card_inner { .douban_page #post_item .douban_card_inner {
display: grid !important; display: grid !important;
grid-template-columns: 100px 1fr; grid-template-columns: 100px 1fr;
grid-template-rows: auto auto 1fr; grid-template-rows: auto auto 1fr;
@@ -658,7 +632,7 @@
align-items: start; align-items: start;
} }
.douban_page #douban_item .douban_media_col { .douban_page #post_item .douban_media_col {
width: 100px; width: 100px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -669,16 +643,16 @@
} }
.douban_page #douban_item { .douban_page #post_item {
align-items: stretch !important; align-items: stretch !important;
} }
.douban_page #douban_item .douban_poster_link, .douban_page #post_item .douban_poster_link,
.douban_page #douban_item .douban_poster_img { .douban_page #post_item .douban_poster_img {
width: 100px; width: 100px;
} }
.douban_page #douban_item .douban_poster_img { .douban_page #post_item .douban_poster_img {
display: block; display: block;
height: 140px; height: 140px;
object-fit: cover; object-fit: cover;
@@ -687,34 +661,75 @@
} }
.douban_page #douban_item .douban_rating_wrap { .douban_page #post_item .douban_rating_wrap {
display: none; display: none;
} }
.douban_page #douban_item .douban_text_col { .douban_page #post_item .douban_text_col {
display: contents; display: contents;
} }
.douban_page #douban_item .douban_title_row { .douban_page #post_item .douban_title_row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
grid-column: 1 / -1; grid-column: 1 / -1;
grid-row: 1; grid-row: 1;
margin-bottom: 6px; margin-bottom: 6px;
text-align: left; text-align: left;
} }
.douban_page #douban_item .douban_title_text { .douban_page #post_item .douban_title_text {
min-width: 0;
overflow: hidden;
color: var(--pix-theme); color: var(--pix-theme);
font-size: 16px; font-size: 16px;
line-height: 1.35; line-height: 1.35;
font-weight: 650; font-weight: 650;
text-decoration: none; text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
} }
.douban_page #douban_item .douban_title_text:hover { .douban_page #post_item .douban_title_text:hover {
color: rgb(28, 156, 90); color: var(--hilight-color);
} }
.douban_page #douban_item .douban_sub_meta { .douban_page #post_item .douban_title_text_plain,
.douban_page #post_item .douban_title_text_plain:hover {
color: #000;
}
.douban_page #post_item .douban_detail_link {
flex: 0 0 auto;
width: auto;
height: auto;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 3px 5px;
border-radius: 4px;
color: var(--pix-theme);
font-size: 13px;
line-height: 1.4;
text-decoration: none;
visibility: hidden;
pointer-events: none;
transition: color 0.2s ease, background-color 0.2s ease;
}
.douban_page #post_item .douban_detail_link.is-visible {
visibility: visible;
pointer-events: auto;
}
.douban_page #post_item .douban_detail_link:hover {
background: var(--pix-background);
color: var(--hilight-color);
}
.douban_page #post_item .douban_sub_meta {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0px; gap: 0px;
@@ -725,24 +740,24 @@
align-self: start; align-self: start;
} }
.douban_page #douban_item .douban_time_text { .douban_page #post_item .douban_time_text {
display: inline-block; display: inline-block;
padding: 3px 8px; padding: 3px 8px;
border-radius: 6px; border-radius: 6px;
background: rgba(168, 85, 247, 0.12); background: rgba(168, 85, 247, 0.12);
color: #a855f7; color: #8b5cf6;
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
font-weight: 500; font-weight: 500;
margin-right: 7px; margin-right: 7px;
} }
.douban_page #douban_item .douban_type_badge { .douban_page #post_item .douban_type_badge {
display: inline-block; display: inline-block;
padding: 3px 8px; padding: 3px 8px;
border-radius: 6px; border-radius: 6px;
background: rgba(56, 189, 248, 0.14); background: rgba(14, 165, 233, 0.13);
color: #0369a1; color: #0284c7;
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
vertical-align: middle; vertical-align: middle;
@@ -750,7 +765,7 @@
margin-right: 7px; margin-right: 7px;
} }
.douban_page #douban_item .douban_score_badge { .douban_page #post_item .douban_score_badge {
display: inline-block; display: inline-block;
padding: 3px 8px; padding: 3px 8px;
border-radius: 6px; border-radius: 6px;
@@ -762,30 +777,25 @@
font-weight: 500; font-weight: 500;
} }
.douban_page #douban_item .douban_content_box { .douban_page #post_item .douban_content_box {
color: #374151; color: #55716a;
grid-column: 2; grid-column: 2;
grid-row: 3; grid-row: 3;
align-self: start; align-self: start;
} }
.douban_page #douban_item .douban_content_main { .douban_page #post_item .douban_content_main {
margin: 0; margin: 0;
font-size: 14px; font-size: 14px;
line-height: 1.6; line-height: 1.6;
color: #1f2937; color: #43584d;
display: block; display: -webkit-box;
overflow: hidden; overflow: hidden;
max-height: 89.6px; -webkit-box-orient: vertical;
transition: max-height 0.35s ease; -webkit-line-clamp: 5;
will-change: max-height;
} }
.douban_page #douban_item .douban_content_main.is-expanded { .douban_page #post_item .douban_expand_btn {
max-height: 10000px;
}
.douban_page #douban_item .douban_expand_btn {
display: inline-block; display: inline-block;
padding: 0; padding: 0;
color: var(--pix-theme); color: var(--pix-theme);
@@ -798,30 +808,58 @@
line-height: 1.6; line-height: 1.6;
} }
.douban_page #douban_item .douban_content_meta { .douban_page #post_item .douban_content_meta {
margin: 8px 0 0; margin: 8px 0 0;
font-size: 12px; font-size: 12px;
color: #6b7280; color: #76937f;
line-height: 1.5; line-height: 1.5;
} }
@media only screen and (max-width:1359px) { @media only screen and (max-width:1359px) {
.douban_page #douban_item { .douban_page #post_item {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.douban_page #douban_item .douban_card_item { .douban_page #post_item .douban_card_item {
border-right: none !important; border-right: none !important;
} }
} }
@media only screen and (max-width:540px) { @media only screen and (max-width:540px) {
.douban_page #douban_item .douban_card_item { .douban_page #post_item .douban_card_item {
padding: 0 15px; padding: 0 10px;
} }
.douban_page #douban_item .douban_card_inner { .douban_page #post_item .douban_card_inner {
column-gap: 11px; column-gap: 11px;
row-gap: 0px; row-gap: 0px;
} }
} }
.douban_detail_page #post_item {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.douban_detail_page #post_item .douban_card_item {
grid-column: 1 / -1;
border-right: none;
}
.douban_detail_page #post_item .douban_detail_link {
display: none;
}
.douban_detail_page #post_item .douban_title_text {
overflow: visible;
text-overflow: clip;
white-space: normal;
overflow-wrap: anywhere;
}
.douban_detail_page #post_item .douban_content_main {
display: block;
overflow: visible;
overflow-wrap: anywhere;
-webkit-line-clamp: unset;
-webkit-box-orient: initial;
}
+15 -462
View File
@@ -246,446 +246,26 @@ function confirmPixarAction() {
customLogout(); customLogout();
} }
// 豆瓣页:分类筛选 + AJAX加载(不依赖 finder API function initDoubanDetailLinks() {
function init_douban_page() { document.querySelectorAll('.douban_page:not(.douban_detail_page) .douban_card_item').forEach(function (card) {
var $page = $('.douban_page'); var link = card.querySelector('.douban_detail_link');
if ($page.length === 0) { var title = card.querySelector('.douban_title_text');
return; var content = card.querySelector('.douban_content_main');
}
var $list = $('#douban_item'); if (!link || !title || !content) {
var $pagination = $('#douban_pagination');
var $paginationBtn = $('#douban_pagination a');
if ($list.length === 0 || $paginationBtn.length === 0) {
return;
}
var state = {
page: 1,
size: 10,
type: '',
loading: false
};
function escapeHtml(input) {
if (input === null || input === undefined) {
return '';
}
return String(input)
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
function formatTime(isoTime) {
if (!isoTime) {
return '--';
}
var date = new Date(isoTime);
if (Number.isNaN(date.getTime())) {
return '--';
}
var year = date.getFullYear();
var month = String(date.getMonth() + 1).padStart(2, '0');
var day = String(date.getDate()).padStart(2, '0');
return year + '-' + month + '-' + day;
}
function buildRequestUrl(page, type) {
var query = new URLSearchParams({
page: String(page),
size: String(state.size)
});
if (type) {
query.append('type', type);
}
return '/apis/api.douban.moony.la/v1alpha1/doubanmovies?' + query.toString();
}
function renderEmpty() {
return '<div class="loading_box"><img src="/themes/theme-pix/assets/img/no-data.webp" alt="暂无内容" style="max-width: 280px; width: 100%; height: auto;"></div>';
}
function parseScoreValue(rawScore) {
if (rawScore === null || rawScore === undefined || rawScore === '') {
return null;
}
var scoreText = String(rawScore);
var matched = scoreText.match(/(\d+(?:\.\d+)?)/);
if (!matched || !matched[1]) {
return null;
}
var scoreNumber = parseFloat(matched[1]);
if (Number.isNaN(scoreNumber)) {
return null;
}
if (scoreNumber < 0) {
scoreNumber = 0;
}
if (scoreNumber > 5) {
scoreNumber = 5;
}
return scoreNumber;
}
function renderTypeNav(typeList) {
var $navList = $('.douban_cat_nav ul');
if ($navList.length === 0) {
return; return;
} }
var navHtml = ['<li><a data-type="" class="cat-link active">全部<span></span></a></li>']; var titleOverflow = title.scrollWidth > title.clientWidth;
var seen = {}; var contentOverflow = content.scrollHeight > content.clientHeight + 1;
link.classList.toggle('is-visible', titleOverflow || contentOverflow);
if (Array.isArray(typeList)) {
typeList.forEach(function (item) {
var key = item && item.key !== undefined && item.key !== null ? String(item.key).trim() : '';
if (!key || seen[key]) {
return;
}
seen[key] = true;
var safeKey = escapeHtml(key);
navHtml.push('<li><a data-type="' + safeKey + '" class="cat-link">' + safeKey + '<span></span></a></li>');
});
}
$navList.html(navHtml.join(''));
}
function renderScore(rawScore) {
var scoreValue = parseScoreValue(rawScore);
if (scoreValue === null) {
return '暂无评分';
}
var formatted = scoreValue.toFixed(1);
return formatted + ' / 5.0';
}
function renderItem(item) {
var spec = item && item.spec ? item.spec : {};
var faves = item && item.faves ? item.faves : {};
var name = escapeHtml(spec.name || '未命名条目');
var link = escapeHtml(spec.link || 'javascript:void(0);');
var poster = escapeHtml(spec.poster || '/themes/theme-pix/assets/img/theme/banner-all.webp');
var rawScore = faves.score || spec.score || '';
var createTime = escapeHtml(formatTime(faves.createTime));
var dataType = escapeHtml(spec.type || '--');
var contentText = escapeHtml(spec.cardSubtitle || '暂无内容简介');
var pid = escapeHtml((item.metadata && item.metadata.name) || ('douban-' + Date.now()));
var scoreText = renderScore(rawScore);
return '' +
'<div id="post-' + pid + '" class="loop_content p_item moment_item douban_card_item uk-animation-slide-bottom-small">' +
' <div class="p_item_inner douban_card_inner">' +
' <div class="douban_text_col">' +
' <div class="douban_title_row">' +
' <a class="douban_title_text" target="_blank" rel="noopener" href="' + link + '">' +
' ' + name +
' </a>' +
' </div>' +
' <div class="douban_media_col">' +
' <img class="douban_poster_img" src="' + poster + '" alt="' + name + '">' +
' </div>' +
' <div class="douban_sub_meta">' +
' <time class="douban_time_text" datetime="' + createTime + '">' + createTime + '</time>' +
' <span class="douban_type_badge">' + dataType + '</span>' +
' <span class="douban_score_badge">' + escapeHtml(scoreText) + '</span>' +
' </div>' +
' <div class="douban_content_box">' +
' <p class="douban_content_main douban_content_collapsed" data-full="' + escapeHtml(contentText) + '">' + contentText + '</p>' +
' <a class="douban_expand_btn" style="display:none;">展开</a>' +
' </div>' +
' </div>' +
' </div>' +
'</div>';
}
function updatePagination(hasNext, nextPage) {
if (hasNext) {
$paginationBtn
.attr('data-next-page', String(nextPage))
.attr('data', String(nextPage))
.text((window.Theme && Theme.site_page) ? Theme.site_page : '翻阅更多')
.show();
$pagination.removeClass('u-hide').css('display', 'flex');
} else {
$paginationBtn.removeAttr('data-next-page').removeAttr('data');
$paginationBtn.hide();
$pagination.hide();
}
}
function renderList(data, isAppend) {
var items = (data && data.items) ? data.items : [];
if (!isAppend) {
$list.empty();
}
if (items.length === 0 && !isAppend) {
$list.html(renderEmpty());
updatePagination(false, 1);
return;
}
var html = items.map(renderItem).join('');
$list.append($(html).fadeIn(300));
if (typeof lazyLoadInstance !== 'undefined') {
lazyLoadInstance.update();
}
if (typeof initializeMomentFold === 'function') {
initializeMomentFold();
}
initializeDoubanExpand();
updatePagination(!!data.hasNext, (data.page || state.page) + 1);
}
function initializeDoubanExpand() {
var collapsedHeight = 89.6;
$(document).off('click.doubanExpand', '.douban_expand_btn').on('click.doubanExpand', '.douban_expand_btn', function (e) {
e.preventDefault();
var $btn = $(this);
var $content = $btn.prev('.douban_content_main');
if ($content.length === 0) {
return;
}
if ($content.hasClass('is-expanded')) {
$content.removeClass('is-expanded');
$content.css('max-height', collapsedHeight + 'px');
$btn.text('展开');
} else {
var contentEl = $content[0];
var fullHeight = $content.data('fullHeight') || (contentEl ? contentEl.scrollHeight : 0);
$content.addClass('is-expanded');
$content.css('max-height', fullHeight + 'px');
$btn.text('收起');
}
});
$('.douban_content_main').each(function () {
var $content = $(this);
var $btn = $content.next('.douban_expand_btn');
if ($btn.length === 0) {
return;
}
var scrollHeight = this.scrollHeight;
var clientHeight = this.clientHeight;
if (scrollHeight > clientHeight) {
$btn.show();
$content.data('fullHeight', scrollHeight);
$content.css('max-height', collapsedHeight + 'px');
}
});
}
function requestList(page, type, isAppend, hooks) {
hooks = hooks || {};
if (state.loading) {
return;
}
state.loading = true;
var appendStartIndex = isAppend ? $list.children('.p_item').length : 0;
var oldState = {
listHtml: $list.html(),
paginationVisible: $pagination.is(':visible'),
btnVisible: $paginationBtn.is(':visible'),
btnText: $paginationBtn.text(),
btnNextPage: $paginationBtn.attr('data-next-page')
};
var apiUrl = buildRequestUrl(page, type);
$.ajax({
type: 'GET',
url: apiUrl,
dataType: 'json',
beforeSend: function () {
if (!isAppend) {
$list.html('<div class="loading_box"><div uk-spinner></div></div>');
$pagination.hide();
} else {
$paginationBtn.hide();
if ($('#douban_pagination .douban-more-loading').length === 0) {
$('#douban_pagination .post-paging').append('<div class="douban-more-loading"><div uk-spinner></div></div>');
}
$pagination.css('display', 'flex');
}
},
success: function (data) {
state.page = page;
renderList(data || {}, !!isAppend);
if (typeof hooks.onSuccess === 'function') {
hooks.onSuccess(data || {});
}
if (isAppend) {
var $newItems = $list.children('.p_item').slice(appendStartIndex);
if ($newItems.length > 0) {
var $scrollBody = (typeof $body !== 'undefined') ? $body : $('html,body');
var targetTop = $newItems.first().offset().top - 58;
if (!window.scroll_param || (!window.loadMoreTimeout && window.scroll_param > targetTop)) {
$scrollBody.animate({ scrollTop: targetTop }, 500);
} else {
window.forceStopLoading = true;
}
}
}
},
error: function () {
cocoMessage.error('数据获取失败');
if (!isAppend) {
if ($.trim(oldState.listHtml || '') !== '') {
$list.html(oldState.listHtml);
} else {
$list.html(renderEmpty());
}
}
if (oldState.paginationVisible) {
$pagination.css('display', 'flex');
} else {
$pagination.hide();
}
if (oldState.btnVisible) {
$paginationBtn.show();
} else {
$paginationBtn.hide();
}
if (oldState.btnText) {
$paginationBtn.text(oldState.btnText);
}
if (oldState.btnNextPage) {
$paginationBtn.attr('data-next-page', oldState.btnNextPage);
$paginationBtn.attr('data', oldState.btnNextPage);
}
if (typeof hooks.onError === 'function') {
hooks.onError();
}
},
complete: function () {
state.loading = false;
$('#douban_pagination .douban-more-loading').remove();
$('.douban_cat_nav .cat-link').removeClass('disabled');
$paginationBtn.text((window.Theme && Theme.site_page) ? Theme.site_page : '翻阅更多');
}
});
}
$(document).off('click.doubanCat', '.douban_cat_nav .cat-link').on('click.doubanCat', '.douban_cat_nav .cat-link', function () {
var $this = $(this);
if ($this.hasClass('disabled')) {
return false;
}
if ($this.hasClass('active')) {
if (window._tagSwitchCallback) {
window._tagSwitchCallback.resolve();
window._tagSwitchCallback = null;
}
return false;
}
$('.douban_cat_nav .cat-link').addClass('disabled');
var $activeBefore = $('.douban_cat_nav .cat-link.active');
var oldType = state.type;
var targetType = $this.attr('data-type') || '';
var targetTag = $this.clone().find('span').remove().end().text().trim();
state.page = 1;
state.type = targetType;
requestList(1, state.type, false, {
onSuccess: function () {
$this.addClass('active').parent().siblings().children('.cat-link').removeClass('active');
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
pix.centerCategoryNavActive($this);
}
var currentUrl = new URL(window.location.href);
if (!targetTag || targetTag === '全部') {
currentUrl.searchParams.delete('tag');
} else {
currentUrl.searchParams.set('tag', targetTag);
}
history.pushState({ url: currentUrl.pathname + currentUrl.search }, '', currentUrl.pathname + currentUrl.search);
// 分类切换后重置分页记录,避免自动恢复加载旧分类页数
$.removeCookie('page', { path: '/' });
if (window._tagSwitchCallback) {
window._tagSwitchCallback.resolve();
window._tagSwitchCallback = null;
}
},
onError: function () {
state.type = oldType;
if ($activeBefore.length > 0) {
$activeBefore.addClass('active').parent().siblings().children('.cat-link').removeClass('active');
}
if (window._tagSwitchCallback) {
window._tagSwitchCallback.reject();
window._tagSwitchCallback = null;
}
}
});
return false;
});
$(document).off('click.doubanMore', '#douban_pagination a').on('click.doubanMore', '#douban_pagination a', function () {
if (state.loading) {
return false;
}
var pageAttr = $(this).attr('data-next-page') || $(this).attr('data');
var nextPage = parseInt(pageAttr, 10);
if (!nextPage || Number.isNaN(nextPage)) {
return false;
}
requestList(nextPage, state.type, true, {
onSuccess: function () {
// 与 app.js 现有逻辑保持一致:记录当前已加载到的页码
$.cookie('page', nextPage, { path: '/' });
}
});
return false;
});
function applyUrlTagState() {
var urlTag = new URLSearchParams(window.location.search).get('tag');
if (urlTag && urlTag.trim() !== '') {
var $matchedTag = $('.douban_cat_nav .cat-link').filter(function () {
var tagText = $(this).clone().find('span').remove().end().text().trim();
return tagText === urlTag;
}).first();
if ($matchedTag.length > 0) {
$matchedTag.addClass('active').parent().siblings().children('.cat-link').removeClass('active');
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
pix.centerCategoryNavActive($matchedTag);
}
state.type = $matchedTag.attr('data-type') || '';
} else {
state.type = $('.douban_cat_nav .cat-link.active').attr('data-type') || '';
}
} else {
state.type = $('.douban_cat_nav .cat-link.active').attr('data-type') || '';
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
pix.centerCategoryNavActive($('.douban_cat_nav .cat-link.active').first());
}
}
}
$.ajax({
type: 'GET',
url: '/apis/api.douban.moony.la/v1alpha1/doubanmovies/-/types',
dataType: 'json',
success: function (data) {
var typeList = Array.isArray(data) ? data : ((data && Array.isArray(data.items)) ? data.items : []);
renderTypeNav(typeList);
},
complete: function () {
applyUrlTagState();
requestList(1, state.type, false);
}
}); });
} }
document.addEventListener('pjax:complete', initDoubanDetailLinks);
document.addEventListener('DOMContentLoaded', initDoubanDetailLinks);
window.addEventListener('resize', initDoubanDetailLinks);
// 打开确认模态框 // 打开确认模态框
function openModal(title, msg, type) { function openModal(title, msg, type) {
var modal = $('#momentsDeleteModal'); var modal = $('#momentsDeleteModal');
@@ -699,32 +279,5 @@ function openModal(title, msg, type) {
modal.fadeIn(200); modal.fadeIn(200);
} }
// 主题通用交互初始化
modify_m_bottom_music_button_link();
// = = = = = = = = = = = = = = = = 触发器 = = = = = = = = = = = = = = = =
// 集合:PJAX(初始化执行+PJAX执行)
function init_anian_pjax() {
// modify_moment_video_size();
init_douban_page();
}
// 集合:初始化(仅初始化执行一次)
function init_anian_inport() {
init_anian_pjax();
modify_m_bottom_music_button_link();
}
// PJAX监听
document.addEventListener('pjax:complete', function () {
init_anian_pjax();
})
// 入口
init_anian_inport();
+7 -23
View File
@@ -245,6 +245,7 @@ function getPreviousPageContext() {
initAgree(); initAgree();
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update(); if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
initializeMomentFold(); initializeMomentFold();
initDoubanDetailLinks();
} }
}; };
} }
@@ -1239,9 +1240,6 @@ $(document).on('click', '.moment_cat_nav ul li a', function () {
// ajax分类筛选朋友圈 // ajax分类筛选朋友圈
$(document).on('click', '.friends_cat_nav .cat-link', function () { $(document).on('click', '.friends_cat_nav .cat-link', function () {
var $this = $(this); var $this = $(this);
if ($this.closest('.douban_cat_nav').length > 0) {
return;
}
if ($this.hasClass('disabled')) { if ($this.hasClass('disabled')) {
return false; return false;
} }
@@ -1296,6 +1294,7 @@ $(document).on('click', '.friends_cat_nav .cat-link', function () {
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update(); if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
$('.friends_cat_nav .cat-link').removeClass('disabled'); $('.friends_cat_nav .cat-link').removeClass('disabled');
initializeMomentFold(); initializeMomentFold();
initDoubanDetailLinks();
// 更新浏览器历史状态 // 更新浏览器历史状态
if (typeof url === 'string') { if (typeof url === 'string') {
@@ -1503,6 +1502,7 @@ $(document).on('click', '#t_pagination a', function () {
initAgree(); initAgree();
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update(); if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
initializeMomentFold(); initializeMomentFold();
initDoubanDetailLinks();
syncPageParamToUrl(currentPage); syncPageParamToUrl(currentPage);
} else { } else {
$('#t_pagination a').hide(); $('#t_pagination a').hide();
@@ -1548,6 +1548,9 @@ $(document).ready(function () {
paginationSelector: '#p_pagination' paginationSelector: '#p_pagination'
}); });
$photosItem.empty();
$('#p_pagination a').hide();
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: url, url: url,
@@ -3114,26 +3117,7 @@ function anianxSpeedFetchXiehouyuWithTimeout(timeout) {
} }
function initjump() { function initjump() {
// 功能1:自定义页面tag接管(后续在自定义测实现,当前为过度) // 登录登出、发布更新等操作后,显示提示信息
const targetPaths = ['/douban'];
const pathname = window.location.pathname;
const urlParams = new URLSearchParams(window.location.search);
const activeTag = urlParams.get('tag')?.trim();
// 同时存在tag、且当前路径在集合内,才执行点击逻辑,不满足直接跳过
if (activeTag && targetPaths.includes(pathname)) {
// 统一导航按钮选择器
const navSelector = '.douban_cat_nav ul li a';
const targetLink = $(navSelector).filter(function () {
const linkText = $(this).clone().find('span').remove().end().text().trim();
return linkText === activeTag;
});
// 匹配到元素则模拟点击
if (targetLink.length) {
targetLink.trigger('click');
}
}
// 功能2:登录登出、发布更新等操作后,显示提示信息
let closeLoading = null; let closeLoading = null;
const loadType = $.cookie('load_type'); const loadType = $.cookie('load_type');
if (loadType) { if (loadType) {
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org"
th:replace="~{modules/layouts/layout :: layout(_head = null,_content = ~{::content},_title = ${douban != null and douban.spec != null ? douban.spec.name + ' - ' + site.title : title + ' - ' + site.title})}">
<th:block th:fragment="content">
<div class="page_main uk-width-2-3@m">
<th:block th:replace="~{modules/header}" />
<div id="pjax-container">
<div class="blog_list douban_page douban_detail_page">
<div class="blog_list_inner" uk-height-viewport="offset-top: true">
<div id="post_item" class="moment_list douban_list">
<th:block th:replace="~{macro/douban-item :: douban-item(${douban})}"></th:block>
<th:block th:if="${douban == null or douban.spec == null}">
<th:block th:replace="~{macro/tpl/content-none}" />
</th:block>
</div>
<div id="comment_form_reset"></div>
</div>
</div>
</div>
<th:block th:replace="~{modules/footer-main}" />
</div>
</th:block>
</html>
+99 -42
View File
@@ -1,42 +1,99 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" <html xmlns:th="https://www.thymeleaf.org"
th:replace="~{modules/layouts/layout :: layout(_head = null,_content = ~{::content},_title = ${title + ' - ' + site.title})}"> th:replace="~{modules/layouts/layout :: layout(_head = null,_content = ~{::content},_title = ${title + ' - ' + site.title})}">
<th:block th:fragment="content"> <th:block th:fragment="content">
<div class="page_main uk-width-2-3@m"> <div class="page_main uk-width-2-3@m">
<th:block th:replace="~{modules/header}" /> <th:block th:replace="~{modules/header}" />
<div id="pjax-container"> <div id="pjax-container" th:with="
page = ${#lists.isEmpty(param.page) or #strings.isEmpty(param.page[0]) ? 1 : param.page[0]},
<div class="blog_list douban_page"> selectedTag = ${#lists.isEmpty(param.tag) ? null : param.tag[0]},
<div class="blog_list_inner" uk-height-viewport="offset-top: true"> doubanPage = ${doubanFinder.list(page, 10, selectedTag, null)}
">
<div class="friends_cat_nav douban_cat_nav">
<ul> <div class="blog_list douban_page">
<li><a data-type="" class="cat-link active">全部<span></span></a></li> <div class="blog_list_inner" uk-height-viewport="offset-top: true">
</ul>
</div> <div class="friends_cat_nav douban_cat_nav">
<ul id="cat_nav_items">
<div id="douban_item" class="moment_list douban_list"></div> <li>
<a th:attr="data-href=@{/books}"
<div id="douban_pagination" class="u-hide"> th:classappend="${#strings.isEmpty(selectedTag) ? 'active' : ''}"
<div class="post-paging"> class="cat-link">
<a data-next-page="2" th:text="${theme.config.base_set.site_page}"></a> 全部<span></span>
</div> </a>
</div> </li>
<li th:each="type : ${types}">
<div id="comment_form_reset"></div> <a th:attr="data-href=@{/books(tag=${type.key})}"
th:classappend="${#strings.equals(selectedTag, type.key) ? 'active' : ''}"
</div> class="cat-link">
</div> <span th:text="${#strings.isEmpty(type.name) ? type.key : type.name}">类型</span>
</a>
</div> </li>
</ul>
<th:block th:replace="~{modules/footer-main}" /> </div>
</div> <div id="post_item" class="moment_list douban_list">
</th:block> <th:block th:each="doubanItem : ${doubanPage.items}">
<th:block th:replace="~{macro/douban-item :: douban-item(${doubanItem})}"></th:block>
</html> </th:block>
<th:block th:if="${#lists.isEmpty(doubanPage.items)}">
<th:block th:replace="~{macro/tpl/content-none}" />
</th:block>
</div>
<th:block th:if="${doubanPage.totalPages > 1}">
<div id="t_pagination">
<div class="post-paging" th:with="_page = ${doubanPage.page + 1}">
<a th:if="${doubanPage.hasNext() and #strings.isEmpty(selectedTag)}"
th:attr="data=@{/books(page=${_page})}"
th:text="${theme.config.base_set.site_page}"></a>
<a th:if="${doubanPage.hasNext() and not #strings.isEmpty(selectedTag)}"
th:attr="data=@{/books(tag=${selectedTag},page=${_page})}"
th:text="${theme.config.base_set.site_page}"></a>
<form class="page-jump-form" method="get" action="/books">
<span class="page-jump-label">转到</span>
<input th:if="${not #strings.isEmpty(selectedTag)}" type="hidden" name="tag"
th:value="${selectedTag}" />
<span class="page-jump-input-wrap">
<button class="page-jump-step page-jump-step-down" type="button"
title="减少页码" aria-label="减少页码">
<i class="ri-subtract-line" aria-hidden="true"></i>
</button>
<input class="page-jump-input" type="number" name="page" min="1"
th:max="${doubanPage.totalPages}" th:value="${doubanPage.page}"
inputmode="numeric" aria-label="页码" autocomplete="off" required />
<button class="page-jump-step page-jump-step-up" type="button"
title="增加页码" aria-label="增加页码">
<i class="ri-add-line" aria-hidden="true"></i>
</button>
</span>
<span class="page-jump-total">/ [[${doubanPage.totalPages}]]</span>
<button class="page-jump-submit" type="submit" title="跳转到指定页"
aria-label="跳转到指定页">
<i class="ri-arrow-right-line" aria-hidden="true"></i>
</button>
</form>
</div>
</div>
</th:block>
<div id="comment_form_reset"></div>
</div>
</div>
</div>
<th:block th:replace="~{modules/footer-main}" />
</div>
</th:block>
</html>
+63
View File
@@ -0,0 +1,63 @@
<th:block th:fragment="douban-item(doubanItem)" th:if="${doubanItem != null and doubanItem.spec != null}"
th:with="spec = ${doubanItem.spec}, faves = ${doubanItem.faves}, score = ${faves == null ? spec.score : (not #strings.isEmpty(faves.score) ? faves.score : spec.score)}, isRead = ${faves != null and faves.status == 'done'}">
<div th:id="${'post-' + doubanItem.metadata.name}"
class="loop_content p_item moment_item douban_card_item uk-animation-slide-bottom-small">
<div class="p_item_inner douban_card_inner">
<div class="douban_text_col">
<div class="douban_title_row">
<a th:if="${isRead and not #strings.isEmpty(spec.link)}"
class="douban_title_text"
th:href="${spec.link}"
th:text="${spec.name}">
豆瓣条目
</a>
<span th:unless="${isRead and not #strings.isEmpty(spec.link)}"
class="douban_title_text douban_title_text_plain"
th:text="${spec.name}">
豆瓣条目
</span>
<a class="douban_detail_link"
th:href="${'/books/' + doubanItem.metadata.name}"
aria-label="查看详情" title="查看详情">
详情
</a>
</div>
<div class="douban_media_col">
<span class="fancybox"
th:href="${#strings.isEmpty(spec.poster) ? '/themes/theme-pix/assets/img/banner-all.webp' : spec.poster}"
th:data-fancybox="${'douban-' + doubanItem.metadata.name}">
<img class="douban_poster_img"
th:src="${#strings.isEmpty(spec.poster) ? '/themes/theme-pix/assets/img/banner-all.webp' : spec.poster}"
th:alt="${spec.name}">
</span>
</div>
<div class="douban_sub_meta">
<time class="douban_time_text"
th:if="${faves != null and faves.createTime != null}"
th:datetime="${#dates.format(faves.createTime, 'yyyy-MM-dd HH:mm')}">
<span th:text="${#dates.format(faves.createTime, 'yyyy-MM-dd')}">2025-01-01</span>
</time>
<span class="douban_type_badge" th:text="${spec.type}">类型</span>
<span class="douban_score_badge"
th:if="${not #strings.isEmpty(score)}"
th:text="|${score}分|">评分</span>
</div>
<div class="douban_content_box">
<p class="douban_content_main"
th:text="${#strings.isEmpty(spec.cardSubtitle) ? '暂无简介' : spec.cardSubtitle}">
暂无简介
</p>
<p class="douban_content_meta">
<span th:if="${not #strings.isEmpty(spec.year)}" th:text="${spec.year}"></span>
<span th:if="${not #strings.isEmpty(spec.pubdate)}" th:text="${spec.pubdate}"></span>
</p>
</div>
</div>
</div>
</div>
</th:block>