Greasy Fork is available in English.

评论历史记录与评论收藏(哔哩哔哩|B站|bilibili)

记录点赞的评论, 发送过的历史评论, Ctrl+双击可收藏页面中的评论, 双击评论记录可跳转到评论来源页面

// ==UserScript==
// @name          评论历史记录与评论收藏(哔哩哔哩|B站|bilibili)
// @namespace     https://greasyfork.org/zh-CN/users/1196880-ling2ling4
// @version       2.8.6
// @author        Ling2Ling4
// @description   记录点赞的评论, 发送过的历史评论, Ctrl+双击可收藏页面中的评论, 双击评论记录可跳转到评论来源页面
// @license       AGPL-3.0-or-later
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAN0AAADICAYAAABs3+QyAAAAAXNSR0IArs4c6QAAEXlJREFUeF7tXUuPHUcVrmqckFhxlBlHBCUWnuvIUqRIWSBFsEDYRog10cTskGcEKyR+Atgj5TewQpoxLGEEbFnEYyk7EAtW3thzE4EUJL+UmMhEzi10+t7u6e7b3fXoquqqrq+lkSG3qrrqO+fTeVVVc4bHKwJ/On60RS98xthWxlj+v9liQf+eLyYiON/ixW8dsxOMzdt+4kLQf/94kWVH9PspxubvzTZa23pdOF5WIsCBhRsE/nD86HJOqoJQnF9mEiK5mclyVMFYTkKQ0iXKamODdGo4dbYiy7Vg7HIo5DJZDhGSC3GbrCMsowmCen1AOj282OHxox22WFxiI1suzWlrNQcJteDSbgzSSSBbkWxLcH6Jk0VL85lTDMk5v5kxdoQYcZgSgHQt+BHRhBDXEiZZr1aRJRSc78EVNSMfSLfCreI27phBmWYvEFBf7kmTDkTTV5h+EygOFll2ExawH9ckSXd498H+lBMhlqlkNpwQB1mW7SH+W4cvGdLldbPF4hrjHO6jGY2MepH7+TXOd0G+E/gmTzokRYy4Yr1TEftdnW3kRfqUn8mSLo/XhLg+5i6QlBWra+0gH2OTIx3IFgfV8wJ8onW/yZCOYjYuxHXU1uIgXWWWc8b5XkpF9+hJB7JFR7LWCafkdkZNuj/ee3gLlm0apCtWkUK2M0rS5el/IW5NS92wmhoCQuxlWXYwxVJDVKSjYzRfCbEP65YMQecLznenVmaIhnSrrOR+MuqGhZYITM3lDJ50sG5g3wn7puFyBk06xG4gXAsC84zzKzHHesGS7vDugxuMc9pRggcIrCMgxN72m2dvxAhNkKRDKSBGVfI/51hjvaBIt3InKVmyvJoODxCQIxCduxkM6ZCdlGsXWvQgEFFdLwjSIX4DnWwgEIu7OTrpVqe4cbDUhtZhDEIgeHdzVNIhYQKWOEOA893t2caBs/EHDDwa6UC4AVJDVzUEAiWed9Jhh4mavqCVJQQCrOd5JR0IZ0mRMIweAoERzyvp4FLq6QpaW0QgoJKCN9KBcBYVCEOZIRAI8byQDoQz0xH0so9ACLU856RDHc6+4mDEgQiMHOM5JR0IN1A50N0dAiMSzxnpsJfSnb5gZEsIjEQ8J6TLPwksxLElaDAMEHCGwILzK77vYLFOuhXh6KYuHM9xpioY2CYCGecznyfRrZMOmUqb6oCxPCHgdZO0VdLhiI4nFcFrXCDgjXjWSIdLhFzoAcb0ioCnxIoV0iFx4lU18DKXCHggnhXSIY5zqQUY2zcCrhMrg0kHt9K3SuB9HhBwGt8NIh3cSg/ixyvGQcChmzmIdNjmNY4+4K1+EHDlZhqTDm6lH8HjLaMi4MTNNCId3MpRFQEv94mAAzfTiHQogvuU+nTe9eoLp9i3XnqenT6V5X/3nz5jdx4/ZV88WwS9SNtupjbpYOWC1o8gJ0dEoz8iXdvz1399FjrxrLqZ2qSDlQtSr4ObVEEy+lf2kLWjv6Afi26mFulg5YJWi9EnV7iP9C+5j6oPuZdk7QJ/rFk7LdJh50ngajHS9GTuo8q0/jx/rNJs3DaWrJ0y6WDlxpV3aG/XcR9lc4/E0uXLsJFUUSYdrJxMdab/u6n7KEOGspgfffpE1iyM3y1YOyXSwcqFIe+xZkFW7a1XXtCK03TmGkUipbKgodZOiXTY7qWjQtNoayNOU0WCrBxZu1geujvz/QubV0znKyUdrJwptPH1sxmn6aw+iiRKY0FDrJ2UdKjL6ahPnG1du499qMSURKmtQ4iD7TfP7ppIvJd0sHImkMbRx6f72IdIbPFcdS2m1q6XdLBycRBIdZZUsKaEiG7xWnV8k3YRbAHrXpZhJrOfdPce0oWxuL/SRJsC6hOKVWtCEq1rOTCT2Uk6nJcLiDUGUylqaip7Hw2Gt9IlZteyBMDA2nWSDmUCK3rlfZAxkyK6i42tVNCxvvn2hc2ZztpbSYcEig6E47cdK9U/ZOVTcC3L9XO+uz3bOFDFo5V0SKCowjduO0qKFIdCx52J/tsn4Vqulq1bLO8i3T7jfEcfSvRwjUCoSRHddU+JdLR2nfLBGungWuqqj5/2McVqKojEuAuld10aCZU10sG1VFEZP21ijNVUkJlUPGfgYraRDq6liuY4bDM1q9aEamquZbE+VRezRjq4lg6ZJBk6hrqaLXQm51oWwCi6mDXSoSBuS63Ux5m6VWsiEdWBVXUx5i1Vs5g10iGe00TZsHlKVq0J0T/uf8E+efKlIXLhd1NxMWukw5UMboU6lXS/KUpTTKCsYaHgYtYt3b2HwhRQ9OtGIOYitk25TjWBUsVIxcUsSYckik31YuWNxiFvOLa7YvloUR/jkS+vbCFzMUvSIZ7TQLWnaWqJEVXUknAtCzAkezFL0iGeU1Wf9XbF4VBYtW4MU3Aty9VLrnI4sXSI57RZl3piRAewydbmOkDYvrDZeWwu/wHxnI76LOM1l/dA6s0m/NZJuZYrcfTFdTnpUBRXU9xvv3o6JxwePQSSci0V4rqcdEiidCtRyoVsPWq1t07RyuVI9MR1IF2HZiFes0E5ln93Lvhvz9lZ6tooXXFdTjpkLk/wQrxmVwNTqc21odYV1y0tHTKXDPGaXbLRaMm6lpK4jqecuUS8Zp9o1RGnvrlZil5HXJck6YhsxU3HUuDQwAiB5K1cz1Effnj8aIcJsW+EbGSdkBzxJ7CUEyhVlNviOp5CuQBk80e24k2p7UDpQjg50iET6Z9s9EZYuQruLZufJ2npQLZxyFa8dSLXpdsBsSWZQqSbzO1fIJsdPRkyChIodfTaDrXyKRTGcTJ7CE3s9oVruY5nc2dK1KQjstEfnjAQgJVrl0MzmcIPI/zwI9zIMEjWnAWsXIdcGskUIl00lxHRCW3arkXFbTzhIZDyPsteacRMuu998yUQLjyu5TOCa9kjmEYGMxr3kqzcj869HKjKYVrJ77Ps4xxjR+9f2LxSNImGdDRhIh2RD09YCMDK9cujWTaIinQoDYRFtmI2SKDI5VItG0RFOloaJVEomQKLJxe0rxbYZylHulo2iI50xfJw6FQuaB8tYOXUUJ4E6WD11ITtuhXKBIoIV8oG0Vq66lJRLFcUvOVmSKBoADo10lVdTor5EO9pKMOApigTaIBX+YRW1Hsv25aMqxg0FGFAU1g5TfAqBfJJHe2pwoAsp6ZSaDZHAkUTsBRIV0AC8mkqh0JzWDkFkBpNqgXyZC4mAvn0FaWrB6ycPpZJkg6WT19R2nrAyhnjON++sDmj3jzVL/bA8pkpD6ycGW7Uq9gKluRls6jxmSsOtnyZY1fsSsG3DFYYYluZXJlg5eQY9bVoku6YMbY1bMj4e+POlX4ZYsvXMB2vk25C1/ANgwVn9rrwQwJlqGYxBtJ1YEj7OMnVxFNHAFu+hmtEnXQJfUREBTqcUK+jBCunojXyNjXSpfyNujaokFSpo4IEipxQKi0WnF+5Ots4yrOX9MR4/6XKQk3awMU8QQ1WzkSD2vuskW4K16vbg4exH2+9YnO4aMeClbMnunVLhwxmDV3EdbjL0h7dliOtkw7JlBrGiOvwnTnnpENcV4c49bgOsZxtyrVYOnoF4roToGlDNF3jnuqDWM6+5GslgzKDeffBDcb5dfuvi3PElJMp2NhsX2dbSZfqMZ8ueE2SKbf//Tn7+YfH7PzLz7Pvv36G/frdN+xLz/GIsHJuAC6P9jSHR73uBBGTZMpzv/lbDdJfvft6dMSDlfNNOpQOSsR1SUcW7uad+2sS2zrzdfbbH8zYpTfOuJGmxVFh5SyC2Riq29KhdFBCpZvBbFq5pvhisHqwcs5Id3JdQ9sr4GIuUdHJYP7uzn32sw/pWGL/Q1bvp2+dDdLlhJWTSW/Q7xLSwcUs0VVNpvzwL3cYJVFUnxBdThxSVZWeUbt+0iGLeQKqCumIbEQ6k+eD755jv3zntdGvgoeVM5Geep/aFXxd3eBiLpFRSaZ0JVBURHLjO+fY22dfZGN/8BJWTkVaA9pUb3juJB0K5Tk0KskUWQKlC+OrFzfZTy6eLX+mD58U5BsgXu2usHLakOl3qH5ApKv36mDrrdQvLJIlU1QTKE2cybqRlWt7fN/JCSunzyHtHiqko0GxF3MJbV9cp5tAofH6CFcVpo/v7t1/+ox99OkTbR1CBz0EimM91Ks8Od42xCFqdr1xnUkCRZVwVXlQXOnqu3uwcnrkMW2tTDp6ARIqLI+z6K/56CZQmjGcjgCJdGT56M/WAytnC0n5OMVuFKmly0mHhEpnkVw1gfKNF59jv3jntdytHPrY/OglrNxQaaj31yIdrF17XKdq5UzcSRVRDk22wMqpoGytTVkYV7J0sHZL4JsupszKkXW7dO5MrSRgTYSVgUyTLbByLqTRPma1MK5MOli7urWTlQmGxG6mqqCTbEFdzhRlw36VcoEe6RDblbtTLv7+n2z++f9qEvBl2WRil+1sgVspQ9DB75zvbs82DoqRe0sGzdennsmkOOre46e10wShkK0pqyLhQrtc6I+eT558yeibBHj8IlAtF2hZOsR2S0H9/T//Zfc+e8re3jxtJRvpQ/wF6eiGLzz+EahmLrVJh9jOv8DwxugRqGUujUi3Ovazn/qezOhVAQvwgkAzc2lEOriZXmSFl0wFgUbm0ph0OIEwFY3AOlwj0EyiGJMO1s61qDD+VBBoJlEGkQ5JlamoBdbhEIG1JMpg0sHNdCguDB0/Ai3x3GDSwc2MXy+wAocIuCLdinj7jPMdh9PH0EAgOgSKD4Y0J661Daxr1XAzo9MHTNg9Aq3xnBX3spg7rnZwL0W8IR4E2orixeytWLqSeDiJEI9WYKZuEeiI56xaumIFuEHMrSwxehwItNXnnFi60uLde0hf0tiKAx7MEghYR6AznnNi6WhQJFasCxEDxoRAj2vpjHQ0ME4jxKQlmKtNBPpcS6eko8FxfZ9NUWKsSBDodS2dkw7Ei0RNME17CEhcSy+kA/HsyRMjhY+AzLX0RjoQL3xlwQytICB1Lb2SDsSzIlQMEjICCq6ld9KBeCFrDOY2EAElKzcK6UC8gaJF9zARULRyo5EOxAtTbzArYwSUrdyopKsQ7xq2jBkLGx1DQEDDyo1OOpoAdq6EoDWYwwAEtKxcEKSjSWCv5gCRo+u4CGhauWBIB+KNqzd4uzEC2lYuKNIVyz68+wD3rRjrADp6RcDAygVJujzBcvxohwlxHQkWryqEl2kg0Hcdg2wYq9c1yF6m8zvFeV8Jsc8Zu6zTD22BgAcEjNzKYl7Bkq7ibt5gnKOs4EGT8Ao1BNq+T6DWc9kqeNLRJFFW0BEp2jpFwDCOq84pCtI1kizkbuL+FaeahcHbEBgSx0VLusLqcSGuI9YDMTwjMCiOi5p0pdVDhtOzzqX9uqFx3CRIB5czbRL4XL1NwkWTSJEBTIkWuJwylPC7CQK2CTcZ0hVggnwmaoU+HQjMF5zvXp1tHNlGKKrsperiQT5VpNDON+EmZ+maAFbIRyUGlBnAMRUErGUpu142SUvXRr5ssbjGOEeNT0XtEm1jqw4ngy8J0lVBgOspU4kkf3cWv7WhmRzpqkkXWL8kCVZftIVtXbooJku6pvUDAXVVJ+725EoKzvdcZCdlyIB0DYTyzdWLxWWcbJCpTsS/j2DdqmiBdD26UxBQcH6JL7OfyIBGyjWybJzzm9uzjYOxlwDSaUgAJNQAK5SmQhwssuzmGG5k0iUDl/IHEV2iazz2nHG+F4JVQ/bSWIbqHemaiWeMbVFcCLdUHbfBLYU4YFl2O2Ps6L3ZxnzweA4HgHvpENxi6IKI9P/zJA1j5wXnW6s4kf4zYkVdOUREsubSQDpdYTtor0DKVIk5Z0IsNxxn2e38nwgsmUxFQDoZQoH9TgSlKZELW0wto/+9WFSt5XnJtD9WXJZsnHwYstqK4zEuRNP1W84ly/L/TqSif0N3EVXX29YOpBuCHvoCAQME/g8ZPlBBSTh+ZwAAAABJRU5ErkJggg==
// @match         *://*.bilibili.com/*
// @run-at        document-end
// @grant         GM_setValue
// @grant         GM_getValue
// @grant         GM_registerMenuCommand
// @noframes
// @compatible    chrome
// @compatible    edge
// @compatible    firefox
// ==/UserScript==

