Files
halo-theme-pix/templates/assets/js/app.js
T
2026-07-29 00:17:31 +08:00

3266 lines
110 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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("||&nbsp&nbsp");
}
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();
});