您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
记录点赞的评论, 发送过的历史评论, Ctrl+双击可收藏页面中的评论, 双击评论记录可跳转到评论来源页面
当前为
// ==UserScript== // @name 评论历史记录与评论收藏(哔哩哔哩|B站|bilibili) // @namespace https://gf.qytechs.cn/zh-CN/users/1196880-ling2ling4 // @version 2.3.5 // @author Ling2Ling4 // @description 记录点赞的评论, 发送过的历史评论, Ctrl+双击可收藏页面中的评论, 双击评论记录可跳转到评论来源页面 // @license AGPL-3.0-or-later // @icon data:image/png;base64,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 // @match *://*.bilibili.com/* // @run-at document-end // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @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") ? "视频" : "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 base_id = "ll_comment_history_", info = { pageType: "", base_id, cssId: base_id + "css", settingsArea: null, settings: { isHiddenBtn: { value: !1, base: !1, valType: "boolean", key: base_id + "isHiddenBtn", txt: "是否隐藏按钮 (隐藏整个区域), 隐藏后鼠标移入时会显示出来", type: "基础设置", compType: "radio", valueText: { true: "隐藏", false: "显示" }, }, isRetractList: { value: !0, base: !0, valType: "boolean", key: base_id + "isRetractList", txt: "是否在鼠标移出列表区域后自动收起列表 (默认3s后收起)", type: "基础设置", compType: "radio", valueText: { true: "自动收起", false: "不收起" }, }, position: { value: "4, 4", base: "4, 4", valType: "string", key: base_id + "position", txt: "设置按钮的显示位置 (按钮距左侧 和 顶部的距离), 可以为负值, 中间用 , 分隔\n如: 10,50 表示距离左侧10像素距离顶部50像素", type: "基础设置", compType: "textarea", compH: "30px", }, listSize: { value: "400x500", base: "400x500", valType: "string", key: base_id + "listSize", txt: "设置列表的宽度与列表的最大高度, 中间用 x 分隔\n如: 400x300 表示列表宽度400像素, 列表最大高度300像素", type: "基础设置", compType: "textarea", compH: "30px", }, scale: { value: 1, base: 1, valType: "number", key: base_id + "scale", txt: "设置整个区域的缩放倍率 (大于1则放大,小于1则缩小)", type: "基础设置", compType: "textarea", compH: "30px", }, sendKeys: { value: "ctrl+enter", base: "ctrl+enter", valType: "string", key: base_id + "sendKeys", txt: "设置发送消息时的快捷键, 每个键用 + 分隔, 特殊字符请用英文符号 (不支持shift+enter)\n例如: ctrl + enter 表示按下ctrl和回车键发送消息\n可使用单个按键, 支持 ctrl shift alt win/meta 字母 数字 等的组合键", type: "快捷键设置", compType: "textarea", compH: "30px", }, addItemKeys: { value: "ctrl", base: "ctrl", valType: "string", key: base_id + "addItemKeys", txt: "设置评论加入评论收藏的组合键, 每个键用 + 分隔, 按下组合键后'双击'评论的文本可将文本添加到评论收藏的列表中\n仅支持 ctrl shift alt win/meta 的组合键", type: "快捷键设置", compType: "textarea", compH: "30px", }, zanListIsDesc: { value: !0, base: !0, valType: "boolean", key: base_id + "zanListIsDesc", txt: "点赞评论的列表是否倒序显示, 倒序则新评论将显示在列表顶部", type: "其他设置", compType: "radio", valueText: { true: "倒序显示", false: "顺序显示" }, }, histListIsDesc: { value: !0, base: !0, valType: "boolean", key: base_id + "histListIsDesc", txt: "历史评论的列表是否倒序显示", type: "其他设置", compType: "radio", valueText: { true: "倒序显示", false: "顺序显示" }, }, sukiListIsDesc: { value: !1, base: !1, valType: "boolean", key: base_id + "sukiListIsDesc", txt: "收藏列表是否倒序显示", type: "其他设置", compType: "radio", valueText: { true: "倒序显示", false: "顺序显示" }, }, isHiddenList: { value: !0, base: !0, valType: "boolean", key: base_id + "isHiddenList", txt: "是否在双击列表的一条评论记录后收起列表", type: "其他设置", compType: "radio", valueText: { true: "双击后收起", false: "不收起" }, }, listMaxLen: { value: 200, base: 200, valType: "number", key: base_id + "listMaxLen", txt: "列表的最大长度, 超出时最早的数据会被删除\n0 表示无长度上限 (收藏列表默认无长度上限)", type: "其他设置", compType: "textarea", compH: "30px", }, hiddenBtnTime: { value: 5e3, base: 5e3, valType: "number", key: base_id + "hiddenBtnTime", txt: "加载页面后隐藏按钮的时间 (毫秒, 1秒=1000毫秒)\n0 表示按钮初始隐藏", type: "其他设置", compType: "textarea", compH: "30px", }, closeListTime: { value: 3e3, base: 3e3, valType: "number", key: base_id + "closeListTime", txt: "自动收起列表的等待时间 (毫秒, 1秒=1000毫秒)\n0 表示鼠标移开后直接收起", type: "其他设置", compType: "textarea", compH: "30px", }, }, history: { width: 30, height: 30, fontSize: 14, imgSuffix: "!web-comment-note.avif", zan_info: { saveName: base_id + "zanList", callback: {} }, data: { saveName: base_id + "list", callback: {} }, suki_info: { saveName: base_id + "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: "", }, }, doms: { box: { id: base_id + "box", title: "" }, btn: { class: "btn", title: "评论记录列表" }, options: { class: "options", title: "" }, zan_comment: { option: { text: "点赞评论", class: "zan-comment" }, list: { class: "zan-comment" }, }, comment: { option: { text: "历史评论", class: "hist-comment" }, list: { class: "hist-comment" }, }, suki_comment: { option: { text: "评论收藏", class: "suki-comment" }, list: { class: "suki-comment" }, }, }, }, 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", link: "jump-link", 视频: { focusDom: "reply-box-textarea", box: "box-normal", 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: "user", likeBtn: "reply-like", subLikeBtn: "sub-reply-like", liked: "liked", }, 番剧: { focusDom: "reply-box-textarea", box: "box-normal", 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: "user", likeBtn: "reply-like", subLikeBtn: "sub-reply-like", liked: "liked", }, 主页: { focusDom: "reply-box-textarea", box: "box-normal", 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: "user", likeBtn: "reply-like", subLikeBtn: "sub-reply-like", liked: "liked", }, 动态: { focusDom: "reply-box-textarea", box: "box-normal", 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: "user", likeBtn: "reply-like", subLikeBtn: "sub-reply-like", liked: "liked", }, 专栏: { focusDom: "textarea-container", box: "textarea-container", textarea: "ipt-txt", sendBtn: "comment-submit", reply: "text", subReply: "text-con", subReplyP: "reply-item", user: "name", subUser: "name", replyUser: { type: "dataset", value: "usercardMid" }, likeBtn: "like", subLikeBtn: "like", liked: "liked", }, 消息: { focusDom: "", box: "reply-box", textarea: "reply-textarea", sendBtn: "send-button", reply: "real-reply", orginalReply: "orginal-reply", user: "name-field", likeBtn: "action-button", liked: "active", }, }, }, }; function getValue({ base = null, key, valType = "string", isReSet = !0, getVal, setVal, } = {}) { let val = getVal ? getVal(key) : localStorage.getItem(key); return ( null !== base && null == val && ((val = base), isReSet && (setVal ? setVal(key, val) : localStorage.setItem(key, val))), "string" === valType ? val : "boolean" === valType || "number" === valType ? JSON.parse(val) : "object" === valType ? JSON.parse(val || {}) : "array" === valType ? JSON.parse(val || []) : val ); } function getData() { const settings = info.settings; for (const valName in settings) { const setting = settings[valName]; setting.value = getValue({ base: setting.base, key: setting.key, valType: setting.valType, getVal: GM_getValue, setVal: GM_setValue, }); } } info.history.zan_info.suki_info = info.history.suki_info.suki_info = info.history.suki_info; const curInfo = info.history, doms = curInfo.doms, settings = info.settings; function setValue({ value, base, key, verification = null, getValue = null, setValue = null, } = {}) { let newVal = value, val = getValue ? getValue(key) : localStorage.getItem(key); return ( null == val && void 0 !== base && ((val = base), setValue ? setValue(key, base) : localStorage.setItem(key, base)), null !== newVal && ("function" != typeof verification || ((newVal = verification(newVal, val)), null !== newVal)) && newVal !== val && (setValue ? setValue(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 editArea_cfg = { versions: "v1.0.5", 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: [], }, allData: {}, baseData: {}, oldData: {}, controls: {}, doms: { page: [] }, editText: {}, callback: { resetBefore: null, confirmBefore: null, finished: null }, }; const css = function css_getCss() { const param = editArea_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 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}\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.tt || "" }">${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 + "" == item.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 = editArea_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 += ""), (editArea_cfg.allData[pgid] = {}), (editArea_cfg.baseData[pgid] = {}); let pageFlag = ""; if ( (editArea_cfg.isShowPage || ((void 0 === param.showPage || pgid === param.showPage + "") && ((pageFlag = "curPage"), (editArea_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), (editArea_cfg.allData[pgid][cpid] = item.value), (editArea_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="${ editArea_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-versions="${editArea_cfg.versions}">\n${menu}\n${pageHTML}\n${btnBox}\n</div>`; }, param = editArea_cfg.param, allData = editArea_cfg.allData, controls = editArea_cfg.controls, editArea_doms = editArea_cfg.doms, cBase = param.classBase; function createEditEle({ id = param.id, box = param.box, classBase = param.classBase, w = param.w, h = param.h, contentH = param.contentH, bg = param.bg, color = param.color, fontSize = param.fontSize, fontFamily = param.fontFamily, zIndex = param.zIndex, resetTt = param.resetTt, isShowMenu = param.isShowMenu, isScrollStyle = param.isScrollStyle, isResetBtn = param.isResetBtn, showPage = param.showPage, page = [], } = {}) { (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() { (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) => { editArea_cfg.isShowPage || (curPage.classList.add("curPage"), (isMenu || param.isShowMenu) && editArea_doms.menus[0].classList.add("active"), (editArea_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; 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) { (e.target.className !== `${cBase}wrap` && e.target.className !== `${cBase}cancel-btn`) || (showEditArea(!1), setCompValue(editArea_cfg.oldData)); } function confirmEdit() { const callback = editArea_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 = editArea_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(editArea_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); })(), editArea_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 && ((editArea_cfg.oldData = getAllData()), "function" == typeof callback) ) { if (!1 === callback(editArea_cfg.oldData)) return; } (editArea_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 && (editArea_cfg.callback = callback); } function toPageObj(settings) { 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) => { const comp = { id: item.key, type: item.compType, title: item.title || "", desc: item.txt.replaceAll("\n", "<br>").trim() || "", name: item.key, value: item.value, base: item.base, }; if ("textarea" === comp.type) (comp.ph = item.base), (comp.width = item.compW), (comp.height = item.compH), (comp.ctrlTt = "默认: " + item.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 showSettings() { const settings = info.settings; info.settingsArea || (info.settingsArea = createEditEle( (function getEditInfo() { return { w: "500px", contentH: "450px", resetTT: "重置所有设置项为默认值", page: toPageObj(info.settings), }; })() )), (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), getData(); showEditArea(!0, { resetBefore: () => confirm("是否重置所有设置项为默认值?"), confirmBefore: () => {}, finished: (data) => { console.log(data); if ( (function isValueChange() { const curData = getAllData(); return ( JSON.stringify(curData) !== JSON.stringify(editArea_cfg.oldData) ); })() ) { for (const pageName in data) { const page = data[pageName]; for (const key in page) { const value = page[key], flag = key.replace(info.base_id, ""), item = settings[flag]; let verifyFn; switch (key) { case settings.isHiddenBtn.key: case settings.isRetractList.key: break; case settings.position.key: verifyFn = (newVal) => newVal || settings.position.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.scale.key: verifyFn = (newVal) => +newVal ? newVal : settings.scale.base; break; case settings.sendKeys.key: case settings.addItemKeys.key: verifyFn = (newVal) => newVal.replaceAll(" ", "").toLowerCase(); break; case settings.zanListIsDesc.key: case settings.histListIsDesc.key: case settings.sukiListIsDesc.key: case settings.isHiddenList.key: break; case settings.listMaxLen.key: verifyFn = (newVal) => +newVal ? newVal : settings.listMaxLen.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; } if (!item) return void console.log("设置的数据对应的对象获取失败"); setValue({ value, base: item.base, key, verification: verifyFn, getValue: GM_getValue, setValue: GM_setValue, }); } } history.go(0); } }, }); } 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; } let searchBox, searchEndTimerId, msgBox, msgDom, msgId, useOne, msgZIndex, msgTimerId, msgEndTimerId; function createSearch({ id = "history-search-box", box = document.body, title = "以'标题='开头表示按标题搜索, '内容='表示按内容搜索, '描述='表示按描述搜索, '日期='表示按日期搜索", 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, } = {}) { 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); })), box.appendChild(ele), (function bindSearchEvents(ele) { const inputEle = ele.textEle, searchBtn = ele.btnEle; let timerId; searchBtn.addEventListener("click", () => { searchEle(); }), inputEle.addEventListener("keydown", (e) => { (13 !== e.keyCode && "enter" !== e.key.toLowerCase()) || 0 == +ele.style.opacity || searchEle(); }), inputEle.addEventListener("input", () => { ele.isAutoSearch && (clearTimeout(timerId), (timerId = setTimeout(() => { searchEle(); }, ele.interval))); }); })(ele), (searchBox = ele), ele ); } function showSearchBox(isShow = !0, originEle = null) { const ele = searchBox; if (isShow) { let left, top, scrollTop; if ((clearTimeout(searchEndTimerId), originEle)) { const rect = originEle.getBoundingClientRect(); (left = rect.left), (top = rect.top), (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 = "日期"), text && console.log("搜索" + searchType + ": " + text); const liArr = listEle.querySelectorAll(".item-box"), len = liArr.length; for (let i = 0; i < len; i++) { const item = liArr[i]; text ? ("标题" === searchType && item.querySelector(".item-tt").innerText.includes(text)) || ("描述" === searchType && item.querySelector(".item-tt").title.includes(text)) || ("内容" === searchType && item.querySelector(".hItem").innerText.includes(text)) || ("日期" === searchType && item.querySelector(".item-control").title.includes(text)) ? (item.style.display = "block") : (item.style.display = "none") : (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 = "", 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, 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, } = {}) { const ele = document.createElement("div"); (ele.title = "点击关闭该弹窗"), (ele.id = id), (ele.className = id), (msgId = id), (ele.style.cssText = `max-width: ${maxWidth}px;\nbackground: ${bg};\nmargin-bottom: 10px;\nborder: ${bd};\npadding: ${pd};\nbox-sizing: border-box;\nborder-radius: ${radius}px;\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"); (ele.ttEle = ttEle), (ttEle.style.color = tt_color), (ttEle.style.fontSize = tt_fontSize + "px"); 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.style.cssText = `\ndisplay: flex;\nflex-direction: column;\nposition: fixed;\nleft: -2000px;\ntop: 0;\nz-index: ${ isUseOne ? msgZIndex : zIndex };`), box.appendChild(msgBox)), msgBox.appendChild(ele), ele.addEventListener("click", () => { ele.remove(); }), ele ); })())), (msg = content || msg); const msgEle = ele.msgEle; (msgEle.innerText = msg), 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"), (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)); } const edit = { isEditing: !1, editText: {}, eleList: {}, callback: { confirmBefore: null, finished: null }, }, eleList = edit.eleList; 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), 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), 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, control_info = control.info; if ( (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; listEle !== searchEle.listEle && (isShow = !0), isShow && message({ title: search.text, msg: search.title }), (searchEle.textEle.value = ""), (searchEle.listEle = listEle), (searchEle.textEle.searchType = search.searchType), showSearchBox(isShow, search.ele), 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); }); } 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) ); 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(() => { uploadObj && 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) => { uploadFile.isUploading = !1; if (!confirm(uploadFile.submitText)) return; info.dataList = JSON.parse(data.data || null) || []; 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) ), 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 = listEle.list_info.outName || listEle.list_info.saveName || "dataList"; outFile.isTime && (outName = formatDate({ timestamp: new Date().getTime(), isExact: !0, midDelimiter: "-", delimiter2: ".", }) + " " + outName); updateDataList(info) && initHisListDom(info), info.dataList.forEach((item) => { item.desc = item.desc .replaceAll("'", "'") .replaceAll(""", '"'); }), (function saveJson({ data = "", fileName = "outData", type = "json", } = {}) { "string" != typeof data && "json" === type && (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); })({ data: info.dataList, fileName: outName }), 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++) { textArr[i].style.maxHeight = newH; } listEle.display = "block"; } const fold = control_info.fold, list_info = listEle.list_info; 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) => { confirm(del.warnText) && (!(function delItem({ info, id, ele } = {}) { const newDataList = updateDataList(info), listEle = info.listEle, dataList = info.dataList; if (!id && !ele && !(ele = listEle.curClickEle)) return; ele ? (id = ele.id) : (ele = listEle.querySelector(`[id='${id}'`)); const len = dataList.length; for (let i = 0; i < len; i++) if (+dataList[i].id == +id) { const del = dataList.splice(i, 1); console.log("删除一项", del[0]); break; } updateDateFlag(info), newDataList ? initHisListDom(info) : (ele.parentElement.remove(), resetNum(listEle), 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("'", "'") .replaceAll(""", '"')), (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(); })( (function domToText(ele) { const dom = document.createElement("div"); document.body.appendChild(dom), (dom.innerHTML = ele.innerHTML); const arr = dom.querySelectorAll("img"); 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; })(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.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.borderColor = 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 resetNum(listEle, liArr = []) { 0 === liArr.length && (liArr = listEle.getElementsByClassName("item-box")); const len = liArr.length; for (let i = 0; i < len; i++) liArr[i].querySelector(".num").innerHTML = getNum( listEle.list_info.isDesc, !1, len, i ); } 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 = "") { "btn" === name ? (info.btnEle.style.display = "none") : ("list" === name || ("显示" !== info.btnEle.btn_info.showMode && (info.btnEle.style.display = "none")), (info.listEle.parentElement.style.transform = "scaleY(0)")), (info.btnEle.style.borderColor = "#ccc"), setBtnColor(info.listEle, info.btnEle), showSearchBox(!1); } function initHisListDom(info) { const listEle = info.listEle; let curTxt, 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; list_info.isDelete && dataList.length > maxLen && dataList.splice(0, dataList.length - maxLen); const isDesc = list_info.isDesc, isAddUp = list_info.isAddUp; let htmlItem; const len = dataList.length, liMaxH = list_info.liMaxHeight, num_color = list_info.num_color, tt_color = list_info.tt_color, initItemFn = info.callback.initListItem; dataList.forEach((item, i) => { if (initItemFn) { const newVal = initItemFn(item); newVal && (item = dataList[i] = newVal); } (curTxt = item.value), item.replaceArr && item.replaceArr.forEach((rp) => { curTxt = curTxt.replaceAll(rp.flag, rp.value); }), (curTxt = curTxt.replaceAll("\n", "<br>")); const desc = item.desc .replaceAll("'", "'") .replaceAll('"', """); (htmlItem = `<div class="item-box"><div class="item-control" title="${formatDate( { timestamp: item.id || new Date().getTime(), 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}">${ item.title || "" }</span></div><div id="${ item.id }" class="hItem" style="max-height:${liMaxH}px">${curTxt}</div></div>`), isAddUp ? (curHtml = htmlItem + curHtml) : (curHtml += htmlItem); }), (listEle.innerHTML = curHtml), bottomText(info), info.updateDate || (info.updateDate = getValue({ base: new Date().getTime(), key: list_info.list_id + "_updateDate", getVal: list_info.getValue, setVal: list_info.setValue, })); } function addItem({ info, title = "", desc = "", showVal = "", value, id, data, isUpdateDom = !0, } = {}) { if (!value && !data) return -1; updateDataList(info) && 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, showVal, 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: !0 })); 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 && (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; (deleteId || isOverLenDel) && (liArr = listEle.getElementsByClassName("item-box")), deleteId && listEle.querySelector(`[id='${deleteId}'`).parentElement.remove(), isOverLenDel && liArr[liArr.length - 1].remove(), (function addLi(info, item) { if (!item.value) return; const listEle = info.listEle, dataList = info.dataList, list_info = listEle.list_info; let curTxt = item.value; item.replaceArr && item.replaceArr.forEach((rp) => { curTxt = curTxt.replaceAll(rp.flag, rp.value); }), (curTxt = curTxt.replaceAll("\n", "<br>")); const hItem = document.createElement("div"), desc = item.desc .replaceAll("'", "'") .replaceAll('"', """); (hItem.className = "item-box"), (hItem.innerHTML = `<div class="item-control" title="${formatDate({ timestamp: item.id || new Date().getTime(), isExact: !0, delimiter2: "时分秒", })}" style="color:${ list_info.tt_color };"><span class="num">${getNum( list_info.isDesc, list_info.isAddUp, dataList.length, dataList.length - 1 )}</span> <span title="${desc}" class="item-tt" style="color:${ list_info.tt_color }">${item.title || ""}</span></div><div id="${ item.id }" class="hItem" style="max-height:${ list_info.liMaxHeight }px">${curTxt}</div>`), list_info.isAddUp ? listEle.insertBefore(hItem, listEle.children[0]) : listEle.querySelector(".bottom_text") ? listEle.insertBefore( hItem, listEle.children[listEle.children.length - 1] ) : listEle.appendChild(hItem); resetNum(listEle), bottomText(info); })(info, curItem); } return { deleteId, isOverLenDel }; } function getItemData({ info, id, ele } = {}) { if ( (updateDataList(info) && 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 = "", replaceArr, 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); newDataList && initHisListDom(info); replaceArr = (data = { id, title, desc, value, replaceArr, ...getItemData({ info, id }), ...data, }).replaceArr; 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; } if ((updateDateFlag(info), !newDataList)) { const tt = ele.parentElement.querySelector(".item-tt"); (tt.innerHTML = getTitle({ text: data.title })), (tt.title = data.desc .replaceAll("'", "'") .replaceAll('"', """)); let curTxt = data.value; replaceArr && replaceArr.forEach((rp) => { curTxt = curTxt.replaceAll(rp.flag, rp.value); }), (curTxt = curTxt.replaceAll("\n", "<br>")), (ele.innerHTML = curTxt), newId && (ele.id = newId); } if (isSave) { const list_info = info.listEle.list_info; list_info.setValue ? list_info.setValue(list_info.saveName, JSON.stringify(dataList)) : localStorage.setItem(list_info.saveName, JSON.stringify(dataList)); } 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, }); } 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({ 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({ key: list_info.saveName, base: "[]", valType: "array", getVal: list_info.getValue, setVal: list_info.setValue, }); return (info.dataList = dataList), dataList; } 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)) { updateDataList(info) && initHisListDom(info); } (listEle.parentElement.style.transform = isClicked ? "scaleY(1)" : "scaleY(0)"), setBtnColor(listEle, btnEle, isClicked), showSearchBox(!1), changeShow(listEle.list_info.control.move_eleList, !1), 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 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 .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 .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: 135px;\n max-height: 180px;\n height: 180px;\n display: block;\n margin: 4px auto;\n border-radius: 6px;\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}", 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}"; 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 = `\n${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};` + 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, controlCfg, controlArr = [], getValue, setValue, } = {}) { if (!box) return; getValue || (getValue = localStorage.getItem), setValue || (setValue = localStorage.setItem), "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"); (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, }), (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 = `width: ${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, }); const defaControls = { add: { name: "add", text: "添加", type: "top", title: "添加一项记录至列表末尾", class: "control-add", noneText: "请填写内容!!", endText: "添加成功", }, search: { name: "search", text: "搜索", type: "top", searchType: "标题", title: "搜索所有记录的标题, 若要按描述搜索请先输入'描述=', 按内容搜索输入'内容=', 按日期搜索输入'日期='", class: "control-search", }, 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", startTipText: "导入数据后当前列表数据将会被覆盖, 建议导入数据前先备份数据", submitText: "导入数据后当前列表数据将会被覆盖, 建议导入数据前先备份数据, 是否确认导入?", uploadingText: "当前已存在上传任务", timeoutText: "文件上传超时", endText: "导入成功", isUploading: !1, }, out: { name: "out", text: "导出", type: "top", title: "将列表的所有记录导出为json文件", class: "control-out", startText: "开始下载", isTime: !0, isFormat: !1, }, 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: "删除成功", }, 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", }, custom: { name: "custom", text: "未定", type: "top", class: "control-custom", }, }; return ( 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 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 || (css = `\n fill:${ color || icon.color || icons.base.fill };\n width:${ width || icon.width || icons.base.width };\n height:${ height || icon.height || icons.base.height };\n margin-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>', }); const pageType = getBiliPageType(window.location); console.log("当前页面:", pageType), "其他" !== pageType && ((document.comment_list_info = info), (info.pageType = pageType), (function setZIndex(val) { msgZIndex = val; })(12e3), (info.edit = (function editArea_createEditEle({ id, box, placeholder = { title: "请输入标题", desc: "请输入描述", value: "请输入内容", }, zIndex = 2e3, } = {}) { 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 = '<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>'), (eleList.wrap.style.display = "none"), (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) { ("ll-edit-wrap" !== e.target.className && "cancel-btn" !== e.target.className) || (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 ); })({ placeholder: { title: "请输入标题", desc: "请输入描述\n鼠标对准标题时将显示描述信息\n鼠标对准序号时将显示日期", value: "请 输 入 内 容", }, zIndex: 12e3, })), getData(), addCss( (function getCss() { const position = settings.position.value.split(/,|,|x|X/), pBase = 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 opacity: ${ +settings.hiddenBtnTime.value <= 0 ? 0 : 1 };\n transform: scale(${ 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 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:all 0.5s;\n transform:scaleX(0);\n transform-origin:left top;\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 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}\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}\n#${ doms.box.id } .img-item {\n min-width: 135px;\n max-width: 180px;\n height: 180px;\n display: block;\n margin: 4px auto;\n border-radius: 6px;\n cursor: zoom-in;\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(); }); })(), "首页" !== pageType && "搜索" !== pageType && (function main() { const pageType = info.pageType, curInfo = info.customKeys, settings = info.settings, classList = curInfo.classList; 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) { for (let i = 0; i < 2; i++) if ((dom = dom.parentElement).classList.contains(boxClass)) return dom; return 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; } } } 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.btn) }) : {} ); } 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.btn) }) : 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; if ( ((data.title = `${shortTime} [${pageType}] ${listTitle}`), (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)) : "主页" === pageType ? (data.desc += "\n主页名称: " + listTitle) : "动态" === pageType ? (data.desc += "\n动态名称: " + listTitle) : "专栏" === pageType ? (data.desc += "\n专栏名称: " + listTitle) : "番剧" === pageType && (data.desc += "\n番剧名称: " + listTitle), (data.desc += `\n评论用户: ${data.user ? data.user : "自己"}`), data.uid && (data.desc += `\nUID: ${data.uid}`), allData.replyUser && ((data.desc += `\n回复用户: ${allData.replyUser}`), allData.replyUid && (data.desc += `\nUID: ${allData.replyUid}`)), 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 (data.desc += "\n评论地址: " + data.url), data; } function getText(dom) { const nodeArr = dom.childNodes, allData = { data: {}, imgArr: [] }; let text = ""; const pType = pageType, classList = curInfo.classList, curClass = curInfo.curClassList, replaceArr = []; 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 = classList.smallEmoji, imgBig = classList.largeEmoji, icon = classList.icon; nClassList && (nClassList.contains(imgSmall) ? (className = imgSmall) : nClassList.contains(imgBig) ? (className = imgBig) : nClassList.contains(icon) ? (iconNum++, (className = icon + "-item"), (flag = `[icon--${iconNum}]`)) : (imgNum++, (flag = `[image--${imgNum}]`), allData.imgArr.push(src))), (text += flag), replaceArr.find((i) => i.flag === flag) || replaceArr.push({ flag, value: `<img class="${className}" src="${src}" alt="${flag}">`, }); } else if ("a" === tag) { const search = classList.search; if (nClassList.contains(search)) continue; const url = node.href || node.dataset.url, className = "a-item", flag = `[${node.textContent}]`; (text += flag), replaceArr.find((i) => i.flag === flag) || replaceArr.push({ flag, value: `<a class="${className}" href="${url}" target="_blank" title="点击跳转到链接地址">${node.textContent}</a>`, }); } else "专栏" === pType ? node.dataset && node.dataset[curClass.replyUser.value] && ((allData.replyUser = node.textContent.replace( "@", "" )), (allData.replyUid = node.dataset[curClass.replyUser.value])) : nClassList && nClassList.contains(curClass.replyUser) && ((allData.replyUser = node.textContent.replace( "@", "" )), (allData.replyUid = node.dataset ? node.dataset.userId : "")), (text += node.textContent); } const image = dom.parentElement.parentElement.querySelector( "." + curInfo.classList.image ); if (image) { imgNum++; const dom = image.querySelector("img"); if (!dom) return; let src = dom.src; "//" === src.slice(0, 2) && (src = window.location.protocol + src); const bigImgUrl = src.split("@")[0] + "@" + info.history.imgSuffix; allData.imgArr.push(bigImgUrl); const flag = `[image-${imgNum}]`; (text += flag), replaceArr.push({ flag, value: `<img class="img-item" src="${src}" data-bigimg="${bigImgUrl}" alt="${dom.alt}" title="点击查看原图">`, }); } } return ( (allData.data.value = text), replaceArr.length > 0 && (allData.data.replaceArr = replaceArr), allData ); } function addComment({ info, doms, replyDom, replyBox, isSub, originType, } = {}) { let data, allData = { data: {} }; if (replyDom || replyBox) { if ( !replyDom && replyBox && ((replyDom = isSub ? replyBox.querySelector("." + curInfo.curClassList.subReply) : replyBox.querySelector("." + curInfo.curClassList.reply)) || (console.log("评论的文本区域的元素获取失败"), (replyDom = document.activeElement.parentElement)), !replyDom) ) return; const userDom = (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 = "专栏" === pageType ? isSub ? box.querySelector("." + curClass.subUser) : box.querySelector("." + curClass.user) : isSub ? (replyBox = box.parentElement).querySelector( "." + curClass.subUser ) : (replyBox = box.parentElement.parentElement).querySelector( "." + curClass.user ); } return userDom; })({ replyDom, replyBox, isSub }); if (userDom) if ("消息" === pageType) { allData.data.user = userDom.textContent; const userUrlArr = userDom.querySelector("a").href.split("/"); allData.data.uid = userUrlArr ? userUrlArr[userUrlArr.length - 1] : ""; } else { const location = window.location; let curUrl = location.href; (allData.data.user = userDom.innerText), (allData.data.uid = userDom.dataset.userId || userDom.dataset.usercardMid), (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("评论用户的数据获取失败"); const subAllData = getText(replyDom); (allData.originType = originType || "收藏"), (allData.replyUser = subAllData.replyUser), (allData.replyUid = subAllData.replyUid), (allData.imgArr = subAllData.imgArr), (allData.data.value = subAllData.data.value), subAllData.data.replaceArr && (allData.data.replaceArr = subAllData.data.replaceArr), (data = getCommentInfo(allData)); } else (allData.originType = "评论"), (allData.data = { value: doms.textarea.value }), (data = getCommentInfo(allData)); addItem({ info, data }); } function isLikeBtn(dom) { 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 && parent.classList.contains(curClass.likeBtn) && ((flag = !0), (replyBox = parent.parentElement.parentElement.parentElement)); } else if ("专栏" === pageType) { if ("i" === tag) parent = dom.parentElement; else { if ("span" !== tag) return { value: !1 }; dom.classList && dom.classList.contains(curClass.liked) ? ((parent = dom), (flag = !0)) : (parent = dom.parentElement); } if (parent.classList.contains(curClass.liked)) return { value: !1 }; parent.classList && ((replyBox = parent.parentElement.parentElement), replyBox.classList.contains(curClass.subReplyP) && (isSub = !0), parent.classList.contains(curClass.likeBtn) ? (flag = !0) : parent.classList.contains(curClass.subLikeBtn) && (flag = isSub = !0)); } 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 && dom.classList.contains(curClass.likeBtn) ? ((parent = dom), (flag = !0)) : (parent = dom.parentElement); } let likeDom = parent.querySelector("i"); if (likeDom && likeDom.classList.contains(curClass.liked)) return { value: !1 }; parent.classList && (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) { let isSub = !1; const curClass = curInfo.curClassList; let flag = e.target.classList.contains(curClass.reply); flag || curClass.reply === curClass.subReply || ((flag = e.target.classList.contains(curClass.subReply)), (isSub = flag)); let replyDom = flag ? e.target : null; if ( (replyDom || ((flag = e.target.parentElement.classList.contains( curClass.reply )), flag || curClass.reply === curClass.subReply || ((flag = e.target.parentElement.classList.contains( curClass.subReply )), (isSub = flag)), (replyDom = flag ? e.target.parentElement : null)), flag) ) { if (!verifyKeys(e, null, settings.addItemKeys.value)) return; message({ title: "收藏", msg: "已添加评论到收藏列表" }), addComment({ 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), document.activeElement.blur(), doms.textarea.blur(), (curInfo.isBtnClickEvent = !1), btn.click(), addComment({ info: info.history.data, doms }), (curInfo.isBtnClickEvent = !0)); } function clickBtn() { curInfo.isBtnClickEvent && addComment({ info: info.history.data, doms: curInfo.curDoms }); } function clickHandle(e) { const target = e.target, result = isLikeBtn(target); if (result.value) return void addComment({ 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; if ( ((curInfo.curTextarea = textarea || target), (curInfo.curDoms = getSendDoms( curInfo.curClassList, curInfo.curTextarea )), (doms = curInfo.curDoms), !doms.btn) ) return void (curInfo.curTextarea = null); (curInfo.curSendBtn = doms.btn), doms.btn.addEventListener("click", clickBtn, !0); } } function magClickHandle(e) { const target = e.target, result = isLikeBtn(target); if (result.value) addComment({ 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; (curInfo.curDoms = doms), (curInfo.curSendBtn = btn), addComment({ info: info.history.data, doms }); } } curInfo.curClassList, (function main() { curInfo.curClassList = classList[pageType]; const clickFn = "消息" === pageType ? magClickHandle : clickHandle; document.addEventListener("click", clickFn, !0), document.addEventListener("dblclick", dblClickHandle, !0), document.addEventListener("keydown", handleKeyDown); })(); })(), (function commentHistory_main() { !(function commentHistory_getData() { const zanList = JSON.parse( GM_getValue(commentHistory_curInfo.zan_info.saveName) || null ) || [], dataList = JSON.parse( GM_getValue(commentHistory_curInfo.data.saveName) || null ) || [], suki_dataList = JSON.parse( GM_getValue(commentHistory_curInfo.suki_info.saveName) || null ) || []; (commentHistory_curInfo.zan_info.dataList = zanList), (commentHistory_curInfo.data.dataList = dataList), (commentHistory_curInfo.suki_info.dataList = suki_dataList); })(), (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: 12e3, })), (function createHisBtnList() { const settings = info.settings, 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/); let w, h; 1 === wh.length ? (w = h = +wh[0].trim() || +whBase[0].trim()) : ((w = +wh[0].trim() || +whBase[0].trim()), (h = +wh[1].trim() || +whBase[1].trim())); let zan_commentListInfo = createHistoryList({ list_id: "ll_comment_zanList", box: commentHistory_doms.options.ele, width: w, maxHeight: h, fontSize: commentHistory_curInfo.fontSize - 2, right: -170, top: 35, saveName: commentHistory_curInfo.zan_info.saveName, outName: commentHistory_doms.zan_comment.option.text, maxLen: settings.listMaxLen.value, listTitle: "双击跳转到评论来源的页面", initialText: "暂无评论记录", isDesc: settings.zanListIsDesc.value, isAddUp: settings.zanListIsDesc.value, isDelete: !!settings.listMaxLen.value, isScrollStyle: !1, isDataSync: !0, isClickClose: settings.isHiddenList.value, setValue: GM_setValue, getValue: GM_getValue, controlArr: [ { name: "add" }, { name: "search", title: "搜索所有评论的内容, 若要按标题搜索请先输入'标题=', 按描述搜索输入'描述=', 按日期搜索输入'日期='", }, { name: "clear" }, { name: "out" }, { name: "import" }, { name: "fold" }, { name: "toBottom" }, { name: "custom", text: "设置", callback: showSettings, title: "打开插件设置界面", }, { name: "update" }, { name: "move", warnText: "" }, { name: "toSuki" }, { name: "copy" }, { name: "delete" }, ], }), commentListInfo = createHistoryList({ list_id: "ll_comment_list", box: commentHistory_doms.options.ele, width: w, maxHeight: h, fontSize: commentHistory_curInfo.fontSize - 2, right: -241, top: 35, cssText: "none", saveName: commentHistory_curInfo.data.saveName, outName: commentHistory_doms.comment.option.text, maxLen: settings.listMaxLen.value, listTitle: "双击跳转到评论来源的页面", initialText: "暂无评论记录", isDesc: settings.histListIsDesc.value, isAddUp: settings.histListIsDesc.value, isDelete: !!settings.listMaxLen.value, isScrollStyle: !1, isDataSync: !0, isClickClose: settings.isHiddenList.value, setValue: GM_setValue, getValue: GM_getValue, controlArr: [ { name: "add" }, { name: "search", title: "搜索所有评论的内容, 若要按标题搜索请先输入'标题=', 按描述搜索输入'描述=', 按日期搜索输入'日期='", }, { name: "clear" }, { name: "out" }, { name: "import" }, { name: "fold" }, { name: "toBottom" }, { name: "custom", text: "设置", callback: showSettings, title: "打开插件设置界面", }, { name: "update" }, { name: "move", warnText: "" }, { name: "toSuki" }, { name: "copy" }, { name: "delete" }, ], }), suki_commentListInfo = createHistoryList({ list_id: "ll_comment_cukiList", box: commentHistory_doms.options.ele, width: w, maxHeight: h, fontSize: commentHistory_curInfo.fontSize - 2, right: -315, top: 35, cssText: "none", saveName: commentHistory_curInfo.suki_info.saveName, outName: commentHistory_doms.suki_comment.option.text, maxLen: settings.listMaxLen.value, listTitle: "双击跳转到评论来源的页面", initialText: "暂无收藏评论", isDesc: settings.sukiListIsDesc.value, isAddUp: settings.sukiListIsDesc.value, isDelete: !1, isScrollStyle: !1, isDataSync: !0, isClickClose: settings.isHiddenList.value, setValue: GM_setValue, getValue: GM_getValue, controlArr: [ { name: "add" }, { name: "search", title: "搜索所有评论的内容, 若要按标题搜索请先输入'标题=', 按描述搜索输入'描述=', 按日期搜索输入'日期='", }, { name: "clear" }, { name: "out" }, { name: "import" }, { name: "fold" }, { name: "toBottom" }, { name: "custom", text: "设置", callback: showSettings, title: "打开插件设置界面", }, { name: "update" }, { name: "move", warnText: "" }, { name: "copy" }, { name: "delete" }, ], }); (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 ); })(), (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 commentHistory_bindEvents() { let startTimer, timer, startTime = +info.settings.hiddenBtnTime.value, closeListTime = +info.settings.closeListTime.value; info.settings.isHiddenBtn.value && startTime > 0 && (startTimer = setTimeout(() => { commentHistory_doms.box.ele.style.opacity = 0; }, startTime)), (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_doms.box.ele.addEventListener("mouseenter", () => { (commentHistory_doms.box.ele.style.opacity = 1), timer && clearTimeout(timer), startTimer && clearTimeout(startTimer); }), commentHistory_doms.box.ele.addEventListener("mouseleave", () => { info.settings.isHiddenBtn.value && (commentHistory_doms.box.ele.style.opacity = 0), info.settings.isRetractList.value && (closeListTime > 0 ? (timer = setTimeout(() => { hiddenBtnList(commentHistory_curInfo.zan_info), hiddenBtnList(commentHistory_curInfo.data), hiddenBtnList(commentHistory_curInfo.suki_info); }, closeListTime)) : (hiddenBtnList(commentHistory_curInfo.zan_info), hiddenBtnList(commentHistory_curInfo.data), hiddenBtnList(commentHistory_curInfo.suki_info))); }), commentHistory_doms.btn.ele.addEventListener("click", () => { const isClose = commentHistory_doms.options.ele.classList.contains("opened"); commentHistory_doms.btn.ele.classList.toggle("opened"), commentHistory_doms.options.ele.classList.toggle("opened"), hiddenBtnList(commentHistory_curInfo.zan_info), hiddenBtnList(commentHistory_curInfo.data), hiddenBtnList(commentHistory_curInfo.suki_info), isClose ? (changeShow( commentHistory_curInfo.zan_info.listEle.list_info .control.move_eleList, !1 ), changeShow( commentHistory_curInfo.data.listEle.list_info.control .move_eleList, !1 ), changeShow( commentHistory_curInfo.suki_info.listEle.list_info .control.move_eleList, !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)) : ((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.btnEle.addEventListener( "click", () => { hiddenBtnList(commentHistory_curInfo.data), hiddenBtnList(commentHistory_curInfo.suki_info); } ), commentHistory_curInfo.data.btnEle.addEventListener( "click", () => { hiddenBtnList(commentHistory_curInfo.zan_info), hiddenBtnList(commentHistory_curInfo.suki_info); } ), commentHistory_curInfo.suki_info.btnEle.addEventListener( "click", () => { hiddenBtnList(commentHistory_curInfo.zan_info), hiddenBtnList(commentHistory_curInfo.data); } ), (commentHistory_curInfo.zan_info.callback.clickItem = commentHistory_curInfo.data.callback.clickItem = commentHistory_curInfo.suki_info.callback.clickItem = (data) => { data.url && window.open(data.url); }); })(); })()); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址