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 = '
'; const PHOTO_LIST_LOADING_HTML = '
'; 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(); } }; } 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 = $('
', { id: 'prev_pagination', class: 'prev-pagination uk-width-1-1' }); const $paging = $('
', { class: 'post-paging' }); const $link = $('', { 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 = $('
', paginationId ? { id: paginationId } : {}); $(insertAfterSelector).last().after($pagination); } let $postPaging = $pagination.find('.post-paging').first(); if (!$postPaging.length) { $postPaging = $('
', { class: 'post-paging' }); $pagination.empty().append($postPaging); } let $button = $postPaging.find('a').first(); if (!$button.length) { $button = $(''); $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 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 `
  • `; } return `
  • `; } 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('').attr('visible', 'PRIVATE'); $(this).children().css({ "background": "#ddd", "color": "#c6c6c6" }); } else { $(this).html('').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("
    " + tot.toFixed(2) + "MB
    "); $.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 ? `` : ``; var media = `
    ${mediaInner}
    `; $(".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 = `
    `; } else { var thum = $(this).children().attr('src') || $(this).children().attr('poster'); mediaHtml = `
    `; } $(".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 = ``; } else { mediaPreview = ``; } var media = `
    ${mediaPreview}
    `; $(".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 += `

    ${catname}

    `; } 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 () { const $pagingArea = $('#t_pagination .post-paging'); if ($pagingArea.length) { $pagingArea.html('
    '); } else { showListLoading('.moment_list'); } }, 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.closest('.douban_cat_nav').length > 0) { return; } 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 () { const $pagingArea = $('#t_pagination .post-paging'); if ($pagingArea.length) { $pagingArea.html('
    '); } else { showListLoading('.moment_list'); } }, 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(); // 更新浏览器历史状态 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('
    '); }, 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('
    '); }, 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(); 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' }); $.ajax({ type: "GET", url: url, headers: HTML_PAGE_AJAX_HEADERS, beforeSend: function () { const $pagingArea = $('#p_pagination .post-paging'); if ($pagingArea.length) { $pagingArea.html('
    '); } else { showListLoading("#photos_item", PHOTO_LIST_LOADING_HTML); } }, 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('
    '); }, 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 = `
    ${title}${author}
    `; } 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 () { const $pagingArea = $('#pagination .post-paging'); if ($pagingArea.length) { $pagingArea.html('
    '); } else { showListLoading('.norpost_list'); } }, 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'); $('.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('
    '); }, 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('
    '); }, 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("" + title + ""); }); $(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 = $(``); $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; body.classList.add('common-fixed-bg'); body.style.backgroundImage = `url('${bgImageUrl}')`; } // 奇遇显示函数封装 function showCenterImage(imageUrl) { const container = document.getElementById('centerImgContainer'); const img = document.getElementById('targetImg'); // 重置所有状态(避免上一次操作残留影响) 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'); // 图片显示1.5秒后,执行自动关闭逻辑 setTimeout(() => { container.classList.remove('container-fade-active'); img.classList.add('img-fade-out'); setTimeout(() => { img.classList.remove('img-fade-in', 'img-fade-out'); }, 500); }, 1500); } // 定义图片加载失败的回调函数 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 += `
    ${extra.join(' · ')}`; textEl.innerHTML = text; if (jieqi === '大寒') showCenterImage('/upload/qiyu-jieqi-dahan.png'); // 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(`
    ${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() { // 功能1:自定义页面tag接管(后续在自定义测实现,当前为过度) const targetPaths = ['/douban']; const pathname = window.location.pathname; const urlParams = new URLSearchParams(window.location.search); const activeTag = urlParams.get('tag')?.trim(); // 同时存在tag、且当前路径在集合内,才执行点击逻辑,不满足直接跳过 if (activeTag && targetPaths.includes(pathname)) { // 统一导航按钮选择器 const navSelector = '.douban_cat_nav ul li a'; const targetLink = $(navSelector).filter(function () { const linkText = $(this).clone().find('span').remove().end().text().trim(); return linkText === activeTag; }); // 匹配到元素则模拟点击 if (targetLink.length) { targetLink.trigger('click'); } } // 功能2:登录登出、发布更新等操作后,显示提示信息 let closeLoading = null; 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(); });