(() => {
  "use strict";
  function getBiliPageType() {
    const url = window.location.href,
      hostname = window.location.hostname,
      pathname = window.location.pathname;
    return "www.bilibili.com" !== hostname ||
      ("/" !== pathname && "/index.html" !== pathname)
      ? url.includes("www.bilibili.com/video") ||
        url.includes("www.bilibili.com/list")
        ? "视频"
        : "search.bilibili.com" === hostname
        ? "搜索"
        : "space.bilibili.com" === hostname
        ? "主页"
        : url.includes("t.bilibili.com") ||
          url.includes("www.bilibili.com/opus")
        ? "动态"
        : url.includes("www.bilibili.com/read")
        ? "专栏"
        : url.includes("www.bilibili.com/bangumi")
        ? "番剧"
        : "live.bilibili.com" === hostname
        ? "直播"
        : "message.bilibili.com" === hostname && "/" === pathname
        ? "消息"
        : "其他"
      : "首页";
  }
  function addCss(cssText, box = document.body, id = "") {
    const style = document.createElement("style");
    return (
      id && (style.id = id),
      box.appendChild(style),
      (style.innerHTML = cssText),
      style
    );
  }
  const className = "emoji-small",
    emoji = {
      "[14周年]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/53148f85bb7e2d8bada8cea57ee4b1f36f48237d.png@48w_48h.webp" alt="[2023]">`,
      "[2023]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fa6dda8b876ed38609de38aa604be5ad109b8591.png@48w_48h.webp" alt="[兔年]">`,
      "[兔年]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9cb6ee2c42986c56ec361d21d5ccbd096aefab0a.png@48w_48h.webp" alt="[14周年]">`,
      "[脱单doge]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/bf7e00ecab02171f8461ee8cf439c73db9797748.png@48w_48h.webp" alt="[脱单doge]">`,
      "[微笑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/685612eadc33f6bc233776c6241813385844f182.png@48w_48h.webp" alt="[微笑]">`,
      "[口罩]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3ad2f66b151496d2a5fb0a8ea75f32265d778dd3.png@48w_48h.webp" alt="[口罩]">`,
      "[doge]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png@48w_48h.webp" alt="[doge]">`,
      "[妙啊]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b4cb77159d58614a9b787b91b1cd22a81f383535.png@48w_48h.webp" alt="[妙啊]">`,
      "[OK]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4683fd9ffc925fa6423110979d7dcac5eda297f4.png@48w_48h.webp" alt="[OK]">`,
      "[星星眼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/63c9d1a31c0da745b61cdb35e0ecb28635675db2.png@48w_48h.webp" alt="[星星眼]">`,
      "[辣眼睛]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/35d62c496d1e4ea9e091243fa812866f5fecc101.png@48w_48h.webp" alt="[辣眼睛]">`,
      "[吃瓜]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4191ce3c44c2b3df8fd97c33f85d3ab15f4f3c84.png@48w_48h.webp" alt="[吃瓜]">`,
      "[滑稽]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/d15121545a99ac46774f1f4465b895fe2d1411c3.png@48w_48h.webp" alt="[滑稽]">`,
      "[呲牙]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b5a5898491944a4268360f2e7a84623149672eb6.png@48w_48h.webp" alt="[呲牙]">`,
      "[打call]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/431432c43da3ee5aab5b0e4f8931953e649e9975.png@48w_48h.webp" alt="[打call]">`,
      "[歪嘴]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4384050fbab0586259acdd170b510fe262f08a17.png@48w_48h.webp" alt="[歪嘴]">`,
      "[调皮]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8290b7308325e3179d2154327c85640af1528617.png@48w_48h.webp" alt="[调皮]">`,
      "[豹富]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3d1dbe52ea16e12ff7b1c371196f728a4097fb33.png@48w_48h.webp" alt="[豹富]">`,
      "[嗑瓜子]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/28a91da1685d90124cfeead74622e1ebb417c0eb.png@48w_48h.webp" alt="[嗑瓜子]">`,
      "[笑哭]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c3043ba94babf824dea03ce500d0e73763bf4f40.png@48w_48h.webp" alt="[笑哭]">`,
      "[藏狐]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ba0937ef6f3ccca85e2e0047e6263f3b4da37201.png@48w_48h.webp" alt="[藏狐]">`,
      "[脸红]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/0922c375da40e6b69002bd89b858572f424dcfca.png@48w_48h.webp" alt="[脸红]">`,
      "[给心心]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1597302b98827463f5b75c7cac1f29ea6ce572c4.png@48w_48h.webp" alt="[给心心]">`,
      "[嘟嘟]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/abd7404537d8162720ccbba9e0a8cdf75547e07a.png@48w_48h.webp" alt="[嘟嘟]">`,
      "[哦呼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/362bded07ea5434886271d23fa25f5d85d8af06c.png@48w_48h.webp" alt="[哦呼]">`,
      "[喜欢]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8a10a4d73a89f665feff3d46ca56e83dc68f9eb8.png@48w_48h.webp" alt="[喜欢]">`,
      "[酸了]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/92b1c8cbceea3ae0e8e32253ea414783e8ba7806.png@48w_48h.webp" alt="[酸了]">`,
      "[嫌弃]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/de4c0783aaa60ec03de0a2b90858927bfad7154b.png@48w_48h.webp" alt="[嫌弃]">`,
      "[害羞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9d2ec4e1fbd6cb1b4d12d2bbbdd124ccb83ddfda.png@48w_48h.webp" alt="[害羞]">`,
      "[大哭]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/2caafee2e5db4db72104650d87810cc2c123fc86.png@48w_48h.webp" alt="[大哭]">`,
      "[疑惑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b7840db4b1f9f4726b7cb23c0972720c1698d661.png@48w_48h.webp" alt="[疑惑]">`,
      "[喜极而泣]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/485a7e0c01c2d70707daae53bee4a9e2e31ef1ed.png@48w_48h.webp" alt="[喜极而泣]">`,
      "[笑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/81edf17314cea3b48674312b4364df44d5c01f17.png@48w_48h.webp" alt="[笑]">`,
      "[偷笑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/6c49d226e76c42cd8002abc47b3112bc5a92f66a.png@48w_48h.webp" alt="[偷笑]">`,
      "[惊讶]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/f8e9a59cad52ae1a19622805696a35f0a0d853f3.png@48w_48h.webp" alt="[惊讶]">`,
      "[捂脸]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/6921bb43f0c634870b92f4a8ad41dada94a5296d.png@48w_48h.webp" alt="[捂脸]">`,
      "[阴险]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ba8d5f8e7d136d59aab52c40fd3b8a43419eb03c.png@48w_48h.webp" alt="[阴险]">`,
      "[呆]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/33ad6000d9f9f168a0976bc60937786f239e5d8c.png@48w_48h.webp" alt="[呆]">`,
      "[抠鼻]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cb89184c97e3f6d50acfd7961c313ce50360d70f.png@48w_48h.webp" alt="[抠鼻]">`,
      "[大笑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ca94ad1c7e6dac895eb5b33b7836b634c614d1c0.png@48w_48h.webp" alt="[大笑]">`,
      "[惊喜]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/0afecaf3a3499479af946f29749e1a6c285b6f65.png@48w_48h.webp" alt="[惊喜]">`,
      "[无语]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/44667b7d9349957e903b1b62cb91fb9b13720f04.png@48w_48h.webp" alt="[无语]">`,
      "[点赞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1a67265993913f4c35d15a6028a30724e83e7d35.png@48w_48h.webp" alt="[点赞]">`,
      "[鼓掌]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/895d1fc616b4b6c830cf96012880818c0e1de00d.png@48w_48h.webp" alt="[鼓掌]">`,
      "[尴尬]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cb321684ed5ce6eacdc2699092ab8fe7679e4fda.png@48w_48h.webp" alt="[尴尬]">`,
      "[灵魂出窍]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/43d3db7d97343c01b47e22cfabeca84b4251f35a.png@48w_48h.webp" alt="[灵魂出窍]">`,
      "[委屈]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/d2f26cbdd6c96960320af03f5514c5b524990840.png@48w_48h.webp" alt="[委屈]">`,
      "[傲娇]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/010540d0f61220a0db4922e4a679a1d8eca94f4e.png@48w_48h.webp" alt="[傲娇]">`,
      "[疼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/905fd9a99ec316e353b9bd4ecd49a5f0a301eabf.png@48w_48h.webp" alt="[疼]">`,
      "[冷]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cb0ebbd0668640f07ebfc0e03f7a18a8cd00b4ed.png@48w_48h.webp" alt="[冷]">`,
      "[热]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4e58a2a6f5f1580ac33df2d2cf7ecad7d9ab3635.png@48w_48h.webp" alt="[热]">`,
      "[生病]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/0f25ce04ae1d7baf98650986454c634f6612cb76.png@48w_48h.webp" alt="[生病]">`,
      "[捂眼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c5c6d6982e1e53e478daae554b239f2b227b172b.png@48w_48h.webp" alt="[捂眼]">`,
      "[嘘声]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/e64af664d20716e090f10411496998095f62f844.png@48w_48h.webp" alt="[嘘声]">`,
      "[思考]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cfa9b7e89e4bfe04bbcd34ccb1b0df37f4fa905c.png@48w_48h.webp" alt="[思考]">`,
      "[再见]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fc510306bae26c9aec7e287cdf201ded27b065b9.png@48w_48h.webp" alt="[再见]">`,
      "[翻白眼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/eba54707c7168925b18f6f8b1f48d532fe08c2b1.png@48w_48h.webp" alt="[翻白眼]">`,
      "[哈欠]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/888d877729cbec444ddbd1cf4c9af155a7a06086.png@48w_48h.webp" alt="[哈欠]">`,
      "[奋斗]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/bb2060c15dba7d3fd731c35079d1617f1afe3376.png@48w_48h.webp" alt="[奋斗]">`,
      "[墨镜]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3a03aebfc06339d86a68c2d893303b46f4b85771.png@48w_48h.webp" alt="[墨镜]">`,
      "[难过]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/a651db36701610aa70a781fa98c07c9789b11543.png@48w_48h.webp" alt="[难过]">`,
      "[撇嘴]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/531863568e5668c5ac181d395508a0eeb1f0cda4.png@48w_48h.webp" alt="[撇嘴]">`,
      "[抓狂]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4c87afff88c22439c45b79e9d2035d21d5622eba.png@48w_48h.webp" alt="[抓狂]">`,
      "[生气]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3195714219c4b582a4fb02033dd1519913d0246d.png@48w_48h.webp" alt="[生气]">`,
      "[水稻]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/d530fcaa5100ba12a17a79b55bad342d530c54e3.png@48w_48h.webp" alt="[水稻]">`,
      "[奶茶干杯]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/d5a491990be551ce69f9660da948050df4eab331.png@48w_48h.webp" alt="[奶茶干杯]">`,
      "[汤圆]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/93609633a9d194cf336687eb19c01dca95bde719.png@48w_48h.webp" alt="[汤圆]">`,
      "[锦鲤]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/643d6c19c8164ffd89e3e9cdf093cf5d773d979c.png@48w_48h.webp" alt="[锦鲤]">`,
      "[福到了]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/5de5373d354c373cf1617b6b836f3a8d53c5a655.png@48w_48h.webp" alt="[福到了]">`,
      "[鸡腿]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c7860392815d345fa69c4f00ef18d67dccfbd574.png@48w_48h.webp" alt="[鸡腿]">`,
      "[雪花]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/a41813c4edf8782047e172c884ebd4507ce5e449.png@48w_48h.webp" alt="[雪花]">`,
      "[视频卫星]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/dce6fc7d6dfeafff01241924db60f8251cca5307.png@48w_48h.webp" alt="[视频卫星]">`,
      "[干杯]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8da12d5f55a2c7e9778dcc05b40571979fe208e6.png@48w_48h.webp" alt="[干杯]">`,
      "[黑洞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c4e9f0e3f35961d5037cb071b16ddba2170b262c.png@48w_48h.webp" alt="[黑洞]">`,
      "[爱心]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ed04066ea7124106d17ffcaf75600700e5442f5c.png@48w_48h.webp" alt="[爱心]">`,
      "[胜利]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b49fa9f4b1e7c3477918153b82c60b114d87347c.png@48w_48h.webp" alt="[胜利]">`,
      "[加油]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c7aaeacb21e107292d3bb053e5abde4a4459ed30.png@48w_48h.webp" alt="[加油]">`,
      "[抱拳]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/89516218158dbea18ab78e8873060bf95d33bbbe.png@48w_48h.webp" alt="[抱拳]">`,
      "[响指]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1b5c53cf14336903e1d2ae3527ca380a1256a077.png@48w_48h.webp" alt="[响指]">`,
      "[保佑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fafe8d3de0dc139ebe995491d2dac458a865fb30.png@48w_48h.webp" alt="[保佑]">`,
      "[福]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/802429a301ac5b35a0480d9526a070ce67cd8097.png@48w_48h.webp" alt="[福]">`,
      "[支持]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/3c210366a5585706c09d4c686a9d942b39feeb50.png@48w_48h.webp" alt="[支持]">`,
      "[拥抱]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/41780a4254750cdaaccb20735730a36044e98ef3.png@48w_48h.webp" alt="[拥抱]">`,
      "[跪了]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/f2b3aee7e521de7799d4e3aa379b01be032698ac.png@48w_48h.webp" alt="[跪了]">`,
      "[怪我咯]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/07cc6077f7f7d75b8d2c722dd9d9828a9fb9e46d.png@48w_48h.webp" alt="[怪我咯]">`,
      "[香格里拉边境]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/80e53d32b4abd12232126f03c68de7c1a67a1e9f.png@48w_48h.webp" alt="[香格里拉边境]">`,
      "[老鼠]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8e6fb491eb1bb0d5862e7ec8ccf9a3da12b6c155.png@48w_48h.webp" alt="[老鼠]">`,
      "[牛年]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9275275ff1f2659310648221107d20bc4970f106.png@48w_48h.webp" alt="[牛年]">`,
      "[三星堆]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fc7dadaa6986e75b813aa26f3eff3281d5f1a6d1.png@48w_48h.webp" alt="[三星堆]">`,
      "[桃源_给花花]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/085d41d0fa25453b58fdc87dc2df538183fea11e.png@48w_48h.webp" alt="[桃源_给花花]">`,
      "[桃源_缘分]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cf1c441507689342713623965035f9bed72b1b17.png@48w_48h.webp" alt="[桃源_缘分]">`,
      "[桃源_傲娇]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ce8314c9c2cfdbe235c239c28b819698e29a02d3.png@48w_48h.webp" alt="[桃源_傲娇]">`,
      "[桃源_欢呼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1f439878d8160bd64a4464904064a10df880c921.png@48w_48h.webp" alt="[桃源_欢呼]">`,
      "[桃源_乖巧]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/57d087b6437002c2ca9e225dcac0ef226d1f2654.png@48w_48h.webp" alt="[桃源_乖巧]">`,
      "[洛天依]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9fe06f3594d9afaf4ee2b74770f1c3086ae0ba11.png@48w_48h.webp" alt="[洛天依]">`,
      "[坎公骑冠剑_吃鸡]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c4248a7b6ab326d66c83fd1fb58f1a50f99df332.png@48w_48h.webp" alt="[坎公骑冠剑_吃鸡]">`,
      "[坎公骑冠剑_钻石]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/0b97c7e50e0cc963370e62fbb9b55f51bbe7f8ab.png@48w_48h.webp" alt="[坎公骑冠剑_钻石]">`,
      "[坎公骑冠剑_无语]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/80eba0ce64c3fc1279b4daede2f1979cb2380e78.png@48w_48h.webp" alt="[坎公骑冠剑_无语]">`,
      "[来古-疑问]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/032fdc0d9d9fe6334776f6c39518a959b73b98f4.png@48w_48h.webp" alt="[来古-疑问]">`,
      "[来古-沉思]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4ee07ff03266d62b246be0b950bebb2abf3d997c.png@48w_48h.webp" alt="[来古-沉思]">`,
      "[来古-呆滞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9a70b365e523f2379f395031ceefcebb75a45903.png@48w_48h.webp" alt="[来古-呆滞]">`,
      "[来古-震撼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8b40f228675602a317d32007de6b795c101135ec.png@48w_48h.webp" alt="[来古-震撼]">`,
      "[来古-注意]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/4b671ba32a2581cf40e5cd41c67b111eb8010de0.png@48w_48h.webp" alt="[来古-注意]">`,
      "[FGO_耶]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cb57c18365601d277e5a5d52b0957616d034f04c.png@48w_48h.webp" alt="[FGO_耶]">`,
      "[FGO_开心]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/300dadb9ec3cf14cf5ed55e2542947fe6e4f0295.png@48w_48h.webp" alt="[FGO_开心]">`,
      "[FGO_汗]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/93d8a770a22914ade2354ca928bb1799b2260d00.png@48w_48h.webp" alt="[FGO_汗]">`,
      "[FGO_怒]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/75ee235f331b3c714e1cfb264fff9e562b20944b.png@48w_48h.webp" alt="[FGO_怒]">`,
      "[FGO_偷看]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b2d752b135b72a93c13b26bb0e272070a906257b.png@48w_48h.webp" alt="[FGO_偷看]">`,
      "[初音未来_大笑]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8e7f71cda83ce407b0684702983399f8ed982f17.png@48w_48h.webp" alt="[初音未来_大笑]">`,
      "[原神_哇]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8188ddf95bace929d382c7a83214afde79d83bfc.png@48w_48h.webp" alt="[原神_哇]">`,
      "[原神_哼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/91ed33b74bc36873c3ac8b2648f70d7ab6d8ab78.png@48w_48h.webp" alt="[原神_哼]">`,
      "[原神_嗯]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8b0a87e414f453a29730b6e0f45ca61f2f898688.png@48w_48h.webp" alt="[原神_嗯]">`,
      "[原神_欸嘿]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/8fba438fcbe0550877b04efd768d857082307c5e.png@48w_48h.webp" alt="[原神_欸嘿]">`,
      "[原神_喝茶]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1de5789fbb3526ef7823c54db7081790a38e7044.png@48w_48h.webp" alt="[原神_喝茶]">`,
      "[原神_生气]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/90a38c34742899f8e84138ed55f56cad3ba611fb.png@48w_48h.webp" alt="[原神_生气]">`,
      "[保卫萝卜_白眼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/9fce63f38288700bf7be84f3be336cf895ba0902.png@48w_48h.webp" alt="[保卫萝卜_白眼]">`,
      "[保卫萝卜_笔芯]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/5ff2ed5cb71b02010018cc5910ac7052a03769af.png@48w_48h.webp" alt="[保卫萝卜_笔芯]">`,
      "[保卫萝卜_哭哭]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/7d249f7c990111d3e2982f7477af15b7eb29cbd9.png@48w_48h.webp" alt="[保卫萝卜_哭哭]">`,
      "[保卫萝卜_哇]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/5f2370e561c32d841245f7b1aab2eef43aeb9544.png@48w_48h.webp" alt="[保卫萝卜_哇]">`,
      "[保卫萝卜_问号]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/41eb93f09fc4a4d0692a310e8a1f85ba60e96060.png@48w_48h.webp" alt="[保卫萝卜_问号]">`,
      "[无悔华夏_不愧是你]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/c58002c32ee78d45366e126f294cb3149dd64ac2.png@48w_48h.webp" alt="[无悔华夏_不愧是你]">`,
      "[无悔华夏_吃瓜]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/273dcff577551bafff4f1eae18561f871e73a6ba.png@48w_48h.webp" alt="[无悔华夏_吃瓜]">`,
      "[无悔华夏_达咩]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cffab383f47bab7f6736ba9c8d6ac098113410d9.png@48w_48h.webp" alt="[无悔华夏_达咩]">`,
      "[无悔华夏_点赞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/b0f2e8db405ec667c3e6aaabd7c15155b6ea8710.png@48w_48h.webp" alt="[无悔华夏_点赞]">`,
      "[无悔华夏_好耶]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/324cd79784aeb37dbf2f47f68bbe8ed5d01f975e.png@48w_48h.webp" alt="[无悔华夏_好耶]">`,
      "[奥比岛_搬砖]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/1fab697214918d91087373a999cc7ef8040ddf85.png@48w_48h.webp" alt="[奥比岛_搬砖]">`,
      "[奥比岛_点赞]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fb0b476fe2ff30cd59385ea7d616627ac114161f.png@48w_48h.webp" alt="[奥比岛_点赞]">`,
      "[奥比岛_击爪]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/35bba1bb8f164c5e844155548438248e6eaa8382.png@48w_48h.webp" alt="[奥比岛_击爪]">`,
      "[奥比岛_委屈]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fda155e7c33b40dbb94c24644e0635d47b6ef3cc.png@48w_48h.webp" alt="[奥比岛_委屈]">`,
      "[奥比岛_喜欢]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ed64e0c81ee194138bd9df30c65077ed978fb88c.png@48w_48h.webp" alt="[奥比岛_喜欢]">`,
      "[黎明觉醒_怒了鸦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/078991ad7546f2fefb79c05894d5f0431736d1e7.png@48w_48h.webp" alt="[黎明觉醒_怒了鸦]">`,
      "[黎明觉醒_石化鸦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/40bc09683e3b93390995b9ea5dc64f982b34e347.png@48w_48h.webp" alt="[黎明觉醒_石化鸦]">`,
      "[黎明觉醒_摊手鸦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/883e4caa8e1745f48de0671c6441810faa4a56ed.png@48w_48h.webp" alt="[黎明觉醒_摊手鸦]">`,
      "[黎明觉醒_比心鸦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/e25f5442c5bce2a54b9c757e3032f44398f1a7df.png@48w_48h.webp" alt="[黎明觉醒_比心鸦]">`,
      "[黎明觉醒_哼白眼鸦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/36de90dbaffeb32477dffdac612ad69da4e19b76.png@48w_48h.webp" alt="[黎明觉醒_哼白眼鸦]">`,
      "[以闪亮之名_哎?!]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/5fafe7d9992e12c756da909a545ddb27486987af.png@48w_48h.webp" alt="[以闪亮之名_哎?!]">`,
      "[以闪亮之名_爱你哦]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/835c3bff4fc686a78f49db1eb68e4d04c0963195.png@48w_48h.webp" alt="[以闪亮之名_爱你哦]">`,
      "[以闪亮之名_吃瓜]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/ebfdda8501e48c2434297e4a9f15218aadf07747.png@48w_48h.webp" alt="[以闪亮之名_吃瓜]">`,
      "[以闪亮之名_好耶!]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/fd0c2bbb806265c468eca83b7a90b0d5fcaa4cec.png@48w_48h.webp" alt="[以闪亮之名_好耶!]">`,
      "[以闪亮之名_星星眼]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/a44a291ffe9334712ba130aa3fca0b940f32908d.png@48w_48h.webp" alt="[以闪亮之名_星星眼]">`,
      "[以闪亮之名_针不戳]": `<img class="${className}" src="https://i0.hdslb.com/bfs/emote/cad39e954972bbd93f0a777978b2f77078b8cf4a.png@48w_48h.webp" alt="[以闪亮之名_针不戳]">`,
    };
  function replaceEmojis(str, obj) {
    if (obj && str) {
      str = str.replaceAll('alt="[', "$_alt_$");
      for (const key in obj) str = str.replaceAll(key, obj[key]);
      str = str.replaceAll("$_alt_$", 'alt="[');
    }
    return str;
  }
  const keyBase = "ll_comment_history_",
    settings = {
      isHiddenBtn: {
        value: !1,
        base: !1,
        valType: "boolean",
        key: keyBase + "isHiddenBtn",
        txt: "是否隐藏按钮 (隐藏整个区域), 隐藏后鼠标移入时会显示出来",
        type: "显示设置",
        compType: "radio",
        valueText: { true: "隐藏", false: "显示" },
      },
      isRetractList: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "isRetractList",
        txt: "是否在鼠标移出列表区域后自动收起列表",
        type: "显示设置",
        compType: "radio",
        valueText: { true: "自动收起", false: "不收起" },
      },
      position: {
        value: "4, 4",
        base: "4, 4",
        valType: "string",
        key: keyBase + "position",
        txt: "设置按钮的显示位置 (左侧 和 顶部的距离), 可以为负值, 中间用 , 分隔\n如: 10,50 表示距离左侧10像素距离顶部50像素",
        type: "显示设置",
        compType: "textarea",
        compH: "30px",
      },
      scale: {
        value: 1,
        base: 1,
        valType: "number",
        key: keyBase + "scale",
        txt: "设置整个区域的缩放倍率 (大于1则放大,小于1则缩小)",
        type: "显示设置",
        compType: "textarea",
        compH: "30px",
      },
      hiddenBtnTime: {
        value: 5e3,
        base: 5e3,
        valType: "number",
        key: keyBase + "hiddenBtnTime",
        txt: "加载页面后隐藏按钮的时间 (毫秒, 1秒=1000毫秒)\n0表示按钮初始隐藏",
        type: "显示设置",
        compType: "textarea",
        compH: "30px",
      },
      closeListTime: {
        value: 0,
        base: 0,
        valType: "number",
        key: keyBase + "closeListTime",
        txt: "自动收起列表的等待时间 (毫秒, 1秒=1000毫秒)\n0表示鼠标移开后立马收起列表",
        type: "显示设置",
        compType: "textarea",
        compH: "30px",
      },
      zanListIsDesc: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "zanListIsDesc",
        txt: "点赞评论的列表是否倒序显示, 倒序则新评论将显示在列表顶部",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "倒序显示", false: "顺序显示" },
      },
      histListIsDesc: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "histListIsDesc",
        txt: "历史评论的列表是否倒序显示",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "倒序显示", false: "顺序显示" },
      },
      sukiListIsDesc: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "sukiListIsDesc",
        txt: "收藏列表是否倒序显示",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "倒序显示", false: "顺序显示" },
      },
      isConfirm: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "isConfirm",
        txt: "点击删除按钮时是否进行弹窗确认",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "弹窗确认", false: "直接删除" },
      },
      editWrapClose: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "editWrapClose",
        txt: "是否在点击编辑区外的背景时取消编辑",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "点击背景时取消编辑", false: "点击背景时无操作" },
      },
      isHiddenList: {
        value: !1,
        base: !1,
        valType: "boolean",
        key: keyBase + "isHiddenList",
        txt: "是否在双击列表的一条评论记录后收起列表",
        type: "列表设置",
        compType: "radio",
        valueText: { true: "双击后收起", false: "不收起" },
      },
      listSize: {
        value: "400x500",
        base: "400x500",
        valType: "string",
        key: keyBase + "listSize",
        txt: "设置列表的宽度和最大高度, 中间用 x 分隔\n如: 400x300 表示列表宽度400像素, 列表最大高度300像素",
        type: "列表设置",
        compType: "textarea",
        compH: "30px",
      },
      zanListMaxLen: {
        value: 1500,
        base: 1500,
        valType: "number",
        key: keyBase + "zanListMaxLen",
        txt: "点赞列表的最大长度, 超出时最早的数据会被删除, 0表示无长度上限 (收藏列表默认无长度上限). 点赞列表过长时会影响页面点赞按钮变色的响应速度",
        type: "列表设置",
        compType: "textarea",
        compH: "30px",
      },
      listMaxLen: {
        value: 0,
        base: 0,
        valType: "number",
        key: keyBase + "listMaxLen",
        txt: "历史列表的最大长度",
        type: "列表设置",
        compType: "textarea",
        compH: "30px",
      },
      liMaxHeight: {
        value: 220,
        base: 220,
        valType: "number",
        key: keyBase + "liMaxHeight",
        txt: "设置列表项的最大高度, 0表示不限制高度, 完全显示每一项",
        type: "列表设置",
        compType: "textarea",
        compH: "30px",
      },
      titleFormat: {
        title: "标题格式",
        value: "[评论日期] [网页标题]",
        base: "[评论日期] [网页标题]",
        valType: "string",
        key: keyBase + "titleFormat",
        txt: '设置新增列表项的标题格式, 可根据需要调整格式, 增减内容, 新增列表项的标题将按照设定的格式生成\n示例: "[评论日期]-[评论来源]: [评论用户]", 则会生成如"2023.12.08-视频: 零泠丶"格式的标题\n可选:\n[评论日期]: 评论的 点赞/发布/收藏 日期, 如: 2023.12.08\n[评论来源]: 评论来自于B站的什么模块, 视频/专栏/动态 ...\n[网页标题]: 视频的标题 / 动态的标题 / 专栏的标题 ...\n[视频ID]: 评论对应的视频的ID (如果是视频页的评论)\n[视频标签]: 评论对应的 视频/专栏 的标签\n[评论用户]: 发布该评论的用户的名称, 自己发布的则显示\'自己\'\n[评论内容]: 评论的内容\n[回复用户]: 回复的用户的名称\n[楼主名称]: 楼中楼的评论对应的楼主的名称\n[楼主评论]: 楼主的评论内容\n',
        type: "列表设置",
        compType: "textarea",
        compH: "30px",
      },
      sendKeys: {
        title: "评论快捷键",
        value: "ctrl+enter",
        base: "ctrl+enter",
        valType: "string",
        key: keyBase + "sendKeys",
        txt: "设置发送消息时的快捷键, 每个键用 + 分隔, 特殊字符请用英文符号 (不支持shift+enter)\n例如: ctrl + enter 表示按下ctrl和回车键发送消息\n可使用单个按键, 支持 ctrl shift alt win/meta 字母 数字 等的组合键",
        type: "快捷键设置",
        compType: "textarea",
        compH: "30px",
      },
      addItemKeys: {
        title: "收藏组合键",
        value: "ctrl",
        base: "ctrl",
        valType: "string",
        key: keyBase + "addItemKeys",
        txt: "设置评论加入评论收藏的组合键, 每个键用 + 分隔, 按下组合键后'双击'评论的文本可将文本添加到评论收藏的列表中\n仅支持 ctrl shift alt win/meta 的组合键",
        type: "快捷键设置",
        compType: "textarea",
        compH: "30px",
      },
      isHiddenMenu: {
        value: !1,
        base: !1,
        valType: "boolean",
        key: keyBase + "isHiddenMenu",
        txt: "鼠标移出整个区域后, 是否自动收起菜单栏",
        type: "其他设置",
        compType: "radio",
        valueText: { true: "收起菜单", false: "不收起" },
      },
      isFormatOut: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "isFormatOut",
        txt: "是否格式化导出评论数据, 格式化后导出的文件便于阅读, 但少数时候格式化数据导入时可能会导入失败",
        type: "其他设置",
        compType: "radio",
        valueText: { true: "格式化导出", false: "标准导出" },
      },
      isDoubleOut: {
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "isDoubleOut",
        txt: "格式化导出时是否再进行一次标准导出, 以防格式化数据可能导入失败",
        type: "其他设置",
        compType: "radio",
        valueText: { true: "导出两份数据", false: "仅导出一份数据" },
      },
      lazyLoadListPages: {
        title: "列表延迟加载",
        value: [
          "首页",
          "视频",
          "搜索",
          "主页",
          "动态",
          "专栏",
          "番剧",
          "直播",
          "消息",
        ],
        base: [
          "首页",
          "视频",
          "搜索",
          "主页",
          "动态",
          "专栏",
          "番剧",
          "直播",
          "消息",
        ],
        valType: "array",
        key: keyBase + "lazyLoadListPages",
        txt: "设置哪些页面对评论列表进行延迟加载. 延迟加载时, 鼠标移入按钮区域后才对评论列表进行加载, 若评论内容过多则评论列表的菜单栏展开时会有一定卡顿(仅初次展开时有影响); 若不延迟加载, 则加载页面时就加载评论列表, 若评论内容过多则会影响页面初始加载的速度",
        type: "其他设置",
        compType: "checkbox",
        valueText: {
          首页: "首页",
          视频: "视频",
          搜索: "搜索",
          主页: "主页",
          动态: "动态",
          专栏: "专栏",
          番剧: "番剧",
          直播: "直播",
          消息: "消息",
        },
      },
      imageLazyLoad: {
        title: "图片懒加载",
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "imageLazyLoad",
        txt: "是否动态加载图片, 动态加载图片时只有可见区域内的图片才会被加载, 列表图片过多时能提高页面响应速度",
        type: "其他设置",
        compType: "radio",
        valueText: { true: "动态加载图片", false: "每次加载全部图片" },
        dis: 80,
      },
      imgType: {
        title: "图片下载格式",
        value: "auto",
        base: "auto",
        valType: "string",
        key: keyBase + "imgType",
        txt: "设置图片下载的格式, 设为auto时将自动识别图片格式\npng: 质量高 体积大\njpg: 质量较高 体积较小\nwebp: 质量较高 体积小",
        type: "其他设置",
        compType: "radio",
        valueText: { png: "png", jpg: "jpg", webp: "webp", auto: "auto" },
      },
      isSaveEmoji: {
        title: "评论表情",
        value: !0,
        base: !0,
        valType: "boolean",
        key: keyBase + "isSaveEmoji",
        descTt:
          "删除评论数据不会影响已经记录的表情, 因此可发送一系列表情的评论, 然后点赞保存到点赞列表中, 接着删除它, 之后就可以显示这些表情了",
        txt: "是否使用基础的小黄脸表情, 并记录新增评论中的表情, 所有列表中对应的表情文本将显示为表情图片(包括之前未显示为表情图片的表情文本), 修改评论内容时可用表情文本表示一个表情, 如: [doge]\n注: 评论数据和表情记录过多时可能在一定程度上影响插件运行的流畅度, 可定期导出数据后清空列表",
        type: "其他设置",
        compType: "radio",
        valueText: {
          true: "使用小黄脸表情并记录新表情",
          false: "仅显示评论内原有的表情",
        },
      },
      autoSave: {
        title: "自动备份",
        value: 10,
        base: 10,
        valType: "number",
        key: keyBase + "autoSave",
        txt: "设置自动备份列表数据的间隔天数, 0表示关闭自动备份",
        type: "其他设置",
        compType: "textarea",
        compH: "30px",
      },
    },
    cfg_keyBase = "ll_comment_history_",
    info = {
      version: "2.8.4",
      pageType: "",
      keyBase: cfg_keyBase,
      cssId: cfg_keyBase + "css",
      settingsArea: null,
      notRecordCommentPages: ["首页", "搜索", "直播"],
      personalHome: "https://space.bilibili.com/",
      doms: {},
      saveData: {
        zanList: {
          value: [],
          base: [],
          key: cfg_keyBase + "zanList",
          valType: "array",
        },
        list: {
          value: [],
          base: [],
          key: cfg_keyBase + "list",
          valType: "array",
        },
        sukiList: {
          value: [],
          base: [],
          key: cfg_keyBase + "sukiList",
          valType: "array",
        },
        emojiList: {
          value: emoji,
          base: emoji,
          key: cfg_keyBase + "emojiList",
          valType: "object",
        },
        autoSaveTime: {
          value: 0,
          base: new Date().getTime(),
          key: cfg_keyBase + "autoSaveTime",
          valType: "number",
        },
      },
      settings,
      history: {
        isListCreated: !1,
        searchZIndex: 12e3,
        editZIndex: 12e3,
        msgZIndex: 12e3,
        width: 30,
        height: 30,
        fontSize: 14,
        imgSuffix: "!web-comment-note.avif",
        lazyBaseImage:
          "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
        imgSize: { w: [110, 165], h: [110, 165] },
        txt: {
          searchTT:
            "搜索所有评论的内容, 若要按标题搜索请先输入'标题=', 按描述搜索输入'描述=', 按日期搜索输入'日期='. 若含有==>或===则表示替换, 如: 标题=A==>B, 表示将列表中所有标题中的A替换为B",
          saveImgText: "是否下载该列表中的所有图片?(包括表情)",
          editPhTT: "请输入标题",
          editPhDesc:
            "请输入描述\n鼠标对准标题时将显示描述信息\n鼠标对准序号时将显示日期",
          editPhValue: "请 输 入 内 容",
          listTT: "双击跳转到评论来源的页面",
          toBottomTT: "滚动到列表底部. 双击评论序号可回到顶部",
          settings: "打开插件设置界面",
        },
        replaceObj: {},
        zan_info: { saveName: cfg_keyBase + "zanList", callback: {} },
        data: { saveName: cfg_keyBase + "list", callback: {} },
        suki_info: { saveName: cfg_keyBase + "sukiList", callback: {} },
        color: {
          main: "#addeee",
          bd: "#dfedfe",
          font: "#4f4f4f",
          h_font: "#75beff",
          listBtnObj: {
            bg: "#fff",
            bd: "",
            hover: "#75b3ff",
            hover_bg: "#fff",
            hover_bd: "",
            click: "#75b3ff",
            click_bg: "#fff",
            click_bd: "",
          },
        },
        classList: { imageLazyLoad: "image-lazy", imageLoaded: "image-loaded" },
        doms: {
          box: { id: cfg_keyBase + "box", title: "" },
          btn: { class: "btn", title: "评论管理工具-2.8.4" },
          options: { class: "options", title: "" },
          zan_comment: {
            option: { text: "点赞评论", class: "zan-comment" },
            list: { class: "ll_comment_zanList" },
          },
          comment: {
            option: { text: "历史评论", class: "hist-comment" },
            list: { class: "ll_comment_list" },
          },
          suki_comment: {
            option: { text: "评论收藏", class: "suki-comment" },
            list: { class: "ll_comment_cukiList" },
          },
        },
      },
      customKeys: {
        isBtnClickEvent: !0,
        curDoms: {},
        curClassList: {},
        classList: {
          focus: "focus",
          noteIcon: "note-prefix",
          icon: "icon",
          smallEmoji: "emoji-small",
          largeEmoji: "emoji-large",
          commentTop: "top-icon",
          image: "image-exhibition",
          search: "search-word",
          视频: {
            replyItem: "reply-item",
            poster: "root-reply-container",
            focusDom: "reply-box-textarea",
            box: "reply-box",
            textarea: "reply-box-textarea",
            sendBtn: "reply-box-send",
            reply: "reply-content",
            subReply: "reply-content",
            subReplyP: "sub-reply-content",
            user: "user-name",
            subUser: "sub-user-name",
            replyUser: { class: "user", uid: "userId" },
            likeBtn: "reply-like",
            subLikeBtn: "sub-reply-like",
            liked: "liked",
            tagBox: { pre: "#", value: "v_tag" },
            tag: "tag-link",
          },
          番剧: {
            replyItem: "reply-item",
            poster: "root-reply-container",
            focusDom: "reply-box-textarea",
            box: "reply-box",
            textarea: "reply-box-textarea",
            sendBtn: "reply-box-send",
            reply: "reply-content",
            subReply: "reply-content",
            subReplyP: "sub-reply-content",
            user: "user-name",
            subUser: "sub-user-name",
            replyUser: { class: "user", uid: "userId" },
            likeBtn: "reply-like",
            subLikeBtn: "sub-reply-like",
            liked: "liked",
          },
          主页: {
            replyItem: "reply-item",
            poster: "root-reply-container",
            focusDom: "reply-box-textarea",
            box: "reply-box",
            textarea: "reply-box-textarea",
            sendBtn: "reply-box-send",
            reply: "reply-content",
            subReply: "reply-content",
            subReplyP: "sub-reply-content",
            user: "user-name",
            subUser: "sub-user-name",
            replyUser: { class: "user", uid: "userId" },
            likeBtn: "reply-like",
            subLikeBtn: "sub-reply-like",
            liked: "liked",
          },
          动态: {
            replyItem: "reply-item",
            poster: "root-reply-container",
            focusDom: "reply-box-textarea",
            box: "reply-box",
            textarea: "reply-box-textarea",
            sendBtn: "reply-box-send",
            reply: "reply-content",
            subReply: "reply-content",
            subReplyP: "sub-reply-content",
            user: "user-name",
            subUser: "sub-user-name",
            replyUser: { class: "user", uid: "userId" },
            likeBtn: "reply-like",
            subLikeBtn: "sub-reply-like",
            liked: "liked",
            cjDetailsId: "bp-app",
          },
          专栏: {
            replyItem: "reply-item",
            poster: "root-reply-container",
            focusDom: "reply-box-textarea",
            box: "reply-box",
            textarea: "reply-box-textarea",
            sendBtn: "reply-box-send",
            reply: "reply-content",
            subReply: "reply-content",
            subReplyP: "sub-reply-content",
            user: "user-name",
            subUser: "sub-user-name",
            replyUser: { class: "user", uid: "userId" },
            likeBtn: "reply-like",
            subLikeBtn: "sub-reply-like",
            liked: "liked",
            tagBox: { pre: ".", value: "article-tags" },
            tag: "tag-item",
          },
          消息: {
            focusDom: "",
            box: "reply-box",
            textarea: "reply-textarea",
            sendBtn: "send-button",
            reply: "real-reply",
            orginalReply: "orginal-reply",
            user: "name-field",
            replyUser: { class: "at", uid: "userId" },
            likeBtn: "action-button",
            likeText: "点赞",
            liked: "active",
          },
        },
      },
    },
    hist = info.history;
  function getValue_getValue({
    base,
    key,
    valType = "string",
    isReSet = !0,
    getValue = null,
    setValue = null,
    getVal = null,
    setVal = null,
  } = {}) {
    getValue && (getVal = getValue), setValue && (setVal = setValue);
    let val = getVal ? getVal(key) : localStorage.getItem(key);
    return (
      void 0 !== base &&
        null == val &&
        ((val = base),
        isReSet &&
          ("string" != typeof base && (base = JSON.stringify(base)),
          setVal ? setVal(key, base) : localStorage.setItem(key, base))),
      (valType = valType.toLowerCase()),
      "string" == typeof val
        ? "string" === valType
          ? val
          : "boolean" === valType || "number" === valType
          ? JSON.parse(val)
          : "object" === valType
          ? val
            ? JSON.parse(val)
            : {}
          : "array" === valType
          ? val
            ? JSON.parse(val)
            : []
          : val
        : val
    );
  }
  function getData() {
    const settings = info.settings;
    for (const valName in settings) {
      const setting = settings[valName];
      setting.value = getValue_getValue({
        base: setting.base,
        key: setting.key,
        valType: setting.valType,
        getVal: GM_getValue,
        setVal: GM_setValue,
      });
    }
    !(function getSaveData() {
      const saveData = info.saveData;
      for (const valName in saveData) {
        const setting = saveData[valName];
        setting.value = getValue_getValue({
          base: setting.base,
          key: setting.key,
          valType: setting.valType,
          getVal: GM_getValue,
          setVal: GM_setValue,
        });
      }
    })();
  }
  hist.zan_info.suki_info = hist.data.suki_info = hist.suki_info;
  const curInfo = info.history,
    doms = curInfo.doms,
    css_settings = info.settings,
    css_history = info.history;
  function setValue({
    value,
    base,
    key,
    verification = null,
    getValue = null,
    setValue = null,
    getVal = null,
    setVal = null,
  } = {}) {
    getValue && (getVal = getValue), setValue && (setVal = setValue);
    let newVal = value,
      val = getVal ? getVal(key) : localStorage.getItem(key);
    return (
      void 0 !== base &&
        null == val &&
        ((val = base),
        "string" != typeof base && (base = JSON.stringify(base)),
        setVal ? setVal(key, base) : localStorage.setItem(key, base)),
      null !== newVal &&
        ("function" != typeof verification ||
          ((newVal = verification(newVal, val)), null !== newVal)) &&
        newVal !== val &&
        ("string" != typeof newVal && (newVal = JSON.stringify(newVal)),
        setVal ? setVal(key, newVal) : localStorage.setItem(key, newVal),
        !0)
    );
  }
  function createEle({
    className = "",
    id = "",
    title = "",
    css,
    box = document.body,
    type = "div",
  } = {}) {
    const ele = document.createElement(type);
    return (
      id && (ele.id = id),
      className && (ele.className = className),
      title && (ele.title = title),
      css && (ele.style.cssText = css),
      box.appendChild(ele),
      ele
    );
  }
  const baseCfg = {
      isEditing: !1,
      isShowPage: !1,
      param: {
        id: "ll_edit_wrap",
        box: document.body,
        classBase: "ll_edit_",
        w: "450px",
        h: "",
        contentH: "450px",
        bg: "rgba(0, 0, 0, 0.12)",
        color: "#333",
        fontSize: "15px",
        fontFamily:
          "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif",
        zIndex: 11e3,
        resetTt: "重置所有设置为默认值",
        isShowMenu: !1,
        isScrollStyle: !0,
        isResetBtn: !0,
        showPage: void 0,
        page: [],
      },
    },
    cfg = {
      version: "v1.0.9",
      isEditing: baseCfg.isEditing,
      isShowPage: baseCfg.isShowPage,
      param: {},
      allData: {},
      baseData: {},
      oldData: {},
      controls: {},
      doms: { page: [] },
      editText: {},
      callback: { resetBefore: null, confirmBefore: null, finished: null },
    };
  const css = function css_getCss() {
    const param = cfg.param,
      cBase = (param.page, param.classBase),
      baseStart = `#${param.id} .${cBase}`,
      fSize = param.fontSize ? param.fontSize : "14px",
      css = `#${
        param.id
      } {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: ${
        param.zIndex || 11e3
      };\n  background: ${
        param.bg || "rgba(0, 0, 0, 0.12)"
      };\n  display: none;\n}\n${baseStart}box {\n  position: relative;\n  width: ${
        param.w || "450px"
      };\n  ${
        param.h ? "max-height:" + param.h : ""
      };\n  margin: auto;\n  color: ${
        param.color || "#333"
      };\n  background: #fff;\n  font-size: ${fSize};\n  line-height: normal;\n  font-family: ${
        param.fontFamily ||
        "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif"
      };\n  border: 3px solid #dfedfe;\n  border-radius: 10px;\n  box-sizing: border-box;\n  padding: 10px 8px 10px 15px;\n  overflow: hidden;\n  overflow-y: auto;\n}\n${baseStart}menu {\n  font-weight: bold;\n  font-size: ${
        parseInt(fSize) + 1
      }px;\n  margin-bottom: 10px;\n  display: flex;\n  flex-wrap: wrap;\n  gap: 8px;\n}\n${baseStart}menu-item {\n  border: 1px solid #dfedfe;\n  color: #9ecaff;\n  background: #eef6ff;\n  border-radius: 6px;\n  padding: 6px 10px;\n  cursor: pointer;\n}\n${baseStart}menu-item:hover {\n  color: #65aaff;\n  background: #dfedfe;\n  border: 1px solid #dfedfe;\n}\n${baseStart}menu-item.active {\n  color: #65aaff;\n  background: #dfedfe;\n  border: 1px solid #dfedfe;\n}\n${baseStart}page-box {\n  max-height: ${
        param.contentH || ""
      };\n  padding-right: 7px;\n  margin-bottom: 8px;\n  overflow: hidden;\n  overflow-y: auto;\n}\n${baseStart}page {\n  display: none;\n}\n${baseStart}page.curPage {\n  display: block;\n}\n${baseStart}comp {\n  margin-bottom: 8px;\n}\n${baseStart}comp:last-child {\n  margin-bottom: 2px;\n}\n${baseStart}comp-tt {\n  font-weight: bold;\n  line-height: 1.5;\n}\n${baseStart}comp-desc {\n  line-height: 1.5;\n}\n${baseStart}title {\n  font-weight: bold;\n  font-size: ${
        parseInt(fSize) + 5
      }px;\n}\n${baseStart}rd-arr {\n  line-height: 22px;\n}\n${baseStart}rd-arr label {\n  margin-right: 6px;\n  cursor: pointer;\n}\n${baseStart}rd-arr input {\n  vertical-align: -2px;\n  cursor: pointer;\n}\n${baseStart}rd-arr span {\n  color: #666;\n  margin-left: 2px;\n}\n#${
        param.id
      } textarea {\n  width: 100%;\n  max-width: 100%;\n  max-height: 300px;\n  border-radius: 6px;\n  line-height: normal;\n  padding: 5px 7px;\n  outline-color: #cee4ff;\n  border: 1px solid #aaa;\n  box-sizing: border-box;\n  font-size: ${
        parseInt(fSize) - 2
      }px;\n  font-family: PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif;\n  /* 保留空格 */\n  white-space: pre-wrap;\n  /* 允许词内换行 */\n  word-break: break-all;\n  letter-spacing: 1px;\n  overflow: hidden;\n  overflow-y: auto;\n}\n#${
        param.id
      } textarea::placeholder {\n  color: #bbb;\n}\n${baseStart}ta-desc {\n  margin-bottom: 3px;\n}\n${baseStart}btn-box {\n  display: flex;\n  justify-content: flex-end;\n}\n${baseStart}btn-box button {\n  font-size: 16px;\n  line-height: normal;\n  color: #65aaff;\n  background: #dfedfe;\n  outline: none;\n  border: none;\n  border-radius: 6px;\n  padding: 8px 16px;\n  box-sizing: border-box;\n  cursor: pointer;\n}\n${baseStart}btn-box .${cBase}reset-btn {\n  position: absolute;\n  left: 15px;\n  bottom: 10px;\n  color: #888;\n  background: #f4f4f4;\n  margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}reset-btn:hover {\n  color: #666;\n  background: #eee;\n}\n${baseStart}btn-box .${cBase}cancel-btn {\n  color: #888;\n  background: #f4f4f4;\n  margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}cancel-btn:hover {\n  color: #666;\n  background: #eee;\n}\n${baseStart}btn-box .${cBase}confirm-btn {\n  margin-right: 7px;\n}\n${baseStart}btn-box .${cBase}confirm-btn:hover {\n  background: #cee4ff;\n}\n`;
    return param.isScrollStyle
      ? css +
          "\n.ll-scroll-style-1::-webkit-scrollbar,\n.ll-scroll-style-1 ::-webkit-scrollbar {\n  width: 8px;\n}\n.ll-scroll-style-1-size-2::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-2::-webkit-scrollbar {\n  width: 10px;\n}\n.ll-scroll-style-1-size-3::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-3::-webkit-scrollbar {\n  width: 12px;\n}\n.ll-scroll-style-1::-webkit-scrollbar-thumb,\n.ll-scroll-style-1 ::-webkit-scrollbar-thumb {\n  border-radius: 10px;\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.05);\n  opacity: 0.2;\n  background: #daedff;\n}\n.ll-scroll-style-1::-webkit-scrollbar-track,\n.ll-scroll-style-1 ::-webkit-scrollbar-track {\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.08);\n  border-radius: 0;\n  background: #fff;\n  border-radius: 5px;\n}"
      : css;
  };
  const editArea_html = function getHTML() {
    function getCompHTML({ info, active = "", id }) {
      let title,
        desc,
        ctrlTt,
        type = info.type;
      if (
        ((type = {
          menuTitle: "mtt",
          title: "tt",
          desc: "ds",
          radio: "rd",
          checkbox: "cb",
          textarea: "ta",
          mtt: "mtt",
          tt: "tt",
          ds: "ds",
          rd: "rd",
          cb: "cb",
          ta: "ta",
        }[type]),
        (id = 0 === id ? "0" : id || ""),
        0 === info.content
          ? (info.content = "0")
          : (info.content = info.content || ""),
        !type)
      )
        return console.log("不存在的组件类型"), !1;
      switch (
        ("tt" !== type &&
          "ds" !== type &&
          "mtt" !== type &&
          ((title = info.title
            ? `<div class="${cBase}comp-tt ${cBase}${type}-tt" title="${
                info.tt || ""
              }">${info.title}</div>`
            : ""),
          (desc = info.desc
            ? `<div class="${cBase}comp-desc ${cBase}${type}-desc">${info.desc}</div>`
            : "")),
        type)
      ) {
        case "mtt":
          return info.content
            ? `<div class="${cBase}menu-item ${active || ""}" title="${
                info.tt || ""
              }">${info.content}</div>`
            : "";
        case "tt":
          return info.content
            ? `<div class="${cBase}title ${cBase}comp" title="${
                info.tt || ""
              }">${info.content}</div>`
            : "";
        case "ds":
          return info.content
            ? `<div class="${cBase}desc ${cBase}comp" title="${
                info.descTt || ""
              }">${info.content}</div>`
            : "";
        case "rd":
          const name = info.name || new Date().getTime();
          (ctrlTt = info.ctrlTt || ""),
            ctrlTt && (ctrlTt = `title="${ctrlTt}"`);
          let radio = `<div class="${cBase}rd ${cBase}rd-arr" ${ctrlTt}>`;
          if (void 0 === info.value && info.radioList[0]) {
            const obj = info.radioList[0];
            info.value = void 0 === obj.value ? obj.text : obj.value;
          }
          return (
            info.radioList.forEach((item) => {
              const value = void 0 === item.value ? item.text : item.value;
              let tt = item.tt || "";
              tt && (tt = `title="${tt}"`);
              let selected = "";
              info.value + "" == item.value + "" && (selected = "checked"),
                (radio += `<label ${tt}><input ${selected} type="radio" name="${name}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
            }),
            (radio += "</div>"),
            `<div class="${cBase}comp ${cBase}ctrl ${cBase}rd-box" data-type="${type}" data-cpid="${id}">${title}${desc}${radio}</div>`
          );
        case "cb":
          const name2 = info.name || new Date().getTime();
          if (
            ((ctrlTt = info.ctrlTt || ""),
            ctrlTt && (ctrlTt = `title="${ctrlTt}"`),
            void 0 === info.value && info.radioList[0])
          ) {
            const obj = info.radioList[0];
            info.value = void 0 === obj.value ? obj.text : obj.value;
          }
          let checkbox = `<div class="${cBase}cb ${cBase}rd-arr" ${ctrlTt}>`;
          return (
            info.radioList.forEach((item) => {
              const value = void 0 === item.value ? item.text : item.value;
              let tt = item.tt || "";
              tt && (tt = `title="${tt}"`);
              let selected = "";
              info.value.includes(value) && (selected = "checked"),
                (checkbox += `<label ${tt}><input ${selected} type="checkbox" name="${name2}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
            }),
            (checkbox += "</div>"),
            `<div class="${cBase}comp ${cBase}ctrl ${cBase}cb-box" data-type="${type}" data-cpid="${id}">${title}${desc}${checkbox}</div>`
          );
        case "ta":
          const style = `style="${
              info.width ? "width:" + info.width + ";" : ""
            }${info.height ? "height:" + info.height + ";" : ""}${
              info.fontSize ? "font-size:" + info.fontSize + ";" : ""
            }${info.fontFamily ? "font-family:" + info.fontFamily + ";" : ""}"`,
            textarea = `<textarea class="${cBase}ta" ${style} data-cpid="${id}" placeholder="${
              info.ph || ""
            }" title="${info.ctrlTt || "拖动右下角可调节宽高"}"></textarea>`;
          return `<div class="${cBase}comp ${cBase}ctrl ${cBase}ta-box" data-type="${type}"  data-cpid="${id}">${title}${desc}${textarea}</div>`;
      }
    }
    const param = cfg.param,
      page = param.page,
      cBase = param.classBase,
      isMenu = 1 !== page.length;
    let menu = `<div class="${cBase}menu">`,
      pageHTML = `<div class="${cBase}page-box ll-scroll-style-1 ll-scroll-style-1-size-2">`;
    page.forEach((curPage, index) => {
      let pgid = curPage.id || index;
      (pgid += ""), (cfg.allData[pgid] = {}), (cfg.baseData[pgid] = {});
      let pageFlag = "";
      if (
        (cfg.isShowPage ||
          ((void 0 === param.showPage || pgid === param.showPage + "") &&
            ((pageFlag = "curPage"), (cfg.isShowPage = !0))),
        (pageHTML += `<div class="${cBase}page ${pageFlag}" data-pgid="${pgid}">`),
        curPage.components)
      ) {
        let compIndex = 0;
        if (isMenu || param.isShowMenu) {
          let curMenu = curPage.components.find(
            (item) => "menuTitle" === item.type
          );
          curMenu || (curMenu = { type: "menuTitle", content: pgid }),
            (menu += getCompHTML({
              info: curMenu,
              active: pageFlag ? "active" : "",
            }));
        }
        curPage.components.forEach((item) => {
          const cpid = item.id || compIndex;
          "menuTitle" !== item.type &&
            (pageHTML += getCompHTML({ info: item, id: cpid })),
            "menuTitle" !== item.type &&
              "title" !== item.type &&
              "desc" !== item.type &&
              ((item.base = void 0 === item.base ? item.value : item.base),
              (cfg.allData[pgid][cpid] = item.value),
              (cfg.baseData[pgid][cpid] = item.base),
              compIndex++);
        });
      }
      pageHTML += "</div>";
    }),
      (pageHTML += "</div>"),
      isMenu || param.isShowMenu ? (menu += "</div>") : (menu = "");
    const resetBtn = param.isResetBtn
        ? `<button class="${cBase}reset-btn" title="${
            cfg.resetTt || "重置所有设置为默认值"
          }">重置</button>`
        : "",
      btnBox = `<div class="${cBase}btn-box">\n${resetBtn}\n<button class="${cBase}cancel-btn">取 消</button>\n<button class="${cBase}confirm-btn">确 认</button>\n</div>`;
    return `<div class="${cBase}box ll-scroll-style-1 ll-scroll-style-1-size-3" data-version="${cfg.version}">\n${menu}\n${pageHTML}\n${btnBox}\n</div>`;
  };
  let param = cfg.param;
  const baseParam = baseCfg.param,
    allData = cfg.allData,
    controls = cfg.controls,
    editArea_doms = cfg.doms;
  function createEditEle({
    id = baseParam.id,
    box = baseParam.box,
    classBase = baseParam.classBase,
    w = baseParam.w,
    h = baseParam.h,
    contentH = baseParam.contentH,
    bg = baseParam.bg,
    color = baseParam.color,
    fontSize = baseParam.fontSize,
    fontFamily = baseParam.fontFamily,
    zIndex = baseParam.zIndex,
    resetTt = baseParam.resetTt,
    isShowMenu = baseParam.isShowMenu,
    isScrollStyle = baseParam.isScrollStyle,
    isResetBtn = baseParam.isResetBtn,
    showPage = baseParam.showPage,
    page = [],
  } = {}) {
    (cfg.isEditing = baseCfg.isEditing),
      (cfg.isShowPage = baseCfg.isShowPage),
      (cfg.param = { ...baseParam }),
      (param = cfg.param),
      (param.id = id),
      (param.box = box),
      (param.classBase = classBase),
      (param.w = w),
      (param.h = h),
      (param.contentH = contentH),
      (param.bg = bg),
      (param.color = color),
      (param.fontSize = fontSize),
      (param.fontFamily = fontFamily),
      (param.zIndex = zIndex),
      (param.resetTt = resetTt),
      (param.isShowMenu = isShowMenu),
      (param.isScrollStyle = isScrollStyle),
      (param.isResetBtn = isResetBtn),
      (param.showPage = showPage),
      (param.page = page);
    const html = editArea_html();
    return (
      addCss(css(), box),
      (editArea_doms.wrap = createEle({ className: id, id })),
      (editArea_doms.wrap.innerHTML = html),
      (function getDoms() {
        const cBase = baseParam.classBase;
        (editArea_doms.box = editArea_doms.wrap.querySelector(`.${cBase}box`)),
          (editArea_doms.cancel = editArea_doms.box.querySelector(
            `.${cBase}cancel-btn`
          )),
          (editArea_doms.confirm = editArea_doms.box.querySelector(
            `.${cBase}confirm-btn`
          ));
        const isMenu = 1 !== param.page.length;
        (isMenu || param.isShowMenu) &&
          ((editArea_doms.menu = editArea_doms.box.querySelector(
            `.${cBase}menu`
          )),
          (editArea_doms.menus = [].slice.call(
            editArea_doms.menu.querySelectorAll(`.${cBase}menu-item`)
          )));
        const pages = [].slice.call(
          editArea_doms.box.querySelectorAll(`.${cBase}page`)
        );
        (editArea_doms.page = []),
          param.isResetBtn &&
            (editArea_doms.reset = editArea_doms.box.querySelector(
              `.${cBase}reset-btn`
            ));
        pages.forEach((curPage, index) => {
          cfg.isShowPage ||
            (curPage.classList.add("curPage"),
            (isMenu || param.isShowMenu) &&
              editArea_doms.menus[0].classList.add("active"),
            (cfg.isShowPage = !0));
          const page = {},
            pgid = curPage.dataset.pgid;
          (page.pgid = curPage.pgid = pgid),
            (page.controls = [].slice.call(
              curPage.querySelectorAll(`.${cBase}ctrl`)
            )),
            (page.ele = curPage),
            editArea_doms.page.push(page),
            (isMenu || param.isShowMenu) &&
              (editArea_doms.menus[index].settingsPage = curPage);
          const ctrls = {};
          (controls[pgid] = ctrls),
            page.controls.forEach((item, i) => {
              const cpid = item.dataset.cpid,
                cType = item.dataset.type;
              let dom;
              (item.cpid = cpid),
                "rd" === cType || "cb" === cType
                  ? ((dom = [].slice.call(item.querySelectorAll("input"))),
                    (dom.compType = cType))
                  : "ta" === cType &&
                    ((dom = item.querySelector("textarea")),
                    (dom.compType = cType),
                    (dom.value = allData[pgid][cpid])),
                (ctrls[cpid] = dom);
            });
        });
      })(),
      (function bindEvents() {
        function menuHandle(e) {
          const dom = e.target,
            cBase = baseParam.classBase;
          if (dom.classList.contains(`${cBase}menu-item`)) {
            const old = editArea_doms.menu.querySelector(".active");
            old.classList.remove("active"),
              old.settingsPage.classList.remove("curPage"),
              dom.classList.add("active"),
              dom.settingsPage.classList.add("curPage");
          }
        }
        function cancelEdit(e) {
          const cBase = baseParam.classBase;
          (e.target.className !== `${cBase}wrap` &&
            e.target.className !== `${cBase}cancel-btn`) ||
            (showEditArea(!1), setCompValue(cfg.oldData));
        }
        function confirmEdit() {
          const callback = cfg.callback,
            data = getAllData();
          if (callback.confirmBefore) {
            let result;
            const func = callback.confirmBefore;
            if (
              (Array.isArray(func)
                ? func.curFn
                  ? ((result = func[curFn](data)), (func.curFn = null))
                  : func.forEach((fn) => {
                      result = fn(data);
                    })
                : (result = func(data)),
              !1 === result)
            )
              return;
          }
          if ((showEditArea(!1), callback.finished)) {
            const func = callback.finished;
            Array.isArray(func)
              ? func.curFn
                ? (func[curFn](data), (func.curFn = null))
                : func.forEach((fn) => {
                    fn(data);
                  })
              : func(data);
          }
        }
        function resetEdit() {
          const callback = cfg.callback,
            data = getAllData();
          if (callback.resetBefore) {
            let result;
            const func = callback.resetBefore;
            if (
              (Array.isArray(func)
                ? func.curFn
                  ? ((result = func[curFn](data)), (func.curFn = null))
                  : func.forEach((fn) => {
                      result = fn(data);
                    })
                : (result = func(data)),
              !1 === result)
            )
              return;
          }
          !(function resetEditData() {
            param.isResetBtn && setCompValue(cfg.baseData);
          })();
        }
        editArea_doms.menu &&
          editArea_doms.menu.addEventListener("click", menuHandle),
          editArea_doms.wrap.addEventListener("click", cancelEdit),
          editArea_doms.cancel.addEventListener("click", cancelEdit),
          editArea_doms.confirm.addEventListener("click", confirmEdit),
          editArea_doms.reset &&
            editArea_doms.reset.addEventListener("click", resetEdit);
      })(),
      cfg
    );
  }
  function getAllData() {
    function getCompItem(pgid, cpid) {
      if (!controls[pgid]) return;
      const ctrl = controls[pgid][cpid];
      if (ctrl) {
        if (!Array.isArray(ctrl)) return ctrl.value;
        if ("rd" === ctrl.compType) {
          return ctrl.find((item) => item.checked).dataset.val;
        }
        if ("cb" === ctrl.compType) {
          return ctrl
            .filter((item) => item.checked)
            .map((item) => item.dataset.val);
        }
      }
    }
    const data = {};
    if (0 === arguments.length) {
      for (const key in controls) {
        const page = controls[key];
        data[key] = {};
        for (const key2 in page) data[key][key2] = getCompItem(key, key2);
      }
      return data;
    }
    if (1 === arguments.length) {
      const ctrls = arguments[0];
      for (const pgid in ctrls) {
        data[pgid] = {};
        controls[pgid].forEach((cpid) => {
          data[pgid][cpid] = getCompItem(pgid, cpid);
        });
      }
      return allData;
    }
    return getCompItem(arguments[0], arguments[1]);
  }
  function setCompValue() {
    function setCompItem(pgid, cpid, value) {
      if (!controls[pgid]) return;
      const ctrl = controls[pgid][cpid];
      if (ctrl)
        if (Array.isArray(ctrl)) {
          if ("rd" === ctrl.compType) {
            const selected = ctrl.find((item) => item.checked);
            selected && (selected.checked = !1);
            const select = ctrl.find((item) => item.dataset.val === value + "");
            select && (select.checked = !0);
          } else if ("cb" === ctrl.compType) {
            if (
              (ctrl
                .filter((item) => item.checked)
                .forEach((item) => {
                  item.checked = !1;
                }),
              Array.isArray(value))
            )
              value.forEach((val) => {
                const select = ctrl.find(
                  (item) => item.dataset.val === val + ""
                );
                select && (select.checked = !0);
              });
            else {
              const select = ctrl.find(
                (item) => item.dataset.val === value + ""
              );
              select && (select.checked = !0);
            }
          }
        } else ctrl.value = value;
    }
    if (1 === arguments.length) {
      const data = arguments[0];
      for (const key in data) {
        const pageData = data[key];
        for (const key2 in pageData) {
          setCompItem(key, key2, pageData[key2]);
        }
      }
    } else {
      setCompItem(arguments[0], arguments[1], arguments[2]);
    }
  }
  function showEditArea(isShow = !0, callback = null) {
    if (
      isShow &&
      ((cfg.oldData = getAllData()), "function" == typeof callback)
    ) {
      if (!1 === callback(cfg.oldData)) return;
    }
    (cfg.isEditing = isShow),
      (editArea_doms.wrap.style.display = isShow ? "block" : "none"),
      isShow &&
        !editArea_doms.box.style.top &&
        (editArea_doms.box.style.top =
          window.innerHeight / 2 - editArea_doms.box.clientHeight / 2 + "px"),
      callback && (cfg.callback = callback);
  }
  function toPageObj(settings, id = "") {
    const pageArr = [],
      menuList = [];
    for (let key in settings) {
      const item = settings[key];
      menuList.includes(item.type) || menuList.push(item.type);
    }
    return (
      menuList.forEach((menuTt) => {
        const components = [],
          page = { id: menuTt, components },
          arr = [];
        for (let key in settings) {
          const item = settings[key];
          item.type === menuTt && arr.push(item);
        }
        arr.forEach((item) => {
          let desc = item.txt || "";
          desc && (desc = desc.replaceAll("\n", "<br>").trim());
          let base = item.base;
          Array.isArray(base) && (base = base.join(", "));
          const comp = {
            id: item.key,
            type: item.compType,
            tt: item.tt || "",
            title: item.title || "",
            desc,
            descTt: item.descTt || "",
            name: item.key,
            value: item.value,
            base: item.base,
          };
          if ("textarea" === comp.type)
            (comp.ph = base),
              (comp.width = item.compW),
              (comp.height = item.compH),
              (comp.ctrlTt = "默认: " + base);
          else if ("radio" === comp.type || "checkbox" === comp.type) {
            let str = "默认: ";
            if ("checkbox" === comp.type) {
              let arr = item.base;
              Array.isArray(arr) || (arr = arr.split(/,|,/)),
                arr.forEach((val, i) => {
                  0 !== i && (str += ", "), (val = val.trim());
                  let valTxt = item.valueText[val];
                  void 0 === valTxt && (valTxt = val), (str += valTxt);
                });
            } else {
              let val = item.valueText[item.base];
              void 0 === val && (val = item.base), (str += val);
            }
            comp.ctrlTt = str;
          }
          if (item.valueText) {
            comp.radioList = [];
            for (let key in item.valueText) {
              const rd = { text: item.valueText[key], value: key };
              comp.radioList.push(rd);
            }
          }
          components.push(comp);
        }),
          pageArr.push(page);
      }),
      pageArr
    );
  }
  function getEditInfo() {
    return {
      w: "500px",
      contentH: "450px",
      resetTt: "重置所有设置项为默认值",
      page: toPageObj(info.settings),
    };
  }
  function showSettings() {
    const settings = info.settings,
      oldSettings = JSON.stringify(settings);
    getData();
    const curSettings = JSON.stringify(settings);
    info.settingsArea
      ? oldSettings !== curSettings &&
        (info.settingsArea.doms.wrap.remove(),
        (info.settingsArea = createEditEle(getEditInfo())))
      : (info.settingsArea = createEditEle(getEditInfo())),
      (function setShowPage(pageId) {
        const old = editArea_doms.menu.querySelector(".active");
        if (!old) return void console.log("不存在菜单栏, 无法切换菜单页");
        let page, menu;
        if (
          (old.classList.remove("active"),
          old.settingsPage.classList.remove("curPage"),
          "number" == typeof pageId)
        ) {
          if (((menu = editArea_doms.menus[pageId]), !menu))
            return void console.log(`不存在第${pageId + 1}项菜单页`);
        } else if (
          ((menu = editArea_doms.menus.find(
            (item) => item.innerHTML === pageId
          )),
          !menu)
        )
          return void console.log(`不存在'${pageId}'的菜单页`);
        (page = menu.settingsPage),
          menu.classList.add("active"),
          page.classList.add("curPage");
      })(0);
    showEditArea(!0, {
      resetBefore: () => confirm("是否重置所有设置项为默认值?"),
      confirmBefore: () => {},
      finished: (data) => {
        console.log(data);
        if (
          (function isValueChange() {
            const curData = getAllData();
            return JSON.stringify(curData) !== JSON.stringify(cfg.oldData);
          })()
        ) {
          for (const pageName in data) {
            const page = data[pageName];
            for (const key in page) {
              const value = page[key],
                flag = key.replace(info.keyBase, ""),
                item = settings[flag];
              let verifyFn;
              switch (key) {
                case settings.position.key:
                  verifyFn = (newVal) => newVal || settings.position.base;
                  break;
                case settings.hiddenBtnTime.key:
                  verifyFn = (newVal) =>
                    (newVal = +newVal) || 0 === newVal
                      ? newVal
                      : settings.hiddenBtnTime.base;
                  break;
                case settings.closeListTime.key:
                  verifyFn = (newVal) =>
                    (newVal = +newVal) || 0 === newVal
                      ? newVal
                      : settings.closeListTime.base;
                  break;
                case settings.listSize.key:
                  verifyFn = (newVal) => {
                    const arr = newVal.split(/,|,|x|X/);
                    let f;
                    return 1 === arr.length
                      ? ((f = +arr[0].trim() > 150),
                        f ? newVal : settings.listSize.base)
                      : ((f = +arr[0].trim() >= 150 && +arr[1].trim() >= 100),
                        f ? newVal : settings.listSize.base);
                  };
                  break;
                case settings.liMaxHeight.key:
                  verifyFn = (newVal) =>
                    0 === (newVal = +newVal) || newVal >= 50
                      ? newVal
                      : settings.liMaxHeight.base;
                  break;
                case settings.scale.key:
                  verifyFn = (newVal) =>
                    +newVal ? newVal : settings.scale.base;
                  break;
                case settings.zanListMaxLen.key:
                  verifyFn = (newVal) =>
                    0 === (newVal = +newVal) || newVal >= 10
                      ? newVal
                      : settings.zanListMaxLen.base;
                  break;
                case settings.listMaxLen.key:
                  verifyFn = (newVal) =>
                    0 === (newVal = +newVal) || newVal >= 10
                      ? newVal
                      : settings.listMaxLen.base;
                  break;
                case settings.titleFormat.key:
                  verifyFn = (newVal) => newVal || settings.titleFormat.base;
                  break;
                case settings.sendKeys.key:
                case settings.addItemKeys.key:
                  verifyFn = (newVal) =>
                    newVal.replaceAll(" ", "").toLowerCase();
                  break;
                case settings.autoSave.key:
                  verifyFn = (newVal) =>
                    (newVal = +newVal) && newVal > 0
                      ? newVal
                      : settings.autoSave.base;
              }
              if (!item)
                return void console.log("设置的数据对应的对象获取失败");
              setValue({
                value,
                base: item.base,
                key,
                verification: verifyFn,
                getValue: GM_getValue,
                setValue: GM_setValue,
              });
            }
          }
          history.go(0);
        }
      },
    });
  }
  function imageLazyLoad({
    box,
    boxRect,
    imgDom,
    imageClass = "image-lazy",
    loadedClass = "image-loaded",
    dis = 50,
  } = {}) {
    if (!imgDom) return;
    if (!imgDom.classList.contains(imageClass)) return;
    boxRect || (boxRect = box.getBoundingClientRect());
    const boxH = boxRect.height;
    if (0 === boxH) return;
    const imgRect = imgDom.getBoundingClientRect(),
      h = imgRect.height,
      top = imgRect.top - boxRect.top;
    if (top + h > 0 - dis && top < boxH + dis) {
      const dataset = imgDom.dataset;
      return (
        (imgDom.src = dataset.src),
        imgDom.classList.add(loadedClass),
        imgDom.classList.remove(imageClass),
        !0
      );
    }
  }
  const classList = info.history.classList;
  function loadImage(img) {
    img.classList.contains(classList.imageLazyLoad) &&
      ((img.src = img.dataset.src),
      img.classList.remove(classList.imageLazyLoad),
      img.classList.add(classList.imageLoaded));
  }
  function listImgLazyLoad(curList, loadItemNum = 0) {
    if (0 === loadItemNum && !curList.classList.contains("opened")) return;
    const lazyLoadClass = classList.imageLazyLoad;
    if (loadItemNum > 0) {
      const listEle = curList.children[2];
      listEle.children.length < loadItemNum &&
        (loadItemNum = listEle.children.length);
      const len = listEle.children.length;
      for (let i = 0; i < loadItemNum && !(i + 1 > len); i++) {
        const item = listEle.children[i];
        if ("none" === item.style.display) {
          loadItemNum++;
          continue;
        }
        let imgArr = item.querySelectorAll(`img.${lazyLoadClass}`);
        (imgArr = [].slice.call(imgArr)),
          imgArr.forEach((img) => {
            loadImage(img);
          });
      }
    } else {
      let isShowed = !1;
      const imgArr = curList.querySelectorAll(`img.${lazyLoadClass}`),
        len = imgArr.length,
        boxRect = curList.getBoundingClientRect();
      for (let i = 0; i < len; i++) {
        const result = imageLazyLoad({
          box: curList,
          boxRect,
          imgDom: imgArr[i],
          imageClass: lazyLoadClass,
          loadedClass: classList.imageLoaded,
          dis: settings.imageLazyLoad.dis,
        });
        if (((isShowed = isShowed && result), isShowed && !result)) break;
      }
    }
  }
  function getWhStyle(src, wh = [], aspectRatio = 1) {
    aspectRatio = aspectRatio || 1;
    const rangeWh = info.history.imgSize;
    if (((wh[0] && wh[1]) || (wh = []), 0 === wh.length)) {
      wh = [];
      let srcSuffix = src.split("@")[1];
      if (srcSuffix) {
        let isH = !1;
        srcSuffix.includes("h_") &&
          ((isH = !0), (srcSuffix = srcSuffix.split("h_")[0]));
        const result = srcSuffix.split("w_");
        srcSuffix.includes("w_")
          ? isH
            ? ((wh[0] = result[0]), (wh[1] = result[1]))
            : (wh[0] = result[0])
          : isH && (wh[1] = srcSuffix);
      }
      wh[0] && !wh[1] && (wh[1] = Math.floor(wh[0] / aspectRatio)),
        !wh[0] && wh[1] && (wh[0] = Math.floor(wh[1] * aspectRatio));
    }
    let finalwh = (function adjustSize(wh) {
      let w = wh[0],
        h = wh[1],
        isAdjustW = !1,
        isAdjustH = !1;
      return (
        w > rangeWh.w[1]
          ? ((w = rangeWh.w[1]), (isAdjustH = !0))
          : w < rangeWh.w[0] && ((w = rangeWh.w[0]), (isAdjustH = !0)),
        h > rangeWh.h[1]
          ? ((h = rangeWh.h[1]), (isAdjustW = !0))
          : h < rangeWh.h[0] && ((h = rangeWh.h[0]), (isAdjustW = !0)),
        isAdjustH &&
          ((h = Math.floor(w / aspectRatio)),
          h < rangeWh.h[0] && (h = rangeWh.h[0])),
        isAdjustW &&
          ((w = Math.floor(h * aspectRatio)),
          w < rangeWh.w[0] && (w = rangeWh.w[0])),
        [w, h]
      );
    })(wh);
    return `width:${finalwh[0]}px;height:${finalwh[1]}px;`;
  }
  function minImgToBigImg(src) {
    return src.split("@")[0] + "@" + info.history.imgSuffix;
  }
  function formatDate({
    timestamp,
    isYear = !0,
    isExact = !1,
    delimiter = ".",
    midDelimiter = " ",
    delimiter2 = ":",
  } = {}) {
    if (!timestamp) return -1;
    const date = new Date(timestamp),
      year = isYear ? date.getFullYear() : "",
      month = (date.getMonth() + 1).toString().padStart(2, "0"),
      day = date.getDate().toString().padStart(2, "0");
    let leftTime;
    leftTime =
      3 === delimiter.length
        ? `${isYear ? year + delimiter[0] : ""}${month}${delimiter[1]}${day}${
            delimiter[2]
          }`
        : `${isYear ? year + delimiter : ""}${month}${delimiter}${day}`;
    let rigthTime = "";
    if (isExact) {
      const hour = date.getHours().toString().padStart(2, "0"),
        minute = date.getMinutes().toString().padStart(2, "0"),
        second = date.getSeconds().toString().padStart(2, "0");
      rigthTime =
        3 === delimiter2.length
          ? `${midDelimiter}${hour}${delimiter2[0]}${minute}${delimiter2[1]}${second}${delimiter2[2]}`
          : `${midDelimiter}${hour}${delimiter2}${minute}${delimiter2}${second}`;
    }
    return leftTime + rigthTime;
  }
  function domToText(ele) {
    const dom = document.createElement("div");
    document.body.appendChild(dom), (dom.innerHTML = ele.innerHTML);
    const arr = [].slice.call(dom.children);
    for (let i = 0; i < arr.length; i++) {
      const node = arr[i];
      if ("img" === (node.nodeName ? node.nodeName.toLowerCase() : "")) {
        const newDom = document.createTextNode(node.alt || "");
        dom.replaceChild(newDom, node);
      }
    }
    const str = dom.innerText;
    return dom.remove(), str;
  }
  let searchBox,
    searchEndTimerId,
    msgBox,
    msgDom,
    msgId,
    useOne,
    msgZIndex,
    msgTimerId,
    msgEndTimerId,
    searchCallback = {};
  function createSearch({
    id = "history-search-box",
    box = document.body,
    title = "以'标题='开头表示按标题搜索, '内容='表示按内容搜索, '描述='表示按描述搜索, '日期='表示按日期搜索. 若含有==>或===则表示替换, 如: 标题=A==>B, 表示将列表中所有标题中的A替换为B",
    width = 200,
    height = 30,
    color = "#333",
    bg = "#fff",
    fontSize = 13,
    bd = "1px solid #aaa",
    hover_bdColor = "#cee4ff",
    pd = "0 8px",
    radius = 5,
    transition = 0.5,
    btnText = "搜索",
    btn_class = "",
    btn_fontSize = 13,
    btn_color = "#65aaff",
    btn_bg = "#dfedfe",
    btn_bd = "1px solid #dfedfe",
    btn_pd = "0 10px",
    btn_radius = 6,
    btn_hover = "#65aaff",
    btn_hover_bg = "#cee4ff",
    btn_hover_bd = "1px solid #dfedfe",
    zIndex = 901,
    placeholder = "请输入搜索的内容",
    isBtn = !0,
    isAutoSearch = !0,
    interval = 500,
    callback = null,
  } = {}) {
    const ele = document.createElement("div");
    (ele.id = id),
      (ele.isAutoSearch = isAutoSearch),
      (ele.interval = interval),
      (ele.transition = transition),
      (ele.style.cssText = `display: flex;\nopacity: 0;\nposition: absolute;\nleft: -2000px;\ntop: 0;\nz-index: ${zIndex};\ntransition: opacity ${transition}s`);
    const text_css = `width: ${width}px;\nheight: ${height}px;\nline-height: ${height}px;\ncolor: ${color};\nborder: ${bd};\npadding: ${pd};\nborder-radius: ${radius}px;\noutline: ${hover_bdColor};\nbox-sizing: border-box;`;
    ele.innerHTML = `<input class="search-text ll-scroll-style-1" style="${text_css}"></input>${
      isBtn ? "<div class='search-btn'></div>" : ""
    }`;
    const textEle = ele.querySelector(".search-text");
    (ele.title = title),
      (ele.textEle = textEle),
      (textEle.placeholder = placeholder),
      (textEle.style.fontSize = fontSize + "px"),
      (textEle.style.background = bg),
      (textEle.style.fontFamily = "math");
    const btnEle = ele.querySelector(".search-btn");
    return (
      btnEle &&
        ((btnEle.style.cssText = `height: ${height}px;\nline-height: ${height}px;\nfont-size: ${btn_fontSize}px;\ncolor: ${btn_color};\nbackground: ${btn_bg};\nborder: ${btn_bd};\npadding: ${btn_pd};\nborder-radius: ${btn_radius}px;\nbox-sizing: border-box;\nwhite-space: nowrap;\nfont-family: math;\ncursor:pointer;`),
        (btnEle.className += " " + btn_class),
        (btnEle.innerHTML = btnText),
        (btnEle.style.fontSize = btn_fontSize),
        (btnEle.style.color = btn_color),
        (btnEle.style.fontSize = fontSize + "px"),
        (ele.btnEle = btnEle),
        btnEle.addEventListener("mouseenter", () => {
          (btnEle.style.color = btn_hover),
            (btnEle.style.background = btn_hover_bg),
            (btnEle.style.border = btn_hover_bd);
        }),
        btnEle.addEventListener("mouseleave", () => {
          (btnEle.style.color = btn_color),
            (btnEle.style.background = btn_bg),
            (btnEle.style.border = btn_bd);
        })),
      (searchBox = ele),
      box.appendChild(ele),
      callback && (searchCallback = callback),
      (ele.search_info = {}),
      (function bindSearchEvents(ele) {
        const inputEle = ele.textEle,
          searchBtn = ele.btnEle,
          search_info = ele.search_info,
          replacedEvent = new CustomEvent("replaced", {
            detail: { search_info },
          });
        function replaceAllItem() {
          const sType = search_info.searchType;
          if ("日期" === sType) return;
          const list_info = ele.listEle.list_info,
            oldVal = search_info.oldVal,
            newVal = search_info.newVal;
          if (
            confirm(
              `是否将所有列表项的${sType}中的'${oldVal}'替换为'${newVal}'`
            )
          ) {
            const dataList = list_info.dataList;
            dataList.forEach((item, i) => {
              "标题" === sType
                ? (dataList[i].title = item.title.replaceAll(oldVal, newVal))
                : "描述" === sType
                ? (dataList[i].desc = item.desc.replaceAll(oldVal, newVal))
                : "内容" === sType &&
                  (dataList[i].value = item.value.replaceAll(oldVal, newVal));
            }),
              ele.dispatchEvent(replacedEvent);
          }
        }
        let timerId;
        searchBtn.addEventListener("click", () => {
          if (searchCallback.searchBefore) {
            if (!1 === searchCallback.searchBefore(inputEle.value)) return;
          }
          searchEle(),
            search_info.isReplace && replaceAllItem(),
            searchCallback.searchAfter &&
              searchCallback.searchAfter(inputEle.value);
        }),
          inputEle.addEventListener("keydown", (e) => {
            if (
              (13 === e.keyCode || "enter" === e.key.toLowerCase()) &&
              0 != +ele.style.opacity
            ) {
              if (searchCallback.searchBefore) {
                if (!1 === searchCallback.searchBefore(inputEle.value)) return;
              }
              searchEle(),
                search_info.isReplace && replaceAllItem(),
                searchCallback.searchAfter &&
                  searchCallback.searchAfter(inputEle.value);
            }
          }),
          inputEle.addEventListener("input", () => {
            ele.isAutoSearch &&
              (clearTimeout(timerId),
              (timerId = setTimeout(() => {
                if (searchCallback.searchBefore) {
                  if (!1 === searchCallback.searchBefore(inputEle.value))
                    return;
                }
                searchEle(),
                  searchCallback.searchAfter &&
                    searchCallback.searchAfter(inputEle.value);
              }, ele.interval)));
          });
      })(ele),
      ele
    );
  }
  function showSearchBox(isShow = !0, originEle = null, position = "relative") {
    const ele = searchBox;
    if (isShow) {
      let left, top, scrollTop;
      if ((ele.textEle.focus(), clearTimeout(searchEndTimerId), originEle)) {
        const rect = originEle.getBoundingClientRect();
        (left = rect.left),
          (top = rect.top),
          "fixed" === position ||
            ("relative" === position &&
              (scrollTop = document.documentElement.scrollTop));
      }
      const h = parseInt(ele.textEle.style.height);
      left && top
        ? ((ele.style.left = left + "px"),
          (ele.style.top = top + scrollTop - h - 12 + "px"))
        : ((ele.style.left = ""),
          (ele.style.right = "12px"),
          (ele.style.top = "12px")),
        (ele.style.opacity = 1);
    } else
      (ele.style.opacity = 0),
        clearTimeout(searchEndTimerId),
        (searchEndTimerId = setTimeout(() => {
          ele.style.left = "-2000px";
        }, 1e3 * ele.transition)),
        hiddenEle(ele.listEle, "");
  }
  function hiddenEle(listEle, text, searchType = "标题") {
    if (!listEle) return;
    "时间" === searchType && (searchType = "日期");
    const info = searchBox.search_info;
    info.searchType = searchType;
    const replaceArr = text.split(/==>|===/);
    replaceArr.length > 1
      ? ((info.oldVal = replaceArr[0]),
        (info.newVal = replaceArr[1]),
        (info.isReplace = !0),
        (text = info.oldVal) &&
          console.log(`搜索: 将'${info.oldVal}'替换为'${info.newVal}'`))
      : text &&
        ((info.isReplace = !1), console.log("搜索" + searchType + ": " + text));
    const liArr = listEle.querySelectorAll(".item-box"),
      len = liArr.length;
    for (let i = 0; i < len; i++) {
      const item = liArr[i];
      if (text) {
        const ttDom = item.querySelector(".item-tt"),
          textDom = item.querySelector(".hItem");
        ("标题" === searchType && domToText(ttDom).includes(text)) ||
        ("描述" === searchType && ttDom.title.includes(text)) ||
        ("内容" === searchType && domToText(textDom).includes(text)) ||
        ("日期" === searchType &&
          item.querySelector(".item-control").title.includes(text))
          ? (item.style.display = "block")
          : (item.style.display = "none");
      } else item.style.display = "block";
    }
  }
  function searchEle() {
    const textEle = searchBox.textEle,
      listEle = searchBox.listEle;
    if (!listEle) return;
    let text = textEle.value,
      searchType = text.slice(0, 3);
    ["标题=", "描述=", "内容=", "日期=", "时间="].includes(searchType)
      ? ((searchType = searchType.slice(0, 2)),
        (text = text.slice(3, text.length)))
      : (searchType = textEle.searchType ? textEle.searchType : "标题"),
      hiddenEle(listEle, text, searchType);
  }
  function message({
    ele,
    title = "",
    content = "",
    msg = "",
    isTitle = !0,
    maxWidth,
    color,
    fontSize,
    tt_color,
    tt_fontSize,
    bg,
    bd,
    pd,
    radius,
    time = "auto",
    disTime = 0,
    postion = "right-top",
    fn,
  } = {}) {
    useOne && (msgDom = null),
      ele ||
        (ele = msgDom) ||
        (msgId &&
          !useOne &&
          (ele = msgDom = document.querySelector("#" + msgId)),
        ele ||
          (ele = msgDom =
            (function createMsg({
              id = "ll-autoCloseMsg",
              box = document.body,
              type = "right",
              isUseOne = !0,
              maxWidth = 224,
              color = "#666",
              fontSize = 14,
              tt_color = "#333",
              tt_fontSize = 16,
              bg = "#fff",
              bd = "2px solid #dfedfe",
              pd = "7px 12px",
              radius = 7,
              zIndex = 1100,
              transition = 0.8,
              isTitle = !0,
            } = {}) {
              const ele = document.createElement("div");
              (ele.title = "点击关闭该弹窗"),
                (ele.id = id),
                (ele.className = id),
                (msgId = id),
                (ele.style.cssText = `max-width:${maxWidth}px;\nline-height:1.5;\nbackground:${bg};\nmargin-bottom:10px;\nborder:${bd};\npadding:${pd};\nbox-sizing:border-box;\nborder-radius:${radius}px;\nword-break:break-all;\ncursor:pointer;\nopacity:0;\ntransition:opacity ${transition}s;\nletter-spacing:1px;`),
                (ele.innerHTML =
                  '<div class="title" style="margin-bottom:5px;font-weight:bold;"></div><div class="msg"></div>'),
                (ele.transition = transition);
              const ttEle = ele.querySelector(".title");
              isTitle
                ? ((ele.ttEle = ttEle),
                  (ttEle.style.color = tt_color),
                  (ttEle.style.fontSize = tt_fontSize + "px"))
                : (ttEle.style.display = "none");
              const msgEle = ele.querySelector(".msg");
              return (
                (ele.msgEle = msgEle),
                (msgEle.style.color = color),
                (msgEle.style.fontSize = fontSize + "px"),
                (useOne = isUseOne),
                (ele.isUseOne = isUseOne),
                (msgDom = ele),
                msgBox ||
                  ((msgBox = document.createElement("div")),
                  (msgBox.id = id + "-box"),
                  (msgBox.style.cssText = `\ndisplay:flex;\nflex-direction:column;\nalign-items:${
                    "right" === type ? "flex-end" : "flex-start"
                  };\nposition:fixed;\nleft:-2000px;\ntop:0;\nz-index:${
                    isUseOne ? msgZIndex : zIndex
                  };`),
                  box.appendChild(msgBox)),
                msgBox.appendChild(ele),
                ele.addEventListener("click", () => {
                  ele.remove();
                }),
                ele
              );
            })({ type: postion.split(/-|_/)[0] }))),
      (msg = content || msg);
    const msgEle = ele.msgEle;
    (msgEle.innerText = msg),
      maxWidth && (ele.style.maxWidth = maxWidth + "px"),
      bd && (ele.style.border = bd),
      pd && (ele.style.padding = pd),
      bg && (ele.style.background = bg),
      radius && (ele.style.borderRadius = radius + "px"),
      color && (msgEle.style.color = color),
      fontSize && (msgEle.style.fontSize = fontSize + "px"),
      isTitle || (ele.ttEle.style.display = "none"),
      (msgBox.style.left = "");
    const placeArr = postion.split(/-|_/);
    if (
      ((msgBox.style[placeArr[0]] = placeArr[0] ? "12px" : ""),
      (msgBox.style[placeArr[1]] = placeArr[1] ? "12px" : ""),
      title)
    ) {
      const ttEle = ele.ttEle;
      (ttEle.innerHTML = title),
        tt_color && (ttEle.style.color = tt_color),
        tt_fontSize && (ttEle.style.fontSize = tt_fontSize + "px");
    }
    "auto" === time
      ? (time = (function getShowTime(text) {
          return 410 * text.length + 1500;
        })(msg))
      : (time *= 1e3),
      (time += disTime),
      useOne || (clearTimeout(msgTimerId), clearTimeout(msgEndTimerId)),
      (ele.style.opacity = 1),
      (msgTimerId = setTimeout(() => {
        (ele.style.opacity = 0),
          (msgEndTimerId = setTimeout(() => {
            (msgBox.style.left = -ele.maxWidth - 100 + "px"),
              fn && fn(),
              useOne && ele.remove();
          }, 1e3 * ele.transition));
      }, time));
  }
  function saveJson({
    data = "",
    fileName = "outData",
    type = "json",
    isFormat = !1,
    space = 2,
    isDoubleOut = !0,
    addText = "-格式化",
  } = {}) {
    "string" != typeof data &&
      "json" === type &&
      (isFormat
        ? (isDoubleOut &&
            saveJson({
              data,
              fileName,
              type,
              isFormat: !1,
              space,
              isDoubleOut: !1,
            }),
          (fileName += addText),
          (data = JSON.stringify(data, null, space)))
        : (data = JSON.stringify(data)));
    const blob = new Blob(
        [data],
        "json" === type ? { type: "application/json" } : { type: "text/plain" }
      ),
      href = URL.createObjectURL(blob),
      alink = document.createElement("a");
    (alink.style.display = "none"),
      (fileName += "." + type),
      (alink.download = fileName),
      (alink.href = href),
      document.body.appendChild(alink),
      alink.click(),
      document.body.removeChild(alink),
      URL.revokeObjectURL(href);
  }
  const downloadImage = (imgsrc, name, type = "png") => {
      "jpg" === type && (type = "jpeg");
      let image = new Image();
      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/${type}`),
            a = document.createElement("a"),
            event = new MouseEvent("click");
          (a.download = name || "pic"), (a.href = url), a.dispatchEvent(event);
        }),
        (image.src = imgsrc);
    },
    editHTML =
      '<div class="edit-box">\n  <div class="edit-item name-box">\n    <div class="name title">标 题</div>\n    <textarea class="edit-name" placeholder="" title="拖动右下角可调节宽高"></textarea>\n  </div>\n  <div class="edit-item desc-box">\n    <div class="desc title">描 述</div>\n    <textarea class="edit-desc" placeholder="" title="拖动右下角可调节宽高"></textarea>\n  </div>\n  <div class="content content-box">\n    <div class="desc title">内 容</div>\n    <textarea class="edit-content" placeholder="" title="拖动右下角可调节宽高"></textarea>\n  </div>\n  <div class="edit-item btn-box">\n    <button class="cancel-btn">取 消</button>\n    <button class="confirm-btn">确 认</button>\n  </div>\n</div>',
    edit = {
      isEditing: !1,
      editText: {},
      eleList: {},
      callback: { confirmBefore: null, finished: null },
    },
    eleList = edit.eleList;
  function editArea_createEditEle({
    id,
    box,
    placeholder = {
      title: "请输入标题",
      desc: "请输入描述",
      value: "请输入内容",
    },
    zIndex = 2e3,
    clickWrapClose = !0,
  } = {}) {
    return (
      addCss(
        `.ll-edit-wrap {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: ${zIndex};\n  background: rgba(0, 0, 0, 0.12);\n}\n.ll-edit-wrap .edit-box {\n  position: relative;\n  width: 480px;\n  top: calc(50% - 250px);\n  margin: auto;\n  color: #333;\n  background: #fff;\n  font-size: 16px;\n  font-family: math;\n  border: 3px solid #dfedfe;\n  border-radius: 10px;\n  box-sizing: border-box;\n  padding: 20px;\n}\n.ll-edit-wrap .edit-box > div {\n  margin-bottom: 15px;\n}\n.ll-edit-wrap .edit-box .edit-item {\n  display: flex;\n}\n.ll-edit-wrap .edit-box textarea {\n  width: 100%;\n  line-height: 18px;\n  border-radius: 6px;\n  padding: 5px 7px;\n  outline-color: #cee4ff;\n  border: 1px solid #aaa;\n  box-sizing: border-box;\n  font-size: 13px;\n  font-family: math;\n  /* 保留空格 */\n  white-space: pre-wrap;\n  /* 允许词内换行 */\n  word-break: break-all;\n  letter-spacing: 1px;\n}\n.ll-edit-wrap .edit-box textarea::placeholder {\n  color: #bbb;\n}\n.ll-edit-wrap .edit-box .title {\n  width: 15%;\n  font-weight: bold;\n  font-size: 18px;\n}\n.ll-edit-wrap .edit-box .content-box .title {\n  width: 100%;\n  margin-bottom: 8px;\n}\n.ll-edit-wrap .edit-box .name-box textarea {\n  height: 30px;\n}\n.ll-edit-wrap .edit-box .desc-box textarea {\n  height: 100px;\n}\n.ll-edit-wrap .edit-box .content-box textarea {\n  width: 100%;\n  height: 200px;\n}\n.ll-edit-wrap .edit-box .btn-box {\n  justify-content: flex-end;\n  margin-bottom: 0;\n}\n.ll-edit-wrap .edit-box .btn-box button {\n  font-size: 16px;\n  color: #65aaff;\n  background: #dfedfe;\n  outline: none;\n  border: none;\n  border-radius: 6px;\n  padding: 8px 16px;\n  box-sizing: border-box;\n  cursor: pointer;\n}\n.ll-edit-wrap .edit-box .btn-box .cancel-btn {\n  color: #888;\n  background: #f4f4f4;\n  margin-right: 20px;\n}\n.ll-edit-wrap .edit-box .btn-box .cancel-btn:hover {\n  color: #666;\n  background: #eee;\n}\n.ll-edit-wrap .edit-box .btn-box .confirm-btn:hover {\n  background: #cee4ff;\n}`
      ),
      (eleList.wrap = createEle({ className: "ll-edit-wrap", box })),
      (eleList.wrap.id = id || ""),
      (eleList.wrap.innerHTML = editHTML),
      (eleList.wrap.style.display = "none"),
      (eleList.wrap.clickWrapClose = clickWrapClose),
      (eleList.box = eleList.wrap.children[0]),
      (eleList.box.className = eleList.box.className + " ll-scroll-style-1"),
      (eleList.title = eleList.box.querySelector(".edit-name")),
      (eleList.desc = eleList.box.querySelector(".edit-desc")),
      (eleList.value = eleList.box.querySelector(".edit-content")),
      (eleList.cancel = eleList.box.querySelector(".cancel-btn")),
      (eleList.confirm = eleList.box.querySelector(".confirm-btn")),
      (eleList.title.placeholder = placeholder.title),
      (eleList.desc.placeholder = placeholder.desc),
      (eleList.value.placeholder = placeholder.value),
      (function editArea_bindEvents() {
        function cancelEdit(e) {
          const dom = e.target,
            className = dom.className;
          if ("ll-edit-wrap" === className || "cancel-btn" === className) {
            if ("ll-edit-wrap" === className && !dom.clickWrapClose) return;
            editArea_showEditArea(!1), clearEditData();
          }
        }
        function confirmEdit() {
          const data = (function getEditData() {
            return {
              title: eleList.title.value,
              desc: eleList.desc.value,
              value: eleList.value.value,
            };
          })();
          if (edit.callback.confirmBefore) {
            let result;
            const func = edit.callback.confirmBefore;
            if (
              (Array.isArray(func)
                ? func.curFn
                  ? ((result = func[curFn](data)), (func.curFn = null))
                  : func.forEach((fn) => {
                      result = fn(data);
                    })
                : (result = func(data)),
              !1 === result)
            )
              return;
          }
          if (eleList.value.value) {
            if (
              (editArea_showEditArea(!1),
              clearEditData(),
              edit.callback.finished)
            ) {
              const func = edit.callback.finished;
              Array.isArray(func)
                ? func.curFn
                  ? (func[curFn](data), (func.curFn = null))
                  : func.forEach((fn) => {
                      fn(data);
                    })
                : func(data);
            }
          } else alert(edit.msg.noneText || "请填写内容!!");
        }
        eleList.wrap.addEventListener("click", cancelEdit),
          eleList.cancel.addEventListener("click", cancelEdit),
          eleList.confirm.addEventListener("click", confirmEdit);
      })(),
      edit
    );
  }
  function editArea_showEditArea(isShow = !0) {
    (edit.isEditing = isShow),
      (eleList.wrap.style.display = isShow ? "block" : "none");
  }
  function clearEditData() {
    (eleList.title.value = ""),
      (eleList.desc.value = ""),
      (eleList.value.value = "");
  }
  function changeShow(controlObj, isShow = "") {
    for (let key in controlObj) {
      const curStyle = controlObj[key].style;
      curStyle.display =
        "" === isShow
          ? "none" === curStyle.display
            ? "block"
            : "none"
          : isShow
          ? "block"
          : "none";
    }
  }
  function showItemControlEvent(control, info) {
    const listEle = info.listEle,
      moveBox = control.eleList.move_control;
    changeShow(control.move_eleList, !1),
      listEle.addEventListener("click", (e) => {
        const item = e.target;
        if (item.classList.contains("hItem")) {
          const oldId = listEle.curClickEle && +listEle.curClickEle.id;
          if (
            (+item.id === oldId
              ? changeShow(control.move_eleList)
              : changeShow(control.move_eleList, !0),
            (moveBox.style.top =
              item.offsetTop - control.cfg.move_height - 3 + "px"),
            (listEle.oldClickEle = listEle.curClickEle),
            (listEle.curClickEle = item),
            (listEle.curId = item.id),
            control.info.move &&
              control.info.move.isMoving &&
              item !== listEle.oldClickEle)
          ) {
            const move = control.info.move;
            (!move.warnText || confirm(move.warnText)) &&
              (!(function moveItem({ info, ele, toEle, id, toId } = {}) {
                const listEle = info.listEle;
                !ele && id
                  ? (ele = listEle.querySelector(`[id='${id}']`))
                  : ele || id || (ele = listEle.oldClickEle);
                !toEle && toId
                  ? (toEle = listEle.querySelector(`[id='${id}']`))
                  : toEle || toId || (toEle = listEle.curClickEle);
                !id && (id = +ele.id), !toId && (toId = +toEle.id);
                const list_info = listEle.list_info,
                  newDataList = updateDataList(info),
                  flag = updateReplaceObj(info),
                  dataList = info.dataList,
                  index = dataList.map((item) => +item.id).indexOf(id);
                if (-1 === index)
                  return (
                    console.log("操作失败, 当前项的数据可能在其他页面中已删除"),
                    void message({
                      title: "移动",
                      msg: info.listEle.list_info.errorSyncText,
                    })
                  );
                const data = dataList.splice(index, 1)[0];
                let toIndex = dataList.map((item) => +item.id).indexOf(toId);
                list_info.isAddUp && (toIndex += 1),
                  dataList.splice(toIndex, 0, data),
                  updateDateFlag(info),
                  flag || newDataList
                    ? initHisListDom(info)
                    : (listEle.insertBefore(
                        ele.parentElement,
                        toEle.parentElement
                      ),
                      resetNum(listEle));
                (ele = toEle = null),
                  list_info.setValue
                    ? list_info.setValue(
                        list_info.saveName,
                        JSON.stringify(dataList)
                      )
                    : localStorage.setItem(
                        list_info.saveName,
                        JSON.stringify(dataList)
                      );
              })({ info }),
              message({ title: move.text, msg: move.endText }),
              changeShow(control.move_eleList, !1)),
              (move.isMoving = !1);
          }
          if (
            control.info.changePlace &&
            control.info.changePlace.isChangePlaceing &&
            item !== listEle.oldClickEle
          ) {
            const changeP = control.info.changePlace;
            (!changeP.warnText || confirm(changeP.warnText)) &&
              (!(function changePlace({ info, ele, toEle, id, toId } = {}) {
                const listEle = info.listEle;
                !ele && id
                  ? (ele = listEle.querySelector(`[id='${id}']`))
                  : ele || (ele = listEle.oldClickEle);
                !toEle && toId
                  ? (toEle = listEle.querySelector(`[id='${id}']`))
                  : toEle || (toEle = listEle.curClickEle);
                if (
                  (!id && (id = +ele.id),
                  !toId && (toId = +toEle.id),
                  ele && toEle)
                ) {
                  const eleData = getItemData({ info, ele }),
                    toEleData = getItemData({ info, ele: toEle });
                  if (!eleData || !toEleData)
                    return void console.log("数据获取失败");
                  toEleData.id = 1234;
                  const changeInfo = updateItem({
                    info,
                    ele,
                    data: toEleData,
                    isSave: !1,
                  });
                  updateItem({ info, ele: toEle, data: eleData, isSave: !1 }),
                    (info.dataList[changeInfo.index].id = toId),
                    (changeInfo.ele.id = toId),
                    resetNum(listEle);
                  const list_info = listEle.list_info;
                  list_info.setValue
                    ? list_info.setValue(
                        list_info.saveName,
                        JSON.stringify(info.dataList)
                      )
                    : localStorage.setItem(
                        list_info.saveName,
                        JSON.stringify(info.dataList)
                      );
                }
              })({ info }),
              message({ title: move.text, msg: move.endText }),
              changeShow(control.move_eleList, !1)),
              (changeP.isChangePlaceing = !1);
          }
        }
        e.stopPropagation();
      });
  }
  function controlEvents(control, info, searchEle, editInfo) {
    if (!control) return;
    const listEle = info.listEle,
      list_info = listEle.list_info,
      control_info = control.info;
    if (
      ((list_info.dataList = info.dataList),
      showItemControlEvent(control, info),
      control_info.add &&
        control_info.add.ele.addEventListener("click", (e) => {
          editArea_showEditArea(),
            (editInfo.msg = { noneText: control_info.add.noneText }),
            (editInfo.callback.finished = (data) => {
              addItem({
                title: data.title,
                desc: data.desc,
                value: data.value,
                info,
              }),
                message({
                  title: control_info.add.text,
                  msg: control_info.add.endText,
                });
            }),
            e.stopPropagation();
        }),
      control_info.clear &&
        control_info.clear.ele.addEventListener("click", (e) => {
          if (confirm(control_info.clear.warnText)) {
            confirm(control_info.clear.twoWarnText) &&
              (!(function clearList(info) {
                (info.listEle.innerHTML = ""),
                  (info.dataList = []),
                  bottomText(info),
                  updateDateFlag(info);
                const list_info = info.listEle.list_info;
                list_info.setValue
                  ? list_info.setValue(list_info.saveName, "[]")
                  : localStorage.removeItem(list_info.saveName);
              })(info),
              changeShow(control.move_eleList, !1));
          }
          e.stopPropagation();
        }),
      control_info.search)
    ) {
      const search = control_info.search;
      (search.eleList = {}),
        search.ele.addEventListener("click", (e) => {
          let isShow = 0 == +searchEle.style.opacity;
          if ((listEle !== searchEle.listEle && (isShow = !0), isShow)) {
            const newDataList = updateDataList(info),
              flag = updateReplaceObj(info);
            (newDataList || flag) && initHisListDom(info),
              message({ title: search.text, msg: search.title, maxWidth: 280 });
          }
          (searchEle.textEle.value = ""),
            (searchEle.listEle = listEle),
            (searchEle.textEle.searchType = search.searchType),
            showSearchBox(isShow, search.ele, search.position),
            e.stopPropagation();
        });
      const inputEle = searchEle.textEle;
      searchEle.btnEle.addEventListener("click", () => {
        changeShow(control.move_eleList, !1);
      }),
        inputEle.addEventListener("keydown", (e) => {
          13 === e.keyCode &&
            0 != +searchEle.style.opacity &&
            changeShow(control.move_eleList, !1);
        }),
        inputEle.addEventListener("input", () => {
          searchEle.isAutoSearch && changeShow(control.move_eleList, !1);
        }),
        searchEle.addEventListener("replaced", (e) => {
          if (listEle !== searchEle.listEle) return;
          list_info.setValue(list_info.saveName, list_info.dataList),
            updateDateFlag(info),
            initHisListDom(info);
          const search_info = e.detail.search_info,
            sType = search_info.searchType,
            oldVal = search_info.oldVal,
            newVal = search_info.newVal;
          message({
            title: "替换",
            msg: search.replacedText
              .replace("searchType", sType)
              .replace("oldVal", oldVal)
              .replace("newVal", newVal),
          });
        });
    }
    if (control_info.import) {
      const uploadFile = control_info.import;
      uploadFile.ele.addEventListener("click", (e) => {
        if (uploadFile.isUploading)
          return (
            message({ title: uploadFile.text, msg: uploadFile.uploadingText }),
            void console.log(uploadFile.uploadingText)
          );
        const isCover = confirm(uploadFile.warnText);
        message({ title: uploadFile.text, msg: uploadFile.startTipText }),
          (function fileUpload_fileUpload({
            uploadObj = {},
            startTt = "上传",
            startText = "开始上传",
            endTt = "上传",
            endText = "上传完成",
            errorTt = "文件上传",
            errorMsg = "上传失败",
            startFn,
            finishFn,
            errorFn,
            timeoutFn,
          } = {}) {
            let input = document.createElement("input");
            (input.type = "file"),
              input.click(),
              input.addEventListener("change", (e) => {
                startText && message({ title: startTt, msg: startText });
                const fileObj = e.target.files[0],
                  reader = new FileReader();
                reader.readAsText(fileObj);
                const data = { info: fileObj, data: {} };
                (startFn && null === startFn(data)) ||
                  (uploadObj.timer && clearTimeout(uploadObj.timer),
                  (uploadObj.timer = setTimeout(() => {
                    void 0 !== uploadObj.isUploading &&
                      uploadObj.isUploading &&
                      (timeoutFn && timeoutFn(),
                      message({
                        title: errorTt,
                        msg: "'" + fileObj.name + "'" + errorMsg,
                      }),
                      console.log("文件上传超时"));
                  }, 12e4)),
                  (reader.onload = function (readRes) {
                    try {
                      data.data = readRes.target.result;
                      const msg = "'" + fileObj.name + "'" + endText;
                      endText && message({ title: endTt, msg }),
                        console.log("上传成功: ", data.data),
                        finishFn && finishFn(data);
                    } catch (e) {
                      errorFn && errorFn(data),
                        message({
                          title: errorTt,
                          msg: "'" + fileObj.name + "'" + errorMsg,
                        });
                    } finally {
                      clearTimeout(uploadObj.timer);
                    }
                  }),
                  (reader.onerror = (e) => {
                    (data.data = e),
                      errorFn && errorFn(data),
                      message({
                        title: errorTt,
                        msg: "'" + fileObj.name + "'" + errorMsg,
                      }),
                      console.log(e),
                      clearTimeout(uploadObj.timer);
                  }));
              }),
              input.remove();
          })({
            uploadObj: uploadFile,
            startTt: uploadFile.text,
            startText: "开始上传",
            endTt: uploadFile.text,
            endText: "上传完成",
            errorTt: uploadFile.text,
            errorMsg: "数据导入失败",
            startFn: () => {
              uploadFile.isUploading = !0;
            },
            finishFn: (data) => {
              let sbText;
              (uploadFile.isUploading = !1),
                (sbText = isCover
                  ? uploadFile.coverSubmitText
                  : uploadFile.submitText);
              if (!confirm(sbText)) return;
              let dataObj, newDataList;
              try {
                dataObj = JSON.parse(data.data || null) || {};
              } catch (e) {
                console.log(e);
                try {
                  dataObj =
                    (function jsonCharsHandle(str) {
                      let obj = {};
                      return (
                        str &&
                          "[object String]" ===
                            Object.prototype.toString.call(str) &&
                          "null" !== str &&
                          ((str = (str = (str = str.replace(
                            /\r/g,
                            " "
                          )).replace(/\n/g, " ")).replace(/\t/g, " ")),
                          (obj = JSON.parse(str))),
                        obj
                      );
                    })(data.data || null) || {};
                } catch (e) {
                  return void console.log("导入失败:", e);
                }
              }
              if (Array.isArray(dataObj)) newDataList = dataObj;
              else {
                newDataList = dataObj.dataList;
                const replaceObj = dataObj.replaceObj;
                if (list_info.isCoverRepObj) list_info.replaceObj = replaceObj;
                else
                  for (const key in replaceObj)
                    list_info.replaceObj[key] = replaceObj[key];
              }
              isCover
                ? Array.isArray(dataObj)
                  ? (info.dataList = dataObj)
                  : (info.dataList = dataObj.dataList)
                : list_info.isDesc
                ? (info.dataList = [...newDataList, ...info.dataList])
                : (info.dataList = [...info.dataList, ...newDataList]),
                list_info.setValue(
                  list_info.saveName,
                  JSON.stringify(info.dataList)
                ),
                updateDateFlag(info),
                initHisListDom(info),
                message({ title: uploadFile.text, msg: uploadFile.endText }),
                console.log(uploadFile.endText);
            },
            errorFn: () => {
              uploadFile.isUploading = !1;
            },
            timeoutFn: () => {
              uploadFile.isUploading = !1;
            },
          }),
          e.stopPropagation();
      });
    }
    if (control_info.out) {
      const outFile = control_info.out;
      outFile.ele.addEventListener("click", (e) => {
        let outName = list_info.outName || list_info.saveName || "dataList";
        outFile.isTime &&
          (outName =
            formatDate({
              timestamp: new Date().getTime(),
              isExact: !0,
              midDelimiter: "-",
              delimiter2: ".",
            }) +
            " " +
            outName);
        const newDataList = updateDataList(info),
          flag = updateReplaceObj(info);
        (newDataList || flag) && initHisListDom(info),
          info.dataList.forEach((item) => {
            item.desc = item.desc
              .replaceAll("&apos;", "'")
              .replaceAll("&quot;", '"');
          });
        const dataObj = { dataList: info.dataList };
        list_info.replaceObj && (dataObj.replaceObj = list_info.replaceObj),
          saveJson({
            data: dataObj,
            fileName: outName,
            isFormat: outFile.isFormat,
            isDoubleOut: outFile.isDoubleOut,
          }),
          message({ title: outFile.text, msg: outFile.startText }),
          e.stopPropagation();
      });
    }
    if ((control_info.skip, control_info.fold)) {
      function setLineH(
        isFold = null,
        listEle = info.listEle,
        fold = control.info.fold
      ) {
        fold.ele.innerText = fold.isFold ? fold.noFoldText : fold.text;
        const textArr = listEle.querySelectorAll(".hItem"),
          len = textArr.length;
        let newH = fold.isFold ? fold.maxHeight : fold.oldMaxH;
        null !== isFold &&
          ((newH = isFold ? fold.maxHeight : fold.oldMaxH),
          (fold.isFold = isFold)),
          (listEle.list_info.liMaxHeight = newH),
          (newH += "px"),
          (listEle.display = "none");
        for (let i = 0; i < len; i++) {
          const item = textArr[i];
          item.style.maxHeight = "0px" === newH ? "initial" : newH;
        }
        listEle.display = "block";
      }
      const fold = control_info.fold;
      let isFold;
      (fold.oldMaxH = list_info.liMaxHeight),
        (isFold = list_info.getValue
          ? list_info.getValue(listEle.list_info.list_id + "_" + fold.name)
          : localStorage.getItem(listEle.list_info.list_id + "_" + fold.name)),
        (fold.isFold = null != isFold && JSON.parse(isFold)),
        setLineH(),
        fold.ele.addEventListener("click", (e) => {
          (fold.isFold = !fold.isFold),
            setLineH(),
            list_info.setValue
              ? list_info.setValue(
                  list_info.list_id + "_" + fold.name,
                  JSON.stringify(fold.isFold)
                )
              : localStorage.setItem(
                  list_info.list_id + "_" + fold.name,
                  JSON.stringify(fold.isFold)
                ),
            bottomText(info),
            changeShow(control.move_eleList, !1),
            e.stopPropagation();
        });
    }
    if (control_info.delete) {
      const del = control_info.delete;
      del.ele.addEventListener("click", (e) => {
        let isDelete = !0;
        del.isConfirm && (isDelete = confirm(del.warnText)),
          isDelete &&
            (!(function delItem({ info, id, ele } = {}) {
              const newDataList = updateDataList(info),
                flag = updateReplaceObj(info),
                listEle = info.listEle,
                dataList = info.dataList;
              if (!id && !ele && !(ele = listEle.curClickEle)) return;
              ele
                ? (id = ele.id)
                : (ele = listEle.querySelector(`[id='${id}']`));
              let delIndex = -1;
              const len = dataList.length;
              for (let i = 0; i < len; i++)
                if (+dataList[i].id == +id) {
                  delIndex = i;
                  const del = dataList.splice(i, 1);
                  console.log("删除一项", del[0]);
                  break;
                }
              updateDateFlag(info),
                flag || newDataList
                  ? initHisListDom(info)
                  : (ele.parentElement.remove(),
                    resetNum(listEle, [], info, "delete", delIndex),
                    bottomText(info));
              const list_info = listEle.list_info;
              list_info.setValue
                ? list_info.setValue(
                    list_info.saveName,
                    JSON.stringify(dataList)
                  )
                : localStorage.setItem(
                    list_info.saveName,
                    JSON.stringify(dataList)
                  );
            })({ info }),
            message({ title: del.text, msg: del.endText }),
            changeShow(control.move_eleList, !1)),
          e.stopPropagation();
      });
    }
    if (control_info.update) {
      const update = control_info.update;
      update.ele.addEventListener("click", (e) => {
        editInfo.msg = { noneText: control_info.add.noneText };
        const itemData = getItemData({ info, ele: info.listEle.curClickEle });
        itemData
          ? ((itemData.desc = itemData.desc
              .replaceAll("&apos;", "'")
              .replaceAll("&quot;", '"')),
            (function inputEditData({
              title = "",
              desc = "",
              value = "",
              data = {},
            } = {}) {
              (eleList.title.value = data.title || title),
                (eleList.desc.value = data.desc || desc),
                (eleList.value.value = data.value || value);
            })(itemData),
            (editInfo.callback.finished = (data) => {
              updateItem({ info, data }),
                message({ title: update.text, msg: update.endText }),
                changeShow(control.move_eleList, !1);
            }),
            editArea_showEditArea(!0),
            e.stopPropagation())
          : console.log("未获取到当前修改项的数据");
      });
    }
    if (control_info.move) {
      const move = control_info.move;
      move.ele.addEventListener("click", (e) => {
        if (!move.isMoving)
          return (
            (move.isMoving = !0),
            void message({
              title: move.text,
              msg: move.tipText + "\n请在提示存在期间完成该操作",
              fn: () => {
                move.isMoving = !1;
              },
            })
          );
        message({ title: move.text, msg: "已取消" + move.text + "操作" }),
          (move.isMoving = !1),
          e.stopPropagation();
      });
    }
    if (control_info.changePlace) {
      const changeP = control_info.changePlace;
      changeP.ele.addEventListener("click", (e) => {
        if (!changeP.isChangePlaceing)
          return (
            (changeP.isChangePlaceing = !0),
            void message({
              title: changeP.text,
              msg: changeP.tipText + "\n请在提示存在期间完成该操作",
              fn: () => {
                changeP.isChangePlaceing = !1;
              },
            })
          );
        message({ title: changeP.text, msg: "已取消" + changeP.text + "操作" }),
          (changeP.isChangePlaceing = !1),
          e.stopPropagation();
      });
    }
    if ((control_info.desc, control_info.toSuki)) {
      const toSuki = control_info.toSuki;
      toSuki.ele.addEventListener("click", (e) => {
        !(function itemToSuki({ info, ele, id } = {}) {
          if (!id && !ele && !(ele = info.listEle.curClickEle)) return;
          let data = getItemData({ info, ele, id });
          if (!data)
            return (
              console.log(info.listEle.list_info.control.info.toSuki.errorText),
              void message({
                title: "收藏",
                msg: info.listEle.list_info.control.info.toSuki.errorText,
              })
            );
          if (info.callback && info.callback.toSuki) {
            let newData;
            const func = info.callback.toSuki;
            Array.isArray(func)
              ? func.curFn
                ? ((newData = func[curFn](data)), (func.curFn = null))
                : func.forEach((fn) => {
                    newData = fn(data);
                  })
              : (newData = func(data)),
              (data = newData || data);
          }
          addItem({ info: info.suki_info, data });
        })({ info }),
          message({ title: toSuki.text, msg: toSuki.endText }),
          e.stopPropagation();
      });
    }
    if (
      (control_info.copy &&
        control_info.copy.ele.addEventListener("click", (e) => {
          !(function copyText(text) {
            const ele = document.createElement("textarea");
            document.body.appendChild(ele),
              (ele.value = text),
              ele.select(),
              ele.setSelectionRange(0, ele.value.length),
              document.execCommand("copy"),
              ele.remove();
          })(domToText(listEle.curClickEle)),
            message({
              title: control_info.copy.text,
              msg: control_info.copy.endText,
            }),
            e.stopPropagation();
        }),
      control_info.toBottom &&
        control_info.toBottom.ele.addEventListener("click", (e) => {
          (info.listEle.parentElement.scrollTop =
            info.listEle.parentElement.scrollHeight),
            e.stopPropagation();
        }),
      control_info.saveImg)
    ) {
      const saveImg = control_info.saveImg;
      saveImg.ele.addEventListener("click", (e) => {
        if (!confirm(saveImg.warnText)) return;
        let imgs = listEle.querySelectorAll("img");
        if (!imgs) return;
        imgs = [].slice.call(imgs);
        const outImgs = [];
        if (
          (imgs.forEach((img) => {
            outImgs.find((i) => i.src === img.src) || outImgs.push(img);
          }),
          0 === outImgs.length)
        )
          return;
        let num = 1;
        outImgs.forEach((img) => {
          let url = img.src;
          if (
            (img.dataset && img.dataset.bigimg && (url = img.dataset.bigimg),
            url)
          ) {
            let imgName,
              imgType = "png";
            if ("auto" === saveImg.saveType) {
              const arr = img.src.split(".");
              arr.length > 1 && (imgType = arr[arr.length - 1]);
            } else imgType = saveImg.saveType;
            img.alt
              ? (imgName = img.alt)
              : ((imgName = saveImg.baseName + num), num++),
              downloadImage(url, imgName, imgType);
          }
        }),
          e.stopPropagation();
      });
    }
    if (control_info.custom) {
      const custom = control_info.custom;
      custom.ele.addEventListener("click", (e) => {
        custom.callback && custom.callback(), e.stopPropagation();
      });
    }
  }
  function setBtnColor(listEle, btnEle, isClicked = "") {
    if (!listEle && !btnEle) return;
    let transformText;
    const btn_info = btnEle.btn_info;
    btn_info.isChangeColor &&
      ("" === isClicked &&
        ((transformText = listEle.parentElement.style.transform),
        (isClicked = "scaleY(1)" === transformText),
        (btnEle.isClicked = isClicked)),
      isClicked
        ? isClicked &&
          ((btnEle.style.color = btn_info.click),
          (btnEle.style.background = btn_info.click_bg),
          (btnEle.style.border = btn_info.click_bd),
          btn_info.isSvg &&
            btnEle.children[0] &&
            (btnEle.children[0].style.fill = btn_info.click))
        : btnEle.isHover
        ? ((btnEle.style.color = btn_info.hover),
          (btnEle.style.background = btn_info.hover_bg),
          btn_info.bd && (btnEle.style.border = btn_info.hover_bd),
          btn_info.isSvg &&
            btnEle.children[0] &&
            (btnEle.children[0].style.fill = btn_info.hover))
        : ((btnEle.style.color = btn_info.color),
          (btnEle.style.background = btn_info.bg),
          btn_info.bd && (btnEle.style.border = btn_info.bd),
          btn_info.isSvg &&
            btnEle.children[0] &&
            (btnEle.children[0].style.fill = btn_info.color)));
  }
  function getTitle({ text, isGetTt = !1, maxLen, addText = "..." } = {}) {
    if (!text) return "";
    let title = text,
      isZs = !1,
      isEnd_l = !1;
    if (isGetTt) {
      "\n" === text[0] && (text = text.slice(1, text.length));
      title = text.split(/(?<=[|\n\r])/)[0].trim();
    }
    return (
      "/" === title[0] &&
        "/" === title[1] &&
        "|" === title[title.length - 1] &&
        ((title = title.slice(2, title.length - 1).trim()), (isZs = !0)),
      "\n\r".includes(title[title.length - 1]) &&
        (title = title.slice(0, title.length - 1)),
      (title = title.replaceAll("\n", " ").replaceAll("\r", " ")),
      maxLen &&
        title.length >= maxLen &&
        (title = title.slice(0, maxLen) + addText),
      "|" === title[title.length - 1] &&
        ((title = title.slice(0, title.length - 1).trim()), (isEnd_l = !0)),
      title.length < 8 &&
        !isZs &&
        !isEnd_l &&
        (title = text
          .trim()
          .replaceAll("\n", " ")
          .replaceAll("\r", " ")
          .slice(0, 8)),
      title
    );
  }
  function getNum(isDesc, isAddUp, len, index) {
    return (isDesc && !isAddUp) || (!isDesc && isAddUp)
      ? len - index
      : index + 1;
  }
  function isResetNum({ info, type = "add", index = -1, oldLen = 0 } = {}) {
    if (null === info || "" === type || -1 === index) return !0;
    const list_info = info.listEle.list_info,
      isDesc = list_info.isDesc,
      isAddUp = list_info.isAddUp;
    if ("add" === type) return !(!isAddUp || isDesc) || !(isAddUp || !isDesc);
    if ("delete" === type) {
      const len = oldLen || info.dataList.length + 1;
      return getNum(isDesc, isAddUp, len, index) !== len;
    }
    return !1;
  }
  function resetNum(listEle, liArr = [], info = null, type = "", index = -1) {
    if (!isResetNum({ info, type, index })) return !1;
    const isDesc = listEle.list_info.isDesc;
    if (0 === liArr.length) {
      const numArr = listEle.getElementsByClassName("num"),
        len = numArr.length;
      for (let i = 0; i < len; i++) {
        const num = getNum(isDesc, !1, len, i),
          target = numArr[i];
        target.innerText !== num && (target.innerText = num);
      }
    } else {
      const len = liArr.length;
      for (let i = 0; i < len; i++) {
        const num = getNum(isDesc, !1, len, i),
          target = liArr[i].querySelector(".num");
        target.innerText !== num && (target.innerText = num);
      }
    }
    return !0;
  }
  function bottomText(info) {
    const listEle = info.listEle,
      dataList = info.dataList,
      list_info = listEle.list_info;
    let bt_box = listEle.querySelector(".bottom_text");
    if (bt_box) {
      let text = list_info.bottomText;
      if (!text) return;
      let isAdd = 50 * dataList.length > list_info.maxHeight - 5;
      isAdd ||
        (isAdd =
          listEle.offsetHeight + list_info.control.offsetHeight >=
          list_info.maxHeight - 5),
        isAdd
          ? (bt_box.innerText = text)
          : bt_box &&
            ((text = list_info.initialText),
            0 === dataList.length
              ? (bt_box.innerHTML = text)
              : bt_box.remove());
    } else if (0 === dataList.length) {
      const text = list_info.initialText;
      text &&
        (listEle.innerHTML = `<div class="bottom_text" title="${list_info.bottomTT}">${text}</div>`);
    } else {
      const text = list_info.bottomText;
      if (!text) return;
      let isAdd = 50 * dataList.length > list_info.maxHeight - 5;
      isAdd ||
        (isAdd =
          listEle.offsetHeight + list_info.control.offsetHeight >=
          list_info.maxHeight - 5),
        isAdd &&
          ((bt_box = document.createElement("div")),
          (bt_box.className = "bottom_text"),
          (bt_box.title = list_info.bottomTT),
          (bt_box.innerText = text),
          listEle.appendChild(bt_box));
    }
  }
  function hiddenBtnList(info, name = "") {
    const listEle = info.listEle,
      listBox = listEle.parentElement;
    "btn" === name
      ? (info.btnEle.style.display = "none")
      : "list" === name
      ? ((listBox.style.transform = "scaleY(0)"),
        listBox.classList.remove("opened"))
      : ("显示" !== info.btnEle.btn_info.showMode &&
          (info.btnEle.style.display = "none"),
        (listBox.style.transform = "scaleY(0)"),
        listBox.classList.remove("opened")),
      setBtnColor(listEle, info.btnEle),
      showSearchBox(!1),
      changeShow(listEle.list_info.control.move_eleList, !1);
  }
  function txtReplaceAll(str, obj) {
    if (obj && str) for (const key in obj) str = str.replaceAll(key, obj[key]);
    return str;
  }
  function initHisListDom(info) {
    const listEle = info.listEle;
    let dataList = info.dataList;
    listEle.innerHTML = "";
    let curHtml = "";
    const list_info = listEle.list_info;
    dataList ||
      (console.log("本地读取数据"),
      list_info.getValue
        ? (info.dataList =
            JSON.parse(list_info.getValue(list_info.saveName) || null) || [])
        : (info.dataList =
            JSON.parse(localStorage.getItem(list_info.saveName) || null) ||
            []));
    const maxLen = list_info.maxLen;
    if (list_info.isDelete && dataList.length > maxLen) {
      const delArr = dataList.splice(0, dataList.length - maxLen);
      console.log("列表过长, 删除一组数据", delArr);
    }
    const isDesc = list_info.isDesc,
      isAddUp = list_info.isAddUp;
    let htmlItem;
    const len = dataList.length,
      liMaxH = list_info.liMaxHeight
        ? `max-height:${list_info.liMaxHeight}px`
        : "",
      num_color = list_info.num_color,
      tt_color = list_info.tt_color,
      initItemFn = info.callback.initListItem,
      rpFn = list_info.replaceObjFn;
    dataList.forEach((item, i) => {
      if (initItemFn) {
        const newVal = initItemFn(item);
        newVal && (item = dataList[i] = newVal);
      }
      let curTxt = item.value,
        title = item.title || "";
      !item.id && (item.id = new Date().getTime()),
        (title = txtReplaceAll(title, item.replaceObj)),
        (curTxt = txtReplaceAll(curTxt, item.replaceObj));
      const rpObj = list_info.replaceObj;
      rpFn
        ? ((title = rpFn(title, rpObj)), (curTxt = rpFn(curTxt, rpObj)))
        : ((title = txtReplaceAll(title, rpObj)),
          (curTxt = txtReplaceAll(curTxt, rpObj))),
        (curTxt = curTxt.replaceAll("\n", "<br>"));
      const desc = item.desc
        .replaceAll("'", "&apos;")
        .replaceAll('"', "&quot;");
      (htmlItem = `<div class="item-box"><div class="item-control" title="${formatDate(
        { timestamp: item.id, isExact: !0, delimiter2: "时分秒" }
      )}" style="color:${num_color}"><span class="num">${getNum(
        isDesc,
        isAddUp,
        len,
        i
      )}</span> <span title="${desc}" class="item-tt" style="color:${tt_color}">${title}</span></div><div id="${
        item.id
      }" class="hItem" style="${liMaxH}">${curTxt}</div></div>`),
        isAddUp ? (curHtml = htmlItem + curHtml) : (curHtml += htmlItem);
    }),
      (listEle.innerHTML = curHtml),
      bottomText(info),
      info.updateDate ||
        (info.updateDate = getValue_getValue({
          base: new Date().getTime(),
          key: list_info.list_id + "_updateDate",
          getVal: list_info.getValue,
          setVal: list_info.setValue,
        })),
      info.replaceObjDate ||
        (info.replaceObjDate = getValue_getValue({
          base: new Date().getTime(),
          key: list_info.replaceObjKey + "_date",
          getVal: list_info.getValue,
          setVal: list_info.setValue,
        }));
  }
  function addItem({
    info,
    title = "",
    desc = "",
    value,
    id,
    data,
    isUpdateDom = !0,
    isGetTt = !0,
  } = {}) {
    if (!value && !data) return -1;
    const newDataList = updateDataList(info),
      flag = updateReplaceObj(info);
    (newDataList || flag) && initHisListDom(info);
    const listEle = info.listEle,
      dataList = info.dataList;
    let deleteId,
      curItem,
      isOverLenDel = !1;
    if (
      (data
        ? ((value = data.value),
          (title = data.title || ""),
          (desc = data.desc || ""),
          (data.title = title),
          (data.desc = desc),
          (id = data.id || new Date().getTime()),
          (curItem = { ...data }),
          (curItem.id = id))
        : (curItem = { value, id: id || new Date().getTime(), desc }),
      !curItem.value)
    )
      return -1;
    const initItemFn = info.callback.initListItem;
    if (initItemFn) {
      const newVal = initItemFn(item);
      newVal && (curItem = newVal);
    }
    console.log("添加一项", curItem),
      (curItem.title = getTitle({ text: title || curItem.value, isGetTt }));
    const list_info = listEle.list_info;
    if (list_info.isDelRepeat)
      for (let i = 0; i < dataList.length; i++) {
        const cur = dataList[i];
        if (
          cur.value === value &&
          (!list_info.isDataStrict ||
            (cur.title === curItem.title && cur.desc === desc))
        ) {
          (deleteId = cur.id), dataList.splice(i, 1);
          break;
        }
      }
    if (
      (dataList.push(curItem),
      list_info.isDelete &&
        dataList.length > list_info.maxLen &&
        (console.log("列表过长, 删除一项", dataList[0]),
        dataList.shift(),
        (isOverLenDel = !0)),
      list_info.setValue
        ? list_info.setValue(list_info.saveName, JSON.stringify(dataList))
        : localStorage.setItem(list_info.saveName, JSON.stringify(dataList)),
      updateDateFlag(info),
      isUpdateDom)
    ) {
      let liArr;
      if (
        ((deleteId || isOverLenDel) &&
          (liArr = listEle.getElementsByClassName("item-box")),
        deleteId &&
          listEle.querySelector(`[id='${deleteId}']`).parentElement.remove(),
        isOverLenDel)
      ) {
        list_info.isDesc ? liArr[liArr.length - 1].remove() : liArr[0].remove();
      }
      !(function addLi(info, item, isOverLenDel = !1) {
        if (!item.value) return;
        const listEle = info.listEle,
          dataList = info.dataList,
          list_info = listEle.list_info;
        let curTxt = item.value,
          title = item.title || "";
        !item.id && (item.id = new Date().getTime()),
          (title = txtReplaceAll(title, item.replaceObj)),
          (curTxt = txtReplaceAll(curTxt, item.replaceObj));
        const replaceObjFn = list_info.replaceObjFn;
        replaceObjFn
          ? ((title = replaceObjFn(title, list_info.replaceObj)),
            (curTxt = replaceObjFn(curTxt, list_info.replaceObj)))
          : ((title = txtReplaceAll(title, list_info.replaceObj)),
            (curTxt = txtReplaceAll(curTxt, list_info.replaceObj))),
          (curTxt = curTxt.replaceAll("\n", "<br>"));
        const isDesc = list_info.isDesc,
          isAddUp = list_info.isAddUp,
          liMaxH = list_info.liMaxHeight
            ? `max-height:${list_info.liMaxHeight}px`
            : "",
          hItem = document.createElement("div"),
          desc = item.desc.replaceAll("'", "&apos;").replaceAll('"', "&quot;");
        hItem.className = "item-box";
        let curHtml = `<div class="item-control" title="${formatDate({
          timestamp: item.id,
          isExact: !0,
          delimiter2: "时分秒",
        })}" style="color:${list_info.tt_color};"><span class="num">${getNum(
          isDesc,
          isAddUp,
          dataList.length,
          dataList.length - 1
        )}</span> <span title="${desc}" class="item-tt" style="color:${
          list_info.tt_color
        }">${title}</span></div><div id="${
          item.id
        }" class="hItem" style="${liMaxH}">${curTxt}</div>`;
        hItem.innerHTML = curHtml;
        const opened = listEle.parentElement.classList.contains("opened");
        opened || (listEle.style.display = "none"),
          isAddUp
            ? listEle.insertBefore(hItem, listEle.children[0])
            : listEle.querySelector(".bottom_text")
            ? listEle.insertBefore(
                hItem,
                listEle.children[listEle.children.length - 1]
              )
            : listEle.appendChild(hItem);
        let isReset;
        opened && (isReset = resetNum(listEle, [], info, "add", 0)),
          !isReset &&
            isOverLenDel &&
            isResetNum({
              info,
              type: "delete",
              index: 0,
              oldLen: info.dataList.length,
            }) &&
            (opened ? resetNum(listEle) : (list_info.isResetNum = !0));
        bottomText(info), opened || (listEle.style.display = "block");
      })(info, curItem, isOverLenDel);
    }
    return { deleteId, isOverLenDel };
  }
  function getItemData({ info, id, ele } = {}) {
    const newDataList = updateDataList(info),
      flag = updateReplaceObj(info);
    if (
      ((newDataList || flag) && initHisListDom(info),
      !id && !ele && !(ele = info.listEle.curClickEle))
    )
      return;
    ele && (id = +ele.id);
    const data = info.dataList.find((i) => +i.id == +id);
    return data
      ? { ...data }
      : (console.log("操作失败, 当前项的数据可能在其他页面中已删除"), null);
  }
  function updateItem({
    info,
    id,
    ele,
    newId,
    title = "",
    desc = "",
    value = "",
    replaceObj,
    data = {},
    isSave = !0,
  } = {}) {
    if (!id && !ele && !(ele = info.listEle.curClickEle))
      return void console.log("未获取到需要修改的列表项的dom");
    data && (newId = +data.id),
      ele ? (id = +ele.id) : (ele = info.listEle.querySelector(`[id='${id}']`));
    const newDataList = updateDataList(info),
      flag = updateReplaceObj(info);
    (newDataList || flag) && initHisListDom(info);
    const oldData = getItemData({ info, id });
    if (
      ((replaceObj = (data = {
        id,
        title,
        desc,
        value,
        replaceObj,
        ...oldData,
        ...data,
      }).replaceObj),
      info.callback && info.callback.updateBefore)
    ) {
      let newData;
      const func = info.callback.updateBefore;
      if (
        (Array.isArray(func)
          ? func.curFn
            ? ((newData = func[curFn](data)), (func.curFn = null))
            : func.forEach((fn) => {
                newData = fn(data);
              })
          : (newData = func(data)),
        null === newData)
      )
        return;
      data !== newData && (replaceObj = (data = newData || data).replaceObj);
    }
    const dataList = info.dataList;
    let index;
    const len = dataList.length;
    for (let i = 0; i < len; i++)
      if (+dataList[i].id == +id) {
        (data.id = dataList[i].id),
          (dataList[i] = data),
          newId && (dataList[i].id = +newId),
          (index = i);
        break;
      }
    updateDateFlag(info);
    const list_info = info.listEle.list_info;
    if (!newDataList) {
      const tt = ele.parentElement.querySelector(".item-tt");
      tt.title = data.desc.replaceAll("'", "&apos;").replaceAll('"', "&quot;");
      let curTxt = data.value;
      (data.title = txtReplaceAll(data.title, replaceObj)),
        (curTxt = txtReplaceAll(curTxt, replaceObj));
      const replaceObjFn = list_info.replaceObjFn;
      replaceObjFn
        ? ((data.title = replaceObjFn(data.title, list_info.replaceObj)),
          (curTxt = replaceObjFn(curTxt, list_info.replaceObj)))
        : ((data.title = txtReplaceAll(data.title, list_info.replaceObj)),
          (curTxt = txtReplaceAll(curTxt, list_info.replaceObj))),
        (curTxt = curTxt.replaceAll("\n", "<br>")),
        (tt.innerHTML = getTitle({ text: data.title })),
        (ele.innerHTML = curTxt),
        newId && (ele.id = newId);
    }
    if (
      (isSave &&
        (list_info.setValue
          ? list_info.setValue(list_info.saveName, JSON.stringify(dataList))
          : localStorage.setItem(list_info.saveName, JSON.stringify(dataList))),
      info.callback && info.callback.updateFinished)
    ) {
      const func = info.callback.updateFinished;
      Array.isArray(func)
        ? func.curFn
          ? (func[curFn](data), (func.curFn = null))
          : func.forEach((fn) => {
              fn(data);
            })
        : func(data);
    }
    return { index, ele };
  }
  function updateDateFlag(info) {
    const list_info = info.listEle.list_info;
    if (!list_info.isDataSync) return;
    const time = new Date().getTime();
    (info.updateDate = time),
      setValue({
        value: time,
        base: time,
        key: list_info.list_id + "_updateDate",
        getValue: list_info.getValue,
        setValue: list_info.setValue,
      });
    const replaceObj = getValue_getValue({
      key: list_info.replaceObjKey,
      base: {},
      valType: "object",
      getVal: list_info.getValue,
      setVal: list_info.setValue,
    });
    JSON.stringify(replaceObj) !== JSON.stringify(list_info.replaceObj) &&
      ((info.replaceObjDate = time),
      setValue({
        value: time,
        base: time,
        key: list_info.replaceObjKey + "_date",
        getValue: list_info.getValue,
        setValue: list_info.setValue,
      }),
      setValue({
        value: list_info.replaceObj,
        base: list_info.replaceObj,
        key: list_info.replaceObjKey,
        getValue: list_info.getValue,
        setValue: list_info.setValue,
      }));
  }
  function updateDataList(info) {
    let list_info = info.listEle.list_info;
    if (!list_info.isDataSync) return !1;
    const time = new Date().getTime(),
      myUpdateDate = info.updateDate,
      updateDate = getValue_getValue({
        base: time,
        key: list_info.list_id + "_updateDate",
        getVal: list_info.getValue,
        setVal: list_info.setValue,
      });
    if (+updateDate > +myUpdateDate) {
      (info.updateDate = updateDate),
        changeShow(list_info.control.move_eleList, !1);
      let dataList = getValue_getValue({
        key: list_info.saveName,
        base: "[]",
        valType: "array",
        getVal: list_info.getValue,
        setVal: list_info.setValue,
      });
      return (info.dataList = dataList), dataList;
    }
    return !1;
  }
  function updateReplaceObj(info) {
    let list_info = info.listEle.list_info;
    if (!list_info.isDataSync) return !1;
    const replaceObjDate = getValue_getValue({
      base: new Date().getTime(),
      key: list_info.replaceObjKey + "_date",
      getVal: list_info.getValue,
      setVal: list_info.setValue,
    });
    if (+replaceObjDate > +info.replaceObjDate) {
      info.replaceObjDate = replaceObjDate;
      const replaceObj = getValue_getValue({
        key: list_info.replaceObjKey,
        base: {},
        valType: "object",
        getVal: list_info.getValue,
        setVal: list_info.setValue,
      });
      for (const key in replaceObj) list_info.replaceObj[key] = replaceObj[key];
      return changeShow(list_info.control.move_eleList, !1), !0;
    }
    return !1;
  }
  function bindHistoryEvents(info) {
    const textEle = info.textEle,
      btnEle = info.btnEle,
      listEle = info.listEle;
    let mode = btnEle.btn_info.showMode;
    if ("显示" !== mode) {
      let eventName = "click";
      "单击" === mode
        ? (eventName = "click")
        : "双击" === mode && (eventName = "dblclick"),
        textEle &&
          textEle.addEventListener(eventName, function historyBtn(e) {
            if (this !== e.target) return;
            !(function btnShow(isShow) {
              (btnEle.style.display = isShow ? "block" : "none"),
                (listEle.parentElement.style.transform = "scaleY(0)"),
                isShow || showSearchBox(!1),
                setBtnColor(listEle, btnEle);
            })("none" === btnEle.style.display),
              e && e.stopPropagation();
          });
    }
    btnEle.addEventListener("click", function historyList(e) {
      if (
        this !== e.target &&
        "svg" !== e.target.tagName.toLowerCase() &&
        "path" !== e.target.tagName.toLowerCase()
      )
        return;
      const isClicked = "scaleY(0)" === listEle.parentElement.style.transform;
      if (((btnEle.isClicked = isClicked), isClicked)) {
        const list_info = listEle.list_info;
        list_info.isResetNum &&
          (resetNum(listEle), (list_info.isResetNum = !1)),
          (function openList(info) {
            const newDataList = updateDataList(info),
              flag = updateReplaceObj(info);
            (newDataList || flag) && initHisListDom(info);
            const listEle = info.listEle,
              listBox = listEle.parentElement;
            "none" === listBox.style.display &&
              ((listBox.style.display = "block"), listBox.offsetHeight),
              (listBox.style.transform = "scaleY(1)"),
              listBox.classList.add("opened"),
              setBtnColor(listEle, info.btnEle),
              showSearchBox(!1),
              changeShow(listEle.list_info.control.move_eleList, !1);
          })(info);
      } else hiddenBtnList(info, "list");
      e && e.stopPropagation();
    }),
      listEle.list_info.isOut &&
        listEle.addEventListener("dblclick", function useHistoryText(e) {
          const item = e.target;
          if ("hItem" === item.className) {
            const clickText = item.innerText;
            if (
              (textEle &&
                ((textEle.value = clickText),
                listEle.list_info.isExit &&
                  (function emitEvent(ele, eventType) {
                    try {
                      if (ele.dispatchEvent) {
                        var evt = new Event(eventType, {
                          bubbles: !1,
                          cancelable: !1,
                        });
                        ele.dispatchEvent(evt);
                      } else ele.fireEvent && ele.fireEvent("on" + eventType);
                    } catch (e) {}
                  })(textEle, "input")),
              info.callback && info.callback.clickItem)
            ) {
              const itemId = +item.id,
                data = info.dataList.find((i) => i.id === itemId),
                func = info.callback.clickItem;
              Array.isArray(func)
                ? func.curFn
                  ? (func[curFn](data), (func.curFn = null))
                  : func.forEach((fn) => {
                      fn(data);
                    })
                : func(data);
            }
            listEle.list_info.isClickClose &&
              ((listEle.parentElement.style.transform = "scaleY(0)"),
              setBtnColor(listEle, btnEle),
              showSearchBox(!1),
              changeShow(listEle.list_info.control.move_eleList, !1));
          } else listEle.parentElement.scrollTop = 0;
          e.stopPropagation();
        }),
      listEle.addEventListener("click", function listClickHandle(e) {
        const dom = e.target;
        if ("bottom_text" === dom.className)
          listEle.parentElement.scrollTop = 0;
        else if ("img" === dom.tagName.toLowerCase()) {
          let src = dom.src;
          const dataset = dom.dataset;
          dataset.url
            ? (src = dataset.url)
            : dataset.bigimg && (src = dataset.bigimg),
            src &&
              "//" === src.slice(0, 2) &&
              (src = window.location.protocol + src),
            src && window.open(src);
        }
      }),
      listEle.parentElement.addEventListener("dblclick", (e) => {
        (listEle.parentElement.scrollTop = 0), e.stopPropagation();
      });
  }
  const searchUpDom = (dom, target, type = "class", num = 5) => {
      let parent = dom;
      for (let i = 0; i < num; i++) {
        if (((parent = parent.parentElement), !parent)) return !1;
        if ("class" === type) {
          if (parent.classList.contains(target)) return parent;
        } else if ("id" === type && parent.id === target) return parent;
      }
      return !1;
    },
    listCss =
      "\n.ll-history-list {\n  transition: all 0.4s cubic-bezier(0.32, 0.1, 0.16, 1) 0s;\n  transform-origin: top;\n  scroll-behavior: smooth;\n  overflow-y: auto;\n}\n.ll-history-list .history-list {\n  word-break: break-all;\n  white-space: pre-wrap;\n}\n.ll-history-list .history-list .item-control {\n  word-break: initial;\n}\n.ll-history-list .history-list .item-control {\n  display: flex;\n  gap: 4px;\n  height: 25px;\n  line-height: 25px;\n  font-size: 17px;\n  border-bottom: 1px solid #ccc;\n  overflow: hidden;\n  cursor: default;\n}\n.ll-history-list .history-list .hItem {\n  font-size: 13px;\n  cursor: pointer;\n  padding: 6px 0;\n  overflow-y: auto\n}\n.ll-history-list .history-list .num {\n  user-select: none;\n}\n.ll-history-list .history-list .item-tt {\n  font-size: 13px;\n  line-height: 27px;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.ll-history-list .history-list .bottom_text {\n  padding: 8px 0;\n  text-align: center;\n  color: #aaa;\n  cursor: pointer;\n}\n.ll-history-list .history-list img {\n  min-width: 110px;\n  max-width: 165px;\n  min-height: 110px;\n  max-height: 165px;\n  display: inline-block;\n  margin: 5px 5px 0 0;\n  border-radius: 6px;\n  object-fit: cover;\n}\n.ll-history-list .history-list a {\n  text-decoration: none;\n  background-color: transparent;\n  color: #3d91c0;\n  cursor: pointer;\n}\n.ll-history-list .history-list a:hover {\n  color: #40b2f1;\n}\n.ll-history-list .list-control > div {\n  user-select: none;\n}\n",
    scrollCss =
      "\n.ll-scroll-style-1::-webkit-scrollbar,\n.ll-scroll-style-1 ::-webkit-scrollbar {\n  width: 8px;\n}\n.ll-scroll-style-1-size-2::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-2::-webkit-scrollbar {\n  width: 10px;\n}\n.ll-scroll-style-1-size-3::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-3::-webkit-scrollbar {\n  width: 12px;\n}\n.ll-scroll-style-1::-webkit-scrollbar-thumb,\n.ll-scroll-style-1 ::-webkit-scrollbar-thumb {\n  border-radius: 10px;\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.05);\n  opacity: 0.2;\n  background: #daedff;\n}\n.ll-scroll-style-1::-webkit-scrollbar-track,\n.ll-scroll-style-1 ::-webkit-scrollbar-track {\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.08);\n  border-radius: 0;\n  background: #fff;\n  border-radius: 5px;\n}",
    defaControls = {
      add: {
        name: "add",
        text: "添加",
        type: "top",
        title: "添加一项记录至列表末尾",
        class: "control-add",
        noneText: "请填写内容!!",
        endText: "添加成功",
      },
      search: {
        name: "search",
        text: "搜索",
        type: "top",
        searchType: "标题",
        title:
          "搜索所有记录的标题, 若要按描述搜索请先输入'描述=', 按内容搜索输入'内容=', 按日期搜索输入'日期='. 若含有==>或===则表示替换, 如: 标题=A==>B, 表示将列表中所有标题中的A替换为B",
        class: "control-search",
        position: "relative",
        replacedText: "已将所有列表项的searchType中的'oldVal'替换为'newVal'",
      },
      clear: {
        name: "clear",
        text: "清空",
        type: "top",
        title: "清空列表所有记录",
        class: "control-clear",
        hover_bg: "#fff",
        warnText: "是否清空列表?",
        twoWarnText:
          "请再次确认是否清空列表?清空数据后将无法复原!建议清空前先备份数据",
      },
      import: {
        name: "import",
        text: "导入",
        type: "top",
        title: "导入含数据记录的json文件",
        class: "control-import",
        warnText:
          "导入数据后是否覆盖原数据, 不覆盖则导入的数据将合并到原数据中",
        startTipText: "导入数据前建议先备份数据",
        submitText: "导入数据的数据将会和当前列表数据合并, 是否确认导入?",
        coverSubmitText:
          "导入数据后当前列表数据将会被覆盖, 建议导入数据前先备份数据, 是否确认导入?",
        uploadingText: "当前已存在上传任务",
        timeoutText: "文件上传超时",
        endText: "导入成功",
        isUploading: !1,
      },
      out: {
        name: "out",
        text: "导出",
        type: "top",
        title: "将列表的所有记录导出为json文件",
        class: "control-out",
        startText: "开始下载",
        isTime: !0,
        isFormat: !1,
        isDoubleOut: !0,
      },
      skip: {
        name: "skip",
        text: "跳转",
        type: "top",
        title: "快速跳转到对应名称的记录的位置",
        class: "control-skip",
      },
      fold: {
        name: "fold",
        text: "折叠",
        maxHeight: 45,
        noFoldText: "展开",
        type: "top",
        title: "将每条记录收起, 以节省空间",
        class: "control-fold",
        isFold: !1,
      },
      delete: {
        name: "delete",
        text: "删除",
        type: "move",
        title: "删除此条记录",
        class: "control-delete",
        bg: "#fff",
        hover: "#ff8b8b",
        hover_bg: "#fff",
        hover_bd: "1px solid #ffd4d4",
        warnText: "是否确认删除?",
        endText: "删除成功",
        isConfirm: !0,
      },
      update: {
        name: "update",
        text: "修改",
        type: "move",
        title: "修改此条记录",
        class: "control-update",
        noneText: "请填写内容!!",
        submitText: "是否确认修改?",
        endText: "修改成功",
      },
      move: {
        name: "move",
        text: "移动",
        type: "move",
        title: "将当前列表项移动到下次点击的列表项的上方",
        class: "control-move",
        tipText: "请点击目标位置的列表项",
        warnText: "是否将当前项移动到该项之前?",
        endText: "移动完成",
        isMoving: !1,
      },
      changePlace: {
        name: "changePlace",
        text: "换位",
        type: "move",
        title: "将当前项和点击的另一项进行位置交换",
        class: "control-changePlace",
        tipText: "请选择需要交换位置的项",
        warnText: "是否交换两项的位置?",
        endText: "换位成功",
        isChangePlaceing: !1,
      },
      desc: {
        name: "desc",
        text: "描述",
        type: "move",
        title: "当前记录的描述文本",
        class: "control-desc",
      },
      toSuki: {
        name: "toSuki",
        text: "收藏",
        type: "move",
        title: "将当前记录添加到收藏列表中",
        class: "control-toSuki",
        endText: "已添加至收藏",
      },
      copy: {
        name: "copy",
        text: "复制",
        type: "move",
        title: "复制内容到剪贴板",
        class: "control-copy",
        endText: "已复制到剪贴板",
      },
      toTop: {
        width: 20,
        height: 20,
        name: "toTop",
        text: "^",
        type: "other",
        title: "返回顶部",
        class: "control-toTop",
        bg: "#fff",
        hover_bg: "#fff",
        bd: "1px solid #dfedfe",
        color: "#65aaff",
        hover: "#65aaff",
        hover_bd: "1px solid #65aaff",
        fontSize: 14,
        pd: "3px 0 0 0",
        isCenter: !0,
        css: "position:absolute; bottom:4px; right:4px;",
      },
      toBottom: {
        name: "toBottom",
        text: "底部",
        type: "top",
        title: "滚动到列表底部, 双击列表项序号可以回到顶部",
        class: "control-toBottom",
      },
      saveImg: {
        name: "saveImg",
        text: "图片下载",
        type: "top",
        title: "下载列表中的所有图片",
        class: "control-saveImg",
        warnText: "是否下载该列表中的所有图片?",
        saveType: "auto",
        baseName: "image",
      },
      custom: {
        name: "custom",
        text: "未定",
        type: "top",
        class: "control-custom",
      },
    };
  function createSwitchBtn({
    box,
    svg,
    text = ">",
    size = 25,
    lineHeight,
    top = 1,
    right = -28,
    titleText = "显示/隐藏历史记录",
    className = "",
    fontSize = 14,
    fontWeight = 400,
    zIndex = 900,
    color = "#65aaff",
    bg = "#fff",
    bd = "1px solid #b7cffe",
    hover = "#65aaff",
    hover_bg = "#f7fbff",
    hover_bd = "1px solid #b7cffe",
    click = "#65aaff",
    click_bg = "#f7fbff",
    click_bd = "1px solid #b7cffe",
    fontFamily = "initial",
    showMode = "单击",
    isChangeColor = !0,
    isPosition = !0,
    child,
  } = {}) {
    if (!box) return;
    let width = size,
      height = size;
    if ("string" == typeof size && size.includes("x")) {
      const sizeArr = size.split("x");
      (width = sizeArr[0]), (height = sizeArr[1]);
    }
    const btnEle = document.createElement("div");
    (btnEle.innerHTML = svg || text),
      child && btnEle.appendChild(child),
      (btnEle.title = titleText),
      (btnEle.className = className + " ll-history-btn");
    const positionCss = isPosition
      ? `\nposition: absolute;\nz-index: ${zIndex};\ntop: ${top}px;\nright: ${right}px;`
      : "";
    (btnEle.style.cssText =
      `${child ? "display: flex;" : ""}\nmin-width: 10px;\nwidth: ${
        "auto" === width ? "auto" : width + "px"
      };\nheight: ${
        "auto" === height ? "auto" : height + "px"
      };\nline-height: ${
        lineHeight || parseInt(height) - 3
      }px;\nfont-size: ${fontSize}px;\nfont-weight: ${fontWeight};\ntext-align: center;\ncolor: ${color};\nbackground: ${bg};\n${
        bd ? "border:" + bd + ";" : ""
      }\nborder-radius: 6px;\nbox-sizing: border-box;\ncursor: pointer;\ndisplay: ${
        "显示" === showMode ? "block" : "none"
      };\nfont-family: ${fontFamily};\nuser-select: none;` + positionCss),
      (btnEle.btn_info = {
        isSvg: !!svg,
        showMode,
        isChangeColor,
        color,
        bg,
        bd,
        hover,
        hover_bg,
        hover_bd,
        click,
        click_bg,
        click_bd,
      });
    const btn_info = btnEle.btn_info;
    return (
      btnEle.addEventListener("mouseenter", () => {
        btn_info.isChangeColor &&
          ((btnEle.style.color = hover),
          (btnEle.style.fill = hover),
          (btnEle.style.background = hover_bg),
          bd && (btnEle.style.border = hover_bd),
          (btnEle.isHover = !0),
          btn_info.isSvg &&
            btnEle.children[0] &&
            (btnEle.children[0].style.fill = btn_info.hover));
      }),
      btnEle.addEventListener("mouseleave", () => {
        btn_info.isChangeColor &&
          (btnEle.isClicked ||
            ((btnEle.style.color = color),
            (btnEle.style.fill = color),
            (btnEle.style.background = bg),
            bd && (btnEle.style.border = bd),
            btn_info.isSvg &&
              btnEle.children[0] &&
              (btnEle.children[0].style.fill = btn_info.color)),
          (btnEle.isHover = !1));
      }),
      box.appendChild(btnEle),
      btnEle
    );
  }
  function createHistoryList({
    list_id = "SD_list_1",
    box,
    width = 350,
    maxHeight = 500,
    liMaxHeight = 220,
    top = 1,
    right = -382,
    fontSize = 12,
    maxLen = 100,
    title = "双击返回顶部",
    cssText = "",
    hoverColor = "#f7fbff",
    num_color = "#b5d6ff",
    tt_color = "#b5d6ff",
    tt_maxLen,
    saveName = "ll-history-list",
    outName = "列表数据",
    controlTitle = "这里是工具栏",
    listTitle = "双击一条记录即可使用",
    bottomTT = "点击返回顶部",
    className = "",
    initialText = "无历史记录",
    bottomText = "没有更多的数据了",
    dataSyncText = "正在同步其他页面的数据, 请稍后再试",
    syncEndText = "数据同步完成, 请重新操作",
    errorSyncText = "操作失败, 当前项的数据可能在其他页面中已删除",
    zIndex = 900,
    color = "#333",
    bg = "#fff",
    bd = "3px solid #dfedfe",
    pd = "6px 5px 6px 10px",
    fontFamily = "math",
    isCenter = !1,
    isDelete = !0,
    isDelRepeat = !0,
    isExit = !1,
    isOut = !0,
    isClickClose = !0,
    isDesc = !0,
    isAddUp = !0,
    isDataStrict = !0,
    isScrollStyle = !0,
    isDataSync = !1,
    isHidden = !1,
    controlCfg,
    controlArr = [],
    getValue,
    setValue,
    replaceObj,
    replaceObjKey,
    replaceObjFn,
    isCoverRepObj = !0,
  } = {}) {
    if (!box) return;
    if (
      (getValue || (getValue = localStorage.getItem),
      setValue || (setValue = localStorage.setItem),
      !replaceObjKey)
    ) {
      replaceObj = [
        ...getValue_getValue({
          base: {},
          key: (replaceObjKey = list_id + "_replaceObj"),
          valType: "object",
          getVal: getValue,
          setVal: setValue,
        }),
        ...replaceObj,
      ];
    }
    "relative" !== box.style.position &&
      "absolute" !== box.style.position &&
      "fixed" !== box.style.position &&
      (box.style.position = "relative");
    const hList = document.createElement("div");
    (hList.id = list_id || ""),
      (hList.className =
        className +
        " ll-history-list ll-scroll-style-1 ll-scroll-style-1-size-2"),
      (hList.title = title),
      (hList.style.scrollBehavior = "smooth"),
      (hList.innerHTML =
        '<div class="list-control"></div><div class="move-control-box"></div><div class="history-list text-list"></div>');
    const control = hList.querySelector(".list-control"),
      moveControlBox = hList.querySelector(".move-control-box"),
      listEle = hList.querySelector(".text-list");
    (control.title = controlTitle), (listEle.title = listTitle);
    const topEle = document.createElement("div");
    return (
      (topEle.className = "to-top"),
      (topEle.innerHTML = "^"),
      (listEle.list_info = {
        className,
        saveName,
        outName,
        maxLen,
        maxHeight,
        liMaxHeight,
        num_color,
        tt_color,
        tt_maxLen,
        initialText,
        bottomText,
        dataSyncText,
        syncEndText,
        errorSyncText,
        isDelete,
        isDelRepeat,
        isExit,
        isOut,
        isClickClose,
        isDesc,
        isAddUp,
        isDataStrict,
        isDataSync,
        control,
        bottomTT,
        list_id,
        setValue,
        getValue,
        replaceObj,
        replaceObjKey,
        replaceObjFn,
        isCoverRepObj,
      }),
      (control.eleList = { move_control: moveControlBox }),
      (control.info = {}),
      (control.style.cssText = "display: flex;\nflex-wrap: wrap;"),
      (moveControlBox.style.cssText =
        "display: flex;\nposition: absolute;\nright: 0;\ntop: 0;"),
      (hList.style.cssText = `${
        isHidden ? "display:none" : "display:block"
      };\nwidth: ${width}px;\nmax-height: ${maxHeight}px;\nline-height: ${
        fontSize + 5
      }px;\nfont-size: ${fontSize}px;\ncolor: ${color};\nbackground: ${bg};\nposition: absolute;\nz-index: ${zIndex};\ntop: ${top}px;\nright: ${right}px;\nbox-sizing: border-box;\nborder: ${bd};\nborder-radius: 8px;\npadding: ${pd};\ntransform: scaleY(0);\nfont-family: ${fontFamily};`),
      (listEle.style.cssText = `\n  ${isCenter ? "text-align: center" : ""};`),
      "none" !== cssText &&
        (isScrollStyle
          ? addCss(cssText + listCss + scrollCss, box, "ll-scroll-style-1")
          : addCss(cssText + listCss, box)),
      (control.cfg = {
        name: "cfg",
        height: 24,
        fontSize: 12,
        color: "#65aaff",
        bg: "#dfedfe",
        mg: "0 2px 4px 2px",
        bd: "1px solid #dfedfe",
        pd: "0 5px",
        radius: 6,
        hover: "#65aaff",
        hover_bg: "#cee4ff",
        hover_bd: "1px solid #dfedfe",
        move_height: 24,
        move_fontSize: 12,
        move_mg: "0 4px 0 0",
        move_pd: "0 5px",
        move_radius: 5,
        ...controlCfg,
      }),
      controlArr.forEach((item) => {
        control.info[item.name] = { ...defaControls[item.name], ...item };
      }),
      (control.top_eleList = {}),
      (control.move_eleList = {}),
      (control.other_eleList = {}),
      listEle.addEventListener("mouseover", (e) => {
        const item = e.target;
        item.classList.contains("hItem") &&
          (item.style.backgroundColor = hoverColor);
      }),
      listEle.addEventListener("mouseout", (e) => {
        const item = e.target;
        item.classList.contains("hItem") &&
          (item.style.backgroundColor = "#fff");
      }),
      (function addControlDom(control) {
        function createControl({ obj, box, type } = {}) {
          (type = type ? type + "_" : ""), (box = box || obj.box || null);
          const dom = document.createElement("div"),
            cfg = control.cfg;
          (dom.className = obj.class),
            (dom.title = obj.title),
            (dom.innerText = obj.text);
          const width = obj.width || cfg[type + "width"] || cfg.width;
          return (
            (dom.style.cssText = `\nheight: ${
              obj.height || cfg[type + "height"] || cfg.height
            }px;\nline-height: ${
              obj.height || cfg[type + "height"] || cfg.height
            }px;\nwidth: ${width ? width + "px" : "auto"};\nfont-size: ${
              obj.fontSize || cfg[type + "fontSize"] || cfg.fontSize
            }px;\ncolor: ${
              obj.color || cfg[type + "color"] || cfg.color
            };\nbackground: ${obj.bg || cfg[type + "bg"] || cfg.bg};\nmargin: ${
              ("move_" === type ? obj[type + "mg"] : obj.mg) || cfg.mg
            };\nborder: ${
              obj.bd || cfg[type + "bd"] || cfg.bd
            };\nborder-radius: ${
              obj.radius || cfg[type + "radius"] || cfg.radius
            }px;\nbox-sizing: border-box;\npadding: ${
              obj.pd || cfg[type + "pd"] || cfg.pd
            };\ncursor:pointer;\n${
              obj.isCenter ? "text-align: center;" : ""
            }\n${obj.css ? obj.css : ""}`),
            dom.addEventListener("mouseenter", () => {
              (dom.style.color = obj.hover || cfg.hover),
                (dom.style.background = obj.hover_bg || cfg.hover_bg),
                (dom.style.border = obj.hover_bd || cfg.hover_bd);
            }),
            dom.addEventListener("mouseleave", () => {
              (dom.style.color = obj.color || cfg.color),
                (dom.style.background = obj.bg || cfg.bg),
                (dom.style.border = obj.bd || cfg.bd);
            }),
            box ? box.appendChild(dom) : control.appendChild(dom),
            dom
          );
        }
        const info = control.info;
        if (!control.info) return;
        for (let key in info) {
          const item = info[key];
          "move" === item.type
            ? ((item.ele = createControl({
                obj: item,
                box: control.eleList.move_control,
                type: item.type,
              })),
              (item.ele.info = item))
            : (item.ele = createControl({ obj: item })),
            (control[item.type + "_eleList"][key] = item.ele);
        }
      })(control),
      box.appendChild(hList),
      {
        value: listEle,
        list_info: listEle.list_info,
        control,
        control_info: control.info,
      }
    );
  }
  const autoSave = (info) => {
      const list_info = info.listEle.list_info;
      let outName = list_info.outName || list_info.saveName || "dataList";
      (outName =
        formatDate({
          timestamp: new Date().getTime(),
          isExact: !0,
          midDelimiter: "-",
          delimiter2: ".",
        }) +
        " " +
        outName),
        info.dataList.forEach((item) => {
          item.desc = item.desc
            .replaceAll("&apos;", "'")
            .replaceAll("&quot;", '"');
        });
      const dataObj = { dataList: info.dataList };
      list_info.replaceObj && (dataObj.replaceObj = list_info.replaceObj);
      const outFile = list_info.control.info.out;
      saveJson({
        data: dataObj,
        fileName: outName,
        isFormat: outFile.isFormat,
        isDoubleOut: outFile.isDoubleOut,
      });
    },
    icons = {
      base: {
        color: "#666",
        width: "100%",
        height: "80%",
        marginTop: "10%",
        html: "",
      },
      lishi: {
        color: "#8a8a8a",
        width: "100%",
        height: "80%",
        marginTop: "10%",
        html: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1700314086069" style="svgStyleFlag" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4255" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512.5 98.29c-227.84 0-412.54 184.7-412.54 412.54s184.7 412.54 412.54 412.54 412.54-184.7 412.54-412.54S740.34 98.29 512.5 98.29z m249.28 661.82c-32.4 32.4-70.1 57.82-112.08 75.58-43.42 18.37-89.59 27.68-137.21 27.68-47.62 0-93.78-9.31-137.2-27.68-41.97-17.75-79.68-43.18-112.08-75.58-32.4-32.4-57.82-70.1-75.58-112.08-18.37-43.42-27.68-89.59-27.68-137.21 0-47.62 9.31-93.78 27.68-137.21 17.75-41.97 43.18-79.68 75.58-112.08s70.1-57.82 112.08-75.58c43.42-18.37 89.59-27.68 137.21-27.68 47.62 0 93.78 9.31 137.21 27.68 41.97 17.75 79.68 43.18 112.08 75.58s57.82 70.1 75.58 112.08c18.37 43.42 27.68 89.59 27.68 137.21 0 47.62-9.31 93.78-27.68 137.21-17.77 41.97-43.19 79.68-75.59 112.08z" p-id="4256"></path><path d="M738.68 674.81L542 497.48V248.27c0-16.57-13.43-30-30-30s-30 13.43-30 30v262.55c0 8.5 3.6 16.59 9.91 22.28L698.5 719.37a29.906 29.906 0 0 0 20.08 7.72c8.2 0 16.37-3.34 22.29-9.91 11.1-12.3 10.12-31.27-2.19-42.37z" p-id="4257"></path></svg>',
      },
      shoucang: {
        color: "#fe9850",
        width: "100%",
        height: "80%",
        marginTop: "10%",
        html: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1700314090785" style="svgStyleFlag" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4405" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M949.888 457.258667c26.069333-29.824 13.866667-67.52-24.789333-76.309334L681.728 325.546667l-127.786667-214.677334c-20.266667-34.069333-59.925333-34.090667-80.213333 0l-127.786667 214.677334-243.370666 55.381333c-38.442667 8.746667-50.858667 46.506667-24.789334 76.309333l164.394667 188.053334-22.613333 248.917333c-3.584 39.466667 28.458667 62.805333 64.896 47.146667l237.781333-102.037334a21.333333 21.333333 0 0 0-16.810667-39.210666L267.626667 902.186667c-6.698667 2.88-6.229333 3.221333-5.568-4.096l24.277333-267.093334-176.426667-201.813333c-4.757333-5.461333-4.906667-5.034667 2.133334-6.634667l261.205333-59.434666 137.152-230.4c3.733333-6.293333 3.136-6.293333 6.869333 0l137.173334 230.4 261.205333 59.434666c7.125333 1.621333 6.954667 1.088 2.133333 6.613334l-176.426666 201.813333 24.256 267.093333a21.333333 21.333333 0 1 0 42.496-3.84l-22.613334-248.917333 164.394667-188.053333z" p-id="4406"></path></svg>',
      },
    };
  const commentHistory_curInfo = info.history,
    commentHistory_doms = commentHistory_curInfo.doms,
    svg = (function getIconHTML({
      name = "",
      svg,
      color,
      width,
      height,
      marginTop,
      css = "",
    } = {}) {
      let icon;
      if (
        (svg
          ? ((icon = { ...icons.base }), (icon.html = svg))
          : (icon = icons[name]),
        icon)
      )
        return (
          (css += `\nfill:${color || icon.color || icons.base.fill};\nwidth:${
            width || icon.width || icons.base.width
          };\nheight:${
            height || icon.height || icons.base.height
          };\nmargin-top:${
            marginTop || icon.marginTop || icons.base.marginTop
          };`),
          icon.html.replace("svgStyleFlag", css)
        );
    })({
      svg: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1700396681111" style="svgStyleFlag" class="" viewBox="0 0 1129 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15893" xmlns:xlink="http://www.w3.org/1999/xlink" width="220.5078125" height="200"><path d="M669.489367 1016.496894c-85.292857 2.785872-189.356466-2.386815-292.381021-29.349537C148.937907 927.424287-6.152335 732.202431 0.187406 497.45884 6.73797 255.283749 172.038056 65.520695 404.560478 15.774058 576.109953-20.939216 737.517347 5.669626 884.799618 103.822669c122.465423 81.618517 190.493403 199.45337 219.790235 340.855193 24.922259 120.206608 25.04273 240.84992-6.166565 360.265943-36.434687 139.368889-127.359522 201.350774-265.990532 211.026032-47.427587 3.312929-95.284349 0.527057-162.93586 0.527057" fill="#ADDEEE" p-id="15894"></path><path d="M389.795357 745.070147c-21.594272-42.932545-21.669566-91.391657-33.761756-136.816428-5.391039-20.231454-13.831478-27.903895-30.65212-35.674219-29.417301-13.605596-58.277429-28.890245-85.73709-46.079827-29.010715-18.145814-27.949072-26.74437 3.056929-42.480782 107.090422-54.339561 218.374711-99.222216 329.576176-144.112401 69.435975-28.024365 139.820652-53.729681 210.145095-79.434996 13.138774-4.796217 30.441298-15.322295 41.426668-3.91528 10.089374 10.488431 4.39716 28.536364 0.639997 43.128309-20.63804 80.135229-54.866618 155.316123-86.723439 231.174663-25.148141 59.873658-54.550384 117.98544-83.064159 176.405926-20.841334 42.691605-25.012612 44.235128-68.299038 22.414975-31.096354-15.676177-60.747066-34.168342-91.037776-51.410631-6.159036 2.763284-12.129837 1.355289-18.017815-0.873408-41.637491-15.774058-41.276081-15.623471-59.331542 26.87237-6.490329 15.314766-7.604677 35.011633-28.22013 40.801729" fill="#FDFEFE" p-id="15895"></path><path d="M389.795357 745.070147c11.858779-26.99284 25.931197-53.277918 34.921281-81.204401 7.785383-24.18438 16.173116-22.324622 32.654936-8.606086 11.24137 9.366553 25.223435 15.457824 37.99327 23.009796-11.72325 28.58154-75.256188 68.788448-105.569487 66.800691" fill="#0294C9" p-id="15896"></path></svg>',
    });
  function useData() {
    const saveData = info.saveData;
    for (const key in saveData) {
      const list = saveData[key].value,
        len = list.length;
      if (["zanList", "sukiList"].includes(key))
        for (let i = 0; i < len; i++) {
          const rpArr = list[i].replaceArr;
          if (rpArr) {
            const replaceObj = {};
            rpArr.forEach((item) => {
              replaceObj[item.flag] = item.value;
            }),
              (list[i].replaceObj = replaceObj),
              delete list[i].replaceArr;
          }
        }
      if (settings.imageLazyLoad.value)
        for (let i = 0; i < len; i++) {
          const rpObj = list[i].replaceObj;
          if (rpObj)
            for (let key in rpObj) {
              const lazyClass = commentHistory_curInfo.classList.imageLazyLoad;
              let src = rpObj[key].split('<img class="img-item" src="');
              if (1 === src.length) continue;
              src = src[1].split('"')[0];
              let style = getWhStyle(src);
              style = style ? `style="${style}"` : "";
              const lazyBaseImage = info.history.lazyBaseImage;
              rpObj[key] = rpObj[key].replace(
                '<img class="img-item" src="',
                `<img class="img-item ${lazyClass}" ${style} src="${lazyBaseImage}" data-src="`
              );
            }
        }
    }
    (commentHistory_curInfo.zan_info.dataList = saveData.zanList.value),
      (commentHistory_curInfo.data.dataList = saveData.list.value),
      (commentHistory_curInfo.suki_info.dataList = saveData.sukiList.value);
  }
  function createHisBtnList() {
    const colorObj = commentHistory_curInfo.color.listBtnObj,
      zan_listBtn = createSwitchBtn({
        titleText: "点赞过的评论都在这里!",
        color: commentHistory_curInfo.color.font,
        fontSize: commentHistory_curInfo.fontSize,
        size: "autoxauto",
        text: commentHistory_doms.zan_comment.option.text,
        box: commentHistory_doms.options.ele,
        ...colorObj,
        showMode: "显示",
        isPosition: !1,
      }),
      listBtn = createSwitchBtn({
        titleText: `按下${settings.sendKeys.value}即可发送评论`,
        color: commentHistory_curInfo.color.font,
        fontSize: commentHistory_curInfo.fontSize,
        size: "autoxauto",
        text: commentHistory_doms.comment.option.text,
        box: commentHistory_doms.options.ele,
        ...colorObj,
        showMode: "显示",
        isPosition: !1,
      }),
      suki_listBtn = createSwitchBtn({
        titleText: `按下${settings.addItemKeys.value}后双击页面中的一条评论即可加入收藏`,
        color: commentHistory_curInfo.color.font,
        fontSize: commentHistory_curInfo.fontSize,
        size: "autoxauto",
        text: commentHistory_doms.suki_comment.option.text,
        box: commentHistory_doms.options.ele,
        ...colorObj,
        showMode: "显示",
        isPosition: !1,
      });
    (zan_listBtn.style.lineHeight = commentHistory_curInfo.height - 3 + "px"),
      (listBtn.style.lineHeight = commentHistory_curInfo.height - 3 + "px"),
      (suki_listBtn.style.lineHeight =
        commentHistory_curInfo.height - 3 + "px");
    const wh = settings.listSize.value.split(/,|,|x|X/),
      whBase = settings.listSize.base.split(/x|X/),
      wBase = +whBase[0].trim(),
      hBase = +whBase[1].trim();
    let w, h;
    1 === wh.length
      ? (w = h = +wh[0].trim() || wBase)
      : ((w = +wh[0].trim() || wBase), (h = +wh[1].trim() || hBase));
    const disW = w - wBase;
    let replaceObj = null;
    settings.isSaveEmoji.value && (replaceObj = info.saveData.emojiList.value);
    let zan_commentListInfo = createHistoryList({
        list_id: commentHistory_doms.zan_comment.list.class,
        box: commentHistory_doms.options.ele,
        width: w,
        maxHeight: h,
        fontSize: commentHistory_curInfo.fontSize - 2,
        right: -170 - disW,
        top: 35,
        liMaxHeight: settings.liMaxHeight.value,
        saveName: commentHistory_curInfo.zan_info.saveName,
        outName: commentHistory_doms.zan_comment.option.text,
        maxLen: settings.zanListMaxLen.value,
        listTitle: commentHistory_curInfo.txt.listTT,
        initialText: "暂无评论记录",
        isDesc: settings.zanListIsDesc.value,
        isAddUp: settings.zanListIsDesc.value,
        isDelete: !!settings.zanListMaxLen.value,
        isScrollStyle: !1,
        isDataSync: !0,
        isClickClose: settings.isHiddenList.value,
        replaceObj,
        isCoverRepObj: !1,
        isHidden: !0,
        replaceObjFn: replaceEmojis,
        replaceObjKey: info.saveData.emojiList.key,
        setValue: GM_setValue,
        getValue: GM_getValue,
        controlArr: [
          { name: "add" },
          {
            name: "search",
            position: "fixed",
            searchType: "内容",
            title: commentHistory_curInfo.txt.searchTT,
          },
          { name: "clear" },
          {
            name: "out",
            isFormat: settings.isFormatOut.value,
            isDoubleOut: settings.isDoubleOut.value,
          },
          { name: "import" },
          { name: "fold" },
          { name: "toBottom", title: commentHistory_curInfo.txt.toBottomTT },
          {
            name: "saveImg",
            text: "图片",
            class: "control-saveImg",
            warnText: commentHistory_curInfo.txt.saveImgText,
            saveType: settings.imgType.value,
          },
          {
            name: "custom",
            text: "设置",
            callback: showSettings,
            title: commentHistory_curInfo.txt.settings,
          },
          { name: "update" },
          { name: "move", warnText: "" },
          { name: "toSuki" },
          { name: "copy" },
          { name: "delete", isConfirm: settings.isConfirm.value },
        ],
      }),
      commentListInfo = createHistoryList({
        list_id: commentHistory_doms.comment.list.class,
        box: commentHistory_doms.options.ele,
        width: w,
        maxHeight: h,
        fontSize: commentHistory_curInfo.fontSize - 2,
        right: -244 - disW,
        top: 35,
        cssText: "none",
        liMaxHeight: settings.liMaxHeight.value,
        saveName: commentHistory_curInfo.data.saveName,
        outName: commentHistory_doms.comment.option.text,
        maxLen: settings.listMaxLen.value,
        listTitle: commentHistory_curInfo.txt.listTT,
        initialText: "暂无评论记录",
        isDesc: settings.histListIsDesc.value,
        isAddUp: settings.histListIsDesc.value,
        isDelete: !!settings.listMaxLen.value,
        isScrollStyle: !1,
        isDataSync: !0,
        isClickClose: settings.isHiddenList.value,
        replaceObj,
        isCoverRepObj: !1,
        isHidden: !0,
        replaceObjFn: replaceEmojis,
        replaceObjKey: info.saveData.emojiList.key,
        setValue: GM_setValue,
        getValue: GM_getValue,
        controlArr: [
          { name: "add" },
          {
            name: "search",
            position: "fixed",
            searchType: "内容",
            title: commentHistory_curInfo.txt.searchTT,
          },
          { name: "clear" },
          {
            name: "out",
            isFormat: settings.isFormatOut.value,
            isDoubleOut: settings.isDoubleOut.value,
          },
          { name: "import" },
          { name: "fold" },
          { name: "toBottom", title: commentHistory_curInfo.txt.toBottomTT },
          {
            name: "saveImg",
            text: "图片",
            class: "control-saveImg",
            warnText: commentHistory_curInfo.txt.saveImgText,
            saveType: settings.imgType.value,
          },
          {
            name: "custom",
            text: "设置",
            callback: showSettings,
            title: commentHistory_curInfo.txt.settings,
          },
          { name: "update" },
          { name: "move", warnText: "" },
          { name: "toSuki" },
          { name: "copy" },
          { name: "delete", isConfirm: settings.isConfirm.value },
        ],
      }),
      suki_commentListInfo = createHistoryList({
        list_id: commentHistory_doms.suki_comment.list.class,
        box: commentHistory_doms.options.ele,
        width: w,
        maxHeight: h,
        fontSize: commentHistory_curInfo.fontSize - 2,
        right: -315 - disW,
        top: 35,
        cssText: "none",
        liMaxHeight: settings.liMaxHeight.value,
        saveName: commentHistory_curInfo.suki_info.saveName,
        outName: commentHistory_doms.suki_comment.option.text,
        listTitle: commentHistory_curInfo.txt.listTT,
        initialText: "暂无收藏评论",
        isDesc: settings.sukiListIsDesc.value,
        isAddUp: settings.sukiListIsDesc.value,
        isDelete: !1,
        isScrollStyle: !1,
        isDataSync: !0,
        isClickClose: settings.isHiddenList.value,
        replaceObj,
        isCoverRepObj: !1,
        isHidden: !0,
        replaceObjFn: replaceEmojis,
        replaceObjKey: info.saveData.emojiList.key,
        setValue: GM_setValue,
        getValue: GM_getValue,
        controlArr: [
          { name: "add" },
          {
            name: "search",
            position: "fixed",
            searchType: "内容",
            title: commentHistory_curInfo.txt.searchTT,
          },
          { name: "clear" },
          {
            name: "out",
            isFormat: settings.isFormatOut.value,
            isDoubleOut: settings.isDoubleOut.value,
          },
          { name: "import" },
          { name: "fold" },
          { name: "toBottom", title: commentHistory_curInfo.txt.toBottomTT },
          {
            name: "saveImg",
            text: "图片",
            class: "control-saveImg",
            warnText: commentHistory_curInfo.txt.saveImgText,
            saveType: settings.imgType.value,
          },
          {
            name: "custom",
            text: "设置",
            callback: showSettings,
            title: commentHistory_curInfo.txt.settings,
          },
          { name: "update" },
          { name: "move", warnText: "" },
          { name: "copy" },
          { name: "delete", isConfirm: settings.isConfirm.value },
        ],
      });
    (commentHistory_curInfo.zan_info.btnEle = zan_listBtn),
      (commentHistory_curInfo.data.btnEle = listBtn),
      (commentHistory_curInfo.suki_info.btnEle = suki_listBtn),
      (commentHistory_curInfo.zan_info.listEle = zan_commentListInfo.value),
      (commentHistory_curInfo.data.listEle = commentListInfo.value),
      (commentHistory_curInfo.suki_info.listEle = suki_commentListInfo.value),
      initHisListDom(commentHistory_curInfo.zan_info),
      initHisListDom(commentHistory_curInfo.data),
      initHisListDom(commentHistory_curInfo.suki_info),
      bindHistoryEvents(commentHistory_curInfo.zan_info),
      bindHistoryEvents(commentHistory_curInfo.data),
      bindHistoryEvents(commentHistory_curInfo.suki_info),
      controlEvents(
        zan_commentListInfo.control,
        commentHistory_curInfo.zan_info,
        info.searchEle,
        info.edit
      ),
      controlEvents(
        commentListInfo.control,
        commentHistory_curInfo.data,
        info.searchEle,
        info.edit
      ),
      controlEvents(
        suki_commentListInfo.control,
        commentHistory_curInfo.suki_info,
        info.searchEle,
        info.edit
      ),
      (commentHistory_curInfo.zan_info.listEle.parentElement.style.opacity = 0),
      (commentHistory_curInfo.data.listEle.parentElement.style.opacity = 0),
      (commentHistory_curInfo.suki_info.listEle.parentElement.style.opacity = 0),
      (commentHistory_curInfo.isListCreated = !0);
  }
  function setToSukiCallback() {
    info.history.zan_info.callback.toSuki = info.history.data.callback.toSuki =
      (data) => {
        const sukiDate = formatDate({
          timestamp: new Date().getTime(),
          isExact: !0,
          delimiter2: "时分秒",
        });
        return (
          data.desc && data.desc.includes("评论的相关信息:")
            ? (data.desc = data.desc.replace(
                "评论的相关信息:",
                `评论的相关信息:\n收藏日期: ${sukiDate}`
              ))
            : (data.desc += `\n收藏日期: ${sukiDate}`),
          data
        );
      };
  }
  function getMenuIsOpened() {
    return commentHistory_doms.options.ele.classList.contains("opened");
  }
  function openMenu(isOpen = !0) {
    isOpen
      ? (commentHistory_doms.btn.ele.classList.add("opened"),
        commentHistory_doms.options.ele.classList.add("opened"))
      : (commentHistory_doms.btn.ele.classList.remove("opened"),
        commentHistory_doms.options.ele.classList.remove("opened"),
        closeAllList()),
      commentHistory_curInfo.isListCreated &&
        (isOpen
          ? ((commentHistory_curInfo.zan_info.listEle.parentElement.style.opacity = 1),
            (commentHistory_curInfo.data.listEle.parentElement.style.opacity = 1),
            (commentHistory_curInfo.suki_info.listEle.parentElement.style.opacity = 1))
          : ((commentHistory_curInfo.zan_info.listEle.parentElement.style.opacity = 0),
            (commentHistory_curInfo.data.listEle.parentElement.style.opacity = 0),
            (commentHistory_curInfo.suki_info.listEle.parentElement.style.opacity = 0)));
  }
  function closeAllList() {
    commentHistory_curInfo.isListCreated &&
      (hiddenBtnList(commentHistory_curInfo.zan_info),
      hiddenBtnList(commentHistory_curInfo.data),
      hiddenBtnList(commentHistory_curInfo.suki_info));
  }
  function bindListEvents() {
    function menuBtnClick(listInfo) {
      if (!commentHistory_curInfo.isListCreated) return;
      listInfo === commentHistory_curInfo.zan_info
        ? (hiddenBtnList(commentHistory_curInfo.data),
          hiddenBtnList(commentHistory_curInfo.suki_info))
        : listInfo === commentHistory_curInfo.data
        ? (hiddenBtnList(commentHistory_curInfo.zan_info),
          hiddenBtnList(commentHistory_curInfo.suki_info))
        : listInfo === commentHistory_curInfo.suki_info &&
          (hiddenBtnList(commentHistory_curInfo.zan_info),
          hiddenBtnList(commentHistory_curInfo.data));
      const listBox = listInfo.listEle.parentElement;
      (!listInfo.old_updateDate ||
        +listInfo.updateDate > +listInfo.old_updateDate) &&
        ((listInfo.old_updateDate = listInfo.updateDate),
        settings.imageLazyLoad.value
          ? ((listInfo.listEle.parentElement.scrollTop = 0),
            listImgLazyLoad(listBox, 7))
          : (function loadAllLazyImage(dom) {
              if (
                ((dom = dom || info.history.doms.box.ele),
                !settings.imageLazyLoad.value)
              ) {
                let imgArr = dom.querySelectorAll(
                  `img.${classList.imageLazyLoad}`
                );
                (imgArr = [].slice.call(imgArr)),
                  imgArr.forEach((img) => {
                    loadImage(img);
                  });
              }
            })(listInfo.listEle));
    }
    const listBoxs = [
      commentHistory_curInfo.zan_info.listEle.parentElement,
      commentHistory_curInfo.data.listEle.parentElement,
      commentHistory_curInfo.suki_info.listEle.parentElement,
    ];
    !(function setSearchCallback(obj) {
      searchCallback = obj;
    })({
      searchAfter: () => {
        listImgLazyLoad(info.searchEle.listEle.parentElement, 7);
      },
    });
    const throttleImgLoad = (function throttleDebounce(fn, interval) {
      let lastTime = 0;
      return function () {
        let nowTime = new Date().getTime();
        const args = arguments;
        let timer;
        interval - (nowTime - lastTime) <= 0
          ? (clearTimeout(timer), fn.apply(this, args), (lastTime = nowTime))
          : (clearTimeout(timer),
            (timer = setTimeout(() => {
              fn.apply(this, args), (lastTime = nowTime);
            }, interval)));
      };
    })(listImgLazyLoad, 400);
    settings.imageLazyLoad.value &&
      listBoxs.forEach((listDom) => {
        listDom.addEventListener("scroll", () => {
          throttleImgLoad(listDom);
        });
      }),
      commentHistory_curInfo.zan_info.btnEle.addEventListener("click", () => {
        menuBtnClick(commentHistory_curInfo.zan_info);
      }),
      commentHistory_curInfo.data.btnEle.addEventListener("click", () => {
        menuBtnClick(commentHistory_curInfo.data);
      }),
      commentHistory_curInfo.suki_info.btnEle.addEventListener("click", () => {
        menuBtnClick(commentHistory_curInfo.suki_info);
      }),
      (commentHistory_curInfo.zan_info.callback.clickItem =
        commentHistory_curInfo.data.callback.clickItem =
        commentHistory_curInfo.suki_info.callback.clickItem =
          (data) => {
            data.url && window.open(data.url);
          }),
      (commentHistory_curInfo.zan_info.callback.updateFinished =
        commentHistory_curInfo.data.callback.updateFinished =
        commentHistory_curInfo.suki_info.callback.updateFinished =
          (data) => {
            !(function itemImgLazyLoad({ box, ele, id, isLazyLoad = !1 }) {
              !ele &&
                id &&
                (ele = info.history.doms.options.ele.querySelector(
                  `[id='${id}']`
                )),
                box || (box = ele.parentElement.parentElement.parentElement);
              const lazyLoadClass = classList.imageLazyLoad;
              let imgArr = ele.querySelectorAll(`img.${lazyLoadClass}`);
              const boxRect = box.getBoundingClientRect();
              if (isLazyLoad)
                for (let i = 0; i < imgArr.length; i++)
                  imageLazyLoad({
                    box,
                    boxRect,
                    imgDom: imgArr[i],
                    imageClass: lazyLoadClass,
                    loadedClass: classList.imageLoaded,
                    dis: settings.imageLazyLoad.dis,
                  });
              else
                (imgArr = [].slice.call(imgArr)),
                  imgArr.forEach((img) => {
                    loadImage(img);
                  });
            })({ id: data.id });
          });
    let isListHidden = !1;
    const resizeHandleDebounce = (function debounce2(fn, duration = 300) {
      let flag = !0,
        timer = null;
      return function (...args) {
        flag && ((flag = !1), fn(...args)),
          clearTimeout(timer),
          (timer = setTimeout(() => {
            (flag = !0), fn(...args);
          }, duration));
      };
    })(() => {
      isListHidden
        ? (listBoxs.forEach((box) => {
            "none" === box.style.display && (box.style.display = "block");
          }),
          (isListHidden = !1))
        : (listBoxs.forEach((box) => {
            box.classList.contains("opened") || (box.style.display = "none");
          }),
          (isListHidden = !0));
    }, 1200);
    window.addEventListener("resize", resizeHandleDebounce);
  }
  function main() {
    useData(),
      (function createDoms() {
        const box = createEle({
            id: commentHistory_doms.box.id,
            title: commentHistory_doms.box.title,
          }),
          btn = createEle({
            className: commentHistory_doms.btn.class,
            title: commentHistory_doms.btn.title,
            box,
          }),
          options = createEle({
            className: commentHistory_doms.options.class,
            title: commentHistory_doms.options.title,
            box,
          });
        (btn.innerHTML = svg),
          (commentHistory_doms.box.ele = box),
          (commentHistory_doms.btn.ele = btn),
          (commentHistory_doms.options.ele = options);
      })(),
      (info.searchEle = createSearch({
        box: commentHistory_doms.box.ele,
        zIndex: commentHistory_curInfo.searchZIndex,
      })),
      settings.lazyLoadListPages.value.includes(info.pageType) ||
        (createHisBtnList(), bindListEvents(), setToSukiCallback()),
      (function autoSaveAll() {
        const interval = settings.autoSave.value;
        if (0 == +interval) return;
        if (
          0 === commentHistory_curInfo.zan_info.length &&
          0 === commentHistory_curInfo.data.length &&
          0 === commentHistory_curInfo.suki_info.length
        )
          return;
        const oldTime = info.saveData.autoSaveTime.value,
          curTime = info.saveData.autoSaveTime.base;
        let dis = +curTime - +oldTime;
        (dis = dis / 1e3 / 60 / 60 / 24),
          dis >= interval &&
            (commentHistory_curInfo.isListCreated ||
              (getData(),
              useData(),
              createHisBtnList(),
              bindListEvents(),
              setToSukiCallback()),
            autoSave(commentHistory_curInfo.zan_info),
            autoSave(commentHistory_curInfo.data),
            autoSave(commentHistory_curInfo.suki_info),
            message({
              title: "自动备份",
              msg: "已备份点赞评论 历史评论 评论收藏的数据",
            }),
            setValue({
              value: curTime,
              base: curTime,
              key: info.saveData.autoSaveTime.key,
              getVal: GM_getValue,
              setVal: GM_setValue,
            }));
      })(),
      (function commentHistory_bindEvents() {
        let startTimer,
          startTime = +settings.hiddenBtnTime.value,
          closeListTime = +settings.closeListTime.value;
        settings.isHiddenBtn.value &&
          startTime > 0 &&
          (startTimer = setTimeout(() => {
            commentHistory_doms.box.ele.style.opacity = 0;
          }, startTime));
        let timer,
          btnNoneTimer,
          listBoxs,
          btnClickNum = 0;
        const btnToNone = () => {
          !getMenuIsOpened() &&
            listBoxs &&
            listBoxs.forEach((box) => {
              box.style.display = "none";
            });
        };
        commentHistory_doms.box.ele.addEventListener("mouseenter", () => {
          clearTimeout(btnNoneTimer),
            (commentHistory_doms.box.ele.style.opacity = 1),
            timer && clearTimeout(timer),
            startTimer && clearTimeout(startTimer),
            commentHistory_curInfo.isListCreated ||
              (getData(),
              useData(),
              createHisBtnList(),
              bindListEvents(),
              setToSukiCallback(),
              (listBoxs = [
                commentHistory_curInfo.zan_info.listEle.parentElement,
                commentHistory_curInfo.data.listEle.parentElement,
                commentHistory_curInfo.suki_info.listEle.parentElement,
              ])),
            listBoxs.forEach((box) => {
              "none" === box.style.display && (box.style.display = "block");
            });
        }),
          commentHistory_doms.box.ele.addEventListener("mouseleave", () => {
            settings.isHiddenBtn.value &&
              (commentHistory_doms.box.ele.style.opacity = 0),
              (settings.isRetractList.value || settings.isHiddenMenu.value) &&
                (closeListTime > 0
                  ? (timer = setTimeout(() => {
                      settings.isRetractList.value && closeAllList(),
                        settings.isHiddenMenu.value && openMenu(!1);
                    }, closeListTime))
                  : (settings.isRetractList.value && closeAllList(),
                    settings.isHiddenMenu.value && openMenu(!1))),
              (btnClickNum = 0),
              (btnNoneTimer = setTimeout(btnToNone, 1500));
          }),
          commentHistory_doms.btn.ele.addEventListener("click", () => {
            btnClickNum++,
              btnClickNum >= 10 && (document.comment_list_info = info),
              commentHistory_curInfo.isListCreated ||
                (getData(),
                useData(),
                createHisBtnList(),
                bindListEvents(),
                setToSukiCallback(),
                (listBoxs = [
                  commentHistory_curInfo.zan_info.listEle.parentElement,
                  commentHistory_curInfo.data.listEle.parentElement,
                  commentHistory_curInfo.suki_info.listEle.parentElement,
                ]),
                commentHistory_doms.box.ele.offsetHeight),
              listBoxs &&
                listBoxs.forEach((box) => {
                  "none" === box.style.display && (box.style.display = "block");
                });
            const isOpen = !getMenuIsOpened();
            isOpen &&
              commentHistory_curInfo.isListCreated &&
              listBoxs &&
              listBoxs.forEach((box) => {
                "none" === box.style.display && (box.style.display = "block");
              }),
              openMenu(isOpen);
          });
      })();
  }
  function customCommentSend_main() {
    const pageType = info.pageType,
      curInfo = info.customKeys,
      saveData = info.saveData,
      history = info.history,
      classList = curInfo.classList;
    curInfo.curClassList = classList[pageType];
    const curClass = curInfo.curClassList;
    function genericGetTextarea(textareaClass, box = null) {
      if (box) return box.querySelector(`.${textareaClass}`);
      {
        const focus = document.activeElement;
        return focus.classList.contains(textareaClass) ? focus : null;
      }
    }
    function getTextarea(classObj, box = null) {
      let textarea;
      return (
        classObj.focusDom &&
          (textarea =
            classObj.focusDom === classObj.box
              ? (box =
                  box ||
                  document.querySelector(
                    `.${classObj.box}.${classList.focus}`
                  ) ||
                  document).querySelector(`.${classObj.textarea}`)
              : box
              ? box.querySelector(`.${classObj.textarea}.${classList.focus}`)
              : document.querySelector(
                  `.${classObj.textarea}.${classList.focus}`
                )),
        (textarea = textarea || genericGetTextarea(classObj.textarea, box)),
        { box, textarea }
      );
    }
    function getContainer(dom, boxClass, num = 4) {
      return searchUpDom(dom, boxClass, "class", num) || dom;
    }
    function getBtn(box, btnClass) {
      let btn = box.querySelector(`.${btnClass}`);
      if (btn) return btn;
      if (((btn = box.querySelector("button")), btn)) return btn;
      {
        const divArr = box.querySelectorAll("div");
        for (let i = 0; i < divArr.length; i++) {
          const div = divArr[i],
            className = div.className;
          if (
            ["send", "submit", "btn", "button"].some((item) =>
              className.includes(item)
            )
          )
            return div;
        }
        return !1;
      }
    }
    function getSendDoms(classObj, textarea = null, btn = null) {
      let box;
      if (!textarea && !btn) {
        const result = getTextarea(classObj);
        return (
          (box = result.box),
          (textarea = result.textarea)
            ? ((box = box || getContainer(textarea, classObj.box)),
              { box, textarea, btn: getBtn(box, classObj.sendBtn) })
            : {}
        );
      }
      return !textarea && btn
        ? ((box = getContainer(btn, classObj.box)),
          {
            box,
            textarea: (textarea = getTextarea(classObj, box).textarea),
            btn,
          })
        : textarea && !btn
        ? ((box = getContainer(textarea, classObj.box)),
          { box, textarea, btn: getBtn(box, classObj.sendBtn) })
        : void 0;
    }
    function verifyKeys(e, key, keys, canShiftEnter = !0) {
      if (!keys) return console.log("未设置快捷键"), !1;
      let keyArr = keys.split("+");
      if (key && key !== keyArr[keyArr.length - 1]) return;
      const keyObj = {
        control: e.ctrlKey,
        ctrl: e.ctrlKey,
        shift: e.shiftKey,
        alt: e.altKey,
        meta: e.metaKey,
        win: e.metaKey,
        window: e.metaKey,
      };
      if (
        !canShiftEnter &&
        "enter" === key &&
        keyObj.shift &&
        !keyObj.control &&
        !keyObj.ctrl &&
        !keyObj.alt &&
        !keyObj.meta &&
        !keyObj.win &&
        !keyObj.window
      )
        return !1;
      for (let i = 0; i < keyArr.length; i++) {
        const item = keyArr[i];
        if (void 0 !== keyObj[item] && !keyObj[item]) return !1;
      }
      return !0;
    }
    function getCommentInfo(allData = {}) {
      const location = window.location,
        host = location.hostname,
        path = location.pathname.split("/"),
        pageType = getBiliPageType(),
        data = {
          id: new Date().getTime(),
          pageType,
          url: location.href,
          ...allData.data,
        },
        longTime = formatDate({
          timestamp: data.id,
          isExact: !0,
          delimiter2: "时分秒",
        }),
        shortTime = formatDate({ timestamp: data.id }),
        pageTitle = document.head.querySelector("title").innerText;
      let listTitle;
      if ("视频" === pageType) {
        const bv = path.find((i) => "BV" === i.slice(0, 2)) || "",
          h1 = document.querySelector("h1");
        (data.bv = bv),
          (listTitle = h1 ? h1.innerText : pageTitle.split("_哔哩哔哩")[0]);
      } else if ("主页" === pageType)
        listTitle = pageTitle.split("-哔哩哔哩")[0];
      else if ("动态" === pageType)
        listTitle = pageTitle.split("的动态")[0] + "的动态";
      else if ("专栏" === pageType) {
        const h1 = document.querySelector("h1");
        listTitle = h1 ? h1.innerText : host;
      } else
        listTitle =
          "番剧" === pageType
            ? pageTitle.split("-番剧")[0]
            : "消息" === pageType
            ? "消息中心"
            : host;
      let ttTmp = settings.titleFormat.value;
      (ttTmp = ttTmp
        .replace("[评论日期]", shortTime)
        .replace("[评论来源]", pageType)
        .replace("[网页标题]", listTitle)
        .replace("[评论内容]", data.value)),
        (data.desc = "评论的相关信息:"),
        "收藏" === allData.originType
          ? (data.desc += "\n收藏日期: " + longTime)
          : "点赞" === allData.originType
          ? (data.desc += "\n点赞日期: " + longTime)
          : (data.desc += "\n评论日期: " + longTime),
        (data.desc += "\n评论来源: " + data.pageType),
        "视频" === pageType
          ? ((data.desc += "\n视频标题: " + listTitle),
            (data.desc += "\n视频ID: " + data.bv),
            (ttTmp = ttTmp.replace("[视频ID]", data.bv)))
          : ((ttTmp = ttTmp.replace("[视频ID]", "")),
            "主页" === pageType
              ? (data.desc += "\n主页名称: " + listTitle)
              : "动态" === pageType
              ? (data.desc += "\n动态名称: " + listTitle)
              : "专栏" === pageType
              ? (data.desc += "\n专栏名称: " + listTitle)
              : "番剧" === pageType &&
                (data.desc += "\n番剧名称: " + listTitle));
      const tagStr =
        (function getTags() {
          if (!curClass.tagBox) return;
          let tagBox = info.doms.tagBox;
          if (
            !tagBox &&
            ((tagBox = document.querySelector(
              `${curClass.tagBox.pre}${curClass.tagBox.value}`
            )),
            !tagBox)
          )
            return;
          info.doms.tagBox = tagBox;
          let tagArr = tagBox.querySelectorAll(`.${curClass.tag}`);
          if (tagArr.length > 0) {
            (tagArr = [].slice.call(tagArr)),
              tagArr.forEach((item, i) => {
                tagArr[i] = item.innerText;
              });
            return tagArr.join("、");
          }
        })() || "";
      if (
        ("专栏" === pageType
          ? (tagStr && (data.desc += "\n专栏标签: " + tagStr),
            (ttTmp = ttTmp.replace("[视频标签]", tagStr)))
          : (tagStr && (data.desc += "\n视频标签: " + tagStr),
            (ttTmp = ttTmp.replace("[视频标签]", tagStr))),
        data.user
          ? ((data.desc += `\n评论用户: ${data.user}`),
            (ttTmp = ttTmp.replace("[评论用户]", data.user)))
          : null !== data.user
          ? ((data.desc += "\n评论用户: 自己"),
            (ttTmp = ttTmp.replace("[评论用户]", "自己")))
          : (ttTmp = ttTmp.replace("[评论用户]", "")),
        data.uid && (data.desc += `\nUID: ${data.uid}`),
        allData.replyUser
          ? ((data.desc += `\n回复用户: ${allData.replyUser}`),
            (ttTmp = ttTmp.replace("[回复用户]", allData.replyUser)),
            allData.replyUid && (data.desc += `\nUID: ${allData.replyUid}`))
          : (ttTmp = ttTmp.replace("[回复用户]", "")),
        allData.replyText && (data.desc += `\n回复评论: ${allData.replyText}`),
        allData.imgArr && allData.imgArr.length > 0)
      )
        if (1 === allData.imgArr.length)
          data.desc += "\n图片地址: " + allData.imgArr[0];
        else {
          const str = allData.imgArr.join("\n");
          data.desc += "\n图片地址: \n" + str;
        }
      return (
        allData.posterUser
          ? ((data.desc += `\n楼主名称: ${allData.posterUser}`),
            (ttTmp = ttTmp.replace("[楼主名称]", allData.posterUser)))
          : (ttTmp = ttTmp.replace("[楼主名称]", "")),
        allData.posterUid && (data.desc += `\n楼主UID: ${allData.posterUid}`),
        allData.posterText
          ? ((data.desc += `\n楼主评论: ${allData.posterText}`),
            (ttTmp = ttTmp.replace("[楼主评论]", allData.posterText)))
          : (ttTmp = ttTmp.replace("[楼主评论]", "")),
        (data.desc += "\n评论地址: " + data.url),
        (data.title = ttTmp),
        data
      );
    }
    function getText(dom) {
      const nodeArr = dom.childNodes,
        allData = { data: {}, imgArr: [] };
      let text = "";
      const pType = pageType,
        classList = curInfo.classList,
        curClass = curInfo.curClassList,
        replaceObj = {};
      let imgNum = 0,
        iconNum = 0;
      if ("消息" === pType) {
        text += dom.textContent;
        const orginalReply = dom.parentElement.querySelector(
          "." + curClass.orginalReply
        );
        orginalReply && (allData.replyText = orginalReply.textContent);
      } else {
        for (let i = 0; i < nodeArr.length; i++) {
          const node = nodeArr[i],
            nClassList = node.classList,
            tag = node.nodeName ? node.nodeName.toLowerCase() : "";
          if (
            !nClassList ||
            (!nClassList.contains(classList.noteIcon) &&
              !nClassList.contains(classList.commentTop))
          )
            if ("br" === tag) text += "\n";
            else if ("img" === tag) {
              let className = "img-item",
                src = node.src,
                flag = node.alt;
              "//" === src.slice(0, 2) &&
                (src = window.location.protocol + src);
              const imgSmall = curClass.smallEmoji || classList.smallEmoji,
                imgBig = curClass.largeEmoji || classList.largeEmoji,
                icon = classList.icon;
              let isEmoji = !1;
              nClassList &&
                (nClassList.contains(imgSmall)
                  ? ((className = classList.smallEmoji), (isEmoji = !0))
                  : nClassList.contains(imgBig)
                  ? ((className = classList.largeEmoji), (isEmoji = !0))
                  : nClassList.contains(icon)
                  ? (iconNum++,
                    (className = icon + "-item"),
                    (flag = `[icon--${iconNum}]`))
                  : (imgNum++,
                    (flag = `[image--${imgNum}]`),
                    allData.imgArr.push(src)));
              let value = `<img class="${className}" src="${src}" alt="${flag}">`;
              (replaceObj[flag] = value),
                isEmoji && (info.saveData.emojiList.value[flag] = value),
                (text += flag);
            } else if ("a" === tag) {
              const search = classList.search;
              if (nClassList.contains(search)) {
                text += node.textContent;
                continue;
              }
              let url = node.href || node.dataset.url || window.location.href;
              if (
                (nClassList &&
                  nClassList.contains(curClass.replyUser.class) &&
                  (allData.replyUser = node.textContent.replace("@", "")),
                node.dataset)
              ) {
                const uid = node.dataset[curClass.replyUser.uid];
                uid &&
                  ((url = info.personalHome + uid), (allData.replyUid = uid));
              }
              "//" === url.slice(0, 2) &&
                (url = window.location.protocol + url);
              const className = "a-item",
                flag = `[${node.textContent}]`,
                value = `<a class="${className}" href="${
                  url || ""
                }" target="_blank" title="点击跳转到链接地址">${
                  node.textContent
                }</a>`;
              (replaceObj[flag] = value), (text += flag);
            } else text += node.textContent;
        }
        const image = dom.parentElement.parentElement.querySelector(
          "." + curInfo.classList.image
        );
        if (image) {
          const imgs = image.querySelectorAll("img");
          if (0 === imgs.length) return;
          for (let i = 0; i < imgs.length; i++) {
            imgNum++;
            const img = imgs[i];
            let src = img.src,
              br = "";
            "//" === src.slice(0, 2) && (src = window.location.protocol + src),
              0 === i && text && (br = "<br>");
            const bigImgUrl = minImgToBigImg(src);
            allData.imgArr.push(bigImgUrl);
            const flag = `[image--${imgNum}]`;
            let value;
            if (settings.imageLazyLoad.value) {
              const lazyClass = info.history.classList.imageLazyLoad,
                wh = [img.width, img.height];
              let style = getWhStyle(src, wh, wh[0] / wh[1]);
              style = style ? `style="${style}"` : "";
              value = `${br}<img class="img-item ${lazyClass}" ${style} src="${info.history.lazyBaseImage}" data-src="${src}" data-bigimg="${bigImgUrl}" alt="${img.alt}" title="点击查看原图">`;
            } else
              value = `${br}<img class="img-item" src="${src}" data-bigimg="${bigImgUrl}" alt="${img.alt}" title="点击查看原图">`;
            (replaceObj[flag] = value), (text += flag);
          }
        }
      }
      return (
        (allData.data.value = text),
        0 !== Object.keys(replaceObj).length &&
          (allData.data.replaceObj = replaceObj),
        allData
      );
    }
    function getUserDom({ replyDom, replyBox, isSub } = {}) {
      const curClass = curInfo.curClassList;
      let userDom;
      if (replyBox)
        userDom = isSub
          ? replyBox.querySelector("." + curClass.subUser)
          : replyBox.querySelector("." + curClass.user);
      else {
        let box = replyDom.parentElement;
        userDom = isSub
          ? (replyBox = box.parentElement).querySelector("." + curClass.subUser)
          : (replyBox = box.parentElement.parentElement).querySelector(
              "." + curClass.user
            );
      }
      return userDom;
    }
    function getPosterInfo(dom, isUpdateUrl = !1) {
      if (!["视频", "番剧", "动态", "主页", "专栏"].includes(pageType)) return;
      const replyItem = searchUpDom(dom, curClass.replyItem, "class", 7);
      if (!replyItem) return void console.log("未获取到该楼的元素");
      const replyBox = replyItem.querySelector(`.${curClass.poster}`);
      if (!replyBox) return void console.log("未获取到楼主的元素");
      let reply, userDom;
      if (
        ((userDom = replyBox.querySelector(`.${curClass.user}`)),
        (reply = replyBox.querySelector(`.${curClass.reply}`)),
        !reply)
      )
        return void console.log("未获取到评论内容的元素");
      const data = {};
      if (
        ((data.posterText = domToText(reply)),
        userDom
          ? ((data.posterUser = userDom.innerText),
            (data.posterUid = userDom.dataset[curClass.replyUser.uid]))
          : console.log("未获取到楼主信息的元素"),
        isUpdateUrl)
      ) {
        const location = window.location;
        let curUrl = location.href;
        const rootId = userDom.dataset.rootReplyId;
        if (rootId) {
          if (location.hash) {
            const urlArr = curUrl.split("#reply");
            1 === urlArr.length
              ? (curUrl += `#reply${rootId}`)
              : (curUrl = urlArr[0] + "#reply" + rootId);
          } else curUrl += `#reply${rootId}`;
          data.newUrl = curUrl;
        }
      }
      return data;
    }
    function getMsgPageUserInfo(userDom) {
      const data = {};
      data.user = userDom.textContent;
      const userUrlArr = userDom.querySelector("a").href.split("/");
      return userUrlArr && (data.uid = userUrlArr[userUrlArr.length - 1]), data;
    }
    function getReplyDom(replyBox, isSub) {
      let replyDom,
        data = {};
      return (
        (replyDom = isSub
          ? replyBox.querySelector("." + curInfo.curClassList.subReply)
          : replyBox.querySelector("." + curInfo.curClassList.reply)),
        replyDom ||
          ((replyDom = document.activeElement.parentElement), (data.flag = 2)),
        (data.value = replyDom),
        data
      );
    }
    function addComment({
      flag = "list",
      info,
      doms,
      replyDom,
      replyBox,
      isSub,
      originType,
    } = {}) {
      let data,
        allData = { data: {} };
      if (replyDom || replyBox) {
        if (!replyDom && replyBox) {
          const replyDomInfo = getReplyDom(replyBox, isSub);
          if (
            ((replyDom = replyDomInfo.value),
            2 === replyDomInfo.flag &&
              (console.log("评论的文本区域的元素获取失败"),
              (allData.data.user = null)),
            !replyDom)
          )
            return;
        }
        const userDom = getUserDom({ replyDom, replyBox, isSub });
        if (userDom)
          if ("消息" === pageType) {
            const userInfo = getMsgPageUserInfo(userDom);
            (allData.data.user = userInfo.user),
              (allData.data.uid = userInfo.uid || "");
          } else {
            const location = window.location;
            let curUrl = location.href;
            (allData.data.user = userDom.innerText),
              (allData.data.uid = userDom.dataset[curClass.replyUser.uid]),
              (allData.data.url = curUrl);
            const rootId = userDom.dataset.rootReplyId;
            if (rootId) {
              if (location.hash) {
                const urlArr = curUrl.split("#reply");
                1 === urlArr.length
                  ? (curUrl += `#reply${rootId}`)
                  : (curUrl = urlArr[0] + "#reply" + rootId);
              } else curUrl += `#reply${rootId}`;
              allData.data.url = curUrl;
            }
          }
        else console.log("评论用户的数据获取失败"), (allData.data.user = null);
        allData.originType = originType || "收藏";
        const commentInfo = getText(replyDom);
        if (
          ((allData.replyUser = commentInfo.replyUser),
          (allData.replyUid = commentInfo.replyUid),
          (allData.replyText = commentInfo.replyText),
          (allData.imgArr = commentInfo.imgArr),
          (allData.data.value = commentInfo.data.value),
          commentInfo.data.replaceObj &&
            (allData.data.replaceObj = commentInfo.data.replaceObj),
          "消息" !== pageType && isSub)
        ) {
          const posterData = getPosterInfo(replyDom);
          posterData &&
            ((allData.posterText = posterData.posterText),
            (allData.posterUser = posterData.posterUser),
            (allData.posterUid = posterData.posterUid));
        }
        data = getCommentInfo(allData);
      } else {
        if (((allData.originType = "评论"), "消息" === pageType)) {
          replyDom = getReplyDom(
            (replyBox = curInfo.curDoms.box.parentElement)
          ).value;
          const userInfo = getMsgPageUserInfo(getUserDom({ replyBox })),
            replyUserInfo = getText(replyDom);
          (allData.replyUser = userInfo.user),
            (allData.replyUid = userInfo.uid || ""),
            (allData.replyText = replyUserInfo.data.value);
        }
        allData.data = { value: doms.textarea.value };
        const ph = doms.textarea.placeholder;
        ph.includes("回复 @") &&
          ph.includes(" : ") &&
          (allData.replyUser = ph.replace("回复 @", "").replace(" : ", ""));
        const posterData = getPosterInfo(doms.textarea, !0);
        posterData &&
          ((allData.posterText = posterData.posterText),
          (allData.posterUser = posterData.posterUser),
          (allData.posterUid = posterData.posterUid),
          posterData.newUrl && (allData.data.url = posterData.newUrl)),
          (data = getCommentInfo(allData));
      }
      if (history.isListCreated) {
        const listEle = info.listEle;
        if (
          (addItem({ info, data, isGetTt: !1 }),
          allData.imgArr && allData.imgArr.length > 0)
        ) {
          const item = listEle.querySelector(`[id='${data.id}']`);
          if (!item) return void console.log("未获取到新添加的评论内容的元素");
          const lazyLoadClass = history.classList.imageLazyLoad;
          let imgs = item.querySelectorAll(`img.${lazyLoadClass}`);
          (imgs = [].slice.call(imgs)),
            imgs.forEach((img) => {
              (img.src = img.dataset.src), img.classList.remove(lazyLoadClass);
            });
        }
      } else {
        data.id = new Date().getTime();
        const curObj = saveData[flag];
        if (!curObj) return;
        const curList = getValue_getValue({
          base: curObj.base,
          key: curObj.key,
          valType: curObj.valType,
          getVal: GM_getValue,
          setVal: GM_setValue,
        });
        curList.push(data),
          console.log("添加一项", data),
          setValue({
            value: curList,
            base: curList,
            key: info.saveName,
            getVal: GM_getValue,
            setVal: GM_setValue,
          });
      }
    }
    function isLikeBtn(dom) {
      if (!dom.classList) return { value: !1 };
      const tag = dom.tagName.toLowerCase();
      let parent,
        replyBox,
        flag = !1,
        isSub = !1;
      const curClass = curInfo.curClassList;
      if ("消息" === pageType) {
        if ("path" === tag) parent = dom.parentElement.parentElement;
        else if ("svg" === tag) parent = dom.parentElement;
        else {
          if ("button" !== tag) return { value: !1 };
          parent = dom;
        }
        if (parent.classList.contains(curClass.liked)) return { value: !1 };
        parent.classList.contains(curClass.likeBtn) &&
          curClass.likeText &&
          parent.innerText.includes(curClass.likeText) &&
          ((flag = !0),
          (replyBox = parent.parentElement.parentElement.parentElement));
      } else {
        if ("path" === tag)
          parent = dom.parentElement.parentElement.parentElement;
        else if ("svg" === tag) parent = dom.parentElement.parentElement;
        else {
          if ("span" !== tag) return { value: !1 };
          dom.classList.contains(curClass.likeBtn)
            ? ((parent = dom), (flag = !0))
            : dom.classList.contains(curClass.subLikeBtn)
            ? ((parent = dom), (flag = isSub = !0))
            : (parent = dom.parentElement);
        }
        let likeDom = parent.querySelector("i");
        if (likeDom && likeDom.classList.contains(curClass.liked))
          return { value: !1 };
        parent.classList.contains(curClass.likeBtn)
          ? ((flag = !0),
            (replyBox = parent.parentElement.parentElement.parentElement))
          : parent.classList.contains(curClass.subLikeBtn) &&
            ((flag = isSub = !0),
            (replyBox = parent.parentElement.parentElement));
      }
      return { value: flag, replyBox, isSub };
    }
    function dblClickHandle(e) {
      const curClass = curInfo.curClassList;
      let isSub = !1,
        target = e.target,
        flag = target.classList.contains(curClass.reply);
      flag ||
        curClass.reply === curClass.subReply ||
        ((flag = target.classList.contains(curClass.subReply)), (isSub = flag));
      let replyDom = flag ? target : null;
      if (
        (replyDom ||
          ((flag = target.parentElement.classList.contains(curClass.subReply)),
          flag
            ? curClass.reply !== curClass.subReply && (isSub = !0)
            : (flag = target.parentElement.classList.contains(curClass.reply)),
          (replyDom = flag ? target.parentElement : null)),
        replyDom ||
          ((replyDom = target.querySelector(`.${curClass.subReply}`)),
          replyDom
            ? curClass.reply !== curClass.subReply && (isSub = !0)
            : (replyDom = target.querySelector(`.${curClass.reply}`)),
          (flag = !!replyDom)),
        replyDom && !isSub && curClass.reply === curClass.subReply)
      ) {
        let sub = replyDom.parentElement.classList.contains(curClass.subReplyP);
        isSub = isSub || sub;
      }
      if (flag) {
        if (!verifyKeys(e, null, settings.addItemKeys.value)) return;
        message({ title: "收藏", msg: "已添加评论到收藏列表" }),
          addComment({
            flag: "sukiList",
            info: info.history.suki_info,
            replyDom,
            isSub,
            originType: "收藏",
          });
      }
    }
    function handleKeyDown(e) {
      const key = (function getKeyDown(e) {
        const keyCode = e.keyCode || e.which || e.charCode;
        let key = e.key || String.fromCharCode(keyCode);
        return (key = key.toLowerCase()), console.log("按下", key), key;
      })(e);
      if (!key) return;
      if (!verifyKeys(e, key, settings.sendKeys.value, !1)) return;
      const doms = getSendDoms(curInfo.curClassList),
        btn = doms.btn;
      btn &&
        ((curInfo.curSendBtn = btn),
        (curInfo.curDoms = doms),
        document.activeElement.blur(),
        doms.textarea.blur(),
        (curInfo.isBtnClickEvent = !1),
        btn.click(),
        addComment({ flag: "list", info: info.history.data, doms }),
        setTimeout(() => {
          curInfo.isBtnClickEvent = !0;
        }, 0));
    }
    function clickBtn() {
      curInfo.isBtnClickEvent &&
        addComment({
          flag: "list",
          info: info.history.data,
          doms: curInfo.curDoms,
        });
    }
    function clickHandle(e) {
      let target = e.target;
      const result = isLikeBtn(target);
      if (result.value)
        return void addComment({
          flag: "zanList",
          info: info.history.zan_info,
          replyBox: result.replyBox,
          isSub: result.isSub,
          originType: "点赞",
        });
      let textarea,
        flag = "textarea" === target.tagName.toLowerCase();
      if (
        (flag ||
          ((textarea = genericGetTextarea(curInfo.curClassList.textarea)),
          (flag = flag || textarea)),
        flag)
      ) {
        if (target.className.includes("edit")) return;
        if (target === curInfo.curTextarea) return;
        let doms = curInfo.curDoms;
        return (
          (curInfo.curTextarea = textarea || target),
          (curInfo.curDoms = getSendDoms(
            curInfo.curClassList,
            curInfo.curTextarea
          )),
          (doms = curInfo.curDoms),
          doms.btn
            ? ((curInfo.curSendBtn = doms.btn),
              void doms.btn.addEventListener("click", clickBtn, !0))
            : void (curInfo.curTextarea = null)
        );
      }
      if (
        ((flag = target.classList.contains(curInfo.curClassList.sendBtn)),
        flag ||
          ((target = target.parentElement),
          (flag = target.classList.contains(curInfo.curClassList.sendBtn))),
        flag && curInfo.curSendBtn !== target)
      ) {
        curInfo.curSendBtn = target;
        const doms = getSendDoms(curInfo.curClassList, null, target);
        if (!doms.textarea) return void console.log("评论的文本框获取失败");
        (curInfo.curDoms = doms), clickBtn();
      }
    }
    function magClickHandle(e) {
      if (!curInfo.isBtnClickEvent) return;
      const target = e.target,
        result = isLikeBtn(target);
      if (result.value)
        addComment({
          flag: "zanList",
          info: info.history.zan_info,
          replyBox: result.replyBox,
          isSub: result.isSub,
          originType: "点赞",
        });
      else if ("button" === target.tagName.toLowerCase()) {
        const btn = target,
          doms = getSendDoms(curInfo.curClassList, null, btn);
        if (!doms.textarea) return void console.log("评论的文本框获取失败");
        (curInfo.curDoms = doms),
          (curInfo.curSendBtn = btn),
          addComment({ flag: "list", info: info.history.data, doms });
      }
    }
    !(function init() {
      const clickFn = "消息" === pageType ? magClickHandle : clickHandle;
      document.addEventListener("click", clickFn, !0),
        document.addEventListener("dblclick", dblClickHandle, !0),
        document.addEventListener("keydown", handleKeyDown);
    })();
  }
  !(function bilibili_comment_history_main() {
    const pageType = getBiliPageType();
    if ("其他" === pageType) return;
    const id = info.history.doms.box.id;
    if (!document.querySelector("#" + id)) {
      if ("动态" === pageType) {
        const curClass = info.customKeys.classList[pageType];
        if (curClass.cjDetailsId) {
          if (document.querySelector("#" + curClass.cjDetailsId)) return;
        }
      }
      console.log("当前页面:", pageType),
        (info.pageType = pageType),
        getData(),
        addCss(
          (function getCss() {
            const position = css_settings.position.value.split(/,|,|x|X/),
              pBase = css_settings.position.base.split(/,|,/);
            let left, right;
            return (
              1 === position.length
                ? (left = right = +position[0].trim() || +pBase[0].trim())
                : ((left = +position[0].trim() || +pBase[0].trim()),
                  (right = +position[1].trim() || +pBase[1].trim())),
              `\n#${doms.box.id} {\n  height:0;\n  opacity:${
                +css_settings.hiddenBtnTime.value <= 0 ? 0 : 1
              };\n  transform:scale(${
                css_settings.scale.value
              });\n  transform-origin:left top;\n  transition:ease 1s 3s all;\n  display:flex;\n  position:fixed;\n  z-index:11000;\n  left:${left}px;\n  top:${right}px;\n  font-family:math;\n  gap:${Math.floor(
                curInfo.height / 4
              )}px;\n}\n#${
                doms.box.id
              }:hover {\n  transition: ease 1s all;\n}\n#${doms.box.id} .${
                doms.btn.class
              } {\n  width:${curInfo.width}px;\n  height:${
                curInfo.height
              }px;\n  background:#fff;\n  border:1px solid #ccc;\n  border-radius:6px;\n  box-sizing:border-box;\n  cursor:pointer;\n}\n#${
                doms.box.id
              } .${doms.btn.class}:hover {\n  border:1px solid ${
                curInfo.color.main
              };\n}\n#${doms.box.id} .${
                doms.options.class
              } {\n  position:relative;\n  display:flex;\n  height:${
                curInfo.height
              }px;\n  line-height:${curInfo.height + 1}px;\n  font-size:${
                curInfo.height - 9
              }px;\n  background:#fff;\n  border:2px solid ${
                curInfo.color.bd
              };\n  border-radius:${Math.floor(
                curInfo.height / 6
              )}px;\n  box-sizing:border-box;\n  padding:0 ${Math.floor(
                curInfo.height / 2
              )}px;\n  gap:${Math.floor(
                curInfo.height / 2
              )}px;\n  transition:opacity 0.5s,transform 0.5s;\n  transform:scaleX(0);\n  transform-origin:left top;\n}\n#${
                doms.box.id
              } .${
                doms.options.class
              }::before {\n  content:"";\n  position:absolute;\n  bottom:-12px;\n  left:0px;\n  display:block;\n  width:100%;\n  height:14px;\n  background:transparent;\n}\n#${
                doms.box.id
              } .${doms.btn.class}.opened {\n  border:1px solid ${
                curInfo.color.main
              };\n}\n#${doms.box.id} .${
                doms.options.class
              }.opened {\n  transform:scaleX(1);\n}\n#${
                doms.box.id
              } img {\n  min-width: initial;\n  max-width: initial;\n  min-height: initial;\n  max-height: initial;\n  display: inline-block;\n  margin: 0;\n}\n#${
                doms.box.id
              } .icon-item,\n#${doms.box.id} .emoji-small {\n  width: ${
                curInfo.fontSize + 5
              }px;\n  height: ${
                curInfo.fontSize + 5
              }px;\n  vertical-align: -5px;\n  border-radius: initial;\n}\n#${
                doms.box.id
              } .emoji-large {\n  width: ${
                3 * curInfo.fontSize + 5
              }px;\n  height: ${
                3 * curInfo.fontSize + 5
              }px;\n  vertical-align: text-bottom;\n    border-radius: initial;\n}\n#${
                doms.box.id
              } .img-item {\n  min-width: ${
                css_history.imgSize.w[0]
              }px;\n  max-width: ${
                css_history.imgSize.w[1]
              }px;\n  min-height: ${
                css_history.imgSize.h[0]
              }px;\n  max-height: ${
                css_history.imgSize.h[1]
              }px;\n  display: inline-block;\n  margin: 5px 5px 0 0;\n  border-radius: 6px;\n  cursor: zoom-in;\n  object-fit: cover;\n  background: #eaf7ff;\n}\n#${
                doms.box.id
              } .a-item {\n  text-decoration: none;\n  background-color: transparent;\n  color: #3d91c0;\n  cursor: pointer;\n}\n#${
                doms.box.id
              } .a-item:hover {\n  color: #40b2f1;\n}\n.ll-scroll-style-1::-webkit-scrollbar,\n.ll-scroll-style-1 ::-webkit-scrollbar {\n  width: 8px;\n}\n.ll-scroll-style-1-size-2::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-2::-webkit-scrollbar {\n  width: 10px;\n}\n.ll-scroll-style-1-size-3::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-3::-webkit-scrollbar {\n  width: 12px;\n}\n.ll-scroll-style-1::-webkit-scrollbar-thumb,\n.ll-scroll-style-1 ::-webkit-scrollbar-thumb {\n  border-radius: 10px;\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.05);\n  opacity: 0.2;\n  background: #daedff;\n}\n.ll-scroll-style-1::-webkit-scrollbar-track,\n.ll-scroll-style-1 ::-webkit-scrollbar-track {\n  -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.08);\n  border-radius: 0;\n  background: #fff;\n  border-radius: 5px;\n}\n`
            );
          })()
        ),
        (function registerMenu() {
          GM_registerMenuCommand("设置", () => {
            showSettings();
          });
        })(),
        (function setZIndex(val) {
          msgZIndex = val;
        })(info.history.msgZIndex),
        (info.edit = editArea_createEditEle({
          placeholder: {
            title: info.history.txt.editPhTT,
            desc: info.history.txt.editPhDesc,
            value: info.history.txt.editPhValue,
          },
          zIndex: info.history.editZIndex,
          clickWrapClose: info.settings.editWrapClose.value,
        })),
        info.notRecordCommentPages.includes(pageType) ||
          customCommentSend_main(),
        main();
    }
  })();
})();