PageSourceSearch

https://cvestone.github.io/js/utils.js

js cvestone.github.io collected 2026-10-03 08:50:47 UTC 48,579 bytes, 1,440 lines download raw bytes

1const anzhiyu = {
2  debounce: (func, wait = 0, immediate = false) => {
3    let timeout;
4    return (...args) => {
5      const later = () => {
6        timeout = null;
7        if (!immediate) func(...args);
8      };
9      const callNow = immediate && !timeout;
10      clearTimeout(timeout);
11      timeout = setTimeout(later, wait);
12      if (callNow) func(...args);
13    };
14  },
15
16  throttle: function (func, wait, options = {}) {
17    let timeout, context, args;
18    let previous = 0;
19
20    const later = () => {
21      previous = options.leading === false ? 0 : new Date().getTime();
22      timeout = null;
23      func.apply(context, args);
24      if (!timeout) context = args = null;
25    };
26
27    const throttled = (...params) => {
28      const now = new Date().getTime();
29      if (!previous && options.leading === false) previous = now;
30      const remaining = wait - (now - previous);
31      context = this;
32      args = params;
33      if (remaining <= 0 || remaining > wait) {
34        if (timeout) {
35          clearTimeout(timeout);
36          timeout = null;
37        }
38        previous = now;
39        func.apply(context, args);
40        if (!timeout) context = args = null;
41      } else if (!timeout && options.trailing !== false) {
42        timeout = setTimeout(later, remaining);
43      }
44    };
45
46    return throttled;
47  },
48
49  sidebarPaddingR: () => {
50    const innerWidth = window.innerWidth;
51    const clientWidth = document.body.clientWidth;
52    const paddingRight = innerWidth - clientWidth;
53    if (innerWidth !== clientWidth) {
54      document.body.style.paddingRight = paddingRight + "px";
55    }
56  },
57
58  snackbarShow: (text, showActionFunction = false, duration = 2000, actionText = false) => {
59    const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar;
60    const bg = document.documentElement.getAttribute("data-theme") === "light" ? bgLight : bgDark;
61    const root = document.querySelector(":root");
62    root.style.setProperty("--anzhiyu-snackbar-time", duration + "ms");
63
64    Snackbar.show({
65      text: text,
66      backgroundColor: bg,
67      onActionClick: showActionFunction,
68      actionText: actionText,
69      showAction: actionText,
70      duration: duration,
71      pos: position,
72      customClass: "snackbar-css",
73    });
74  },
75
76  loadComment: (dom, callback) => {
77    if ("IntersectionObserver" in window) {
78      const observerItem = new IntersectionObserver(
79        entries => {
80          if (entries[0].isIntersecting) {
81            callback();
82            observerItem.disconnect();
83          }
84        },
85        { threshold: [0] }
86      );
87      observerItem.observe(dom);
88    } else {
89      callback();
90    }
91  },
92
93  scrollToDest: (pos, time = 500) => {
94    const currentPos = window.pageYOffset;
95    if ("scrollBehavior" in document.documentElement.style) {
96      window.scrollTo({
97        top: pos,
98        behavior: "smooth",
99      });
100      return;
101    }
102
103    let start = null;
104    pos = +pos;
105    window.requestAnimationFrame(function step(currentTime) {
106      start = !start ? currentTime : start;
107      const progress = currentTime - start;
108      if (currentPos < pos) {
109        window.scrollTo(0, ((pos - currentPos) * progress) / time + currentPos);
110      } else {
111        window.scrollTo(0, currentPos - ((currentPos - pos) * progress) / time);
112      }
113      if (progress < time) {
114        window.requestAnimationFrame(step);
115      } else {
116        window.scrollTo(0, pos);
117      }
118    });
119  },
120
121  initJustifiedGallery: function (selector) {
122    const runJustifiedGallery = i => {
123      if (!anzhiyu.isHidden(i)) {
124        fjGallery(i, {
125          itemSelector: ".fj-gallery-item",
126          rowHeight: i.getAttribute("data-rowHeight"),
127          gutter: 4,
128          onJustify: function () {
129            this.$container.style.opacity = "1";
130          },
131        });
132      }
133    };
134
135    if (Array.from(selector).length === 0) runJustifiedGallery(selector);
136    else
137      selector.forEach(i => {
138        runJustifiedGallery(i);
139      });
140  },
141
142  animateIn: (ele, text) => {
143    ele.style.display = "block";
144    ele.style.animation = text;
145  },
146
147  animateOut: (ele, text) => {
148    ele.addEventListener("animationend", function f() {
149      ele.style.display = "";
150      ele.style.animation = "";
151      ele.removeEventListener("animationend", f);
152    });
153    ele.style.animation = text;
154  },
155
156  /**
157   * @param {*} selector
158   * @param {*} eleType the type of create element
159   * @param {*} options object key: value
160   */
161  wrap: (selector, eleType, options) => {
162    const creatEle = document.createElement(eleType);
163    for (const [key, value] of Object.entries(options)) {
164      creatEle.setAttribute(key, value);
165    }
166    selector.parentNode.insertBefore(creatEle, selector);
167    creatEle.appendChild(selector);
168  },
169
170  isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
171
172  getEleTop: ele => {
173    let actualTop = ele.offsetTop;
174    let current = ele.offsetParent;
175
176    while (current !== null) {
177      actualTop += current.offsetTop;
178      current = current.offsetParent;
179    }
180
181    return actualTop;
182  },
183
184  loadLightbox: ele => {
185    const service = GLOBAL_CONFIG.lightbox;
186
187    if (service === "mediumZoom") {
188      const zoom = mediumZoom(ele);
189      zoom.on("open", e => {
190        const photoBg = document.documentElement.getAttribute("data-theme") === "dark" ? "#121212" : "#fff";
191        zoom.update({
192          background: photoBg,
193        });
194      });
195    }
196
197    if (service === "fancybox") {
198      Array.from(ele).forEach(i => {
199        if (i.parentNode.tagName !== "A") {
200          const dataSrc = i.dataset.lazySrc || i.src;
201          const dataCaption = i.title || i.alt || "";
202          anzhiyu.wrap(i, "a", {
203            href: dataSrc,
204            "data-fancybox": "gallery",
205            "data-caption": dataCaption,
206            "data-thumb": dataSrc,
207          });
208        }
209      });
210
211      if (!window.fancyboxRun) {
212        Fancybox.bind("[data-fancybox]", {
213          Hash: false,
214          Thumbs: {
215            autoStart: false,
216          },
217        });
218        window.fancyboxRun = true;
219      }
220    }
221  },
222
223  setLoading: {
224    add: ele => {
225      const html = `
226        <div class="loading-container">
227          <div class="loading-item">
228            <div></div><div></div><div></div><div></div><div></div>
229          </div>
230        </div>
231      `;
232      ele.insertAdjacentHTML("afterend", html);
233    },
234    remove: ele => {
235      ele.nextElementSibling.remove();
236    },
237  },
238
239  updateAnchor: anchor => {
240    if (anchor !== window.location.hash) {
241      if (!anchor) anchor = location.pathname;
242      const title = GLOBAL_CONFIG_SITE.title;
243      window.history.replaceState(
244        {
245          url: location.href,
246          title,
247        },
248        title,
249        anchor
250      );
251    }
252  },
253
254  getScrollPercent: (currentTop, ele) => {
255    const docHeight = ele.clientHeight;
256    const winHeight = document.documentElement.clientHeight;
257    const headerHeight = ele.offsetTop;
258    const contentMath =
259      docHeight > winHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight;
260    const scrollPercent = (currentTop - headerHeight) / contentMath;
261    const scrollPercentRounded = Math.round(scrollPercent * 100);
262    const percentage = scrollPercentRounded > 100 ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded;
263    return percentage;
264  },
265
266  addGlobalFn: (key, fn, name = false, parent = window) => {
267    const globalFn = parent.globalFn || {};
268    const keyObj = globalFn[key] || {};
269
270    if (name && keyObj[name]) return;
271
272    name = name || Object.keys(keyObj).length;
273    keyObj[name] = fn;
274    globalFn[key] = keyObj;
275    parent.globalFn = globalFn;
276  },
277
278  addEventListenerPjax: (ele, event, fn, option = false) => {
279    ele.addEventListener(event, fn, option);
280    anzhiyu.addGlobalFn("pjax", () => {
281      ele.removeEventListener(event, fn, option);
282    });
283  },
284
285  removeGlobalFnEvent: (key, parent = window) => {
286    const { globalFn = {} } = parent;
287    const keyObj = globalFn[key] || {};
288    const keyArr = Object.keys(keyObj);
289    if (!keyArr.length) return;
290    keyArr.forEach(i => {
291      keyObj[i]();
292    });
293    delete parent.globalFn[key];
294  },
295
296  //更改主题色
297  changeThemeMetaColor: function (color) {
298    // console.info(`%c ${color}`, `font-size:36px;color:${color};`);
299    if (themeColorMeta !== null) {
300      themeColorMeta.setAttribute("content", color);
301    }
302  },
303
304  //顶栏自适应主题色
305  initThemeColor: function () {
306    let themeColor = getComputedStyle(document.documentElement)
307      .getPropertyValue("--anzhiyu-bar-background")
308      .trim()
309      .replace('"', "")
310      .replace('"', "");
311    const currentTop = window.scrollY || document.documentElement.scrollTop;
312    if (currentTop > 26) {
313      if (anzhiyu.is_Post()) {
314        themeColor = getComputedStyle(document.documentElement)
315          .getPropertyValue("--anzhiyu-meta-theme-post-color")
316          .trim()
317          .replace('"', "")
318          .replace('"', "");
319      }
320      if (themeColorMeta.getAttribute("content") === themeColor) return;
321      this.changeThemeMetaColor(themeColor);
322    } else {
323      if (themeColorMeta.getAttribute("content") === themeColor) return;
324      this.changeThemeMetaColor(themeColor);
325    }
326  },
327  //是否是文章页
328  is_Post: function () {
329    var url = window.location.href; //获取url
330    if (url.indexOf("/posts/") >= 0) {
331      //判断url地址中是否包含code字符串
332      return true;
333    } else {
334      return false;
335    }
336  },
337  //监测是否在页面开头
338  addNavBackgroundInit: function () {
339    var scrollTop = 0,
340      bodyScrollTop = 0,
341      documentScrollTop = 0;
342    if ($bodyWrap) {
343      bodyScrollTop = $bodyWrap.scrollTop;
344    }
345    if (document.documentElement) {
346      documentScrollTop = document.documentElement.scrollTop;
347    }
348    scrollTop = bodyScrollTop - documentScrollTop > 0 ? bodyScrollTop : documentScrollTop;
349
350    if (scrollTop != 0) {
351      pageHeaderEl.classList.add("nav-fixed");
352      pageHeaderEl.classList.add("nav-visible");
353    }
354  },
355  // 下载图片
356  downloadImage: function (imgsrc, name) {
357    //下载图片地址和图片名
358    rm.hideRightMenu();
359    if (rm.downloadimging == false) {
360      rm.downloadimging = true;
361      anzhiyu.snackbarShow("Downloading, please wait..", false, 10000);
362      setTimeout(function () {
363        let image = new Image();
364        // 解决跨域 Canvas 污染问题
365        image.setAttribute("crossOrigin", "anonymous");
366        image.onload = function () {
367          let canvas = document.createElement("canvas");
368          canvas.width = image.width;
369          canvas.height = image.height;
370          let context = canvas.getContext("2d");
371          context.drawImage(image, 0, 0, image.width, image.height);
372          let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
373          let a = document.createElement("a"); // 生成一个a元素
374          let event = new MouseEvent("click"); // 创建一个单击事件
375          a.download = name || "photo"; // 设置图片名称
376          a.href = url; // 将生成的URL设置为a.href属性
377          a.dispatchEvent(event); // 触发a的单击事件
378        };
379        image.src = imgsrc;
380        anzhiyu.snackbarShow("The image has been embedded with a blind watermark. Please comply with the copyright agreement");
381        rm.downloadimging = false;
382      }, "10000");
383    } else {
384      anzhiyu.snackbarShow("There is a download in progress, please try again later");
385    }
386  },
387  //禁止图片右键单击
388  stopImgRightDrag: function () {
389    var img = document.getElementsByTagName("img");
390    for (var i = 0; i < img.length; i++) {
391      img[i].addEventListener("dragstart", function () {
392        return false;
393      });
394    }
395  },
396  //滚动到指定id
397  scrollTo: function (id) {
398    var domTop = document.querySelector(id).offsetTop;
399    window.scrollTo(0, domTop - 80);
400  },
401  //隐藏侧边栏
402  hideAsideBtn: () => {
403    // Hide aside
404    const $htmlDom = document.documentElement.classList;
405    $htmlDom.contains("hide-aside")
406      ? saveToLocal.set("aside-status", "show", 2)
407      : saveToLocal.set("aside-status", "hide", 2);
408    $htmlDom.toggle("hide-aside");
409    $htmlDom.contains("hide-aside")
410      ? document.querySelector("#consoleHideAside").classList.add("on")
411      : document.querySelector("#consoleHideAside").classList.remove("on");
412  },
413  // 热评切换
414  switchCommentBarrage: function () {
415    let commentBarrage = document.querySelector(".comment-barrage");
416    if (commentBarrage) {
417      if (window.getComputedStyle(commentBarrage).display === "flex") {
418        commentBarrage.style.display = "none";
419        anzhiyu.snackbarShow("✨ 已关闭评论弹幕");
420        document.querySelector(".menu-commentBarrage-text").textContent = "显示热评";
421        document.querySelector("#consoleCommentBarrage").classList.remove("on");
422        localStorage.setItem("commentBarrageSwitch", "false");
423      } else {
424        commentBarrage.style.display = "flex";
425        document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评";
426        document.querySelector("#consoleCommentBarrage").classList.add("on");
427        anzhiyu.snackbarShow("✨ 已开启评论弹幕");
428        localStorage.removeItem("commentBarrageSwitch");
429      }
430    }
431    rm && rm.hideRightMenu();
432  },
433  initPaginationObserver: () => {
434    const commentElement = document.getElementById("post-comment");
435    const paginationElement = document.getElementById("pagination");
436
437    if (commentElement && paginationElement) {
438      new IntersectionObserver(entries => {
439        const commentBarrage = document.querySelector(".comment-barrage");
440
441        entries.forEach(entry => {
442          if (entry.isIntersecting) {
443            paginationElement.classList.add("show-window");
444            if (commentBarrage) {
445              commentBarrage.style.bottom = "-200px";
446            }
447          } else {
448            paginationElement.classList.remove("show-window");
449            if (commentBarrage) {
450              commentBarrage.style.bottom = "0px";
451            }
452          }
453        });
454      }).observe(commentElement);
455    }
456  },
457  // 初始化即刻
458  initIndexEssay: function () {
459    if (!document.getElementById("bbTimeList")) return;
460    setTimeout(() => {
461      let essay_bar_swiper = new Swiper(".essay_bar_swiper_container", {
462        passiveListeners: true,
463        direction: "vertical",
464        loop: true,
465        autoplay: {
466          disableOnInteraction: true,
467          delay: 3000,
468        },
469        mousewheel: true,
470      });
471
472      let essay_bar_comtainer = document.getElementById("bbtalk");
473      if (essay_bar_comtainer !== null) {
474        essay_bar_comtainer.onmouseenter = function () {
475          essay_bar_swiper.autoplay.stop();
476        };
477        essay_bar_comtainer.onmouseleave = function () {
478          essay_bar_swiper.autoplay.start();
479        };
480      }
481    }, 100);
482  },
483  scrollByMouseWheel: function ($list, $target) {
484    const scrollHandler = function (e) {
485      $list.scrollLeft -= e.wheelDelta / 2;
486      e.preventDefault();
487    };
488    $list.addEventListener("mousewheel", scrollHandler, { passive: false });
489    if ($target) {
490      $target.classList.add("selected");
491      $list.scrollLeft = $target.offsetLeft - $list.offsetLeft - ($list.offsetWidth - $target.offsetWidth) / 2;
492    }
493  },
494  // catalog激活
495  catalogActive: function () {
496    const $list = document.getElementById("catalog-list");
497    if ($list) {
498      const pathname = decodeURIComponent(window.location.pathname);
499      const catalogListItems = $list.querySelectorAll(".catalog-list-item");
500
501      let $catalog = null;
502      catalogListItems.forEach(item => {
503        if (pathname.startsWith(item.id)) {
504          $catalog = item;
505          return;
506        }
507      });
508
509      anzhiyu.scrollByMouseWheel($list, $catalog);
510    }
511  },
512  // Page Tag 激活
513  tagsPageActive: function () {
514    const $list = document.getElementById("tag-page-tags");
515    if ($list) {
516      const $tagPageTags = document.getElementById(decodeURIComponent(window.location.pathname));
517      anzhiyu.scrollByMouseWheel($list, $tagPageTags);
518    }
519  },
520  // 修改时间显示"最近"
521  diffDate: function (d, more = false, simple = false) {
522    const dateNow = new Date();
523    const datePost = new Date(d);
524    const dateDiff = dateNow.getTime() - datePost.getTime();
525    const minute = 1000 * 60;
526    const hour = minute * 60;
527    const day = hour * 24;
528    const month = day * 30;
529
530    let result;
531    if (more) {
532      const monthCount = dateDiff / month;
533      const dayCount = dateDiff / day;
534      const hourCount = dateDiff / hour;
535      const minuteCount = dateDiff / minute;
536
537      if (monthCount >= 1) {
538        result = datePost.toLocaleDateString().replace(/\//g, "-");
539      } else if (dayCount >= 1) {
540        result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day;
541      } else if (hourCount >= 1) {
542        result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour;
543      } else if (minuteCount >= 1) {
544        result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min;
545      } else {
546        result = GLOBAL_CONFIG.date_suffix.just;
547      }
548    } else if (simple) {
549      const monthCount = dateDiff / month;
550      const dayCount = dateDiff / day;
551      const hourCount = dateDiff / hour;
552      const minuteCount = dateDiff / minute;
553      if (monthCount >= 1) {
554        result = datePost.toLocaleDateString().replace(/\//g, "-");
555      } else if (dayCount >= 1 && dayCount <= 3) {
556        result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day;
557      } else if (dayCount > 3) {
558        result = datePost.getMonth() + 1 + "/" + datePost.getDate();
559      } else if (hourCount >= 1) {
560        result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour;
561      } else if (minuteCount >= 1) {
562        result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min;
563      } else {
564        result = GLOBAL_CONFIG.date_suffix.just;
565      }
566    } else {
567      result = parseInt(dateDiff / day);
568    }
569    return result;
570  },
571
572  // 修改即刻中的时间显示
573  changeTimeInEssay: function () {
574    document.querySelector("#bber") &&
575      document.querySelectorAll("#bber time").forEach(function (e) {
576        var t = e,
577          datetime = t.getAttribute("datetime");
578        (t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline");
579      });
580  },
581  // 修改相册集中的时间
582  changeTimeInAlbumDetail: function () {
583    document.querySelector("#album_detail") &&
584      document.querySelectorAll("#album_detail time").forEach(function (e) {
585        var t = e,
586          datetime = t.getAttribute("datetime");
587        (t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline");
588      });
589  },
590  // 刷新瀑布流
591  reflashEssayWaterFall: function () {
592    const waterfallEl = document.getElementById("waterfall");
593    if (waterfallEl) {
594      setTimeout(function () {
595        waterfall(waterfallEl);
596        waterfallEl.classList.add("show");
597      }, 800);
598    }
599  },
600  sayhi: function () {
601    const $sayhiEl = document.getElementById("author-info__sayhi");
602
603    const getTimeState = () => {
604      const hour = new Date().getHours();
605      let message = "";
606
607      if (hour >= 0 && hour <= 5) {
608        message = "pwn2life";
609      } else if (hour > 5 && hour <= 10) {
610        message = "pwn2life";
611      } else if (hour > 10 && hour <= 14) {
612        message = "ret2self";
613      } else if (hour > 14 && hour <= 18) {
614        message = "ret2self";
615      } else if (hour > 18 && hour <= 24) {
616        message = "pwn2life";
617      }
618
619      return message;
620    };
621
622    if ($sayhiEl) {
623      $sayhiEl.innerHTML = getTimeState();
624    }
625  },
626
627  // 友链注入预设评论
628  addFriendLink() {
629    var input = document.getElementsByClassName("el-textarea__inner")[0];
630    if (!input) return;
631    const evt = new Event("input", { cancelable: true, bubbles: true });
632    const defaultPlaceholder =
633      "昵称(请勿包含博客等字样):\n网站地址(要求博客地址,请勿提交个人主页):\n头像图片url(请提供尽可能清晰的图片,我会上传到我自己的图床):\n描述:\n站点截图(可选):\n";
634    input.value = this.getConfigIfPresent(GLOBAL_CONFIG.linkPageTop, "addFriendPlaceholder", defaultPlaceholder);
635    input.dispatchEvent(evt);
636    input.focus();
637    input.setSelectionRange(-1, -1);
638  },
639  // 获取配置,如果为空则返回默认值
640  getConfigIfPresent: function (config, configKey, defaultValue) {
641    if (!config) return defaultValue;
642    if (!config.hasOwnProperty(configKey)) return defaultValue;
643    if (!config[configKey]) return defaultValue;
644    return config[configKey];
645  },
646  //切换音乐播放状态
647  musicToggle: function (changePaly = true) {
648    if (!anzhiyu_musicFirst) {
649      anzhiyu.musicBindEvent();
650      anzhiyu_musicFirst = true;
651    }
652    let msgPlay = '<i class="anzhiyufont anzhiyu-icon-play"></i><span>播放音乐</span>';
653    let msgPause = '<i class="anzhiyufont anzhiyu-icon-pause"></i><span>暂停音乐</span>';
654    if (anzhiyu_musicPlaying) {
655      navMusicEl.classList.remove("playing");
656      document.getElementById("menu-music-toggle").innerHTML = msgPlay;
657      document.getElementById("nav-music-hoverTips").innerHTML = "音乐已暂停";
658      document.querySelector("#consoleMusic").classList.remove("on");
659      anzhiyu_musicPlaying = false;
660      navMusicEl.classList.remove("stretch");
661    } else {
662      navMusicEl.classList.add("playing");
663      document.getElementById("menu-music-toggle").innerHTML = msgPause;
664      document.querySelector("#consoleMusic").classList.add("on");
665      anzhiyu_musicPlaying = true;
666      navMusicEl.classList.add("stretch");
667    }
668    if (changePaly) document.querySelector("#nav-music meting-js").aplayer.toggle();
669    rm && rm.hideRightMenu();
670  },
671  // 音乐伸缩
672  musicTelescopic: function () {
673    if (navMusicEl.classList.contains("stretch")) {
674      navMusicEl.classList.remove("stretch");
675    } else {
676      navMusicEl.classList.add("stretch");
677    }
678  },
679
680  //音乐上一曲
681  musicSkipBack: function () {
682    navMusicEl.querySelector("meting-js").aplayer.skipBack();
683    rm && rm.hideRightMenu();
684  },
685
686  //音乐下一曲
687  musicSkipForward: function () {
688    navMusicEl.querySelector("meting-js").aplayer.skipForward();
689    rm && rm.hideRightMenu();
690  },
691
692  //获取音乐中的名称
693  musicGetName: function () {
694    var x = document.querySelectorAll(".aplayer-title");
695    var arr = [];
696    for (var i = x.length - 1; i >= 0; i--) {
697      arr[i] = x[i].innerText;
698    }
699    return arr[0];
700  },
701
702  //初始化console图标
703  initConsoleState: function () {
704    //初始化隐藏边栏
705    const $htmlDomClassList = document.documentElement.classList;
706    $htmlDomClassList.contains("hide-aside")
707      ? document.querySelector("#consoleHideAside").classList.add("on")
708      : document.querySelector("#consoleHideAside").classList.remove("on");
709  },
710
711  // 显示打赏中控台
712  rewardShowConsole: function () {
713    // 判断是否为赞赏打开控制台
714    consoleEl.classList.add("reward-show");
715    anzhiyu.initConsoleState();
716  },
717  // 显示中控台
718  showConsole: function () {
719    consoleEl.classList.add("show");
720    anzhiyu.initConsoleState();
721  },
722
723  //隐藏中控台
724  hideConsole: function () {
725    if (consoleEl.classList.contains("show")) {
726      // 如果是一般控制台,就关闭一般控制台
727      consoleEl.classList.remove("show");
728    } else if (consoleEl.classList.contains("reward-show")) {
729      // 如果是打赏控制台,就关闭打赏控制台
730      consoleEl.classList.remove("reward-show");
731    }
732    // 获取center-console元素
733    const centerConsole = document.getElementById("center-console");
734
735    // 检查center-console是否被选中
736    if (centerConsole.checked) {
737      // 取消选中状态
738      centerConsole.checked = false;
739    }
740  },
741  // 取消加载动画
742  hideLoading: function () {
743    document.getElementById("loading-box").classList.add("loaded");
744  },
745  // 将音乐缓存播放
746  cacheAndPlayMusic() {
747    let data = localStorage.getItem("musicData");
748    if (data) {
749      data = JSON.parse(data);
750      const currentTime = new Date().getTime();
751      if (currentTime - data.timestamp < 24 * 60 * 60 * 1000) {
752        // 如果缓存的数据没有过期,直接使用
753        anzhiyu.playMusic(data.songs);
754        return;
755      }
756    }
757
758    // 否则重新从服务器获取数据
759    fetch("/json/music.json")
760      .then(response => response.json())
761      .then(songs => {
762        const cacheData = {
763          timestamp: new Date().getTime(),
764          songs: songs,
765        };
766        localStorage.setItem("musicData", JSON.stringify(cacheData));
767        anzhiyu.playMusic(songs);
768      });
769  },
770  // 播放音乐
771  playMusic(songs) {
772    const anMusicPage = document.getElementById("anMusic-page");
773    const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
774    const randomIndex = Math.floor(Math.random() * songs.length);
775    const randomSong = songs[randomIndex];
776    const allAudios = metingAplayer.list.audios;
777    if (!selectRandomSong.includes(randomSong.name)) {
778      // 如果随机到的歌曲已经未被随机到过,就添加进metingAplayer.list
779      metingAplayer.list.add([randomSong]);
780      // 播放最后一首(因为是添加到了最后)
781      metingAplayer.list.switch(allAudios.length);
782      // 添加到已被随机的歌曲列表
783      selectRandomSong.push(randomSong.name);
784    } else {
785      // 随机到的歌曲已经在播放列表中了
786      // 直接继续随机直到随机到没有随机过的歌曲,如果全部随机过了就切换到对应的歌曲播放即可
787      let songFound = false;
788      while (!songFound) {
789        const newRandomIndex = Math.floor(Math.random() * songs.length);
790        const newRandomSong = songs[newRandomIndex];
791        if (!selectRandomSong.includes(newRandomSong.name)) {
792          metingAplayer.list.add([newRandomSong]);
793          metingAplayer.list.switch(allAudios.length);
794          selectRandomSong.push(newRandomSong.name);
795          songFound = true;
796        }
797        // 如果全部歌曲都已被随机过,跳出循环
798        if (selectRandomSong.length === songs.length) {
799          break;
800        }
801      }
802      if (!songFound) {
803        // 如果全部歌曲都已被随机过,切换到对应的歌曲播放
804        const palyMusicIndex = allAudios.findIndex(song => song.name === randomSong.name);
805        if (palyMusicIndex != -1) metingAplayer.list.switch(palyMusicIndex);
806      }
807    }
808
809    console.info("已随机歌曲:", selectRandomSong, "本次随机歌曲:", randomSong.name);
810  },
811  // 音乐节目切换背景
812  changeMusicBg: function (isChangeBg = true) {
813    const anMusicBg = document.getElementById("an_music_bg");
814
815    if (isChangeBg) {
816      // player listswitch 会进入此处
817      const musiccover = document.querySelector("#anMusic-page .aplayer-pic");
818      anMusicBg.style.backgroundImage = musiccover.style.backgroundImage;
819    } else {
820      // 第一次进入,绑定事件,改背景
821      let timer = setInterval(() => {
822        const musiccover = document.querySelector("#anMusic-page .aplayer-pic");
823        // 确保player加载完成
824        if (musiccover) {
825          clearInterval(timer);
826          // 绑定事件
827          anzhiyu.addEventListenerMusic();
828          // 确保第一次能够正确替换背景
829          anzhiyu.changeMusicBg();
830
831          // 暂停nav的音乐
832          if (
833            document.querySelector("#nav-music meting-js").aplayer &&
834            !document.querySelector("#nav-music meting-js").aplayer.audio.paused
835          ) {
836            anzhiyu.musicToggle();
837          }
838        }
839      }, 100);
840    }
841  },
842  // 获取自定义播放列表
843  getCustomPlayList: function () {
844    if (!window.location.pathname.startsWith("/music/")) {
845      return;
846    }
847    const urlParams = new URLSearchParams(window.location.search);
848    const userId = "8152976493";
849    const userServer = "netease";
850    const anMusicPageMeting = document.getElementById("anMusic-page-meting");
851    if (urlParams.get("id") && urlParams.get("server")) {
852      const id = urlParams.get("id");
853      const server = urlParams.get("server");
854      anMusicPageMeting.innerHTML = `<meting-js id="${id}" server=${server} type="playlist" type="playlist" mutex="true" preload="auto" theme="var(--anzhiyu-main)" order="list" list-max-height="calc(100vh - 169px)!important"></meting-js>`;
855    } else {
856      anMusicPageMeting.innerHTML = `<meting-js id="${userId}" server="${userServer}" type="playlist" mutex="true" preload="auto" theme="var(--anzhiyu-main)" order="list" list-max-height="calc(100vh - 169px)!important"></meting-js>`;
857    }
858    anzhiyu.changeMusicBg(false);
859  },
860  //隐藏今日推荐
861  hideTodayCard: function () {
862    if (document.getElementById("todayCard")) {
863      document.getElementById("todayCard").classList.add("hide");
864      const topGroup = document.querySelector(".topGroup");
865      const recentPostItems = topGroup.querySelectorAll(".recent-post-item");
866      recentPostItems.forEach(item => {
867        item.style.display = "flex";
868      });
869    }
870  },
871
872  // 监听音乐背景改变
873  addEventListenerMusic: function () {
874    const anMusicPage = document.getElementById("anMusic-page");
875    const aplayerIconMenu = anMusicPage.querySelector(".aplayer-info .aplayer-time .aplayer-icon-menu");
876    const anMusicBtnGetSong = anMusicPage.querySelector("#anMusicBtnGetSong");
877    const anMusicRefreshBtn = anMusicPage.querySelector("#anMusicRefreshBtn");
878    const anMusicSwitchingBtn = anMusicPage.querySelector("#anMusicSwitching");
879    const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
880    //初始化音量
881    metingAplayer.volume(0.8, true);
882    metingAplayer.on("loadeddata", function () {
883      anzhiyu.changeMusicBg();
884    });
885
886    aplayerIconMenu.addEventListener("click", function () {
887      document.getElementById("menu-mask").style.display = "block";
888      document.getElementById("menu-mask").style.animation = "0.5s ease 0s 1 normal none running to_show";
889      anMusicPage.querySelector(".aplayer.aplayer-withlist .aplayer-list").style.opacity = "1";
890    });
891
892    function anMusicPageMenuAask() {
893      if (window.location.pathname != "/music/") {
894        document.getElementById("menu-mask").removeEventListener("click", anMusicPageMenuAask);
895        return;
896      }
897
898      anMusicPage.querySelector(".aplayer-list").classList.remove("aplayer-list-hide");
899    }
900
901    document.getElementById("menu-mask").addEventListener("click", anMusicPageMenuAask);
902
903    // 监听增加单曲按钮
904    anMusicBtnGetSong.addEventListener("click", () => {
905      if (changeMusicListFlag) {
906        const anMusicPage = document.getElementById("anMusic-page");
907        const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
908        const allAudios = metingAplayer.list.audios;
909        const randomIndex = Math.floor(Math.random() * allAudios.length);
910        // 随机播放一首
911        metingAplayer.list.switch(randomIndex);
912      } else {
913        anzhiyu.cacheAndPlayMusic();
914      }
915    });
916    anMusicRefreshBtn.addEventListener("click", () => {
917      localStorage.removeItem("musicData");
918      anzhiyu.snackbarShow("已移除相关缓存歌曲");
919    });
920    anMusicSwitchingBtn.addEventListener("click", () => {
921      anzhiyu.changeMusicList();
922    });
923
924    // 默认加载的歌单
925    if (GLOBAL_CONFIG.music_page_default === "custom") {
926      anzhiyu.changeMusicList();
927    }
928
929    // 监听键盘事件
930    //空格控制音乐
931    document.addEventListener("keydown", function (event) {
932      //暂停开启音乐
933      if (event.code === "Space") {
934        event.preventDefault();
935        metingAplayer.toggle();
936      }
937      //切换下一曲
938      if (event.keyCode === 39) {
939        event.preventDefault();
940        metingAplayer.skipForward();
941      }
942      //切换上一曲
943      if (event.keyCode === 37) {
944        event.preventDefault();
945        metingAplayer.skipBack();
946      }
947      //增加音量
948      if (event.keyCode === 38) {
949        if (musicVolume <= 1) {
950          musicVolume += 0.1;
951          metingAplayer.volume(musicVolume, true);
952        }
953      }
954      //减小音量
955      if (event.keyCode === 40) {
956        if (musicVolume >= 0) {
957          musicVolume += -0.1;
958          metingAplayer.volume(musicVolume, true);
959        }
960      }
961    });
962  },
963  // 切换歌单
964  changeMusicList: async function () {
965    const anMusicPage = document.getElementById("anMusic-page");
966    const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
967    const currentTime = new Date().getTime();
968    const cacheData = JSON.parse(localStorage.getItem("musicData")) || { timestamp: 0 };
969    let songs = [];
970
971    if (changeMusicListFlag) {
972      songs = defaultPlayMusicList;
973    } else {
974      // 保存当前默认播放列表,以使下次可以切换回来
975      defaultPlayMusicList = metingAplayer.list.audios;
976      // 如果缓存的数据没有过期,直接使用
977      if (currentTime - cacheData.timestamp < 24 * 60 * 60 * 1000) {
978        songs = cacheData.songs;
979      } else {
980        // 否则重新从服务器获取数据
981        const response = await fetch("/json/music.json");
982        songs = await response.json();
983        cacheData.timestamp = currentTime;
984        cacheData.songs = songs;
985        localStorage.setItem("musicData", JSON.stringify(cacheData));
986      }
987    }
988
989    // 清除当前播放列表并添加新的歌曲
990    metingAplayer.list.clear();
991    metingAplayer.list.add(songs);
992
993    // 切换标志位
994    changeMusicListFlag = !changeMusicListFlag;
995  },
996  // 控制台音乐列表监听
997  addEventListenerConsoleMusicList: function () {
998    const navMusic = document.getElementById("nav-music");
999    if (!navMusic) return;
1000    navMusic.addEventListener("click", e => {
1001      const aplayerList = navMusic.querySelector(".aplayer-list");
1002      const listBtn = navMusic.querySelector(
1003        "div.aplayer-info > div.aplayer-controller > div.aplayer-time.aplayer-time-narrow > button.aplayer-icon.aplayer-icon-menu svg"
1004      );
1005      if (e.target != listBtn && aplayerList.classList.contains("aplayer-list-hide")) {
1006        aplayerList.classList.remove("aplayer-list-hide");
1007      }
1008    });
1009  },
1010  // 监听按键
1011  toPage: function () {
1012    var toPageText = document.getElementById("toPageText"),
1013      toPageButton = document.getElementById("toPageButton"),
1014      pageNumbers = document.querySelectorAll(".page-number"),
1015      lastPageNumber = Number(pageNumbers[pageNumbers.length - 1].innerHTML),
1016      pageNumber = Number(toPageText.value);
1017
1018    if (!isNaN(pageNumber) && pageNumber >= 1 && Number.isInteger(pageNumber)) {
1019      var url = "/page/" + (pageNumber > lastPageNumber ? lastPageNumber : pageNumber) + "/";
1020      toPageButton.href = pageNumber === 1 ? "/" : url;
1021    } else {
1022      toPageButton.href = "javascript:void(0);";
1023    }
1024  },
1025
1026  //删除多余的class
1027  removeBodyPaceClass: function () {
1028    document.body.className = "pace-done";
1029  },
1030  // 修改body的type类型以适配css
1031  setValueToBodyType: function () {
1032    const input = document.getElementById("page-type"); // 获取input元素
1033    const value = input.value; // 获取input的value值
1034    document.body.dataset.type = value; // 将value值赋值到body的type属性上
1035  },
1036  //匿名评论
1037  addRandomCommentInfo: function () {
1038    // 从形容词数组中随机取一个值
1039    const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
1040
1041    // 从蔬菜水果动物名字数组中随机取一个值
1042    const randomName = vegetablesAndFruits[Math.floor(Math.random() * vegetablesAndFruits.length)];
1043
1044    // 将两个值组合成一个字符串
1045    const name = `${randomAdjective}${randomName}`;
1046
1047    function dr_js_autofill_commentinfos() {
1048      var lauthor = [
1049          "#author",
1050          "input[name='comname']",
1051          "#inpName",
1052          "input[name='author']",
1053          "#ds-dialog-name",
1054          "#name",
1055          "input[name='nick']",
1056          "#comment_author",
1057        ],
1058        lmail = [
1059          "#mail",
1060          "#email",
1061          "input[name='commail']",
1062          "#inpEmail",
1063          "input[name='email']",
1064          "#ds-dialog-email",
1065          "input[name='mail']",
1066          "#comment_email",
1067        ],
1068        lurl = [
1069          "#url",
1070          "input[name='comurl']",
1071          "#inpHomePage",
1072          "#ds-dialog-url",
1073          "input[name='url']",
1074          "input[name='website']",
1075          "#website",
1076          "input[name='link']",
1077          "#comment_url",
1078        ];
1079      for (var i = 0; i < lauthor.length; i++) {
1080        var author = document.querySelector(lauthor[i]);
1081        if (author != null) {
1082          author.value = name;
1083          author.dispatchEvent(new Event("input"));
1084          author.dispatchEvent(new Event("change"));
1085          break;
1086        }
1087      }
1088      for (var j = 0; j < lmail.length; j++) {
1089        var mail = document.querySelector(lmail[j]);
1090        if (mail != null) {
1091          mail.value = visitorMail;
1092          mail.dispatchEvent(new Event("input"));
1093          mail.dispatchEvent(new Event("change"));
1094          break;
1095        }
1096      }
1097      return !1;
1098    }
1099
1100    dr_js_autofill_commentinfos();
1101    var input = document.getElementsByClassName("el-textarea__inner")[0];
1102    input.focus();
1103    input.setSelectionRange(-1, -1);
1104  },
1105
1106  // 跳转开往
1107  totraveling: function () {
1108    anzhiyu.snackbarShow(
1109      "即将跳转到「开往」项目的成员博客,不保证跳转网站的安全性和可用性",
1110      element => {
1111        element.style.opacity = 0;
1112        travellingsTimer && clearTimeout(travellingsTimer);
1113      },
1114      5000,
1115      "取消"
1116    );
1117    travellingsTimer = setTimeout(function () {
1118      window.open("https://www.travellings.cn/go.html", "_blank");
1119    }, "5000");
1120  },
1121
1122  // 工具函数替换字符串
1123  replaceAll: function (e, n, t) {
1124    return e.split(n).join(t);
1125  },
1126
1127  // 音乐绑定事件
1128  musicBindEvent: function () {
1129    document.querySelector("#nav-music .aplayer-music").addEventListener("click", function () {
1130      anzhiyu.musicTelescopic();
1131    });
1132    document.querySelector("#nav-music .aplayer-button").addEventListener("click", function () {
1133      anzhiyu.musicToggle(false);
1134    });
1135  },
1136
1137  // 判断是否是移动端
1138  hasMobile: function () {
1139    let isMobile = false;
1140    if (
1141      navigator.userAgent.match(
1142        /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
1143      ) ||
1144      document.body.clientWidth < 800
1145    ) {
1146      // 移动端
1147      isMobile = true;
1148    }
1149    return isMobile;
1150  },
1151
1152  // 创建二维码
1153  qrcodeCreate: function () {
1154    if (document.getElementById("qrcode")) {
1155      document.getElementById("qrcode").innerHTML = "";
1156      var qrcode = new QRCode(document.getElementById("qrcode"), {
1157        text: window.location.href,
1158        width: 250,
1159        height: 250,
1160        colorDark: "#000",
1161        colorLight: "#ffffff",
1162        correctLevel: QRCode.CorrectLevel.H,
1163      });
1164    }
1165  },
1166
1167  // 判断是否在el内
1168  isInViewPortOfOne: function (el) {
1169    if (!el) return;
1170    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
1171    const offsetTop = el.offsetTop;
1172    const scrollTop = document.documentElement.scrollTop;
1173    const top = offsetTop - scrollTop;
1174    return top <= viewPortHeight;
1175  },
1176  //添加赞赏蒙版
1177  addRewardMask: function () {
1178    if (!document.querySelector(".reward-main")) return;
1179    document.querySelector(".reward-main").style.display = "flex";
1180    document.querySelector(".reward-main").style.zIndex = "102";
1181    document.getElementById("quit-box").style.display = "flex";
1182  },
1183  // 移除赞赏蒙版
1184  removeRewardMask: function () {
1185    if (!document.querySelector(".reward-main")) return;
1186    document.querySelector(".reward-main").style.display = "none";
1187    document.getElementById("quit-box").style.display = "none";
1188  },
1189
1190  keyboardToggle: function () {
1191    const isKeyboardOn = anzhiyu_keyboard;
1192
1193    if (isKeyboardOn) {
1194      const consoleKeyboard = document.querySelector("#consoleKeyboard");
1195      consoleKeyboard.classList.remove("on");
1196      anzhiyu_keyboard = false;
1197    } else {
1198      const consoleKeyboard = document.querySelector("#consoleKeyboard");
1199      consoleKeyboard.classList.add("on");
1200      anzhiyu_keyboard = true;
1201    }
1202
1203    localStorage.setItem("keyboardToggle", isKeyboardOn ? "false" : "true");
1204  },
1205  rightMenuToggle: function () {
1206    if (window.oncontextmenu) {
1207      window.oncontextmenu = null;
1208    } else if (!window.oncontextmenu && oncontextmenuFunction) {
1209      window.oncontextmenu = oncontextmenuFunction;
1210    }
1211  },
1212  switchConsole: () => {
1213    // switch console
1214    const consoleEl = document.getElementById("console");
1215    //初始化隐藏边栏
1216    const $htmlDom = document.documentElement.classList;
1217    $htmlDom.contains("hide-aside")
1218      ? document.querySelector("#consoleHideAside").classList.add("on")
1219      : document.querySelector("#consoleHideAside").classList.remove("on");
1220    if (consoleEl.classList.contains("show")) {
1221      consoleEl.classList.remove("show");
1222    } else {
1223      consoleEl.classList.add("show");
1224    }
1225    const consoleKeyboard = document.querySelector("#consoleKeyboard");
1226
1227    if (consoleKeyboard) {
1228      if (localStorage.getItem("keyboardToggle") === "true") {
1229        consoleKeyboard.classList.add("on");
1230        anzhiyu_keyboard = true;
1231      } else {
1232        consoleKeyboard.classList.remove("on");
1233        anzhiyu_keyboard = false;
1234      }
1235    }
1236  },
1237  // 定义 intersectionObserver 函数,并接收两个可选参数
1238  intersectionObserver: function (enterCallback, leaveCallback) {
1239    let observer;
1240    return () => {
1241      if (!observer) {
1242        observer = new IntersectionObserver(entries => {
1243          entries.forEach(entry => {
1244            if (entry.intersectionRatio > 0) {
1245              enterCallback?.();
1246            } else {
1247              leaveCallback?.();
1248            }
1249          });
1250        });
1251      } else {
1252        // 如果 observer 对象已经存在,则先取消对之前元素的观察
1253        observer.disconnect();
1254      }
1255      return observer;
1256    };
1257  },
1258  // CategoryBar滚动
1259  scrollCategoryBarToRight: function () {
1260    // 获取需要操作的元素
1261    const items = document.getElementById("catalog-list");
1262    const nextButton = document.getElementById("category-bar-next");
1263
1264    // 检查元素是否存在
1265    if (items && nextButton) {
1266      const itemsWidth = items.clientWidth;
1267
1268      // 判断是否已经滚动到最右侧
1269      if (items.scrollLeft + items.clientWidth + 1 >= items.scrollWidth) {
1270        // 滚动到初始位置并更新按钮内容
1271        items.scroll({
1272          left: 0,
1273          behavior: "smooth",
1274        });
1275        nextButton.innerHTML = '<i class="anzhiyufont anzhiyu-icon-angle-double-right"></i>';
1276      } else {
1277        // 滚动到下一个视图
1278        items.scrollBy({
1279          left: itemsWidth,
1280          behavior: "smooth",
1281        });
1282      }
1283    } else {
1284      console.error("Element(s) not found: 'catalog-list' and/or 'category-bar-next'.");
1285    }
1286  },
1287  // 分类条
1288  categoriesBarActive: function () {
1289    const urlinfo = decodeURIComponent(window.location.pathname);
1290    const $categoryBar = document.getElementById("category-bar");
1291    if (!$categoryBar) return;
1292
1293    if (urlinfo === "/") {
1294      $categoryBar.querySelector("#首页").classList.add("select");
1295    } else {
1296      const pattern = /\/categories\/.*?\//;
1297      const patbool = pattern.test(urlinfo);
1298      if (!patbool) return;
1299
1300      const nowCategorie = urlinfo.split("/")[2];
1301      $categoryBar.querySelector(`#${nowCategorie}`).classList.add("select");
1302    }
1303  },
1304  topCategoriesBarScroll: function () {
1305    const $categoryBarItems = document.getElementById("category-bar-items");
1306    if (!$categoryBarItems) return;
1307
1308    $categoryBarItems.addEventListener("mousewheel", function (e) {
1309      const v = -e.wheelDelta / 2;
1310      this.scrollLeft += v;
1311      e.preventDefault();
1312    });
1313  },
1314  // 切换菜单显示热评
1315  switchRightClickMenuHotReview: function () {
1316    const postComment = document.getElementById("post-comment");
1317    const menuCommentBarrageDom = document.getElementById("menu-commentBarrage");
1318    if (postComment) {
1319      menuCommentBarrageDom.style.display = "flex";
1320    } else {
1321      menuCommentBarrageDom.style.display = "none";
1322    }
1323  },
1324  // 切换作者卡片状态文字
1325  changeSayHelloText: function () {
1326    const greetings = GLOBAL_CONFIG.authorStatus.skills;
1327
1328    const authorInfoSayHiElement = document.getElementById("author-info__sayhi");
1329
1330    // 如果只有一个问候语,设置为默认值
1331    if (greetings.length === 1) {
1332      authorInfoSayHiElement.textContent = greetings[0];
1333      return;
1334    }
1335
1336    let lastSayHello = authorInfoSayHiElement.textContent;
1337
1338    let randomGreeting = lastSayHello;
1339    while (randomGreeting === lastSayHello) {
1340      randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
1341    }
1342    authorInfoSayHiElement.textContent = randomGreeting;
1343  },
1344};
1345
1346const anzhiyuPopupManager = {
1347  queue: [],
1348  processing: false,
1349  Jump: false,
1350
1351  enqueuePopup(title, tip, url, duration = 3000) {
1352    this.queue.push({ title, tip, url, duration });
1353    if (!this.processing) {
1354      this.processQueue();
1355    }
1356  },
1357
1358  processQueue() {
1359    if (this.queue.length > 0 && !this.processing) {
1360      this.processing = true;
1361      const { title, tip, url, duration } = this.queue.shift();
1362      this.popupShow(title, tip, url, duration);
1363    }
1364  },
1365
1366  popupShow(title, tip, url, duration) {
1367    const popupWindow = document.getElementById("popup-window");
1368    if (!popupWindow) return;
1369    const windowTitle = popupWindow.querySelector(".popup-window-title");
1370    const windowContent = popupWindow.querySelector(".popup-window-content");
1371    const cookiesTip = windowContent.querySelector(".popup-tip");
1372    if (popupWindow.classList.contains("show-popup-window")) {
1373      popupWindow.classList.add("popup-hide");
1374    }
1375
1376    // 等待上一个弹窗完全消失
1377    setTimeout(() => {
1378      // 移除之前的点击事件处理程序
1379      popupWindow.removeEventListener("click", this.clickEventHandler);
1380      if (url) {
1381        if (window.pjax) {
1382          this.clickEventHandler = event => {
1383            event.preventDefault();
1384            pjax.loadUrl(url);
1385            popupWindow.classList.remove("show-popup-window");
1386            popupWindow.classList.remove("popup-hide");
1387            this.Jump = true;
1388
1389            // 处理队列中的下一个弹出窗口
1390            this.processing = false;
1391            this.processQueue();
1392          };
1393
1394          popupWindow.addEventListener("click", this.clickEventHandler);
1395        } else {
1396          this.clickEventHandler = () => {
1397            window.location.href = url;
1398          };
1399          popupWindow.addEventListener("click", this.clickEventHandler);
1400        }
1401        if (popupWindow.classList.contains("no-url")) {
1402          popupWindow.classList.remove("no-url");
1403        }
1404      } else {
1405        if (!popupWindow.classList.contains("no-url")) {
1406          popupWindow.classList.add("no-url");
1407        }
1408
1409        this.clickEventHandler = () => {
1410          popupWindow.classList.add("popup-hide");
1411          setTimeout(() => {
1412            popupWindow.classList.remove("popup-hide");
1413            popupWindow.classList.remove("show-popup-window");
1414          }, 1000);
1415        };
1416        popupWindow.addEventListener("click", this.clickEventHandler);
1417      }
1418
1419      if (popupWindow.classList.contains("popup-hide")) {
1420        popupWindow.classList.remove("popup-hide");
1421      }
1422      popupWindow.classList.add("show-popup-window");
1423      windowTitle.textContent = title;
1424      cookiesTip.textContent = tip;
1425    }, 800);
1426
1427    setTimeout(() => {
1428      if (url && !this.Jump) {
1429        this.Jump = false;
1430      }
1431      if (!popupWindow.classList.contains("popup-hide") && popupWindow.className != "") {
1432        popupWindow.classList.add("popup-hide");
1433      }
1434
1435      // 处理队列中的下一个弹出窗口
1436      this.processing = false;
1437      this.processQueue();
1438    }, duration);
1439  },
1440};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.