const anzhiyu = { debounce: (func, wait = 0, immediate = false) => { let timeout; return (...args) => { const later = () => { timeout = null; if (!immediate) func(...args); }; const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func(...args); }; }, throttle: function (func, wait, options = {}) { let timeout, context, args; let previous = 0; const later = () => { previous = options.leading === false ? 0 : new Date().getTime(); timeout = null; func.apply(context, args); if (!timeout) context = args = null; }; const throttled = (...params) => { const now = new Date().getTime(); if (!previous && options.leading === false) previous = now; const remaining = wait - (now - previous); context = this; args = params; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } }; return throttled; }, sidebarPaddingR: () => { const innerWidth = window.innerWidth; const clientWidth = document.body.clientWidth; const paddingRight = innerWidth - clientWidth; if (innerWidth !== clientWidth) { document.body.style.paddingRight = paddingRight + "px"; } }, snackbarShow: (text, showActionFunction = false, duration = 2000, actionText = false) => { const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar; const bg = document.documentElement.getAttribute("data-theme") === "light" ? bgLight : bgDark; const root = document.querySelector(":root"); root.style.setProperty("--anzhiyu-snackbar-time", duration + "ms"); Snackbar.show({ text: text, backgroundColor: bg, onActionClick: showActionFunction, actionText: actionText, showAction: actionText, duration: duration, pos: position, customClass: "snackbar-css", }); }, loadComment: (dom, callback) => { if ("IntersectionObserver" in window) { const observerItem = new IntersectionObserver( entries => { if (entries[0].isIntersecting) { callback(); observerItem.disconnect(); } }, { threshold: [0] } ); observerItem.observe(dom); } else { callback(); } }, scrollToDest: (pos, time = 500) => { const currentPos = window.pageYOffset; if ("scrollBehavior" in document.documentElement.style) { window.scrollTo({ top: pos, behavior: "smooth", }); return; } let start = null; pos = +pos; window.requestAnimationFrame(function step(currentTime) { start = !start ? currentTime : start; const progress = currentTime - start; if (currentPos < pos) { window.scrollTo(0, ((pos - currentPos) * progress) / time + currentPos); } else { window.scrollTo(0, currentPos - ((currentPos - pos) * progress) / time); } if (progress < time) { window.requestAnimationFrame(step); } else { window.scrollTo(0, pos); } }); }, initJustifiedGallery: function (selector) { const runJustifiedGallery = i => { if (!anzhiyu.isHidden(i)) { fjGallery(i, { itemSelector: ".fj-gallery-item", rowHeight: i.getAttribute("data-rowHeight"), gutter: 4, onJustify: function () { this.$container.style.opacity = "1"; }, }); } }; if (Array.from(selector).length === 0) runJustifiedGallery(selector); else selector.forEach(i => { runJustifiedGallery(i); }); }, animateIn: (ele, text) => { ele.style.display = "block"; ele.style.animation = text; }, animateOut: (ele, text) => { ele.addEventListener("animationend", function f() { ele.style.display = ""; ele.style.animation = ""; ele.removeEventListener("animationend", f); }); ele.style.animation = text; }, /** * @param {*} selector * @param {*} eleType the type of create element * @param {*} options object key: value */ wrap: (selector, eleType, options) => { const creatEle = document.createElement(eleType); for (const [key, value] of Object.entries(options)) { creatEle.setAttribute(key, value); } selector.parentNode.insertBefore(creatEle, selector); creatEle.appendChild(selector); }, isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0, getEleTop: ele => { let actualTop = ele.offsetTop; let current = ele.offsetParent; while (current !== null) { actualTop += current.offsetTop; current = current.offsetParent; } return actualTop; }, loadLightbox: ele => { const service = GLOBAL_CONFIG.lightbox; if (service === "mediumZoom") { const zoom = mediumZoom(ele); zoom.on("open", e => { const photoBg = document.documentElement.getAttribute("data-theme") === "dark" ? "#121212" : "#fff"; zoom.update({ background: photoBg, }); }); } if (service === "fancybox") { Array.from(ele).forEach(i => { if (i.parentNode.tagName !== "A") { const dataSrc = i.dataset.lazySrc || i.src; const dataCaption = i.title || i.alt || ""; anzhiyu.wrap(i, "a", { href: dataSrc, "data-fancybox": "gallery", "data-caption": dataCaption, "data-thumb": dataSrc, }); } }); if (!window.fancyboxRun) { Fancybox.bind("[data-fancybox]", { Hash: false, Thumbs: { autoStart: false, }, }); window.fancyboxRun = true; } } }, setLoading: { add: ele => { const html = `
`; ele.insertAdjacentHTML("afterend", html); }, remove: ele => { ele.nextElementSibling.remove(); }, }, updateAnchor: anchor => { if (anchor !== window.location.hash) { if (!anchor) anchor = location.pathname; const title = GLOBAL_CONFIG_SITE.title; window.history.replaceState( { url: location.href, title, }, title, anchor ); } }, getScrollPercent: (currentTop, ele) => { const docHeight = ele.clientHeight; const winHeight = document.documentElement.clientHeight; const headerHeight = ele.offsetTop; const contentMath = docHeight > winHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight; const scrollPercent = (currentTop - headerHeight) / contentMath; const scrollPercentRounded = Math.round(scrollPercent * 100); const percentage = scrollPercentRounded > 100 ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded; return percentage; }, addGlobalFn: (key, fn, name = false, parent = window) => { const globalFn = parent.globalFn || {}; const keyObj = globalFn[key] || {}; if (name && keyObj[name]) return; name = name || Object.keys(keyObj).length; keyObj[name] = fn; globalFn[key] = keyObj; parent.globalFn = globalFn; }, addEventListenerPjax: (ele, event, fn, option = false) => { ele.addEventListener(event, fn, option); anzhiyu.addGlobalFn("pjax", () => { ele.removeEventListener(event, fn, option); }); }, removeGlobalFnEvent: (key, parent = window) => { const { globalFn = {} } = parent; const keyObj = globalFn[key] || {}; const keyArr = Object.keys(keyObj); if (!keyArr.length) return; keyArr.forEach(i => { keyObj[i](); }); delete parent.globalFn[key]; }, //更改主题色 changeThemeMetaColor: function (color) { // console.info(`%c ${color}`, `font-size:36px;color:${color};`); if (themeColorMeta !== null) { themeColorMeta.setAttribute("content", color); } }, //顶栏自适应主题色 initThemeColor: function () { let themeColor = getComputedStyle(document.documentElement) .getPropertyValue("--anzhiyu-bar-background") .trim() .replace('"', "") .replace('"', ""); const currentTop = window.scrollY || document.documentElement.scrollTop; if (currentTop > 26) { if (anzhiyu.is_Post()) { themeColor = getComputedStyle(document.documentElement) .getPropertyValue("--anzhiyu-meta-theme-post-color") .trim() .replace('"', "") .replace('"', ""); } if (themeColorMeta.getAttribute("content") === themeColor) return; this.changeThemeMetaColor(themeColor); } else { if (themeColorMeta.getAttribute("content") === themeColor) return; this.changeThemeMetaColor(themeColor); } }, //是否是文章页 is_Post: function () { var url = window.location.href; //获取url if (url.indexOf("/posts/") >= 0) { //判断url地址中是否包含code字符串 return true; } else { return false; } }, //监测是否在页面开头 addNavBackgroundInit: function () { var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0; if ($bodyWrap) { bodyScrollTop = $bodyWrap.scrollTop; } if (document.documentElement) { documentScrollTop = document.documentElement.scrollTop; } scrollTop = bodyScrollTop - documentScrollTop > 0 ? bodyScrollTop : documentScrollTop; if (scrollTop != 0) { pageHeaderEl.classList.add("nav-fixed"); pageHeaderEl.classList.add("nav-visible"); } }, // 下载图片 downloadImage: function (imgsrc, name) { //下载图片地址和图片名 rm.hideRightMenu(); if (rm.downloadimging == false) { rm.downloadimging = true; anzhiyu.snackbarShow("正在下载中,请稍后", false, 10000); setTimeout(function () { let image = new Image(); // 解决跨域 Canvas 污染问题 image.setAttribute("crossOrigin", "anonymous"); image.onload = function () { let canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; let context = canvas.getContext("2d"); context.drawImage(image, 0, 0, image.width, image.height); let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据 let a = document.createElement("a"); // 生成一个a元素 let event = new MouseEvent("click"); // 创建一个单击事件 a.download = name || "photo"; // 设置图片名称 a.href = url; // 将生成的URL设置为a.href属性 a.dispatchEvent(event); // 触发a的单击事件 }; image.src = imgsrc; anzhiyu.snackbarShow("图片已添加盲水印,请遵守版权协议"); rm.downloadimging = false; }, "10000"); } else { anzhiyu.snackbarShow("有正在进行中的下载,请稍后再试"); } }, //禁止图片右键单击 stopImgRightDrag: function () { var img = document.getElementsByTagName("img"); for (var i = 0; i < img.length; i++) { img[i].addEventListener("dragstart", function () { return false; }); } }, //滚动到指定id scrollTo: function (id) { var domTop = document.querySelector(id).offsetTop; window.scrollTo(0, domTop - 80); }, //隐藏侧边栏 hideAsideBtn: () => { // Hide aside const $htmlDom = document.documentElement.classList; $htmlDom.contains("hide-aside") ? saveToLocal.set("aside-status", "show", 2) : saveToLocal.set("aside-status", "hide", 2); $htmlDom.toggle("hide-aside"); $htmlDom.contains("hide-aside") ? document.querySelector("#consoleHideAside").classList.add("on") : document.querySelector("#consoleHideAside").classList.remove("on"); }, // 热评切换 switchCommentBarrage: function () { let commentBarrage = document.querySelector(".comment-barrage"); if (commentBarrage) { if (window.getComputedStyle(commentBarrage).display === "flex") { commentBarrage.style.display = "none"; anzhiyu.snackbarShow("✨ 已关闭评论弹幕"); document.querySelector(".menu-commentBarrage-text").textContent = "显示热评"; document.querySelector("#consoleCommentBarrage").classList.remove("on"); localStorage.setItem("commentBarrageSwitch", "false"); } else { commentBarrage.style.display = "flex"; document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评"; document.querySelector("#consoleCommentBarrage").classList.add("on"); anzhiyu.snackbarShow("✨ 已开启评论弹幕"); localStorage.removeItem("commentBarrageSwitch"); } } rm && rm.hideRightMenu(); }, initPaginationObserver: () => { const commentElement = document.getElementById("post-comment"); const paginationElement = document.getElementById("pagination"); if (commentElement && paginationElement) { new IntersectionObserver(entries => { const commentBarrage = document.querySelector(".comment-barrage"); entries.forEach(entry => { if (entry.isIntersecting) { paginationElement.classList.add("show-window"); if (commentBarrage) { commentBarrage.style.bottom = "-200px"; } } else { paginationElement.classList.remove("show-window"); if (commentBarrage) { commentBarrage.style.bottom = "0px"; } } }); }).observe(commentElement); } }, // 初始化即刻 initIndexEssay: function () { if (!document.getElementById("bbTimeList")) return; setTimeout(() => { let essay_bar_swiper = new Swiper(".essay_bar_swiper_container", { passiveListeners: true, direction: "vertical", loop: true, autoplay: { disableOnInteraction: true, delay: 3000, }, mousewheel: true, }); let essay_bar_comtainer = document.getElementById("bbtalk"); if (essay_bar_comtainer !== null) { essay_bar_comtainer.onmouseenter = function () { essay_bar_swiper.autoplay.stop(); }; essay_bar_comtainer.onmouseleave = function () { essay_bar_swiper.autoplay.start(); }; } }, 100); }, scrollByMouseWheel: function ($list, $target) { const scrollHandler = function (e) { $list.scrollLeft -= e.wheelDelta / 2; e.preventDefault(); }; $list.addEventListener("mousewheel", scrollHandler, { passive: false }); if ($target) { $target.classList.add("selected"); $list.scrollLeft = $target.offsetLeft - $list.offsetLeft - ($list.offsetWidth - $target.offsetWidth) / 2; } }, // catalog激活 catalogActive: function () { const $list = document.getElementById("catalog-list"); if ($list) { const pathname = decodeURIComponent(window.location.pathname); const catalogListItems = $list.querySelectorAll(".catalog-list-item"); let $catalog = null; catalogListItems.forEach(item => { if (pathname.startsWith(item.id)) { $catalog = item; return; } }); anzhiyu.scrollByMouseWheel($list, $catalog); } }, // Page Tag 激活 tagsPageActive: function () { const $list = document.getElementById("tag-page-tags"); if ($list) { const $tagPageTags = document.getElementById(decodeURIComponent(window.location.pathname)); anzhiyu.scrollByMouseWheel($list, $tagPageTags); } }, // 修改时间显示"最近" diffDate: function (d, more = false, simple = false) { const dateNow = new Date(); const datePost = new Date(d); const dateDiff = dateNow.getTime() - datePost.getTime(); const minute = 1000 * 60; const hour = minute * 60; const day = hour * 24; const month = day * 30; let result; if (more) { const monthCount = dateDiff / month; const dayCount = dateDiff / day; const hourCount = dateDiff / hour; const minuteCount = dateDiff / minute; if (monthCount >= 1) { result = datePost.toLocaleDateString().replace(/\//g, "-"); } else if (dayCount >= 1) { result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day; } else if (hourCount >= 1) { result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour; } else if (minuteCount >= 1) { result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min; } else { result = GLOBAL_CONFIG.date_suffix.just; } } else if (simple) { const monthCount = dateDiff / month; const dayCount = dateDiff / day; const hourCount = dateDiff / hour; const minuteCount = dateDiff / minute; if (monthCount >= 1) { result = datePost.toLocaleDateString().replace(/\//g, "-"); } else if (dayCount >= 1 && dayCount <= 3) { result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day; } else if (dayCount > 3) { result = datePost.getMonth() + 1 + "/" + datePost.getDate(); } else if (hourCount >= 1) { result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour; } else if (minuteCount >= 1) { result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min; } else { result = GLOBAL_CONFIG.date_suffix.just; } } else { result = parseInt(dateDiff / day); } return result; }, // 修改即刻中的时间显示 changeTimeInEssay: function () { document.querySelector("#bber") && document.querySelectorAll("#bber time").forEach(function (e) { var t = e, datetime = t.getAttribute("datetime"); (t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline"); }); }, // 修改相册集中的时间 changeTimeInAlbumDetail: function () { document.querySelector("#album_detail") && document.querySelectorAll("#album_detail time").forEach(function (e) { var t = e, datetime = t.getAttribute("datetime"); (t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline"); }); }, // 刷新瀑布流 reflashEssayWaterFall: function () { const waterfallEl = document.getElementById("waterfall"); if (waterfallEl) { setTimeout(function () { waterfall(waterfallEl); waterfallEl.classList.add("show"); }, 800); } }, sayhi: function () { const $sayhiEl = document.getElementById("author-info__sayhi"); const getTimeState = () => { const hour = new Date().getHours(); let message = ""; if (hour >= 0 && hour <= 5) { message = "睡个好觉,保证精力充沛"; } else if (hour > 5 && hour <= 10) { message = "一日之计在于晨"; } else if (hour > 10 && hour <= 14) { message = "吃饱了才有力气干活"; } else if (hour > 14 && hour <= 18) { message = "集中精力,攻克难关"; } else if (hour > 18 && hour <= 24) { message = "不要太劳累了,早睡更健康"; } return message; }; if ($sayhiEl) { $sayhiEl.innerHTML = getTimeState(); } }, // 友链注入预设评论 addFriendLink() { var input = document.getElementsByClassName("el-textarea__inner")[0]; if (!input) return; const evt = new Event("input", { cancelable: true, bubbles: true }); const defaultPlaceholder = "昵称(请勿包含博客等字样):\n网站地址(要求博客地址,请勿提交个人主页):\n头像图片url(请提供尽可能清晰的图片,我会上传到我自己的图床):\n描述:\n站点截图(可选):\n"; input.value = this.getConfigIfPresent(GLOBAL_CONFIG.linkPageTop, "addFriendPlaceholder", defaultPlaceholder); input.dispatchEvent(evt); input.focus(); input.setSelectionRange(-1, -1); }, // 获取配置,如果为空则返回默认值 getConfigIfPresent: function (config, configKey, defaultValue) { if (!config) return defaultValue; if (!config.hasOwnProperty(configKey)) return defaultValue; if (!config[configKey]) return defaultValue; return config[configKey]; }, //切换音乐播放状态 musicToggle: function (changePaly = true) { if (!anzhiyu_musicFirst) { anzhiyu.musicBindEvent(); anzhiyu_musicFirst = true; } let msgPlay = '播放音乐'; let msgPause = '暂停音乐'; if (anzhiyu_musicPlaying) { navMusicEl.classList.remove("playing"); document.getElementById("menu-music-toggle").innerHTML = msgPlay; document.getElementById("nav-music-hoverTips").innerHTML = "音乐已暂停"; document.querySelector("#consoleMusic").classList.remove("on"); anzhiyu_musicPlaying = false; navMusicEl.classList.remove("stretch"); } else { navMusicEl.classList.add("playing"); document.getElementById("menu-music-toggle").innerHTML = msgPause; document.querySelector("#consoleMusic").classList.add("on"); anzhiyu_musicPlaying = true; navMusicEl.classList.add("stretch"); } if (changePaly) document.querySelector("#nav-music meting-js").aplayer.toggle(); rm && rm.hideRightMenu(); }, // 音乐伸缩 musicTelescopic: function () { if (navMusicEl.classList.contains("stretch")) { navMusicEl.classList.remove("stretch"); } else { navMusicEl.classList.add("stretch"); } }, //音乐上一曲 musicSkipBack: function () { navMusicEl.querySelector("meting-js").aplayer.skipBack(); rm && rm.hideRightMenu(); }, //音乐下一曲 musicSkipForward: function () { navMusicEl.querySelector("meting-js").aplayer.skipForward(); rm && rm.hideRightMenu(); }, //获取音乐中的名称 musicGetName: function () { var x = document.querySelector(".aplayer-title"); var arr = []; for (var i = x.length - 1; i >= 0; i--) { arr[i] = x[i].innerText; } return arr[0]; }, //初始化console图标 initConsoleState: function () { //初始化隐藏边栏 const $htmlDomClassList = document.documentElement.classList; $htmlDomClassList.contains("hide-aside") ? document.querySelector("#consoleHideAside").classList.add("on") : document.querySelector("#consoleHideAside").classList.remove("on"); }, // 显示打赏中控台 rewardShowConsole: function () { // 判断是否为赞赏打开控制台 consoleEl.classList.add("reward-show"); anzhiyu.initConsoleState(); }, // 显示中控台 showConsole: function () { consoleEl.classList.add("show"); anzhiyu.initConsoleState(); }, //隐藏中控台 hideConsole: function () { if (consoleEl.classList.contains("show")) { // 如果是一般控制台,就关闭一般控制台 consoleEl.classList.remove("show"); } else if (consoleEl.classList.contains("reward-show")) { // 如果是打赏控制台,就关闭打赏控制台 consoleEl.classList.remove("reward-show"); } // 获取center-console元素 const centerConsole = document.getElementById("center-console"); // 检查center-console是否被选中 if (centerConsole.checked) { // 取消选中状态 centerConsole.checked = false; } }, // 取消加载动画 hideLoading: function () { document.getElementById("loading-box").classList.add("loaded"); }, // 将音乐缓存播放 cacheAndPlayMusic() { let data = localStorage.getItem("musicData"); if (data) { data = JSON.parse(data); const currentTime = new Date().getTime(); if (currentTime - data.timestamp < 24 * 60 * 60 * 1000) { // 如果缓存的数据没有过期,直接使用 anzhiyu.playMusic(data.songs); return; } } // 否则重新从服务器获取数据 fetch("/json/music.json") .then(response => response.json()) .then(songs => { const cacheData = { timestamp: new Date().getTime(), songs: songs, }; localStorage.setItem("musicData", JSON.stringify(cacheData)); anzhiyu.playMusic(songs); }); }, // 播放音乐 playMusic(songs) { const anMusicPage = document.getElementById("anMusic-page"); const metingAplayer = anMusicPage.querySelector("meting-js").aplayer; const randomIndex = Math.floor(Math.random() * songs.length); const randomSong = songs[randomIndex]; const allAudios = metingAplayer.list.audios; if (!selectRandomSong.includes(randomSong.name)) { // 如果随机到的歌曲已经未被随机到过,就添加进metingAplayer.list metingAplayer.list.add([randomSong]); // 播放最后一首(因为是添加到了最后) metingAplayer.list.switch(allAudios.length); // 添加到已被随机的歌曲列表 selectRandomSong.push(randomSong.name); } else { // 随机到的歌曲已经在播放列表中了 // 直接继续随机直到随机到没有随机过的歌曲,如果全部随机过了就切换到对应的歌曲播放即可 let songFound = false; while (!songFound) { const newRandomIndex = Math.floor(Math.random() * songs.length); const newRandomSong = songs[newRandomIndex]; if (!selectRandomSong.includes(newRandomSong.name)) { metingAplayer.list.add([newRandomSong]); metingAplayer.list.switch(allAudios.length); selectRandomSong.push(newRandomSong.name); songFound = true; } // 如果全部歌曲都已被随机过,跳出循环 if (selectRandomSong.length === songs.length) { break; } } if (!songFound) { // 如果全部歌曲都已被随机过,切换到对应的歌曲播放 const palyMusicIndex = allAudios.findIndex(song => song.name === randomSong.name); if (palyMusicIndex != -1) metingAplayer.list.switch(palyMusicIndex); } } console.info("已随机歌曲:", selectRandomSong, "本次随机歌曲:", randomSong.name); }, // 音乐节目切换背景 changeMusicBg: function (isChangeBg = true) { const anMusicBg = document.getElementById("an_music_bg"); if (isChangeBg) { // player listswitch 会进入此处 const musiccover = document.querySelector("#anMusic-page .aplayer-pic"); anMusicBg.style.backgroundImage = musiccover.style.backgroundImage; } else { // 第一次进入,绑定事件,改背景 let timer = setInterval(() => { const musiccover = document.querySelector("#anMusic-page .aplayer-pic"); // 确保player加载完成 if (musiccover) { clearInterval(timer); // 绑定事件 anzhiyu.addEventListenerMusic(); // 确保第一次能够正确替换背景 anzhiyu.changeMusicBg(); // 暂停nav的音乐 if ( document.querySelector("#nav-music meting-js").aplayer && !document.querySelector("#nav-music meting-js").aplayer.audio.paused ) { anzhiyu.musicToggle(); } } }, 100); } }, // 获取自定义播放列表 getCustomPlayList: function () { if (!window.location.pathname.startsWith("/music/")) { return; } const urlParams = new URLSearchParams(window.location.search); const userId = "8152976493"; const userServer = "netease"; const anMusicPageMeting = document.getElementById("anMusic-page-meting"); if (urlParams.get("id") && urlParams.get("server")) { const id = urlParams.get("id"); const server = urlParams.get("server"); anMusicPageMeting.innerHTML = ``; } else { anMusicPageMeting.innerHTML = ``; } anzhiyu.changeMusicBg(false); }, //隐藏今日推荐 hideTodayCard: function () { if (document.getElementById("todayCard")) { document.getElementById("todayCard").classList.add("hide"); const topGroup = document.querySelector(".topGroup"); const recentPostItems = topGroup.querySelectorAll(".recent-post-item"); recentPostItems.forEach(item => { item.style.display = "flex"; }); } }, // 监听音乐背景改变 addEventListenerMusic: function () { const anMusicPage = document.getElementById("anMusic-page"); const aplayerIconMenu = anMusicPage.querySelector(".aplayer-info .aplayer-time .aplayer-icon-menu"); const anMusicBtnGetSong = anMusicPage.querySelector("#anMusicBtnGetSong"); const anMusicRefreshBtn = anMusicPage.querySelector("#anMusicRefreshBtn"); const anMusicSwitchingBtn = anMusicPage.querySelector("#anMusicSwitching"); const metingAplayer = anMusicPage.querySelector("meting-js").aplayer; //初始化音量 metingAplayer.volume(0.8, true); metingAplayer.on("loadeddata", function () { anzhiyu.changeMusicBg(); }); aplayerIconMenu.addEventListener("click", function () { document.getElementById("menu-mask").style.display = "block"; document.getElementById("menu-mask").style.animation = "0.5s ease 0s 1 normal none running to_show"; anMusicPage.querySelector(".aplayer.aplayer-withlist .aplayer-list").style.opacity = "1"; }); function anMusicPageMenuAask() { if (window.location.pathname != "/music/") { document.getElementById("menu-mask").removeEventListener("click", anMusicPageMenuAask); return; } anMusicPage.querySelector(".aplayer-list").classList.remove("aplayer-list-hide"); } document.getElementById("menu-mask").addEventListener("click", anMusicPageMenuAask); // 监听增加单曲按钮 anMusicBtnGetSong.addEventListener("click", () => { if (changeMusicListFlag) { const anMusicPage = document.getElementById("anMusic-page"); const metingAplayer = anMusicPage.querySelector("meting-js").aplayer; const allAudios = metingAplayer.list.audios; const randomIndex = Math.floor(Math.random() * allAudios.length); // 随机播放一首 metingAplayer.list.switch(randomIndex); } else { anzhiyu.cacheAndPlayMusic(); } }); anMusicRefreshBtn.addEventListener("click", () => { localStorage.removeItem("musicData"); anzhiyu.snackbarShow("已移除相关缓存歌曲"); }); anMusicSwitchingBtn.addEventListener("click", () => { anzhiyu.changeMusicList(); }); // 监听键盘事件 //空格控制音乐 document.addEventListener("keydown", function (event) { //暂停开启音乐 if (event.code === "Space") { event.preventDefault(); metingAplayer.toggle(); } //切换下一曲 if (event.keyCode === 39) { event.preventDefault(); metingAplayer.skipForward(); } //切换上一曲 if (event.keyCode === 37) { event.preventDefault(); metingAplayer.skipBack(); } //增加音量 if (event.keyCode === 38) { if (musicVolume <= 1) { musicVolume += 0.1; metingAplayer.volume(musicVolume, true); } } //减小音量 if (event.keyCode === 40) { if (musicVolume >= 0) { musicVolume += -0.1; metingAplayer.volume(musicVolume, true); } } }); }, // 切换歌单 changeMusicList: async function () { const anMusicPage = document.getElementById("anMusic-page"); const metingAplayer = anMusicPage.querySelector("meting-js").aplayer; const currentTime = new Date().getTime(); const cacheData = JSON.parse(localStorage.getItem("musicData")) || { timestamp: 0 }; let songs = []; if (changeMusicListFlag) { songs = defaultPlayMusicList; } else { // 保存当前默认播放列表,以使下次可以切换回来 defaultPlayMusicList = metingAplayer.list.audios; // 如果缓存的数据没有过期,直接使用 if (currentTime - cacheData.timestamp < 24 * 60 * 60 * 1000) { songs = cacheData.songs; } else { // 否则重新从服务器获取数据 const response = await fetch("/json/music.json"); songs = await response.json(); cacheData.timestamp = currentTime; cacheData.songs = songs; localStorage.setItem("musicData", JSON.stringify(cacheData)); } } // 清除当前播放列表并添加新的歌曲 metingAplayer.list.clear(); metingAplayer.list.add(songs); // 切换标志位 changeMusicListFlag = !changeMusicListFlag; }, // 控制台音乐列表监听 addEventListenerConsoleMusicList: function () { const navMusic = document.getElementById("nav-music"); if (!navMusic) return; navMusic.addEventListener("click", e => { const aplayerList = navMusic.querySelector(".aplayer-list"); const listBtn = navMusic.querySelector( "div.aplayer-info > div.aplayer-controller > div.aplayer-time.aplayer-time-narrow > button.aplayer-icon.aplayer-icon-menu svg" ); if (e.target != listBtn && aplayerList.classList.contains("aplayer-list-hide")) { aplayerList.classList.remove("aplayer-list-hide"); } }); }, // 监听按键 toPage: function () { var toPageText = document.getElementById("toPageText"), toPageButton = document.getElementById("toPageButton"), pageNumbers = document.querySelectorAll(".page-number"), lastPageNumber = Number(pageNumbers[pageNumbers.length - 1].innerHTML), pageNumber = Number(toPageText.value); if (!isNaN(pageNumber) && pageNumber >= 1 && Number.isInteger(pageNumber)) { var url = "/page/" + (pageNumber > lastPageNumber ? lastPageNumber : pageNumber) + "/"; toPageButton.href = pageNumber === 1 ? "/" : url; } else { toPageButton.href = "javascript:void(0);"; } }, //删除多余的class removeBodyPaceClass: function () { document.body.className = "pace-done"; }, // 修改body的type类型以适配css setValueToBodyType: function () { const input = document.getElementById("page-type"); // 获取input元素 const value = input.value; // 获取input的value值 document.body.dataset.type = value; // 将value值赋值到body的type属性上 }, //匿名评论 addRandomCommentInfo: function () { // 从形容词数组中随机取一个值 const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)]; // 从蔬菜水果动物名字数组中随机取一个值 const randomName = vegetablesAndFruits[Math.floor(Math.random() * vegetablesAndFruits.length)]; // 将两个值组合成一个字符串 const name = `${randomAdjective}${randomName}`; function dr_js_autofill_commentinfos() { var lauthor = [ "#author", "input[name='comname']", "#inpName", "input[name='author']", "#ds-dialog-name", "#name", "input[name='nick']", "#comment_author", ], lmail = [ "#mail", "#email", "input[name='commail']", "#inpEmail", "input[name='email']", "#ds-dialog-email", "input[name='mail']", "#comment_email", ], lurl = [ "#url", "input[name='comurl']", "#inpHomePage", "#ds-dialog-url", "input[name='url']", "input[name='website']", "#website", "input[name='link']", "#comment_url", ]; for (var i = 0; i < lauthor.length; i++) { var author = document.querySelector(lauthor[i]); if (author != null) { author.value = name; author.dispatchEvent(new Event("input")); author.dispatchEvent(new Event("change")); break; } } for (var j = 0; j < lmail.length; j++) { var mail = document.querySelector(lmail[j]); if (mail != null) { mail.value = visitorMail; mail.dispatchEvent(new Event("input")); mail.dispatchEvent(new Event("change")); break; } } return !1; } dr_js_autofill_commentinfos(); var input = document.getElementsByClassName("el-textarea__inner")[0]; input.focus(); input.setSelectionRange(-1, -1); }, // 跳转开往 totraveling: function () { anzhiyu.snackbarShow( "即将跳转到「开往」项目的成员博客,不保证跳转网站的安全性和可用性", element => { element.style.opacity = 0; travellingsTimer && clearTimeout(travellingsTimer); }, 5000, "取消" ); travellingsTimer = setTimeout(function () { window.open("https://www.travellings.cn/go.html", "_blank"); }, "5000"); }, // 工具函数替换字符串 replaceAll: function (e, n, t) { return e.split(n).join(t); }, // 音乐绑定事件 musicBindEvent: function () { document.querySelector("#nav-music .aplayer-music").addEventListener("click", function () { anzhiyu.musicTelescopic(); }); document.querySelector("#nav-music .aplayer-button").addEventListener("click", function () { anzhiyu.musicToggle(false); }); }, // 判断是否是移动端 hasMobile: function () { let isMobile = false; if ( navigator.userAgent.match( /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i ) || document.body.clientWidth < 800 ) { // 移动端 isMobile = true; } return isMobile; }, // 创建二维码 qrcodeCreate: function () { if (document.getElementById("qrcode")) { document.getElementById("qrcode").innerHTML = ""; var qrcode = new QRCode(document.getElementById("qrcode"), { text: window.location.href, width: 250, height: 250, colorDark: "#000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H, }); } }, // 判断是否在el内 isInViewPortOfOne: function (el) { if (!el) return; const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; const offsetTop = el.offsetTop; const scrollTop = document.documentElement.scrollTop; const top = offsetTop - scrollTop; return top <= viewPortHeight; }, //添加赞赏蒙版 addRewardMask: function () { if (!document.querySelector(".reward-main")) return; document.querySelector(".reward-main").style.display = "flex"; document.querySelector(".reward-main").style.zIndex = "102"; document.getElementById("quit-box").style.display = "flex"; }, // 移除赞赏蒙版 removeRewardMask: function () { if (!document.querySelector(".reward-main")) return; document.querySelector(".reward-main").style.display = "none"; document.getElementById("quit-box").style.display = "none"; }, keyboardToggle: function () { const isKeyboardOn = anzhiyu_keyboard; if (isKeyboardOn) { const consoleKeyboard = document.querySelector("#consoleKeyboard"); consoleKeyboard.classList.remove("on"); anzhiyu_keyboard = false; } else { const consoleKeyboard = document.querySelector("#consoleKeyboard"); consoleKeyboard.classList.add("on"); anzhiyu_keyboard = true; } localStorage.setItem("keyboardToggle", isKeyboardOn ? "false" : "true"); }, rightMenuToggle: function () { if (window.oncontextmenu) { window.oncontextmenu = null; } else if (!window.oncontextmenu && oncontextmenuFunction) { window.oncontextmenu = oncontextmenuFunction; } }, switchConsole: () => { // switch console const consoleEl = document.getElementById("console"); //初始化隐藏边栏 const $htmlDom = document.documentElement.classList; $htmlDom.contains("hide-aside") ? document.querySelector("#consoleHideAside").classList.add("on") : document.querySelector("#consoleHideAside").classList.remove("on"); if (consoleEl.classList.contains("show")) { consoleEl.classList.remove("show"); } else { consoleEl.classList.add("show"); } const consoleKeyboard = document.querySelector("#consoleKeyboard"); if (consoleKeyboard) { if (localStorage.getItem("keyboardToggle") === "true") { consoleKeyboard.classList.add("on"); anzhiyu_keyboard = true; } else { consoleKeyboard.classList.remove("on"); anzhiyu_keyboard = false; } } }, // 定义 intersectionObserver 函数,并接收两个可选参数 intersectionObserver: function (enterCallback, leaveCallback) { let observer; return () => { if (!observer) { observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.intersectionRatio > 0) { enterCallback?.(); } else { leaveCallback?.(); } }); }); } else { // 如果 observer 对象已经存在,则先取消对之前元素的观察 observer.disconnect(); } return observer; }; }, // CategoryBar滚动 scrollCategoryBarToRight: function () { // 获取需要操作的元素 const items = document.getElementById("catalog-list"); const nextButton = document.getElementById("category-bar-next"); // 检查元素是否存在 if (items && nextButton) { const itemsWidth = items.clientWidth; // 判断是否已经滚动到最右侧 if (items.scrollLeft + items.clientWidth + 1 >= items.scrollWidth) { // 滚动到初始位置并更新按钮内容 items.scroll({ left: 0, behavior: "smooth", }); nextButton.innerHTML = ''; } else { // 滚动到下一个视图 items.scrollBy({ left: itemsWidth, behavior: "smooth", }); } } else { console.error("Element(s) not found: 'catalog-list' and/or 'category-bar-next'."); } }, // 分类条 categoriesBarActive: function () { const urlinfo = decodeURIComponent(window.location.pathname); const $categoryBar = document.getElementById("category-bar"); if (!$categoryBar) return; if (urlinfo === "/") { $categoryBar.querySelector("#首页").classList.add("select"); } else { const pattern = /\/categories\/.*?\//; const patbool = pattern.test(urlinfo); if (!patbool) return; const nowCategorie = urlinfo.split("/")[2]; $categoryBar.querySelector(`#${nowCategorie}`).classList.add("select"); } }, topCategoriesBarScroll: function () { const $categoryBarItems = document.getElementById("category-bar-items"); if (!$categoryBarItems) return; $categoryBarItems.addEventListener("mousewheel", function (e) { const v = -e.wheelDelta / 2; this.scrollLeft += v; e.preventDefault(); }); }, // 切换菜单显示热评 switchRightClickMenuHotReview: function () { const postComment = document.getElementById("post-comment"); const menuCommentBarrageDom = document.getElementById("menu-commentBarrage"); if (postComment) { menuCommentBarrageDom.style.display = "flex"; } else { menuCommentBarrageDom.style.display = "none"; } }, // 切换作者卡片状态文字 changeSayHelloText: function () { const greetings = GLOBAL_CONFIG.authorStatus.skills; const authorInfoSayHiElement = document.getElementById("author-info__sayhi"); // 如果只有一个问候语,设置为默认值 if (greetings.length === 1) { authorInfoSayHiElement.textContent = greetings[0]; return; } let lastSayHello = authorInfoSayHiElement.textContent; let randomGreeting = lastSayHello; while (randomGreeting === lastSayHello) { randomGreeting = greetings[Math.floor(Math.random() * greetings.length)]; } authorInfoSayHiElement.textContent = randomGreeting; }, }; const anzhiyuPopupManager = { queue: [], processing: false, Jump: false, enqueuePopup(title, tip, url, duration = 3000) { this.queue.push({ title, tip, url, duration }); if (!this.processing) { this.processQueue(); } }, processQueue() { if (this.queue.length > 0 && !this.processing) { this.processing = true; const { title, tip, url, duration } = this.queue.shift(); this.popupShow(title, tip, url, duration); } }, popupShow(title, tip, url, duration) { const popupWindow = document.getElementById("popup-window"); if (!popupWindow) return; const windowTitle = popupWindow.querySelector(".popup-window-title"); const windowContent = popupWindow.querySelector(".popup-window-content"); const cookiesTip = windowContent.querySelector(".popup-tip"); if (popupWindow.classList.contains("show-popup-window")) { popupWindow.classList.add("popup-hide"); } // 等待上一个弹窗完全消失 setTimeout(() => { // 移除之前的点击事件处理程序 popupWindow.removeEventListener("click", this.clickEventHandler); if (url) { if (window.pjax) { this.clickEventHandler = event => { event.preventDefault(); pjax.loadUrl(url); popupWindow.classList.remove("show-popup-window"); popupWindow.classList.remove("popup-hide"); this.Jump = true; // 处理队列中的下一个弹出窗口 this.processing = false; this.processQueue(); }; popupWindow.addEventListener("click", this.clickEventHandler); } else { this.clickEventHandler = () => { window.location.href = url; }; popupWindow.addEventListener("click", this.clickEventHandler); } if (popupWindow.classList.contains("no-url")) { popupWindow.classList.remove("no-url"); } } else { if (!popupWindow.classList.contains("no-url")) { popupWindow.classList.add("no-url"); } this.clickEventHandler = () => { popupWindow.classList.add("popup-hide"); setTimeout(() => { popupWindow.classList.remove("popup-hide"); popupWindow.classList.remove("show-popup-window"); }, 1000); }; popupWindow.addEventListener("click", this.clickEventHandler); } if (popupWindow.classList.contains("popup-hide")) { popupWindow.classList.remove("popup-hide"); } popupWindow.classList.add("show-popup-window"); windowTitle.textContent = title; cookiesTip.textContent = tip; }, 800); setTimeout(() => { if (url && !this.Jump) { this.Jump = false; } if (!popupWindow.classList.contains("popup-hide") && popupWindow.className != "") { popupWindow.classList.add("popup-hide"); } // 处理队列中的下一个弹出窗口 this.processing = false; this.processQueue(); }, duration); }, };