3266 lines
110 KiB
JavaScript
3266 lines
110 KiB
JavaScript
var $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body');
|
||
var storage = window.localStorage;
|
||
const HTML_PAGE_AJAX_HEADERS = {
|
||
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||
};
|
||
const DEFAULT_LIST_LOADING_HTML = '<div class="loading_box"><div uk-spinner></div></div>';
|
||
const PHOTO_LIST_LOADING_HTML = '<div class="loading_box" style="text-align:center;padding:50px;"><div uk-spinner></div></div>';
|
||
|
||
var lazyLoadInstance = new LazyLoad({});
|
||
|
||
function highlightMenu() {
|
||
$('.left_menu_box ul li').removeClass('current-pjax-item')
|
||
// 路径映射表
|
||
const pathMap = {
|
||
'/moments': '/',
|
||
'/tags': '/content',
|
||
'/archives': '/archives',
|
||
'/categories': '/content'
|
||
}
|
||
|
||
// 获取清洗后的 pathname(去掉 ? 和 #)
|
||
function getPathname(url) {
|
||
const cleanUrl = url.substring(0,
|
||
url.indexOf('?') === -1
|
||
? (url.indexOf('#') === -1 ? url.length : url.indexOf('#'))
|
||
: url.indexOf('?')
|
||
)
|
||
return new URL(cleanUrl).pathname
|
||
}
|
||
|
||
// 从长到短匹配路径映射(支持 /categories/shi 匹配 /categories)
|
||
function getTargetPathname(pathname) {
|
||
const segments = pathname.split('/').filter(Boolean)
|
||
for (let i = segments.length; i >= 0; i--) {
|
||
const currentPath = '/' + segments.slice(0, i).join('/')
|
||
if (pathMap[currentPath]) return pathMap[currentPath]
|
||
}
|
||
return pathname // 无映射则返回原路径
|
||
}
|
||
|
||
const currentPathname = getPathname(location.href)
|
||
const targetPathname = getTargetPathname(currentPathname)
|
||
let hasMatched = false
|
||
|
||
// 遍历一级菜单匹配
|
||
$('.left_menu_box ul li a').each((i, e) => {
|
||
const menuPathname = getPathname(e.href)
|
||
if (targetPathname === menuPathname) {
|
||
e.parentElement.classList.add('current-pjax-item')
|
||
hasMatched = true
|
||
}
|
||
})
|
||
|
||
// 兜底匹配 /navigator
|
||
if (!hasMatched) {
|
||
$('.left_menu_box ul li a').each((i, e) => {
|
||
const menuPathname = getPathname(e.href)
|
||
if (menuPathname === '/navigator') {
|
||
e.parentElement.classList.add('current-pjax-item')
|
||
}
|
||
})
|
||
}
|
||
|
||
// 高亮完成后再滚动,确保当前项在导航容器内可见并尽量居中。
|
||
const activeMenuLink = document.querySelector('.left_menu_box ul li.current-pjax-item a');
|
||
if (activeMenuLink && typeof activeMenuLink.scrollIntoView === 'function') {
|
||
activeMenuLink.scrollIntoView({
|
||
behavior: 'smooth',
|
||
block: 'nearest',
|
||
inline: 'center'
|
||
});
|
||
}
|
||
}
|
||
|
||
function closeMomentPushModal() {
|
||
const modal = document.getElementById('create_post_box');
|
||
if (!modal || !window.UIkit || typeof UIkit.modal !== 'function') return;
|
||
|
||
try {
|
||
UIkit.modal(modal).hide();
|
||
} catch (e) { }
|
||
}
|
||
|
||
function reloadCurrentPageByPjax(loadType) {
|
||
if (window.pjax && typeof window.pjax.loadUrl === 'function') {
|
||
try {
|
||
$.removeCookie('load_type', { path: '/' });
|
||
window.pjax.loadUrl(window.location.href, {
|
||
history: false,
|
||
scrollTo: false
|
||
});
|
||
return;
|
||
} catch (e) { }
|
||
}
|
||
|
||
if (loadType) $.cookie('load_type', loadType, { path: '/' });
|
||
location.reload();
|
||
}
|
||
|
||
function buildRelativeUrl(url) {
|
||
const relativeUrl = url.pathname + url.search + url.hash;
|
||
try {
|
||
return decodeURI(relativeUrl);
|
||
} catch (e) {
|
||
return relativeUrl;
|
||
}
|
||
}
|
||
|
||
function removePageParamFromUrl(url) {
|
||
try {
|
||
const targetUrl = new URL(url || window.location.href, window.location.origin);
|
||
targetUrl.searchParams.delete('page');
|
||
return buildRelativeUrl(targetUrl);
|
||
} catch (e) {
|
||
return url || window.location.pathname;
|
||
}
|
||
}
|
||
|
||
function syncPageParamToUrl(page) {
|
||
const pageNumber = parseInt(page, 10);
|
||
if (!pageNumber || pageNumber < 1) return;
|
||
|
||
const url = new URL(window.location.href);
|
||
url.pathname = url.pathname.replace(/\/page\/\d+\/?$/, '') || '/';
|
||
if (url.pathname !== '/' && url.pathname.endsWith('/')) {
|
||
url.pathname = url.pathname.slice(0, -1);
|
||
}
|
||
|
||
if (pageNumber > 1) {
|
||
url.searchParams.set('page', pageNumber);
|
||
} else {
|
||
url.searchParams.delete('page');
|
||
}
|
||
|
||
const displayUrl = buildRelativeUrl(url);
|
||
const currentState = history.state && typeof history.state === 'object' ? history.state : {};
|
||
|
||
// PJAX uses history.state.url when restoring a popstate entry. Keep it in
|
||
// sync with the visible URL after AJAX pagination changes the current page.
|
||
history.replaceState(
|
||
Object.assign({}, currentState, { url: displayUrl, page: pageNumber }),
|
||
'',
|
||
displayUrl
|
||
);
|
||
}
|
||
|
||
function getPageNumberFromUrl(urlValue) {
|
||
try {
|
||
const targetUrl = new URL(urlValue || window.location.href, window.location.origin);
|
||
const pageParam = parseInt(targetUrl.searchParams.get('page'), 10);
|
||
if (pageParam && pageParam > 0) return pageParam;
|
||
|
||
const pathPage = targetUrl.pathname.match(/\/page\/(\d+)\/?$/);
|
||
return pathPage ? parseInt(pathPage[1], 10) : 1;
|
||
} catch (e) {
|
||
const pageMatch = String(urlValue || '').match(/[?&]page=(\d+)|\/page\/(\d+)\/?$/);
|
||
return pageMatch ? parseInt(pageMatch[1] || pageMatch[2], 10) : 1;
|
||
}
|
||
}
|
||
|
||
function buildPageUrlFromCurrent(page) {
|
||
const pageNumber = parseInt(page, 10);
|
||
if (!pageNumber || pageNumber < 1) return buildRelativeUrl(new URL(window.location.href));
|
||
|
||
const url = new URL(window.location.href);
|
||
const pathPageReg = /\/page\/\d+\/?$/;
|
||
const usesPathPage = !url.searchParams.has('page') && pathPageReg.test(url.pathname);
|
||
|
||
if (usesPathPage) {
|
||
if (pageNumber > 1) {
|
||
url.pathname = url.pathname.replace(pathPageReg, '/page/' + pageNumber);
|
||
} else {
|
||
url.pathname = url.pathname.replace(pathPageReg, '') || '/';
|
||
}
|
||
} else {
|
||
url.pathname = url.pathname.replace(pathPageReg, '') || '/';
|
||
if (pageNumber > 1) {
|
||
url.searchParams.set('page', pageNumber);
|
||
} else {
|
||
url.searchParams.delete('page');
|
||
}
|
||
}
|
||
|
||
if (url.pathname !== '/' && url.pathname.endsWith('/')) {
|
||
url.pathname = url.pathname.slice(0, -1);
|
||
}
|
||
|
||
return buildRelativeUrl(url);
|
||
}
|
||
|
||
function getPreviousPageContext() {
|
||
const $photosList = $('#photos_item');
|
||
if ($photosList.length) {
|
||
return {
|
||
type: 'photos',
|
||
$list: $photosList,
|
||
extract: function (data) {
|
||
return $(data).find('#photos_item .gallery-photo, .norpost_list .gallery-photo');
|
||
},
|
||
insert: function ($items, data) {
|
||
const $gallery = $('#photos_item .gallery-photos').first();
|
||
if ($gallery.length) {
|
||
$gallery.prepend($items.hide().fadeIn(300));
|
||
return $items.last();
|
||
}
|
||
|
||
const previousPhotosHtml = $(data).find('#photos_item').html();
|
||
if (previousPhotosHtml) {
|
||
this.$list.html(previousPhotosHtml);
|
||
return this.$list.find('.gallery-photo').last();
|
||
}
|
||
|
||
return $();
|
||
},
|
||
afterLoad: function () {
|
||
if (typeof pix !== 'undefined' && pix.initGalleryPhotos) pix.initGalleryPhotos();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
if ($('.gallery-photos').length > 0 && typeof waterfall === 'function') {
|
||
waterfall('.gallery-photos');
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
const $momentList = $('#post_item.moment_list');
|
||
if ($momentList.length) {
|
||
return {
|
||
type: 'moment',
|
||
$list: $momentList,
|
||
extract: function (data) {
|
||
return $(data).find('.moment_list .p_item');
|
||
},
|
||
insert: function ($items) {
|
||
const $previousButton = this.$list.children('#prev_pagination').first();
|
||
if ($previousButton.length) {
|
||
$previousButton.after($items.hide().fadeIn(300));
|
||
} else {
|
||
this.$list.prepend($items.hide().fadeIn(300));
|
||
}
|
||
return $items.last();
|
||
},
|
||
afterLoad: function () {
|
||
refreshAjaxPostList();
|
||
getMomentAudio();
|
||
initAgree();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
initializeMomentFold();
|
||
initDoubanDetailLinks();
|
||
}
|
||
};
|
||
}
|
||
|
||
const $postList = $('#post_item.norpost_list');
|
||
if ($postList.length) {
|
||
return {
|
||
type: 'post',
|
||
$list: $postList,
|
||
extract: function (data) {
|
||
return $(data).find('.norpost_list').children();
|
||
},
|
||
insert: function ($items) {
|
||
const $previousButton = this.$list.children('#prev_pagination').first();
|
||
if ($previousButton.length) {
|
||
$previousButton.after($items.hide().fadeIn(400));
|
||
} else {
|
||
this.$list.prepend($items.hide().fadeIn(400));
|
||
}
|
||
return $items.last();
|
||
},
|
||
afterLoad: function () {
|
||
refreshAjaxPostList();
|
||
initAgree();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
}
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function initPreviousPageButton(page) {
|
||
const context = getPreviousPageContext();
|
||
const $oldButton = $('#prev_pagination');
|
||
|
||
if (!context) {
|
||
$oldButton.remove();
|
||
return;
|
||
}
|
||
|
||
// 有BUG:PJAX加载失败后可能会新增本不该存在的上一页按钮,不管了
|
||
if ((page === undefined || page === null) && $oldButton.length) {
|
||
return;
|
||
}
|
||
|
||
const previousPage = page !== undefined && page !== null
|
||
? parseInt(page, 10)
|
||
: getPageNumberFromUrl(window.location.href) - 1;
|
||
|
||
if (!previousPage || previousPage < 1) {
|
||
$oldButton.remove();
|
||
return;
|
||
}
|
||
|
||
const previousUrl = buildPageUrlFromCurrent(previousPage);
|
||
const buttonText = (window.Theme && Theme.prev_page) ? Theme.prev_page : '翻阅更多';
|
||
|
||
if ($oldButton.length) {
|
||
$oldButton.addClass('uk-width-1-1');
|
||
$oldButton.find('a').attr('data', previousUrl).attr('data-page', previousPage).text(buttonText).show();
|
||
context.$list.prepend($oldButton);
|
||
animatePreviousPageButton($oldButton);
|
||
return;
|
||
}
|
||
|
||
const $button = $('<div/>', {
|
||
id: 'prev_pagination',
|
||
class: 'prev-pagination uk-width-1-1'
|
||
});
|
||
const $paging = $('<div/>', { class: 'post-paging' });
|
||
const $link = $('<a/>', {
|
||
class: 'prev-page-btn',
|
||
text: buttonText
|
||
}).attr('data', previousUrl).attr('data-page', previousPage);
|
||
|
||
$button.append($paging.append($link));
|
||
context.$list.prepend($button);
|
||
animatePreviousPageButton($button);
|
||
}
|
||
|
||
function createAjaxPageSnapshot(options) {
|
||
options = options || {};
|
||
const $content = options.$content || (options.contentSelector ? $(options.contentSelector) : $());
|
||
const $pagination = options.$pagination || (options.paginationSelector ? $(options.paginationSelector) : $());
|
||
const $pagingArea = options.$pagingArea || (options.pagingAreaSelector ? $(options.pagingAreaSelector) : $());
|
||
|
||
return {
|
||
$content: $content,
|
||
contentHtml: $content.length ? $content.html() : '',
|
||
paginationSelector: options.paginationSelector,
|
||
paginationHtml: $pagination.length ? $pagination.prop('outerHTML') : '',
|
||
paginationInsert: options.paginationInsert || 'after',
|
||
$paginationAnchor: options.$paginationAnchor || $content,
|
||
$pagingArea: $pagingArea,
|
||
pagingHtml: $pagingArea.length ? $pagingArea.html() : ''
|
||
};
|
||
}
|
||
|
||
function restoreAjaxPageSnapshot(snapshot, options) {
|
||
if (!snapshot) return;
|
||
|
||
options = options || {};
|
||
const restoreContent = options.content !== false;
|
||
const restorePagination = options.pagination !== false;
|
||
const restorePaging = options.paging === true;
|
||
|
||
if (restoreContent && snapshot.$content && snapshot.$content.length) {
|
||
snapshot.$content.html(snapshot.contentHtml);
|
||
}
|
||
|
||
if (restorePagination && snapshot.paginationSelector) {
|
||
const $currentPagination = $(snapshot.paginationSelector);
|
||
if (snapshot.paginationHtml) {
|
||
if ($currentPagination.length) {
|
||
$currentPagination.replaceWith(snapshot.paginationHtml);
|
||
} else if (snapshot.$paginationAnchor && snapshot.$paginationAnchor.length) {
|
||
if (snapshot.paginationInsert === 'before') {
|
||
snapshot.$paginationAnchor.before(snapshot.paginationHtml);
|
||
} else if (snapshot.paginationInsert === 'prepend') {
|
||
snapshot.$paginationAnchor.prepend(snapshot.paginationHtml);
|
||
} else {
|
||
snapshot.$paginationAnchor.after(snapshot.paginationHtml);
|
||
}
|
||
}
|
||
} else if ($currentPagination.length) {
|
||
$currentPagination.remove();
|
||
}
|
||
}
|
||
|
||
if (restorePaging && snapshot.$pagingArea && snapshot.$pagingArea.length) {
|
||
snapshot.$pagingArea.html(snapshot.pagingHtml);
|
||
}
|
||
}
|
||
|
||
function animatePreviousPageButton($button) {
|
||
if (!$button || !$button.length) return;
|
||
if ($button.hasClass('is-visible')) return;
|
||
|
||
requestAnimationFrame(() => {
|
||
requestAnimationFrame(() => {
|
||
$button.addClass('is-visible');
|
||
});
|
||
});
|
||
}
|
||
|
||
function getLoadMoreText() {
|
||
return (window.Theme && Theme.site_page) ? Theme.site_page : '翻阅更多';
|
||
}
|
||
|
||
function ensureLoadMoreButton(paginationSelector, insertAfterSelector) {
|
||
let $pagination = $(paginationSelector);
|
||
|
||
if (!$pagination.length) {
|
||
const paginationId = paginationSelector.charAt(0) === '#' ? paginationSelector.slice(1) : '';
|
||
$pagination = $('<div/>', paginationId ? { id: paginationId } : {});
|
||
$(insertAfterSelector).last().after($pagination);
|
||
}
|
||
|
||
let $postPaging = $pagination.find('.post-paging').first();
|
||
if (!$postPaging.length) {
|
||
$postPaging = $('<div/>', { class: 'post-paging' });
|
||
$pagination.empty().append($postPaging);
|
||
}
|
||
|
||
let $button = $postPaging.find('a').first();
|
||
if (!$button.length) {
|
||
$button = $('<a/>');
|
||
$postPaging.empty().append($button);
|
||
}
|
||
|
||
return $button;
|
||
}
|
||
|
||
function updateLoadMorePagination(paginationSelector, insertAfterSelector, data, fallbackPaginationSelector) {
|
||
const $data = $(data);
|
||
const $newPagination = $data.find(paginationSelector).first();
|
||
let newHref = $newPagination.find('a').attr('data');
|
||
|
||
if (newHref === undefined && fallbackPaginationSelector) {
|
||
newHref = $data.find(fallbackPaginationSelector + ' a').attr('data');
|
||
}
|
||
|
||
const newPaginationHtml = $newPagination.length ? $newPagination.prop('outerHTML') : '';
|
||
let $pagination = $(paginationSelector);
|
||
|
||
if (newPaginationHtml) {
|
||
if ($pagination.length) {
|
||
$pagination.replaceWith(newPaginationHtml);
|
||
} else {
|
||
$(insertAfterSelector).last().after(newPaginationHtml);
|
||
}
|
||
$pagination = $(paginationSelector);
|
||
}
|
||
|
||
if (newHref !== undefined) {
|
||
const $paginationBtn = ensureLoadMoreButton(paginationSelector, insertAfterSelector);
|
||
$paginationBtn.attr('data', newHref).text(getLoadMoreText()).show();
|
||
$(paginationSelector).show();
|
||
$(paginationSelector + ' .post-paging').show();
|
||
} else if (newPaginationHtml) {
|
||
// 最后一页仍保留页码跳转控件,只隐藏不存在的下一页按钮。
|
||
$(paginationSelector + ' .post-paging > a').hide();
|
||
$(paginationSelector).show();
|
||
$(paginationSelector + ' .post-paging').show();
|
||
} else {
|
||
$(paginationSelector + ' a').hide();
|
||
$(paginationSelector).hide();
|
||
}
|
||
|
||
initPageJumpSteppers();
|
||
return newHref;
|
||
}
|
||
|
||
function showListLoading(selector, loadingHtml) {
|
||
$(selector).html(loadingHtml || DEFAULT_LIST_LOADING_HTML);
|
||
}
|
||
|
||
function hidePagination(selector) {
|
||
$(selector).hide();
|
||
}
|
||
|
||
function setCategoryLinkActive($link, childSelector) {
|
||
$link.addClass('active').parent().siblings().children(childSelector || 'a').removeClass('active');
|
||
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
|
||
pix.centerCategoryNavActive($link);
|
||
}
|
||
}
|
||
|
||
function cacheCommentFormForAjax() {
|
||
var temp = $("#comment_form_reset");
|
||
var formHtml = $("#t_commentform").prop('outerHTML');
|
||
temp.html(formHtml);
|
||
}
|
||
|
||
function refreshAjaxPostList() {
|
||
const postListElement = document.getElementById("post_item");
|
||
window.pjax && window.pjax.refresh(postListElement);
|
||
}
|
||
|
||
function restoreAjaxSnapshotWithError(pageSnapshot, restoreOptions, message) {
|
||
restoreAjaxPageSnapshot(pageSnapshot, restoreOptions);
|
||
cocoMessage.error(message || '内容获取失败');
|
||
}
|
||
|
||
function restorePagingSnapshotWithError(pageSnapshot, message) {
|
||
restoreAjaxSnapshotWithError(pageSnapshot, { content: false, pagination: false, paging: true }, message);
|
||
}
|
||
|
||
function buildMediaLibraryUrl(page) {
|
||
return `/apis/${Theme.moments.attachments_api}/v1alpha1/attachments?group=&page=${page}&size=10&ungrouped=false&accepts=image/*&accepts=video/*`;
|
||
}
|
||
|
||
function buildMediaLibraryItem(value) {
|
||
var src = value.status.permalink;
|
||
var mediaType = value.spec.mediaType || '';
|
||
|
||
if (mediaType.startsWith('video/')) {
|
||
return `<li data-src="${src}" data-type="${mediaType}">
|
||
<video class="media-video-thumb" src="${src}" preload="metadata" muted></video>
|
||
</li>`;
|
||
}
|
||
|
||
return `<li data-src="${src}" data-type="${mediaType}">
|
||
<img src="${src}">
|
||
</li>`;
|
||
}
|
||
|
||
function renderMediaLibraryList(data) {
|
||
$(".wp_get_media_list").empty();
|
||
$.each(data.items || [], function (i, value) {
|
||
$(".wp_get_media_list").append(buildMediaLibraryItem(value));
|
||
});
|
||
}
|
||
|
||
function updateMediaLibraryPagination(page, totalPages) {
|
||
$(".attch_nav .nex").toggle(totalPages > page);
|
||
$(".attch_nav .pre").toggle(page > 1);
|
||
}
|
||
|
||
function loadMediaLibraryPage(page) {
|
||
$.ajax({
|
||
type: "get",
|
||
url: buildMediaLibraryUrl(page),
|
||
contentType: "application/json",
|
||
success: function (data) {
|
||
renderMediaLibraryList(data);
|
||
updateMediaLibraryPagination(page, data.totalPages);
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
//话题表情添加
|
||
$(document).on('click', 'a.smile_btn', function () {
|
||
var a = $(this).html();
|
||
var textarea = $("textarea#topic_content");
|
||
var content = textarea.val();
|
||
textarea.val(content + a);
|
||
textarea.focus();
|
||
});
|
||
|
||
$(document).on('click', '.smile_box i', function () {
|
||
var t = $(".smile_show");
|
||
t.slideToggle(100);
|
||
});
|
||
//选择话题
|
||
$(document).on('click', '.t_cat_box li', function () {
|
||
var name = $(this).find('.c_name span').html();
|
||
$('.t_cat_toogle span').html(name);
|
||
|
||
UIkit.dropdown('.t_cat_box').hide(false);
|
||
});
|
||
|
||
$(document).on('click', '.up_cat_btn', function () {
|
||
var name = $('input#add_cat').val();
|
||
if (!name) {
|
||
cocoMessage.error("请填写话题");
|
||
return false;
|
||
}
|
||
$('.t_cat_toogle span').text(name)
|
||
UIkit.dropdown('.t_cat_box').hide(false);
|
||
});
|
||
|
||
$(document).on('click', '.simi a', function () {
|
||
var visible = $(this).attr('visible');
|
||
if (visible == 'PUBLIC') {
|
||
$(this).html('<i class="ri-lock-line"></i>').attr('visible', 'PRIVATE');
|
||
$(this).children().css({ "background": "#ddd", "color": "#c6c6c6" });
|
||
} else {
|
||
$(this).html('<i class="ri-lock-unlock-line"></i>').attr('visible', 'PUBLIC');
|
||
$(this).children().css({ "background": "#e3efe7", "color": "#66c187" });
|
||
}
|
||
});
|
||
|
||
//消息通知
|
||
cocoMessage.config({
|
||
duration: 2000,
|
||
});
|
||
|
||
//ajax上传媒体文件到媒体库(已兼容图片/视频)
|
||
$(document).on('change', '#topic_img_up', function (e) {
|
||
e.preventDefault();
|
||
if ($('#topic_img_up').val() == '') return;
|
||
|
||
const policyName = Theme.moments.policy_name;
|
||
const groupName = Theme.moments.group_name;
|
||
|
||
var files = $('#topic_img_up')[0].files;
|
||
var imgtot = 0;
|
||
var num = $('.add_img_box .t_media_item').length;
|
||
|
||
// 修改提示语为“文件”
|
||
if (num + files.length > 9) {
|
||
cocoMessage.error("最多上传9个媒体文件");
|
||
return;
|
||
}
|
||
|
||
$.each(files, function (i, file) {
|
||
imgtot += file['size'];
|
||
});
|
||
|
||
var tot = imgtot / 1024000;
|
||
|
||
$(".up_img_btn i").hide();
|
||
$(".up_img_btn").prepend("<div class='img_load_text'><div uk-spinner='ratio: .6'></div><span>"
|
||
+ tot.toFixed(2) + "MB</span></div>");
|
||
|
||
$.each(files, function (i, file) {
|
||
var data = new FormData();
|
||
data.append('file', file);
|
||
policyName && data.append('policyName', policyName);
|
||
groupName && data.append('groupName', groupName);
|
||
|
||
$.ajax({
|
||
type: "POST",
|
||
url: `${Theme.moments.attachments_upload_api}`,
|
||
dataType: 'json',
|
||
data: data,
|
||
processData: false,
|
||
contentType: false,
|
||
beforeSend: function () {
|
||
$('input#topic_img_up').attr('disabled', 'disabled');
|
||
},
|
||
success: function (data) {
|
||
// 1. 获取上传后的地址
|
||
var src = data.metadata.annotations["storage.halo.run/uri"]
|
||
|| data.metadata.annotations["storage.halo.run/external-link"]
|
||
|| data.metadata.annotations["lskypro.plugin.halo.chenhe.me/image-link"];
|
||
|
||
// 2. 获取文件类型 (MIME Type)
|
||
// Halo 的 API 通常在 data.spec.mediaType 中返回类型,或者根据后缀判断
|
||
var mediaType = data.spec.mediaType || "";
|
||
var isVideo = mediaType.startsWith('video/') || /\.(mp4|webm|mov)$/i.test(src);
|
||
|
||
// 3. 动态生成预览 HTML
|
||
var mediaInner = isVideo
|
||
? `<video src="${src}" class="pix_video" preload="metadata" muted></video>`
|
||
: `<img src="${src}">`;
|
||
|
||
var media = `<div class="t_media_item" data-src="${src}" data-type="${mediaType}" data-thum="${src}">
|
||
<a class="topic-img-de"><i class="ri-subtract-line"></i></a>
|
||
${mediaInner}
|
||
</div>`;
|
||
|
||
$(".img_show").prepend(media);
|
||
|
||
num = $('.add_img_box .t_media_item').length;
|
||
$(".img_load_text").remove();
|
||
|
||
if (num < 10) $(".up_img_btn i").show();
|
||
$('input#topic_img_up').removeAttr('disabled');
|
||
},
|
||
error: function () {
|
||
cocoMessage.error("上传失败");
|
||
$(".img_load_text").remove();
|
||
$(".up_img_btn i").show();
|
||
$('input#topic_img_up').removeAttr('disabled');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
//同步修改检查数量的提示语
|
||
function check_image_num() {
|
||
var num = $('.add_img_box .t_media_item').length;
|
||
if (num > 8) {
|
||
cocoMessage.error("最多上传9个媒体文件");
|
||
return true;
|
||
}
|
||
}
|
||
|
||
//sortable事件 隐藏input
|
||
UIkit.util.on('.img_show', 'start', function (item) {
|
||
$(".up_img_btn").hide();
|
||
});
|
||
UIkit.util.on('.img_show', 'moved', function (item) {
|
||
var img_num = $('.add_img_box .t_media_item').length;
|
||
if (img_num < 9) {
|
||
$(".up_img_btn").show();
|
||
}
|
||
|
||
});
|
||
UIkit.util.on('.img_show', 'stop', function (item) {
|
||
var img_num = $('.add_img_box .t_media_item').length;
|
||
if (img_num < 9) {
|
||
$(".up_img_btn").show();
|
||
}
|
||
});
|
||
|
||
//获取媒体库图片/视频(功能不变)
|
||
$(document).on('click', '.up_from_media a', function () {
|
||
$(".attch_nav .pre").hide();
|
||
$(".attch_nav .nex").hide();
|
||
$(".attch_nav").attr('paged', '1');
|
||
$(".wp_get_media_list").empty();
|
||
$(".show_media_box").show();
|
||
loadMediaLibraryPage(1);
|
||
});
|
||
|
||
//媒体库分页(功能不变)
|
||
$(document).on('click', '.attch_nav a', function () {
|
||
$(".wp_get_media_list").empty();
|
||
var type = $(this).attr('class');
|
||
var paged = $(".attch_nav").attr('paged');
|
||
|
||
if (type == 'nex') {
|
||
paged = parseInt(paged) + 1;
|
||
} else if (type == 'pre' && paged) {
|
||
paged = parseInt(paged) - 1;
|
||
}
|
||
|
||
$(".attch_nav").attr('paged', paged);
|
||
loadMediaLibraryPage(paged);
|
||
});
|
||
|
||
//收起媒体库(无修改)
|
||
$(document).on('click', '.show_media_box .souqi', function () {
|
||
$(".show_media_box").hide();
|
||
$(".wp_get_media_list").empty();
|
||
});
|
||
|
||
//从媒体库插入图片/视频(删除按钮样式简化)
|
||
$(document).on('click', '.wp_get_media_list li', function () {
|
||
var num = $('.add_img_box .t_media_item').length;
|
||
if (num == 8) {
|
||
$("a.up_img_btn").hide();
|
||
}
|
||
if (check_image_num()) {
|
||
return false;
|
||
}
|
||
|
||
var src = $(this).attr('data-src');
|
||
var type = $(this).attr('data-type');
|
||
var mediaHtml = '';
|
||
|
||
if (type.startsWith('video/')) {
|
||
mediaHtml = `<div class="t_media_item" data-src="${src}" data-type="${type}">
|
||
<a class="topic-img-de"><i class="ri-subtract-line"></i></a>
|
||
<video src="${src}" class="pix_video" preload="metadata" muted></video>
|
||
</div>`;
|
||
} else {
|
||
var thum = $(this).children().attr('src') || $(this).children().attr('poster');
|
||
mediaHtml = `<div class="t_media_item" data-src="${src}" data-thum="${thum}" data-type="${type}">
|
||
<a class="topic-img-de"><i class="ri-subtract-line"></i></a>
|
||
<img src="${thum}">
|
||
</div>`;
|
||
}
|
||
$(".img_show").prepend(mediaHtml);
|
||
});
|
||
|
||
//删除图片/视频(保留事件冒泡修复)
|
||
$(document).on('click', '.topic-img-de', function (e) {
|
||
e.stopPropagation();
|
||
$(this).parent().remove();
|
||
var num = $('.add_img_box .t_media_item').length;
|
||
if (num < 9) {
|
||
$("a.up_img_btn").show();
|
||
}
|
||
});
|
||
|
||
//插入外部图片链接
|
||
$(document).on('click', '.up_from_cdn a', function () {
|
||
//$(".show_media_box .souqi").click();
|
||
$(".show_cdn_media").show();
|
||
|
||
});
|
||
|
||
//取消
|
||
$(document).on('click', 'a.img_link_cancel', function () {
|
||
$(".show_cdn_media").hide();
|
||
});
|
||
|
||
//插入图片或视频链接
|
||
$(document).on('click', 'a.img_link_btn', function () {
|
||
var img_url = $("#img_link_up").val().trim();
|
||
|
||
// 1. 扩展正则判断,支持视频后缀
|
||
if (!/\.(mp4|webm|jpg|png|gif|webp|jpeg)$/i.test(img_url) || img_url == '') {
|
||
cocoMessage.error("媒体格式不正确或链接为空!");
|
||
return false;
|
||
}
|
||
|
||
if (check_image_num()) {
|
||
return false;
|
||
}
|
||
|
||
var num = $('.add_img_box .t_media_item').length;
|
||
if (num == 8) {
|
||
$("a.up_img_btn").hide();
|
||
}
|
||
|
||
var src = img_url;
|
||
// 获取后缀名并转为小写
|
||
var ext = img_url.substring(img_url.lastIndexOf('.') + 1).toLowerCase();
|
||
|
||
// 2. 判定是否为视频
|
||
var isVideo = (ext === 'mp4' || ext === 'webm');
|
||
var type = isVideo ? 'video/' + ext : 'image/' + ext;
|
||
|
||
// 3. 根据类型生成预览 HTML
|
||
var mediaPreview = '';
|
||
if (isVideo) {
|
||
mediaPreview = `<video src="${src}" class="pix_video" preload="metadata" muted></video>`;
|
||
} else {
|
||
mediaPreview = `<img src="${src}">`;
|
||
}
|
||
|
||
var media = `<div class="t_media_item" data-src="${src}" data-thum="${src}" data-type="${type}">
|
||
<a class="topic-img-de"><i class="ri-subtract-line"></i></a>
|
||
${mediaPreview}
|
||
</div>`;
|
||
|
||
$(".img_show").prepend(media);
|
||
$("#img_link_up").val('');
|
||
});
|
||
|
||
//ajax获取我的地理位置
|
||
$(document).on('click', '.loca .laqu', function () {
|
||
var gaode_key = Theme.moments.gaode_key;
|
||
var ip = '';
|
||
$.ajax({
|
||
type: "get",
|
||
url: `/apis/uc.api.security.halo.run/v1alpha1/devices`,
|
||
contentType: "application/json",
|
||
success: function (data) {
|
||
if (data.length > 0) {
|
||
var ipAddress = data[0].device.spec.ipAddress;
|
||
if (!/^10\.|^192\.|^168\.|^172\./.test(ipAddress)) {
|
||
ip = data[0].device.spec.ipAddress
|
||
}
|
||
}
|
||
$.ajax({
|
||
type: "get",
|
||
url: `https://restapi.amap.com/v3/ip?ip=${ip}&key=${gaode_key}`,
|
||
contentType: "application/json",
|
||
beforeSend: function () {
|
||
$(".loca_text").text("数据拉取中..");
|
||
},
|
||
success: function (data) {
|
||
if (data.status == '1') {
|
||
var city = 'X市';
|
||
if (typeof data.city === 'string') {
|
||
city = data.city;
|
||
}
|
||
var province = 'X省';
|
||
if (typeof data.province === 'string') {
|
||
province = data.province;
|
||
}
|
||
var loca = "" + province + " · " + city + "";
|
||
$(".loca_text").html(loca).attr("state", '1'); //设置为开启
|
||
} else {
|
||
cocoMessage.error(data.info);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|
||
});
|
||
|
||
//插入自定义位置【点击关闭】
|
||
$(document).on('click', 'a.set_local_btn', function (e) {
|
||
var loca = $("#set_local").val();
|
||
var state = $(".loca_text").attr('state');
|
||
if (loca == '') {
|
||
cocoMessage.error("为空则不显示位置");
|
||
$(".loca_text").text('').attr("state", '0');
|
||
$("a.close_local").text('位置已关闭').css('color', '#ddd');
|
||
$.removeCookie('mylocal', { path: '/' });
|
||
} else {
|
||
$(".loca_text").text(loca).attr("state", '1');
|
||
$("a.close_local").text('位置已开启').css('color', '#8890cc');
|
||
$.cookie('mylocal', loca, { expires: 30, path: '/' });
|
||
}
|
||
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
UIkit.dropdown($('.local_box')).hide(0);
|
||
});
|
||
|
||
//插入自定义位置【input监控】
|
||
$(document).on('input', '#set_local', function () {
|
||
var loca = $(this).val();
|
||
var state = $(".loca_text").attr('state');
|
||
|
||
if (loca == '') {
|
||
cocoMessage.error("为空则不显示位置");
|
||
$(".loca_text").text('').attr("state", '0');
|
||
$("a.close_local").text('位置已关闭').css('color', '#ddd');
|
||
} else {
|
||
$(".loca_text").text(loca).attr("state", '1');
|
||
$("a.close_local").text('位置已开启,点击关闭').css('color', '#8890cc');
|
||
}
|
||
});
|
||
|
||
//关闭地理位置
|
||
$(document).on('click', 'a.close_local', function () {
|
||
$(".loca_text").text('').attr("state", '0');
|
||
$('#set_local, [name="set_local"]').val('');
|
||
$("a.close_local").text('位置已关闭').css('color', '#ddd');
|
||
});
|
||
|
||
$(document).on('click', '.loca_text', function () {
|
||
$("a.close_local").text('位置已开启,点击关闭').css('color', '#8890cc');
|
||
});
|
||
|
||
//发布更新瞬间
|
||
let isSubmittingMoment = false;
|
||
$(document).on('click', '.push_item', function () {
|
||
if (isSubmittingMoment) return false;
|
||
let closeLoading = null;
|
||
var content = $("#topic_content").val();
|
||
var catname = $(".t_cat_toogle span").text();
|
||
var loca = $(".loca_text").text();
|
||
var act = $('.push_item').attr('action');
|
||
var pid = $('.push_item').attr('pid');
|
||
var moment_type = $('.push_item').attr('type');
|
||
var visible = $(".simi a").attr('visible');
|
||
var min = Theme.moments.min_push_num;
|
||
|
||
if (min > 0) {
|
||
if (!content) {
|
||
cocoMessage.error("请输入内容");
|
||
return false;
|
||
}
|
||
if (content.length < min) {
|
||
cocoMessage.error("内容不得少于" + min + "个字");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
let tags = [];
|
||
if (catname) {
|
||
tags.push(catname);
|
||
content += `<p><a class="tag" href="?tag=${catname}" data-pjax="">${catname}</a></p>`;
|
||
}
|
||
|
||
get_moment_data(moment_type);
|
||
|
||
isSubmittingMoment = true;
|
||
|
||
const $btn = $(this);
|
||
$btn.attr('disabled', true).addClass('disabled');
|
||
|
||
function release() {
|
||
isSubmittingMoment = false;
|
||
$('.push_close, .push_item').prop('disabled', false);
|
||
$btn.removeClass('disabled');
|
||
}
|
||
|
||
if (act === 'push') {
|
||
|
||
let pushData = {
|
||
apiVersion: 'moment.halo.run/v1alpha1',
|
||
kind: 'Moment',
|
||
metadata: { generateName: "moment-" },
|
||
spec: {
|
||
content: {
|
||
html: content,
|
||
medium: moment_data,
|
||
raw: content
|
||
},
|
||
owner: "",
|
||
tags: tags,
|
||
visible: visible
|
||
}
|
||
};
|
||
|
||
if (loca && loca !== '数据拉取中..') {
|
||
pushData.metadata.annotations = { mylocal: loca };
|
||
}
|
||
|
||
closeLoading = cocoMessage.loading('正在发布...');
|
||
$('.push_close, .push_item').prop('disabled', true);
|
||
|
||
$.ajax({
|
||
type: "POST",
|
||
url: `/apis/${Theme.moments.push_api}/v1alpha1/moments`,
|
||
contentType: "application/json",
|
||
data: JSON.stringify(pushData),
|
||
success() {
|
||
closeLoading?.()
|
||
cocoMessage.success('发布成功!');
|
||
release();
|
||
closeMomentPushModal();
|
||
reloadCurrentPageByPjax('create');
|
||
},
|
||
error() {
|
||
$('.push_close, .push_item').prop('disabled', false);
|
||
closeLoading?.()
|
||
cocoMessage.error('发布失败!');
|
||
release();
|
||
}
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
if (act === 'update') {
|
||
|
||
let updateData = {
|
||
apiVersion: 'moment.halo.run/v1alpha1',
|
||
kind: 'Moment',
|
||
metadata: {
|
||
name: pid,
|
||
generateName: "moment-",
|
||
finalizers: ["tag-moment-protection", "moment-protection"],
|
||
version: parseInt($('.push_item').attr('version'))
|
||
},
|
||
spec: {
|
||
content: {
|
||
html: content,
|
||
medium: moment_data,
|
||
raw: content
|
||
},
|
||
owner: $('.push_item').attr('owner'),
|
||
releaseTime: $('.push_item').attr('releaseTime'),
|
||
tags: tags,
|
||
visible: visible
|
||
}
|
||
};
|
||
|
||
if (loca && loca !== '数据拉取中..') {
|
||
updateData.metadata.annotations = { mylocal: loca };
|
||
}
|
||
|
||
closeLoading = cocoMessage.loading('正在更新...');
|
||
$('.push_close, .push_item').prop('disabled', true);
|
||
|
||
$.ajax({
|
||
type: "PUT",
|
||
url: `/apis/${Theme.moments.api}/v1alpha1/moments/${pid}`,
|
||
contentType: "application/json",
|
||
data: JSON.stringify(updateData),
|
||
success() {
|
||
closeLoading?.()
|
||
cocoMessage.success('更新成功!');
|
||
release();
|
||
closeMomentPushModal();
|
||
reloadCurrentPageByPjax('update');
|
||
},
|
||
error() {
|
||
closeLoading?.()
|
||
cocoMessage.error('更新失败!');
|
||
$('.push_close, .push_item').prop('disabled', false);
|
||
release();
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
//获取片刻类型参数
|
||
function get_moment_data(type) {
|
||
moment_data = [];
|
||
switch (type) {
|
||
case "image":
|
||
$(".t_media_item").each(function () {
|
||
var src = $(this).attr('data-src');
|
||
var type = $(this).attr('data-type');
|
||
var obj = {
|
||
url: src,
|
||
type: "PHOTO",
|
||
originType: type
|
||
}
|
||
moment_data.push(obj); //图片
|
||
});
|
||
break;
|
||
case "card":
|
||
$(".card_sortble .moment_card_item").each(function () {
|
||
var pid = $(this).attr('pid');
|
||
var type = $(this).attr('type');
|
||
var obj = {
|
||
url: pid,
|
||
type: "POST",
|
||
originType: type
|
||
}
|
||
moment_data.push(obj); //卡片
|
||
});
|
||
break;
|
||
case "audio":
|
||
get_audio_data();
|
||
break;
|
||
case "video":
|
||
get_video_data();
|
||
break;
|
||
}
|
||
}
|
||
|
||
//片刻音乐参数
|
||
function get_audio_data() {
|
||
var type = $('.audio_choose li.uk-active a').attr('au_type');
|
||
if (type == 'local') {
|
||
var url = $('input#moment_audio_url').val();
|
||
var obj = {
|
||
url: url,
|
||
type: "AUDIO",
|
||
originType: 'audio/' + type
|
||
}
|
||
} else {
|
||
var n_id = $('input#moment_audio_api').val();
|
||
var obj = {
|
||
url: n_id,
|
||
type: "AUDIO",
|
||
originType: 'audio/' + type
|
||
}
|
||
}
|
||
moment_data.push(obj);
|
||
}
|
||
|
||
//片刻视频参数
|
||
function get_video_data() {
|
||
var type = $('.video_choose li.uk-active a').attr('vi_type');
|
||
if (type == 'local') {
|
||
var url = $('input#moment_video_url').val();
|
||
var obj = {
|
||
url: url,
|
||
type: "VIDEO",
|
||
originType: 'video/mp4'
|
||
}
|
||
|
||
} else if (type == 'bili') {
|
||
var bvid = $('input#moment_video_bili').val();
|
||
var obj = {
|
||
url: bvid,
|
||
type: "VIDEO",
|
||
originType: 'video/bili'
|
||
}
|
||
}
|
||
moment_data.push(obj);
|
||
|
||
}
|
||
|
||
//片刻空值提示
|
||
function get_moment_error(type) {
|
||
switch (type) {
|
||
case "card":
|
||
var v = $('.show_card .moment_card_item');
|
||
if (v.length == 0) {
|
||
return false;
|
||
}
|
||
break;
|
||
case "audio":
|
||
var au_type = $('.audio_choose li.uk-active a').attr('au_type');
|
||
var url = $('input#moment_audio_url').val(); //歌曲链接
|
||
var title = $('input#moment_audio_name').val(); //标题
|
||
var cover = $('.loacl_audio .audio_left img').length; //封面
|
||
if (au_type == 'local') {
|
||
if (url == '' || title == '' || cover == 0) {
|
||
return false;
|
||
}
|
||
} else {
|
||
var n_id = $('input#moment_audio_api').val();
|
||
if (n_id == '') {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
case "video":
|
||
var vi_type = $('.video_choose li.uk-active a').attr('vi_type');
|
||
var url = $('input#moment_video_url').val();
|
||
if (vi_type == 'local') {
|
||
if (url == '') {
|
||
return false;
|
||
}
|
||
} else {
|
||
var bvid = $('input#moment_video_bili').val();
|
||
if (bvid == '') {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// ajax分类筛选 moment
|
||
$(document).on('click', '.moment_cat_nav ul li a', function () {
|
||
var $this = $(this);
|
||
if ($this.hasClass('disabled')) {
|
||
return false;
|
||
}
|
||
$('.moment_cat_nav ul li a').addClass('disabled');
|
||
|
||
cacheCommentFormForAjax();
|
||
|
||
// --- 1. 保存旧内容---
|
||
var $momentList = $(".moment_list");
|
||
var pageSnapshot = createAjaxPageSnapshot({
|
||
$content: $momentList,
|
||
paginationSelector: '#t_pagination'
|
||
});
|
||
|
||
$(".moment_list").empty();
|
||
$('#t_pagination a').hide();
|
||
|
||
var cat = $this.attr('data');
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: cat,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
showListLoading('.moment_list');
|
||
hidePagination('#t_pagination');
|
||
},
|
||
success: function (data) {
|
||
setCategoryLinkActive($this);
|
||
$('.moment_list .loading_box').remove();
|
||
var result = $(data).find(".moment_list .p_item");
|
||
$(".moment_list").append(result.fadeIn(300));
|
||
|
||
updateLoadMorePagination('#t_pagination', '.moment_list', data);
|
||
getMomentAudio();
|
||
initAgree();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
$('.moment_cat_nav ul li a').removeClass('disabled');
|
||
initializeMomentFold();
|
||
// if (typeof modify_moment_video_size === 'function') modify_moment_video_size();
|
||
if (cat.indexOf('tag=') !== -1) {
|
||
const displayUrl = removePageParamFromUrl(cat);
|
||
history.replaceState({ url: displayUrl }, '', displayUrl);
|
||
} else {
|
||
history.replaceState({ url: cat }, '', '/');
|
||
}
|
||
},
|
||
error: function () {
|
||
$('.moment_cat_nav ul li a').removeClass('disabled');
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
});
|
||
|
||
// ajax分类筛选朋友圈
|
||
$(document).on('click', '.friends_cat_nav .cat-link', function () {
|
||
var $this = $(this);
|
||
if ($this.hasClass('disabled')) {
|
||
return false;
|
||
}
|
||
$('.friends_cat_nav .cat-link').addClass('disabled');
|
||
|
||
// 保留原有的表单重置逻辑(如果不需要可删除)
|
||
cacheCommentFormForAjax();
|
||
|
||
// --- 1. 保存旧内容---
|
||
var $momentList = $(".moment_list");
|
||
var pageSnapshot = createAjaxPageSnapshot({
|
||
$content: $momentList,
|
||
paginationSelector: '#t_pagination'
|
||
});
|
||
|
||
// 清空列表并隐藏分页
|
||
$(".moment_list").empty();
|
||
$('#t_pagination a').hide();
|
||
|
||
// 获取目标 URL(注意这里用的是 data-href)
|
||
var url = $this.attr('data-href');
|
||
if (!url) {
|
||
$('.friends_cat_nav .cat-link').removeClass('disabled');
|
||
return;
|
||
}
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: url,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
showListLoading('.moment_list');
|
||
hidePagination('#t_pagination');
|
||
},
|
||
success: function (data) {
|
||
setCategoryLinkActive($this);
|
||
// 移除加载动画
|
||
$('.moment_list .loading_box').remove();
|
||
|
||
// 提取并插入新的列表项
|
||
var result = $(data).find(".moment_list .p_item");
|
||
$(".moment_list").append(result.fadeIn(300));
|
||
|
||
// 处理分页逻辑
|
||
updateLoadMorePagination('#t_pagination', '.moment_list', data);
|
||
|
||
// --- 功能初始化区域(根据您的实际情况启用/禁用) ---
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
$('.friends_cat_nav .cat-link').removeClass('disabled');
|
||
initializeMomentFold();
|
||
initDoubanDetailLinks();
|
||
|
||
// 更新浏览器历史状态
|
||
if (typeof url === 'string') {
|
||
const displayUrl = removePageParamFromUrl(url.replace('author', 'tag'));
|
||
history.replaceState({ url: displayUrl }, '', displayUrl);
|
||
}
|
||
},
|
||
error: function () {
|
||
$('.friends_cat_nav .cat-link').removeClass('disabled');
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
});
|
||
|
||
//ajax加载上一页
|
||
$(document).on('click', '#prev_pagination a', function () {
|
||
const $btn = $(this);
|
||
if ($btn.hasClass('disabled')) return false;
|
||
|
||
const href = $btn.attr('data');
|
||
const context = getPreviousPageContext();
|
||
if (!href || !context) return false;
|
||
|
||
const previousPage = parseInt($btn.attr('data-page'), 10) || Math.max(getPageNumberFromUrl(window.location.href) - 1, 1);
|
||
const $pagingArea = $('#prev_pagination .post-paging');
|
||
const pageSnapshot = createAjaxPageSnapshot({
|
||
$content: context.$list,
|
||
paginationSelector: '#prev_pagination',
|
||
paginationInsert: 'prepend',
|
||
$paginationAnchor: context.$list,
|
||
$pagingArea: $pagingArea
|
||
});
|
||
const scrollTopBeforeLoad = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||
const listHeightBeforeLoad = context.$list[0] ? context.$list[0].scrollHeight : 0;
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: href,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
$btn.addClass('disabled').attr('aria-disabled', 'true');
|
||
$pagingArea.html('<div uk-spinner></div>');
|
||
},
|
||
success: function (data) {
|
||
const $items = context.extract(data);
|
||
if (!$items.length) {
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
return;
|
||
}
|
||
|
||
restoreAjaxPageSnapshot(pageSnapshot, { content: false, pagination: false, paging: true });
|
||
context.insert($items, data);
|
||
context.afterLoad();
|
||
initPreviousPageButton(previousPage - 1);
|
||
syncPageParamToUrl(previousPage);
|
||
|
||
const listHeightAfterLoad = context.$list[0] ? context.$list[0].scrollHeight : listHeightBeforeLoad;
|
||
const heightDelta = Math.max(0, listHeightAfterLoad - listHeightBeforeLoad);
|
||
window.scrollTo(0, scrollTopBeforeLoad + heightDelta - 50);
|
||
$body.animate({ scrollTop: '-=100' }, 500);
|
||
},
|
||
error: function () {
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
|
||
return false;
|
||
});
|
||
|
||
function updatePageJumpStepperState(input) {
|
||
const value = Number(input.value);
|
||
const min = Number(input.min);
|
||
const max = Number(input.max);
|
||
const $stepper = $(input).closest('.page-jump-input-wrap');
|
||
|
||
$stepper.find('.page-jump-step-up').prop('disabled', Number.isFinite(value) && value >= max);
|
||
$stepper.find('.page-jump-step-down').prop('disabled', !Number.isFinite(value) || value <= min);
|
||
}
|
||
|
||
function validatePageJumpInput(input, notify) {
|
||
const value = input.value.trim();
|
||
const min = input.min === '' ? null : Number(input.min);
|
||
const max = input.max === '' ? null : Number(input.max);
|
||
const page = Number(value);
|
||
let message = '';
|
||
|
||
if (!value) {
|
||
message = '请输入页码';
|
||
} else if (!Number.isInteger(page)) {
|
||
message = '请输入有效页码';
|
||
} else if (Number.isFinite(min) && page < min) {
|
||
message = `页码不能小于 ${min}`;
|
||
} else if (Number.isFinite(max) && page > max) {
|
||
message = `页码不能大于 ${max}`;
|
||
}
|
||
|
||
const wasInvalid = input.dataset.pageJumpInvalid === 'true';
|
||
input.setCustomValidity(message);
|
||
input.dataset.pageJumpInvalid = message ? 'true' : 'false';
|
||
|
||
if (notify && message && message !== '请输入页码' && !wasInvalid
|
||
&& window.cocoMessage && typeof window.cocoMessage.warning === 'function') {
|
||
window.cocoMessage.warning(message);
|
||
}
|
||
|
||
return !message;
|
||
}
|
||
|
||
function stepPageJumpInput(input, direction) {
|
||
const min = Number(input.min);
|
||
const max = Number(input.max);
|
||
const step = Number(input.step) > 0 ? Number(input.step) : 1;
|
||
const current = Number(input.value);
|
||
const value = Number.isFinite(current) ? current + direction * step : min;
|
||
|
||
input.value = String(Math.min(max, Math.max(min, value)));
|
||
input.dispatchEvent(new Event('input', { bubbles: true }));
|
||
input.focus();
|
||
}
|
||
|
||
function initPageJumpSteppers() {
|
||
$('.page-jump-input').each(function () {
|
||
updatePageJumpStepperState(this);
|
||
});
|
||
}
|
||
|
||
$(document).on('click', '.page-jump-step', function (event) {
|
||
event.preventDefault();
|
||
if (this.disabled) return;
|
||
|
||
const input = $(this).closest('.page-jump-input-wrap').find('.page-jump-input')[0];
|
||
if (input) {
|
||
stepPageJumpInput(input, $(this).hasClass('page-jump-step-up') ? 1 : -1);
|
||
}
|
||
});
|
||
|
||
$(document).on('keydown', '.page-jump-input', function (event) {
|
||
if (event.ctrlKey || event.metaKey || event.altKey) return;
|
||
|
||
const allowedKeys = ['Backspace', 'Delete', 'Tab', 'Enter', 'Escape', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
|
||
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
|
||
event.preventDefault();
|
||
stepPageJumpInput(this, event.key === 'ArrowUp' ? 1 : -1);
|
||
return;
|
||
}
|
||
if (!allowedKeys.includes(event.key) && !/^[0-9]$/.test(event.key)) {
|
||
event.preventDefault();
|
||
}
|
||
});
|
||
|
||
$(document).on('input', '.page-jump-input', function () {
|
||
this.value = this.value.replace(/[^0-9]/g, '').replace(/^0+(?=\d)/, '');
|
||
validatePageJumpInput(this, true);
|
||
updatePageJumpStepperState(this);
|
||
});
|
||
|
||
// 跳转到指定页:沿用当前 URL 的分类或标签参数,通过 PJAX 加载目标页。
|
||
$(document).on('submit', '.page-jump-form', function (event) {
|
||
event.preventDefault();
|
||
const $form = $(this);
|
||
const input = $form.find('.page-jump-input')[0];
|
||
validatePageJumpInput(input, true);
|
||
if (!this.checkValidity()) {
|
||
input.focus();
|
||
if (typeof input.reportValidity === 'function') input.reportValidity();
|
||
return false;
|
||
}
|
||
|
||
const targetPage = parseInt($form.find('.page-jump-input').val(), 10);
|
||
const href = buildPageUrlFromCurrent(targetPage);
|
||
|
||
if (window.pjax && typeof window.pjax.loadUrl === 'function') {
|
||
window.pjax.loadUrl(href);
|
||
} else {
|
||
window.location.assign(href);
|
||
}
|
||
|
||
return false;
|
||
});
|
||
|
||
//ajax加载片刻
|
||
$(document).on('click', '#t_pagination a', function () {
|
||
var href = $(this).attr('data');
|
||
const currentPage = getPageNumberFromUrl(href);
|
||
const $pagingArea = $('#t_pagination .post-paging');
|
||
const pageSnapshot = createAjaxPageSnapshot({ $pagingArea: $pagingArea });
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: href,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
$('#t_pagination .post-paging').html('<div uk-spinner></div>');
|
||
},
|
||
success: function (posts) {
|
||
if (posts) {
|
||
var result = $(posts).find(".moment_list .p_item");
|
||
$(".moment_list").append(result.fadeIn(300));
|
||
refreshAjaxPostList();
|
||
updateLoadMorePagination('#t_pagination', '.moment_list', posts);
|
||
if (result.length) {
|
||
$body.animate({ scrollTop: result.first().offset().top - 58 }, 500);
|
||
}
|
||
getMomentAudio();
|
||
initAgree();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
initializeMomentFold();
|
||
initDoubanDetailLinks();
|
||
syncPageParamToUrl(currentPage);
|
||
} else {
|
||
$('#t_pagination a').hide();
|
||
}
|
||
},
|
||
error: function () {
|
||
restorePagingSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
|
||
// AJAX分类切换图库
|
||
$(document).ready(function () {
|
||
$(document).on('click', '.photos_cat_nav ul li a', function (e) {
|
||
var $this = $(this);
|
||
|
||
if ($this.hasClass('disabled') || $this.hasClass('active')) {
|
||
return false;
|
||
}
|
||
|
||
var url = $this.data('href');
|
||
if (!url) {
|
||
return false;
|
||
}
|
||
|
||
var displayUrl = removePageParamFromUrl(url);
|
||
// page 参数现在统一通过 removePageParamFromUrl 清理。
|
||
/*
|
||
try {
|
||
var photoUrl = new URL(url, window.location.origin);
|
||
photoUrl.searchParams.delete('page');
|
||
displayUrl = decodeURI(photoUrl.pathname + photoUrl.search + photoUrl.hash);
|
||
} catch (e) { }
|
||
*/
|
||
|
||
$('.photos_cat_nav ul li a').addClass('disabled');
|
||
|
||
// --- 1. 保存旧内容 (关键修改) ---
|
||
var $photosItem = $("#photos_item");
|
||
var pageSnapshot = createAjaxPageSnapshot({
|
||
$content: $photosItem,
|
||
paginationSelector: '#p_pagination'
|
||
});
|
||
|
||
$photosItem.empty();
|
||
$('#p_pagination a').hide();
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: url,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
showListLoading("#photos_item", PHOTO_LIST_LOADING_HTML);
|
||
hidePagination('#p_pagination');
|
||
},
|
||
success: function (data) {
|
||
setCategoryLinkActive($this);
|
||
var $data = $(data);
|
||
|
||
var newContent = $data.find("#photos_item").html();
|
||
$("#photos_item").html(newContent);
|
||
|
||
updateLoadMorePagination('#p_pagination', '#photos_item', data);
|
||
|
||
if (typeof pix !== 'undefined' && pix.initGalleryPhotos) {
|
||
pix.initGalleryPhotos();
|
||
}
|
||
if (typeof lazyLoadInstance !== 'undefined') {
|
||
lazyLoadInstance.update();
|
||
}
|
||
if ($('.gallery-photos').length > 0 && typeof waterfall === 'function') {
|
||
waterfall('.gallery-photos');
|
||
}
|
||
|
||
$('.photos_cat_nav ul li a').removeClass('disabled');
|
||
|
||
history.replaceState({ path: displayUrl }, '', displayUrl);
|
||
},
|
||
error: function () {
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
$('.photos_cat_nav ul li a').removeClass('disabled');
|
||
}
|
||
});
|
||
|
||
return false;
|
||
});
|
||
});
|
||
|
||
//ajax加载图库
|
||
$(document).on('click', '#p_pagination a', function () {
|
||
var href = $(this).attr('data');
|
||
const currentPage = getPageNumberFromUrl(href);
|
||
const $pagingArea = $('#p_pagination .post-paging');
|
||
const pageSnapshot = createAjaxPageSnapshot({ $pagingArea: $pagingArea });
|
||
const targetOffsetTop = $('#p_pagination a').offset().top;
|
||
$.ajax({
|
||
type: "GET",
|
||
url: href,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
$('#p_pagination .post-paging').html('<div uk-spinner></div>');
|
||
},
|
||
success: function (photos) {
|
||
if (photos) {
|
||
var result = $(photos).find(".norpost_list .gallery-photo");
|
||
$(".gallery-photos").append(result.fadeIn(300));
|
||
updateLoadMorePagination('#p_pagination', '#photos_item', photos);
|
||
$body.animate({ scrollTop: targetOffsetTop - 358 }, 500);
|
||
pix.initGalleryPhotos();
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
syncPageParamToUrl(currentPage);
|
||
} else {
|
||
$('#p_pagination a').hide();
|
||
}
|
||
},
|
||
error: function () {
|
||
restorePagingSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
|
||
//阅读更多按钮
|
||
$(document).on('click', 'a.show-more-btn', function () {
|
||
var t = $(this);
|
||
t.prev().show();
|
||
t.next().show();
|
||
t.siblings('.dotd').hide();
|
||
t.hide();
|
||
});
|
||
|
||
$(document).on('click', 'a.read-less-btn', function () {
|
||
var t = $(this);
|
||
t.siblings('.rm_hidden').hide();
|
||
t.siblings('.dotd').show();
|
||
t.prev().show();
|
||
t.hide();
|
||
});
|
||
|
||
|
||
//ajax加载评论
|
||
$(document).on('click', '.show_comment', function () {
|
||
$('.blog_list_inner').css('min-height', 'calc(100vh)');
|
||
var pid = $(this).attr('pid');
|
||
var other = $(this).parents('.moment_item').siblings('div');
|
||
$.each(other, function (name, value) {
|
||
|
||
//遍历每个 回复表单
|
||
var otherid = $(this).find('.show_comment').attr('pid');
|
||
$("#halo-comment-" + otherid).hide();
|
||
|
||
});
|
||
$(`#halo-comment-${pid}`).css('display', $(`#halo-comment-${pid}`).css('display') == 'block' ? 'none' : 'block');
|
||
|
||
});
|
||
|
||
//片刻点赞
|
||
$(document).on('click', '.up_like ', function () {
|
||
|
||
if ($(this).hasClass('done')) {
|
||
cocoMessage.info("地久天长");
|
||
return false;
|
||
} else {
|
||
$(this).addClass('done');
|
||
var pid = $(this).data("id");
|
||
var key = $(this).data("key");
|
||
let agreeArr = localStorage.getItem(`pix.upvoted.${key}.names`)
|
||
? JSON.parse(localStorage.getItem(`pix.upvoted.${key}.names`))
|
||
: [];
|
||
rateHolder = $(this).children('span');
|
||
iconHolder = $(this).children('i');
|
||
$.ajax({
|
||
type: 'post',
|
||
contentType: "application/json; charset=utf-8",
|
||
url: '/apis/api.halo.run/v1alpha1/trackers/upvote',
|
||
data: JSON.stringify({
|
||
group: key == "moment" ? "moment.halo.run" : "content.halo.run",
|
||
plural: key == "moment" ? "moments" : "posts",
|
||
name: pid,
|
||
}),
|
||
success: function (data) {
|
||
$(iconHolder).toggleClass('ri-heart-2-fill');
|
||
var num = $(rateHolder).text();
|
||
$(rateHolder).text(++num);
|
||
agreeArr.push(pid);
|
||
const val = JSON.stringify(agreeArr);
|
||
localStorage.setItem(`pix.upvoted.${key}.names`, val);
|
||
cocoMessage.success("卿卿与黄");
|
||
}
|
||
}); // end ajax
|
||
|
||
}
|
||
});
|
||
|
||
function initAgree() {
|
||
var agreeAnnius = $('.up_like')
|
||
if (agreeAnnius.length > 0) {
|
||
let agreeArr = JSON.parse(localStorage.getItem(`pix.upvoted.${$(agreeAnnius[0]).data("key")}.names`))
|
||
for (var i = 0; i < agreeAnnius.length; i++) {
|
||
let pid = $(agreeAnnius[i]).attr('data-id');
|
||
if (agreeArr != null) {
|
||
let flag = agreeArr.includes(pid);
|
||
if (flag) {
|
||
$(agreeAnnius[i]).addClass('done');
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
function getMomentAudio() {
|
||
var audioList = $('.pix_player.qt')
|
||
if (audioList.length > 0) {
|
||
for (var i = 0; i < audioList.length; i++) {
|
||
let id = $(audioList[i]).attr('id');
|
||
let type = $(audioList[i]).attr('type');
|
||
var result = type.substring(type.indexOf("audio/") + 6);
|
||
if (id != null && id != '') {
|
||
var api = `${Theme.play.pix_mu_api || 'https://api.i-meto.com/meting/api'}?type=song&id=:id`
|
||
var meta = {
|
||
type: result,
|
||
id: id,
|
||
}
|
||
let url = api.replace(":id", meta.id);
|
||
$.ajax({
|
||
type: "get",
|
||
url: url,
|
||
success: function (res) {
|
||
var html = ''
|
||
if (res.length > 0) {
|
||
let author = res[0].author;
|
||
let pic = res[0].pic;
|
||
let title = res[0].title;
|
||
let url = res[0].url;
|
||
let lrc = res[0].lrc;
|
||
html = `<div class="player_thum">
|
||
<img src="${pic}">
|
||
</div>
|
||
<div class="player_meta">
|
||
<div class="title"><span class="name">${title}</span><span class="author">${author}</span></div>
|
||
<div class="player_tool">
|
||
<div class="player_time"><div class="current_time"></div><span></span><div class="total_time"></div></div>
|
||
</div>
|
||
</div>
|
||
<a class="play_btn" data ="${url}" lrc="${lrc}"><i class="ri-play-line"></i></a>
|
||
<div class="play_bg"><img src="${pic}"></div>`;
|
||
} else {
|
||
html = '音乐参数错误';
|
||
}
|
||
$('#' + id).html(html);
|
||
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
// ajax分类筛选 posts(首页片刻时改这个)
|
||
$(document).on('click', '.posts_cat_nav ul li a', function (e) {
|
||
e.preventDefault();
|
||
var $this = $(this);
|
||
var t = $('.posts_cat_nav ul li a');
|
||
|
||
if (t.hasClass('disabled')) {
|
||
return false;
|
||
}
|
||
$('.posts_cat_nav ul li a').addClass('disabled');
|
||
|
||
// --- 1. 保存旧内容---
|
||
var $momentList = $(".norpost_list");
|
||
var pageSnapshot = createAjaxPageSnapshot({
|
||
$content: $momentList,
|
||
paginationSelector: '#pagination'
|
||
});
|
||
|
||
$(".norpost_list").empty();
|
||
$('#pagination a').hide();
|
||
|
||
var cat = $(this).attr('data');
|
||
// 替换:获取a标签内的中文文本并去除空格
|
||
var tag = $(this).text().trim();
|
||
var displayUrl = '/archives';
|
||
try {
|
||
const archiveUrl = new URL(cat, window.location.origin);
|
||
archiveUrl.searchParams.delete('page');
|
||
if (archiveUrl.pathname === '/archives') {
|
||
displayUrl = decodeURI(archiveUrl.pathname + archiveUrl.search + archiveUrl.hash);
|
||
} else if (tag !== '全部' && tag !== '') {
|
||
displayUrl = '/archives?tag=' + encodeURIComponent(tag);
|
||
}
|
||
} catch (e) {
|
||
if (tag !== '全部' && tag !== '') {
|
||
displayUrl = '/archives?tag=' + encodeURIComponent(tag);
|
||
}
|
||
}
|
||
displayUrl = removePageParamFromUrl(displayUrl);
|
||
|
||
$.ajax({
|
||
type: "GET",
|
||
url: cat, // 完全保留原有请求URL,不修改
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
showListLoading('.norpost_list');
|
||
hidePagination('#pagination');
|
||
},
|
||
success: function (data) {
|
||
setCategoryLinkActive($this);
|
||
$('#pagination a').text(Theme.site_page);
|
||
var result = $(data).find(".norpost_list").children();
|
||
$(".norpost_list").append(result.fadeIn(300));
|
||
refreshAjaxPostList();
|
||
|
||
updateLoadMorePagination('#pagination', '.norpost_list', data, '.arc_pagenav');
|
||
|
||
$('.norpost_list .loading_box').remove();
|
||
initAgree();
|
||
lazyLoadInstance.update();
|
||
$('.posts_cat_nav ul li a').removeClass('disabled');
|
||
|
||
history.replaceState({ url: displayUrl }, '', displayUrl);
|
||
},
|
||
error: function () {
|
||
$('.posts_cat_nav ul li a').removeClass('disabled');
|
||
restoreAjaxSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
});
|
||
|
||
//ajax加载文章
|
||
$('body').on('click', '#pagination a', function () {
|
||
const $pagingArea = $('#pagination .post-paging');
|
||
const pageSnapshot = createAjaxPageSnapshot({ $pagingArea: $pagingArea });
|
||
var href = $(this).attr('data');
|
||
const currentPage = getPageNumberFromUrl(href);
|
||
$.ajax({
|
||
type: "GET",
|
||
url: href,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
$('#pagination .post-paging').html('<div uk-spinner></div>');
|
||
},
|
||
success: function (data) {
|
||
if (data) {
|
||
var result = $(data).find(".norpost_list ").children();
|
||
$('.norpost_list').append($(result).fadeIn(400));
|
||
|
||
refreshAjaxPostList();
|
||
updateLoadMorePagination('#pagination', '.norpost_list', data, '.arc_pagenav');
|
||
if (result.length) {
|
||
$body.animate({ scrollTop: result.first().offset().top - 58 }, 500);
|
||
}
|
||
initAgree()
|
||
if (typeof lazyLoadInstance !== 'undefined') lazyLoadInstance.update();
|
||
syncPageParamToUrl(currentPage);
|
||
} else {
|
||
$("#pagination a").hide();
|
||
}
|
||
},
|
||
error: function () {
|
||
restorePagingSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
|
||
// ajax加载分类页面文章
|
||
$('body').on('click', '.arc_pagenav a', function () {
|
||
// 【新增】保存分页区域的原始HTML,用于失败时恢复
|
||
const $pagingArea = $('.arc_pagenav');
|
||
const pageSnapshot = createAjaxPageSnapshot({ $pagingArea: $pagingArea });
|
||
var href = $(this).attr('data');
|
||
const currentPage = getPageNumberFromUrl(href);
|
||
|
||
$(this).hide();
|
||
var content = $('.norpost_list');
|
||
if (href != undefined) {
|
||
$.ajax({
|
||
type: "GET",
|
||
url: href,
|
||
headers: HTML_PAGE_AJAX_HEADERS,
|
||
beforeSend: function () {
|
||
$('.arc_pagenav').append('<div uk-spinner></div>');
|
||
},
|
||
success: function (data) {
|
||
var post = $(data).find(".norpost_list").children();
|
||
content.append(post.fadeIn(300));
|
||
|
||
refreshAjaxPostList();
|
||
|
||
var newhref = $(data).find(".arc_pagenav a").attr("data"); //找出新的下一页链接
|
||
if (newhref != undefined) {
|
||
$(".arc_pagenav a").attr("data", newhref);
|
||
$('.arc_pagenav a').show();
|
||
} else {
|
||
$(".arc_pagenav a").hide(); //如果没有下一页了,隐藏
|
||
}
|
||
$('.arc_pagenav .uk-spinner').remove();
|
||
$body.animate({ scrollTop: post.offset().top - 58 }, 500);
|
||
initAgree()
|
||
lazyLoadInstance.update();
|
||
syncPageParamToUrl(currentPage);
|
||
},
|
||
error: function () {
|
||
restorePagingSnapshotWithError(pageSnapshot);
|
||
}
|
||
});
|
||
}
|
||
|
||
return false;
|
||
|
||
});
|
||
|
||
function loginUrl() {
|
||
window.location.href = `/login?redirect_uri=${encodeURIComponent(window.location.pathname)}`;
|
||
}
|
||
|
||
$(document).on('mouseenter', '.lbc .left_menu_box ul li a , body.mod_third_s .left_menu_box ul li a', function (event) {
|
||
var title = $(this).find('.nav_title').text();
|
||
$(this).append("<span class='menu_tips'>" + title + "</span>");
|
||
});
|
||
|
||
$(document).on('mouseleave', '.lbc .left_menu_box ul li a , body.mod_third_s .left_menu_box ul li a', function (event) {
|
||
$(this).find('.menu_tips').remove();
|
||
|
||
});
|
||
|
||
//滚动
|
||
$(document).ready(function (e) {
|
||
$(window).scroll(function () {
|
||
|
||
var b = $(window).scrollTop(); //监控窗口已滚动的距离;
|
||
|
||
if (b > 190) {
|
||
|
||
$('.top_bar').addClass('mobile_active');
|
||
|
||
} else {
|
||
$('.top_bar').removeClass('mobile_active');
|
||
}
|
||
|
||
if (b > 1500) {
|
||
$('a.go_top').addClass('show');
|
||
$('a.tool_top').addClass('show');
|
||
} else {
|
||
$('a.go_top').removeClass('show');
|
||
$('a.tool_top').removeClass('show');
|
||
}
|
||
|
||
});
|
||
});
|
||
|
||
$.fn.autoTextarea = function (options) {
|
||
var defaults = {
|
||
maxHeight: null,//文本框是否自动撑高,默认:null,不自动撑高;如果自动撑高必须输入数值,该值作为文本框自动撑高的最大高度
|
||
minHeight: 50
|
||
};
|
||
var opts = $.extend({}, defaults, options);
|
||
return $(this).each(function () {
|
||
$(this).bind("paste cut keydown keyup focus blur", function () {
|
||
var height, style = this.style;
|
||
this.style.height = opts.minHeight + 'px';
|
||
if (this.scrollHeight > opts.minHeight) {
|
||
if (opts.maxHeight && this.scrollHeight > opts.maxHeight) {
|
||
height = opts.maxHeight;
|
||
style.overflowY = 'scroll';
|
||
} else {
|
||
height = this.scrollHeight;
|
||
style.overflowY = 'hidden';
|
||
}
|
||
style.height = height + 'px';
|
||
}
|
||
});
|
||
});
|
||
};
|
||
|
||
$('body').on('click', '.com_msg_btn', function () {
|
||
|
||
var num = $(this).attr('check');
|
||
if (num == 0) {
|
||
return false;
|
||
}
|
||
$.ajax({
|
||
type: 'POST',
|
||
dataType: 'json',
|
||
url: Theme.ajaxurl,
|
||
data: {
|
||
'action': 'up_unread_msg',
|
||
},
|
||
beforeSend: function () {
|
||
|
||
},
|
||
success: function (data) {
|
||
if (data.code == '0') {
|
||
$('small.f_unread_num').remove();
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
});
|
||
|
||
});
|
||
|
||
//搜索类型
|
||
$('body').on('click', '.s_set_box a', function () {
|
||
var type = $(this).attr('data');
|
||
$(this).addClass('active').siblings('a').removeClass('active');
|
||
$('form#index_search input[type="hidden"]').val(type);
|
||
$.cookie('s_type', type, { expires: 30, path: '/' });
|
||
});
|
||
|
||
$('body').on('click', '.top_s_box a', function () {
|
||
UIkit.dropdown('.s_set_box').hide(false);
|
||
var data = $(this).attr('data');
|
||
var type = $(this).text();
|
||
$('.set_text').text(type);
|
||
$('form#top_search input[type="hidden"]').val(data);
|
||
});
|
||
|
||
//黑暗模式
|
||
$('body').on('click', '.t_dark a', function () {
|
||
var t = $('html');
|
||
if (t.hasClass('dark')) {
|
||
$.cookie('dark', 'normal', { path: '/', expires: 30 });
|
||
} else {
|
||
$.cookie('dark', 'dark', { path: '/', expires: 30 });
|
||
}
|
||
t.toggleClass('dark');
|
||
|
||
});
|
||
//片刻管理按钮
|
||
|
||
$(document).on('mouseenter', '.post_control_btn', function (event) {
|
||
var a = $(this).siblings('.post_control_box');
|
||
a.addClass('show');
|
||
});
|
||
|
||
$(document).on('mouseleave', '.post_control', function (event) {
|
||
$(this).find('.post_control_box').removeClass('show');
|
||
});
|
||
|
||
|
||
//社交小工具二维码
|
||
$(document).on('mouseenter', '.sw_social', function (event) {
|
||
var qrbox = $(this).siblings('.sw_qrcode');
|
||
if (qrbox.length > 0) {
|
||
qrbox.addClass('active');
|
||
qrbox.fadeIn(200);
|
||
}
|
||
});
|
||
|
||
$(document).on('mouseleave', '.sw_social', function (event) {
|
||
var qrbox = $(this).siblings('.sw_qrcode');
|
||
if (qrbox.length > 0) {
|
||
qrbox.removeClass('active');
|
||
qrbox.fadeOut(200);
|
||
}
|
||
});
|
||
|
||
//点击收起移动侧栏
|
||
$('body').on('click', '.m_offcanvas', function () {
|
||
var target = event.target;
|
||
var parentAnchor = $(target).closest('a');
|
||
if (target.getAttribute('href') == '#' || parentAnchor.attr('href') == '#') {
|
||
} else {
|
||
UIkit.offcanvas('.m_offcanvas').hide();
|
||
}
|
||
});
|
||
|
||
// 刷新内容(兼容一言和今日诗词API)
|
||
let yiyanLoading = false; // 标志是否正在请求
|
||
$('body').on('click', '.yiyan_box .change', function () {
|
||
// 若请求还未恢复消息,直接return
|
||
if (yiyanLoading) {
|
||
return;
|
||
}
|
||
yiyanLoading = true; // 设置请求开始标志
|
||
var url = Theme.widget_yiyan.api || 'https://v1.hitokoto.cn';
|
||
fetch(url)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const targetElement = document.querySelector('.yiyan_box p');
|
||
if (url.includes('api.anian.net')) {
|
||
// 新增处理逻辑
|
||
targetElement.innerText = data.content || '一日不见如隔三秋';
|
||
const tooltipTitle = data.title || '失败:超时或发生错误';
|
||
targetElement.setAttribute("uk-tooltip", tooltipTitle === '失败:超时或发生错误' ? `${tooltipTitle}${data.author || ''}` : `《${tooltipTitle}》${data.author || ''}`);
|
||
} else {
|
||
// 原有一言API处理逻辑
|
||
targetElement.innerText = data.hitokoto || '一日不见如隔三秋';
|
||
targetElement.setAttribute("uk-tooltip", data.from || '失败:超时或发生错误');
|
||
}
|
||
})
|
||
.finally(() => {
|
||
yiyanLoading = false; // 请求完成,重置标志
|
||
})
|
||
});
|
||
|
||
$('.yiyan_box .change').click();
|
||
|
||
//pjax
|
||
|
||
$(document).on('pjax:error', function (event, xhr, textStatus, errorThrown, options) {
|
||
cocoMessage.error('加载失败!');
|
||
});
|
||
|
||
if (Theme.pjax) {
|
||
let pjaxSelectors = ["head title", "#pjax-container", ".pjax"]
|
||
var pjax = new Pjax({
|
||
elements: 'a:not([target="_blank"]):not([pjax="exclude"])',
|
||
selectors: pjaxSelectors,
|
||
analytics: false,
|
||
cacheBust: false,
|
||
});
|
||
|
||
document.addEventListener('pjax:send', function () {
|
||
NProgress.start();
|
||
})
|
||
|
||
document.addEventListener('pjax:complete', function () {
|
||
lazyLoadInstance.update();
|
||
typeof hljs === 'object' && hljs.highlightAll();
|
||
typeof Prism === 'object' && Prism.highlightAll();
|
||
autoload_posts_music();
|
||
initBlog();
|
||
initPageJumpSteppers();
|
||
refreshCommentWidget();
|
||
NProgress.done();
|
||
initPreviousPageButton()
|
||
})
|
||
}
|
||
|
||
// 刷新评论组件函数
|
||
function refreshCommentWidget() {
|
||
const commentWrappers = document.querySelectorAll('.halo-comment');
|
||
if (commentWrappers.length > 0) {
|
||
commentWrappers.forEach(wrapper => {
|
||
const scripts = wrapper.querySelectorAll('script[type="module"]');
|
||
scripts.forEach(oldScript => {
|
||
const newScript = document.createElement('script');
|
||
newScript.type = 'module';
|
||
// 复制所有属性
|
||
Array.from(oldScript.attributes).forEach(attr => {
|
||
if (attr.name !== 'type') {
|
||
newScript.setAttribute(attr.name, attr.value);
|
||
}
|
||
});
|
||
// 复制脚本内容
|
||
newScript.textContent = oldScript.textContent;
|
||
// 替换旧脚本
|
||
oldScript.parentNode.insertBefore(newScript, oldScript);
|
||
oldScript.remove();
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
$('body').on('click', '.msg_modal_inner .unread_box .box .mark_read', function (e) {
|
||
let msg_name = $(this).parent()[0].getAttribute('msg-name')
|
||
let username = Theme.username
|
||
$.ajax({
|
||
type: "put",
|
||
url: `/apis/api.notification.halo.run/v1alpha1/userspaces/${username}/notifications/${msg_name}/mark-as-read`,
|
||
success: function (res) {
|
||
pix.getMsg()
|
||
}
|
||
});
|
||
})
|
||
|
||
|
||
const getWindowInfo = () => {
|
||
pix.initTopBar()
|
||
};
|
||
const debounce = (fn, delay) => {
|
||
let timer;
|
||
return function () {
|
||
if (timer) {
|
||
clearTimeout(timer);
|
||
}
|
||
timer = setTimeout(() => {
|
||
fn();
|
||
}, delay);
|
||
}
|
||
};
|
||
|
||
const cancalDebounce = debounce(getWindowInfo, 1);
|
||
window.addEventListener('resize', cancalDebounce);
|
||
|
||
//固定顶部栏
|
||
$(document).scroll(function () {
|
||
let topBar = $('#masthead .top_bar');
|
||
var placeholder = document.querySelector('#masthead .uk-sticky-placeholder');
|
||
var width = topBar.width();
|
||
var scrT = document.documentElement.scrollTop;
|
||
if (window.innerWidth > 960) {
|
||
// 如果滚动的距离>60
|
||
if (scrT > 60) {
|
||
topBar.addClass('uk-active uk-sticky-fixed').css({ "width": width, "top": '0px', "position": "fixed" });
|
||
placeholder.hidden = false;
|
||
} else {
|
||
topBar.removeClass('uk-active uk-sticky-fixed').css({ "width": "auto", "top": "auto", "position": "" });
|
||
placeholder.hidden = true;
|
||
}
|
||
} else {
|
||
// 如果滚动的距离>0
|
||
if (scrT > 0) {
|
||
topBar.addClass('uk-active uk-sticky-below')
|
||
} else {
|
||
topBar.removeClass('uk-active uk-sticky-below')
|
||
}
|
||
|
||
}
|
||
|
||
});
|
||
|
||
$('body').on('click', '.listree-btn', function (event) {
|
||
event.preventDefault();
|
||
setListreeOpen(!$('.listree-box').hasClass('is-open'));
|
||
return false;
|
||
});
|
||
|
||
$(document).on('click.listreeOutside', function (event) {
|
||
if (!$('body').hasClass('toc-open')) return;
|
||
if ($(event.target).closest('.listree-box, .toc_nav').length) return;
|
||
setListreeOpen(false);
|
||
});
|
||
|
||
$(document).on('keydown.listree', function (event) {
|
||
if (event.key === 'Escape') {
|
||
setListreeOpen(false);
|
||
}
|
||
});
|
||
|
||
function resetListree() {
|
||
$('body').removeClass('toc-ready toc-open');
|
||
$('.toc_nav').attr('aria-hidden', 'true');
|
||
$('.listree-btn')
|
||
.removeClass('is-active')
|
||
.attr({
|
||
'title': '展开目录',
|
||
'aria-label': '展开目录',
|
||
'aria-expanded': 'false'
|
||
});
|
||
$('.listree-box')
|
||
.removeClass('is-open')
|
||
.attr('aria-hidden', 'true');
|
||
}
|
||
|
||
function setListreeOpen(open) {
|
||
if (open && !$('body').hasClass('toc-ready')) return;
|
||
|
||
$('body').toggleClass('toc-open', open);
|
||
$('.listree-box')
|
||
.toggleClass('is-open', open)
|
||
.attr('aria-hidden', open ? 'false' : 'true');
|
||
$('.listree-btn')
|
||
.toggleClass('is-active', open)
|
||
.attr({
|
||
'title': open ? '收起目录' : '展开目录',
|
||
'aria-label': open ? '收起目录' : '展开目录',
|
||
'aria-expanded': open ? 'true' : 'false'
|
||
});
|
||
}
|
||
|
||
// toc
|
||
function autotree() {
|
||
$(document).ready(function () {
|
||
resetListree();
|
||
|
||
$('#listree-ol').empty().hide();
|
||
|
||
// 获取所有标题元素
|
||
var headings = document.querySelectorAll('.post-single .single-content *:is(h1, h2, h3, h4, h5, h6)');
|
||
var tocList = document.querySelector('#listree-ol');
|
||
|
||
if (!tocList || headings.length < 1) {
|
||
$(window).off('scroll.listree resize.listree');
|
||
return;
|
||
}
|
||
|
||
// 保存每个级别的父列表项
|
||
var parentItems = {};
|
||
|
||
// 遍历每个标题元素
|
||
headings.forEach(function (heading, index) {
|
||
heading.classList.add('listree-list');
|
||
heading.id = 'listree-list' + index;
|
||
|
||
var level = parseInt(heading.tagName.slice(1));
|
||
var listItem = document.createElement('li');
|
||
var link = document.createElement('a');
|
||
var parentItem = null;
|
||
|
||
listItem.setAttribute('data-level', level);
|
||
listItem.style.setProperty('--toc-index', index);
|
||
|
||
link.href = '#listree-list' + index;
|
||
link.classList.add('toc-link', 'node-name--' + heading.tagName);
|
||
link.textContent = heading.textContent.trim();
|
||
listItem.appendChild(link);
|
||
|
||
for (var parentLevel = level - 1; parentLevel >= 1; parentLevel--) {
|
||
if (parentItems[parentLevel]) {
|
||
parentItem = parentItems[parentLevel];
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (parentItem) {
|
||
if (!parentItem.querySelector('ul')) {
|
||
parentItem.appendChild(document.createElement('ul'));
|
||
}
|
||
parentItem.querySelector('ul').appendChild(listItem);
|
||
} else {
|
||
tocList.appendChild(listItem);
|
||
}
|
||
|
||
parentItems[level] = listItem;
|
||
Object.keys(parentItems).forEach(function (key) {
|
||
if (parseInt(key) > level) {
|
||
delete parentItems[key];
|
||
}
|
||
});
|
||
});
|
||
|
||
$('body').addClass('toc-ready');
|
||
$('.toc_nav').attr('aria-hidden', 'false');
|
||
$('#listree-ol').show();
|
||
|
||
$('body').off('click.listreeLink', 'a.toc-link').on('click.listreeLink', 'a.toc-link', function (event) {
|
||
event.preventDefault();
|
||
var targetId = $(this).attr("href");
|
||
var $target = $(targetId);
|
||
if (!$target.length) return;
|
||
|
||
$("html, body").animate({
|
||
scrollTop: $target.offset().top - 77
|
||
}, 500);
|
||
|
||
if (window.innerWidth <= 768) {
|
||
setListreeOpen(false);
|
||
}
|
||
});
|
||
})
|
||
jQuery(document).ready(function (f) {
|
||
var T = f(".listree-list");
|
||
if (T.length < 1)
|
||
return;
|
||
var b = [];
|
||
|
||
function Q() {
|
||
b = [];
|
||
T.each(function () {
|
||
var T = f(this).offset();
|
||
b.push(Math.floor(T.top))
|
||
})
|
||
}
|
||
|
||
function a(T) {
|
||
var b = f("#listree-ol li");
|
||
if (b.length < 1)
|
||
return;
|
||
if (!b.eq(T).hasClass("current")) {
|
||
b.removeClass("current");
|
||
b.eq(T).addClass("current");
|
||
}
|
||
}
|
||
|
||
function X() {
|
||
if ($('#listree-ol').children().length < 1)
|
||
return;
|
||
var f = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||
var Q = Math.ceil(f + 77);
|
||
var X = 0;
|
||
for (var aU = 0; aU < b.length; aU++) {
|
||
if (Q >= b[aU]) {
|
||
X = aU
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
if (X < 0)
|
||
X = 0;
|
||
if (!T.eq(X).hasClass("current")) {
|
||
T.removeClass("current");
|
||
T.eq(X).addClass("current");
|
||
a(X)
|
||
}
|
||
}
|
||
|
||
Q();
|
||
setTimeout(X, 0);
|
||
f(window).off('scroll.listree resize.listree').on('scroll.listree', X).on('resize.listree', function () {
|
||
Q();
|
||
X();
|
||
})
|
||
});
|
||
}
|
||
|
||
pix.addRuntime();
|
||
|
||
$(document).ready(function () {
|
||
$("[data-fancybox]").fancybox({
|
||
selector: '[data-fancybox]',
|
||
loop: true,
|
||
transitionEffect: 'slide',
|
||
protect: true,
|
||
buttons: ['slideShow', 'fullScreen', 'thumbs', 'close'],
|
||
hash: false
|
||
})
|
||
})
|
||
|
||
// 手机端底部菜单高亮
|
||
function highlightActiveMenu() {
|
||
let currentPath = window.location.pathname.replace(/\/+$/, "");
|
||
const pathParts = currentPath.split('/');
|
||
let firstLevelPath = '/' + (pathParts[1] || '');
|
||
if (firstLevelPath === '/') currentPath = '/';
|
||
const menuRules = {
|
||
diary: ['/', '/moments'],
|
||
composition: ['/content', '/categories', '/tags', '/archives'],
|
||
appendix: []
|
||
};
|
||
const footerMenu = document.querySelector('.footer_menu');
|
||
if (!footerMenu) return;
|
||
const diaryLi = footerMenu.querySelector('a[href="/"]').closest('li');
|
||
const compositionLi = footerMenu.querySelector('a[href="/archives"]').closest('li');
|
||
const appendixLi = footerMenu.querySelector('a[href="/navigator"]').closest('li');
|
||
const allMenuLis = footerMenu.querySelectorAll('.item li');
|
||
allMenuLis.forEach(li => {
|
||
li.classList.remove('active');
|
||
const link = li.querySelector('a');
|
||
if (link) {
|
||
link.classList.remove('active');
|
||
link.style.color = "";
|
||
const icon = link.querySelector("i");
|
||
if (icon) icon.style.color = "";
|
||
}
|
||
});
|
||
const highlightMenu = (menuLi) => {
|
||
if (!menuLi) return;
|
||
const link = menuLi.querySelector('a');
|
||
menuLi.classList.add('active');
|
||
link.classList.add('active');
|
||
link.style.color = "#4CAF50";
|
||
const icon = link.querySelector("i");
|
||
if (icon) icon.style.color = "#4CAF50";
|
||
};
|
||
if (menuRules.diary.includes(firstLevelPath)) {
|
||
highlightMenu(diaryLi);
|
||
}
|
||
else if (menuRules.composition.includes(firstLevelPath)) {
|
||
highlightMenu(compositionLi);
|
||
}
|
||
else {
|
||
highlightMenu(appendixLi);
|
||
}
|
||
}
|
||
|
||
|
||
// 指定日期黑白效果
|
||
function setPageGrayscale() {
|
||
const dateList = ['12-13'];
|
||
const style = document.createElement('style');
|
||
style.innerHTML = '.grayscale-mode{filter:grayscale(100%)!important;-webkit-filter:grayscale(100%)!important;transition:filter 60s ease!important;}';
|
||
document.head.appendChild(style);
|
||
const today = new Date();
|
||
const todayMd = `${today.getMonth() + 1}-${today.getDate()}`;
|
||
if (dateList.includes(todayMd)) {
|
||
document.documentElement.classList.add('grayscale-mode');
|
||
}
|
||
}
|
||
|
||
// 内容折叠初始化
|
||
function initializeMomentFold() {
|
||
const foldConfig = {
|
||
maxHeight: 240,
|
||
moreText: '展开',
|
||
lessText: '收起'
|
||
};
|
||
|
||
$('.moment-collapse-container').each(function () {
|
||
const $contentContainer = $(this);
|
||
if ($contentContainer.next('.moment-fold-btn').length > 0) return;
|
||
|
||
// 完整内容高度
|
||
const fullHeight = $contentContainer[0].scrollHeight;
|
||
const needFold = fullHeight > foldConfig.maxHeight;
|
||
if (!needFold) return;
|
||
|
||
// 初始化折叠状态
|
||
$contentContainer.addClass('collapsed').css('max-height', foldConfig.maxHeight + 'px');
|
||
const $foldBtn = $(`<button type="button" class="moment-fold-btn">${foldConfig.moreText}</button>`);
|
||
$contentContainer.after($foldBtn);
|
||
|
||
// 折叠/展开切换
|
||
$foldBtn.on('click', function () {
|
||
const isCollapsed = $contentContainer.hasClass('collapsed');
|
||
const heightDiff = fullHeight - foldConfig.maxHeight; // 完整高度与折叠高度的差值
|
||
|
||
if (isCollapsed) {
|
||
// 展开逻辑
|
||
$contentContainer.removeClass('collapsed').css('max-height', fullHeight + 'px');
|
||
$(this).text(foldConfig.lessText);
|
||
} else {
|
||
// 收起逻辑:页面向下滚动差值距离
|
||
$('html, body').animate({ scrollTop: $(window).scrollTop() - heightDiff }, 300, 'linear');
|
||
|
||
$contentContainer.addClass('collapsed').css('max-height', foldConfig.maxHeight + 'px');
|
||
$(this).text(foldConfig.moreText);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// 更换背景函数封装
|
||
function setFixedBackground(bgImageUrl) {
|
||
const body = document.body;
|
||
const requestId = (Number(body.dataset.backgroundRequestId) || 0) + 1;
|
||
body.dataset.backgroundRequestId = requestId;
|
||
|
||
// 传入空值时淡出并清除当前背景。
|
||
if (bgImageUrl == null || String(bgImageUrl).trim().toLowerCase() === 'null' || String(bgImageUrl).trim() === '') {
|
||
body.querySelectorAll('.fixed-background-layer').forEach((layer) => {
|
||
layer.classList.remove('is-visible');
|
||
setTimeout(() => layer.remove(), 650);
|
||
});
|
||
body.classList.remove('common-fixed-bg');
|
||
return;
|
||
}
|
||
|
||
const image = new Image();
|
||
image.onload = async () => {
|
||
if (typeof image.decode === 'function') {
|
||
try { await image.decode(); } catch (_) { }
|
||
}
|
||
|
||
if (body.dataset.backgroundRequestId !== String(requestId)) return;
|
||
|
||
const backgroundLayer = document.createElement('div');
|
||
backgroundLayer.className = 'fixed-background-layer';
|
||
backgroundLayer.style.backgroundImage = `url('${bgImageUrl}')`;
|
||
body.appendChild(backgroundLayer);
|
||
|
||
// 先应用透明状态,再切换到可见状态,确保每次调用都触发淡入。
|
||
backgroundLayer.offsetWidth;
|
||
requestAnimationFrame(() => backgroundLayer.classList.add('is-visible'));
|
||
|
||
body.querySelectorAll('.fixed-background-layer:not(:last-child)').forEach((layer) => {
|
||
layer.classList.remove('is-visible');
|
||
setTimeout(() => layer.remove(), 650);
|
||
});
|
||
};
|
||
|
||
body.classList.add('common-fixed-bg');
|
||
image.src = bgImageUrl;
|
||
}
|
||
|
||
// 奇遇显示函数封装
|
||
function showCenterImage(imageUrl, duration = 2000) {
|
||
const container = document.getElementById('centerImgContainer');
|
||
const img = document.getElementById('targetImg');
|
||
|
||
// 清理上一次调用遗留的自动关闭定时器。
|
||
clearTimeout(container._centerImageCloseTimer);
|
||
clearTimeout(container._centerImageResetTimer);
|
||
|
||
// 重置所有状态(避免上一次操作残留影响)
|
||
container.classList.remove('container-fade-active');
|
||
img.classList.remove('img-fade-in', 'img-fade-out');
|
||
img.style.opacity = 0;
|
||
img.src = ""; // 先清空原有src
|
||
|
||
// 定义图片加载成功的回调函数
|
||
function handleImageLoad() {
|
||
// 移除事件监听(防止重复绑定)
|
||
img.removeEventListener('load', handleImageLoad);
|
||
img.removeEventListener('error', handleImageError);
|
||
|
||
// 图片加载成功后,再执行淡入动画
|
||
container.classList.add('container-fade-active');
|
||
img.classList.add('img-fade-in');
|
||
|
||
// duration 为 0 时保持显示,不执行自动关闭逻辑。
|
||
if (duration <= 0) return;
|
||
|
||
container._centerImageCloseTimer = setTimeout(() => {
|
||
container.classList.remove('container-fade-active');
|
||
img.classList.add('img-fade-out');
|
||
|
||
container._centerImageResetTimer = setTimeout(() => {
|
||
img.classList.remove('img-fade-in', 'img-fade-out');
|
||
}, 500);
|
||
}, duration);
|
||
}
|
||
|
||
// 定义图片加载失败的回调函数
|
||
function handleImageError() {
|
||
// 移除事件监听
|
||
img.removeEventListener('load', handleImageLoad);
|
||
img.removeEventListener('error', handleImageError);
|
||
|
||
// 重置容器和图片状态,不执行任何动画
|
||
container.classList.remove('container-fade-active');
|
||
img.classList.remove('img-fade-in', 'img-fade-out');
|
||
img.style.opacity = 0;
|
||
img.src = "";
|
||
}
|
||
|
||
// 绑定图片加载/失败事件监听(先绑定,再赋值src,避免缓存导致回调不触发)
|
||
img.addEventListener('load', handleImageLoad);
|
||
img.addEventListener('error', handleImageError);
|
||
|
||
// 最后赋值src,触发图片加载(异步操作)
|
||
img.src = imageUrl;
|
||
}
|
||
|
||
// 侧边栏农历信息显示函数
|
||
function anian_renderLunarUI() {
|
||
const textEl = document.getElementById('anianLunarText');
|
||
|
||
if (!textEl) return;
|
||
|
||
const doRender = (data) => {
|
||
if (!data) {
|
||
textEl.innerHTML = '一日不见 · 如隔三秋';
|
||
return;
|
||
}
|
||
|
||
const { ganzhiYear = '', lunarMonth = '', lunarDay = '', jieqi = '', jijie = '', traditionalFestival = '', shengxiao = '' } = data;
|
||
|
||
let text = `${ganzhiYear}${shengxiao}年 · ${lunarMonth}月${lunarDay}`;
|
||
const extra = [];
|
||
if (jieqi) extra.push(jieqi);
|
||
if (traditionalFestival) extra.push(traditionalFestival);
|
||
if (extra.length) text += `<br>${extra.join(' · ')}`;
|
||
|
||
textEl.innerHTML = text;
|
||
|
||
if (jieqi) showCenterImage('/upload/' + jieqi + '.webp');
|
||
// setFixedBackground('/upload/JX3WJ.mp4_20260207_022345.027.jpg');
|
||
};
|
||
|
||
const tryRender = (attempt) => {
|
||
let data = null;
|
||
try {
|
||
const cookieVal = $.cookie('anian_lunar_info');
|
||
if (cookieVal) data = JSON.parse(cookieVal);
|
||
} catch (_) { }
|
||
|
||
if (data) {
|
||
doRender(data);
|
||
} else if (attempt < 20) {
|
||
setTimeout(() => tryRender(attempt + 1), 500);
|
||
} else {
|
||
doRender(null);
|
||
}
|
||
};
|
||
|
||
tryRender(0);
|
||
}
|
||
|
||
// 绿色数字时钟粒子效果
|
||
function initGreenDigitalClock() {
|
||
var t = 820;
|
||
var a = 250;
|
||
var r = 7;
|
||
var n = 10;
|
||
var e = .65;
|
||
var f;
|
||
var o = [];
|
||
|
||
const v = ["#00FF7F", "#32CD32", "#228B22", "#008000", "#006400", "#90EE90", "#98FB98", "#00FA9A", "#00FF00", "#3CB371"];
|
||
|
||
var h = [];
|
||
var u = [
|
||
[[0, 0, 1, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0]],
|
||
[[0, 0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1]],
|
||
[[0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1]],
|
||
[[1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0]],
|
||
[[0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0], [0, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1, 1]],
|
||
[[1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0]],
|
||
[[0, 0, 0, 0, 1, 1, 0], [0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0]],
|
||
[[1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0]],
|
||
[[0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0]],
|
||
[[0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 0, 0]],
|
||
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
||
];
|
||
|
||
function l(t) {
|
||
var a = [];
|
||
f.fillStyle = "#006400";
|
||
var r = new Date;
|
||
var e = 70, o = 30;
|
||
var v = r.getHours();
|
||
var u = Math.floor(v / 10);
|
||
var l = v % 10;
|
||
a.push({ num: u });
|
||
a.push({ num: l });
|
||
a.push({ num: 10 });
|
||
var c = r.getMinutes();
|
||
var u = Math.floor(c / 10);
|
||
var l = c % 10;
|
||
a.push({ num: u });
|
||
a.push({ num: l });
|
||
a.push({ num: 10 });
|
||
var M = r.getSeconds();
|
||
var u = Math.floor(M / 10);
|
||
var l = M % 10;
|
||
a.push({ num: u });
|
||
a.push({ num: l });
|
||
for (var p = 0; p < a.length; p++) {
|
||
a[p].offsetX = e;
|
||
e = m(e, o, a[p].num, t);
|
||
if (p < a.length - 1) {
|
||
if (a[p].num != 10 && a[p + 1].num != 10) {
|
||
e += n
|
||
}
|
||
}
|
||
}
|
||
if (h.length == 0) {
|
||
h = a
|
||
} else {
|
||
for (var C = 0; C < h.length; C++) {
|
||
if (h[C].num != a[C].num) {
|
||
s(a[C]);
|
||
h[C].num = a[C].num
|
||
}
|
||
}
|
||
}
|
||
i(t);
|
||
g();
|
||
return r
|
||
}
|
||
|
||
function s(t) {
|
||
var a = t.num;
|
||
var n = u[a];
|
||
for (var e = 0; e < n.length; e++) {
|
||
for (var f = 0; f < n[e].length; f++) {
|
||
if (n[e][f] == 1) {
|
||
var h = {
|
||
offsetX: t.offsetX + r + r * 2 * f,
|
||
offsetY: 30 + r + r * 2 * e,
|
||
color: v[Math.floor(Math.random() * v.length)],
|
||
g: 1.5 + Math.random(),
|
||
vx: Math.pow(-1, Math.ceil(Math.random() * 10)) * 4 + Math.random(),
|
||
vy: -5
|
||
};
|
||
o.push(h)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function i(t) {
|
||
for (var a = 0; a < o.length; a++) {
|
||
t.beginPath();
|
||
t.fillStyle = o[a].color;
|
||
t.arc(o[a].offsetX, o[a].offsetY, r, 0, 2 * Math.PI);
|
||
t.fill()
|
||
}
|
||
}
|
||
|
||
function g() {
|
||
var n = 0;
|
||
for (var f = 0; f < o.length; f++) {
|
||
var v = o[f];
|
||
v.offsetX += v.vx;
|
||
v.offsetY += v.vy;
|
||
v.vy += v.g;
|
||
if (v.offsetY > a - r) {
|
||
v.offsetY = a - r;
|
||
v.vy = -v.vy * e
|
||
}
|
||
if (v.offsetX > r && v.offsetX < t - r) {
|
||
o[n] = o[f];
|
||
n++
|
||
}
|
||
}
|
||
for (; n < o.length; n++) {
|
||
o.pop()
|
||
}
|
||
}
|
||
|
||
function m(t, a, n, e) {
|
||
var f = u[n];
|
||
for (var o = 0; o < f.length; o++) {
|
||
for (var v = 0; v < f[o].length; v++) {
|
||
if (f[o][v] == 1) {
|
||
e.beginPath();
|
||
e.arc(t + r + r * 2 * v, a + r + r * 2 * o, r, 0, 2 * Math.PI);
|
||
e.fill()
|
||
}
|
||
}
|
||
}
|
||
e.beginPath();
|
||
t += f[0].length * r * 2;
|
||
return t
|
||
}
|
||
|
||
var c = document.getElementById("canvas");
|
||
c.width = t;
|
||
c.height = a;
|
||
f = c.getContext("2d");
|
||
var M = new Date;
|
||
setInterval(function () {
|
||
f.clearRect(0, 0, f.canvas.width, f.canvas.height);
|
||
l(f)
|
||
}, 50)
|
||
}
|
||
|
||
// 侧边栏公告提醒 - 多RSS监控版(精准到秒+无兜底)
|
||
const COOKIE_EXPIRE_YEARS = 10;
|
||
const NOTICE_DETAIL_PATH = '/notice';
|
||
const RSS_URLS = [
|
||
'https://git.anian.net/anian/halo-theme-pix/rss/branch/master',
|
||
];
|
||
|
||
async function getAllLatestNoticeDatesFromRSS() {
|
||
try {
|
||
const rssResponses = await Promise.all(
|
||
RSS_URLS.map(url => fetch(url))
|
||
);
|
||
for (let [index, response] of rssResponses.entries()) {
|
||
if (!response.ok) {
|
||
throw new Error(`RSS ${RSS_URLS[index]} 请求失败:${response.status}`);
|
||
}
|
||
}
|
||
const allPubDates = [];
|
||
for (let response of rssResponses) {
|
||
const xmlText = await response.text();
|
||
const parser = new DOMParser();
|
||
const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
|
||
const items = xmlDoc.querySelectorAll('item');
|
||
if (items.length === 0) continue;
|
||
const itemDates = Array.from(items).map(item => {
|
||
const pubDateStr = item.querySelector('pubDate').textContent;
|
||
const pubDate = new Date(pubDateStr);
|
||
return `${pubDate.getFullYear()}-${String(pubDate.getMonth() + 1).padStart(2, '0')}-${String(pubDate.getDate()).padStart(2, '0')}-${String(pubDate.getHours()).padStart(2, '0')}-${String(pubDate.getMinutes()).padStart(2, '0')}-${String(pubDate.getSeconds()).padStart(2, '0')}`;
|
||
});
|
||
allPubDates.push(itemDates[0]);
|
||
}
|
||
const sortedDates = allPubDates.sort((a, b) => new Date(b) - new Date(a));
|
||
const combinedDateStr = sortedDates.join('_'); // 用_分隔多个日期
|
||
|
||
return combinedDateStr;
|
||
|
||
} catch (error) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// 标记已读(接收拼接后的日期字符串)
|
||
function markAsRead(combinedDateStr) {
|
||
if (!combinedDateStr) return; // 无有效日期则不操作
|
||
const noticeBubble = document.getElementById('noticeBubble');
|
||
const noticeBtn = document.getElementById('noticeBtn');
|
||
if (!noticeBubble || !noticeBtn) return;
|
||
$.cookie('latest_notice_date', combinedDateStr, { path: '/', expires: 365 });
|
||
noticeBubble.classList.remove('show');
|
||
noticeBtn.classList.remove('has-notice');
|
||
}
|
||
|
||
// 检测公告详情页并标记已读
|
||
function checkNoticeDetailPage(combinedDateStr) {
|
||
if (!combinedDateStr) return; // 无有效日期则不检查
|
||
const currentPath = window.location.pathname.replace(/\/$/, '');
|
||
const local_notice = $.cookie('latest_notice_date');
|
||
const hasUnread = !local_notice || local_notice !== combinedDateStr;
|
||
|
||
if (currentPath === NOTICE_DETAIL_PATH && hasUnread) {
|
||
markAsRead(combinedDateStr);
|
||
}
|
||
}
|
||
|
||
// 通知按钮绑定
|
||
function bindGlobalNoticeEvents(combinedDateStr) {
|
||
if (document.body.dataset.noticeEventsBound) return;
|
||
|
||
document.addEventListener('click', (e) => {
|
||
const noticeBtn = document.getElementById('noticeBtn');
|
||
if (noticeBtn && (e.target === noticeBtn || noticeBtn.contains(e.target))) {
|
||
markAsRead(combinedDateStr);
|
||
}
|
||
});
|
||
|
||
document.body.dataset.noticeEventsBound = 'true';
|
||
}
|
||
|
||
// 异步初始化(无兜底逻辑)
|
||
async function initNoticeTip() {
|
||
// 1. 获取所有RSS的拼接日期字符串,失败则直接终止
|
||
const combinedDateStr = await getAllLatestNoticeDatesFromRSS();
|
||
if (!combinedDateStr) return; // 【核心】RSS失败则不检查、不显示提醒
|
||
|
||
const noticeBubble = document.getElementById('noticeBubble');
|
||
const noticeBtn = document.getElementById('noticeBtn');
|
||
if (!noticeBubble || !noticeBtn) return;
|
||
|
||
const local_notice = $.cookie('latest_notice_date');
|
||
const hasUnread = !local_notice || local_notice !== combinedDateStr;
|
||
|
||
// 2. 只有RSS获取成功,才判断并显示/隐藏提醒
|
||
if (hasUnread) {
|
||
noticeBubble.classList.add('show');
|
||
noticeBtn.classList.add('has-notice');
|
||
$('.footer_menu a[href="/navigator"]').css('color', '#ecc94b').find('i').css('color', '#ecc94b');
|
||
} else {
|
||
noticeBubble.classList.remove('show');
|
||
noticeBtn.classList.remove('has-notice');
|
||
}
|
||
bindGlobalNoticeEvents(combinedDateStr);
|
||
checkNoticeDetailPage(combinedDateStr);
|
||
}
|
||
|
||
// 测速侧边栏
|
||
const anianxSpeedBubble = document.getElementById("anianxBubble"),
|
||
anianxSpeedBubbleText = document.getElementById("anianxBubbleText"),
|
||
anianxSpeedGroup = document.querySelector(".anianx-group"),
|
||
anianxSpeedMainLine = document.querySelector('[data-anianx-type="main"]'),
|
||
anianxSpeedTestLine = document.querySelector('[data-anianx-type="test"]'),
|
||
anianxSpeedSubLine = document.querySelector('[data-anianx-type="sub"]');
|
||
let anianxSpeedGlobalLock = false;
|
||
|
||
function anianxSpeedMoveArrow(btn) {
|
||
if (anianxSpeedGlobalLock) return;
|
||
const btnRect = btn.getBoundingClientRect(),
|
||
groupRect = anianxSpeedGroup.getBoundingClientRect(),
|
||
center = (btnRect.left - groupRect.left) + (btnRect.width / 2);
|
||
anianxSpeedBubble.style.setProperty("--anianx-arrow", center + "px");
|
||
}
|
||
|
||
function anianxSpeedSetTooltip(btn, text) {
|
||
if (!btn) return;
|
||
btn.setAttribute("title", text);
|
||
btn.setAttribute("uk-tooltip", "pos: top; offset: 2;");
|
||
}
|
||
|
||
function anianxSpeedClearTooltip(btn) {
|
||
if (!btn) return;
|
||
btn.removeAttribute("title");
|
||
btn.removeAttribute("uk-tooltip");
|
||
}
|
||
|
||
function anianxSpeedFetchLuckWithTimeout(timeout) {
|
||
const controller = new AbortController();
|
||
const timer = setTimeout(() => controller.abort(), timeout);
|
||
|
||
return fetch("https://api.anian.net/luck/api", {
|
||
signal: controller.signal
|
||
}).then(response => {
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP ${response.status}`);
|
||
}
|
||
return response.json();
|
||
}).finally(() => {
|
||
clearTimeout(timer);
|
||
});
|
||
}
|
||
|
||
function anianxSpeedBuildLuckTooltip(idText, poetryText, meaningText, explanationText) {
|
||
const signText = idText ? `第${idText}签。` : "第?签";
|
||
return [
|
||
signText,
|
||
poetryText || "",
|
||
meaningText || "",
|
||
explanationText || ""
|
||
].join("||  ");
|
||
}
|
||
|
||
if (anianxSpeedMainLine) {
|
||
anianxSpeedMainLine.addEventListener("click", () => {
|
||
if (anianxSpeedGlobalLock) return;
|
||
anianxSpeedMoveArrow(anianxSpeedMainLine);
|
||
anianxSpeedGlobalLock = true;
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.classList.add("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = "抽取中";
|
||
|
||
const request = anianxSpeedFetchLuckWithTimeout(5000);
|
||
|
||
request.then(data => {
|
||
const result = data || {};
|
||
const typeText = result.type || "";
|
||
const titleText = result.title || "";
|
||
const idText = result.id || "";
|
||
const explanationText = result.explanation || "";
|
||
const poetryText = result.poetry || "";
|
||
const meaningText = result.meaning || "";
|
||
anianxSpeedBubbleText.innerText = [typeText, titleText].filter(Boolean).join(" · ") || "失败:超时或发生错误";
|
||
anianxSpeedSetTooltip(anianxSpeedBubbleText, anianxSpeedBuildLuckTooltip(idText, poetryText, meaningText, explanationText));
|
||
}).catch(() => {
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.innerText = "失败:超时或发生错误";
|
||
}).finally(() => {
|
||
anianxSpeedBubbleText.classList.remove("anianx-loading");
|
||
anianxSpeedGlobalLock = false;
|
||
});
|
||
});
|
||
}
|
||
|
||
if (anianxSpeedTestLine) {
|
||
anianxSpeedTestLine.addEventListener("click", () => {
|
||
if (anianxSpeedGlobalLock) return;
|
||
anianxSpeedMoveArrow(anianxSpeedTestLine);
|
||
anianxSpeedGlobalLock = true;
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.classList.add("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = "测速中";
|
||
Promise.all([
|
||
anianxSpeedTestWithTimeout(10000),
|
||
anianxSpeedFetchIpWithTimeout(5000)
|
||
]).then(([speedResult, ipResult]) => {
|
||
anianxSpeedBubbleText.classList.remove("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = speedResult;
|
||
const tooltipText = anianxSpeedBuildIpTooltip(ipResult);
|
||
anianxSpeedSetTooltip(anianxSpeedBubbleText, tooltipText);
|
||
}).catch(() => {
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.classList.remove("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = "失败:超时或发生错误";
|
||
}).finally(() => {
|
||
anianxSpeedGlobalLock = false;
|
||
});
|
||
});
|
||
}
|
||
|
||
if (anianxSpeedSubLine) {
|
||
anianxSpeedSubLine.addEventListener("click", () => {
|
||
if (anianxSpeedGlobalLock) return;
|
||
anianxSpeedMoveArrow(anianxSpeedSubLine);
|
||
anianxSpeedGlobalLock = true;
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.classList.add("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = "加载中";
|
||
|
||
anianxSpeedFetchXiehouyuWithTimeout(5000).then(data => {
|
||
anianxSpeedBubbleText.classList.remove("anianx-loading");
|
||
if (data && data.riddle) {
|
||
anianxSpeedBubbleText.innerText = data.riddle;
|
||
// 设置tooltip显示答案
|
||
const tooltipText = data.answer || "失败:超时或发生错误";
|
||
anianxSpeedSetTooltip(anianxSpeedBubbleText, tooltipText);
|
||
} else {
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.innerText = "失败:超时或发生错误";
|
||
}
|
||
}).catch(() => {
|
||
anianxSpeedClearTooltip(anianxSpeedBubbleText);
|
||
anianxSpeedBubbleText.classList.remove("anianx-loading");
|
||
anianxSpeedBubbleText.innerText = "失败:超时或发生错误";
|
||
}).finally(() => {
|
||
anianxSpeedGlobalLock = false;
|
||
});
|
||
});
|
||
}
|
||
|
||
function anianxSpeedTestWithTimeout(timeout) {
|
||
const controller = new AbortController();
|
||
const timer = setTimeout(() => controller.abort(), timeout);
|
||
return new Promise(async (resolve, reject) => {
|
||
try {
|
||
const t0 = Date.now();
|
||
const res = await fetch(`/upload/dy-32097365860-260719-1.mp4?t=${Date.now()}`, {
|
||
signal: controller.signal
|
||
});
|
||
const blob = await res.blob();
|
||
const size = blob.size;
|
||
const sec = (Date.now() - t0) / 1000;
|
||
const mbps = ((size * 8) / (sec * 1024 * 1024)).toFixed(2);
|
||
clearTimeout(timer);
|
||
resolve("访问速率:" + mbps + " Mbps");
|
||
} catch (e) {
|
||
clearTimeout(timer);
|
||
reject(e);
|
||
}
|
||
});
|
||
}
|
||
|
||
function anianxSpeedFetchIpWithTimeout(timeout) {
|
||
const controller = new AbortController();
|
||
const timer = setTimeout(() => controller.abort(), timeout);
|
||
|
||
return fetch("https://api.anian.net/ip/api", {
|
||
signal: controller.signal
|
||
}).then(response => {
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP ${response.status}`);
|
||
}
|
||
return response.json();
|
||
}).then(data => {
|
||
clearTimeout(timer);
|
||
return {
|
||
ip: data.ip || "",
|
||
region: data.region || ""
|
||
};
|
||
}).catch(e => {
|
||
clearTimeout(timer);
|
||
return {
|
||
ip: "",
|
||
region: ""
|
||
};
|
||
});
|
||
}
|
||
|
||
function anianxSpeedBuildIpTooltip(ipInfo) {
|
||
if (!ipInfo || (!ipInfo.ip && !ipInfo.region)) {
|
||
return "失败:超时或发生错误";
|
||
}
|
||
|
||
const lines = [];
|
||
if (ipInfo.ip) {
|
||
lines.push(`IP地址: ${ipInfo.ip}`);
|
||
}
|
||
if (ipInfo.region) {
|
||
lines.push(`<br>${ipInfo.region}`);
|
||
}
|
||
|
||
return lines.join("\n");
|
||
}
|
||
|
||
function anianxSpeedFetchXiehouyuWithTimeout(timeout) {
|
||
const controller = new AbortController();
|
||
const timer = setTimeout(() => controller.abort(), timeout);
|
||
|
||
return fetch("https://api.anian.net/riddle/api", {
|
||
signal: controller.signal
|
||
}).then(response => {
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP ${response.status}`);
|
||
}
|
||
return response.json();
|
||
}).then(data => {
|
||
clearTimeout(timer);
|
||
return data;
|
||
}).catch(e => {
|
||
clearTimeout(timer);
|
||
return null;
|
||
});
|
||
}
|
||
|
||
function initjump() {
|
||
// 登录登出、发布更新等操作后,显示提示信息
|
||
let closeLoading = null;
|
||
const loadType = $.cookie('load_type');
|
||
if (loadType) {
|
||
$.removeCookie('load_type', { path: '/' });
|
||
switch (loadType) {
|
||
case 'create':
|
||
cocoMessage.success('发布成功!');
|
||
break;
|
||
case 'update':
|
||
cocoMessage.success('更新成功!');
|
||
break;
|
||
case 'login':
|
||
cocoMessage.success('登录成功!');
|
||
break;
|
||
case 'logout':
|
||
cocoMessage.success('登出成功!');
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// 侧边栏订阅函数
|
||
async function handleSubscribe(event) {
|
||
event.preventDefault();
|
||
|
||
const form = event.target;
|
||
const input = form.querySelector(".subscribe-input");
|
||
const btn = form.querySelector(".subscribe-btn");
|
||
const msg = document.getElementById("subscribe-message");
|
||
|
||
const email = input.value.trim();
|
||
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||
return show("请输入正确格式的邮箱地址", "error");
|
||
}
|
||
|
||
btn.disabled = true;
|
||
show("正在提交...");
|
||
|
||
try {
|
||
const res = await fetch(
|
||
"/apis/api.flow.post.kunkunyu.com/v1alpha1/follows/-/submit",
|
||
{
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ email })
|
||
}
|
||
);
|
||
|
||
if (res.status === 200) {
|
||
show("订阅成功", "success");
|
||
input.value = "";
|
||
} else {
|
||
show("您已订阅过", "warning");
|
||
}
|
||
} catch {
|
||
show("网络错误,请稍后再试", "error");
|
||
}
|
||
|
||
btn.disabled = false;
|
||
|
||
function show(text, type) {
|
||
msg.textContent = text;
|
||
msg.className = `subscribe-message ${type}`;
|
||
}
|
||
}
|
||
|
||
// 图库兼容视频监听刷新排版
|
||
let wfTimer = null;
|
||
document.addEventListener('loadedmetadata', function (e) {
|
||
if (
|
||
e.target.tagName === 'VIDEO' &&
|
||
e.target.closest('.gallery-photos')
|
||
) {
|
||
clearTimeout(wfTimer);
|
||
wfTimer = setTimeout(() => {
|
||
waterfall('.gallery-photos');
|
||
}, 300);
|
||
}
|
||
}, true);
|
||
|
||
function initBlog() {
|
||
pix.initTopBar(),
|
||
pix.getMsg(),
|
||
initAgree(),
|
||
pix.initGalleryPhotos(),
|
||
pix.loadLightbox(),
|
||
pix.topCategoriesBarScroll(),
|
||
pix.topTableBarScroll(),
|
||
pix.centerCategoryNavActive(),
|
||
getMomentAudio(),
|
||
Theme.toc.all_open && autotree(),
|
||
|
||
highlightActiveMenu(),
|
||
syncFooterWithAudioState(),
|
||
highlightMenu(),
|
||
initializeMomentFold()
|
||
// nextBanner()
|
||
|
||
}
|
||
|
||
|
||
$(document).ready(function () {
|
||
pix.roleMoments();
|
||
initBlog();
|
||
initPageJumpSteppers();
|
||
|
||
initPreviousPageButton()
|
||
setPageGrayscale();
|
||
anian_renderLunarUI();
|
||
updateMusicBtnColor('default');
|
||
initGreenDigitalClock();
|
||
initNoticeTip();
|
||
initjump();
|
||
});
|