V2Next-Mobile

楼中楼、简洁模式、高赞回复排序、查看回复上下文、发送图片和表情、UI美化、base64 解码等功能

目前为 2024-01-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name V2Next-Mobile
  3. // @namespace http://tampermonkey.net/
  4. // @version 8.0.5
  5. // @author zyronon
  6. // @description 楼中楼、简洁模式、高赞回复排序、查看回复上下文、发送图片和表情、UI美化、base64 解码等功能
  7. // @license GPL License
  8. // @icon https://v2next.netlify.app/favicon.ico
  9. // @homepage https://github.com/zyronon/web-scripts
  10. // @homepageURL https://github.com/zyronon/web-scripts
  11. // @supportURL https://update.greasyfork.org/scripts/485356/V2Next-Mobile.user.js
  12. // @match https://v2ex.com/
  13. // @match https://v2ex.com/?tab=*
  14. // @match https://v2ex.com/t/*
  15. // @match https://v2ex.com/recent*
  16. // @match https://v2ex.com/go/*
  17. // @match https://v2ex.com/member/*
  18. // @match https://v2ex.com/changes*
  19. // @match https://*.v2ex.com/
  20. // @match https://*.v2ex.com/?tab=*
  21. // @match https://*.v2ex.com/t/*
  22. // @match https://*.v2ex.com/recent*
  23. // @match https://*.v2ex.com/go/*
  24. // @match https://*.v2ex.com/member/*
  25. // @match https://*.v2ex.com/changes*
  26. // @require http://code.jquery.com/jquery-3.7.1.min.js
  27. // @require https://cdn.jsdelivr.net/npm/vue@3.4.14/dist/vue.global.prod.js
  28. // @grant GM_addStyle
  29. // @grant GM_notification
  30. // @grant GM_openInTab
  31. // @grant GM_registerMenuCommand
  32. // ==/UserScript==
  33.  
  34. (e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const o=document.createElement("style");o.textContent=e,document.head.append(o)})(' .tip[data-v-ee672411]{position:fixed;font-size:1.6rem;z-index:9999;max-width:10rem;border-radius:.5rem;padding:1rem;color:var(--color-font-8);background:var(--color-tooltip-bg);box-shadow:0 0 6px 1px var(--color-tooltip-shadow)}.v-enter-active[data-v-e7c0fbef],.v-leave-active[data-v-e7c0fbef]{transition:opacity .3s ease}.v-enter-from[data-v-e7c0fbef],.v-leave-to[data-v-e7c0fbef]{opacity:0}.fade-in[data-v-e7c0fbef]{animation:fade-in-e7c0fbef .3s}.fade-out[data-v-e7c0fbef]{animation:fade-out-e7c0fbef .4s}@keyframes fade-in-e7c0fbef{0%{opacity:0}to{opacity:1}}@keyframes fade-out-e7c0fbef{0%{opacity:1}to{opacity:0;display:none}}.username[data-v-e7c0fbef]{font-weight:700;font-size:1.4rem;margin-right:1rem}.link-num[data-v-e7c0fbef]{font-size:1.4rem;color:var(--color-font-8);color:#e02a2a}.owner[data-v-e7c0fbef]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.mod[data-v-e7c0fbef]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;transform:scale(.8);background:#1484cd;color:#fff;margin-right:1rem}.my-tag[data-v-e7c0fbef]{font-size:1.4rem;color:red;margin-left:1rem}.my-tag .remove[data-v-e7c0fbef]{margin-left:.5rem;display:none}.add-tag[data-v-e7c0fbef]{font-size:2.4rem;transform:translateY(.2rem);line-height:1rem;display:inline-block;margin-left:1rem;position:absolute;display:none}.floor[data-v-e7c0fbef]{font-size:1.1rem;line-height:1rem;border-radius:.5rem;display:inline-block;color:var(--color-floor-font);cursor:default;margin-right:1rem}.base-avatar[data-v-e7c0fbef]{margin-right:1rem;display:inline-flex}.base-avatar img[data-v-e7c0fbef]{width:2.8rem;height:2.8rem;border-radius:.4rem}html[data-v-e7c0fbef]{font-size:10px}[data-v-e7c0fbef]:root{--box-border-radius: 8px}#site-header[data-v-e7c0fbef]{height:4rem}#site-header #site-header-menu #menu-body[data-v-e7c0fbef]{top:5rem;right:1rem}#Wrapper .cell .count_livid[data-v-e7c0fbef]{font-size:14px;font-weight:700;padding:3px 10px;border-radius:5px}a[data-v-e7c0fbef]{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-user-select:none;-moz-user-focus:none;-moz-user-select:none}.post-item[data-v-e7c0fbef]{background:var(--box-background-color)}.post-item .new-item[data-v-e7c0fbef]{display:flex;justify-content:space-between}.post-item .new-item .left .top[data-v-e7c0fbef]{display:flex;align-items:center;line-height:1.2;gap:1rem}.post-item .new-item .left .small[data-v-e7c0fbef],.post-item .new-item .left a.node[data-v-e7c0fbef]{font-size:1.2rem}.post-item .new-item .left .bottom[data-v-e7c0fbef]{margin:1rem 0 .5rem}.post-item .new-item .left .bottom .item_title[data-v-e7c0fbef]{font-size:1.6rem}.post-item .new-item .left .bottom a[data-v-e7c0fbef]{text-decoration:none!important}.post-item .new-item .right[data-v-e7c0fbef]{min-width:5rem;display:flex;justify-content:flex-end;align-items:center}.post-item .new-item .right .count_livid[data-v-e7c0fbef]{font-size:1.4rem!important;margin-right:0;padding:.3rem 1rem!important;border-radius:.5rem!important}.post-item .post-content[data-v-e7c0fbef]{display:block;max-height:30rem;overflow:hidden;line-break:anywhere;-webkit-mask-image:linear-gradient(180deg,#000 60%,transparent);height:0;color:#000;text-decoration:none!important}.post-item .post-content blockquote[data-v-e7c0fbef]{margin-top:.5rem}.post-item .post-content p[data-v-e7c0fbef]:first-child{margin-top:0}.post-item .post-content[data-v-e7c0fbef]:visited{color:var(--link-visited-color)}.post-item .show-more[data-v-e7c0fbef]{font-size:1.3rem;text-align:right;height:3rem;align-items:center;justify-content:center;position:relative;z-index:9;display:none}.preview[data-v-e7c0fbef]{margin-bottom:.7rem;border-radius:var(--box-border-radius)}.preview .topic-link[data-v-e7c0fbef]:link{color:#000!important}.preview .show-all[data-v-e7c0fbef]{max-height:unset;-webkit-mask-image:none}.preview .post-content[data-v-e7c0fbef]{height:unset!important}.preview .show-more[data-v-e7c0fbef]{display:flex}.preview .item_title[data-v-e7c0fbef]{font-weight:700}.Night .post-item[data-v-e7c0fbef]{background:#18222d!important}.Night .preview[data-v-e7c0fbef]{border:1px solid #3b536e}.Night .preview>.post-content[data-v-e7c0fbef]:link{color:#d1d5d9}.Night .preview>.post-content[data-v-e7c0fbef]:visited{color:#393f4e!important}.Night .preview .topic-link[data-v-e7c0fbef]:link{color:#c0dbff!important}[data-v-e7c0fbef]:root{--color-main-bg: #e2e2e2;--color-second-bg: white;--color-third-bg: #e2e2e2;--color-four-bg: #e7e9eb;--color-item-bg: white;--color-swtich-bg: #dcdfe6;--color-active: #409eff;--color-font: #999;--color-font-8: rgba(0, 0, 0, .8);--color-font-3: rgba(0, 0, 0, .3);--color-font-pure: black;--color-input-bg: white;--color-input-border: #e2e2e2;--color-input-border-hover: #a3a6ad;--color-radio-border: #e2e2e2;--color-tooltip-bg: white;--color-tooltip-shadow: #bbbbbb;--color-scrollbar: #93ade3;--color-line: #e2e2e2;--color-line2: #cecece;--color-loading-1: #00000033;--color-loading-2: #000;--color-floor: #f0f0f0;--color-floor-font: #bdbdbd;--color-editor-toolbar: #f6f7f8;--color-sp-btn-bg: #f1f1f1;--color-call-list-bg: white;--space: 1rem}html.dark[data-v-e7c0fbef]{--color-main-bg: #22303f;--color-second-bg: #18222d;--color-third-bg: #31475e;--color-four-bg: #22303f;--color-item-bg: #18222d;--color-swtich-bg: #4c4d4f;--color-active: #409eff;--color-font: rgba(255, 255, 255, .5);--color-font-8: rgba(255, 255, 255, .8);--color-font-3: rgba(255, 255, 255, .3);--color-font-pure: white;--color-input-bg: #333333;--color-input-border: #6c6e72;--color-input-border-hover: #a3a6ad;--color-radio-border: #454847;--color-tooltip-bg: #31475e;--color-tooltip-shadow: #3b3b3b;--color-scrollbar: #5c5d5e;--color-line: var(--box-border-color);--color-loading-1: rgba(178, 177, 177, .2);--color-loading-2: #ffffff;--color-floor: #293b4d;--color-floor-font: rgba(255, 255, 255, .3);--color-editor-toolbar: var(--box-background-hover-color);--color-sp-btn-bg: #31475e;--color-call-list-bg: #31475e}.flex[data-v-e7c0fbef]{display:flex;align-items:center;justify-content:space-between}.flex-end[data-v-e7c0fbef]{justify-content:flex-end}.flex-center[data-v-e7c0fbef]{justify-content:center}.p1[data-v-e7c0fbef]{padding:1rem}.p2[data-v-e7c0fbef]{padding:2rem}.p0[data-v-e7c0fbef]{padding:0!important}body :is(.topic_content,.reply_content) a[href^=http][data-v-e7c0fbef]{text-underline-offset:.46ex;color:currentcolor;text-decoration:underline 1.5px}a[data-v-e7c0fbef]{text-decoration:none}.tool[data-v-e7c0fbef]{position:relative;display:flex;align-items:center;border-radius:.3rem;height:2.6rem;padding:0 .5rem;gap:.6rem}.tool>svg[data-v-e7c0fbef]{width:2.2rem!important;height:2.2rem!important}.tool.disabled[data-v-e7c0fbef]{cursor:not-allowed}.tool span[data-v-e7c0fbef]{line-height:1rem}.my-node[data-v-e7c0fbef]{border-radius:.2rem;padding:.4rem;font-size:1rem;color:#999;background:#f5f5f5}.msgs[data-v-e7c0fbef]{position:fixed;margin-left:calc(50% - 25rem);width:50rem;z-index:9999;bottom:0;left:0;right:0}.my-box[data-v-e7c0fbef]{background:var(--box-background-color);margin-bottom:.5rem;width:100%;overflow:hidden;box-sizing:border-box;transition:background-color .3s}.my-box .box-content[data-v-e7c0fbef]{padding:.5rem}.my-cell[data-v-e7c0fbef]{color:var(--color-font);height:4.2rem;padding:0 1rem;font-size:1.4rem;line-height:150%;text-align:left;border-bottom:1px solid var(--color-line)}.modal[data-v-e7c0fbef]{position:fixed;z-index:100;width:100vw;height:100vh;left:0;top:0;display:flex;justify-content:center;align-items:center}.modal .title[data-v-e7c0fbef]{font-size:2.4rem;margin-bottom:1rem;text-align:center}.modal .option[data-v-e7c0fbef]{display:flex;align-items:center;padding:.6rem 0}.modal .option>span[data-v-e7c0fbef]{position:relative}.radio-group2[data-v-e7c0fbef]{display:inline-flex;border-radius:.5rem;overflow:hidden;border:1px solid var(--color-radio-border);background:var(--box-background-alt-color)}.radio-group2 .radio[data-v-e7c0fbef]{background:transparent;padding:.5rem 1.2rem;border-left:1px solid var(--color-radio-border);font-size:1.3rem;color:var(--color-gray)}.radio-group2 .radio[data-v-e7c0fbef]:first-child{border-left:none}.radio-group2 .active[data-v-e7c0fbef]{background:var(--color-active);color:#fff}.pop-confirm[data-v-e7c0fbef]{position:relative;display:inline-flex;justify-content:center}input[data-v-e7c0fbef]{width:10rem;height:3rem;outline:unset;border:1px solid var(--color-input-border);padding:0 .5rem;border-radius:5px;box-sizing:border-box;transition:all .3s;background:var(--color-input-bg);color:var(--color-font)}input[data-v-e7c0fbef]:focus{border:1px solid var(--color-active)}.danger[data-v-e7c0fbef]{color:red!important}.topic_content[data-v-e7c0fbef],.reply_content[data-v-e7c0fbef]{font-size:1.6rem}.mask[data-v-e7c0fbef]{z-index:10;position:fixed;top:0;width:100vw;height:100vh;background:#000000bb}.mask.dark[data-v-e7c0fbef]{background:#000000bb}.mask.light[data-v-e7c0fbef]{background:transparent}.mask.lightgray[data-v-e7c0fbef]{background:rgba(0,0,0,.25)}.mask.white[data-v-e7c0fbef]{background:transparent}.slide[data-v-e7c0fbef]{flex:1;width:100vw;height:100vh;transition:height .3s;position:relative;overflow:hidden}.slide .slide-list[data-v-e7c0fbef]{height:100%;width:100%;display:flex;position:relative;transition:transform .3s}.slide .slide-list .slide-item[data-v-e7c0fbef]{height:100%;width:100%;flex-shrink:0;position:relative;overflow:auto}.page1[data-v-e7c0fbef]{overflow:hidden!important}.post-wrapper[data-v-e7c0fbef],.setting-wrapper[data-v-e7c0fbef]{position:absolute;left:0;top:0;height:100%;width:100%;background:var(--color-main-bg);overflow:auto}.setting-wrapper[data-v-e7c0fbef],.setting-wrapper2[data-v-e7c0fbef]{height:100%;overflow:hidden;background:var(--color-second-bg)}.mobile-page[data-v-e7c0fbef]{height:100%;overflow:hidden;font-size:1.8rem;display:flex;flex-direction:column}.mobile-page>.page-content[data-v-e7c0fbef]{padding:1rem;padding-top:0;box-sizing:border-box;overflow:auto}.switch[data-v-e7c0fbef]{width:4.5rem;height:2.2rem;border-radius:2rem;position:relative;display:flex;align-items:center;background:var(--color-swtich-bg);transition:all .3s}.switch.active[data-v-e7c0fbef]{background:var(--color-active)}.switch.active[data-v-e7c0fbef]:before{right:.2rem}.switch[data-v-e7c0fbef]:before{position:absolute;content:" ";transition:all .3s;right:calc(100% - 2rem);width:1.8rem;height:1.8rem;background:white;border-radius:50%}.nav-bar[data-v-fda0acaa]{box-sizing:border-box;width:100%;height:5rem;padding:0 var(--space);display:flex;align-items:center;justify-content:center;position:relative;font-size:2rem;color:var(--color-font-pure)}.nav-bar[data-v-fda0acaa] .back-icon{left:var(--space);position:absolute}.display-type[data-v-1d327f48]{height:3rem;padding:0 .3rem;background:var(--color-main-bg);border-radius:1rem;display:flex;font-size:1.4rem;align-items:center;color:#a9a9a9}.display-type .type[data-v-1d327f48]{border-radius:.8rem;padding:0 1.3rem;height:2.5rem;align-items:center;display:flex;position:relative}.display-type .type.active[data-v-1d327f48]{background:var(--color-second-bg);color:var(--color-font-pure);box-shadow:0 0 6px 0 var(--color-tooltip-shadow)}.display-type .type-list[data-v-1d327f48]{position:absolute;background:white;right:0;top:3rem;font-size:1.4rem;box-shadow:0 0 6px 0 var(--color-tooltip-shadow);border-radius:.6rem;z-index:9;color:var(--color-font)}.display-type .type-list .item[data-v-1d327f48]{word-break:keep-all;padding:.8rem 1rem}.display-type .type-list .item.active[data-v-1d327f48]{color:var(--color-font-pure)}.display-type svg[data-v-1d327f48]{width:1.5rem}.font-size[data-v-a64ba8b8]{margin-bottom:3rem;display:flex;flex-direction:column;align-items:center;justify-content:center}.font-size .steps[data-v-a64ba8b8]{width:100%;border-radius:10rpx;display:flex;justify-content:space-between;align-items:center;position:relative;z-index:2}.font-size .steps .step[data-v-a64ba8b8]{width:100%;font-size:20rpx;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:4.8rem;gap:1.5rem;color:gray}.font-size .steps .step .text[data-v-a64ba8b8]{font-size:1.4rem}.font-size .steps .step .point[data-v-a64ba8b8]{border-radius:50%;min-width:6px;min-height:6px;background:#adadad}.font-size .steps .step.active[data-v-a64ba8b8]{color:var(--color-font-pure)}.font-size .steps .step.active .point[data-v-a64ba8b8]{box-shadow:0 0 1px 1px #f1f1f1;background:white;transform:scale(3)}.font-size .line[data-v-a64ba8b8]{position:relative;z-index:1;margin-top:-4px;height:2px;width:76%;background:var(--color-font)}.row[data-v-424a2b09]{min-height:4rem;display:flex;justify-content:space-between;align-items:center;color:var(--color-font-8)}.row .wrapper[data-v-424a2b09]{height:3rem;flex:1;display:flex;justify-content:flex-end;align-items:center;gap:var(--space)}.row .main-title[data-v-424a2b09]{font-size:2.2rem;font-weight:700}.row .item-title[data-v-424a2b09]{font-size:1.8rem}.desc[data-v-424a2b09]{margin-bottom:1rem;font-size:1.4rem;text-align:left;color:var(--color-font)}.tool>svg[data-v-b7c6664e]{width:1.8rem!important;height:1.8rem!important}.more[data-v-e92e0529]{height:1.6rem;width:2.08rem;padding:1rem .8rem 1rem 0;display:flex;flex-direction:column;justify-content:space-between;align-items:flex-end}.more div[data-v-e92e0529]{background:var(--color-floor-font);width:.3rem;height:.3rem;border-radius:50%}.Author[data-v-9041586a]{display:flex;align-items:center;justify-content:space-between;font-size:1.2rem;position:relative}.Author.expand[data-v-9041586a]{margin-bottom:0}.Author .Author-left[data-v-9041586a]{display:flex;align-items:center;width:80%;word-break:break-all}.Author .Author-left .info[data-v-9041586a]{display:flex;flex-direction:column}.Author .Author-left .username[data-v-9041586a]{font-size:1.4rem;margin-right:1rem}.Author .Author-left .expand-icon[data-v-9041586a]{margin-right:.8rem;width:2.4rem;height:2.4rem;transform:rotate(90deg)}.Author .Author-left .texts[data-v-9041586a]{flex:1}.Author .Author-left .owner[data-v-9041586a]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.Author .Author-left .dup[data-v-9041586a]{display:inline-block;background-color:transparent;color:red;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid red;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.Author .Author-left .mod[data-v-9041586a]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;transform:scale(.8);background:#1484cd;color:#fff;margin-right:1rem}.Author .Author-right[data-v-9041586a]{position:absolute;right:0;display:flex;align-items:center}.loading[data-v-2697baa2]{border:2px solid;border-color:var(--color-loading-2) var(--color-loading-1) var(--color-loading-1) var(--color-loading-1);border-radius:100%;animation:circle-2697baa2 infinite 1s linear;width:2rem;height:2rem}.loading.small[data-v-2697baa2]{width:1.2rem;height:1.2rem}.loading.large[data-v-2697baa2]{width:3rem;height:3rem}@keyframes circle-2697baa2{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.base-button[data-v-04f4c89d]{border-radius:.6rem;padding:0 1.5rem;display:inline-flex;align-items:center;justify-content:center;transition:all .3s;height:3.6rem;line-height:1;position:relative}.base-button .loading[data-v-04f4c89d]{position:absolute}.base-button.disabled[data-v-04f4c89d]{opacity:.6;cursor:not-allowed;-webkit-user-select:none;user-select:none}.base-button.small[data-v-04f4c89d]{height:3rem}.base-button.small>span[data-v-04f4c89d]{font-size:1.3rem}.base-button.large[data-v-04f4c89d]{height:5rem;font-size:1.8rem;padding:0 2.2rem}.base-button.large>span[data-v-04f4c89d]{font-size:1.8rem}.base-button.primary[data-v-04f4c89d]{background:var(--color-active)}.base-button.primary>span[data-v-04f4c89d]{color:#fff}.base-button.gary[data-v-04f4c89d]{background:#4b5563}.base-button.link[data-v-04f4c89d]{border-radius:0;border-bottom:2px solid transparent}.base-button.link>span[data-v-04f4c89d]{color:var(--color-font-8)}.base-button.active[data-v-04f4c89d]{opacity:.4}.key-notice[data-v-04f4c89d]{margin-left:1rem;display:flex;align-items:center;justify-content:center;font-size:1.2rem;color:#fff}.key-notice .key[data-v-04f4c89d]{transform:scale(.8)}.post-editor-wrapper[data-v-0612e02f]{width:100%;box-sizing:border-box;position:relative;overflow:hidden;transition:all .3s;color:var(--color-font)}.post-editor-wrapper.isFocus .post-editor[data-v-0612e02f]{border:1px solid var(--color-active)}.post-editor-wrapper .post-editor[data-v-0612e02f]{border:1px solid var(--color-line);border-radius:var(--box-border-radius);transition:border .3s;width:100%;max-width:100%;padding:.6rem 1.4rem;box-sizing:border-box;outline:none;font-family:Avenir,Helvetica,Arial,sans-serif;font-size:1.6rem;min-height:13rem;resize:none;background:var(--box-background-color);color:var(--color-font-pure)}.post-editor-wrapper .toolbar[data-v-0612e02f]{box-sizing:border-box;padding:.5rem 1rem;width:100%;position:relative;display:flex;justify-content:space-between;align-items:center}.post-editor-wrapper .toolbar .left[data-v-0612e02f]{display:flex;gap:1rem}.post-editor-wrapper .toolbar .left .upload input[data-v-0612e02f]{position:absolute;width:20px;height:20px;opacity:0}.post-editor-wrapper .toolbar span[data-v-0612e02f]{color:gray;font-size:1.3rem}.post-editor-wrapper .get-cursor[data-v-0612e02f]{border:1px solid var(--color-line);border-radius:var(--box-border-radius);transition:border .3s;width:100%;max-width:100%;padding:.6rem 1.4rem;box-sizing:border-box;outline:none;font-family:Avenir,Helvetica,Arial,sans-serif;font-size:1.6rem;min-height:13rem;resize:none;background:var(--box-background-color);color:var(--color-font-pure);position:absolute;top:0;z-index:-100}.post-editor-wrapper .emoticon-pack[data-v-0612e02f]{z-index:999999999;border-radius:1rem;padding:1rem;width:31rem;max-width:31rem;height:30rem;max-height:30rem;overflow:auto;background:var(--color-third-bg);border:1px solid var(--color-font-3);box-shadow:0 9px 24px -3px #0000000f,0 4px 8px -1px #0000001f;position:fixed;bottom:11rem;left:14rem}.post-editor-wrapper .emoticon-pack i[data-v-0612e02f]{position:absolute;right:2rem;font-size:2rem;color:#e2e2e2}.post-editor-wrapper .emoticon-pack .list[data-v-0612e02f]{margin:1rem 0}.post-editor-wrapper .emoticon-pack img[data-v-0612e02f]{width:3rem;height:3rem;padding:.5rem}.post-editor-wrapper .emoticon-pack span[data-v-0612e02f]{display:inline-block;font-size:2.3rem;padding:.5rem}.v-enter-active[data-v-f8165980],.v-leave-active[data-v-f8165980]{transition:opacity .3s ease}.v-enter-from[data-v-f8165980],.v-leave-to[data-v-f8165980]{opacity:0}.fade-in[data-v-f8165980]{animation:fade-in-f8165980 .3s}.fade-out[data-v-f8165980]{animation:fade-out-f8165980 .4s}@keyframes fade-in-f8165980{0%{opacity:0}to{opacity:1}}@keyframes fade-out-f8165980{0%{opacity:1}to{opacity:0;display:none}}.username[data-v-f8165980]{font-weight:700;font-size:1.4rem;margin-right:1rem}.link-num[data-v-f8165980]{font-size:1.4rem;color:var(--color-font-8);color:#e02a2a}.owner[data-v-f8165980]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.mod[data-v-f8165980]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;transform:scale(.8);background:#1484cd;color:#fff;margin-right:1rem}.my-tag[data-v-f8165980]{font-size:1.4rem;color:red;margin-left:1rem}.my-tag .remove[data-v-f8165980]{margin-left:.5rem;display:none}.add-tag[data-v-f8165980]{font-size:2.4rem;transform:translateY(.2rem);line-height:1rem;display:inline-block;margin-left:1rem;position:absolute;display:none}.floor[data-v-f8165980]{font-size:1.1rem;line-height:1rem;border-radius:.5rem;display:inline-block;color:var(--color-floor-font);cursor:default;margin-right:1rem}.base-avatar[data-v-f8165980]{margin-right:1rem;display:inline-flex}.base-avatar img[data-v-f8165980]{width:2.8rem;height:2.8rem;border-radius:.4rem}html[data-v-f8165980]{font-size:10px}[data-v-f8165980]:root{--box-border-radius: 8px}#site-header[data-v-f8165980]{height:4rem}#site-header #site-header-menu #menu-body[data-v-f8165980]{top:5rem;right:1rem}#Wrapper .cell .count_livid[data-v-f8165980]{font-size:14px;font-weight:700;padding:3px 10px;border-radius:5px}a[data-v-f8165980]{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-user-select:none;-moz-user-focus:none;-moz-user-select:none}.post-item[data-v-f8165980]{background:var(--box-background-color)}.post-item .new-item[data-v-f8165980]{display:flex;justify-content:space-between}.post-item .new-item .left .top[data-v-f8165980]{display:flex;align-items:center;line-height:1.2;gap:1rem}.post-item .new-item .left .small[data-v-f8165980],.post-item .new-item .left a.node[data-v-f8165980]{font-size:1.2rem}.post-item .new-item .left .bottom[data-v-f8165980]{margin:1rem 0 .5rem}.post-item .new-item .left .bottom .item_title[data-v-f8165980]{font-size:1.6rem}.post-item .new-item .left .bottom a[data-v-f8165980]{text-decoration:none!important}.post-item .new-item .right[data-v-f8165980]{min-width:5rem;display:flex;justify-content:flex-end;align-items:center}.post-item .new-item .right .count_livid[data-v-f8165980]{font-size:1.4rem!important;margin-right:0;padding:.3rem 1rem!important;border-radius:.5rem!important}.post-item .post-content[data-v-f8165980]{display:block;max-height:30rem;overflow:hidden;line-break:anywhere;-webkit-mask-image:linear-gradient(180deg,#000 60%,transparent);height:0;color:#000;text-decoration:none!important}.post-item .post-content blockquote[data-v-f8165980]{margin-top:.5rem}.post-item .post-content p[data-v-f8165980]:first-child{margin-top:0}.post-item .post-content[data-v-f8165980]:visited{color:var(--link-visited-color)}.post-item .show-more[data-v-f8165980]{font-size:1.3rem;text-align:right;height:3rem;align-items:center;justify-content:center;position:relative;z-index:9;display:none}.preview[data-v-f8165980]{margin-bottom:.7rem;border-radius:var(--box-border-radius)}.preview .topic-link[data-v-f8165980]:link{color:#000!important}.preview .show-all[data-v-f8165980]{max-height:unset;-webkit-mask-image:none}.preview .post-content[data-v-f8165980]{height:unset!important}.preview .show-more[data-v-f8165980]{display:flex}.preview .item_title[data-v-f8165980]{font-weight:700}.Night .post-item[data-v-f8165980]{background:#18222d!important}.Night .preview[data-v-f8165980]{border:1px solid #3b536e}.Night .preview>.post-content[data-v-f8165980]:link{color:#d1d5d9}.Night .preview>.post-content[data-v-f8165980]:visited{color:#393f4e!important}.Night .preview .topic-link[data-v-f8165980]:link{color:#c0dbff!important}[data-v-f8165980]:root{--color-main-bg: #e2e2e2;--color-second-bg: white;--color-third-bg: #e2e2e2;--color-four-bg: #e7e9eb;--color-item-bg: white;--color-swtich-bg: #dcdfe6;--color-active: #409eff;--color-font: #999;--color-font-8: rgba(0, 0, 0, .8);--color-font-3: rgba(0, 0, 0, .3);--color-font-pure: black;--color-input-bg: white;--color-input-border: #e2e2e2;--color-input-border-hover: #a3a6ad;--color-radio-border: #e2e2e2;--color-tooltip-bg: white;--color-tooltip-shadow: #bbbbbb;--color-scrollbar: #93ade3;--color-line: #e2e2e2;--color-line2: #cecece;--color-loading-1: #00000033;--color-loading-2: #000;--color-floor: #f0f0f0;--color-floor-font: #bdbdbd;--color-editor-toolbar: #f6f7f8;--color-sp-btn-bg: #f1f1f1;--color-call-list-bg: white;--space: 1rem}html.dark[data-v-f8165980]{--color-main-bg: #22303f;--color-second-bg: #18222d;--color-third-bg: #31475e;--color-four-bg: #22303f;--color-item-bg: #18222d;--color-swtich-bg: #4c4d4f;--color-active: #409eff;--color-font: rgba(255, 255, 255, .5);--color-font-8: rgba(255, 255, 255, .8);--color-font-3: rgba(255, 255, 255, .3);--color-font-pure: white;--color-input-bg: #333333;--color-input-border: #6c6e72;--color-input-border-hover: #a3a6ad;--color-radio-border: #454847;--color-tooltip-bg: #31475e;--color-tooltip-shadow: #3b3b3b;--color-scrollbar: #5c5d5e;--color-line: var(--box-border-color);--color-loading-1: rgba(178, 177, 177, .2);--color-loading-2: #ffffff;--color-floor: #293b4d;--color-floor-font: rgba(255, 255, 255, .3);--color-editor-toolbar: var(--box-background-hover-color);--color-sp-btn-bg: #31475e;--color-call-list-bg: #31475e}.flex[data-v-f8165980]{display:flex;align-items:center;justify-content:space-between}.flex-end[data-v-f8165980]{justify-content:flex-end}.flex-center[data-v-f8165980]{justify-content:center}.p1[data-v-f8165980]{padding:1rem}.p2[data-v-f8165980]{padding:2rem}.p0[data-v-f8165980]{padding:0!important}body :is(.topic_content,.reply_content) a[href^=http][data-v-f8165980]{text-underline-offset:.46ex;color:currentcolor;text-decoration:underline 1.5px}a[data-v-f8165980]{text-decoration:none}.tool[data-v-f8165980]{position:relative;display:flex;align-items:center;border-radius:.3rem;height:2.6rem;padding:0 .5rem;gap:.6rem}.tool>svg[data-v-f8165980]{width:2.2rem!important;height:2.2rem!important}.tool.disabled[data-v-f8165980]{cursor:not-allowed}.tool span[data-v-f8165980]{line-height:1rem}.my-node[data-v-f8165980]{border-radius:.2rem;padding:.4rem;font-size:1rem;color:#999;background:#f5f5f5}.msgs[data-v-f8165980]{position:fixed;margin-left:calc(50% - 25rem);width:50rem;z-index:9999;bottom:0;left:0;right:0}.my-box[data-v-f8165980]{background:var(--box-background-color);margin-bottom:.5rem;width:100%;overflow:hidden;box-sizing:border-box;transition:background-color .3s}.my-box .box-content[data-v-f8165980]{padding:.5rem}.my-cell[data-v-f8165980]{color:var(--color-font);height:4.2rem;padding:0 1rem;font-size:1.4rem;line-height:150%;text-align:left;border-bottom:1px solid var(--color-line)}.modal[data-v-f8165980]{position:fixed;z-index:100;width:100vw;height:100vh;left:0;top:0;display:flex;justify-content:center;align-items:center}.modal .title[data-v-f8165980]{font-size:2.4rem;margin-bottom:1rem;text-align:center}.modal .option[data-v-f8165980]{display:flex;align-items:center;padding:.6rem 0}.modal .option>span[data-v-f8165980]{position:relative}.radio-group2[data-v-f8165980]{display:inline-flex;border-radius:.5rem;overflow:hidden;border:1px solid var(--color-radio-border);background:var(--box-background-alt-color)}.radio-group2 .radio[data-v-f8165980]{background:transparent;padding:.5rem 1.2rem;border-left:1px solid var(--color-radio-border);font-size:1.3rem;color:var(--color-gray)}.radio-group2 .radio[data-v-f8165980]:first-child{border-left:none}.radio-group2 .active[data-v-f8165980]{background:var(--color-active);color:#fff}.pop-confirm[data-v-f8165980]{position:relative;display:inline-flex;justify-content:center}input[data-v-f8165980]{width:10rem;height:3rem;outline:unset;border:1px solid var(--color-input-border);padding:0 .5rem;border-radius:5px;box-sizing:border-box;transition:all .3s;background:var(--color-input-bg);color:var(--color-font)}input[data-v-f8165980]:focus{border:1px solid var(--color-active)}.danger[data-v-f8165980]{color:red!important}.topic_content[data-v-f8165980],.reply_content[data-v-f8165980]{font-size:1.6rem}.mask[data-v-f8165980]{z-index:10;position:fixed;top:0;width:100vw;height:100vh;background:#000000bb}.mask.dark[data-v-f8165980]{background:#000000bb}.mask.light[data-v-f8165980]{background:transparent}.mask.lightgray[data-v-f8165980]{background:rgba(0,0,0,.25)}.mask.white[data-v-f8165980]{background:transparent}.slide[data-v-f8165980]{flex:1;width:100vw;height:100vh;transition:height .3s;position:relative;overflow:hidden}.slide .slide-list[data-v-f8165980]{height:100%;width:100%;display:flex;position:relative;transition:transform .3s}.slide .slide-list .slide-item[data-v-f8165980]{height:100%;width:100%;flex-shrink:0;position:relative;overflow:auto}.page1[data-v-f8165980]{overflow:hidden!important}.post-wrapper[data-v-f8165980],.setting-wrapper[data-v-f8165980]{position:absolute;left:0;top:0;height:100%;width:100%;background:var(--color-main-bg);overflow:auto}.setting-wrapper[data-v-f8165980],.setting-wrapper2[data-v-f8165980]{height:100%;overflow:hidden;background:var(--color-second-bg)}.mobile-page[data-v-f8165980]{height:100%;overflow:hidden;font-size:1.8rem;display:flex;flex-direction:column}.mobile-page>.page-content[data-v-f8165980]{padding:1rem;padding-top:0;box-sizing:border-box;overflow:auto}.html-wrapper[data-v-f8165980]{position:relative}.html-wrapper .htmlMask[data-v-f8165980]{max-height:90rem;overflow:hidden;-webkit-mask-image:linear-gradient(180deg,#000 80%,transparent)}.html-wrapper .expand[data-v-f8165980]{position:absolute;z-index:1;bottom:2rem;padding:.2rem 1.5rem;border-radius:2rem;border:1px solid gray;background:white;color:gray;left:50%;transform:translate(-50%)}.comment[data-v-312e9541]{width:100%;box-sizing:border-box;margin-top:.6rem}.comment.isLevelOne[data-v-312e9541]{border-bottom:1px solid var(--color-line);padding:.8rem 1rem;margin-top:0}.comment.ding[data-v-312e9541]{background:rgba(255,255,0,.3)!important}.comment .comment-content-w .more[data-v-312e9541]{text-align:center;margin:1rem 0}.comment .comment-content[data-v-312e9541]{display:flex;position:relative}.comment .comment-content .expand-line[data-v-312e9541]{margin-top:.6rem;width:1.8rem;min-width:1.8rem;position:relative}.comment .comment-content .expand-line[data-v-312e9541]:after{position:absolute;left:30%;content:" ";height:100%;width:0;border-right:1px solid var(--color-line)}.comment .comment-content .right[data-v-312e9541]{flex:1;width:calc(100% - 3rem)}.comment .comment-content .right .w[data-v-312e9541]{margin:.5rem 0}.wrong-wrapper[data-v-312e9541]{font-size:1.4rem;margin-bottom:1rem}.wrong-wrapper .del-line[data-v-312e9541]{text-decoration:line-through}.wrong-wrapper .wrong-icon[data-v-312e9541]{margin-left:.5rem}.wrong-wrapper .warning[data-v-312e9541]{border-top:1px solid #e1e1e1;border-bottom:1px solid #e1e1e1;padding:1rem 0;margin-top:1rem;font-size:1.2rem;color:red}.toolbar[data-v-6234240d]{border-top:1px solid var(--color-line);height:4rem;padding:0 1rem;display:flex;align-items:center;color:var(--color-font);font-size:1.4rem;justify-content:space-between}.toolbar .left[data-v-6234240d],.toolbar .right[data-v-6234240d]{gap:1rem;display:flex}.toolbar .right[data-v-6234240d]{gap:.6rem}.comment[data-v-0869dab5]{width:100%;box-sizing:border-box;display:flex;gap:1rem;padding:1rem;border-bottom:1px solid var(--color-line)}.comment .base-avatar[data-v-0869dab5]{display:flex;margin-right:0}.comment .base-avatar img[data-v-0869dab5]{width:2.8rem;height:2.8rem;border-radius:.3rem}.comment .comment-body[data-v-0869dab5]{flex:1;display:flex;flex-direction:column}.comment .comment-body .texts[data-v-0869dab5]{display:flex;align-items:center}.comment .comment-body .reply_content[data-v-0869dab5]{margin-top:1rem;max-width:calc(100% - 5rem)}.comment .isRight[data-v-0869dab5]{align-items:flex-end}.comment .isRight .owner[data-v-0869dab5],.comment .isRight .mod[data-v-0869dab5],.comment .isRight .username[data-v-0869dab5]{margin:0 0 0 1rem}.comment .Author-right[data-v-0869dab5]{display:flex;flex-direction:column;align-items:center}.comment .Author-right .floor[data-v-0869dab5]{margin:0;border-radius:.5rem;background-color:var(--color-floor);padding:3px 9px}.comment .Author-right .jump[data-v-0869dab5]{color:#929596;margin-top:.4rem;font-size:1.4rem}.comment .point[data-v-0869dab5]{margin:0 1rem;display:flex;gap:.5rem;align-items:center}.comment .point svg[data-v-0869dab5]{font-size:1.6rem}.FromBottomDialog[data-v-3a54f208]{z-index:11;position:fixed;width:100%;overflow-y:auto;bottom:0;box-sizing:border-box;border-radius:var(--0013fa15);transition:all .3s;background:var(--color-four-bg)}.FromBottomDialog.no-heng-gang[data-v-3a54f208]{padding-top:0}.FromBottomDialog .heng-gang[data-v-3a54f208]{border-radius:.5rem .5rem 0 0;border-radius:var(--0013fa15);z-index:3;width:100%;position:fixed;min-height:3rem;display:flex;justify-content:center;align-items:center}.FromBottomDialog .heng-gang .gang-content[data-v-3a54f208]{background:darkgray;border-radius:2px;height:.4rem;width:3rem}.FromBottomDialog .dialog-wrapper[data-v-3a54f208]{margin-top:3rem}.wrapper .options[data-v-ce52828d]{padding:1rem 2rem 3rem;display:grid;grid-template-columns:repeat(5,1fr);justify-content:space-between;gap:2rem}.wrapper .options .item[data-v-ce52828d]{display:flex;flex-direction:column;align-items:center;color:gray;font-size:1.2rem}.wrapper .options .item.disabled[data-v-ce52828d]{opacity:.5}.wrapper .options .item.disabled svg[data-v-ce52828d]{color:gray!important}.wrapper .options .item .icon-wrap[data-v-ce52828d]{margin-bottom:.5rem;width:100%;height:15vw;display:flex;justify-content:center;align-items:center;background:var(--color-second-bg);border-radius:1rem}.wrapper .options .item .icon-wrap svg[data-v-ce52828d]{font-size:3rem}.wrapper .options .black[data-v-ce52828d]{color:var(--color-font-pure)}.wrapper .cancel[data-v-ce52828d]{border-top:1px solid var(--color-tooltip-bg);display:flex;align-items:center;justify-content:center;font-size:1.6rem;height:5rem;color:#646f81}.wrapper .options[data-v-8ef13a81]{padding:1rem 2rem 3rem;display:grid;grid-template-columns:repeat(5,1fr);justify-content:space-between;gap:2rem}.wrapper .options .item[data-v-8ef13a81]{display:flex;flex-direction:column;align-items:center;color:gray;font-size:1.2rem}.wrapper .options .item.disabled[data-v-8ef13a81]{opacity:.5}.wrapper .options .item.disabled svg[data-v-8ef13a81]{color:gray!important}.wrapper .options .item.full svg[data-v-8ef13a81]{color:#e02a2a!important}.wrapper .options .item .icon-wrap[data-v-8ef13a81]{margin-bottom:.5rem;width:100%;height:15vw;display:flex;justify-content:center;align-items:center;background:var(--color-second-bg);border-radius:1rem}.wrapper .options .item .icon-wrap svg[data-v-8ef13a81]{font-size:3rem;color:#39ae55}.wrapper .cancel[data-v-8ef13a81]{border-top:1px solid var(--color-line2);display:flex;align-items:center;justify-content:center;font-size:1.6rem;height:5rem;color:#646f81}.sticky{position:sticky;bottom:-2px;z-index:2;background:var(--box-background-hover-color)!important}.sticky[stuck]{box-shadow:0 2px 20px #00000059!important}.v-enter-active[data-v-546d3b11],.v-leave-active[data-v-546d3b11]{transition:opacity .3s ease}.v-enter-from[data-v-546d3b11],.v-leave-to[data-v-546d3b11]{opacity:0}.fade-in[data-v-546d3b11]{animation:fade-in-546d3b11 .3s}.fade-out[data-v-546d3b11]{animation:fade-out-546d3b11 .4s}@keyframes fade-in-546d3b11{0%{opacity:0}to{opacity:1}}@keyframes fade-out-546d3b11{0%{opacity:1}to{opacity:0;display:none}}.username[data-v-546d3b11]{font-weight:700;font-size:1.4rem;margin-right:1rem}.link-num[data-v-546d3b11]{font-size:1.4rem;color:var(--color-font-8);color:#e02a2a}.owner[data-v-546d3b11]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.mod[data-v-546d3b11]{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;transform:scale(.8);background:#1484cd;color:#fff;margin-right:1rem}.my-tag[data-v-546d3b11]{font-size:1.4rem;color:red;margin-left:1rem}.my-tag .remove[data-v-546d3b11]{margin-left:.5rem;display:none}.add-tag[data-v-546d3b11]{font-size:2.4rem;transform:translateY(.2rem);line-height:1rem;display:inline-block;margin-left:1rem;position:absolute;display:none}.floor[data-v-546d3b11]{font-size:1.1rem;line-height:1rem;border-radius:.5rem;display:inline-block;color:var(--color-floor-font);cursor:default;margin-right:1rem}.base-avatar[data-v-546d3b11]{margin-right:1rem;display:inline-flex}.base-avatar img[data-v-546d3b11]{width:2.8rem;height:2.8rem;border-radius:.4rem}html[data-v-546d3b11]{font-size:10px}[data-v-546d3b11]:root{--box-border-radius: 8px}#site-header[data-v-546d3b11]{height:4rem}#site-header #site-header-menu #menu-body[data-v-546d3b11]{top:5rem;right:1rem}#Wrapper .cell .count_livid[data-v-546d3b11]{font-size:14px;font-weight:700;padding:3px 10px;border-radius:5px}a[data-v-546d3b11]{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-user-select:none;-moz-user-focus:none;-moz-user-select:none}.post-item[data-v-546d3b11]{background:var(--box-background-color)}.post-item .new-item[data-v-546d3b11]{display:flex;justify-content:space-between}.post-item .new-item .left .top[data-v-546d3b11]{display:flex;align-items:center;line-height:1.2;gap:1rem}.post-item .new-item .left .small[data-v-546d3b11],.post-item .new-item .left a.node[data-v-546d3b11]{font-size:1.2rem}.post-item .new-item .left .bottom[data-v-546d3b11]{margin:1rem 0 .5rem}.post-item .new-item .left .bottom .item_title[data-v-546d3b11]{font-size:1.6rem}.post-item .new-item .left .bottom a[data-v-546d3b11]{text-decoration:none!important}.post-item .new-item .right[data-v-546d3b11]{min-width:5rem;display:flex;justify-content:flex-end;align-items:center}.post-item .new-item .right .count_livid[data-v-546d3b11]{font-size:1.4rem!important;margin-right:0;padding:.3rem 1rem!important;border-radius:.5rem!important}.post-item .post-content[data-v-546d3b11]{display:block;max-height:30rem;overflow:hidden;line-break:anywhere;-webkit-mask-image:linear-gradient(180deg,#000 60%,transparent);height:0;color:#000;text-decoration:none!important}.post-item .post-content blockquote[data-v-546d3b11]{margin-top:.5rem}.post-item .post-content p[data-v-546d3b11]:first-child{margin-top:0}.post-item .post-content[data-v-546d3b11]:visited{color:var(--link-visited-color)}.post-item .show-more[data-v-546d3b11]{font-size:1.3rem;text-align:right;height:3rem;align-items:center;justify-content:center;position:relative;z-index:9;display:none}.preview[data-v-546d3b11]{margin-bottom:.7rem;border-radius:var(--box-border-radius)}.preview .topic-link[data-v-546d3b11]:link{color:#000!important}.preview .show-all[data-v-546d3b11]{max-height:unset;-webkit-mask-image:none}.preview .post-content[data-v-546d3b11]{height:unset!important}.preview .show-more[data-v-546d3b11]{display:flex}.preview .item_title[data-v-546d3b11]{font-weight:700}.Night .post-item[data-v-546d3b11]{background:#18222d!important}.Night .preview[data-v-546d3b11]{border:1px solid #3b536e}.Night .preview>.post-content[data-v-546d3b11]:link{color:#d1d5d9}.Night .preview>.post-content[data-v-546d3b11]:visited{color:#393f4e!important}.Night .preview .topic-link[data-v-546d3b11]:link{color:#c0dbff!important}[data-v-546d3b11]:root{--color-main-bg: #e2e2e2;--color-second-bg: white;--color-third-bg: #e2e2e2;--color-four-bg: #e7e9eb;--color-item-bg: white;--color-swtich-bg: #dcdfe6;--color-active: #409eff;--color-font: #999;--color-font-8: rgba(0, 0, 0, .8);--color-font-3: rgba(0, 0, 0, .3);--color-font-pure: black;--color-input-bg: white;--color-input-border: #e2e2e2;--color-input-border-hover: #a3a6ad;--color-radio-border: #e2e2e2;--color-tooltip-bg: white;--color-tooltip-shadow: #bbbbbb;--color-scrollbar: #93ade3;--color-line: #e2e2e2;--color-line2: #cecece;--color-loading-1: #00000033;--color-loading-2: #000;--color-floor: #f0f0f0;--color-floor-font: #bdbdbd;--color-editor-toolbar: #f6f7f8;--color-sp-btn-bg: #f1f1f1;--color-call-list-bg: white;--space: 1rem}html.dark[data-v-546d3b11]{--color-main-bg: #22303f;--color-second-bg: #18222d;--color-third-bg: #31475e;--color-four-bg: #22303f;--color-item-bg: #18222d;--color-swtich-bg: #4c4d4f;--color-active: #409eff;--color-font: rgba(255, 255, 255, .5);--color-font-8: rgba(255, 255, 255, .8);--color-font-3: rgba(255, 255, 255, .3);--color-font-pure: white;--color-input-bg: #333333;--color-input-border: #6c6e72;--color-input-border-hover: #a3a6ad;--color-radio-border: #454847;--color-tooltip-bg: #31475e;--color-tooltip-shadow: #3b3b3b;--color-scrollbar: #5c5d5e;--color-line: var(--box-border-color);--color-loading-1: rgba(178, 177, 177, .2);--color-loading-2: #ffffff;--color-floor: #293b4d;--color-floor-font: rgba(255, 255, 255, .3);--color-editor-toolbar: var(--box-background-hover-color);--color-sp-btn-bg: #31475e;--color-call-list-bg: #31475e}.flex[data-v-546d3b11]{display:flex;align-items:center;justify-content:space-between}.flex-end[data-v-546d3b11]{justify-content:flex-end}.flex-center[data-v-546d3b11]{justify-content:center}.p1[data-v-546d3b11]{padding:1rem}.p2[data-v-546d3b11]{padding:2rem}.p0[data-v-546d3b11]{padding:0!important}body :is(.topic_content,.reply_content) a[href^=http][data-v-546d3b11]{text-underline-offset:.46ex;color:currentcolor;text-decoration:underline 1.5px}a[data-v-546d3b11]{text-decoration:none}.tool[data-v-546d3b11]{position:relative;display:flex;align-items:center;border-radius:.3rem;height:2.6rem;padding:0 .5rem;gap:.6rem}.tool>svg[data-v-546d3b11]{width:2.2rem!important;height:2.2rem!important}.tool.disabled[data-v-546d3b11]{cursor:not-allowed}.tool span[data-v-546d3b11]{line-height:1rem}.my-node[data-v-546d3b11]{border-radius:.2rem;padding:.4rem;font-size:1rem;color:#999;background:#f5f5f5}.msgs[data-v-546d3b11]{position:fixed;margin-left:calc(50% - 25rem);width:50rem;z-index:9999;bottom:0;left:0;right:0}.my-box[data-v-546d3b11]{background:var(--box-background-color);margin-bottom:.5rem;width:100%;overflow:hidden;box-sizing:border-box;transition:background-color .3s}.my-box .box-content[data-v-546d3b11]{padding:.5rem}.my-cell[data-v-546d3b11]{color:var(--color-font);height:4.2rem;padding:0 1rem;font-size:1.4rem;line-height:150%;text-align:left;border-bottom:1px solid var(--color-line)}.modal[data-v-546d3b11]{position:fixed;z-index:100;width:100vw;height:100vh;left:0;top:0;display:flex;justify-content:center;align-items:center}.modal .title[data-v-546d3b11]{font-size:2.4rem;margin-bottom:1rem;text-align:center}.modal .option[data-v-546d3b11]{display:flex;align-items:center;padding:.6rem 0}.modal .option>span[data-v-546d3b11]{position:relative}.radio-group2[data-v-546d3b11]{display:inline-flex;border-radius:.5rem;overflow:hidden;border:1px solid var(--color-radio-border);background:var(--box-background-alt-color)}.radio-group2 .radio[data-v-546d3b11]{background:transparent;padding:.5rem 1.2rem;border-left:1px solid var(--color-radio-border);font-size:1.3rem;color:var(--color-gray)}.radio-group2 .radio[data-v-546d3b11]:first-child{border-left:none}.radio-group2 .active[data-v-546d3b11]{background:var(--color-active);color:#fff}.pop-confirm[data-v-546d3b11]{position:relative;display:inline-flex;justify-content:center}input[data-v-546d3b11]{width:10rem;height:3rem;outline:unset;border:1px solid var(--color-input-border);padding:0 .5rem;border-radius:5px;box-sizing:border-box;transition:all .3s;background:var(--color-input-bg);color:var(--color-font)}input[data-v-546d3b11]:focus{border:1px solid var(--color-active)}.danger[data-v-546d3b11]{color:red!important}.topic_content[data-v-546d3b11],.reply_content[data-v-546d3b11]{font-size:1.6rem}.mask[data-v-546d3b11]{z-index:10;position:fixed;top:0;width:100vw;height:100vh;background:#000000bb}.mask.dark[data-v-546d3b11]{background:#000000bb}.mask.light[data-v-546d3b11]{background:transparent}.mask.lightgray[data-v-546d3b11]{background:rgba(0,0,0,.25)}.mask.white[data-v-546d3b11]{background:transparent}.slide[data-v-546d3b11]{flex:1;width:100vw;height:100vh;transition:height .3s;position:relative;overflow:hidden}.slide .slide-list[data-v-546d3b11]{height:100%;width:100%;display:flex;position:relative;transition:transform .3s}.slide .slide-list .slide-item[data-v-546d3b11]{height:100%;width:100%;flex-shrink:0;position:relative;overflow:auto}.page1[data-v-546d3b11]{overflow:hidden!important}.post-wrapper[data-v-546d3b11],.setting-wrapper[data-v-546d3b11]{position:absolute;left:0;top:0;height:100%;width:100%;background:var(--color-main-bg);overflow:auto}.setting-wrapper[data-v-546d3b11],.setting-wrapper2[data-v-546d3b11]{height:100%;overflow:hidden;background:var(--color-second-bg)}.mobile-page[data-v-546d3b11]{height:100%;overflow:hidden;font-size:1.8rem;display:flex;flex-direction:column}.mobile-page>.page-content[data-v-546d3b11]{padding:1rem;padding-top:0;box-sizing:border-box;overflow:auto}.post-detail[data-v-546d3b11]{text-align:start;background:var(--color-main-bg);font-size:1.6rem;display:flex;justify-content:center;flex-wrap:wrap;padding-bottom:10rem}.post-detail[data-v-546d3b11] .subtle{background-color:#ecfdf5e6;border-left:4px solid #a7f3d0}.post-detail.isNight[data-v-546d3b11] .subtle{background-color:#1a3332;border-left:4px solid #047857}.post-detail .nav-bar[data-v-546d3b11]{position:fixed;top:0;z-index:9;height:4.6rem;display:flex;justify-content:space-between;align-items:center;padding:1rem;margin-bottom:-1px}.post-detail .nav-bar svg[data-v-546d3b11]{width:2rem;height:2rem;color:var(--color-font)}.post-detail .nav-bar .left[data-v-546d3b11],.post-detail .nav-bar .right[data-v-546d3b11]{display:flex;align-items:center;gap:1rem}.post-detail .post-main-body .box-header[data-v-546d3b11]{padding:0 .5rem}.post-detail .post-main-body .box-header h1[data-v-546d3b11]{font-size:2.2rem;font-weight:700}.post-detail .post-main-body .box-header small[data-v-546d3b11]{display:flex;align-items:center}.post-detail .loading-wrapper[data-v-546d3b11]{height:20rem;display:flex;justify-content:center;align-items:center}.post-detail .comments-header[data-v-546d3b11]{width:100%;padding:0 1rem;box-sizing:border-box;background:var(--box-background-color)}.post-detail #no-comments-yet[data-v-546d3b11]{color:#a9a9a9;font-weight:700;text-align:center;width:100%;margin:2rem 1rem;box-sizing:border-box}.post-detail .relationReply[data-v-546d3b11]{position:fixed;width:25vw;top:6.5rem;bottom:15rem;z-index:100;transform:translate(calc(100% + 2rem));font-size:2rem;overflow:hidden}.post-detail .relationReply .my-cell[data-v-546d3b11]{background:var(--color-second-bg);border-radius:var(--box-border-radius) var(--box-border-radius) 0 0}.post-detail .relationReply .comments[data-v-546d3b11]{max-height:calc(100% - 4.2rem);overflow:auto;background:var(--color-second-bg);border-radius:0 0 var(--box-border-radius) var(--box-border-radius)}.post-detail .call-list[data-v-546d3b11]{z-index:9;position:absolute;top:12rem;border:1px solid var(--color-main-bg);background:var(--color-call-list-bg);box-shadow:0 5px 15px #0000001a;overflow:auto;max-height:30rem;border-radius:var(--box-border-radius);min-width:8rem;box-sizing:content-box}.post-detail .call-list .call-item[data-v-546d3b11]{border-top:1px solid var(--color-main-bg);height:3rem;display:flex;padding:0 1rem;align-items:center;font-size:14px;box-sizing:border-box}.post-detail .call-list .call-item .select[data-v-546d3b11],.post-detail .call-list .call-item.select[data-v-546d3b11]{background:var(--color-main-bg);text-decoration:none}.post-detail .call-list .call-item[data-v-546d3b11]:nth-child(1){border-top:1px solid transparent}.post-detail .top-reply[data-v-546d3b11]{color:var(--color-font-3);font-size:2rem;margin-right:1rem}.base64_tooltip[data-v-1988f33b]{box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d;background:var(--color-third-bg);min-height:2.2rem;max-width:20rem;padding:1rem;position:fixed;z-index:9998;display:flex;align-items:center;border-radius:.5rem;line-break:anywhere;font-size:1.4rem;color:var(--color-font-8)}.base64_tooltip svg[data-v-1988f33b]{margin-left:1rem;min-width:1.8rem}.base64_tooltip[data-v-1988f33b] .base-button{margin-left:1rem;margin-top:1rem}.msg[data-v-0dcc0508]{cursor:default;margin-bottom:2rem;display:flex;font-size:1.4rem;box-sizing:border-box;border-radius:var(--box-border-radius);color:var(--color-font-8);background:var(--color-tooltip-bg);box-shadow:0 0 6px 1px var(--color-tooltip-shadow)}.msg.success .left[data-v-0dcc0508]{background:var(--color-active)}.msg.warning .left[data-v-0dcc0508]{background:#c8c002}.msg.error .left[data-v-0dcc0508]{background:red}.msg .left[data-v-0dcc0508]{border-radius:var(--box-border-radius) 0 0 var(--box-border-radius);display:flex;align-items:center;background:var(--color-active)}.msg .left svg[data-v-0dcc0508]{color:#fff;font-size:2.2rem;margin:0 .6rem}.msg .right[data-v-0dcc0508]{flex:1;padding:1rem 2rem;display:flex;justify-content:space-between;align-items:center}.tag-modal .wrapper[data-v-674b86aa]{z-index:9;background:var(--color-main-bg);color:var(--color-font-8);border-radius:1.6rem;font-size:1.4rem;padding:2rem 4rem;width:25rem}.tag-modal .wrapper .title[data-v-674b86aa]{font-weight:700}.tag-modal .wrapper .btns[data-v-674b86aa]{margin-top:1.5rem;display:flex;justify-content:flex-end;align-items:center;gap:1.5rem;font-size:1.4rem}.msgs[data-v-93c4dec0]{position:fixed;margin-left:calc(50% - 40vw);width:80vw;z-index:9999;bottom:0;left:0;right:0}.tag-modal .modal-root[data-v-19a5903e]{z-index:9;background:var(--color-second-bg);color:var(--color-font-8);border-radius:1.6rem;font-size:1.4rem;width:50vw;height:70vh;display:flex;flex-direction:column}.tag-modal .modal-root .modal-header[data-v-19a5903e]{padding:2.4rem;display:flex;justify-content:space-between}.tag-modal .modal-root .modal-header .title[data-v-19a5903e]{font-size:2.6rem;font-weight:700;text-align:left;margin-bottom:0}.tag-modal .modal-root .modal-header i[data-v-19a5903e]{font-size:2.2rem}.tag-modal .modal-root .modal-body[data-v-19a5903e]{padding:2rem;padding-top:0;flex:1;overflow:auto}.tag-modal .modal-root .modal-body[data-v-19a5903e] .cell{padding:2rem}.v-enter-active,.v-leave-active{transition:opacity .3s ease}.v-enter-from,.v-leave-to{opacity:0}.fade-in{animation:fade-in .3s}.fade-out{animation:fade-out .4s}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-out{0%{opacity:1}to{opacity:0;display:none}}.username{font-weight:700;font-size:1.4rem;margin-right:1rem}.link-num{font-size:1.4rem;color:var(--color-font-8);color:#e02a2a}.owner{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;margin-right:1rem;transform:scale(.8)}.mod{display:inline-block;background-color:transparent;color:#1484cd;border-radius:.3rem;padding:0 .3rem;cursor:default;border:2px solid #1484cd;font-size:1.2rem;font-weight:700;transform:scale(.8);background:#1484cd;color:#fff;margin-right:1rem}.my-tag{font-size:1.4rem;color:red;margin-left:1rem}.my-tag .remove{margin-left:.5rem;display:none}.add-tag{font-size:2.4rem;transform:translateY(.2rem);line-height:1rem;display:inline-block;margin-left:1rem;position:absolute;display:none}.floor{font-size:1.1rem;line-height:1rem;border-radius:.5rem;display:inline-block;color:var(--color-floor-font);cursor:default;margin-right:1rem}.base-avatar{margin-right:1rem;display:inline-flex}.base-avatar img{width:2.8rem;height:2.8rem;border-radius:.4rem}html{font-size:10px}:root{--box-border-radius: 8px}#site-header{height:4rem}#site-header #site-header-menu #menu-body{top:5rem;right:1rem}#Wrapper .cell .count_livid{font-size:14px;font-weight:700;padding:3px 10px;border-radius:5px}a{-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-user-select:none;-moz-user-focus:none;-moz-user-select:none}.post-item{background:var(--box-background-color)}.post-item .new-item{display:flex;justify-content:space-between}.post-item .new-item .left .top{display:flex;align-items:center;line-height:1.2;gap:1rem}.post-item .new-item .left .small,.post-item .new-item .left a.node{font-size:1.2rem}.post-item .new-item .left .bottom{margin:1rem 0 .5rem}.post-item .new-item .left .bottom .item_title{font-size:1.6rem}.post-item .new-item .left .bottom a{text-decoration:none!important}.post-item .new-item .right{min-width:5rem;display:flex;justify-content:flex-end;align-items:center}.post-item .new-item .right .count_livid{font-size:1.4rem!important;margin-right:0;padding:.3rem 1rem!important;border-radius:.5rem!important}.post-item .post-content{display:block;max-height:30rem;overflow:hidden;line-break:anywhere;-webkit-mask-image:linear-gradient(180deg,#000 60%,transparent);height:0;color:#000;text-decoration:none!important}.post-item .post-content blockquote{margin-top:.5rem}.post-item .post-content p:first-child{margin-top:0}.post-item .post-content:visited{color:var(--link-visited-color)}.post-item .show-more{font-size:1.3rem;text-align:right;height:3rem;align-items:center;justify-content:center;position:relative;z-index:9;display:none}.preview{margin-bottom:.7rem;border-radius:var(--box-border-radius)}.preview .topic-link:link{color:#000!important}.preview .show-all{max-height:unset;-webkit-mask-image:none}.preview .post-content{height:unset!important}.preview .show-more{display:flex}.preview .item_title{font-weight:700}.Night .post-item{background:#18222d!important}.Night .preview{border:1px solid #3b536e}.Night .preview>.post-content:link{color:#d1d5d9}.Night .preview>.post-content:visited{color:#393f4e!important}.Night .preview .topic-link:link{color:#c0dbff!important}:root{--color-main-bg: #e2e2e2;--color-second-bg: white;--color-third-bg: #e2e2e2;--color-four-bg: #e7e9eb;--color-item-bg: white;--color-swtich-bg: #dcdfe6;--color-active: #409eff;--color-font: #999;--color-font-8: rgba(0, 0, 0, .8);--color-font-3: rgba(0, 0, 0, .3);--color-font-pure: black;--color-input-bg: white;--color-input-border: #e2e2e2;--color-input-border-hover: #a3a6ad;--color-radio-border: #e2e2e2;--color-tooltip-bg: white;--color-tooltip-shadow: #bbbbbb;--color-scrollbar: #93ade3;--color-line: #e2e2e2;--color-line2: #cecece;--color-loading-1: #00000033;--color-loading-2: #000;--color-floor: #f0f0f0;--color-floor-font: #bdbdbd;--color-editor-toolbar: #f6f7f8;--color-sp-btn-bg: #f1f1f1;--color-call-list-bg: white;--space: 1rem}html.dark{--color-main-bg: #22303f;--color-second-bg: #18222d;--color-third-bg: #31475e;--color-four-bg: #22303f;--color-item-bg: #18222d;--color-swtich-bg: #4c4d4f;--color-active: #409eff;--color-font: rgba(255, 255, 255, .5);--color-font-8: rgba(255, 255, 255, .8);--color-font-3: rgba(255, 255, 255, .3);--color-font-pure: white;--color-input-bg: #333333;--color-input-border: #6c6e72;--color-input-border-hover: #a3a6ad;--color-radio-border: #454847;--color-tooltip-bg: #31475e;--color-tooltip-shadow: #3b3b3b;--color-scrollbar: #5c5d5e;--color-line: var(--box-border-color);--color-loading-1: rgba(178, 177, 177, .2);--color-loading-2: #ffffff;--color-floor: #293b4d;--color-floor-font: rgba(255, 255, 255, .3);--color-editor-toolbar: var(--box-background-hover-color);--color-sp-btn-bg: #31475e;--color-call-list-bg: #31475e}.flex{display:flex;align-items:center;justify-content:space-between}.flex-end{justify-content:flex-end}.flex-center{justify-content:center}.p1{padding:1rem}.p2{padding:2rem}.p0{padding:0!important}body :is(.topic_content,.reply_content) a[href^=http]{text-underline-offset:.46ex;color:currentcolor;text-decoration:underline 1.5px}a{text-decoration:none}.tool{position:relative;display:flex;align-items:center;border-radius:.3rem;height:2.6rem;padding:0 .5rem;gap:.6rem}.tool>svg{width:2.2rem!important;height:2.2rem!important}.tool.disabled{cursor:not-allowed}.tool span{line-height:1rem}.my-node{border-radius:.2rem;padding:.4rem;font-size:1rem;color:#999;background:#f5f5f5}.msgs{position:fixed;margin-left:calc(50% - 25rem);width:50rem;z-index:9999;bottom:0;left:0;right:0}.my-box{background:var(--box-background-color);margin-bottom:.5rem;width:100%;overflow:hidden;box-sizing:border-box;transition:background-color .3s}.my-box .box-content{padding:.5rem}.my-cell{color:var(--color-font);height:4.2rem;padding:0 1rem;font-size:1.4rem;line-height:150%;text-align:left;border-bottom:1px solid var(--color-line)}.modal{position:fixed;z-index:100;width:100vw;height:100vh;left:0;top:0;display:flex;justify-content:center;align-items:center}.modal .title{font-size:2.4rem;margin-bottom:1rem;text-align:center}.modal .option{display:flex;align-items:center;padding:.6rem 0}.modal .option>span{position:relative}.radio-group2{display:inline-flex;border-radius:.5rem;overflow:hidden;border:1px solid var(--color-radio-border);background:var(--box-background-alt-color)}.radio-group2 .radio{background:transparent;padding:.5rem 1.2rem;border-left:1px solid var(--color-radio-border);font-size:1.3rem;color:var(--color-gray)}.radio-group2 .radio:first-child{border-left:none}.radio-group2 .active{background:var(--color-active);color:#fff}.pop-confirm{position:relative;display:inline-flex;justify-content:center}input{width:10rem;height:3rem;outline:unset;border:1px solid var(--color-input-border);padding:0 .5rem;border-radius:5px;box-sizing:border-box;transition:all .3s;background:var(--color-input-bg);color:var(--color-font)}input:focus{border:1px solid var(--color-active)}.danger{color:red!important}.topic_content,.reply_content{font-size:1.6rem}.mask{z-index:10;position:fixed;top:0;width:100vw;height:100vh;background:#000000bb}.mask.dark{background:#000000bb}.mask.light{background:transparent}.mask.lightgray{background:rgba(0,0,0,.25)}.mask.white{background:transparent}.slide{flex:1;width:100vw;height:100vh;transition:height .3s;position:relative;overflow:hidden}.slide .slide-list{height:100%;width:100%;display:flex;position:relative;transition:transform .3s}.slide .slide-list .slide-item{height:100%;width:100%;flex-shrink:0;position:relative;overflow:auto}.page1{overflow:hidden!important}.post-wrapper,.setting-wrapper{position:absolute;left:0;top:0;height:100%;width:100%;background:var(--color-main-bg);overflow:auto}.setting-wrapper,.setting-wrapper2{height:100%;overflow:hidden;background:var(--color-second-bg)}.mobile-page{height:100%;overflow:hidden;font-size:1.8rem;display:flex;flex-direction:column}.mobile-page>.page-content{padding:1rem;padding-top:0;box-sizing:border-box;overflow:auto}.target-user-tags[data-v-f3ce1685]{background:var(--color-second-bg);color:var(--color-font);word-break:break-all;text-align:start;font-size:1.4rem;box-shadow:0 2px 3px #0000001a;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.target-user-tags .add-tag[data-v-f3ce1685]{display:inline-block}.loaded[data-v-f3ce1685]{font-size:1.4rem;display:flex;align-items:center;gap:1rem} ');
  35.  
  36. (function (vue) {
  37. 'use strict';
  38.  
  39. var PageType = /* @__PURE__ */ ((PageType2) => {
  40. PageType2["Home"] = "Home";
  41. PageType2["Node"] = "Node";
  42. PageType2["Post"] = "Post";
  43. PageType2["Member"] = "Member";
  44. PageType2["Changes"] = "Changes";
  45. return PageType2;
  46. })(PageType || {});
  47. var CommentDisplayType = /* @__PURE__ */ ((CommentDisplayType2) => {
  48. CommentDisplayType2[CommentDisplayType2["FloorInFloor"] = 0] = "FloorInFloor";
  49. CommentDisplayType2[CommentDisplayType2["FloorInFloorNoCallUser"] = 4] = "FloorInFloorNoCallUser";
  50. CommentDisplayType2[CommentDisplayType2["FloorInFloorNested"] = 5] = "FloorInFloorNested";
  51. CommentDisplayType2[CommentDisplayType2["Like"] = 1] = "Like";
  52. CommentDisplayType2[CommentDisplayType2["V2exOrigin"] = 2] = "V2exOrigin";
  53. CommentDisplayType2[CommentDisplayType2["OnlyOp"] = 3] = "OnlyOp";
  54. CommentDisplayType2[CommentDisplayType2["New"] = 6] = "New";
  55. return CommentDisplayType2;
  56. })(CommentDisplayType || {});
  57. const MAX_REPLY_LIMIT = 400;
  58. const _sfc_main$r = {
  59. name: "Tooltip",
  60. props: {
  61. title: {
  62. type: String,
  63. default() {
  64. return "";
  65. }
  66. },
  67. disabled: {
  68. type: Boolean,
  69. default() {
  70. return false;
  71. }
  72. }
  73. },
  74. data() {
  75. return {
  76. show: false
  77. };
  78. },
  79. methods: {
  80. showPop(e2) {
  81. if (this.disabled)
  82. return;
  83. if (!this.title)
  84. return;
  85. e2.stopPropagation();
  86. let rect = e2.target.getBoundingClientRect();
  87. this.show = true;
  88. vue.nextTick(() => {
  89. var _a, _b;
  90. let tip = (_b = (_a = this.$refs) == null ? void 0 : _a.tip) == null ? void 0 : _b.getBoundingClientRect();
  91. if (!tip)
  92. return;
  93. if (rect.top < 50) {
  94. this.$refs.tip.style.top = rect.top + rect.height + 10 + "px";
  95. } else {
  96. this.$refs.tip.style.top = rect.top - tip.height - 10 + "px";
  97. }
  98. let tipWidth = tip.width;
  99. let rectWidth = rect.width;
  100. this.$refs.tip.style.left = rect.left - (tipWidth - rectWidth) / 2 + "px";
  101. });
  102. }
  103. },
  104. render() {
  105. let Vnode = this.$slots.default()[0];
  106. return vue.createVNode(vue.Fragment, null, [this.show && this.title && vue.createVNode(vue.Teleport, {
  107. "to": "body"
  108. }, {
  109. default: () => [vue.createVNode(vue.Transition, {
  110. "name": "fade"
  111. }, {
  112. default: () => [vue.createVNode("div", {
  113. "ref": "tip",
  114. "className": "tip"
  115. }, [this.title])]
  116. })]
  117. }), vue.createVNode(Vnode, {
  118. "onClick": () => this.show = false,
  119. "onmouseenter": (e2) => this.showPop(e2),
  120. "onmouseleave": () => this.show = false
  121. }, null)]);
  122. }
  123. };
  124. const _export_sfc = (sfc, props) => {
  125. const target = sfc.__vccOpts || sfc;
  126. for (const [key, val] of props) {
  127. target[key] = val;
  128. }
  129. return target;
  130. };
  131. const Tooltip = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["__scopeId", "data-v-ee672411"]]);
  132. const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
  133. __name: "BaseSwitch",
  134. props: {
  135. modelValue: { type: Boolean }
  136. },
  137. emits: ["update:modelValue"],
  138. setup(__props, { emit: __emit }) {
  139. return (_ctx, _cache) => {
  140. return vue.openBlock(), vue.createElementBlock("div", {
  141. class: vue.normalizeClass(["switch", { active: _ctx.modelValue }]),
  142. onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("update:modelValue", !_ctx.modelValue))
  143. }, null, 2);
  144. };
  145. }
  146. });
  147. const BaseSwitch = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["__scopeId", "data-v-e7c0fbef"]]);
  148. const matchIconName = /^[a-z0-9]+(-[a-z0-9]+)*$/;
  149. const stringToIcon = (value, validate, allowSimpleName, provider = "") => {
  150. const colonSeparated = value.split(":");
  151. if (value.slice(0, 1) === "@") {
  152. if (colonSeparated.length < 2 || colonSeparated.length > 3) {
  153. return null;
  154. }
  155. provider = colonSeparated.shift().slice(1);
  156. }
  157. if (colonSeparated.length > 3 || !colonSeparated.length) {
  158. return null;
  159. }
  160. if (colonSeparated.length > 1) {
  161. const name2 = colonSeparated.pop();
  162. const prefix = colonSeparated.pop();
  163. const result = {
  164. // Allow provider without '@': "provider:prefix:name"
  165. provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
  166. prefix,
  167. name: name2
  168. };
  169. return validate && !validateIconName(result) ? null : result;
  170. }
  171. const name = colonSeparated[0];
  172. const dashSeparated = name.split("-");
  173. if (dashSeparated.length > 1) {
  174. const result = {
  175. provider,
  176. prefix: dashSeparated.shift(),
  177. name: dashSeparated.join("-")
  178. };
  179. return validate && !validateIconName(result) ? null : result;
  180. }
  181. if (allowSimpleName && provider === "") {
  182. const result = {
  183. provider,
  184. prefix: "",
  185. name
  186. };
  187. return validate && !validateIconName(result, allowSimpleName) ? null : result;
  188. }
  189. return null;
  190. };
  191. const validateIconName = (icon, allowSimpleName) => {
  192. if (!icon) {
  193. return false;
  194. }
  195. return !!((icon.provider === "" || icon.provider.match(matchIconName)) && (allowSimpleName && icon.prefix === "" || icon.prefix.match(matchIconName)) && icon.name.match(matchIconName));
  196. };
  197. const defaultIconDimensions = Object.freeze(
  198. {
  199. left: 0,
  200. top: 0,
  201. width: 16,
  202. height: 16
  203. }
  204. );
  205. const defaultIconTransformations = Object.freeze({
  206. rotate: 0,
  207. vFlip: false,
  208. hFlip: false
  209. });
  210. const defaultIconProps = Object.freeze({
  211. ...defaultIconDimensions,
  212. ...defaultIconTransformations
  213. });
  214. const defaultExtendedIconProps = Object.freeze({
  215. ...defaultIconProps,
  216. body: "",
  217. hidden: false
  218. });
  219. function mergeIconTransformations(obj1, obj2) {
  220. const result = {};
  221. if (!obj1.hFlip !== !obj2.hFlip) {
  222. result.hFlip = true;
  223. }
  224. if (!obj1.vFlip !== !obj2.vFlip) {
  225. result.vFlip = true;
  226. }
  227. const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
  228. if (rotate) {
  229. result.rotate = rotate;
  230. }
  231. return result;
  232. }
  233. function mergeIconData(parent, child) {
  234. const result = mergeIconTransformations(parent, child);
  235. for (const key in defaultExtendedIconProps) {
  236. if (key in defaultIconTransformations) {
  237. if (key in parent && !(key in result)) {
  238. result[key] = defaultIconTransformations[key];
  239. }
  240. } else if (key in child) {
  241. result[key] = child[key];
  242. } else if (key in parent) {
  243. result[key] = parent[key];
  244. }
  245. }
  246. return result;
  247. }
  248. function getIconsTree(data, names) {
  249. const icons = data.icons;
  250. const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
  251. const resolved = /* @__PURE__ */ Object.create(null);
  252. function resolve(name) {
  253. if (icons[name]) {
  254. return resolved[name] = [];
  255. }
  256. if (!(name in resolved)) {
  257. resolved[name] = null;
  258. const parent = aliases[name] && aliases[name].parent;
  259. const value = parent && resolve(parent);
  260. if (value) {
  261. resolved[name] = [parent].concat(value);
  262. }
  263. }
  264. return resolved[name];
  265. }
  266. (names || Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);
  267. return resolved;
  268. }
  269. function internalGetIconData(data, name, tree) {
  270. const icons = data.icons;
  271. const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
  272. let currentProps = {};
  273. function parse(name2) {
  274. currentProps = mergeIconData(
  275. icons[name2] || aliases[name2],
  276. currentProps
  277. );
  278. }
  279. parse(name);
  280. tree.forEach(parse);
  281. return mergeIconData(data, currentProps);
  282. }
  283. function parseIconSet(data, callback) {
  284. const names = [];
  285. if (typeof data !== "object" || typeof data.icons !== "object") {
  286. return names;
  287. }
  288. if (data.not_found instanceof Array) {
  289. data.not_found.forEach((name) => {
  290. callback(name, null);
  291. names.push(name);
  292. });
  293. }
  294. const tree = getIconsTree(data);
  295. for (const name in tree) {
  296. const item = tree[name];
  297. if (item) {
  298. callback(name, internalGetIconData(data, name, item));
  299. names.push(name);
  300. }
  301. }
  302. return names;
  303. }
  304. const optionalPropertyDefaults = {
  305. provider: "",
  306. aliases: {},
  307. not_found: {},
  308. ...defaultIconDimensions
  309. };
  310. function checkOptionalProps(item, defaults) {
  311. for (const prop in defaults) {
  312. if (prop in item && typeof item[prop] !== typeof defaults[prop]) {
  313. return false;
  314. }
  315. }
  316. return true;
  317. }
  318. function quicklyValidateIconSet(obj) {
  319. if (typeof obj !== "object" || obj === null) {
  320. return null;
  321. }
  322. const data = obj;
  323. if (typeof data.prefix !== "string" || !obj.icons || typeof obj.icons !== "object") {
  324. return null;
  325. }
  326. if (!checkOptionalProps(obj, optionalPropertyDefaults)) {
  327. return null;
  328. }
  329. const icons = data.icons;
  330. for (const name in icons) {
  331. const icon = icons[name];
  332. if (!name.match(matchIconName) || typeof icon.body !== "string" || !checkOptionalProps(
  333. icon,
  334. defaultExtendedIconProps
  335. )) {
  336. return null;
  337. }
  338. }
  339. const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
  340. for (const name in aliases) {
  341. const icon = aliases[name];
  342. const parent = icon.parent;
  343. if (!name.match(matchIconName) || typeof parent !== "string" || !icons[parent] && !aliases[parent] || !checkOptionalProps(
  344. icon,
  345. defaultExtendedIconProps
  346. )) {
  347. return null;
  348. }
  349. }
  350. return data;
  351. }
  352. const dataStorage = /* @__PURE__ */ Object.create(null);
  353. function newStorage(provider, prefix) {
  354. return {
  355. provider,
  356. prefix,
  357. icons: /* @__PURE__ */ Object.create(null),
  358. missing: /* @__PURE__ */ new Set()
  359. };
  360. }
  361. function getStorage(provider, prefix) {
  362. const providerStorage = dataStorage[provider] || (dataStorage[provider] = /* @__PURE__ */ Object.create(null));
  363. return providerStorage[prefix] || (providerStorage[prefix] = newStorage(provider, prefix));
  364. }
  365. function addIconSet(storage2, data) {
  366. if (!quicklyValidateIconSet(data)) {
  367. return [];
  368. }
  369. return parseIconSet(data, (name, icon) => {
  370. if (icon) {
  371. storage2.icons[name] = icon;
  372. } else {
  373. storage2.missing.add(name);
  374. }
  375. });
  376. }
  377. function addIconToStorage(storage2, name, icon) {
  378. try {
  379. if (typeof icon.body === "string") {
  380. storage2.icons[name] = { ...icon };
  381. return true;
  382. }
  383. } catch (err) {
  384. }
  385. return false;
  386. }
  387. let simpleNames = false;
  388. function allowSimpleNames(allow) {
  389. if (typeof allow === "boolean") {
  390. simpleNames = allow;
  391. }
  392. return simpleNames;
  393. }
  394. function getIconData(name) {
  395. const icon = typeof name === "string" ? stringToIcon(name, true, simpleNames) : name;
  396. if (icon) {
  397. const storage2 = getStorage(icon.provider, icon.prefix);
  398. const iconName = icon.name;
  399. return storage2.icons[iconName] || (storage2.missing.has(iconName) ? null : void 0);
  400. }
  401. }
  402. function addIcon(name, data) {
  403. const icon = stringToIcon(name, true, simpleNames);
  404. if (!icon) {
  405. return false;
  406. }
  407. const storage2 = getStorage(icon.provider, icon.prefix);
  408. return addIconToStorage(storage2, icon.name, data);
  409. }
  410. function addCollection(data, provider) {
  411. if (typeof data !== "object") {
  412. return false;
  413. }
  414. if (typeof provider !== "string") {
  415. provider = data.provider || "";
  416. }
  417. if (simpleNames && !provider && !data.prefix) {
  418. let added = false;
  419. if (quicklyValidateIconSet(data)) {
  420. data.prefix = "";
  421. parseIconSet(data, (name, icon) => {
  422. if (icon && addIcon(name, icon)) {
  423. added = true;
  424. }
  425. });
  426. }
  427. return added;
  428. }
  429. const prefix = data.prefix;
  430. if (!validateIconName({
  431. provider,
  432. prefix,
  433. name: "a"
  434. })) {
  435. return false;
  436. }
  437. const storage2 = getStorage(provider, prefix);
  438. return !!addIconSet(storage2, data);
  439. }
  440. const defaultIconSizeCustomisations = Object.freeze({
  441. width: null,
  442. height: null
  443. });
  444. const defaultIconCustomisations = Object.freeze({
  445. // Dimensions
  446. ...defaultIconSizeCustomisations,
  447. // Transformations
  448. ...defaultIconTransformations
  449. });
  450. const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
  451. const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
  452. function calculateSize(size, ratio, precision) {
  453. if (ratio === 1) {
  454. return size;
  455. }
  456. precision = precision || 100;
  457. if (typeof size === "number") {
  458. return Math.ceil(size * ratio * precision) / precision;
  459. }
  460. if (typeof size !== "string") {
  461. return size;
  462. }
  463. const oldParts = size.split(unitsSplit);
  464. if (oldParts === null || !oldParts.length) {
  465. return size;
  466. }
  467. const newParts = [];
  468. let code = oldParts.shift();
  469. let isNumber = unitsTest.test(code);
  470. while (true) {
  471. if (isNumber) {
  472. const num = parseFloat(code);
  473. if (isNaN(num)) {
  474. newParts.push(code);
  475. } else {
  476. newParts.push(Math.ceil(num * ratio * precision) / precision);
  477. }
  478. } else {
  479. newParts.push(code);
  480. }
  481. code = oldParts.shift();
  482. if (code === void 0) {
  483. return newParts.join("");
  484. }
  485. isNumber = !isNumber;
  486. }
  487. }
  488. const isUnsetKeyword = (value) => value === "unset" || value === "undefined" || value === "none";
  489. function iconToSVG(icon, customisations) {
  490. const fullIcon = {
  491. ...defaultIconProps,
  492. ...icon
  493. };
  494. const fullCustomisations = {
  495. ...defaultIconCustomisations,
  496. ...customisations
  497. };
  498. const box = {
  499. left: fullIcon.left,
  500. top: fullIcon.top,
  501. width: fullIcon.width,
  502. height: fullIcon.height
  503. };
  504. let body = fullIcon.body;
  505. [fullIcon, fullCustomisations].forEach((props) => {
  506. const transformations = [];
  507. const hFlip = props.hFlip;
  508. const vFlip = props.vFlip;
  509. let rotation = props.rotate;
  510. if (hFlip) {
  511. if (vFlip) {
  512. rotation += 2;
  513. } else {
  514. transformations.push(
  515. "translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")"
  516. );
  517. transformations.push("scale(-1 1)");
  518. box.top = box.left = 0;
  519. }
  520. } else if (vFlip) {
  521. transformations.push(
  522. "translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")"
  523. );
  524. transformations.push("scale(1 -1)");
  525. box.top = box.left = 0;
  526. }
  527. let tempValue;
  528. if (rotation < 0) {
  529. rotation -= Math.floor(rotation / 4) * 4;
  530. }
  531. rotation = rotation % 4;
  532. switch (rotation) {
  533. case 1:
  534. tempValue = box.height / 2 + box.top;
  535. transformations.unshift(
  536. "rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")"
  537. );
  538. break;
  539. case 2:
  540. transformations.unshift(
  541. "rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")"
  542. );
  543. break;
  544. case 3:
  545. tempValue = box.width / 2 + box.left;
  546. transformations.unshift(
  547. "rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")"
  548. );
  549. break;
  550. }
  551. if (rotation % 2 === 1) {
  552. if (box.left !== box.top) {
  553. tempValue = box.left;
  554. box.left = box.top;
  555. box.top = tempValue;
  556. }
  557. if (box.width !== box.height) {
  558. tempValue = box.width;
  559. box.width = box.height;
  560. box.height = tempValue;
  561. }
  562. }
  563. if (transformations.length) {
  564. body = '<g transform="' + transformations.join(" ") + '">' + body + "</g>";
  565. }
  566. });
  567. const customisationsWidth = fullCustomisations.width;
  568. const customisationsHeight = fullCustomisations.height;
  569. const boxWidth = box.width;
  570. const boxHeight = box.height;
  571. let width;
  572. let height;
  573. if (customisationsWidth === null) {
  574. height = customisationsHeight === null ? "1em" : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
  575. width = calculateSize(height, boxWidth / boxHeight);
  576. } else {
  577. width = customisationsWidth === "auto" ? boxWidth : customisationsWidth;
  578. height = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
  579. }
  580. const attributes = {};
  581. const setAttr = (prop, value) => {
  582. if (!isUnsetKeyword(value)) {
  583. attributes[prop] = value.toString();
  584. }
  585. };
  586. setAttr("width", width);
  587. setAttr("height", height);
  588. attributes.viewBox = box.left.toString() + " " + box.top.toString() + " " + boxWidth.toString() + " " + boxHeight.toString();
  589. return {
  590. attributes,
  591. body
  592. };
  593. }
  594. const regex = /\sid="(\S+)"/g;
  595. const randomPrefix = "IconifyId" + Date.now().toString(16) + (Math.random() * 16777216 | 0).toString(16);
  596. let counter = 0;
  597. function replaceIDs(body, prefix = randomPrefix) {
  598. const ids = [];
  599. let match;
  600. while (match = regex.exec(body)) {
  601. ids.push(match[1]);
  602. }
  603. if (!ids.length) {
  604. return body;
  605. }
  606. const suffix = "suffix" + (Math.random() * 16777216 | Date.now()).toString(16);
  607. ids.forEach((id) => {
  608. const newID = typeof prefix === "function" ? prefix(id) : prefix + (counter++).toString();
  609. const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  610. body = body.replace(
  611. // Allowed characters before id: [#;"]
  612. // Allowed characters after id: [)"], .[a-z]
  613. new RegExp('([#;"])(' + escapedID + ')([")]|\\.[a-z])', "g"),
  614. "$1" + newID + suffix + "$3"
  615. );
  616. });
  617. body = body.replace(new RegExp(suffix, "g"), "");
  618. return body;
  619. }
  620. const storage = /* @__PURE__ */ Object.create(null);
  621. function setAPIModule(provider, item) {
  622. storage[provider] = item;
  623. }
  624. function getAPIModule(provider) {
  625. return storage[provider] || storage[""];
  626. }
  627. function createAPIConfig(source) {
  628. let resources;
  629. if (typeof source.resources === "string") {
  630. resources = [source.resources];
  631. } else {
  632. resources = source.resources;
  633. if (!(resources instanceof Array) || !resources.length) {
  634. return null;
  635. }
  636. }
  637. const result = {
  638. // API hosts
  639. resources,
  640. // Root path
  641. path: source.path || "/",
  642. // URL length limit
  643. maxURL: source.maxURL || 500,
  644. // Timeout before next host is used.
  645. rotate: source.rotate || 750,
  646. // Timeout before failing query.
  647. timeout: source.timeout || 5e3,
  648. // Randomise default API end point.
  649. random: source.random === true,
  650. // Start index
  651. index: source.index || 0,
  652. // Receive data after time out (used if time out kicks in first, then API module sends data anyway).
  653. dataAfterTimeout: source.dataAfterTimeout !== false
  654. };
  655. return result;
  656. }
  657. const configStorage = /* @__PURE__ */ Object.create(null);
  658. const fallBackAPISources = [
  659. "https://api.simplesvg.com",
  660. "https://api.unisvg.com"
  661. ];
  662. const fallBackAPI = [];
  663. while (fallBackAPISources.length > 0) {
  664. if (fallBackAPISources.length === 1) {
  665. fallBackAPI.push(fallBackAPISources.shift());
  666. } else {
  667. if (Math.random() > 0.5) {
  668. fallBackAPI.push(fallBackAPISources.shift());
  669. } else {
  670. fallBackAPI.push(fallBackAPISources.pop());
  671. }
  672. }
  673. }
  674. configStorage[""] = createAPIConfig({
  675. resources: ["https://api.iconify.design"].concat(fallBackAPI)
  676. });
  677. function addAPIProvider(provider, customConfig) {
  678. const config2 = createAPIConfig(customConfig);
  679. if (config2 === null) {
  680. return false;
  681. }
  682. configStorage[provider] = config2;
  683. return true;
  684. }
  685. function getAPIConfig(provider) {
  686. return configStorage[provider];
  687. }
  688. const detectFetch = () => {
  689. let callback;
  690. try {
  691. callback = fetch;
  692. if (typeof callback === "function") {
  693. return callback;
  694. }
  695. } catch (err) {
  696. }
  697. };
  698. let fetchModule = detectFetch();
  699. function calculateMaxLength(provider, prefix) {
  700. const config2 = getAPIConfig(provider);
  701. if (!config2) {
  702. return 0;
  703. }
  704. let result;
  705. if (!config2.maxURL) {
  706. result = 0;
  707. } else {
  708. let maxHostLength = 0;
  709. config2.resources.forEach((item) => {
  710. const host = item;
  711. maxHostLength = Math.max(maxHostLength, host.length);
  712. });
  713. const url = prefix + ".json?icons=";
  714. result = config2.maxURL - maxHostLength - config2.path.length - url.length;
  715. }
  716. return result;
  717. }
  718. function shouldAbort(status) {
  719. return status === 404;
  720. }
  721. const prepare = (provider, prefix, icons) => {
  722. const results = [];
  723. const maxLength = calculateMaxLength(provider, prefix);
  724. const type = "icons";
  725. let item = {
  726. type,
  727. provider,
  728. prefix,
  729. icons: []
  730. };
  731. let length = 0;
  732. icons.forEach((name, index) => {
  733. length += name.length + 1;
  734. if (length >= maxLength && index > 0) {
  735. results.push(item);
  736. item = {
  737. type,
  738. provider,
  739. prefix,
  740. icons: []
  741. };
  742. length = name.length;
  743. }
  744. item.icons.push(name);
  745. });
  746. results.push(item);
  747. return results;
  748. };
  749. function getPath(provider) {
  750. if (typeof provider === "string") {
  751. const config2 = getAPIConfig(provider);
  752. if (config2) {
  753. return config2.path;
  754. }
  755. }
  756. return "/";
  757. }
  758. const send = (host, params, callback) => {
  759. if (!fetchModule) {
  760. callback("abort", 424);
  761. return;
  762. }
  763. let path = getPath(params.provider);
  764. switch (params.type) {
  765. case "icons": {
  766. const prefix = params.prefix;
  767. const icons = params.icons;
  768. const iconsList = icons.join(",");
  769. const urlParams = new URLSearchParams({
  770. icons: iconsList
  771. });
  772. path += prefix + ".json?" + urlParams.toString();
  773. break;
  774. }
  775. case "custom": {
  776. const uri = params.uri;
  777. path += uri.slice(0, 1) === "/" ? uri.slice(1) : uri;
  778. break;
  779. }
  780. default:
  781. callback("abort", 400);
  782. return;
  783. }
  784. let defaultError = 503;
  785. fetchModule(host + path).then((response) => {
  786. const status = response.status;
  787. if (status !== 200) {
  788. setTimeout(() => {
  789. callback(shouldAbort(status) ? "abort" : "next", status);
  790. });
  791. return;
  792. }
  793. defaultError = 501;
  794. return response.json();
  795. }).then((data) => {
  796. if (typeof data !== "object" || data === null) {
  797. setTimeout(() => {
  798. if (data === 404) {
  799. callback("abort", data);
  800. } else {
  801. callback("next", defaultError);
  802. }
  803. });
  804. return;
  805. }
  806. setTimeout(() => {
  807. callback("success", data);
  808. });
  809. }).catch(() => {
  810. callback("next", defaultError);
  811. });
  812. };
  813. const fetchAPIModule = {
  814. prepare,
  815. send
  816. };
  817. function sortIcons(icons) {
  818. const result = {
  819. loaded: [],
  820. missing: [],
  821. pending: []
  822. };
  823. const storage2 = /* @__PURE__ */ Object.create(null);
  824. icons.sort((a, b) => {
  825. if (a.provider !== b.provider) {
  826. return a.provider.localeCompare(b.provider);
  827. }
  828. if (a.prefix !== b.prefix) {
  829. return a.prefix.localeCompare(b.prefix);
  830. }
  831. return a.name.localeCompare(b.name);
  832. });
  833. let lastIcon = {
  834. provider: "",
  835. prefix: "",
  836. name: ""
  837. };
  838. icons.forEach((icon) => {
  839. if (lastIcon.name === icon.name && lastIcon.prefix === icon.prefix && lastIcon.provider === icon.provider) {
  840. return;
  841. }
  842. lastIcon = icon;
  843. const provider = icon.provider;
  844. const prefix = icon.prefix;
  845. const name = icon.name;
  846. const providerStorage = storage2[provider] || (storage2[provider] = /* @__PURE__ */ Object.create(null));
  847. const localStorage2 = providerStorage[prefix] || (providerStorage[prefix] = getStorage(provider, prefix));
  848. let list;
  849. if (name in localStorage2.icons) {
  850. list = result.loaded;
  851. } else if (prefix === "" || localStorage2.missing.has(name)) {
  852. list = result.missing;
  853. } else {
  854. list = result.pending;
  855. }
  856. const item = {
  857. provider,
  858. prefix,
  859. name
  860. };
  861. list.push(item);
  862. });
  863. return result;
  864. }
  865. function removeCallback(storages, id) {
  866. storages.forEach((storage2) => {
  867. const items = storage2.loaderCallbacks;
  868. if (items) {
  869. storage2.loaderCallbacks = items.filter((row) => row.id !== id);
  870. }
  871. });
  872. }
  873. function updateCallbacks(storage2) {
  874. if (!storage2.pendingCallbacksFlag) {
  875. storage2.pendingCallbacksFlag = true;
  876. setTimeout(() => {
  877. storage2.pendingCallbacksFlag = false;
  878. const items = storage2.loaderCallbacks ? storage2.loaderCallbacks.slice(0) : [];
  879. if (!items.length) {
  880. return;
  881. }
  882. let hasPending = false;
  883. const provider = storage2.provider;
  884. const prefix = storage2.prefix;
  885. items.forEach((item) => {
  886. const icons = item.icons;
  887. const oldLength = icons.pending.length;
  888. icons.pending = icons.pending.filter((icon) => {
  889. if (icon.prefix !== prefix) {
  890. return true;
  891. }
  892. const name = icon.name;
  893. if (storage2.icons[name]) {
  894. icons.loaded.push({
  895. provider,
  896. prefix,
  897. name
  898. });
  899. } else if (storage2.missing.has(name)) {
  900. icons.missing.push({
  901. provider,
  902. prefix,
  903. name
  904. });
  905. } else {
  906. hasPending = true;
  907. return true;
  908. }
  909. return false;
  910. });
  911. if (icons.pending.length !== oldLength) {
  912. if (!hasPending) {
  913. removeCallback([storage2], item.id);
  914. }
  915. item.callback(
  916. icons.loaded.slice(0),
  917. icons.missing.slice(0),
  918. icons.pending.slice(0),
  919. item.abort
  920. );
  921. }
  922. });
  923. });
  924. }
  925. }
  926. let idCounter = 0;
  927. function storeCallback(callback, icons, pendingSources) {
  928. const id = idCounter++;
  929. const abort = removeCallback.bind(null, pendingSources, id);
  930. if (!icons.pending.length) {
  931. return abort;
  932. }
  933. const item = {
  934. id,
  935. icons,
  936. callback,
  937. abort
  938. };
  939. pendingSources.forEach((storage2) => {
  940. (storage2.loaderCallbacks || (storage2.loaderCallbacks = [])).push(item);
  941. });
  942. return abort;
  943. }
  944. function listToIcons(list, validate = true, simpleNames2 = false) {
  945. const result = [];
  946. list.forEach((item) => {
  947. const icon = typeof item === "string" ? stringToIcon(item, validate, simpleNames2) : item;
  948. if (icon) {
  949. result.push(icon);
  950. }
  951. });
  952. return result;
  953. }
  954. var defaultConfig = {
  955. resources: [],
  956. index: 0,
  957. timeout: 2e3,
  958. rotate: 750,
  959. random: false,
  960. dataAfterTimeout: false
  961. };
  962. function sendQuery(config2, payload, query, done) {
  963. const resourcesCount = config2.resources.length;
  964. const startIndex = config2.random ? Math.floor(Math.random() * resourcesCount) : config2.index;
  965. let resources;
  966. if (config2.random) {
  967. let list = config2.resources.slice(0);
  968. resources = [];
  969. while (list.length > 1) {
  970. const nextIndex = Math.floor(Math.random() * list.length);
  971. resources.push(list[nextIndex]);
  972. list = list.slice(0, nextIndex).concat(list.slice(nextIndex + 1));
  973. }
  974. resources = resources.concat(list);
  975. } else {
  976. resources = config2.resources.slice(startIndex).concat(config2.resources.slice(0, startIndex));
  977. }
  978. const startTime = Date.now();
  979. let status = "pending";
  980. let queriesSent = 0;
  981. let lastError;
  982. let timer = null;
  983. let queue = [];
  984. let doneCallbacks = [];
  985. if (typeof done === "function") {
  986. doneCallbacks.push(done);
  987. }
  988. function resetTimer() {
  989. if (timer) {
  990. clearTimeout(timer);
  991. timer = null;
  992. }
  993. }
  994. function abort() {
  995. if (status === "pending") {
  996. status = "aborted";
  997. }
  998. resetTimer();
  999. queue.forEach((item) => {
  1000. if (item.status === "pending") {
  1001. item.status = "aborted";
  1002. }
  1003. });
  1004. queue = [];
  1005. }
  1006. function subscribe(callback, overwrite) {
  1007. if (overwrite) {
  1008. doneCallbacks = [];
  1009. }
  1010. if (typeof callback === "function") {
  1011. doneCallbacks.push(callback);
  1012. }
  1013. }
  1014. function getQueryStatus() {
  1015. return {
  1016. startTime,
  1017. payload,
  1018. status,
  1019. queriesSent,
  1020. queriesPending: queue.length,
  1021. subscribe,
  1022. abort
  1023. };
  1024. }
  1025. function failQuery() {
  1026. status = "failed";
  1027. doneCallbacks.forEach((callback) => {
  1028. callback(void 0, lastError);
  1029. });
  1030. }
  1031. function clearQueue() {
  1032. queue.forEach((item) => {
  1033. if (item.status === "pending") {
  1034. item.status = "aborted";
  1035. }
  1036. });
  1037. queue = [];
  1038. }
  1039. function moduleResponse(item, response, data) {
  1040. const isError = response !== "success";
  1041. queue = queue.filter((queued) => queued !== item);
  1042. switch (status) {
  1043. case "pending":
  1044. break;
  1045. case "failed":
  1046. if (isError || !config2.dataAfterTimeout) {
  1047. return;
  1048. }
  1049. break;
  1050. default:
  1051. return;
  1052. }
  1053. if (response === "abort") {
  1054. lastError = data;
  1055. failQuery();
  1056. return;
  1057. }
  1058. if (isError) {
  1059. lastError = data;
  1060. if (!queue.length) {
  1061. if (!resources.length) {
  1062. failQuery();
  1063. } else {
  1064. execNext();
  1065. }
  1066. }
  1067. return;
  1068. }
  1069. resetTimer();
  1070. clearQueue();
  1071. if (!config2.random) {
  1072. const index = config2.resources.indexOf(item.resource);
  1073. if (index !== -1 && index !== config2.index) {
  1074. config2.index = index;
  1075. }
  1076. }
  1077. status = "completed";
  1078. doneCallbacks.forEach((callback) => {
  1079. callback(data);
  1080. });
  1081. }
  1082. function execNext() {
  1083. if (status !== "pending") {
  1084. return;
  1085. }
  1086. resetTimer();
  1087. const resource = resources.shift();
  1088. if (resource === void 0) {
  1089. if (queue.length) {
  1090. timer = setTimeout(() => {
  1091. resetTimer();
  1092. if (status === "pending") {
  1093. clearQueue();
  1094. failQuery();
  1095. }
  1096. }, config2.timeout);
  1097. return;
  1098. }
  1099. failQuery();
  1100. return;
  1101. }
  1102. const item = {
  1103. status: "pending",
  1104. resource,
  1105. callback: (status2, data) => {
  1106. moduleResponse(item, status2, data);
  1107. }
  1108. };
  1109. queue.push(item);
  1110. queriesSent++;
  1111. timer = setTimeout(execNext, config2.rotate);
  1112. query(resource, payload, item.callback);
  1113. }
  1114. setTimeout(execNext);
  1115. return getQueryStatus;
  1116. }
  1117. function initRedundancy(cfg) {
  1118. const config2 = {
  1119. ...defaultConfig,
  1120. ...cfg
  1121. };
  1122. let queries = [];
  1123. function cleanup() {
  1124. queries = queries.filter((item) => item().status === "pending");
  1125. }
  1126. function query(payload, queryCallback, doneCallback) {
  1127. const query2 = sendQuery(
  1128. config2,
  1129. payload,
  1130. queryCallback,
  1131. (data, error) => {
  1132. cleanup();
  1133. if (doneCallback) {
  1134. doneCallback(data, error);
  1135. }
  1136. }
  1137. );
  1138. queries.push(query2);
  1139. return query2;
  1140. }
  1141. function find(callback) {
  1142. return queries.find((value) => {
  1143. return callback(value);
  1144. }) || null;
  1145. }
  1146. const instance = {
  1147. query,
  1148. find,
  1149. setIndex: (index) => {
  1150. config2.index = index;
  1151. },
  1152. getIndex: () => config2.index,
  1153. cleanup
  1154. };
  1155. return instance;
  1156. }
  1157. function emptyCallback$1() {
  1158. }
  1159. const redundancyCache = /* @__PURE__ */ Object.create(null);
  1160. function getRedundancyCache(provider) {
  1161. if (!redundancyCache[provider]) {
  1162. const config2 = getAPIConfig(provider);
  1163. if (!config2) {
  1164. return;
  1165. }
  1166. const redundancy = initRedundancy(config2);
  1167. const cachedReundancy = {
  1168. config: config2,
  1169. redundancy
  1170. };
  1171. redundancyCache[provider] = cachedReundancy;
  1172. }
  1173. return redundancyCache[provider];
  1174. }
  1175. function sendAPIQuery(target, query, callback) {
  1176. let redundancy;
  1177. let send2;
  1178. if (typeof target === "string") {
  1179. const api = getAPIModule(target);
  1180. if (!api) {
  1181. callback(void 0, 424);
  1182. return emptyCallback$1;
  1183. }
  1184. send2 = api.send;
  1185. const cached = getRedundancyCache(target);
  1186. if (cached) {
  1187. redundancy = cached.redundancy;
  1188. }
  1189. } else {
  1190. const config2 = createAPIConfig(target);
  1191. if (config2) {
  1192. redundancy = initRedundancy(config2);
  1193. const moduleKey = target.resources ? target.resources[0] : "";
  1194. const api = getAPIModule(moduleKey);
  1195. if (api) {
  1196. send2 = api.send;
  1197. }
  1198. }
  1199. }
  1200. if (!redundancy || !send2) {
  1201. callback(void 0, 424);
  1202. return emptyCallback$1;
  1203. }
  1204. return redundancy.query(query, send2, callback)().abort;
  1205. }
  1206. const browserCacheVersion = "iconify2";
  1207. const browserCachePrefix = "iconify";
  1208. const browserCacheCountKey = browserCachePrefix + "-count";
  1209. const browserCacheVersionKey = browserCachePrefix + "-version";
  1210. const browserStorageHour = 36e5;
  1211. const browserStorageCacheExpiration = 168;
  1212. function getStoredItem(func, key) {
  1213. try {
  1214. return func.getItem(key);
  1215. } catch (err) {
  1216. }
  1217. }
  1218. function setStoredItem(func, key, value) {
  1219. try {
  1220. func.setItem(key, value);
  1221. return true;
  1222. } catch (err) {
  1223. }
  1224. }
  1225. function removeStoredItem(func, key) {
  1226. try {
  1227. func.removeItem(key);
  1228. } catch (err) {
  1229. }
  1230. }
  1231. function setBrowserStorageItemsCount(storage2, value) {
  1232. return setStoredItem(storage2, browserCacheCountKey, value.toString());
  1233. }
  1234. function getBrowserStorageItemsCount(storage2) {
  1235. return parseInt(getStoredItem(storage2, browserCacheCountKey)) || 0;
  1236. }
  1237. const browserStorageConfig = {
  1238. local: true,
  1239. session: true
  1240. };
  1241. const browserStorageEmptyItems = {
  1242. local: /* @__PURE__ */ new Set(),
  1243. session: /* @__PURE__ */ new Set()
  1244. };
  1245. let browserStorageStatus = false;
  1246. function setBrowserStorageStatus(status) {
  1247. browserStorageStatus = status;
  1248. }
  1249. let _window = typeof window === "undefined" ? {} : window;
  1250. function getBrowserStorage(key) {
  1251. const attr = key + "Storage";
  1252. try {
  1253. if (_window && _window[attr] && typeof _window[attr].length === "number") {
  1254. return _window[attr];
  1255. }
  1256. } catch (err) {
  1257. }
  1258. browserStorageConfig[key] = false;
  1259. }
  1260. function iterateBrowserStorage(key, callback) {
  1261. const func = getBrowserStorage(key);
  1262. if (!func) {
  1263. return;
  1264. }
  1265. const version = getStoredItem(func, browserCacheVersionKey);
  1266. if (version !== browserCacheVersion) {
  1267. if (version) {
  1268. const total2 = getBrowserStorageItemsCount(func);
  1269. for (let i = 0; i < total2; i++) {
  1270. removeStoredItem(func, browserCachePrefix + i.toString());
  1271. }
  1272. }
  1273. setStoredItem(func, browserCacheVersionKey, browserCacheVersion);
  1274. setBrowserStorageItemsCount(func, 0);
  1275. return;
  1276. }
  1277. const minTime = Math.floor(Date.now() / browserStorageHour) - browserStorageCacheExpiration;
  1278. const parseItem = (index) => {
  1279. const name = browserCachePrefix + index.toString();
  1280. const item = getStoredItem(func, name);
  1281. if (typeof item !== "string") {
  1282. return;
  1283. }
  1284. try {
  1285. const data = JSON.parse(item);
  1286. if (typeof data === "object" && typeof data.cached === "number" && data.cached > minTime && typeof data.provider === "string" && typeof data.data === "object" && typeof data.data.prefix === "string" && // Valid item: run callback
  1287. callback(data, index)) {
  1288. return true;
  1289. }
  1290. } catch (err) {
  1291. }
  1292. removeStoredItem(func, name);
  1293. };
  1294. let total = getBrowserStorageItemsCount(func);
  1295. for (let i = total - 1; i >= 0; i--) {
  1296. if (!parseItem(i)) {
  1297. if (i === total - 1) {
  1298. total--;
  1299. setBrowserStorageItemsCount(func, total);
  1300. } else {
  1301. browserStorageEmptyItems[key].add(i);
  1302. }
  1303. }
  1304. }
  1305. }
  1306. function initBrowserStorage() {
  1307. if (browserStorageStatus) {
  1308. return;
  1309. }
  1310. setBrowserStorageStatus(true);
  1311. for (const key in browserStorageConfig) {
  1312. iterateBrowserStorage(key, (item) => {
  1313. const iconSet = item.data;
  1314. const provider = item.provider;
  1315. const prefix = iconSet.prefix;
  1316. const storage2 = getStorage(
  1317. provider,
  1318. prefix
  1319. );
  1320. if (!addIconSet(storage2, iconSet).length) {
  1321. return false;
  1322. }
  1323. const lastModified = iconSet.lastModified || -1;
  1324. storage2.lastModifiedCached = storage2.lastModifiedCached ? Math.min(storage2.lastModifiedCached, lastModified) : lastModified;
  1325. return true;
  1326. });
  1327. }
  1328. }
  1329. function updateLastModified(storage2, lastModified) {
  1330. const lastValue = storage2.lastModifiedCached;
  1331. if (
  1332. // Matches or newer
  1333. lastValue && lastValue >= lastModified
  1334. ) {
  1335. return lastValue === lastModified;
  1336. }
  1337. storage2.lastModifiedCached = lastModified;
  1338. if (lastValue) {
  1339. for (const key in browserStorageConfig) {
  1340. iterateBrowserStorage(key, (item) => {
  1341. const iconSet = item.data;
  1342. return item.provider !== storage2.provider || iconSet.prefix !== storage2.prefix || iconSet.lastModified === lastModified;
  1343. });
  1344. }
  1345. }
  1346. return true;
  1347. }
  1348. function storeInBrowserStorage(storage2, data) {
  1349. if (!browserStorageStatus) {
  1350. initBrowserStorage();
  1351. }
  1352. function store(key) {
  1353. let func;
  1354. if (!browserStorageConfig[key] || !(func = getBrowserStorage(key))) {
  1355. return;
  1356. }
  1357. const set = browserStorageEmptyItems[key];
  1358. let index;
  1359. if (set.size) {
  1360. set.delete(index = Array.from(set).shift());
  1361. } else {
  1362. index = getBrowserStorageItemsCount(func);
  1363. if (!setBrowserStorageItemsCount(func, index + 1)) {
  1364. return;
  1365. }
  1366. }
  1367. const item = {
  1368. cached: Math.floor(Date.now() / browserStorageHour),
  1369. provider: storage2.provider,
  1370. data
  1371. };
  1372. return setStoredItem(
  1373. func,
  1374. browserCachePrefix + index.toString(),
  1375. JSON.stringify(item)
  1376. );
  1377. }
  1378. if (data.lastModified && !updateLastModified(storage2, data.lastModified)) {
  1379. return;
  1380. }
  1381. if (!Object.keys(data.icons).length) {
  1382. return;
  1383. }
  1384. if (data.not_found) {
  1385. data = Object.assign({}, data);
  1386. delete data.not_found;
  1387. }
  1388. if (!store("local")) {
  1389. store("session");
  1390. }
  1391. }
  1392. function emptyCallback() {
  1393. }
  1394. function loadedNewIcons(storage2) {
  1395. if (!storage2.iconsLoaderFlag) {
  1396. storage2.iconsLoaderFlag = true;
  1397. setTimeout(() => {
  1398. storage2.iconsLoaderFlag = false;
  1399. updateCallbacks(storage2);
  1400. });
  1401. }
  1402. }
  1403. function loadNewIcons(storage2, icons) {
  1404. if (!storage2.iconsToLoad) {
  1405. storage2.iconsToLoad = icons;
  1406. } else {
  1407. storage2.iconsToLoad = storage2.iconsToLoad.concat(icons).sort();
  1408. }
  1409. if (!storage2.iconsQueueFlag) {
  1410. storage2.iconsQueueFlag = true;
  1411. setTimeout(() => {
  1412. storage2.iconsQueueFlag = false;
  1413. const { provider, prefix } = storage2;
  1414. const icons2 = storage2.iconsToLoad;
  1415. delete storage2.iconsToLoad;
  1416. let api;
  1417. if (!icons2 || !(api = getAPIModule(provider))) {
  1418. return;
  1419. }
  1420. const params = api.prepare(provider, prefix, icons2);
  1421. params.forEach((item) => {
  1422. sendAPIQuery(provider, item, (data) => {
  1423. if (typeof data !== "object") {
  1424. item.icons.forEach((name) => {
  1425. storage2.missing.add(name);
  1426. });
  1427. } else {
  1428. try {
  1429. const parsed = addIconSet(
  1430. storage2,
  1431. data
  1432. );
  1433. if (!parsed.length) {
  1434. return;
  1435. }
  1436. const pending = storage2.pendingIcons;
  1437. if (pending) {
  1438. parsed.forEach((name) => {
  1439. pending.delete(name);
  1440. });
  1441. }
  1442. storeInBrowserStorage(storage2, data);
  1443. } catch (err) {
  1444. console.error(err);
  1445. }
  1446. }
  1447. loadedNewIcons(storage2);
  1448. });
  1449. });
  1450. });
  1451. }
  1452. }
  1453. const loadIcons = (icons, callback) => {
  1454. const cleanedIcons = listToIcons(icons, true, allowSimpleNames());
  1455. const sortedIcons = sortIcons(cleanedIcons);
  1456. if (!sortedIcons.pending.length) {
  1457. let callCallback = true;
  1458. if (callback) {
  1459. setTimeout(() => {
  1460. if (callCallback) {
  1461. callback(
  1462. sortedIcons.loaded,
  1463. sortedIcons.missing,
  1464. sortedIcons.pending,
  1465. emptyCallback
  1466. );
  1467. }
  1468. });
  1469. }
  1470. return () => {
  1471. callCallback = false;
  1472. };
  1473. }
  1474. const newIcons = /* @__PURE__ */ Object.create(null);
  1475. const sources = [];
  1476. let lastProvider, lastPrefix;
  1477. sortedIcons.pending.forEach((icon) => {
  1478. const { provider, prefix } = icon;
  1479. if (prefix === lastPrefix && provider === lastProvider) {
  1480. return;
  1481. }
  1482. lastProvider = provider;
  1483. lastPrefix = prefix;
  1484. sources.push(getStorage(provider, prefix));
  1485. const providerNewIcons = newIcons[provider] || (newIcons[provider] = /* @__PURE__ */ Object.create(null));
  1486. if (!providerNewIcons[prefix]) {
  1487. providerNewIcons[prefix] = [];
  1488. }
  1489. });
  1490. sortedIcons.pending.forEach((icon) => {
  1491. const { provider, prefix, name } = icon;
  1492. const storage2 = getStorage(provider, prefix);
  1493. const pendingQueue = storage2.pendingIcons || (storage2.pendingIcons = /* @__PURE__ */ new Set());
  1494. if (!pendingQueue.has(name)) {
  1495. pendingQueue.add(name);
  1496. newIcons[provider][prefix].push(name);
  1497. }
  1498. });
  1499. sources.forEach((storage2) => {
  1500. const { provider, prefix } = storage2;
  1501. if (newIcons[provider][prefix].length) {
  1502. loadNewIcons(storage2, newIcons[provider][prefix]);
  1503. }
  1504. });
  1505. return callback ? storeCallback(callback, sortedIcons, sources) : emptyCallback;
  1506. };
  1507. function mergeCustomisations(defaults, item) {
  1508. const result = {
  1509. ...defaults
  1510. };
  1511. for (const key in item) {
  1512. const value = item[key];
  1513. const valueType = typeof value;
  1514. if (key in defaultIconSizeCustomisations) {
  1515. if (value === null || value && (valueType === "string" || valueType === "number")) {
  1516. result[key] = value;
  1517. }
  1518. } else if (valueType === typeof result[key]) {
  1519. result[key] = key === "rotate" ? value % 4 : value;
  1520. }
  1521. }
  1522. return result;
  1523. }
  1524. const separator = /[\s,]+/;
  1525. function flipFromString(custom, flip) {
  1526. flip.split(separator).forEach((str) => {
  1527. const value = str.trim();
  1528. switch (value) {
  1529. case "horizontal":
  1530. custom.hFlip = true;
  1531. break;
  1532. case "vertical":
  1533. custom.vFlip = true;
  1534. break;
  1535. }
  1536. });
  1537. }
  1538. function rotateFromString(value, defaultValue = 0) {
  1539. const units = value.replace(/^-?[0-9.]*/, "");
  1540. function cleanup(value2) {
  1541. while (value2 < 0) {
  1542. value2 += 4;
  1543. }
  1544. return value2 % 4;
  1545. }
  1546. if (units === "") {
  1547. const num = parseInt(value);
  1548. return isNaN(num) ? 0 : cleanup(num);
  1549. } else if (units !== value) {
  1550. let split = 0;
  1551. switch (units) {
  1552. case "%":
  1553. split = 25;
  1554. break;
  1555. case "deg":
  1556. split = 90;
  1557. }
  1558. if (split) {
  1559. let num = parseFloat(value.slice(0, value.length - units.length));
  1560. if (isNaN(num)) {
  1561. return 0;
  1562. }
  1563. num = num / split;
  1564. return num % 1 === 0 ? cleanup(num) : 0;
  1565. }
  1566. }
  1567. return defaultValue;
  1568. }
  1569. function iconToHTML(body, attributes) {
  1570. let renderAttribsHTML = body.indexOf("xlink:") === -1 ? "" : ' xmlns:xlink="http://www.w3.org/1999/xlink"';
  1571. for (const attr in attributes) {
  1572. renderAttribsHTML += " " + attr + '="' + attributes[attr] + '"';
  1573. }
  1574. return '<svg xmlns="http://www.w3.org/2000/svg"' + renderAttribsHTML + ">" + body + "</svg>";
  1575. }
  1576. function encodeSVGforURL(svg) {
  1577. return svg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
  1578. }
  1579. function svgToData(svg) {
  1580. return "data:image/svg+xml," + encodeSVGforURL(svg);
  1581. }
  1582. function svgToURL(svg) {
  1583. return 'url("' + svgToData(svg) + '")';
  1584. }
  1585. const defaultExtendedIconCustomisations = {
  1586. ...defaultIconCustomisations,
  1587. inline: false
  1588. };
  1589. const svgDefaults = {
  1590. "xmlns": "http://www.w3.org/2000/svg",
  1591. "xmlns:xlink": "http://www.w3.org/1999/xlink",
  1592. "aria-hidden": true,
  1593. "role": "img"
  1594. };
  1595. const commonProps = {
  1596. display: "inline-block"
  1597. };
  1598. const monotoneProps = {
  1599. backgroundColor: "currentColor"
  1600. };
  1601. const coloredProps = {
  1602. backgroundColor: "transparent"
  1603. };
  1604. const propsToAdd = {
  1605. Image: "var(--svg)",
  1606. Repeat: "no-repeat",
  1607. Size: "100% 100%"
  1608. };
  1609. const propsToAddTo = {
  1610. webkitMask: monotoneProps,
  1611. mask: monotoneProps,
  1612. background: coloredProps
  1613. };
  1614. for (const prefix in propsToAddTo) {
  1615. const list = propsToAddTo[prefix];
  1616. for (const prop in propsToAdd) {
  1617. list[prefix + prop] = propsToAdd[prop];
  1618. }
  1619. }
  1620. const customisationAliases = {};
  1621. ["horizontal", "vertical"].forEach((prefix) => {
  1622. const attr = prefix.slice(0, 1) + "Flip";
  1623. customisationAliases[prefix + "-flip"] = attr;
  1624. customisationAliases[prefix.slice(0, 1) + "-flip"] = attr;
  1625. customisationAliases[prefix + "Flip"] = attr;
  1626. });
  1627. function fixSize(value) {
  1628. return value + (value.match(/^[-0-9.]+$/) ? "px" : "");
  1629. }
  1630. const render = (icon, props) => {
  1631. const customisations = mergeCustomisations(defaultExtendedIconCustomisations, props);
  1632. const componentProps = { ...svgDefaults };
  1633. const mode = props.mode || "svg";
  1634. const style = {};
  1635. const propsStyle = props.style;
  1636. const customStyle = typeof propsStyle === "object" && !(propsStyle instanceof Array) ? propsStyle : {};
  1637. for (let key in props) {
  1638. const value = props[key];
  1639. if (value === void 0) {
  1640. continue;
  1641. }
  1642. switch (key) {
  1643. case "icon":
  1644. case "style":
  1645. case "onLoad":
  1646. case "mode":
  1647. break;
  1648. case "inline":
  1649. case "hFlip":
  1650. case "vFlip":
  1651. customisations[key] = value === true || value === "true" || value === 1;
  1652. break;
  1653. case "flip":
  1654. if (typeof value === "string") {
  1655. flipFromString(customisations, value);
  1656. }
  1657. break;
  1658. case "color":
  1659. style.color = value;
  1660. break;
  1661. case "rotate":
  1662. if (typeof value === "string") {
  1663. customisations[key] = rotateFromString(value);
  1664. } else if (typeof value === "number") {
  1665. customisations[key] = value;
  1666. }
  1667. break;
  1668. case "ariaHidden":
  1669. case "aria-hidden":
  1670. if (value !== true && value !== "true") {
  1671. delete componentProps["aria-hidden"];
  1672. }
  1673. break;
  1674. default: {
  1675. const alias = customisationAliases[key];
  1676. if (alias) {
  1677. if (value === true || value === "true" || value === 1) {
  1678. customisations[alias] = true;
  1679. }
  1680. } else if (defaultExtendedIconCustomisations[key] === void 0) {
  1681. componentProps[key] = value;
  1682. }
  1683. }
  1684. }
  1685. }
  1686. const item = iconToSVG(icon, customisations);
  1687. const renderAttribs = item.attributes;
  1688. if (customisations.inline) {
  1689. style.verticalAlign = "-0.125em";
  1690. }
  1691. if (mode === "svg") {
  1692. componentProps.style = {
  1693. ...style,
  1694. ...customStyle
  1695. };
  1696. Object.assign(componentProps, renderAttribs);
  1697. let localCounter = 0;
  1698. let id = props.id;
  1699. if (typeof id === "string") {
  1700. id = id.replace(/-/g, "_");
  1701. }
  1702. componentProps["innerHTML"] = replaceIDs(item.body, id ? () => id + "ID" + localCounter++ : "iconifyVue");
  1703. return vue.h("svg", componentProps);
  1704. }
  1705. const { body, width, height } = icon;
  1706. const useMask = mode === "mask" || (mode === "bg" ? false : body.indexOf("currentColor") !== -1);
  1707. const html = iconToHTML(body, {
  1708. ...renderAttribs,
  1709. width: width + "",
  1710. height: height + ""
  1711. });
  1712. componentProps.style = {
  1713. ...style,
  1714. "--svg": svgToURL(html),
  1715. "width": fixSize(renderAttribs.width),
  1716. "height": fixSize(renderAttribs.height),
  1717. ...commonProps,
  1718. ...useMask ? monotoneProps : coloredProps,
  1719. ...customStyle
  1720. };
  1721. return vue.h("span", componentProps);
  1722. };
  1723. allowSimpleNames(true);
  1724. setAPIModule("", fetchAPIModule);
  1725. if (typeof document !== "undefined" && typeof window !== "undefined") {
  1726. initBrowserStorage();
  1727. const _window2 = window;
  1728. if (_window2.IconifyPreload !== void 0) {
  1729. const preload = _window2.IconifyPreload;
  1730. const err = "Invalid IconifyPreload syntax.";
  1731. if (typeof preload === "object" && preload !== null) {
  1732. (preload instanceof Array ? preload : [preload]).forEach((item) => {
  1733. try {
  1734. if (
  1735. // Check if item is an object and not null/array
  1736. typeof item !== "object" || item === null || item instanceof Array || // Check for 'icons' and 'prefix'
  1737. typeof item.icons !== "object" || typeof item.prefix !== "string" || // Add icon set
  1738. !addCollection(item)
  1739. ) {
  1740. console.error(err);
  1741. }
  1742. } catch (e2) {
  1743. console.error(err);
  1744. }
  1745. });
  1746. }
  1747. }
  1748. if (_window2.IconifyProviders !== void 0) {
  1749. const providers = _window2.IconifyProviders;
  1750. if (typeof providers === "object" && providers !== null) {
  1751. for (let key in providers) {
  1752. const err = "IconifyProviders[" + key + "] is invalid.";
  1753. try {
  1754. const value = providers[key];
  1755. if (typeof value !== "object" || !value || value.resources === void 0) {
  1756. continue;
  1757. }
  1758. if (!addAPIProvider(key, value)) {
  1759. console.error(err);
  1760. }
  1761. } catch (e2) {
  1762. console.error(err);
  1763. }
  1764. }
  1765. }
  1766. }
  1767. }
  1768. const emptyIcon = {
  1769. ...defaultIconProps,
  1770. body: ""
  1771. };
  1772. const Icon = vue.defineComponent({
  1773. // Do not inherit other attributes: it is handled by render()
  1774. inheritAttrs: false,
  1775. // Set initial data
  1776. data() {
  1777. return {
  1778. // Mounted status
  1779. iconMounted: false,
  1780. // Callback counter to trigger re-render
  1781. counter: 0
  1782. };
  1783. },
  1784. mounted() {
  1785. this._name = "";
  1786. this._loadingIcon = null;
  1787. this.iconMounted = true;
  1788. },
  1789. unmounted() {
  1790. this.abortLoading();
  1791. },
  1792. methods: {
  1793. abortLoading() {
  1794. if (this._loadingIcon) {
  1795. this._loadingIcon.abort();
  1796. this._loadingIcon = null;
  1797. }
  1798. },
  1799. // Get data for icon to render or null
  1800. getIcon(icon, onload) {
  1801. if (typeof icon === "object" && icon !== null && typeof icon.body === "string") {
  1802. this._name = "";
  1803. this.abortLoading();
  1804. return {
  1805. data: icon
  1806. };
  1807. }
  1808. let iconName;
  1809. if (typeof icon !== "string" || (iconName = stringToIcon(icon, false, true)) === null) {
  1810. this.abortLoading();
  1811. return null;
  1812. }
  1813. const data = getIconData(iconName);
  1814. if (!data) {
  1815. if (!this._loadingIcon || this._loadingIcon.name !== icon) {
  1816. this.abortLoading();
  1817. this._name = "";
  1818. if (data !== null) {
  1819. this._loadingIcon = {
  1820. name: icon,
  1821. abort: loadIcons([iconName], () => {
  1822. this.counter++;
  1823. })
  1824. };
  1825. }
  1826. }
  1827. return null;
  1828. }
  1829. this.abortLoading();
  1830. if (this._name !== icon) {
  1831. this._name = icon;
  1832. if (onload) {
  1833. onload(icon);
  1834. }
  1835. }
  1836. const classes = ["iconify"];
  1837. if (iconName.prefix !== "") {
  1838. classes.push("iconify--" + iconName.prefix);
  1839. }
  1840. if (iconName.provider !== "") {
  1841. classes.push("iconify--" + iconName.provider);
  1842. }
  1843. return { data, classes };
  1844. }
  1845. },
  1846. // Render icon
  1847. render() {
  1848. this.counter;
  1849. const props = this.$attrs;
  1850. const icon = this.iconMounted ? this.getIcon(props.icon, props.onLoad) : null;
  1851. if (!icon) {
  1852. return render(emptyIcon, props);
  1853. }
  1854. let newProps = props;
  1855. if (icon.classes) {
  1856. newProps = {
  1857. ...props,
  1858. class: (typeof props["class"] === "string" ? props["class"] + " " : "") + icon.classes.join(" ")
  1859. };
  1860. }
  1861. return render({
  1862. ...defaultIconProps,
  1863. ...icon.data
  1864. }, newProps);
  1865. }
  1866. });
  1867. const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
  1868. __name: "BackIcon",
  1869. setup(__props) {
  1870. return (_ctx, _cache) => {
  1871. return vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  1872. class: "back-icon",
  1873. icon: "octicon:arrow-left-24",
  1874. width: "22"
  1875. });
  1876. };
  1877. }
  1878. });
  1879. const _hoisted_1$n = { class: "nav-bar" };
  1880. const _hoisted_2$j = {
  1881. key: 0,
  1882. class: "title"
  1883. };
  1884. const _sfc_main$o = /* @__PURE__ */ vue.defineComponent({
  1885. __name: "NavBar",
  1886. props: {
  1887. title: {}
  1888. },
  1889. emits: ["back"],
  1890. setup(__props, { emit: __emit }) {
  1891. const emit = __emit;
  1892. return (_ctx, _cache) => {
  1893. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$n, [
  1894. vue.createVNode(_sfc_main$p, {
  1895. onClick: _cache[0] || (_cache[0] = ($event) => emit("back"))
  1896. }),
  1897. _ctx.title ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$j, vue.toDisplayString(_ctx.title), 1)) : vue.createCommentVNode("", true)
  1898. ]);
  1899. };
  1900. }
  1901. });
  1902. const NavBar = /* @__PURE__ */ _export_sfc(_sfc_main$o, [["__scopeId", "data-v-fda0acaa"]]);
  1903. const _hoisted_1$m = { class: "display-type" };
  1904. const _hoisted_2$i = { style: { "position": "relative" } };
  1905. const _hoisted_3$f = {
  1906. key: 0,
  1907. class: "type-list"
  1908. };
  1909. const _sfc_main$n = /* @__PURE__ */ vue.defineComponent({
  1910. __name: "BaseSelect",
  1911. props: {
  1912. displayType: {}
  1913. },
  1914. emits: ["update:displayType"],
  1915. setup(__props, { emit: __emit }) {
  1916. const props = __props;
  1917. const emit = __emit;
  1918. let state = vue.reactive({
  1919. showChangeDisplayType: false,
  1920. lastDisplayType: null
  1921. });
  1922. function changeOption(item) {
  1923. if (![CommentDisplayType.New, CommentDisplayType.Like].includes(props.displayType)) {
  1924. state.lastDisplayType = props.displayType;
  1925. }
  1926. emit("update:displayType", item);
  1927. state.showChangeDisplayType = false;
  1928. }
  1929. function clickDisplayType() {
  1930. if ([CommentDisplayType.New, CommentDisplayType.Like].includes(props.displayType)) {
  1931. return changeOption(state.lastDisplayType ?? CommentDisplayType.FloorInFloorNoCallUser);
  1932. }
  1933. state.showChangeDisplayType = !state.showChangeDisplayType;
  1934. }
  1935. const currentDisplayType = vue.computed(() => {
  1936. let judge = props.displayType;
  1937. if ([CommentDisplayType.New, CommentDisplayType.Like].includes(props.displayType)) {
  1938. judge = state.lastDisplayType;
  1939. }
  1940. switch (judge) {
  1941. case CommentDisplayType.FloorInFloorNoCallUser:
  1942. return "楼中楼";
  1943. case CommentDisplayType.FloorInFloor:
  1944. return "楼中楼(@)";
  1945. case CommentDisplayType.FloorInFloorNested:
  1946. return "冗余楼中楼";
  1947. case CommentDisplayType.V2exOrigin:
  1948. return "V2原版";
  1949. case CommentDisplayType.OnlyOp:
  1950. return "只看楼主";
  1951. default:
  1952. return "楼中楼";
  1953. }
  1954. });
  1955. return (_ctx, _cache) => {
  1956. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$m, [
  1957. vue.createElementVNode("div", {
  1958. class: vue.normalizeClass(["type", _ctx.displayType === vue.unref(CommentDisplayType).Like && "active"]),
  1959. onClick: _cache[0] || (_cache[0] = ($event) => changeOption(vue.unref(CommentDisplayType).Like))
  1960. }, "最热 ", 2),
  1961. vue.createElementVNode("div", _hoisted_2$i, [
  1962. vue.createElementVNode("div", {
  1963. class: vue.normalizeClass(["type", ![vue.unref(CommentDisplayType).New, vue.unref(CommentDisplayType).Like].includes(_ctx.displayType) && "active"]),
  1964. onClick: clickDisplayType
  1965. }, [
  1966. vue.createElementVNode("span", null, vue.toDisplayString(currentDisplayType.value), 1),
  1967. vue.createVNode(vue.unref(Icon), { icon: "mingcute:down-line" })
  1968. ], 2),
  1969. vue.unref(state).showChangeDisplayType ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$f, [
  1970. vue.createElementVNode("div", {
  1971. class: vue.normalizeClass(["item", _ctx.displayType === vue.unref(CommentDisplayType).FloorInFloorNoCallUser && "active"]),
  1972. onClick: _cache[1] || (_cache[1] = vue.withModifiers(($event) => changeOption(vue.unref(CommentDisplayType).FloorInFloorNoCallUser), ["stop"]))
  1973. }, "楼中楼 ", 2),
  1974. vue.createElementVNode("div", {
  1975. class: vue.normalizeClass(["item", _ctx.displayType === vue.unref(CommentDisplayType).FloorInFloor && "active"]),
  1976. onClick: _cache[2] || (_cache[2] = vue.withModifiers(($event) => changeOption(vue.unref(CommentDisplayType).FloorInFloor), ["stop"]))
  1977. }, "楼中楼(@) ", 2),
  1978. vue.createElementVNode("div", {
  1979. class: vue.normalizeClass(["item", _ctx.displayType === vue.unref(CommentDisplayType).FloorInFloorNested && "active"]),
  1980. onClick: _cache[3] || (_cache[3] = vue.withModifiers(($event) => changeOption(vue.unref(CommentDisplayType).FloorInFloorNested), ["stop"]))
  1981. }, "冗余楼中楼 ", 2),
  1982. vue.createElementVNode("div", {
  1983. class: vue.normalizeClass(["item", _ctx.displayType === vue.unref(CommentDisplayType).OnlyOp && "active"]),
  1984. onClick: _cache[4] || (_cache[4] = vue.withModifiers(($event) => changeOption(vue.unref(CommentDisplayType).OnlyOp), ["stop"]))
  1985. }, "只看楼主 ", 2),
  1986. vue.createElementVNode("div", {
  1987. class: vue.normalizeClass(["item", _ctx.displayType === vue.unref(CommentDisplayType).V2exOrigin && "active"]),
  1988. onClick: _cache[5] || (_cache[5] = vue.withModifiers(($event) => changeOption(vue.unref(CommentDisplayType).V2exOrigin), ["stop"]))
  1989. }, "V2原版 ", 2)
  1990. ])) : vue.createCommentVNode("", true)
  1991. ])
  1992. ]);
  1993. };
  1994. }
  1995. });
  1996. const BaseSelect = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["__scopeId", "data-v-1d327f48"]]);
  1997. const eventBus = {
  1998. eventMap: /* @__PURE__ */ new Map(),
  1999. on(eventType, cb) {
  2000. let cbs = this.eventMap.get(eventType);
  2001. if (cbs) {
  2002. cbs.push(cb);
  2003. } else {
  2004. cbs = [cb];
  2005. }
  2006. this.eventMap.set(eventType, cbs);
  2007. },
  2008. emit(eventType, val) {
  2009. let cbs = this.eventMap.get(eventType);
  2010. if (cbs) {
  2011. cbs.map((cb) => cb(val));
  2012. }
  2013. },
  2014. off(eventType) {
  2015. let cbs = this.eventMap.has(eventType);
  2016. if (cbs) {
  2017. this.eventMap.delete(eventType);
  2018. }
  2019. },
  2020. clear() {
  2021. this.eventMap = /* @__PURE__ */ new Map();
  2022. }
  2023. };
  2024. const CMD = {
  2025. SHOW_TOOLTIP: "SHOW_TOOLTIP",
  2026. SHOW_MSG: "SHOW_MSG",
  2027. SET_CALL: "SET_CALL",
  2028. SHOW_CALL: "SHOW_CALL",
  2029. REFRESH_ONCE: "REFRESH_ONCE",
  2030. ADD_REPLY: "ADD_REPLY",
  2031. IGNORE: "IGNORE",
  2032. MERGE: "MERGE",
  2033. MERGE_CONFIG: "MERGE_CONFIG",
  2034. REMOVE: "REMOVE",
  2035. CHANGE_COMMENT_THANK: "CHANGE_COMMENT_THANK",
  2036. CHANGE_POST_THANK: "CHANGE_POST_THANK",
  2037. ADD_TAG: "ADD_TAG",
  2038. REMOVE_TAG: "REMOVE_TAG",
  2039. RELATION_REPLY: "RELATION_REPLY",
  2040. JUMP: "JUMP",
  2041. ADD_READ: "ADD_READ",
  2042. REFRESH_POST: "REFRESH_POST",
  2043. SHOW_COMMENT_OPTIONS: "SHOW_COMMENT_OPTIONS",
  2044. SHOW_EDITOR: "COMMENT_REPLY"
  2045. };
  2046. const _withScopeId$e = (n2) => (vue.pushScopeId("data-v-a64ba8b8"), n2 = n2(), vue.popScopeId(), n2);
  2047. const _hoisted_1$l = { class: "font-size" };
  2048. const _hoisted_2$h = { class: "steps" };
  2049. const _hoisted_3$e = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", {
  2050. class: "text",
  2051. style: { "font-size": "1.2rem" }
  2052. }, "小", -1));
  2053. const _hoisted_4$d = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "point" }, null, -1));
  2054. const _hoisted_5$b = [
  2055. _hoisted_3$e,
  2056. _hoisted_4$d
  2057. ];
  2058. const _hoisted_6$a = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "text" }, "标准", -1));
  2059. const _hoisted_7$9 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "point" }, null, -1));
  2060. const _hoisted_8$9 = [
  2061. _hoisted_6$a,
  2062. _hoisted_7$9
  2063. ];
  2064. const _hoisted_9$9 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", {
  2065. class: "text",
  2066. style: { "font-size": "1.8rem" }
  2067. }, "大", -1));
  2068. const _hoisted_10$8 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "point" }, null, -1));
  2069. const _hoisted_11$8 = [
  2070. _hoisted_9$9,
  2071. _hoisted_10$8
  2072. ];
  2073. const _hoisted_12$8 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", {
  2074. class: "text",
  2075. style: { "font-size": "2.2rem" }
  2076. }, "特大", -1));
  2077. const _hoisted_13$8 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "point" }, null, -1));
  2078. const _hoisted_14$7 = [
  2079. _hoisted_12$8,
  2080. _hoisted_13$8
  2081. ];
  2082. const _hoisted_15$7 = /* @__PURE__ */ _withScopeId$e(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "line" }, null, -1));
  2083. const _sfc_main$m = /* @__PURE__ */ vue.defineComponent({
  2084. __name: "FontSizeType",
  2085. setup(__props) {
  2086. const config2 = vue.inject("config");
  2087. return (_ctx, _cache) => {
  2088. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$l, [
  2089. vue.createElementVNode("div", _hoisted_2$h, [
  2090. vue.createElementVNode("div", {
  2091. class: vue.normalizeClass(["step", [vue.unref(config2).fontSizeType === "small" && "active"]]),
  2092. onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(eventBus).emit(vue.unref(CMD).MERGE_CONFIG, { fontSizeType: "small" }))
  2093. }, _hoisted_5$b, 2),
  2094. vue.createElementVNode("div", {
  2095. class: vue.normalizeClass(["step", [vue.unref(config2).fontSizeType === "normal" && "active"]]),
  2096. onClick: _cache[1] || (_cache[1] = ($event) => vue.unref(eventBus).emit(vue.unref(CMD).MERGE_CONFIG, { fontSizeType: "normal" }))
  2097. }, _hoisted_8$9, 2),
  2098. vue.createElementVNode("div", {
  2099. class: vue.normalizeClass(["step", [vue.unref(config2).fontSizeType === "large" && "active"]]),
  2100. onClick: _cache[2] || (_cache[2] = ($event) => vue.unref(eventBus).emit(vue.unref(CMD).MERGE_CONFIG, { fontSizeType: "large" }))
  2101. }, _hoisted_11$8, 2),
  2102. vue.createElementVNode("div", {
  2103. class: vue.normalizeClass(["step", [vue.unref(config2).fontSizeType === "big-large" && "active"]]),
  2104. onClick: _cache[3] || (_cache[3] = ($event) => vue.unref(eventBus).emit(vue.unref(CMD).MERGE_CONFIG, { fontSizeType: "big-large" }))
  2105. }, _hoisted_14$7, 2)
  2106. ]),
  2107. _hoisted_15$7
  2108. ]);
  2109. };
  2110. }
  2111. });
  2112. const FontSizeType = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["__scopeId", "data-v-a64ba8b8"]]);
  2113. var _GM_notification = /* @__PURE__ */ (() => typeof GM_notification != "undefined" ? GM_notification : void 0)();
  2114. var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)();
  2115. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  2116. const DefaultPost = {
  2117. allReplyUsers: [],
  2118. content_rendered: "",
  2119. createDate: "",
  2120. createDateAgo: "",
  2121. fr: "",
  2122. replyList: [],
  2123. nestedReplies: [],
  2124. nestedRedundReplies: [],
  2125. username: "",
  2126. url: "",
  2127. member: {},
  2128. node: {
  2129. title: "",
  2130. url: ""
  2131. },
  2132. headerTemplate: "",
  2133. title: "",
  2134. id: "",
  2135. type: "post",
  2136. once: "",
  2137. replyCount: 0,
  2138. clickCount: 0,
  2139. thankCount: 0,
  2140. collectCount: 0,
  2141. lastReadFloor: 0,
  2142. isFavorite: false,
  2143. isIgnore: false,
  2144. isThanked: false,
  2145. isReport: false,
  2146. inList: false
  2147. };
  2148. const DefaultUser = {
  2149. tagPrefix: "--用户标签--",
  2150. tags: {},
  2151. tagsId: "",
  2152. username: "",
  2153. avatar: "",
  2154. readPrefix: "--已读楼层--",
  2155. readNoteItemId: "",
  2156. readList: {},
  2157. imgurPrefix: "--imgur图片删除hash--",
  2158. imgurList: {},
  2159. imgurNoteId: ""
  2160. };
  2161. const DefaultConfig = {
  2162. showToolbar: true,
  2163. showPreviewBtn: true,
  2164. autoOpenDetail: true,
  2165. openTag: false,
  2166. //给用户打标签
  2167. clickPostItemOpenDetail: true,
  2168. closePostDetailBySpace: true,
  2169. //点击空白处关闭详情
  2170. contentAutoCollapse: true,
  2171. //正文超长自动折叠
  2172. viewType: "table",
  2173. commentDisplayType: CommentDisplayType.FloorInFloorNoCallUser,
  2174. newTabOpen: false,
  2175. //新标签打开
  2176. base64: true,
  2177. //base功能
  2178. sov2ex: false,
  2179. postWidth: "",
  2180. showTopReply: true,
  2181. topReplyLoveMinCount: 3,
  2182. topReplyCount: 3,
  2183. autoJumpLastReadFloor: false,
  2184. rememberLastReadFloor: false,
  2185. autoSignin: true,
  2186. customBgColor: "",
  2187. version: 1,
  2188. collectBrowserNotice: false,
  2189. fontSizeType: "normal"
  2190. };
  2191. const DefaultVal = {
  2192. pageType: void 0,
  2193. pageData: { pageNo: 1 },
  2194. targetUserName: "",
  2195. currentVersion: 1,
  2196. isNight: false,
  2197. cb: null,
  2198. stopMe: null,
  2199. postList: [],
  2200. git: "https://github.com/zyronon/web-scripts",
  2201. shortGit: "zyronon/web-scripts",
  2202. issue: "https://github.com/zyronon/web-scripts/issues"
  2203. };
  2204. const functions = {
  2205. //获取所有回复
  2206. getAllReply(repliesMap = []) {
  2207. return repliesMap.sort((a, b) => a.i - b.i).reduce((pre, i) => {
  2208. pre = pre.concat(i.replyList);
  2209. return pre;
  2210. }, []);
  2211. },
  2212. //查找子回复
  2213. findChildren(item, endList, all) {
  2214. var _a;
  2215. const fn = (child, endList2, parent) => {
  2216. child.level = parent.level + 1;
  2217. let rIndex = all.findIndex((v) => v.floor === child.floor);
  2218. if (rIndex > -1) {
  2219. all[rIndex].isUse = true;
  2220. }
  2221. parent.children.push(this.findChildren(child, endList2, all));
  2222. };
  2223. item.children = [];
  2224. let floorReplyList = [];
  2225. for (let i = 0; i < endList.length; i++) {
  2226. let currentItem = endList[i];
  2227. if (currentItem.isUse)
  2228. continue;
  2229. if (currentItem.replyFloor === item.floor) {
  2230. if (currentItem.replyUsers.length === 1 && currentItem.replyUsers[0] === item.username) {
  2231. currentItem.isUse = true;
  2232. floorReplyList.push({ endList: endList.slice(i + 1), currentItem });
  2233. } else {
  2234. currentItem.isWrong = true;
  2235. }
  2236. }
  2237. }
  2238. floorReplyList.reverse().map(({ currentItem, endList: endList2 }) => {
  2239. fn(currentItem, endList2, item);
  2240. });
  2241. let nextMeIndex = endList.findIndex((v) => {
  2242. var _a2;
  2243. return v.username === item.username && ((_a2 = v.replyUsers) == null ? void 0 : _a2[0]) !== item.username;
  2244. });
  2245. let findList = nextMeIndex > -1 ? endList.slice(0, nextMeIndex) : endList;
  2246. for (let i = 0; i < findList.length; i++) {
  2247. let currentItem = findList[i];
  2248. if (currentItem.isUse)
  2249. continue;
  2250. if (currentItem.replyUsers.length === 1) {
  2251. if (currentItem.replyFloor !== -1) {
  2252. if (((_a = all[currentItem.replyFloor - 1]) == null ? void 0 : _a.username) === currentItem.replyUsers[0]) {
  2253. continue;
  2254. }
  2255. }
  2256. let endList2 = endList.slice(i + 1);
  2257. if (currentItem.username === item.username) {
  2258. if (currentItem.replyUsers[0] === item.username) {
  2259. fn(currentItem, endList2, item);
  2260. }
  2261. break;
  2262. } else {
  2263. if (currentItem.replyUsers[0] === item.username) {
  2264. fn(currentItem, endList2, item);
  2265. }
  2266. }
  2267. } else {
  2268. if (currentItem.username === item.username)
  2269. break;
  2270. }
  2271. }
  2272. item.children = item.children.sort((a, b) => a.floor - b.floor);
  2273. return item;
  2274. },
  2275. //生成嵌套回复
  2276. createNestedList(allList = []) {
  2277. if (!allList.length)
  2278. return [];
  2279. let list = window.clone(allList);
  2280. let nestedList = [];
  2281. list.map((item, index) => {
  2282. let startList = list.slice(0, index);
  2283. let startReplyUsers = Array.from(new Set(startList.map((v) => v.username)));
  2284. let endList = list.slice(index + 1);
  2285. if (index === 0) {
  2286. nestedList.push(this.findChildren(item, endList, list));
  2287. } else {
  2288. if (!item.isUse) {
  2289. let isOneLevelReply = false;
  2290. if (item.replyUsers.length) {
  2291. if (item.replyUsers.length > 1) {
  2292. isOneLevelReply = true;
  2293. } else {
  2294. isOneLevelReply = !startReplyUsers.find((v) => v === item.replyUsers[0]);
  2295. }
  2296. } else {
  2297. isOneLevelReply = true;
  2298. }
  2299. if (isOneLevelReply) {
  2300. item.level = 0;
  2301. nestedList.push(this.findChildren(item, endList, list));
  2302. }
  2303. }
  2304. }
  2305. });
  2306. return nestedList;
  2307. },
  2308. //生成嵌套冗余回复
  2309. createNestedRedundantList(allList = []) {
  2310. if (!allList.length)
  2311. return [];
  2312. let list = window.clone(allList);
  2313. let nestedList = [];
  2314. list.map((item, index) => {
  2315. let startList = list.slice(0, index);
  2316. let startReplyUsers = Array.from(new Set(startList.map((v) => v.username)));
  2317. let endList = list.slice(index + 1);
  2318. if (index === 0) {
  2319. nestedList.push(this.findChildren(item, endList, list));
  2320. } else {
  2321. if (!item.isUse) {
  2322. let isOneLevelReply = false;
  2323. if (item.replyUsers.length) {
  2324. if (item.replyUsers.length > 1) {
  2325. isOneLevelReply = true;
  2326. } else {
  2327. isOneLevelReply = !startReplyUsers.find((v) => v === item.replyUsers[0]);
  2328. }
  2329. } else {
  2330. isOneLevelReply = true;
  2331. }
  2332. if (isOneLevelReply) {
  2333. item.level = 0;
  2334. nestedList.push(this.findChildren(item, endList, list));
  2335. }
  2336. } else {
  2337. let newItem = window.clone(item);
  2338. newItem.children = [];
  2339. newItem.level = 0;
  2340. newItem.isDup = true;
  2341. nestedList.push(newItem);
  2342. }
  2343. }
  2344. });
  2345. return nestedList;
  2346. },
  2347. //解析A标签
  2348. parseA(a) {
  2349. let href = a.href;
  2350. let id;
  2351. if (href.includes("/t/")) {
  2352. id = a.pathname.substring("/t/".length);
  2353. }
  2354. return { href, id, title: a.innerText };
  2355. },
  2356. //图片链接转Img标签
  2357. checkPhotoLink2Img(str) {
  2358. if (!str)
  2359. return;
  2360. try {
  2361. let imgWebs = [
  2362. /<a((?!<a).)*href="https?:\/\/((?!<a).)*imgur.com((?!<a).)*>(((?!<a).)*)<\/a>/g,
  2363. /<a((?!<a).)*href="https?:\/\/((?!<a).)*\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG) ((?!<a).)*>(((?!<a).)*)<\/a>/g
  2364. ];
  2365. imgWebs.map((v, i) => {
  2366. let has = str.matchAll(v);
  2367. let res2 = [...has];
  2368. res2.map((r2) => {
  2369. let p = i === 0 ? r2[4] : r2[5];
  2370. if (p) {
  2371. let link = p.toLowerCase();
  2372. let src = p;
  2373. if (link.includes(".png") || link.includes(".jpg") || link.includes(".jpeg") || link.includes(".gif")) {
  2374. } else {
  2375. src = p + ".png";
  2376. }
  2377. str = str.replace(r2[0], `<img src="${src}" data-originUrl="${p}" data-notice="此img标签由v2ex-超级增强脚本解析" style="max-width: 100%">`);
  2378. }
  2379. });
  2380. });
  2381. } catch (e2) {
  2382. console.log("正则解析html里面的a标签的图片链接出错了");
  2383. }
  2384. return str;
  2385. },
  2386. //检测帖子回复长度
  2387. async checkPostReplies(id, needOpen = true) {
  2388. return new Promise(async (resolve) => {
  2389. var _a;
  2390. let showJsonUrl = `${location.origin}/api/topics/show.json?id=${id}`;
  2391. let r2 = await fetch(showJsonUrl);
  2392. if (r2) {
  2393. let res = await r2.json();
  2394. if (res) {
  2395. if (((_a = res[0]) == null ? void 0 : _a.replies) > MAX_REPLY_LIMIT) {
  2396. if (needOpen) {
  2397. window.parse.openNewTab(`https://www.v2ex.com/t/${id}?p=1&script=1`);
  2398. }
  2399. return resolve(true);
  2400. }
  2401. }
  2402. }
  2403. resolve(false);
  2404. });
  2405. },
  2406. async sleep(time) {
  2407. return new Promise((resolve) => {
  2408. setTimeout(resolve, time);
  2409. });
  2410. },
  2411. //打开新标签页
  2412. openNewTab(href) {
  2413. _GM_openInTab(href, { active: true });
  2414. },
  2415. async cbChecker(val, count = 0) {
  2416. if (window.cb) {
  2417. window.cb(val);
  2418. } else {
  2419. while (!window.cb && count < 30) {
  2420. await functions.sleep(500);
  2421. count++;
  2422. }
  2423. window.cb && window.cb(val);
  2424. }
  2425. },
  2426. //初始化脚本菜单
  2427. initMonkeyMenu() {
  2428. try {
  2429. _GM_registerMenuCommand("脚本设置", () => {
  2430. functions.cbChecker({ type: "openSetting" });
  2431. });
  2432. _GM_registerMenuCommand("仓库地址", () => {
  2433. functions.openNewTab(window.const.git);
  2434. });
  2435. _GM_registerMenuCommand("反馈 & 建议", functions.feedback);
  2436. } catch (e2) {
  2437. console.error("无法使用Tampermonkey");
  2438. }
  2439. },
  2440. clone(val) {
  2441. return JSON.parse(JSON.stringify(val));
  2442. },
  2443. feedback() {
  2444. functions.openNewTab(DefaultVal.issue);
  2445. }
  2446. };
  2447. const _sfc_main$l = {
  2448. name: "Setting",
  2449. components: {
  2450. FontSizeType,
  2451. BaseSelect,
  2452. NavBar,
  2453. BaseSwitch,
  2454. Tooltip,
  2455. Icon
  2456. },
  2457. emits: ["back"],
  2458. props: {
  2459. modelValue: {
  2460. type: Object,
  2461. default() {
  2462. return {};
  2463. }
  2464. },
  2465. show: {
  2466. type: Boolean,
  2467. default() {
  2468. return false;
  2469. }
  2470. },
  2471. to: {
  2472. type: String,
  2473. default() {
  2474. return "";
  2475. }
  2476. }
  2477. },
  2478. data() {
  2479. return {
  2480. activeEruda: !!localStorage.getItem("active-eruda"),
  2481. config: window.clone(this.modelValue)
  2482. };
  2483. },
  2484. computed: {
  2485. DefaultVal() {
  2486. return DefaultVal;
  2487. },
  2488. functions() {
  2489. return functions;
  2490. },
  2491. CommentDisplayType() {
  2492. return CommentDisplayType;
  2493. },
  2494. isNew() {
  2495. return this.config.version < window.currentVersion;
  2496. }
  2497. },
  2498. watch: {
  2499. config: {
  2500. handler(n2) {
  2501. n2.topReplyLoveMinCount = Math.trunc(n2.topReplyLoveMinCount);
  2502. if (n2.topReplyLoveMinCount < 0) {
  2503. n2.topReplyLoveMinCount = 1;
  2504. }
  2505. this.$emit("update:modelValue", n2);
  2506. },
  2507. deep: true
  2508. },
  2509. activeEruda(n2) {
  2510. if (n2) {
  2511. localStorage.setItem("active-eruda", 1);
  2512. } else {
  2513. localStorage.setItem("active-eruda", "");
  2514. }
  2515. }
  2516. }
  2517. };
  2518. const _withScopeId$d = (n2) => (vue.pushScopeId("data-v-424a2b09"), n2 = n2(), vue.popScopeId(), n2);
  2519. const _hoisted_1$k = { class: "mobile-page" };
  2520. const _hoisted_2$g = { class: "page-content" };
  2521. const _hoisted_3$d = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2522. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "关于脚本")
  2523. ], -1));
  2524. const _hoisted_4$c = { class: "row" };
  2525. const _hoisted_5$a = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "GitHub", -1));
  2526. const _hoisted_6$9 = { class: "wrapper" };
  2527. const _hoisted_7$8 = ["href"];
  2528. const _hoisted_8$8 = { class: "row" };
  2529. const _hoisted_9$8 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "反馈 & 建议", -1));
  2530. const _hoisted_10$7 = { class: "wrapper" };
  2531. const _hoisted_11$7 = ["href"];
  2532. const _hoisted_12$7 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2533. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "列表设置")
  2534. ], -1));
  2535. const _hoisted_13$7 = { class: "row" };
  2536. const _hoisted_14$6 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "列表展示方式", -1));
  2537. const _hoisted_15$6 = { class: "wrapper" };
  2538. const _hoisted_16$6 = { class: "radio-group2" };
  2539. const _hoisted_17$3 = { class: "row" };
  2540. const _hoisted_18$3 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "帖子弹框显示", -1));
  2541. const _hoisted_19$3 = { class: "wrapper" };
  2542. const _hoisted_20$3 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "desc" }, " 开启此选项后,帖子始终会以弹框的方式显示。优先级大于“新标签页打开链接” ", -1));
  2543. const _hoisted_21$2 = { class: "row" };
  2544. const _hoisted_22$2 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "新标签页打开链接", -1));
  2545. const _hoisted_23$2 = { class: "wrapper" };
  2546. const _hoisted_24$2 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "desc" }, " 网页上所有链接通过新标签页打开 ", -1));
  2547. const _hoisted_25$2 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2548. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "主题设置")
  2549. ], -1));
  2550. const _hoisted_26$1 = { class: "row" };
  2551. const _hoisted_27$1 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "回复展示方式", -1));
  2552. const _hoisted_28$1 = { class: "wrapper" };
  2553. const _hoisted_29$1 = { class: "row" };
  2554. const _hoisted_30$1 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "正文超长自动折叠", -1));
  2555. const _hoisted_31$1 = { class: "wrapper" };
  2556. const _hoisted_32$1 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2557. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "高赞回复")
  2558. ], -1));
  2559. const _hoisted_33$1 = { class: "row" };
  2560. const _hoisted_34$1 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "显示高赞回复", -1));
  2561. const _hoisted_35$1 = { class: "wrapper" };
  2562. const _hoisted_36$1 = { class: "row" };
  2563. const _hoisted_37$1 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "最多显示多少个高赞回复", -1));
  2564. const _hoisted_38$1 = { class: "wrapper" };
  2565. const _hoisted_39$1 = { class: "row" };
  2566. const _hoisted_40 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "最少需要多少赞才能被判定为高赞", -1));
  2567. const _hoisted_41 = { class: "wrapper" };
  2568. const _hoisted_42 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2569. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "记忆阅读")
  2570. ], -1));
  2571. const _hoisted_43 = { class: "row" };
  2572. const _hoisted_44 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "记录上次阅读楼层(误差1层左右):", -1));
  2573. const _hoisted_45 = { class: "wrapper" };
  2574. const _hoisted_46 = { class: "row" };
  2575. const _hoisted_47 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "打开帖子自动跳转到上次阅读楼层", -1));
  2576. const _hoisted_48 = { class: "wrapper" };
  2577. const _hoisted_49 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2578. /* @__PURE__ */ vue.createElementVNode("label", { class: "main-title" }, "其他设置")
  2579. ], -1));
  2580. const _hoisted_50 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "row" }, [
  2581. /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "字体设置")
  2582. ], -1));
  2583. const _hoisted_51 = { class: "row" };
  2584. const _hoisted_52 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "用户打标签(跨平台,数据保存在自己的记事本):", -1));
  2585. const _hoisted_53 = { class: "wrapper" };
  2586. const _hoisted_54 = { class: "row" };
  2587. const _hoisted_55 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "划词显示Base64解码框", -1));
  2588. const _hoisted_56 = { class: "wrapper" };
  2589. const _hoisted_57 = { class: "row" };
  2590. const _hoisted_58 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "自动签到", -1));
  2591. const _hoisted_59 = { class: "wrapper" };
  2592. const _hoisted_60 = { class: "row" };
  2593. const _hoisted_61 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "收藏时提醒添加到书签", -1));
  2594. const _hoisted_62 = { class: "wrapper" };
  2595. const _hoisted_63 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "desc" }, " V站帐号一旦被封禁,则无法登录,无法查看账号收藏了 ", -1));
  2596. const _hoisted_64 = { class: "row" };
  2597. const _hoisted_65 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("label", { class: "item-title" }, "调试模式", -1));
  2598. const _hoisted_66 = { class: "wrapper" };
  2599. const _hoisted_67 = /* @__PURE__ */ _withScopeId$d(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "desc" }, " 开启此项会显示调试控制台,刷新页面生效 ", -1));
  2600. function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
  2601. const _component_NavBar = vue.resolveComponent("NavBar");
  2602. const _component_BaseSwitch = vue.resolveComponent("BaseSwitch");
  2603. const _component_BaseSelect = vue.resolveComponent("BaseSelect");
  2604. const _component_font_size_type = vue.resolveComponent("font-size-type");
  2605. return vue.openBlock(), vue.createBlock(vue.Teleport, { to: $props.to }, [
  2606. vue.createElementVNode("div", _hoisted_1$k, [
  2607. vue.createVNode(_component_NavBar, {
  2608. title: "设置",
  2609. onBack: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("back"))
  2610. }),
  2611. vue.createElementVNode("div", _hoisted_2$g, [
  2612. _hoisted_3$d,
  2613. vue.createElementVNode("div", _hoisted_4$c, [
  2614. _hoisted_5$a,
  2615. vue.createElementVNode("div", _hoisted_6$9, [
  2616. vue.createElementVNode("a", {
  2617. href: $options.DefaultVal.git,
  2618. target: "_blank"
  2619. }, vue.toDisplayString($options.DefaultVal.shortGit), 9, _hoisted_7$8)
  2620. ])
  2621. ]),
  2622. vue.createElementVNode("div", _hoisted_8$8, [
  2623. _hoisted_9$8,
  2624. vue.createElementVNode("div", _hoisted_10$7, [
  2625. vue.createElementVNode("a", {
  2626. href: $options.DefaultVal.issue,
  2627. target: "_blank"
  2628. }, "点此填写Issue", 8, _hoisted_11$7)
  2629. ])
  2630. ]),
  2631. _hoisted_12$7,
  2632. vue.createElementVNode("div", _hoisted_13$7, [
  2633. _hoisted_14$6,
  2634. vue.createElementVNode("div", _hoisted_15$6, [
  2635. vue.createElementVNode("div", _hoisted_16$6, [
  2636. vue.createElementVNode("div", {
  2637. class: vue.normalizeClass(["radio", $data.config.viewType === "table" ? "active" : ""]),
  2638. onClick: _cache[1] || (_cache[1] = ($event) => $data.config.viewType = "table")
  2639. }, "表格 ", 2),
  2640. vue.createElementVNode("div", {
  2641. class: vue.normalizeClass(["radio", $data.config.viewType === "card" ? "active" : ""]),
  2642. onClick: _cache[2] || (_cache[2] = ($event) => $data.config.viewType = "card")
  2643. }, "卡片 ", 2)
  2644. ])
  2645. ])
  2646. ]),
  2647. vue.createElementVNode("div", _hoisted_17$3, [
  2648. _hoisted_18$3,
  2649. vue.createElementVNode("div", _hoisted_19$3, [
  2650. vue.createVNode(_component_BaseSwitch, {
  2651. modelValue: $data.config.clickPostItemOpenDetail,
  2652. "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $data.config.clickPostItemOpenDetail = $event)
  2653. }, null, 8, ["modelValue"])
  2654. ])
  2655. ]),
  2656. _hoisted_20$3,
  2657. vue.createElementVNode("div", _hoisted_21$2, [
  2658. _hoisted_22$2,
  2659. vue.createElementVNode("div", _hoisted_23$2, [
  2660. vue.createVNode(_component_BaseSwitch, {
  2661. modelValue: $data.config.newTabOpen,
  2662. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.config.newTabOpen = $event)
  2663. }, null, 8, ["modelValue"])
  2664. ])
  2665. ]),
  2666. _hoisted_24$2,
  2667. _hoisted_25$2,
  2668. vue.createElementVNode("div", _hoisted_26$1, [
  2669. _hoisted_27$1,
  2670. vue.createElementVNode("div", _hoisted_28$1, [
  2671. vue.createVNode(_component_BaseSelect, {
  2672. "display-type": $data.config.commentDisplayType,
  2673. "onUpdate:displayType": _cache[5] || (_cache[5] = ($event) => $data.config.commentDisplayType = $event)
  2674. }, null, 8, ["display-type"])
  2675. ])
  2676. ]),
  2677. vue.createElementVNode("div", _hoisted_29$1, [
  2678. _hoisted_30$1,
  2679. vue.createElementVNode("div", _hoisted_31$1, [
  2680. vue.createVNode(_component_BaseSwitch, {
  2681. modelValue: $data.config.contentAutoCollapse,
  2682. "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $data.config.contentAutoCollapse = $event)
  2683. }, null, 8, ["modelValue"])
  2684. ])
  2685. ]),
  2686. _hoisted_32$1,
  2687. vue.createElementVNode("div", _hoisted_33$1, [
  2688. _hoisted_34$1,
  2689. vue.createElementVNode("div", _hoisted_35$1, [
  2690. vue.createVNode(_component_BaseSwitch, {
  2691. modelValue: $data.config.showTopReply,
  2692. "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $data.config.showTopReply = $event)
  2693. }, null, 8, ["modelValue"])
  2694. ])
  2695. ]),
  2696. vue.createElementVNode("div", _hoisted_36$1, [
  2697. _hoisted_37$1,
  2698. vue.createElementVNode("div", _hoisted_38$1, [
  2699. vue.withDirectives(vue.createElementVNode("input", {
  2700. type: "number",
  2701. min: "1",
  2702. "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => $data.config.topReplyCount = $event)
  2703. }, null, 512), [
  2704. [vue.vModelText, $data.config.topReplyCount]
  2705. ])
  2706. ])
  2707. ]),
  2708. vue.createElementVNode("div", _hoisted_39$1, [
  2709. _hoisted_40,
  2710. vue.createElementVNode("div", _hoisted_41, [
  2711. vue.withDirectives(vue.createElementVNode("input", {
  2712. type: "number",
  2713. min: "1",
  2714. "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => $data.config.topReplyLoveMinCount = $event)
  2715. }, null, 512), [
  2716. [vue.vModelText, $data.config.topReplyLoveMinCount]
  2717. ])
  2718. ])
  2719. ]),
  2720. _hoisted_42,
  2721. vue.createElementVNode("div", _hoisted_43, [
  2722. _hoisted_44,
  2723. vue.createElementVNode("div", _hoisted_45, [
  2724. vue.createVNode(_component_BaseSwitch, {
  2725. "model-value": $data.config.rememberLastReadFloor,
  2726. "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => {
  2727. $data.config.rememberLastReadFloor = !$data.config.rememberLastReadFloor;
  2728. $data.config.autoJumpLastReadFloor = false;
  2729. })
  2730. }, null, 8, ["model-value"])
  2731. ])
  2732. ]),
  2733. vue.createElementVNode("div", _hoisted_46, [
  2734. _hoisted_47,
  2735. vue.createElementVNode("div", _hoisted_48, [
  2736. vue.createVNode(_component_BaseSwitch, {
  2737. modelValue: $data.config.autoJumpLastReadFloor,
  2738. "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => $data.config.autoJumpLastReadFloor = $event)
  2739. }, null, 8, ["modelValue"])
  2740. ])
  2741. ]),
  2742. _hoisted_49,
  2743. _hoisted_50,
  2744. vue.createVNode(_component_font_size_type),
  2745. vue.createElementVNode("div", _hoisted_51, [
  2746. _hoisted_52,
  2747. vue.createElementVNode("div", _hoisted_53, [
  2748. vue.createVNode(_component_BaseSwitch, {
  2749. modelValue: $data.config.openTag,
  2750. "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => $data.config.openTag = $event)
  2751. }, null, 8, ["modelValue"])
  2752. ])
  2753. ]),
  2754. vue.createElementVNode("div", _hoisted_54, [
  2755. _hoisted_55,
  2756. vue.createElementVNode("div", _hoisted_56, [
  2757. vue.createVNode(_component_BaseSwitch, {
  2758. modelValue: $data.config.base64,
  2759. "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => $data.config.base64 = $event)
  2760. }, null, 8, ["modelValue"])
  2761. ])
  2762. ]),
  2763. vue.createElementVNode("div", _hoisted_57, [
  2764. _hoisted_58,
  2765. vue.createElementVNode("div", _hoisted_59, [
  2766. vue.createVNode(_component_BaseSwitch, {
  2767. modelValue: $data.config.autoSignin,
  2768. "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => $data.config.autoSignin = $event)
  2769. }, null, 8, ["modelValue"])
  2770. ])
  2771. ]),
  2772. vue.createElementVNode("div", _hoisted_60, [
  2773. _hoisted_61,
  2774. vue.createElementVNode("div", _hoisted_62, [
  2775. vue.createVNode(_component_BaseSwitch, {
  2776. modelValue: $data.config.collectBrowserNotice,
  2777. "onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => $data.config.collectBrowserNotice = $event)
  2778. }, null, 8, ["modelValue"])
  2779. ])
  2780. ]),
  2781. _hoisted_63,
  2782. vue.createElementVNode("div", _hoisted_64, [
  2783. _hoisted_65,
  2784. vue.createElementVNode("div", _hoisted_66, [
  2785. vue.createVNode(_component_BaseSwitch, {
  2786. modelValue: $data.activeEruda,
  2787. "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => $data.activeEruda = $event)
  2788. }, null, 8, ["modelValue"])
  2789. ])
  2790. ]),
  2791. _hoisted_67
  2792. ])
  2793. ])
  2794. ], 8, ["to"]);
  2795. }
  2796. const Setting = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["render", _sfc_render$9], ["__scopeId", "data-v-424a2b09"]]);
  2797. const _sfc_main$k = {
  2798. name: "Point",
  2799. components: { Icon },
  2800. inject: ["post", "isLogin"],
  2801. props: {
  2802. item: {
  2803. type: Object,
  2804. default() {
  2805. return {};
  2806. }
  2807. },
  2808. full: {
  2809. type: Boolean,
  2810. default() {
  2811. return true;
  2812. }
  2813. },
  2814. apiUrl: ""
  2815. },
  2816. methods: {
  2817. thankError() {
  2818. if (!this.isLogin) {
  2819. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  2820. }
  2821. if (this.item.username === window.user.username) {
  2822. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "不能感谢自己" });
  2823. }
  2824. if (this.item.isThanked) {
  2825. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "已经感谢过了" });
  2826. }
  2827. this.thank();
  2828. },
  2829. async thank() {
  2830. this.$emit("addThank");
  2831. let url = `${window.baseUrl}/thank/${this.apiUrl}?once=${this.post.once}`;
  2832. $.post(url).then((res) => {
  2833. if (!res.success) {
  2834. this.$emit("recallThank");
  2835. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: res.message });
  2836. }
  2837. eventBus.emit(CMD.REFRESH_ONCE, res.once);
  2838. }, (err) => {
  2839. this.$emit("recallThank");
  2840. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "感谢失败" });
  2841. eventBus.emit(CMD.REFRESH_ONCE);
  2842. });
  2843. }
  2844. }
  2845. };
  2846. const _hoisted_1$j = {
  2847. key: 2,
  2848. class: "link-num"
  2849. };
  2850. function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
  2851. const _component_Icon = vue.resolveComponent("Icon");
  2852. return vue.openBlock(), vue.createElementBlock("div", {
  2853. class: "tool",
  2854. onClick: _cache[0] || (_cache[0] = (...args) => $options.thankError && $options.thankError(...args))
  2855. }, [
  2856. $props.item.isThanked ? (vue.openBlock(), vue.createBlock(_component_Icon, {
  2857. key: 0,
  2858. color: "red",
  2859. icon: "icon-park-solid:like"
  2860. })) : (vue.openBlock(), vue.createBlock(_component_Icon, {
  2861. key: 1,
  2862. color: "rgb(224,42,42)",
  2863. icon: "icon-park-outline:like"
  2864. })),
  2865. $props.item.thankCount ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$j, vue.toDisplayString($props.item.thankCount), 1)) : vue.createCommentVNode("", true)
  2866. ]);
  2867. }
  2868. const Point = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["render", _sfc_render$8], ["__scopeId", "data-v-b7c6664e"]]);
  2869. const _sfc_main$j = {};
  2870. const _withScopeId$c = (n2) => (vue.pushScopeId("data-v-e92e0529"), n2 = n2(), vue.popScopeId(), n2);
  2871. const _hoisted_1$i = { class: "more" };
  2872. const _hoisted_2$f = /* @__PURE__ */ _withScopeId$c(() => /* @__PURE__ */ vue.createElementVNode("div", null, null, -1));
  2873. const _hoisted_3$c = /* @__PURE__ */ _withScopeId$c(() => /* @__PURE__ */ vue.createElementVNode("div", null, null, -1));
  2874. const _hoisted_4$b = /* @__PURE__ */ _withScopeId$c(() => /* @__PURE__ */ vue.createElementVNode("div", null, null, -1));
  2875. const _hoisted_5$9 = [
  2876. _hoisted_2$f,
  2877. _hoisted_3$c,
  2878. _hoisted_4$b
  2879. ];
  2880. function _sfc_render$7(_ctx, _cache) {
  2881. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$i, _hoisted_5$9);
  2882. }
  2883. const MoreIcon = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$7], ["__scopeId", "data-v-e92e0529"]]);
  2884. const _sfc_main$i = {
  2885. name: "Author",
  2886. components: { MoreIcon, Point, Icon },
  2887. inject: ["isLogin", "tags", "config", "isNight"],
  2888. props: {
  2889. modelValue: false,
  2890. comment: {
  2891. type: Object,
  2892. default() {
  2893. return {};
  2894. }
  2895. },
  2896. type: {
  2897. type: String,
  2898. default() {
  2899. return "list";
  2900. }
  2901. }
  2902. },
  2903. computed: {
  2904. eventBus() {
  2905. return eventBus;
  2906. },
  2907. CMD() {
  2908. return CMD;
  2909. },
  2910. pointInfo() {
  2911. return {
  2912. isThanked: this.comment.isThanked,
  2913. thankCount: this.comment.thankCount,
  2914. username: this.comment.username
  2915. };
  2916. },
  2917. myTags() {
  2918. return this.tags[this.comment.username] ?? [];
  2919. }
  2920. },
  2921. methods: {
  2922. addTag() {
  2923. eventBus.emit(CMD.ADD_TAG, this.comment.username);
  2924. },
  2925. removeTag(tag) {
  2926. eventBus.emit(CMD.REMOVE_TAG, { username: this.comment.username, tag });
  2927. },
  2928. checkIsLogin(emitName = "") {
  2929. if (!this.isLogin) {
  2930. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  2931. return false;
  2932. }
  2933. this.$emit(emitName);
  2934. return true;
  2935. },
  2936. addThank() {
  2937. eventBus.emit(CMD.CHANGE_COMMENT_THANK, { id: this.comment.id, type: "add" });
  2938. },
  2939. recallThank() {
  2940. eventBus.emit(CMD.CHANGE_COMMENT_THANK, { id: this.comment.id, type: "recall" });
  2941. }
  2942. }
  2943. };
  2944. const _withScopeId$b = (n2) => (vue.pushScopeId("data-v-9041586a"), n2 = n2(), vue.popScopeId(), n2);
  2945. const _hoisted_1$h = { class: "Author-left" };
  2946. const _hoisted_2$e = ["href"];
  2947. const _hoisted_3$b = ["src"];
  2948. const _hoisted_4$a = { class: "info" };
  2949. const _hoisted_5$8 = { class: "top" };
  2950. const _hoisted_6$8 = { class: "texts" };
  2951. const _hoisted_7$7 = ["href"];
  2952. const _hoisted_8$7 = {
  2953. key: 0,
  2954. class: "owner"
  2955. };
  2956. const _hoisted_9$7 = {
  2957. key: 1,
  2958. class: "dup"
  2959. };
  2960. const _hoisted_10$6 = {
  2961. key: 2,
  2962. class: "mod"
  2963. };
  2964. const _hoisted_11$6 = { class: "my-tag" };
  2965. const _hoisted_12$6 = /* @__PURE__ */ _withScopeId$b(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-tag" }, null, -1));
  2966. const _hoisted_13$6 = ["onClick"];
  2967. const _hoisted_14$5 = { class: "floor" };
  2968. const _hoisted_15$5 = { class: "ago" };
  2969. const _hoisted_16$5 = { class: "Author-right" };
  2970. function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
  2971. const _component_Icon = vue.resolveComponent("Icon");
  2972. const _component_Point = vue.resolveComponent("Point");
  2973. const _component_MoreIcon = vue.resolveComponent("MoreIcon");
  2974. return vue.openBlock(), vue.createElementBlock("div", {
  2975. class: vue.normalizeClass(["Author", { expand: !$props.modelValue }])
  2976. }, [
  2977. vue.createElementVNode("div", _hoisted_1$h, [
  2978. !$props.modelValue ? (vue.openBlock(), vue.createBlock(_component_Icon, {
  2979. key: 0,
  2980. onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("update:modelValue", true)),
  2981. color: "#177EC9",
  2982. class: "expand-icon",
  2983. icon: "gravity-ui:chevrons-expand-up-right"
  2984. })) : vue.createCommentVNode("", true),
  2985. $options.config.viewType !== "simple" ? (vue.openBlock(), vue.createElementBlock("a", {
  2986. key: 1,
  2987. class: "base-avatar",
  2988. href: `/member/${$props.comment.username}`
  2989. }, [
  2990. vue.createElementVNode("img", {
  2991. src: $props.comment.avatar,
  2992. alt: ""
  2993. }, null, 8, _hoisted_3$b)
  2994. ], 8, _hoisted_2$e)) : vue.createCommentVNode("", true),
  2995. vue.createElementVNode("div", _hoisted_4$a, [
  2996. vue.createElementVNode("div", _hoisted_5$8, [
  2997. vue.createElementVNode("span", _hoisted_6$8, [
  2998. vue.createElementVNode("strong", null, [
  2999. vue.createElementVNode("a", {
  3000. href: `/member/${$props.comment.username}`,
  3001. class: vue.normalizeClass(["username", { "dark": $options.isNight }])
  3002. }, vue.toDisplayString($props.comment.username), 11, _hoisted_7$7)
  3003. ]),
  3004. $props.comment.isOp ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8$7, "OP")) : vue.createCommentVNode("", true),
  3005. $props.comment.isDup ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_9$7, "DUP")) : vue.createCommentVNode("", true),
  3006. $props.comment.isMod ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10$6, "MOD")) : vue.createCommentVNode("", true),
  3007. $options.isLogin && $options.config.openTag ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 3 }, [
  3008. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.myTags, (i) => {
  3009. return vue.openBlock(), vue.createElementBlock("span", _hoisted_11$6, [
  3010. _hoisted_12$6,
  3011. vue.createElementVNode("span", null, vue.toDisplayString(i), 1),
  3012. vue.createElementVNode("i", {
  3013. class: "fa fa-trash-o remove",
  3014. onClick: ($event) => $options.removeTag(i)
  3015. }, null, 8, _hoisted_13$6)
  3016. ]);
  3017. }), 256)),
  3018. vue.createElementVNode("span", {
  3019. class: "add-tag ago",
  3020. onClick: _cache[1] || (_cache[1] = (...args) => $options.addTag && $options.addTag(...args)),
  3021. title: "添加标签"
  3022. }, "+")
  3023. ], 64)) : vue.createCommentVNode("", true)
  3024. ])
  3025. ]),
  3026. vue.createElementVNode("div", null, [
  3027. vue.createElementVNode("span", _hoisted_14$5, vue.toDisplayString($props.comment.floor) + "楼", 1),
  3028. vue.createElementVNode("span", _hoisted_15$5, vue.toDisplayString($props.comment.date), 1)
  3029. ])
  3030. ])
  3031. ]),
  3032. vue.createElementVNode("div", _hoisted_16$5, [
  3033. vue.withDirectives(vue.createVNode(_component_Point, {
  3034. item: $options.pointInfo,
  3035. onAddThank: $options.addThank,
  3036. onRecallThank: $options.recallThank,
  3037. "api-url": "reply/" + $props.comment.id
  3038. }, null, 8, ["item", "onAddThank", "onRecallThank", "api-url"]), [
  3039. [vue.vShow, $props.comment.thankCount]
  3040. ]),
  3041. vue.createVNode(_component_MoreIcon, {
  3042. onClick: _cache[2] || (_cache[2] = vue.withModifiers(($event) => $options.eventBus.emit($options.CMD.SHOW_COMMENT_OPTIONS, { ...$props.comment, top: $props.type === "top" }), ["stop"]))
  3043. })
  3044. ])
  3045. ], 2);
  3046. }
  3047. const Author = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$6], ["__scopeId", "data-v-9041586a"]]);
  3048. const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
  3049. __name: "BaseLoading",
  3050. props: {
  3051. size: { default: "normal" }
  3052. },
  3053. setup(__props) {
  3054. return (_ctx, _cache) => {
  3055. return vue.openBlock(), vue.createElementBlock("div", {
  3056. class: vue.normalizeClass(["loading", [_ctx.size]])
  3057. }, null, 2);
  3058. };
  3059. }
  3060. });
  3061. const BaseLoading = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["__scopeId", "data-v-2697baa2"]]);
  3062. const _hoisted_1$g = {
  3063. key: 1,
  3064. class: "key-notice"
  3065. };
  3066. const _hoisted_2$d = { class: "key" };
  3067. const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
  3068. __name: "BaseButton",
  3069. props: {
  3070. keyboard: {},
  3071. active: { type: Boolean },
  3072. disabled: { type: Boolean },
  3073. loading: { type: Boolean },
  3074. size: { default: "normal" },
  3075. type: { default: "primary" }
  3076. },
  3077. emits: ["click"],
  3078. setup(__props) {
  3079. return (_ctx, _cache) => {
  3080. return vue.openBlock(), vue.createBlock(Tooltip, {
  3081. disabled: !_ctx.keyboard,
  3082. title: `快捷键: ${_ctx.keyboard}`
  3083. }, {
  3084. default: vue.withCtx(() => [
  3085. vue.createElementVNode("div", vue.mergeProps({ class: "base-button" }, _ctx.$attrs, {
  3086. onClick: _cache[0] || (_cache[0] = (e2) => !_ctx.disabled && !_ctx.loading && _ctx.$emit("click", e2)),
  3087. class: [
  3088. _ctx.active && "active",
  3089. _ctx.size,
  3090. _ctx.type,
  3091. (_ctx.disabled || _ctx.loading) && "disabled",
  3092. !_ctx.disabled && "hvr-grow"
  3093. ]
  3094. }), [
  3095. vue.createElementVNode("span", {
  3096. style: vue.normalizeStyle({ opacity: _ctx.loading ? 0 : 1 })
  3097. }, [
  3098. vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
  3099. ], 4),
  3100. _ctx.loading ? (vue.openBlock(), vue.createBlock(BaseLoading, {
  3101. key: 0,
  3102. size: "small"
  3103. })) : vue.createCommentVNode("", true),
  3104. _ctx.keyboard ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$g, [
  3105. vue.createElementVNode("span", _hoisted_2$d, vue.toDisplayString(_ctx.keyboard), 1)
  3106. ])) : vue.createCommentVNode("", true)
  3107. ], 16)
  3108. ]),
  3109. _: 3
  3110. }, 8, ["disabled", "title"]);
  3111. };
  3112. }
  3113. });
  3114. const BaseButton = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["__scopeId", "data-v-04f4c89d"]]);
  3115. const _withScopeId$a = (n2) => (vue.pushScopeId("data-v-0612e02f"), n2 = n2(), vue.popScopeId(), n2);
  3116. const _hoisted_1$f = { class: "get-cursor" };
  3117. const _hoisted_2$c = ["innerHTML"];
  3118. const _hoisted_3$a = { class: "toolbar" };
  3119. const _hoisted_4$9 = { class: "left" };
  3120. const _hoisted_5$7 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("path", {
  3121. d: "M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z",
  3122. fill: "none",
  3123. stroke: "#929596",
  3124. "stroke-width": "2",
  3125. "stroke-linejoin": "round"
  3126. }, null, -1));
  3127. const _hoisted_6$7 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("path", {
  3128. d: "M24 35C29 35 31 31 31 31H17C17 31 19 35 24 35Z",
  3129. stroke: "#929596",
  3130. "stroke-width": "2",
  3131. "stroke-linecap": "round",
  3132. "stroke-linejoin": "round"
  3133. }, null, -1));
  3134. const _hoisted_7$6 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("path", {
  3135. d: "M31 18V22",
  3136. stroke: "#929596",
  3137. "stroke-width": "2",
  3138. "stroke-linecap": "round",
  3139. "stroke-linejoin": "round"
  3140. }, null, -1));
  3141. const _hoisted_8$6 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("path", {
  3142. d: "M17 18V22",
  3143. stroke: "#929596",
  3144. "stroke-width": "2",
  3145. "stroke-linecap": "round",
  3146. "stroke-linejoin": "round"
  3147. }, null, -1));
  3148. const _hoisted_9$6 = [
  3149. _hoisted_5$7,
  3150. _hoisted_6$7,
  3151. _hoisted_7$6,
  3152. _hoisted_8$6
  3153. ];
  3154. const _hoisted_10$5 = { class: "upload" };
  3155. const _hoisted_11$5 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("svg", {
  3156. width: "20",
  3157. height: "20",
  3158. viewBox: "0 0 48 48",
  3159. fill: "none",
  3160. xmlns: "http://www.w3.org/2000/svg"
  3161. }, [
  3162. /* @__PURE__ */ vue.createElementVNode("path", {
  3163. "fill-rule": "evenodd",
  3164. "clip-rule": "evenodd",
  3165. d: "M5 10C5 8.89543 5.89543 8 7 8L41 8C42.1046 8 43 8.89543 43 10V38C43 39.1046 42.1046 40 41 40H7C5.89543 40 5 39.1046 5 38V10Z",
  3166. stroke: "#929596",
  3167. "stroke-width": "2",
  3168. "stroke-linecap": "round",
  3169. "stroke-linejoin": "round"
  3170. }),
  3171. /* @__PURE__ */ vue.createElementVNode("path", {
  3172. "fill-rule": "evenodd",
  3173. "clip-rule": "evenodd",
  3174. d: "M14.5 18C15.3284 18 16 17.3284 16 16.5C16 15.6716 15.3284 15 14.5 15C13.6716 15 13 15.6716 13 16.5C13 17.3284 13.6716 18 14.5 18Z",
  3175. stroke: "#929596",
  3176. "stroke-width": "2",
  3177. "stroke-linecap": "round",
  3178. "stroke-linejoin": "round"
  3179. }),
  3180. /* @__PURE__ */ vue.createElementVNode("path", {
  3181. d: "M15 24L20 28L26 21L43 34V38C43 39.1046 42.1046 40 41 40H7C5.89543 40 5 39.1046 5 38V34L15 24Z",
  3182. fill: "none",
  3183. stroke: "#929596",
  3184. "stroke-width": "2",
  3185. "stroke-linejoin": "round"
  3186. })
  3187. ], -1));
  3188. const _hoisted_12$5 = {
  3189. key: 0,
  3190. style: { "color": "black", "font-size": "1.4rem" }
  3191. };
  3192. const _hoisted_13$5 = { class: "right" };
  3193. const _hoisted_14$4 = /* @__PURE__ */ _withScopeId$a(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "title" }, "经典表情", -1));
  3194. const _hoisted_15$4 = { class: "list" };
  3195. const _hoisted_16$4 = ["src", "onClick"];
  3196. const _hoisted_17$2 = { class: "emoji" };
  3197. const _hoisted_18$2 = { class: "title" };
  3198. const _hoisted_19$2 = { class: "list" };
  3199. const _hoisted_20$2 = ["onClick"];
  3200. const _sfc_main$f = {
  3201. __name: "PostEditor",
  3202. props: {
  3203. replyUser: null,
  3204. replyFloor: null,
  3205. useType: {
  3206. type: String,
  3207. default() {
  3208. return "reply-comment";
  3209. }
  3210. }
  3211. },
  3212. emits: ["close"],
  3213. setup(__props, { expose: __expose, emit: __emit }) {
  3214. let props = __props;
  3215. let { replyUser, replyFloor, useType } = props;
  3216. let replyInfo = replyUser ? `@${replyUser} #${replyFloor} ` : "";
  3217. const emits = __emit;
  3218. const post = vue.inject("post");
  3219. const show = vue.inject("show");
  3220. const isNight = vue.inject("isNight");
  3221. const allReplyUsers = vue.inject("allReplyUsers");
  3222. let isFocus = vue.ref(false);
  3223. const loading = vue.ref(false);
  3224. const uploadLoading = vue.ref(false);
  3225. const isShowEmoticons = vue.ref(false);
  3226. const editorId = vue.ref("editorId_" + Date.now());
  3227. const content = vue.ref(replyInfo);
  3228. const txtRef = vue.ref(null);
  3229. const cursorRef = vue.ref(null);
  3230. const emoticonsRef = vue.ref(null);
  3231. const none = vue.ref('<span style="white-space:pre-wrap;"> </span>');
  3232. vue.watch(props, (n2) => {
  3233. replyUser = props.replyUser;
  3234. replyFloor = props.replyFloor;
  3235. useType = props.useType;
  3236. replyInfo = replyUser ? `@${replyUser} #${replyFloor} ` : "";
  3237. content.value = replyInfo;
  3238. });
  3239. const emojiEmoticons = [
  3240. {
  3241. title: "小黄脸",
  3242. list: [
  3243. "😀",
  3244. "😁",
  3245. "😂",
  3246. "🤣",
  3247. "😅",
  3248. "😊",
  3249. "😋",
  3250. "😘",
  3251. "🥰",
  3252. "😗",
  3253. "🤩",
  3254. "🤔",
  3255. "🤨",
  3256. "😐",
  3257. "😑",
  3258. "🙄",
  3259. "😏",
  3260. "😪",
  3261. "😫",
  3262. "🥱",
  3263. "😜",
  3264. "😒",
  3265. "😔",
  3266. "😨",
  3267. "😰",
  3268. "😱",
  3269. "🥵",
  3270. "😡",
  3271. "🥳",
  3272. "🥺",
  3273. "🤭",
  3274. "🧐",
  3275. "😎",
  3276. "🤓",
  3277. "😭",
  3278. "🤑",
  3279. "🤮"
  3280. ]
  3281. },
  3282. {
  3283. title: "手势",
  3284. list: [
  3285. "🙋",
  3286. "🙎",
  3287. "🙅",
  3288. "🙇",
  3289. "🤷",
  3290. "🤏",
  3291. "👉",
  3292. "✌️",
  3293. "🤘",
  3294. "🤙",
  3295. "👌",
  3296. "🤌",
  3297. "👍",
  3298. "👎",
  3299. "👋",
  3300. "🤝",
  3301. "🙏",
  3302. "👏"
  3303. ]
  3304. },
  3305. {
  3306. title: "庆祝",
  3307. list: ["✨", "🎉", "🎊"]
  3308. },
  3309. {
  3310. title: "其他",
  3311. list: ["👻", "🤡", "🐔", "👀", "💩", "🐴", "🦄", "🐧", "🐶", "🐒", "🙈", "🙉", "🙊", "🐵"]
  3312. }
  3313. ];
  3314. const classicsEmoticons = [
  3315. {
  3316. name: "[狗头]",
  3317. low: "https://i.imgur.com/io2SM1h.png",
  3318. high: "https://i.imgur.com/0icl60r.png"
  3319. },
  3320. {
  3321. name: "[马]",
  3322. low: "https://i.imgur.com/8EKZv7I.png",
  3323. high: "https://i.imgur.com/ANFUX52.png"
  3324. },
  3325. {
  3326. name: "[不高兴]",
  3327. low: "https://i.imgur.com/huX6coX.png",
  3328. high: "https://i.imgur.com/N7JEuvc.png"
  3329. },
  3330. {
  3331. name: "[呵呵]",
  3332. low: "https://i.imgur.com/RvoLAbX.png",
  3333. high: "https://i.imgur.com/xSzIqrK.png"
  3334. },
  3335. {
  3336. name: "[真棒]",
  3337. low: "https://i.imgur.com/xr1UOz1.png",
  3338. high: "https://i.imgur.com/w8YEw9Q.png"
  3339. },
  3340. {
  3341. name: "[鄙视]",
  3342. low: "https://i.imgur.com/u6jlqVq.png",
  3343. high: "https://i.imgur.com/8JFNANq.png"
  3344. },
  3345. {
  3346. name: "[疑问]",
  3347. low: "https://i.imgur.com/F29pmQ6.png",
  3348. high: "https://i.imgur.com/EbbTQAR.png"
  3349. },
  3350. {
  3351. name: "[吐舌]",
  3352. low: "https://i.imgur.com/InmIzl9.png",
  3353. high: "https://i.imgur.com/Ovj56Cd.png"
  3354. },
  3355. // {
  3356. // name: '[嘲笑]',
  3357. // low: 'https://i.imgur.com/BaWcsMR.png',
  3358. // high: 'https://i.imgur.com/0OGfJw4.png'
  3359. // },
  3360. // {
  3361. // name: '[滑稽]',
  3362. // low: 'https://i.imgur.com/lmbN0yI.png',
  3363. // high: 'https://i.imgur.com/Pc0wH85.png'
  3364. // },
  3365. {
  3366. name: "[笑眼]",
  3367. low: "https://i.imgur.com/ZveiiGy.png",
  3368. high: "https://i.imgur.com/PI1CfEr.png"
  3369. },
  3370. {
  3371. name: "[狂汗]",
  3372. low: "https://i.imgur.com/veWihk6.png",
  3373. high: "https://i.imgur.com/3LtHdQv.png"
  3374. },
  3375. {
  3376. name: "[大哭]",
  3377. low: "https://i.imgur.com/hu4oR6C.png",
  3378. high: "https://i.imgur.com/b4X9XLE.png"
  3379. },
  3380. {
  3381. name: "[喷]",
  3382. low: "https://i.imgur.com/bkw3VRr.png",
  3383. high: "https://i.imgur.com/wnZL13L.png"
  3384. },
  3385. {
  3386. name: "[苦笑]",
  3387. low: "https://i.imgur.com/VUWFktU.png",
  3388. high: "https://i.imgur.com/NAfspZ1.png"
  3389. },
  3390. {
  3391. name: "[喝酒]",
  3392. low: "https://i.imgur.com/2ZZSapE.png",
  3393. high: "https://i.imgur.com/rVbSVak.png"
  3394. },
  3395. {
  3396. name: "[吃瓜]",
  3397. low: "https://i.imgur.com/ee8Lq7H.png",
  3398. high: "https://i.imgur.com/0L26og9.png"
  3399. },
  3400. {
  3401. name: "[捂脸]",
  3402. low: "https://i.imgur.com/krir4IG.png",
  3403. high: "https://i.imgur.com/qqBqgVm.png"
  3404. },
  3405. {
  3406. name: "[呕]",
  3407. low: "https://i.imgur.com/6CUiUxv.png",
  3408. high: "https://i.imgur.com/kgdxRsG.png"
  3409. },
  3410. {
  3411. name: "[阴险]",
  3412. low: "https://i.imgur.com/MA8YqTP.png",
  3413. high: "https://i.imgur.com/e94jbaT.png"
  3414. },
  3415. {
  3416. name: "[怒]",
  3417. low: "https://i.imgur.com/n4kWfGB.png",
  3418. high: "https://i.imgur.com/iMXxNxh.png"
  3419. },
  3420. {
  3421. name: "[衰]",
  3422. low: "https://i.imgur.com/voHFDyQ.png",
  3423. high: "https://i.imgur.com/XffE6gu.png"
  3424. },
  3425. {
  3426. name: "[合十]",
  3427. low: "https://i.imgur.com/I8x3ang.png",
  3428. high: "https://i.imgur.com/T4rJVee.png"
  3429. },
  3430. {
  3431. name: "[赞]",
  3432. low: "https://i.imgur.com/lG44yUl.png",
  3433. high: "https://i.imgur.com/AoF5PLp.png"
  3434. },
  3435. {
  3436. name: "[踩]",
  3437. low: "https://i.imgur.com/cJp0uKZ.png",
  3438. high: "https://i.imgur.com/1XYGfXj.png"
  3439. },
  3440. {
  3441. name: "[爱心]",
  3442. low: "https://i.imgur.com/sLENaF5.png",
  3443. high: "https://i.imgur.com/dND56oX.png"
  3444. },
  3445. {
  3446. name: "[心碎]",
  3447. low: "https://i.imgur.com/AZxJzve.png",
  3448. high: "https://i.imgur.com/RiUsPci.png"
  3449. }
  3450. ];
  3451. const imgurClientIdPool = [
  3452. "3107b9ef8b316f3",
  3453. "442b04f26eefc8a",
  3454. "59cfebe717c09e4",
  3455. "60605aad4a62882",
  3456. "6c65ab1d3f5452a",
  3457. "83e123737849aa9",
  3458. "9311f6be1c10160",
  3459. "c4a4a563f698595",
  3460. "81be04b9e4a08ce"
  3461. ];
  3462. const editorClass = vue.computed(() => {
  3463. return [isFocus.value ? "isFocus" : "", isNight.value ? "isNight" : ""];
  3464. });
  3465. const cursorHtml = vue.computed(() => {
  3466. var _a;
  3467. if (!txtRef.value || !content.value)
  3468. return "";
  3469. let index = ((_a = txtRef.value) == null ? void 0 : _a.selectionStart) || 0;
  3470. return content.value.substring(0, index).replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br/>").replace(/\s/g, none.value);
  3471. });
  3472. const disabled = vue.computed(() => {
  3473. if (content.value) {
  3474. return content.value === replyInfo;
  3475. } else {
  3476. return true;
  3477. }
  3478. });
  3479. function focus() {
  3480. txtRef.value.focus();
  3481. }
  3482. __expose({ content, focus });
  3483. function drop(e2) {
  3484. e2.preventDefault();
  3485. upload(e2.dataTransfer.files[0]);
  3486. }
  3487. async function upload(file) {
  3488. if (!file)
  3489. return;
  3490. if (uploadLoading.value)
  3491. return;
  3492. uploadLoading.value = true;
  3493. const formData = new FormData();
  3494. formData.append("image", file);
  3495. const randomIndex = Math.floor(Math.random() * imgurClientIdPool.length);
  3496. const clidenId = imgurClientIdPool[randomIndex];
  3497. const res = await fetch("https://api.imgur.com/3/upload", {
  3498. method: "POST",
  3499. headers: { Authorization: `Client-ID ${clidenId}` },
  3500. body: formData
  3501. });
  3502. uploadLoading.value = false;
  3503. if (res.ok) {
  3504. const resData = await res.json();
  3505. if (resData.success) {
  3506. return insert(" " + resData.data.link + " ");
  3507. }
  3508. }
  3509. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "上传失败" });
  3510. }
  3511. async function submit() {
  3512. if (disabled.value || loading.value)
  3513. return;
  3514. loading.value = true;
  3515. let submit_content = content.value.replace(/\[((?!\[).)+\]/g, function(match) {
  3516. let item2 = classicsEmoticons.find((v) => v.name === match);
  3517. if (item2) {
  3518. return item2.low + " ";
  3519. }
  3520. return match;
  3521. });
  3522. let show_content = content.value.replace(/https?:\/\/(i\.)?imgur\.com\/((?!http).)+\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)/g, function(match) {
  3523. return `<img src="${match}" data-originUrl="${match}" data-notice="这个img标签由v2ex-超级增强脚本解析" style="max-width: 100%">`;
  3524. });
  3525. show_content = show_content.replace(/\[((?!\[).)+\]/g, function(match) {
  3526. let item2 = classicsEmoticons.find((v) => v.name === match);
  3527. if (item2) {
  3528. return `<a target="_blank" href="${item2.low}" rel="nofollow noopener"><img src="${item2.low}" class="embedded_image" rel="noreferrer"></a> `;
  3529. }
  3530. return match;
  3531. });
  3532. let matchUsers = show_content.match(/@([\w]+?[\s])/g);
  3533. if (matchUsers) {
  3534. matchUsers.map((i) => {
  3535. let username = i.replace("@", "").replace(" ", "");
  3536. show_content = show_content.replace(username, `<a href="/member/${username}">${username}</a>`);
  3537. });
  3538. }
  3539. show_content = show_content.replaceAll("\n", "<br/>");
  3540. let item = {
  3541. thankCount: 0,
  3542. isThanked: false,
  3543. isOp: post.value.username === window.user.username,
  3544. isDup: false,
  3545. id: Date.now(),
  3546. username: window.user.username,
  3547. avatar: window.user.avatar,
  3548. date: "几秒前",
  3549. floor: post.value.replyCount + 1,
  3550. reply_content: show_content ?? "",
  3551. children: [],
  3552. replyUsers: replyUser ? [replyUser] : [],
  3553. replyFloor: replyFloor || -1,
  3554. level: useType === "reply-comment" ? 1 : 0
  3555. };
  3556. item.hideCallUserReplyContent = item.reply_content;
  3557. if (item.replyUsers.length === 1) {
  3558. item.hideCallUserReplyContent = item.reply_content.replace(/@<a href="\/member\/[\s\S]+?<\/a>(\s#[\d]+)?\s(<br>)?/, () => "");
  3559. }
  3560. console.log("回复", item);
  3561. let url = `${window.baseUrl}/t/${post.value.id}`;
  3562. $.post(url, { content: submit_content, once: post.value.once }).then(
  3563. // $.post(url, {content: submit_content, once: 123}).then(
  3564. (res) => {
  3565. loading.value = false;
  3566. let r2 = res.search("你上一条回复的内容和这条相同");
  3567. if (r2 > -1)
  3568. return eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "你上一条回复的内容和这条相同" });
  3569. r2 = res.search("请不要在每一个回复中都包括外链,这看起来像是在 spamming");
  3570. if (r2 > -1)
  3571. return eventBus.emit(CMD.SHOW_MSG, {
  3572. type: "error",
  3573. text: "请不要在每一个回复中都包括外链,这看起来像是在 spamming"
  3574. });
  3575. let r22 = res.search("创建新回复");
  3576. if (r22 > -1) {
  3577. eventBus.emit(CMD.REFRESH_ONCE, res);
  3578. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "回复出现了问题,请使用原版进行回复" });
  3579. let clientWidth = window.document.body.clientWidth;
  3580. let windowWidth = 1200;
  3581. let left = clientWidth / 2 - windowWidth / 2;
  3582. let newWin = window.open("创建新回复", "", `width=${windowWidth},height=600,left=${left},top=100`);
  3583. newWin.document.write(res);
  3584. let loop = setInterval(function() {
  3585. if (newWin.closed) {
  3586. clearInterval(loop);
  3587. eventBus.emit(CMD.REFRESH_POST);
  3588. }
  3589. }, 1e3);
  3590. return;
  3591. }
  3592. content.value = replyInfo;
  3593. emits("close");
  3594. eventBus.emit(CMD.REFRESH_ONCE, res);
  3595. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "回复成功" });
  3596. eventBus.emit(CMD.ADD_REPLY, item);
  3597. },
  3598. (err) => {
  3599. console.log("err", err);
  3600. loading.value = false;
  3601. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "回复失败" });
  3602. }
  3603. ).catch((r2) => {
  3604. console.log("catch", r2);
  3605. });
  3606. }
  3607. function showEmoticons(e2) {
  3608. if (isShowEmoticons.value) {
  3609. return isShowEmoticons.value = false;
  3610. }
  3611. let rect = e2.currentTarget.getBoundingClientRect();
  3612. emoticonsRef.value.style.left = rect.left + 30 + "px";
  3613. emoticonsRef.value.style.bottom = window.innerHeight - rect.top - 20 + "px";
  3614. isShowEmoticons.value = true;
  3615. }
  3616. function off() {
  3617. eventBus.emit(CMD.SHOW_CALL, { show: false });
  3618. eventBus.off(CMD.SET_CALL);
  3619. }
  3620. function checkHeight2() {
  3621. txtRef.value.style.height = 0;
  3622. txtRef.value.style.height = txtRef.value.scrollHeight + "px";
  3623. }
  3624. function insert(str) {
  3625. let cursorPos = txtRef.value.selectionStart;
  3626. let start = content.value.slice(0, cursorPos);
  3627. let end = content.value.slice(cursorPos, content.value.length);
  3628. content.value = start + str + end;
  3629. let moveCursorPos = start.length + str.length;
  3630. setTimeout(() => {
  3631. txtRef.value.focus();
  3632. txtRef.value.setSelectionRange(moveCursorPos, moveCursorPos);
  3633. checkHeight2();
  3634. });
  3635. }
  3636. function showCallPopover(text) {
  3637. let r2 = cursorRef.value.getBoundingClientRect();
  3638. eventBus.emit(CMD.SHOW_CALL, { show: true, top: r2.top, left: r2.left, text });
  3639. eventBus.off(CMD.SET_CALL);
  3640. eventBus.on(CMD.SET_CALL, (e2) => {
  3641. let cursorPos = txtRef.value.selectionStart;
  3642. let start = content.value.slice(0, cursorPos);
  3643. let end = content.value.slice(cursorPos, content.value.length);
  3644. let lastCallPos = start.lastIndexOf("@");
  3645. start = content.value.slice(0, lastCallPos + 1);
  3646. if (e2 === "管理员") {
  3647. e2 = "Livid @Kai @Olivia @GordianZ @sparanoid";
  3648. }
  3649. if (e2 === "所有人") {
  3650. e2 = allReplyUsers.value.map((v, i) => {
  3651. if (i)
  3652. return "@" + v;
  3653. else
  3654. return v;
  3655. }).join(" ");
  3656. }
  3657. content.value = start + e2 + " " + end;
  3658. let moveCursorPos = start.length + e2.length + 1;
  3659. setTimeout(() => {
  3660. txtRef.value.setSelectionRange(moveCursorPos, moveCursorPos);
  3661. checkHeight2();
  3662. });
  3663. eventBus.off(CMD.SET_CALL);
  3664. });
  3665. }
  3666. function onKeydown(e2) {
  3667. let code = e2.keyCode;
  3668. switch (code) {
  3669. case 8:
  3670. if (content.value === "@") {
  3671. off();
  3672. }
  3673. break;
  3674. case 37:
  3675. case 38:
  3676. case 39:
  3677. case 40:
  3678. setTimeout(() => onInput({ data: "" }), 100);
  3679. break;
  3680. case 27:
  3681. e2.preventDefault();
  3682. e2.stopPropagation();
  3683. e2.stopImmediatePropagation();
  3684. return false;
  3685. case 13:
  3686. if (e2.ctrlKey)
  3687. submit();
  3688. if (e2.metaKey)
  3689. submit();
  3690. break;
  3691. }
  3692. }
  3693. function onInput(e2) {
  3694. let cursorPos = txtRef.value.selectionStart;
  3695. if (!content.value)
  3696. return;
  3697. if (e2.data === " ") {
  3698. return off();
  3699. }
  3700. if (e2.data === "@") {
  3701. if (content.value.length !== 1) {
  3702. if (content.value[cursorPos - 2] === " " || content.value[cursorPos - 2] === "\n") {
  3703. return showCallPopover("");
  3704. }
  3705. } else {
  3706. return showCallPopover("");
  3707. }
  3708. off();
  3709. } else {
  3710. let judgeStr = content.value.slice(0, cursorPos);
  3711. let lastCallPos = judgeStr.lastIndexOf("@");
  3712. if (lastCallPos === -1) {
  3713. return off();
  3714. }
  3715. let callStr = judgeStr.slice(lastCallPos, cursorPos);
  3716. let hasSpace = callStr.includes(" ");
  3717. if (hasSpace) {
  3718. off();
  3719. } else {
  3720. if (lastCallPos === 0) {
  3721. return showCallPopover(callStr.replace("@", ""));
  3722. }
  3723. if (content.value.length !== 1) {
  3724. if (content.value[lastCallPos - 1] === " " || content.value[lastCallPos - 1] === "\n") {
  3725. return showCallPopover(callStr.replace("@", ""));
  3726. }
  3727. } else {
  3728. return showCallPopover(callStr.replace("@", ""));
  3729. }
  3730. off();
  3731. }
  3732. }
  3733. }
  3734. function onPaste(e2) {
  3735. const dataTransferItemList = e2.clipboardData.items;
  3736. const items = [].slice.call(dataTransferItemList).filter(function(item) {
  3737. return item.type.indexOf("image") !== -1;
  3738. });
  3739. if (items.length === 0) {
  3740. return;
  3741. }
  3742. const dataTransferItem = items[0];
  3743. const blob = dataTransferItem.getAsFile();
  3744. upload(blob);
  3745. }
  3746. function onBlur() {
  3747. document.removeEventListener("paste", onPaste);
  3748. isFocus.value = false;
  3749. }
  3750. function onFocusin() {
  3751. document.addEventListener("paste", onPaste);
  3752. }
  3753. vue.watch(() => show, (n2) => {
  3754. if (n2.value)
  3755. isShowEmoticons.value = false;
  3756. }, { deep: true });
  3757. vue.onMounted(() => {
  3758. $(`.${editorId.value}`).each(function() {
  3759. this.setAttribute("style", "height:" + this.scrollHeight + "px;overflow-y:hidden;");
  3760. }).on("input", function() {
  3761. this.style.height = 0;
  3762. this.style.height = this.scrollHeight + "px";
  3763. });
  3764. });
  3765. return (_ctx, _cache) => {
  3766. return vue.openBlock(), vue.createElementBlock("div", {
  3767. class: vue.normalizeClass(["post-editor-wrapper", editorClass.value])
  3768. }, [
  3769. vue.withDirectives(vue.createElementVNode("textarea", {
  3770. class: vue.normalizeClass(["post-editor", editorId.value]),
  3771. ref_key: "txtRef",
  3772. ref: txtRef,
  3773. onFocus: _cache[0] || (_cache[0] = ($event) => vue.isRef(isFocus) ? isFocus.value = true : isFocus = true),
  3774. onBlur,
  3775. onFocusin,
  3776. placeholder: "请尽量让自己的回复能够对别人有帮助",
  3777. onInput,
  3778. onKeydown,
  3779. onDrop: drop,
  3780. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => content.value = $event)
  3781. }, null, 34), [
  3782. [vue.vModelText, content.value]
  3783. ]),
  3784. vue.createElementVNode("div", _hoisted_1$f, [
  3785. vue.createElementVNode("span", { innerHTML: cursorHtml.value }, null, 8, _hoisted_2$c),
  3786. vue.createElementVNode("span", {
  3787. class: "cursor",
  3788. ref_key: "cursorRef",
  3789. ref: cursorRef
  3790. }, "|", 512)
  3791. ]),
  3792. vue.createElementVNode("div", _hoisted_3$a, [
  3793. vue.createElementVNode("div", _hoisted_4$9, [
  3794. (vue.openBlock(), vue.createElementBlock("svg", {
  3795. onClick: showEmoticons,
  3796. width: "20",
  3797. height: "20",
  3798. viewBox: "0 0 48 48",
  3799. fill: "none",
  3800. xmlns: "http://www.w3.org/2000/svg"
  3801. }, _hoisted_9$6)),
  3802. vue.createElementVNode("div", _hoisted_10$5, [
  3803. vue.createElementVNode("input", {
  3804. type: "file",
  3805. accept: "image/*",
  3806. onChange: _cache[2] || (_cache[2] = (e2) => upload(e2.currentTarget.files[0]))
  3807. }, null, 32),
  3808. _hoisted_11$5
  3809. ]),
  3810. uploadLoading.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_12$5, "上传中.....")) : vue.createCommentVNode("", true)
  3811. ]),
  3812. vue.createElementVNode("div", _hoisted_13$5, [
  3813. vue.createVNode(BaseButton, {
  3814. size: "small",
  3815. disabled: disabled.value,
  3816. loading: loading.value,
  3817. onClick: submit
  3818. }, {
  3819. default: vue.withCtx(() => [
  3820. vue.createTextVNode("回复 ")
  3821. ]),
  3822. _: 1
  3823. }, 8, ["disabled", "loading"])
  3824. ])
  3825. ]),
  3826. vue.withDirectives(vue.createElementVNode("div", {
  3827. class: "emoticon-pack",
  3828. ref_key: "emoticonsRef",
  3829. ref: emoticonsRef
  3830. }, [
  3831. vue.createElementVNode("i", {
  3832. class: "fa fa-times",
  3833. "aria-hidden": "true",
  3834. onClick: _cache[3] || (_cache[3] = ($event) => isShowEmoticons.value = false)
  3835. }),
  3836. _hoisted_14$4,
  3837. vue.createElementVNode("div", _hoisted_15$4, [
  3838. (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(classicsEmoticons, (item) => {
  3839. return vue.createElementVNode("img", {
  3840. src: item.high,
  3841. onClick: ($event) => {
  3842. insert(item.name);
  3843. isShowEmoticons.value = false;
  3844. }
  3845. }, null, 8, _hoisted_16$4);
  3846. }), 64))
  3847. ]),
  3848. vue.createElementVNode("div", _hoisted_17$2, [
  3849. (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(emojiEmoticons, (item) => {
  3850. return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
  3851. vue.createElementVNode("div", _hoisted_18$2, vue.toDisplayString(item.title), 1),
  3852. vue.createElementVNode("div", _hoisted_19$2, [
  3853. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(item.list, (emoji) => {
  3854. return vue.openBlock(), vue.createElementBlock("span", {
  3855. onClick: ($event) => {
  3856. insert(emoji);
  3857. isShowEmoticons.value = false;
  3858. }
  3859. }, vue.toDisplayString(emoji), 9, _hoisted_20$2);
  3860. }), 256))
  3861. ])
  3862. ], 64);
  3863. }), 64))
  3864. ])
  3865. ], 512), [
  3866. [vue.vShow, isShowEmoticons.value]
  3867. ])
  3868. ], 2);
  3869. };
  3870. }
  3871. };
  3872. const PostEditor = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["__scopeId", "data-v-0612e02f"]]);
  3873. const _hoisted_1$e = {
  3874. key: 0,
  3875. class: "html-wrapper"
  3876. };
  3877. const _hoisted_2$b = ["innerHTML"];
  3878. const checkHeight = 900;
  3879. const _sfc_main$e = {
  3880. __name: "BaseHtmlRender",
  3881. props: ["html"],
  3882. setup(__props) {
  3883. const config2 = vue.inject("config");
  3884. const props = __props;
  3885. const contentRef = vue.ref(null);
  3886. const htmlMask = vue.ref(false);
  3887. const handOpen = vue.ref(false);
  3888. function mouseup(e2) {
  3889. if (!config2.value.base64)
  3890. return;
  3891. let selectionText = window.win().getSelection().toString();
  3892. if (selectionText) {
  3893. let r2 = selectionText.match(/([A-Za-z0-9+/=]+)/g);
  3894. if (r2) {
  3895. if (r2[0].length < 4)
  3896. return;
  3897. eventBus.emit(CMD.SHOW_TOOLTIP, { text: r2[0], e: e2 });
  3898. }
  3899. }
  3900. }
  3901. vue.watch(config2.value, (newVale) => {
  3902. if (!newVale.contentAutoCollapse) {
  3903. htmlMask.value = false;
  3904. }
  3905. });
  3906. vue.watch([() => contentRef.value, () => props.html], () => {
  3907. if (!contentRef.value || !props.html)
  3908. return;
  3909. if (!config2.value.contentAutoCollapse)
  3910. return;
  3911. contentRef.value.querySelectorAll("img").forEach((item) => {
  3912. item.removeEventListener("load", checkContentHeight);
  3913. item.addEventListener("load", checkContentHeight);
  3914. });
  3915. checkContentHeight();
  3916. }, { immediate: true, flush: "post" });
  3917. function checkContentHeight() {
  3918. if (handOpen.value)
  3919. return;
  3920. let rect = contentRef.value.getBoundingClientRect();
  3921. htmlMask.value = rect.height >= checkHeight;
  3922. }
  3923. return (_ctx, _cache) => {
  3924. return props.html ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$e, [
  3925. vue.createElementVNode("div", {
  3926. class: vue.normalizeClass({ htmlMask: htmlMask.value })
  3927. }, [
  3928. vue.createElementVNode("div", {
  3929. ref_key: "contentRef",
  3930. ref: contentRef,
  3931. innerHTML: props.html,
  3932. onMouseup: mouseup
  3933. }, null, 40, _hoisted_2$b)
  3934. ], 2),
  3935. htmlMask.value ? (vue.openBlock(), vue.createElementBlock("div", {
  3936. key: 0,
  3937. class: "expand",
  3938. onClick: _cache[0] || (_cache[0] = ($event) => {
  3939. htmlMask.value = false;
  3940. handOpen.value = true;
  3941. })
  3942. }, "展开")) : vue.createCommentVNode("", true)
  3943. ])) : vue.createCommentVNode("", true);
  3944. };
  3945. }
  3946. };
  3947. const BaseHtmlRender = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["__scopeId", "data-v-f8165980"]]);
  3948. const _sfc_main$d = {
  3949. name: "Comment",
  3950. components: { MoreIcon, BaseHtmlRender, Author, PostEditor, Point },
  3951. inject: ["post", "show", "isNight", "config"],
  3952. props: {
  3953. modelValue: {
  3954. reply_content: ""
  3955. },
  3956. type: {
  3957. type: String,
  3958. default() {
  3959. return "list";
  3960. }
  3961. }
  3962. },
  3963. data() {
  3964. return {
  3965. edit: false,
  3966. ding: false,
  3967. expand: true,
  3968. expandWrong: false,
  3969. replyInfo: `@${this.modelValue.username} #${this.modelValue.floor} `,
  3970. cssStyle: null,
  3971. floor: this.modelValue.floor
  3972. };
  3973. },
  3974. watch: {
  3975. show(e2) {
  3976. if (e2) {
  3977. this.edit = false;
  3978. }
  3979. },
  3980. postDetailWidth(n2, o) {
  3981. this.checkIsTooLong(n2);
  3982. }
  3983. },
  3984. computed: {
  3985. eventBus() {
  3986. return eventBus;
  3987. },
  3988. CMD() {
  3989. return CMD;
  3990. },
  3991. CommentDisplayType() {
  3992. return CommentDisplayType;
  3993. },
  3994. myClass() {
  3995. return {
  3996. isOp: this.modelValue.isOp,
  3997. ding: this.ding,
  3998. isLevelOne: this.modelValue.level === 0,
  3999. ["c_" + this.floor]: this.type !== "top"
  4000. };
  4001. }
  4002. },
  4003. mounted() {
  4004. this.checkIsTooLong();
  4005. },
  4006. methods: {
  4007. checkIsTooLong() {
  4008. let rect = this.$refs.comment.getBoundingClientRect();
  4009. let postDetailWidth = document.body.clientWidth;
  4010. let ban = postDetailWidth / 2;
  4011. if (ban < rect.width && rect.width < ban + 25 && this.modelValue.children.length) {
  4012. this.expand = false;
  4013. let padding = 2;
  4014. this.cssStyle = {
  4015. padding: "1rem 0",
  4016. width: `calc(${postDetailWidth}px - ${padding}rem)`,
  4017. transform: `translateX(calc(${rect.width - postDetailWidth}px + ${padding}rem))`,
  4018. background: this.isNight ? "#18222d" : "white"
  4019. };
  4020. }
  4021. },
  4022. //高亮一下
  4023. showDing() {
  4024. this.ding = true;
  4025. setTimeout(() => {
  4026. this.ding = false;
  4027. }, 2e3);
  4028. },
  4029. toggle() {
  4030. this.expand = !this.expand;
  4031. }
  4032. }
  4033. };
  4034. const _withScopeId$9 = (n2) => (vue.pushScopeId("data-v-312e9541"), n2 = n2(), vue.popScopeId(), n2);
  4035. const _hoisted_1$d = ["data-floor"];
  4036. const _hoisted_2$a = { class: "comment-content" };
  4037. const _hoisted_3$9 = { class: "right" };
  4038. const _hoisted_4$8 = { class: "w" };
  4039. const _hoisted_5$6 = {
  4040. key: 0,
  4041. class: "wrong-wrapper"
  4042. };
  4043. const _hoisted_6$6 = ["href"];
  4044. const _hoisted_7$5 = { class: "del-line" };
  4045. const _hoisted_8$5 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("i", {
  4046. class: "fa fa-question-circle-o wrong-icon",
  4047. "aria-hidden": "true"
  4048. }, null, -1));
  4049. const _hoisted_9$5 = {
  4050. key: 0,
  4051. class: "warning"
  4052. };
  4053. const _hoisted_10$4 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  4054. const _hoisted_11$4 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  4055. const _hoisted_12$4 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  4056. const _hoisted_13$4 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  4057. const _hoisted_14$3 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  4058. const _hoisted_15$3 = /* @__PURE__ */ _withScopeId$9(() => /* @__PURE__ */ vue.createElementVNode("a", {
  4059. href: "https://github.com/zyronon/web-scripts/issues",
  4060. target: "_blank"
  4061. }, "这里", -1));
  4062. const _hoisted_16$3 = { class: "simple-wrapper" };
  4063. function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
  4064. const _component_Author = vue.resolveComponent("Author");
  4065. const _component_BaseHtmlRender = vue.resolveComponent("BaseHtmlRender");
  4066. const _component_Comment = vue.resolveComponent("Comment", true);
  4067. return vue.openBlock(), vue.createElementBlock("div", {
  4068. class: vue.normalizeClass(["comment", $options.myClass]),
  4069. ref: "comment",
  4070. "data-floor": $data.floor
  4071. }, [
  4072. vue.createVNode(_component_Author, {
  4073. modelValue: $data.expand,
  4074. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.expand = $event),
  4075. comment: $props.modelValue,
  4076. type: $props.type
  4077. }, null, 8, ["modelValue", "comment", "type"]),
  4078. $data.cssStyle && !$data.expand ? (vue.openBlock(), vue.createElementBlock("div", {
  4079. key: 0,
  4080. class: "more ago",
  4081. onClick: _cache[1] || (_cache[1] = ($event) => $data.expand = !$data.expand)
  4082. }, " 由于嵌套回复层级太深,自动将后续回复隐藏 ")) : vue.createCommentVNode("", true),
  4083. $data.expand ? (vue.openBlock(), vue.createElementBlock("div", {
  4084. key: 1,
  4085. class: "comment-content-w",
  4086. style: vue.normalizeStyle($data.cssStyle)
  4087. }, [
  4088. $data.cssStyle ? (vue.openBlock(), vue.createElementBlock("div", {
  4089. key: 0,
  4090. class: "more ago",
  4091. onClick: _cache[2] || (_cache[2] = ($event) => $data.expand = !$data.expand)
  4092. }, " 由于嵌套回复层级太深,自动将以下回复移至可见范围 ")) : vue.createCommentVNode("", true),
  4093. vue.createElementVNode("div", _hoisted_2$a, [
  4094. vue.createElementVNode("div", {
  4095. class: "left expand-line",
  4096. onClick: _cache[3] || (_cache[3] = (...args) => $options.toggle && $options.toggle(...args))
  4097. }),
  4098. vue.createElementVNode("div", _hoisted_3$9, [
  4099. vue.createElementVNode("div", _hoisted_4$8, [
  4100. $props.modelValue.isWrong ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$6, [
  4101. vue.createElementVNode("span", {
  4102. onClick: _cache[4] || (_cache[4] = ($event) => $data.expandWrong = !$data.expandWrong),
  4103. title: "点击楼层号查看提示"
  4104. }, [
  4105. vue.createElementVNode("a", {
  4106. href: "/member/" + $props.modelValue.replyUsers[0]
  4107. }, "@" + vue.toDisplayString($props.modelValue.replyUsers[0]) + "  ", 9, _hoisted_6$6),
  4108. vue.createElementVNode("span", _hoisted_7$5, "#" + vue.toDisplayString($props.modelValue.replyFloor), 1),
  4109. _hoisted_8$5
  4110. ]),
  4111. $data.expandWrong ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_9$5, [
  4112. vue.createTextVNode(" 这条回复似乎有点问题,指定的楼层号与@的人对应不上 "),
  4113. _hoisted_10$4,
  4114. vue.createTextVNode(" 原因可能有下面几种: "),
  4115. _hoisted_11$4,
  4116. vue.createTextVNode(" 一、屏蔽用户导致楼层塌陷:你屏蔽了A,自A以后的回复的楼层号都会减1 "),
  4117. _hoisted_12$4,
  4118. vue.createTextVNode(" 二、忽略回复导致楼层塌陷:原理同上 "),
  4119. _hoisted_13$4,
  4120. vue.createTextVNode(" 三、层主回复时指定错了楼层号(同一,层主屏蔽了别人,导致楼层塌陷) "),
  4121. _hoisted_14$3,
  4122. vue.createTextVNode(" 四、脚本解析错误,请在 "),
  4123. _hoisted_15$3,
  4124. vue.createTextVNode("反馈 ")
  4125. ])) : vue.createCommentVNode("", true)
  4126. ])) : vue.createCommentVNode("", true),
  4127. $options.config.commentDisplayType === $options.CommentDisplayType.FloorInFloorNoCallUser && this.type !== "top" ? (vue.openBlock(), vue.createBlock(_component_BaseHtmlRender, {
  4128. key: 1,
  4129. class: "reply_content",
  4130. html: $props.modelValue.hideCallUserReplyContent
  4131. }, null, 8, ["html"])) : (vue.openBlock(), vue.createBlock(_component_BaseHtmlRender, {
  4132. key: 2,
  4133. class: "reply_content",
  4134. html: $props.modelValue.reply_content
  4135. }, null, 8, ["html"]))
  4136. ]),
  4137. vue.createElementVNode("div", _hoisted_16$3, [
  4138. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($props.modelValue.children, (item, index) => {
  4139. return vue.openBlock(), vue.createBlock(_component_Comment, {
  4140. modelValue: $props.modelValue.children[index],
  4141. "onUpdate:modelValue": ($event) => $props.modelValue.children[index] = $event,
  4142. key: index
  4143. }, null, 8, ["modelValue", "onUpdate:modelValue"]);
  4144. }), 128))
  4145. ])
  4146. ])
  4147. ]),
  4148. $data.cssStyle ? (vue.openBlock(), vue.createElementBlock("div", {
  4149. key: 1,
  4150. class: "more ago",
  4151. onClick: _cache[5] || (_cache[5] = ($event) => $data.expand = !$data.expand)
  4152. }, " 由于嵌套回复层级太深,自动将以上回复移至可见范围 ")) : vue.createCommentVNode("", true)
  4153. ], 4)) : vue.createCommentVNode("", true)
  4154. ], 10, _hoisted_1$d);
  4155. }
  4156. const Comment = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$5], ["__scopeId", "data-v-312e9541"]]);
  4157. const _sfc_main$c = {
  4158. name: "Toolbar",
  4159. components: { Icon, BaseLoading },
  4160. inject: [
  4161. "isLogin",
  4162. "post",
  4163. "pageType"
  4164. ],
  4165. data() {
  4166. return {
  4167. timer: null,
  4168. loading: false,
  4169. loading3: false
  4170. };
  4171. },
  4172. methods: {
  4173. checkIsLogin(emitName = "") {
  4174. if (!this.isLogin) {
  4175. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  4176. return false;
  4177. }
  4178. this.$emit(emitName);
  4179. return true;
  4180. },
  4181. async toggleFavorite() {
  4182. if (config.collectBrowserNotice) {
  4183. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "别忘记添加到书签哦" });
  4184. }
  4185. if (!this.checkIsLogin())
  4186. return;
  4187. let isFavorite = this.post.isFavorite;
  4188. let url = `${window.baseUrl}/${isFavorite ? "unfavorite" : "favorite"}/topic/${this.post.id}?once=${this.post.once}`;
  4189. this.loading = true;
  4190. let apiRes = await fetch(url);
  4191. this.loading = false;
  4192. if (apiRes.redirected) {
  4193. let htmlText = await apiRes.text();
  4194. if (htmlText.search(this.post.isFavorite ? "加入收藏" : "取消收藏")) {
  4195. eventBus.emit(CMD.MERGE, { collectCount: isFavorite ? this.post.collectCount - 1 : this.post.collectCount + 1 });
  4196. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: isFavorite ? "取消成功" : "收藏成功" });
  4197. eventBus.emit(CMD.REFRESH_ONCE, htmlText);
  4198. eventBus.emit(CMD.MERGE, { isFavorite: !isFavorite });
  4199. return;
  4200. }
  4201. }
  4202. eventBus.emit(CMD.REFRESH_ONCE);
  4203. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "操作失败" });
  4204. }
  4205. }
  4206. };
  4207. const _hoisted_1$c = { class: "toolbar" };
  4208. const _hoisted_2$9 = { class: "left" };
  4209. const _hoisted_3$8 = { class: "right" };
  4210. const _hoisted_4$7 = { key: 2 };
  4211. function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
  4212. const _component_BaseLoading = vue.resolveComponent("BaseLoading");
  4213. const _component_Icon = vue.resolveComponent("Icon");
  4214. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$c, [
  4215. vue.createElementVNode("div", _hoisted_2$9, [
  4216. vue.createElementVNode("div", null, vue.toDisplayString($options.post.createDate.substring(0, 16)), 1)
  4217. ]),
  4218. vue.createElementVNode("div", _hoisted_3$8, [
  4219. vue.createElementVNode("div", {
  4220. class: vue.normalizeClass(["tool", { disabled: $data.loading }]),
  4221. onClick: _cache[0] || (_cache[0] = (...args) => $options.toggleFavorite && $options.toggleFavorite(...args))
  4222. }, [
  4223. $data.loading ? (vue.openBlock(), vue.createBlock(_component_BaseLoading, {
  4224. key: 0,
  4225. size: "small"
  4226. })) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  4227. $options.post.isFavorite ? (vue.openBlock(), vue.createBlock(_component_Icon, {
  4228. key: 0,
  4229. color: "rgb(224,42,42)",
  4230. icon: "iconoir:star-solid"
  4231. })) : (vue.openBlock(), vue.createBlock(_component_Icon, {
  4232. key: 1,
  4233. icon: "iconoir:star"
  4234. }))
  4235. ], 64)),
  4236. $options.post.collectCount !== 0 ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4$7, vue.toDisplayString($options.post.collectCount), 1)) : vue.createCommentVNode("", true)
  4237. ], 2),
  4238. vue.createElementVNode("div", {
  4239. class: "tool",
  4240. onClick: _cache[1] || (_cache[1] = ($event) => $options.checkIsLogin("reply"))
  4241. }, [
  4242. vue.createVNode(_component_Icon, { icon: "mynaui:message" })
  4243. ])
  4244. ])
  4245. ]);
  4246. }
  4247. const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$4], ["__scopeId", "data-v-6234240d"]]);
  4248. const _withScopeId$8 = (n2) => (vue.pushScopeId("data-v-0869dab5"), n2 = n2(), vue.popScopeId(), n2);
  4249. const _hoisted_1$b = {
  4250. class: "comment",
  4251. ref: "comment"
  4252. };
  4253. const _hoisted_2$8 = ["href"];
  4254. const _hoisted_3$7 = ["src"];
  4255. const _hoisted_4$6 = { class: "texts" };
  4256. const _hoisted_5$5 = {
  4257. key: 0,
  4258. class: "point"
  4259. };
  4260. const _hoisted_6$5 = { class: "link-num" };
  4261. const _hoisted_7$4 = { class: "my-tag" };
  4262. const _hoisted_8$4 = /* @__PURE__ */ _withScopeId$8(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-tag" }, null, -1));
  4263. const _hoisted_9$4 = {
  4264. key: 2,
  4265. class: "ago"
  4266. };
  4267. const _hoisted_10$3 = {
  4268. key: 3,
  4269. class: "mod"
  4270. };
  4271. const _hoisted_11$3 = {
  4272. key: 4,
  4273. class: "owner"
  4274. };
  4275. const _hoisted_12$3 = ["href"];
  4276. const _hoisted_13$3 = {
  4277. key: 5,
  4278. class: "owner"
  4279. };
  4280. const _hoisted_14$2 = {
  4281. key: 6,
  4282. class: "mod"
  4283. };
  4284. const _hoisted_15$2 = {
  4285. key: 7,
  4286. class: "ago"
  4287. };
  4288. const _hoisted_16$2 = { class: "my-tag" };
  4289. const _hoisted_17$1 = /* @__PURE__ */ _withScopeId$8(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-tag" }, null, -1));
  4290. const _hoisted_18$1 = {
  4291. key: 9,
  4292. class: "point"
  4293. };
  4294. const _hoisted_19$1 = { class: "link-num" };
  4295. const _hoisted_20$1 = ["href"];
  4296. const _hoisted_21$1 = ["src"];
  4297. const _hoisted_22$1 = { class: "Author-right" };
  4298. const _hoisted_23$1 = { class: "floor" };
  4299. const _hoisted_24$1 = /* @__PURE__ */ _withScopeId$8(() => /* @__PURE__ */ vue.createElementVNode("span", null, "跳转", -1));
  4300. const _hoisted_25$1 = [
  4301. _hoisted_24$1
  4302. ];
  4303. const _sfc_main$b = {
  4304. __name: "SingleComment",
  4305. props: {
  4306. comment: {
  4307. reply_content: ""
  4308. },
  4309. isRight: {
  4310. type: Boolean,
  4311. default() {
  4312. return false;
  4313. }
  4314. }
  4315. },
  4316. setup(__props) {
  4317. const config2 = vue.inject("config");
  4318. const isLogin = vue.inject("isLogin");
  4319. const tags = vue.inject("tags");
  4320. const props = __props;
  4321. const myTags = vue.computed(() => {
  4322. return tags[props.comment.username] ?? [];
  4323. });
  4324. function jump() {
  4325. eventBus.emit(CMD.JUMP, props.comment.floor);
  4326. }
  4327. return (_ctx, _cache) => {
  4328. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$b, [
  4329. !__props.isRight ? (vue.openBlock(), vue.createElementBlock("a", {
  4330. key: 0,
  4331. class: "base-avatar",
  4332. href: `/member/${__props.comment.username}`
  4333. }, [
  4334. vue.createElementVNode("img", {
  4335. src: __props.comment.avatar,
  4336. alt: ""
  4337. }, null, 8, _hoisted_3$7)
  4338. ], 8, _hoisted_2$8)) : vue.createCommentVNode("", true),
  4339. vue.createElementVNode("div", {
  4340. class: vue.normalizeClass(["comment-body", { isRight: __props.isRight }])
  4341. }, [
  4342. vue.createElementVNode("div", _hoisted_4$6, [
  4343. __props.comment.thankCount && __props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$5, [
  4344. __props.comment.isThanked ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4345. key: 0,
  4346. color: "red",
  4347. icon: "icon-park-solid:like"
  4348. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4349. key: 1,
  4350. color: "rgb(224,42,42)",
  4351. icon: "icon-park-outline:like"
  4352. })),
  4353. vue.createElementVNode("div", _hoisted_6$5, vue.toDisplayString(__props.comment.thankCount), 1)
  4354. ])) : vue.createCommentVNode("", true),
  4355. vue.unref(isLogin) && vue.unref(config2).openTag && __props.isRight ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 1 }, vue.renderList(myTags.value, (i) => {
  4356. return vue.openBlock(), vue.createElementBlock("span", _hoisted_7$4, [
  4357. _hoisted_8$4,
  4358. vue.createElementVNode("span", null, vue.toDisplayString(i), 1)
  4359. ]);
  4360. }), 256)) : vue.createCommentVNode("", true),
  4361. __props.isRight ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_9$4, vue.toDisplayString(__props.comment.date), 1)) : vue.createCommentVNode("", true),
  4362. __props.comment.isMod && __props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10$3, "MOD")) : vue.createCommentVNode("", true),
  4363. __props.comment.isOp && __props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_11$3, "OP")) : vue.createCommentVNode("", true),
  4364. vue.createElementVNode("a", {
  4365. href: `/member/${__props.comment.username}`,
  4366. class: "username"
  4367. }, vue.toDisplayString(__props.comment.username), 9, _hoisted_12$3),
  4368. __props.comment.isOp && !__props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_13$3, "OP")) : vue.createCommentVNode("", true),
  4369. __props.comment.isMod && !__props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_14$2, "MOD")) : vue.createCommentVNode("", true),
  4370. !__props.isRight ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_15$2, vue.toDisplayString(__props.comment.date), 1)) : vue.createCommentVNode("", true),
  4371. vue.unref(isLogin) && vue.unref(config2).openTag && !__props.isRight ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 8 }, vue.renderList(myTags.value, (i) => {
  4372. return vue.openBlock(), vue.createElementBlock("span", _hoisted_16$2, [
  4373. _hoisted_17$1,
  4374. vue.createElementVNode("span", null, vue.toDisplayString(i), 1)
  4375. ]);
  4376. }), 256)) : vue.createCommentVNode("", true),
  4377. __props.comment.thankCount && !__props.isRight ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_18$1, [
  4378. __props.comment.isThanked ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4379. key: 0,
  4380. color: "red",
  4381. icon: "icon-park-solid:like"
  4382. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4383. key: 1,
  4384. color: "rgb(224,42,42)",
  4385. icon: "icon-park-outline:like"
  4386. })),
  4387. vue.createElementVNode("div", _hoisted_19$1, vue.toDisplayString(__props.comment.thankCount), 1)
  4388. ])) : vue.createCommentVNode("", true)
  4389. ]),
  4390. vue.createVNode(BaseHtmlRender, {
  4391. class: "reply_content",
  4392. html: __props.comment.reply_content
  4393. }, null, 8, ["html"])
  4394. ], 2),
  4395. __props.isRight ? (vue.openBlock(), vue.createElementBlock("a", {
  4396. key: 1,
  4397. class: "base-avatar",
  4398. href: `/member/${__props.comment.username}`
  4399. }, [
  4400. vue.createElementVNode("img", {
  4401. src: __props.comment.avatar,
  4402. alt: ""
  4403. }, null, 8, _hoisted_21$1)
  4404. ], 8, _hoisted_20$1)) : vue.createCommentVNode("", true),
  4405. vue.createElementVNode("div", _hoisted_22$1, [
  4406. vue.createElementVNode("div", _hoisted_23$1, vue.toDisplayString(__props.comment.floor) + "楼", 1),
  4407. vue.createElementVNode("div", {
  4408. class: "tool jump",
  4409. onClick: jump
  4410. }, _hoisted_25$1)
  4411. ])
  4412. ], 512);
  4413. };
  4414. }
  4415. };
  4416. const SingleComment = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-0869dab5"]]);
  4417. function debounce(fn, delay, scope) {
  4418. let timer = null;
  4419. return function() {
  4420. let context = scope || this, args = arguments;
  4421. clearTimeout(timer);
  4422. timer = setTimeout(function() {
  4423. fn.apply(context, args);
  4424. timer = null;
  4425. }, delay);
  4426. };
  4427. }
  4428. async function copy(text) {
  4429. if (navigator.clipboard) {
  4430. await navigator.clipboard.writeText(text);
  4431. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "复制成功" });
  4432. return true;
  4433. } else {
  4434. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "复制失败!浏览器不支持!" });
  4435. }
  4436. }
  4437. const _sfc_main$a = {
  4438. name: "FromBottomDialog",
  4439. props: {
  4440. modelValue: {
  4441. type: Boolean,
  4442. default: false
  4443. },
  4444. mode: {
  4445. type: String,
  4446. // default: 'dark'
  4447. default: "light"
  4448. // default: 'white'
  4449. },
  4450. maskMode: {
  4451. type: String,
  4452. default: "dark"
  4453. },
  4454. height: {
  4455. type: String,
  4456. default: "70vh"
  4457. },
  4458. showHengGang: {
  4459. type: Boolean,
  4460. default: true
  4461. },
  4462. pageId: {
  4463. type: String,
  4464. default: null,
  4465. required: true
  4466. },
  4467. borderRadius: {
  4468. type: String,
  4469. default: "1rem 1rem 0 0"
  4470. },
  4471. tag: {
  4472. type: String,
  4473. default: ""
  4474. }
  4475. },
  4476. watch: {
  4477. modelValue(newVal) {
  4478. let page = document.getElementById(this.pageId);
  4479. if (newVal) {
  4480. page.style.overflow = "hidden";
  4481. this.scroll = page.scrollTop;
  4482. let mask = $(`<div class="mask fade-in ${this.maskMode}"></div>`);
  4483. mask.on("click", (e2) => {
  4484. this.hide(false);
  4485. });
  4486. page.appendChild(mask[0]);
  4487. } else {
  4488. page.style.overflow = "unset";
  4489. let mask = $(".mask");
  4490. mask.removeClass("fade-in");
  4491. mask.addClass("fade-out");
  4492. setTimeout(() => {
  4493. mask.remove();
  4494. }, 250);
  4495. }
  4496. }
  4497. },
  4498. data() {
  4499. return {
  4500. scroll: 0,
  4501. startLocationY: 0,
  4502. moveYDistance: 0,
  4503. startTime: 0,
  4504. pagePosition: null
  4505. };
  4506. },
  4507. computed: {},
  4508. created() {
  4509. },
  4510. methods: {
  4511. beforeEnter(el) {
  4512. el.style["transition-duration"] = `250ms`;
  4513. el.style["transform"] = `translate3d(0,${this.height},0)`;
  4514. },
  4515. enter(el, done) {
  4516. setTimeout(() => {
  4517. el.style["transform"] = `translate3d(0,0,0)`;
  4518. }, 0);
  4519. setTimeout(() => {
  4520. el.style["transform"] = `none`;
  4521. done();
  4522. }, 250);
  4523. },
  4524. afterEnter() {
  4525. },
  4526. beforeLeave(el) {
  4527. el.style["transition-duration"] = `250ms`;
  4528. el.style["transform"] = `translate3d(0,0,0)`;
  4529. },
  4530. leave(el, done) {
  4531. let maxHeight = $(".FromBottomDialog").css("max-height");
  4532. el.style["transform"] = `translate3d(0,${maxHeight},0)`;
  4533. setTimeout(done, 250);
  4534. },
  4535. afterLeave() {
  4536. },
  4537. hide(val = false) {
  4538. this.$emit("update:modelValue", val);
  4539. this.$emit("cancel");
  4540. },
  4541. start(e2) {
  4542. if (this.$refs.dialog.scrollTop !== 0)
  4543. return;
  4544. this.startLocationY = e2.touches[0].pageY;
  4545. this.startTime = Date.now();
  4546. this.$refs.dialog.style["transition-duration"] = `0ms`;
  4547. },
  4548. move(e2) {
  4549. if (this.$refs.dialog.scrollTop !== 0)
  4550. return;
  4551. this.moveYDistance = e2.touches[0].pageY - this.startLocationY;
  4552. if (this.moveYDistance > 0) {
  4553. this.$refs.dialog.style["transform"] = `translate3d(0,${this.moveYDistance}px,0)`;
  4554. }
  4555. },
  4556. end(e2) {
  4557. if (Date.now() - this.startTime < 150 && Math.abs(this.moveYDistance) < 30) {
  4558. return;
  4559. }
  4560. if (this.$refs.dialog.scrollTop !== 0)
  4561. return;
  4562. let clientHeight = this.$refs.dialog.clientHeight;
  4563. this.$refs.dialog.style["transition-duration"] = `250ms`;
  4564. if (Math.abs(this.moveYDistance) > clientHeight / 2) {
  4565. this.$refs.dialog.style["transform"] = `translate3d(0,${clientHeight}px,0)`;
  4566. setTimeout(this.hide, 250);
  4567. } else {
  4568. this.$refs.dialog.style["transform"] = `translate3d(0,0,0)`;
  4569. setTimeout(() => {
  4570. if (this.$refs.dialog) {
  4571. this.$refs.dialog.style["transform"] = `none`;
  4572. }
  4573. }, 250);
  4574. }
  4575. this.moveYDistance = 0;
  4576. }
  4577. }
  4578. };
  4579. const __injectCSSVars__ = () => {
  4580. vue.useCssVars((_ctx) => ({
  4581. "0013fa15": _ctx.borderRadius
  4582. }));
  4583. };
  4584. const __setup__ = _sfc_main$a.setup;
  4585. _sfc_main$a.setup = __setup__ ? (props, ctx) => {
  4586. __injectCSSVars__();
  4587. return __setup__(props, ctx);
  4588. } : __injectCSSVars__;
  4589. const _withScopeId$7 = (n2) => (vue.pushScopeId("data-v-3a54f208"), n2 = n2(), vue.popScopeId(), n2);
  4590. const _hoisted_1$a = /* @__PURE__ */ _withScopeId$7(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "gang-content" }, null, -1));
  4591. const _hoisted_2$7 = [
  4592. _hoisted_1$a
  4593. ];
  4594. const _hoisted_3$6 = { class: "dialog-wrapper" };
  4595. function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
  4596. return vue.openBlock(), vue.createBlock(vue.Transition, {
  4597. onBeforeEnter: $options.beforeEnter,
  4598. onEnter: $options.enter,
  4599. onAfterEnter: $options.afterEnter,
  4600. onBeforeLeave: $options.beforeLeave,
  4601. onLeave: $options.leave,
  4602. onAfterLeave: $options.afterLeave,
  4603. css: false
  4604. }, {
  4605. default: vue.withCtx(() => [
  4606. $props.modelValue ? (vue.openBlock(), vue.createElementBlock("div", {
  4607. key: 0,
  4608. ref: "dialog",
  4609. class: vue.normalizeClass(["FromBottomDialog", [$props.mode, $props.showHengGang ? "" : "no-heng-gang"]]),
  4610. style: vue.normalizeStyle({ "max-height": $props.height }),
  4611. onTouchstart: _cache[0] || (_cache[0] = (...args) => $options.start && $options.start(...args)),
  4612. onTouchmove: _cache[1] || (_cache[1] = (...args) => $options.move && $options.move(...args)),
  4613. onTouchend: _cache[2] || (_cache[2] = (...args) => $options.end && $options.end(...args))
  4614. }, [
  4615. vue.renderSlot(_ctx.$slots, "header", {}, void 0, true),
  4616. $props.showHengGang ? (vue.openBlock(), vue.createElementBlock("div", {
  4617. key: 0,
  4618. class: vue.normalizeClass(["heng-gang", $props.mode])
  4619. }, _hoisted_2$7, 2)) : vue.createCommentVNode("", true),
  4620. vue.createElementVNode("div", _hoisted_3$6, [
  4621. vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
  4622. ])
  4623. ], 38)) : vue.createCommentVNode("", true)
  4624. ]),
  4625. _: 3
  4626. }, 8, ["onBeforeEnter", "onEnter", "onAfterEnter", "onBeforeLeave", "onLeave", "onAfterLeave"]);
  4627. }
  4628. const FromBottomDialog = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$3], ["__scopeId", "data-v-3a54f208"]]);
  4629. const _withScopeId$6 = (n2) => (vue.pushScopeId("data-v-ce52828d"), n2 = n2(), vue.popScopeId(), n2);
  4630. const _hoisted_1$9 = { class: "wrapper" };
  4631. const _hoisted_2$6 = { class: "options" };
  4632. const _hoisted_3$5 = { class: "icon-wrap" };
  4633. const _hoisted_4$5 = /* @__PURE__ */ _withScopeId$6(() => /* @__PURE__ */ vue.createElementVNode("span", null, "分享", -1));
  4634. const _hoisted_5$4 = { class: "icon-wrap" };
  4635. const _hoisted_6$4 = { class: "icon-wrap" };
  4636. const _hoisted_7$3 = /* @__PURE__ */ _withScopeId$6(() => /* @__PURE__ */ vue.createElementVNode("span", null, "回复", -1));
  4637. const _hoisted_8$3 = { class: "icon-wrap" };
  4638. const _hoisted_9$3 = { class: "icon-wrap" };
  4639. const _hoisted_10$2 = { class: "icon-wrap" };
  4640. const _hoisted_11$2 = { class: "icon-wrap" };
  4641. const _hoisted_12$2 = /* @__PURE__ */ _withScopeId$6(() => /* @__PURE__ */ vue.createElementVNode("span", null, "复制链接", -1));
  4642. const _hoisted_13$2 = { class: "icon-wrap" };
  4643. const _hoisted_14$1 = /* @__PURE__ */ _withScopeId$6(() => /* @__PURE__ */ vue.createElementVNode("span", null, "复制内容", -1));
  4644. const _hoisted_15$1 = { class: "icon-wrap" };
  4645. const _hoisted_16$1 = /* @__PURE__ */ _withScopeId$6(() => /* @__PURE__ */ vue.createElementVNode("span", null, "刷新", -1));
  4646. const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
  4647. __name: "PostOptions",
  4648. props: {
  4649. modelValue: { type: Boolean },
  4650. post: {}
  4651. },
  4652. emits: ["close", "reply", "refresh", "merge", "update:modelValue"],
  4653. setup(__props, { emit: __emit }) {
  4654. let state = vue.reactive({
  4655. timer: null,
  4656. loading: false,
  4657. loading1: false,
  4658. loading2: false,
  4659. loading3: false,
  4660. loading4: false
  4661. });
  4662. const props = __props;
  4663. const emit = __emit;
  4664. const isLogin = vue.inject("isLogin");
  4665. const pageType = vue.inject("pageType");
  4666. const config2 = vue.inject("config");
  4667. function close() {
  4668. emit("close");
  4669. emit("update:modelValue", false);
  4670. }
  4671. function checkIsLogin() {
  4672. if (!isLogin.value) {
  4673. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  4674. return false;
  4675. }
  4676. return true;
  4677. }
  4678. async function copyLink() {
  4679. let text = props.post.url;
  4680. if (await copy(text)) {
  4681. close();
  4682. }
  4683. }
  4684. async function copyContent() {
  4685. let text = props.post.headerTemplate;
  4686. text = $(`<div>${text}</div>`).text();
  4687. if (await copy(text)) {
  4688. close();
  4689. }
  4690. }
  4691. function share() {
  4692. var _a;
  4693. let username = ((_a = window.user) == null ? void 0 : _a.username) ?? "";
  4694. let url = `https://twitter.com/intent/tweet?url=${location.origin}/t/${props.post.id}?r=${username}&related=v2ex&text=${props.post.title}`;
  4695. window.open(url, "_blank");
  4696. close();
  4697. }
  4698. function reply() {
  4699. if (!checkIsLogin())
  4700. return;
  4701. emit("reply");
  4702. close();
  4703. }
  4704. async function toggleIgnore() {
  4705. if (!checkIsLogin())
  4706. return;
  4707. if (state.loading2)
  4708. return;
  4709. let isIgnore = props.post.isIgnore;
  4710. let url = `${location.origin}/${isIgnore ? "unignore" : "ignore"}/topic/${props.post.id}?once=${props.post.once}`;
  4711. state.loading2 = true;
  4712. let apiRes = await fetch(url);
  4713. state.loading2 = false;
  4714. if (apiRes.redirected) {
  4715. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: isIgnore ? "取消成功" : "忽略成功" });
  4716. } else {
  4717. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "忽略失败" });
  4718. }
  4719. if (isIgnore) {
  4720. eventBus.emit(CMD.MERGE, { isIgnore: !isIgnore });
  4721. } else {
  4722. if (pageType.value === PageType.Post) {
  4723. location.href = location.origin;
  4724. } else {
  4725. eventBus.emit(CMD.IGNORE);
  4726. }
  4727. }
  4728. eventBus.emit(CMD.REFRESH_ONCE);
  4729. close();
  4730. }
  4731. async function toggleFavorite() {
  4732. if (config2.value.collectBrowserNotice) {
  4733. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "别忘记添加到书签哦" });
  4734. }
  4735. if (!checkIsLogin())
  4736. return;
  4737. if (state.loading)
  4738. return;
  4739. let isFavorite = props.post.isFavorite;
  4740. let url = `${location.origin}/${isFavorite ? "unfavorite" : "favorite"}/topic/${props.post.id}?once=${props.post.once}`;
  4741. state.loading = true;
  4742. let apiRes = await fetch(url);
  4743. state.loading = false;
  4744. if (apiRes.redirected) {
  4745. let htmlText = await apiRes.text();
  4746. if (htmlText.search(isFavorite ? "加入收藏" : "取消收藏")) {
  4747. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: isFavorite ? "取消成功" : "收藏成功" });
  4748. eventBus.emit(CMD.MERGE, { collectCount: isFavorite ? props.post.collectCount - 1 : props.post.collectCount + 1 });
  4749. eventBus.emit(CMD.REFRESH_ONCE, htmlText);
  4750. eventBus.emit(CMD.MERGE, { isFavorite: !isFavorite });
  4751. return close();
  4752. }
  4753. }
  4754. eventBus.emit(CMD.REFRESH_ONCE);
  4755. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "操作失败,请重试" });
  4756. }
  4757. async function report() {
  4758. if (!checkIsLogin())
  4759. return;
  4760. if (!isLogin.value)
  4761. return;
  4762. if (state.loading1)
  4763. return;
  4764. let isReport = props.post.isReport;
  4765. if (isReport) {
  4766. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "你已对本主题进行了报告" });
  4767. return;
  4768. }
  4769. let url = `${location.origin}/report/topic/${props.post.id}?once=${props.post.once}`;
  4770. state.loading1 = true;
  4771. let apiRes = await fetch(url);
  4772. state.loading1 = false;
  4773. if (apiRes.redirected) {
  4774. let htmlText = await apiRes.text();
  4775. if (htmlText.search("你已对本主题进行了报告")) {
  4776. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "你已对本主题进行了报告" });
  4777. eventBus.emit(CMD.REFRESH_ONCE, htmlText);
  4778. eventBus.emit(CMD.MERGE, { isReport: !isReport });
  4779. return close();
  4780. }
  4781. }
  4782. eventBus.emit(CMD.REFRESH_ONCE);
  4783. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "操作失败,请重试" });
  4784. }
  4785. async function thank() {
  4786. if (!isLogin.value) {
  4787. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  4788. }
  4789. if (props.post.username === window.user.username) {
  4790. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "不能感谢自己" });
  4791. }
  4792. let isThanked = props.post.isThanked;
  4793. if (isThanked) {
  4794. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "已经感谢过了" });
  4795. }
  4796. if (state.loading4)
  4797. return;
  4798. eventBus.emit(CMD.MERGE, { isThanked: !isThanked });
  4799. let url = `${location.origin}/thank/reply/${props.post.id}?once=${props.post.once}`;
  4800. state.loading4 = true;
  4801. await fetch(url);
  4802. state.loading4 = false;
  4803. $.post(url).then((res) => {
  4804. if (!res.success) {
  4805. eventBus.emit(CMD.MERGE, { isThanked: !isThanked });
  4806. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: res.message });
  4807. }
  4808. eventBus.emit(CMD.REFRESH_ONCE, res.once);
  4809. }, (err) => {
  4810. state.loading4 = false;
  4811. eventBus.emit(CMD.MERGE, { isThanked: !isThanked });
  4812. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "感谢失败" });
  4813. eventBus.emit(CMD.REFRESH_ONCE);
  4814. });
  4815. close();
  4816. }
  4817. return (_ctx, _cache) => {
  4818. return vue.openBlock(), vue.createBlock(FromBottomDialog, {
  4819. "page-id": "post-detail",
  4820. height: "40rem",
  4821. "model-value": _ctx.modelValue,
  4822. onCancel: _cache[1] || (_cache[1] = ($event) => emit("update:modelValue", false))
  4823. }, {
  4824. default: vue.withCtx(() => [
  4825. vue.createElementVNode("div", _hoisted_1$9, [
  4826. vue.createElementVNode("div", _hoisted_2$6, [
  4827. vue.createElementVNode("div", {
  4828. class: "item",
  4829. onClick: share
  4830. }, [
  4831. vue.createElementVNode("div", _hoisted_3$5, [
  4832. vue.createVNode(vue.unref(Icon), {
  4833. color: "rgb(57,174,85)",
  4834. icon: "ph:share-fat-fill"
  4835. })
  4836. ]),
  4837. _hoisted_4$5
  4838. ]),
  4839. vue.createElementVNode("div", {
  4840. class: "item",
  4841. onClick: toggleIgnore
  4842. }, [
  4843. vue.createElementVNode("div", _hoisted_5$4, [
  4844. vue.unref(state).loading2 ? (vue.openBlock(), vue.createBlock(BaseLoading, { key: 0 })) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  4845. _ctx.post.isIgnore ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4846. key: 0,
  4847. color: "rgb(224,42,42)",
  4848. icon: "mdi:eye-off-outline"
  4849. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4850. key: 1,
  4851. color: "rgb(57,174,85)",
  4852. icon: "mdi:eye-outline"
  4853. }))
  4854. ], 64))
  4855. ]),
  4856. vue.createElementVNode("span", null, vue.toDisplayString(_ctx.post.isIgnore ? "取消" : "") + "忽略", 1)
  4857. ]),
  4858. vue.createElementVNode("div", {
  4859. class: "item",
  4860. onClick: reply
  4861. }, [
  4862. vue.createElementVNode("div", _hoisted_6$4, [
  4863. vue.createVNode(vue.unref(Icon), {
  4864. color: "rgb(57,174,85)",
  4865. icon: "mynaui:message"
  4866. })
  4867. ]),
  4868. _hoisted_7$3
  4869. ]),
  4870. vue.createElementVNode("div", {
  4871. class: "item",
  4872. onClick: thank
  4873. }, [
  4874. vue.createElementVNode("div", _hoisted_8$3, [
  4875. _ctx.post.isThanked ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4876. key: 0,
  4877. icon: "flat-color-icons:like"
  4878. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4879. key: 1,
  4880. color: "rgb(57,174,85)",
  4881. icon: "icon-park-outline:like"
  4882. }))
  4883. ]),
  4884. vue.createElementVNode("span", null, vue.toDisplayString(_ctx.post.isThanked ? "已" : "") + "感谢", 1)
  4885. ]),
  4886. vue.createElementVNode("div", {
  4887. class: "item",
  4888. onClick: toggleFavorite
  4889. }, [
  4890. vue.createElementVNode("div", _hoisted_9$3, [
  4891. vue.unref(state).loading ? (vue.openBlock(), vue.createBlock(BaseLoading, { key: 0 })) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  4892. _ctx.post.isFavorite ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4893. key: 0,
  4894. color: "rgb(224,42,42)",
  4895. icon: "iconoir:star-solid"
  4896. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4897. key: 1,
  4898. color: "rgb(57,174,85)",
  4899. icon: "iconoir:star"
  4900. }))
  4901. ], 64))
  4902. ]),
  4903. vue.createElementVNode("span", null, vue.toDisplayString(_ctx.post.isFavorite ? "取消" : "") + "收藏", 1)
  4904. ]),
  4905. vue.createElementVNode("div", {
  4906. class: vue.normalizeClass(["item", [_ctx.post.isReport && "disabled"]]),
  4907. onClick: report
  4908. }, [
  4909. vue.createElementVNode("div", _hoisted_10$2, [
  4910. vue.unref(state).loading1 ? (vue.openBlock(), vue.createBlock(BaseLoading, { key: 0 })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  4911. key: 1,
  4912. class: "black",
  4913. icon: "solar:danger-triangle-outline"
  4914. }))
  4915. ]),
  4916. vue.createElementVNode("span", null, vue.toDisplayString(_ctx.post.isReport ? "已报告" : "报告问题"), 1)
  4917. ], 2),
  4918. vue.createElementVNode("div", {
  4919. class: "item",
  4920. onClick: copyLink
  4921. }, [
  4922. vue.createElementVNode("div", _hoisted_11$2, [
  4923. vue.createVNode(vue.unref(Icon), {
  4924. class: "black",
  4925. icon: "solar:link-broken"
  4926. })
  4927. ]),
  4928. _hoisted_12$2
  4929. ]),
  4930. vue.createElementVNode("div", {
  4931. class: "item",
  4932. onClick: copyContent
  4933. }, [
  4934. vue.createElementVNode("div", _hoisted_13$2, [
  4935. vue.createVNode(vue.unref(Icon), {
  4936. class: "black",
  4937. icon: "octicon:copy-24"
  4938. })
  4939. ]),
  4940. _hoisted_14$1
  4941. ]),
  4942. vue.createElementVNode("div", {
  4943. class: "item",
  4944. onClick: _cache[0] || (_cache[0] = ($event) => (emit("refresh"), close()))
  4945. }, [
  4946. vue.createElementVNode("div", _hoisted_15$1, [
  4947. vue.createVNode(vue.unref(Icon), {
  4948. class: "black",
  4949. icon: "ion:refresh"
  4950. })
  4951. ]),
  4952. _hoisted_16$1
  4953. ])
  4954. ]),
  4955. vue.createVNode(FontSizeType),
  4956. vue.createElementVNode("div", {
  4957. class: "cancel",
  4958. onClick: close
  4959. }, "取消")
  4960. ])
  4961. ]),
  4962. _: 1
  4963. }, 8, ["model-value"]);
  4964. };
  4965. }
  4966. });
  4967. const PostOptions = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-ce52828d"]]);
  4968. const _withScopeId$5 = (n2) => (vue.pushScopeId("data-v-8ef13a81"), n2 = n2(), vue.popScopeId(), n2);
  4969. const _hoisted_1$8 = { class: "wrapper" };
  4970. const _hoisted_2$5 = { class: "options" };
  4971. const _hoisted_3$4 = { class: "icon-wrap" };
  4972. const _hoisted_4$4 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ vue.createElementVNode("span", null, "忽略", -1));
  4973. const _hoisted_5$3 = { class: "icon-wrap" };
  4974. const _hoisted_6$3 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ vue.createElementVNode("span", null, "复制", -1));
  4975. const _hoisted_7$2 = { class: "icon-wrap" };
  4976. const _hoisted_8$2 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ vue.createElementVNode("span", null, "上下文", -1));
  4977. const _hoisted_9$2 = { class: "icon-wrap" };
  4978. const _hoisted_10$1 = { class: "icon-wrap" };
  4979. const _hoisted_11$1 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ vue.createElementVNode("span", null, "回复", -1));
  4980. const _hoisted_12$1 = { class: "icon-wrap" };
  4981. const _hoisted_13$1 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ vue.createElementVNode("span", null, "跳转", -1));
  4982. const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
  4983. __name: "CommentOptions",
  4984. props: {
  4985. modelValue: { type: Boolean },
  4986. comment: {},
  4987. post: {}
  4988. },
  4989. emits: ["close", "reply", "merge", "update:modelValue"],
  4990. setup(__props, { emit: __emit }) {
  4991. const props = __props;
  4992. const emit = __emit;
  4993. const config2 = vue.inject("config");
  4994. const isLogin = vue.inject("isLogin");
  4995. function close() {
  4996. emit("close");
  4997. emit("update:modelValue", false);
  4998. }
  4999. function checkIsLogin() {
  5000. if (!isLogin.value) {
  5001. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请先登录!" });
  5002. return false;
  5003. }
  5004. return true;
  5005. }
  5006. async function handleCopy() {
  5007. let text = props.comment.reply_content;
  5008. if (config2.value.commentDisplayType === CommentDisplayType.FloorInFloorNoCallUser) {
  5009. text = props.comment.hideCallUserReplyContent;
  5010. }
  5011. text = $(`<div>${text}</div>`).text();
  5012. if (await copy(text)) {
  5013. close();
  5014. }
  5015. }
  5016. async function hide() {
  5017. if (!checkIsLogin())
  5018. return;
  5019. let url = `${window.baseUrl}/ignore/reply/${props.comment.id}?once=${props.post.once}`;
  5020. eventBus.emit(CMD.REMOVE, props.comment.floor);
  5021. close();
  5022. $.post(url).then((res) => {
  5023. eventBus.emit(CMD.REFRESH_ONCE);
  5024. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "隐藏成功" });
  5025. }, (err) => {
  5026. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "隐藏成功,仅本次有效(接口调用失败!)" });
  5027. });
  5028. }
  5029. function jump() {
  5030. eventBus.emit(CMD.JUMP, props.comment.floor);
  5031. close();
  5032. }
  5033. function showRelationReply() {
  5034. if (!props.comment.replyUsers.length) {
  5035. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "该回复无上下文" });
  5036. return;
  5037. }
  5038. eventBus.emit(CMD.RELATION_REPLY, {
  5039. left: props.comment.replyUsers,
  5040. right: props.comment.username,
  5041. rightFloor: props.comment.floor
  5042. });
  5043. close();
  5044. }
  5045. function recallThank() {
  5046. eventBus.emit(CMD.CHANGE_COMMENT_THANK, { id: props.comment.id, type: "recall" });
  5047. }
  5048. function thank() {
  5049. if (!checkIsLogin())
  5050. return;
  5051. if (props.comment.username === window.user.username) {
  5052. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "不能感谢自己" });
  5053. }
  5054. if (props.comment.isThanked) {
  5055. return eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "已经感谢过了" });
  5056. }
  5057. eventBus.emit(CMD.CHANGE_COMMENT_THANK, { id: props.comment.id, type: "add" });
  5058. let url = `${window.baseUrl}/thank/reply/${props.comment.id}?once=${props.post.once}`;
  5059. $.post(url).then((res) => {
  5060. if (!res.success) {
  5061. recallThank();
  5062. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: res.message });
  5063. }
  5064. eventBus.emit(CMD.REFRESH_ONCE, res.once);
  5065. }, (err) => {
  5066. recallThank();
  5067. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "感谢失败" });
  5068. eventBus.emit(CMD.REFRESH_ONCE);
  5069. });
  5070. close();
  5071. }
  5072. return (_ctx, _cache) => {
  5073. return vue.openBlock(), vue.createBlock(FromBottomDialog, {
  5074. "page-id": "post-detail",
  5075. height: "40rem",
  5076. "model-value": _ctx.modelValue,
  5077. onCancel: _cache[1] || (_cache[1] = ($event) => emit("update:modelValue", false))
  5078. }, {
  5079. default: vue.withCtx(() => [
  5080. vue.createElementVNode("div", _hoisted_1$8, [
  5081. vue.createElementVNode("div", _hoisted_2$5, [
  5082. vue.createElementVNode("div", {
  5083. class: "item",
  5084. onClick: hide
  5085. }, [
  5086. vue.createElementVNode("div", _hoisted_3$4, [
  5087. vue.createVNode(vue.unref(Icon), { icon: "solar:forbidden-circle-outline" })
  5088. ]),
  5089. _hoisted_4$4
  5090. ]),
  5091. vue.createElementVNode("div", {
  5092. class: "item",
  5093. onClick: handleCopy
  5094. }, [
  5095. vue.createElementVNode("div", _hoisted_5$3, [
  5096. vue.createVNode(vue.unref(Icon), { icon: "octicon:copy-24" })
  5097. ]),
  5098. _hoisted_6$3
  5099. ]),
  5100. vue.createElementVNode("div", {
  5101. class: vue.normalizeClass(["item", [!_ctx.comment.replyUsers.length && "disabled"]]),
  5102. onClick: showRelationReply
  5103. }, [
  5104. vue.createElementVNode("div", _hoisted_7$2, [
  5105. vue.createVNode(vue.unref(Icon), { icon: "iconoir:page-search" })
  5106. ]),
  5107. _hoisted_8$2
  5108. ], 2),
  5109. vue.createElementVNode("div", {
  5110. class: vue.normalizeClass(["item", [_ctx.comment.isThanked && "full"]]),
  5111. onClick: thank
  5112. }, [
  5113. vue.createElementVNode("div", _hoisted_9$2, [
  5114. _ctx.comment.isThanked ? (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  5115. key: 0,
  5116. icon: "icon-park-solid:like"
  5117. })) : (vue.openBlock(), vue.createBlock(vue.unref(Icon), {
  5118. key: 1,
  5119. icon: "icon-park-outline:like"
  5120. }))
  5121. ]),
  5122. vue.createElementVNode("span", null, vue.toDisplayString(_ctx.comment.isThanked ? "已" : "") + "感谢", 1)
  5123. ], 2),
  5124. vue.createElementVNode("div", {
  5125. class: "item",
  5126. onClick: _cache[0] || (_cache[0] = ($event) => emit("reply"))
  5127. }, [
  5128. vue.createElementVNode("div", _hoisted_10$1, [
  5129. vue.createVNode(vue.unref(Icon), { icon: "mynaui:message" })
  5130. ]),
  5131. _hoisted_11$1
  5132. ]),
  5133. _ctx.comment.top ? (vue.openBlock(), vue.createElementBlock("div", {
  5134. key: 0,
  5135. class: "item",
  5136. onClick: jump
  5137. }, [
  5138. vue.createElementVNode("div", _hoisted_12$1, [
  5139. vue.createVNode(vue.unref(Icon), { icon: "icon-park-outline:to-bottom" })
  5140. ]),
  5141. _hoisted_13$1
  5142. ])) : vue.createCommentVNode("", true)
  5143. ]),
  5144. vue.createElementVNode("div", {
  5145. class: "cancel",
  5146. onClick: close
  5147. }, "取消")
  5148. ])
  5149. ]),
  5150. _: 1
  5151. }, 8, ["model-value"]);
  5152. };
  5153. }
  5154. });
  5155. const CommentOptions = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-8ef13a81"]]);
  5156. const _hoisted_1$7 = { class: "comments" };
  5157. const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
  5158. __name: "RelationReply",
  5159. props: {
  5160. modelValue: { type: Boolean },
  5161. relationReply: {},
  5162. targetUser: {},
  5163. post: {}
  5164. },
  5165. emits: ["close", "reply", "merge", "update:modelValue"],
  5166. setup(__props, { emit: __emit }) {
  5167. const emit = __emit;
  5168. vue.inject("config");
  5169. vue.inject("isLogin");
  5170. return (_ctx, _cache) => {
  5171. return vue.openBlock(), vue.createBlock(FromBottomDialog, {
  5172. "page-id": "post-detail",
  5173. height: "70vh",
  5174. "model-value": _ctx.modelValue,
  5175. onCancel: _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", false))
  5176. }, {
  5177. default: vue.withCtx(() => [
  5178. vue.createElementVNode("div", _hoisted_1$7, [
  5179. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.relationReply, (item, index) => {
  5180. return vue.openBlock(), vue.createBlock(SingleComment, {
  5181. "is-right": item.username === _ctx.targetUser.right,
  5182. key: item.floor,
  5183. comment: item
  5184. }, null, 8, ["is-right", "comment"]);
  5185. }), 128))
  5186. ])
  5187. ]),
  5188. _: 1
  5189. }, 8, ["model-value"]);
  5190. };
  5191. }
  5192. });
  5193. const _sfc_main$6 = {
  5194. name: "detail",
  5195. emits: ["saveReadList", "refresh"],
  5196. components: {
  5197. BackIcon: _sfc_main$p,
  5198. BaseSelect,
  5199. RelationReply: _sfc_main$7,
  5200. CommentOptions,
  5201. FromBottomDialog,
  5202. PostOptions,
  5203. MoreIcon,
  5204. BaseButton,
  5205. SingleComment,
  5206. Comment,
  5207. PostEditor,
  5208. Point,
  5209. Toolbar,
  5210. BaseHtmlRender,
  5211. Tooltip,
  5212. BaseLoading,
  5213. Icon
  5214. },
  5215. inject: ["allReplyUsers", "user", "post", "tags", "isLogin", "config", "pageType", "isNight"],
  5216. props: {
  5217. modelValue: {
  5218. type: Boolean,
  5219. default() {
  5220. return false;
  5221. }
  5222. },
  5223. loading: {
  5224. type: Boolean,
  5225. default() {
  5226. return false;
  5227. }
  5228. },
  5229. refreshLoading: {
  5230. type: Boolean,
  5231. default() {
  5232. return false;
  5233. }
  5234. },
  5235. displayType: CommentDisplayType.FloorInFloorNoCallUser
  5236. },
  5237. data() {
  5238. return {
  5239. isSticky: false,
  5240. showPostOptions: false,
  5241. showCommentOptions: false,
  5242. selectCallIndex: 0,
  5243. showCallList: false,
  5244. showRelationReply: false,
  5245. replyText: "",
  5246. callStyle: {
  5247. top: 0,
  5248. left: 0
  5249. },
  5250. targetUser: {
  5251. left: [],
  5252. right: "",
  5253. rightFloor: -1
  5254. },
  5255. debounceScroll: () => {
  5256. },
  5257. read: {
  5258. floor: 0,
  5259. total: 0
  5260. },
  5261. currentFloor: "",
  5262. showOpTag: false,
  5263. currentComment: null
  5264. };
  5265. },
  5266. computed: {
  5267. eventBus() {
  5268. return eventBus;
  5269. },
  5270. CMD() {
  5271. return CMD;
  5272. },
  5273. replyUser() {
  5274. if (this.currentComment)
  5275. return this.currentComment.username;
  5276. return null;
  5277. },
  5278. replyFloor() {
  5279. if (this.currentComment)
  5280. return this.currentComment.floor;
  5281. return null;
  5282. },
  5283. isMy() {
  5284. return this.post.member.username === window.user.username;
  5285. },
  5286. myTags() {
  5287. return this.tags[this.post.member.username] ?? [];
  5288. },
  5289. CommentDisplayType() {
  5290. return CommentDisplayType;
  5291. },
  5292. isPost() {
  5293. return this.pageType === PageType.Post;
  5294. },
  5295. filterCallList() {
  5296. if (this.showCallList) {
  5297. let list = ["管理员", "所有人"].concat(this.allReplyUsers);
  5298. if (this.replyText)
  5299. return list.filter((i) => i.search(this.replyText) > -1);
  5300. return list;
  5301. }
  5302. return [];
  5303. },
  5304. topReply() {
  5305. return this.post.replyList.filter((v) => v.thankCount >= this.config.topReplyLoveMinCount).sort((a, b) => b.thankCount - a.thankCount).slice(0, this.config.topReplyCount);
  5306. },
  5307. replyList() {
  5308. if ([CommentDisplayType.FloorInFloor, CommentDisplayType.FloorInFloorNoCallUser].includes(this.displayType))
  5309. return this.post.nestedReplies;
  5310. if (this.displayType === CommentDisplayType.Like) {
  5311. return window.clone(this.post.nestedReplies).sort((a, b) => b.thankCount - a.thankCount);
  5312. }
  5313. if (this.displayType === CommentDisplayType.V2exOrigin)
  5314. return this.post.replyList;
  5315. if (this.displayType === CommentDisplayType.FloorInFloorNested)
  5316. return this.post.nestedRedundReplies;
  5317. if (this.displayType === CommentDisplayType.OnlyOp)
  5318. return this.post.replyList.filter((v) => {
  5319. var _a;
  5320. return v.username === ((_a = this.post.member) == null ? void 0 : _a.username);
  5321. });
  5322. return [];
  5323. },
  5324. //关联回复
  5325. relationReply() {
  5326. if (this.targetUser.left.length && this.targetUser.right) {
  5327. return this.post.replyList.filter((v) => {
  5328. if (this.targetUser.left.includes(v.username)) {
  5329. if (v.floor > this.targetUser.rightFloor) {
  5330. if (v.replyUsers.includes(this.targetUser.right)) {
  5331. return true;
  5332. }
  5333. } else {
  5334. return true;
  5335. }
  5336. }
  5337. if (v.username === this.targetUser.right) {
  5338. for (let i = 0; i < this.targetUser.left.length; i++) {
  5339. if (v.replyUsers.includes(this.targetUser.left[i])) {
  5340. return true;
  5341. }
  5342. }
  5343. }
  5344. });
  5345. }
  5346. return [];
  5347. }
  5348. },
  5349. watch: {
  5350. "post.id"(n2, o) {
  5351. if (this.$refs["post-editor"]) {
  5352. this.$refs["post-editor"].content = "";
  5353. vue.nextTick(() => {
  5354. this.scrollTop(false);
  5355. });
  5356. }
  5357. },
  5358. "post.headerTemplate"(n2, o) {
  5359. let mountEl = document.querySelector(".main-wrapper .post-wrapper .html-wrapper .header");
  5360. if (mountEl) {
  5361. this.showOpTag = true;
  5362. }
  5363. },
  5364. modelValue: {
  5365. handler(newVal) {
  5366. if (this.isPost) {
  5367. return;
  5368. }
  5369. if (newVal) {
  5370. if (!window.history.state) {
  5371. window.history.pushState({}, 0, this.post.href);
  5372. }
  5373. this.read = this.post.read;
  5374. this.currentFloor = "";
  5375. vue.nextTick(() => {
  5376. window.document.title = this.post.title ?? "V2EX";
  5377. });
  5378. } else {
  5379. this.$emit("saveReadList");
  5380. window.document.title = "V2EX";
  5381. this.isSticky = false;
  5382. this.showRelationReply = false;
  5383. if (window.history.state) {
  5384. window.history.back();
  5385. }
  5386. }
  5387. }
  5388. }
  5389. },
  5390. mounted() {
  5391. this.debounceScroll = debounce(this.scroll, 300, false);
  5392. if (this.isLogin) {
  5393. const observer = new IntersectionObserver(
  5394. ([e2]) => e2.target.toggleAttribute("stuck", e2.intersectionRatio < 1),
  5395. { threshold: [1] }
  5396. );
  5397. observer.observe(this.$refs.replyBox);
  5398. window.addEventListener("keydown", this.onKeyDown);
  5399. }
  5400. eventBus.on(CMD.SHOW_CALL, (val) => {
  5401. if (val.show) {
  5402. this.showCallList = true;
  5403. this.replyText = val.text;
  5404. if (this.isPost) {
  5405. this.callStyle.top = val.top + $(window.win()).scrollTop() + -40 + "px";
  5406. } else {
  5407. this.callStyle.top = val.top + $(".post-detail").scrollTop() + 15 + "px";
  5408. }
  5409. this.callStyle.left = val.left - $(".main")[0].getBoundingClientRect().left + 10 + "px";
  5410. if (this.selectCallIndex >= this.filterCallList.length) {
  5411. this.selectCallIndex = 0;
  5412. }
  5413. } else {
  5414. this.replyText = "";
  5415. this.showCallList = false;
  5416. this.selectCallIndex = 0;
  5417. }
  5418. });
  5419. eventBus.on(CMD.RELATION_REPLY, (val) => {
  5420. this.targetUser = val;
  5421. this.showRelationReply = true;
  5422. });
  5423. eventBus.on(CMD.JUMP, this.jump);
  5424. if (this.isPost) {
  5425. window.addEventListener("scroll", this.debounceScroll);
  5426. }
  5427. eventBus.on(CMD.SHOW_COMMENT_OPTIONS, (comment) => {
  5428. this.currentComment = comment;
  5429. this.showCommentOptions = true;
  5430. });
  5431. eventBus.on(CMD.SHOW_EDITOR, (comment) => {
  5432. this.currentComment = comment;
  5433. this.isSticky = true;
  5434. setTimeout(() => {
  5435. var _a;
  5436. (_a = this.$refs["post-editor"]) == null ? void 0 : _a.focus();
  5437. }, 300);
  5438. });
  5439. },
  5440. beforeUnmount() {
  5441. window.removeEventListener("keydown", this.onKeyDown);
  5442. eventBus.off(CMD.SHOW_CALL);
  5443. },
  5444. methods: {
  5445. clickAvatar() {
  5446. window.functions.clickAvatar(".post-wrapper ");
  5447. },
  5448. addTag() {
  5449. eventBus.emit(CMD.ADD_TAG, this.post.member.username);
  5450. },
  5451. removeTag(tag) {
  5452. eventBus.emit(CMD.REMOVE_TAG, { username: this.post.member.username, tag });
  5453. },
  5454. scroll() {
  5455. if (!this.config.rememberLastReadFloor)
  5456. return;
  5457. let height = window.innerHeight * 0.3;
  5458. let comments = $(".comments .comment");
  5459. let forCount = 0;
  5460. for (let i = 0; i < comments.length; i++) {
  5461. forCount++;
  5462. let ins = comments[i];
  5463. let rect = ins.getBoundingClientRect();
  5464. if (rect.top > height) {
  5465. let lastReadFloor = Number(ins.dataset["floor"]);
  5466. console.log("当前阅读楼层", lastReadFloor);
  5467. eventBus.emit(CMD.ADD_READ, {
  5468. floor: lastReadFloor > 3 ? lastReadFloor : 0,
  5469. total: this.post.replyList.length
  5470. });
  5471. if (lastReadFloor > 3) {
  5472. this.read.floor = 0;
  5473. }
  5474. break;
  5475. }
  5476. }
  5477. if (forCount === comments.length) {
  5478. console.log("看到最后了");
  5479. eventBus.emit(CMD.ADD_READ, {
  5480. floor: forCount,
  5481. total: this.post.replyList.length
  5482. });
  5483. }
  5484. },
  5485. jump(floor) {
  5486. let lastItem = this.replyList[this.replyList.length - 1];
  5487. if (floor === "") {
  5488. floor = lastItem.floor;
  5489. } else {
  5490. try {
  5491. floor = Number(floor);
  5492. } catch (e2) {
  5493. floor = lastItem.floor;
  5494. }
  5495. if (floor === 0) {
  5496. floor = 1;
  5497. }
  5498. if (floor > lastItem.floor)
  5499. floor = lastItem.floor;
  5500. }
  5501. if (!this.post.replyList.length) {
  5502. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "没有回复可跳转!" });
  5503. this.read.floor = 0;
  5504. return;
  5505. }
  5506. if (floor > this.post.replyList.length) {
  5507. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "没有找到对应回复!" });
  5508. this.read.floor = 0;
  5509. return;
  5510. }
  5511. let comment = $(`.c_${floor}`);
  5512. if (!comment.length) {
  5513. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "没有找到对应回复!" });
  5514. this.read.floor = 0;
  5515. return;
  5516. }
  5517. comment[0].scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
  5518. comment.addClass("ding");
  5519. this.read.floor = 0;
  5520. this.currentFloor = floor + 1;
  5521. setTimeout(() => {
  5522. comment.removeClass("ding");
  5523. }, 2e3);
  5524. },
  5525. jumpLastRead(floor) {
  5526. if (this.config.autoJumpLastReadFloor) {
  5527. if (!floor)
  5528. return;
  5529. setTimeout(() => {
  5530. console.log("上次跳转", floor);
  5531. this.jump(floor);
  5532. eventBus.emit(CMD.SHOW_MSG, { type: "success", text: "已跳转到上次阅读位置" });
  5533. }, 300);
  5534. }
  5535. },
  5536. collapseTopReplyList() {
  5537. $(this.$refs.topReply).slideToggle("fast");
  5538. },
  5539. goBottom() {
  5540. this.isSticky = false;
  5541. setTimeout(() => {
  5542. let postWrapper = document.querySelector(".post-wrapper");
  5543. postWrapper.scrollTo({ top: this.$refs["detail"].clientHeight, behavior: "smooth" });
  5544. });
  5545. },
  5546. close() {
  5547. this.$emit("update:modelValue", false);
  5548. },
  5549. setCall(e2) {
  5550. eventBus.emit(CMD.SET_CALL, e2);
  5551. this.showCallList = false;
  5552. },
  5553. onKeyDown(e2) {
  5554. if (!this.modelValue)
  5555. return;
  5556. if (!this.showCallList)
  5557. return;
  5558. let length = this.filterCallList.slice(0, 10).length;
  5559. if (e2.keyCode === 13) {
  5560. this.setCall(this.filterCallList[this.selectCallIndex]);
  5561. e2.preventDefault();
  5562. }
  5563. if (e2.keyCode === 38) {
  5564. this.selectCallIndex--;
  5565. if (this.selectCallIndex < 0) {
  5566. this.selectCallIndex = length - 1;
  5567. }
  5568. e2.preventDefault();
  5569. }
  5570. if (e2.keyCode === 40) {
  5571. this.selectCallIndex++;
  5572. if (this.selectCallIndex > length - 1) {
  5573. this.selectCallIndex = 0;
  5574. }
  5575. e2.preventDefault();
  5576. }
  5577. },
  5578. scrollTop(anim = true) {
  5579. document.querySelector(".post-wrapper").scrollTo({ top: 0, behavior: anim ? "smooth" : "instant" });
  5580. }
  5581. }
  5582. };
  5583. const _withScopeId$4 = (n2) => (vue.pushScopeId("data-v-546d3b11"), n2 = n2(), vue.popScopeId(), n2);
  5584. const _hoisted_1$6 = { class: "left" };
  5585. const _hoisted_2$4 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("a", { href: "/" }, "V2EX", -1));
  5586. const _hoisted_3$3 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("span", { class: "chevron" }, "  ›  ", -1));
  5587. const _hoisted_4$3 = ["href"];
  5588. const _hoisted_5$2 = { class: "right" };
  5589. const _hoisted_6$2 = ["src"];
  5590. const _hoisted_7$1 = { class: "my-box post-main-body" };
  5591. const _hoisted_8$1 = { class: "box-content" };
  5592. const _hoisted_9$1 = { class: "box-header" };
  5593. const _hoisted_10 = { class: "gray" };
  5594. const _hoisted_11 = ["href"];
  5595. const _hoisted_12 = ["src"];
  5596. const _hoisted_13 = { class: "info" };
  5597. const _hoisted_14 = { class: "top" };
  5598. const _hoisted_15 = ["href"];
  5599. const _hoisted_16 = {
  5600. key: 0,
  5601. class: "center"
  5602. };
  5603. const _hoisted_17 = { class: "my-tag" };
  5604. const _hoisted_18 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-tag" }, null, -1));
  5605. const _hoisted_19 = ["onClick"];
  5606. const _hoisted_20 = { class: "bottom" };
  5607. const _hoisted_21 = ["title"];
  5608. const _hoisted_22 = ["href"];
  5609. const _hoisted_23 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-info-circle" }, null, -1));
  5610. const _hoisted_24 = [
  5611. _hoisted_23
  5612. ];
  5613. const _hoisted_25 = ["href"];
  5614. const _hoisted_26 = {
  5615. key: 0,
  5616. class: "my-box"
  5617. };
  5618. const _hoisted_27 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("span", { class: "" }, "高赞回复", -1));
  5619. const _hoisted_28 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "top-reply" }, [
  5620. /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-compress" })
  5621. ], -1));
  5622. const _hoisted_29 = [
  5623. _hoisted_27,
  5624. _hoisted_28
  5625. ];
  5626. const _hoisted_30 = { ref: "topReply" };
  5627. const _hoisted_31 = {
  5628. key: 1,
  5629. class: "my-cell flex comments-header"
  5630. };
  5631. const _hoisted_32 = {
  5632. key: 2,
  5633. class: "my-box comment-wrapper"
  5634. };
  5635. const _hoisted_33 = {
  5636. key: 0,
  5637. class: "loading-wrapper"
  5638. };
  5639. const _hoisted_34 = {
  5640. key: 1,
  5641. class: "comments"
  5642. };
  5643. const _hoisted_35 = {
  5644. key: 3,
  5645. id: "no-comments-yet"
  5646. };
  5647. const _hoisted_36 = { class: "my-cell flex" };
  5648. const _hoisted_37 = { class: "notice-right gray" };
  5649. const _hoisted_38 = { class: "p1" };
  5650. const _hoisted_39 = ["onClick"];
  5651. function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
  5652. const _component_BackIcon = vue.resolveComponent("BackIcon");
  5653. const _component_BaseLoading = vue.resolveComponent("BaseLoading");
  5654. const _component_MoreIcon = vue.resolveComponent("MoreIcon");
  5655. const _component_BaseHtmlRender = vue.resolveComponent("BaseHtmlRender");
  5656. const _component_Toolbar = vue.resolveComponent("Toolbar");
  5657. const _component_Comment = vue.resolveComponent("Comment");
  5658. const _component_BaseSelect = vue.resolveComponent("BaseSelect");
  5659. const _component_PostEditor = vue.resolveComponent("PostEditor");
  5660. const _component_post_options = vue.resolveComponent("post-options");
  5661. const _component_comment_options = vue.resolveComponent("comment-options");
  5662. const _component_relation_reply = vue.resolveComponent("relation-reply");
  5663. return vue.openBlock(), vue.createBlock(vue.Teleport, { to: ".post-wrapper" }, [
  5664. vue.createElementVNode("div", {
  5665. class: vue.normalizeClass(["post-detail", [
  5666. $options.isNight ? "isNight" : "",
  5667. $options.pageType
  5668. ]]),
  5669. ref: "detail",
  5670. id: "post-detail",
  5671. onScroll: _cache[20] || (_cache[20] = (...args) => $data.debounceScroll && $data.debounceScroll(...args))
  5672. }, [
  5673. vue.createElementVNode("div", {
  5674. class: "my-box nav-bar",
  5675. onDblclick: _cache[2] || (_cache[2] = vue.withModifiers((...args) => $options.scrollTop && $options.scrollTop(...args), ["stop"]))
  5676. }, [
  5677. vue.createElementVNode("div", _hoisted_1$6, [
  5678. !$options.isPost ? (vue.openBlock(), vue.createBlock(_component_BackIcon, {
  5679. key: 0,
  5680. onClick: vue.withModifiers($options.close, ["stop"])
  5681. }, null, 8, ["onClick"])) : vue.createCommentVNode("", true),
  5682. $options.isPost ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  5683. _hoisted_2$4,
  5684. _hoisted_3$3
  5685. ], 64)) : vue.createCommentVNode("", true),
  5686. vue.createElementVNode("a", {
  5687. href: $options.post.node.url
  5688. }, vue.toDisplayString($options.post.node.title), 9, _hoisted_4$3)
  5689. ]),
  5690. vue.createElementVNode("div", _hoisted_5$2, [
  5691. $props.refreshLoading ? (vue.openBlock(), vue.createBlock(_component_BaseLoading, { key: 0 })) : vue.createCommentVNode("", true),
  5692. vue.createVNode(_component_MoreIcon, {
  5693. onClick: _cache[0] || (_cache[0] = vue.withModifiers(($event) => $data.showPostOptions = true, ["stop"]))
  5694. }),
  5695. $options.user.avatar ? (vue.openBlock(), vue.createElementBlock("img", {
  5696. key: 1,
  5697. onClick: _cache[1] || (_cache[1] = (...args) => $options.clickAvatar && $options.clickAvatar(...args)),
  5698. style: { "margin-right": "0" },
  5699. class: "avatar mobile",
  5700. src: $options.user.avatar
  5701. }, null, 8, _hoisted_6$2)) : vue.createCommentVNode("", true)
  5702. ])
  5703. ], 32),
  5704. vue.createElementVNode("div", _hoisted_7$1, [
  5705. vue.createElementVNode("div", _hoisted_8$1, [
  5706. vue.createElementVNode("div", _hoisted_9$1, [
  5707. vue.createElementVNode("small", _hoisted_10, [
  5708. $options.post.member.avatar_large ? (vue.openBlock(), vue.createElementBlock("a", {
  5709. key: 0,
  5710. class: "base-avatar",
  5711. href: `/member/${$options.post.member.username}`
  5712. }, [
  5713. vue.createElementVNode("img", {
  5714. src: $options.post.member.avatar_large
  5715. }, null, 8, _hoisted_12)
  5716. ], 8, _hoisted_11)) : vue.createCommentVNode("", true),
  5717. vue.createElementVNode("div", _hoisted_13, [
  5718. vue.createElementVNode("div", _hoisted_14, [
  5719. vue.createElementVNode("a", {
  5720. href: `/member/${$options.post.member.username}`
  5721. }, vue.toDisplayString($options.post.member.username), 9, _hoisted_15),
  5722. $options.post.member.createDate ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  5723. vue.createTextVNode(" · "),
  5724. vue.createElementVNode("span", {
  5725. class: vue.normalizeClass($options.post.member.isNew && "danger")
  5726. }, vue.toDisplayString($options.post.member.createDate), 3)
  5727. ], 64)) : vue.createCommentVNode("", true)
  5728. ]),
  5729. $options.isLogin && $options.config.openTag ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_16, [
  5730. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.myTags, (i) => {
  5731. return vue.openBlock(), vue.createElementBlock("span", _hoisted_17, [
  5732. _hoisted_18,
  5733. vue.createElementVNode("span", null, vue.toDisplayString(i), 1),
  5734. vue.createElementVNode("i", {
  5735. class: "fa fa-trash-o remove",
  5736. onClick: ($event) => $options.removeTag(i)
  5737. }, null, 8, _hoisted_19)
  5738. ]);
  5739. }), 256)),
  5740. vue.createElementVNode("span", {
  5741. class: "add-tag ago",
  5742. onClick: _cache[3] || (_cache[3] = (...args) => $options.addTag && $options.addTag(...args)),
  5743. title: "添加标签"
  5744. }, "+")
  5745. ])) : vue.createCommentVNode("", true),
  5746. vue.createElementVNode("div", _hoisted_20, [
  5747. $options.post.createDateAgo ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  5748. vue.createElementVNode("span", {
  5749. title: $options.post.createDate
  5750. }, vue.toDisplayString($options.post.createDateAgo), 9, _hoisted_21),
  5751. vue.createTextVNode(" · ")
  5752. ], 64)) : vue.createCommentVNode("", true),
  5753. vue.createTextVNode(" " + vue.toDisplayString($options.post.clickCount) + " 次点击 ", 1),
  5754. $options.isMy ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  5755. vue.createTextVNode("   "),
  5756. vue.createElementVNode("a", {
  5757. href: `/t/${$options.post.id}/info`
  5758. }, _hoisted_24, 8, _hoisted_22),
  5759. vue.createTextVNode("   "),
  5760. vue.createElementVNode("a", {
  5761. href: `/append/topic/${$options.post.id}`,
  5762. class: "op"
  5763. }, "APPEND", 8, _hoisted_25)
  5764. ], 64)) : vue.createCommentVNode("", true)
  5765. ])
  5766. ])
  5767. ]),
  5768. vue.createElementVNode("h1", null, vue.toDisplayString($options.post.title), 1)
  5769. ]),
  5770. vue.createVNode(_component_BaseHtmlRender, {
  5771. html: $options.post.headerTemplate
  5772. }, null, 8, ["html"])
  5773. ]),
  5774. vue.createVNode(_component_Toolbar, {
  5775. onReply: _cache[4] || (_cache[4] = ($event) => {
  5776. $data.isSticky = !$data.isSticky;
  5777. $data.currentComment = null;
  5778. })
  5779. })
  5780. ]),
  5781. $options.topReply.length && $options.config.showTopReply ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_26, [
  5782. vue.createElementVNode("div", {
  5783. class: "my-cell flex",
  5784. onClick: _cache[5] || (_cache[5] = (...args) => $options.collapseTopReplyList && $options.collapseTopReplyList(...args))
  5785. }, _hoisted_29),
  5786. vue.createElementVNode("div", _hoisted_30, [
  5787. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.topReply, (item, index) => {
  5788. return vue.openBlock(), vue.createBlock(_component_Comment, {
  5789. key: item.floor,
  5790. type: "top",
  5791. modelValue: $options.topReply[index],
  5792. "onUpdate:modelValue": ($event) => $options.topReply[index] = $event
  5793. }, null, 8, ["modelValue", "onUpdate:modelValue"]);
  5794. }), 128))
  5795. ], 512)
  5796. ])) : vue.createCommentVNode("", true),
  5797. $options.post.replyList.length || $props.loading ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_31, [
  5798. vue.createElementVNode("span", null, vue.toDisplayString($options.post.replyCount) + " 条回复", 1),
  5799. vue.createVNode(_component_BaseSelect, {
  5800. "display-type": $props.displayType,
  5801. "onUpdate:displayType": _cache[6] || (_cache[6] = (e2) => _ctx.$emit("update:displayType", e2))
  5802. }, null, 8, ["display-type"])
  5803. ])) : vue.createCommentVNode("", true),
  5804. $options.replyList.length || $props.loading ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_32, [
  5805. $props.loading ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_33, [
  5806. vue.createVNode(_component_BaseLoading, { size: "large" })
  5807. ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_34, [
  5808. $props.modelValue ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 0 }, vue.renderList($options.replyList, (item, index) => {
  5809. return vue.openBlock(), vue.createBlock(_component_Comment, {
  5810. key: item.floor,
  5811. modelValue: $options.replyList[index],
  5812. "onUpdate:modelValue": ($event) => $options.replyList[index] = $event
  5813. }, null, 8, ["modelValue", "onUpdate:modelValue"]);
  5814. }), 128)) : vue.createCommentVNode("", true)
  5815. ]))
  5816. ])) : vue.createCommentVNode("", true),
  5817. !($options.replyList.length || $props.loading) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_35, "目前尚无回复")) : vue.createCommentVNode("", true),
  5818. $options.isLogin ? (vue.openBlock(), vue.createElementBlock("div", {
  5819. key: 4,
  5820. class: vue.normalizeClass(["my-box", { "sticky": $data.isSticky }]),
  5821. ref: "replyBox"
  5822. }, [
  5823. vue.createElementVNode("div", _hoisted_36, [
  5824. vue.createElementVNode("span", null, vue.toDisplayString($data.currentComment ? `回复${$data.currentComment.floor}楼` : "回复主题"), 1),
  5825. vue.createElementVNode("div", _hoisted_37, [
  5826. $data.isSticky ? (vue.openBlock(), vue.createElementBlock("a", {
  5827. key: 0,
  5828. style: { "margin-right": "2rem" },
  5829. onClick: _cache[7] || (_cache[7] = ($event) => {
  5830. $data.isSticky = false;
  5831. $data.currentComment = null;
  5832. })
  5833. }, "取消回复框停靠")) : vue.createCommentVNode("", true),
  5834. vue.createElementVNode("a", {
  5835. onClick: _cache[8] || (_cache[8] = (...args) => $options.scrollTop && $options.scrollTop(...args))
  5836. }, "回到顶部")
  5837. ])
  5838. ]),
  5839. vue.createElementVNode("div", _hoisted_38, [
  5840. vue.createVNode(_component_PostEditor, {
  5841. onClose: $options.goBottom,
  5842. ref: "post-editor",
  5843. useType: $data.currentComment ? "reply-comment" : "reply-post",
  5844. replyUser: $options.replyUser,
  5845. replyFloor: $options.replyFloor,
  5846. onClick: _cache[9] || (_cache[9] = ($event) => $data.isSticky = true)
  5847. }, null, 8, ["onClose", "useType", "replyUser", "replyFloor"])
  5848. ])
  5849. ], 2)) : vue.createCommentVNode("", true),
  5850. $data.showCallList && $options.filterCallList.length ? (vue.openBlock(), vue.createElementBlock("div", {
  5851. key: 5,
  5852. class: "call-list",
  5853. style: vue.normalizeStyle($data.callStyle)
  5854. }, [
  5855. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.filterCallList, (item, index) => {
  5856. return vue.openBlock(), vue.createElementBlock("div", {
  5857. class: vue.normalizeClass(["call-item", { select: index === $data.selectCallIndex }]),
  5858. onClick: ($event) => $options.setCall(item)
  5859. }, [
  5860. vue.createElementVNode("a", null, vue.toDisplayString(item), 1)
  5861. ], 10, _hoisted_39);
  5862. }), 256))
  5863. ], 4)) : vue.createCommentVNode("", true),
  5864. vue.createVNode(_component_post_options, {
  5865. onMerge: _cache[10] || (_cache[10] = (val) => {
  5866. $options.post = Object.assign($options.post, val);
  5867. console.log("va", val, $options.post);
  5868. }),
  5869. post: $options.post,
  5870. onReply: _cache[11] || (_cache[11] = ($event) => ($options.eventBus.emit($options.CMD.SHOW_EDITOR, null), $data.showPostOptions = false)),
  5871. onRefresh: _cache[12] || (_cache[12] = ($event) => _ctx.$emit("refresh")),
  5872. modelValue: $data.showPostOptions,
  5873. "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => $data.showPostOptions = $event)
  5874. }, null, 8, ["post", "modelValue"]),
  5875. vue.createVNode(_component_comment_options, {
  5876. onMerge: _cache[14] || (_cache[14] = (val) => $data.currentComment = Object.assign($data.currentComment, val)),
  5877. onRecallThank: _cache[15] || (_cache[15] = ($event) => $data.currentComment.isThanked = false),
  5878. post: $options.post,
  5879. comment: $data.currentComment,
  5880. onClose: _cache[16] || (_cache[16] = ($event) => $data.currentComment = null),
  5881. onReply: _cache[17] || (_cache[17] = ($event) => ($options.eventBus.emit($options.CMD.SHOW_EDITOR, $data.currentComment), $data.showCommentOptions = false)),
  5882. modelValue: $data.showCommentOptions,
  5883. "onUpdate:modelValue": _cache[18] || (_cache[18] = ($event) => $data.showCommentOptions = $event)
  5884. }, null, 8, ["post", "comment", "modelValue"]),
  5885. vue.createVNode(_component_relation_reply, {
  5886. post: $options.post,
  5887. "relation-reply": $options.relationReply,
  5888. modelValue: $data.showRelationReply,
  5889. "onUpdate:modelValue": _cache[19] || (_cache[19] = ($event) => $data.showRelationReply = $event),
  5890. "target-user": $data.targetUser
  5891. }, null, 8, ["post", "relation-reply", "modelValue", "target-user"])
  5892. ], 34)
  5893. ]);
  5894. }
  5895. const PostDetail = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$2], ["__scopeId", "data-v-546d3b11"]]);
  5896. const _withScopeId$3 = (n2) => (vue.pushScopeId("data-v-1988f33b"), n2 = n2(), vue.popScopeId(), n2);
  5897. const _hoisted_1$5 = /* @__PURE__ */ _withScopeId$3(() => /* @__PURE__ */ vue.createElementVNode("svg", {
  5898. width: "24",
  5899. height: "24",
  5900. viewBox: "0 0 48 48",
  5901. fill: "none",
  5902. xmlns: "http://www.w3.org/2000/svg"
  5903. }, [
  5904. /* @__PURE__ */ vue.createElementVNode("path", {
  5905. d: "M17 32L19.1875 27M31 32L28.8125 27M19.1875 27L24 16L28.8125 27M19.1875 27H28.8125",
  5906. stroke: "#929596",
  5907. "stroke-width": "4",
  5908. "stroke-linecap": "round",
  5909. "stroke-linejoin": "round"
  5910. }),
  5911. /* @__PURE__ */ vue.createElementVNode("path", {
  5912. d: "M43.1999 20C41.3468 10.871 33.2758 4 23.5999 4C13.9241 4 5.85308 10.871 4 20L10 18",
  5913. stroke: "#929596",
  5914. "stroke-width": "4",
  5915. "stroke-linecap": "round",
  5916. "stroke-linejoin": "round"
  5917. }),
  5918. /* @__PURE__ */ vue.createElementVNode("path", {
  5919. d: "M4 28C5.85308 37.129 13.9241 44 23.5999 44C33.2758 44 41.3468 37.129 43.1999 28L38 30",
  5920. stroke: "#929596",
  5921. "stroke-width": "4",
  5922. "stroke-linecap": "round",
  5923. "stroke-linejoin": "round"
  5924. })
  5925. ], -1));
  5926. const _hoisted_2$3 = { key: 1 };
  5927. const _sfc_main$5 = {
  5928. __name: "Base64Tooltip",
  5929. setup(__props) {
  5930. const tooltip = vue.ref(null);
  5931. const show = vue.ref(false);
  5932. const originalText = vue.ref("");
  5933. const decodeText = vue.ref("");
  5934. const styleObject = vue.reactive({
  5935. left: "-100vw",
  5936. top: "-100vh"
  5937. });
  5938. vue.onMounted(() => {
  5939. eventBus.on(CMD.SHOW_TOOLTIP, ({ text, e: e2 }) => {
  5940. setTimeout(() => show.value = true);
  5941. originalText.value = text;
  5942. decodeText.value = "";
  5943. styleObject.left = e2.clientX + "px";
  5944. styleObject.top = e2.clientY + 20 + "px";
  5945. });
  5946. window.addEventListener("click", (e2) => {
  5947. if (!tooltip.value)
  5948. return;
  5949. if (!tooltip.value.contains(e2.target) && show.value) {
  5950. show.value = false;
  5951. }
  5952. }, { capture: true });
  5953. const fn = () => show.value && (show.value = false);
  5954. $(".post-detail", window.win().doc).on("scroll", fn);
  5955. });
  5956. function base64ToArrayBuffer(base64) {
  5957. let binary_string = window.atob(base64);
  5958. let len = binary_string.length;
  5959. let bytes = new Uint8Array(len);
  5960. for (let i = 0; i < len; i++) {
  5961. bytes[i] = binary_string.charCodeAt(i);
  5962. }
  5963. return bytes.buffer;
  5964. }
  5965. function decode() {
  5966. try {
  5967. new Blob([base64ToArrayBuffer(originalText.value)]).text().then((r2) => {
  5968. decodeText.value = r2;
  5969. });
  5970. } catch (e2) {
  5971. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "Base64解码失败!不是标准数据!" });
  5972. }
  5973. }
  5974. return (_ctx, _cache) => {
  5975. return vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", {
  5976. class: "base64_tooltip",
  5977. style: vue.normalizeStyle(styleObject),
  5978. onClick: decode,
  5979. ref_key: "tooltip",
  5980. ref: tooltip
  5981. }, [
  5982. !decodeText.value ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  5983. vue.createTextVNode(" Base64解码:" + vue.toDisplayString(originalText.value) + " ", 1),
  5984. _hoisted_1$5
  5985. ], 64)) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$3, [
  5986. vue.createElementVNode("span", null, vue.toDisplayString(decodeText.value), 1),
  5987. vue.createVNode(BaseButton, {
  5988. class: "btn",
  5989. size: "small",
  5990. onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(copy)(decodeText.value))
  5991. }, {
  5992. default: vue.withCtx(() => [
  5993. vue.createTextVNode("点击复制")
  5994. ]),
  5995. _: 1
  5996. })
  5997. ]))
  5998. ], 4)), [
  5999. [vue.vShow, show.value]
  6000. ]);
  6001. };
  6002. }
  6003. };
  6004. const Base64Tooltip = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-1988f33b"]]);
  6005. const _sfc_main$4 = {
  6006. name: "Msg",
  6007. components: { Icon },
  6008. props: {
  6009. type: "",
  6010. text: ""
  6011. },
  6012. created() {
  6013. setTimeout(() => {
  6014. this.$emit("close");
  6015. }, 3e3);
  6016. }
  6017. };
  6018. const _hoisted_1$4 = { class: "right" };
  6019. function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
  6020. const _component_Icon = vue.resolveComponent("Icon");
  6021. return vue.openBlock(), vue.createElementBlock("div", {
  6022. class: vue.normalizeClass(["msg", $props.type])
  6023. }, [
  6024. vue.createElementVNode("div", {
  6025. class: "left",
  6026. onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("close"))
  6027. }, [
  6028. vue.createVNode(_component_Icon, { icon: "ic:round-close" })
  6029. ]),
  6030. vue.createElementVNode("div", _hoisted_1$4, vue.toDisplayString($props.text), 1)
  6031. ], 2);
  6032. }
  6033. const Msg = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$1], ["__scopeId", "data-v-0dcc0508"]]);
  6034. const _withScopeId$2 = (n2) => (vue.pushScopeId("data-v-674b86aa"), n2 = n2(), vue.popScopeId(), n2);
  6035. const _hoisted_1$3 = {
  6036. key: 0,
  6037. class: "tag-modal modal"
  6038. };
  6039. const _hoisted_2$2 = { class: "wrapper" };
  6040. const _hoisted_3$2 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "title" }, " 添加标签 ", -1));
  6041. const _hoisted_4$2 = { class: "option" };
  6042. const _hoisted_5$1 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("span", null, "用户:", -1));
  6043. const _hoisted_6$1 = { class: "btns" };
  6044. const _sfc_main$3 = {
  6045. __name: "TagModal",
  6046. props: ["tags"],
  6047. emits: ["update:tags"],
  6048. setup(__props, { emit: __emit }) {
  6049. const tagModal = vue.reactive({
  6050. show: false,
  6051. currentUsername: "",
  6052. tag: ""
  6053. });
  6054. const props = __props;
  6055. const emit = __emit;
  6056. const inputRef = vue.ref();
  6057. vue.onMounted(() => {
  6058. eventBus.on(CMD.ADD_TAG, (username) => {
  6059. tagModal.currentUsername = username;
  6060. tagModal.show = true;
  6061. vue.nextTick(() => {
  6062. inputRef.value.focus();
  6063. });
  6064. });
  6065. });
  6066. async function addTag() {
  6067. if (!tagModal.tag) {
  6068. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "请输入标签" });
  6069. return;
  6070. }
  6071. let oldTag = window.clone(props.tags);
  6072. let tempTag = window.clone(props.tags);
  6073. let userTags = tempTag[tagModal.currentUsername] ?? [];
  6074. let rIndex = userTags.findIndex((v) => v === tagModal.tag);
  6075. if (rIndex > -1) {
  6076. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "标签已存在!" });
  6077. return;
  6078. } else {
  6079. userTags.push(tagModal.tag);
  6080. }
  6081. tempTag[tagModal.currentUsername] = userTags;
  6082. emit("update:tags", tempTag);
  6083. tagModal.tag = "";
  6084. tagModal.show = false;
  6085. let res = await window.parse.saveTags(tempTag);
  6086. if (!res) {
  6087. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "标签添加失败!" });
  6088. emit("update:tags", oldTag);
  6089. }
  6090. }
  6091. return (_ctx, _cache) => {
  6092. return vue.openBlock(), vue.createBlock(vue.Transition, null, {
  6093. default: vue.withCtx(() => [
  6094. tagModal.show ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
  6095. vue.createElementVNode("div", {
  6096. class: "mask",
  6097. onClick: _cache[0] || (_cache[0] = vue.withModifiers(($event) => tagModal.show = false, ["stop"]))
  6098. }),
  6099. vue.createElementVNode("div", _hoisted_2$2, [
  6100. _hoisted_3$2,
  6101. vue.createElementVNode("div", _hoisted_4$2, [
  6102. _hoisted_5$1,
  6103. vue.createElementVNode("div", null, [
  6104. vue.createElementVNode("b", null, vue.toDisplayString(tagModal.currentUsername), 1)
  6105. ])
  6106. ]),
  6107. vue.withDirectives(vue.createElementVNode("input", {
  6108. type: "text",
  6109. ref_key: "inputRef",
  6110. ref: inputRef,
  6111. style: { "width": "100%" },
  6112. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => tagModal.tag = $event),
  6113. onKeydown: vue.withKeys(addTag, ["enter"])
  6114. }, null, 544), [
  6115. [vue.vModelText, tagModal.tag]
  6116. ]),
  6117. vue.createElementVNode("div", _hoisted_6$1, [
  6118. vue.createVNode(BaseButton, {
  6119. type: "link",
  6120. onClick: _cache[2] || (_cache[2] = ($event) => tagModal.show = false)
  6121. }, {
  6122. default: vue.withCtx(() => [
  6123. vue.createTextVNode("取消")
  6124. ]),
  6125. _: 1
  6126. }),
  6127. vue.createVNode(BaseButton, { onClick: addTag }, {
  6128. default: vue.withCtx(() => [
  6129. vue.createTextVNode("确定")
  6130. ]),
  6131. _: 1
  6132. })
  6133. ])
  6134. ])
  6135. ])) : vue.createCommentVNode("", true)
  6136. ]),
  6137. _: 1
  6138. });
  6139. };
  6140. }
  6141. };
  6142. const TagModal = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-674b86aa"]]);
  6143. const _hoisted_1$2 = { class: "msgs" };
  6144. const _sfc_main$2 = {
  6145. __name: "MsgModal",
  6146. setup(__props) {
  6147. const msgList = vue.reactive([
  6148. // {type: 'success', text: '123', id: Date.now()}
  6149. ]);
  6150. vue.onMounted(() => {
  6151. eventBus.on(CMD.SHOW_MSG, (val) => {
  6152. msgList.push({ ...val, id: Date.now() });
  6153. });
  6154. });
  6155. function removeMsg(id) {
  6156. let rIndex = msgList.findIndex((item) => item.id === id);
  6157. if (rIndex > -1) {
  6158. msgList.splice(rIndex, 1);
  6159. }
  6160. }
  6161. return (_ctx, _cache) => {
  6162. return vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
  6163. vue.createElementVNode("div", _hoisted_1$2, [
  6164. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(msgList, (v) => {
  6165. return vue.openBlock(), vue.createBlock(Msg, {
  6166. key: v.id,
  6167. type: v.type,
  6168. text: v.text,
  6169. onClose: ($event) => removeMsg(v.id)
  6170. }, null, 8, ["type", "text", "onClose"]);
  6171. }), 128))
  6172. ])
  6173. ]);
  6174. };
  6175. }
  6176. };
  6177. const MsgModal = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-93c4dec0"]]);
  6178. let u = ".__cf_email__", f = "data-cfemail", d = document.createElement("div");
  6179. function e(e2) {
  6180. console.error(e2);
  6181. }
  6182. function r(e2, t) {
  6183. let r2 = e2.substr(t, 2);
  6184. return parseInt(r2, 16);
  6185. }
  6186. function n(href, index) {
  6187. let o = "", a = r(href, index);
  6188. for (let i = index + 2; i < href.length; i += 2) {
  6189. let l = r(href, i) ^ a;
  6190. o += String.fromCharCode(l);
  6191. }
  6192. try {
  6193. o = decodeURIComponent(escape(o));
  6194. } catch (u2) {
  6195. e(u2);
  6196. }
  6197. d.innerHTML = '<a href="' + o.replace(/"/g, "&quot;") + '"></a>';
  6198. return d.childNodes[0].getAttribute("href") || "";
  6199. }
  6200. function decodeEmail(body) {
  6201. try {
  6202. let as = body.find(u);
  6203. as.each(function() {
  6204. try {
  6205. let o = this, a = o.parentNode, i = o.getAttribute(f);
  6206. if (i) {
  6207. let l = n(i, 0), d2 = document.createTextNode(l);
  6208. a.replaceChild(d2, o);
  6209. }
  6210. } catch (h2) {
  6211. e(h2);
  6212. }
  6213. });
  6214. } catch (s) {
  6215. e(s);
  6216. }
  6217. }
  6218. const _withScopeId$1 = (n2) => (vue.pushScopeId("data-v-19a5903e"), n2 = n2(), vue.popScopeId(), n2);
  6219. const _hoisted_1$1 = {
  6220. key: 0,
  6221. class: "tag-modal modal"
  6222. };
  6223. const _hoisted_2$1 = { class: "modal-root" };
  6224. const _hoisted_3$1 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "title" }, " 提醒系统 ", -1));
  6225. const _hoisted_4$1 = ["innerHTML"];
  6226. const _sfc_main$1 = {
  6227. __name: "NotificationModal",
  6228. props: ["modelValue", "h"],
  6229. emits: ["update:modelValue"],
  6230. setup(__props, { emit: __emit }) {
  6231. const emit = __emit;
  6232. vue.onMounted(() => {
  6233. });
  6234. function close() {
  6235. emit("update:modelValue", false);
  6236. }
  6237. return (_ctx, _cache) => {
  6238. return vue.openBlock(), vue.createBlock(vue.Transition, null, {
  6239. default: vue.withCtx(() => [
  6240. __props.modelValue ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
  6241. vue.createElementVNode("div", {
  6242. class: "mask",
  6243. onClick: vue.withModifiers(close, ["stop"])
  6244. }),
  6245. vue.createElementVNode("div", _hoisted_2$1, [
  6246. vue.createElementVNode("div", { class: "modal-header" }, [
  6247. _hoisted_3$1,
  6248. vue.createElementVNode("i", {
  6249. class: "fa fa-times",
  6250. onClick: close
  6251. })
  6252. ]),
  6253. vue.createElementVNode("div", {
  6254. innerHTML: __props.h,
  6255. class: "modal-body"
  6256. }, null, 8, _hoisted_4$1)
  6257. ])
  6258. ])) : vue.createCommentVNode("", true)
  6259. ]),
  6260. _: 1
  6261. });
  6262. };
  6263. }
  6264. };
  6265. const NotificationModal = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-19a5903e"]]);
  6266. const _sfc_main = {
  6267. components: {
  6268. BaseButton,
  6269. NotificationModal,
  6270. BaseLoading,
  6271. BaseSwitch,
  6272. MsgModal,
  6273. TagModal,
  6274. Tooltip,
  6275. Setting,
  6276. PostDetail,
  6277. Base64Tooltip,
  6278. Msg
  6279. },
  6280. provide() {
  6281. return {
  6282. user: vue.computed(() => window.user),
  6283. isLogin: vue.computed(() => this.isLogin),
  6284. isNight: vue.computed(() => this.isNight),
  6285. pageType: vue.computed(() => this.pageType),
  6286. tags: vue.computed(() => this.tags),
  6287. show: vue.computed(() => this.show),
  6288. post: vue.computed(() => this.current),
  6289. config: vue.computed(() => this.config),
  6290. allReplyUsers: vue.computed(() => {
  6291. var _a, _b, _c;
  6292. if ((_a = this.current) == null ? void 0 : _a.replyList) {
  6293. return Array.from(new Set(((_c = (_b = this.current) == null ? void 0 : _b.replyList) == null ? void 0 : _c.map((v) => v.username)) ?? []));
  6294. }
  6295. return [];
  6296. })
  6297. };
  6298. },
  6299. data() {
  6300. return {
  6301. loading: window.pageType === PageType.Post,
  6302. refreshLoading: false,
  6303. loadMore: false,
  6304. isLogin: !!window.user.username,
  6305. pageType: window.pageType,
  6306. isNight: window.isNight,
  6307. stopMe: window.stopMe,
  6308. //停止使用脚本
  6309. show: false,
  6310. current: window.clone(window.initPost),
  6311. list: [],
  6312. config: window.clone(window.config),
  6313. tags: window.user.tags,
  6314. readList: window.user.readList,
  6315. notificationModal: {
  6316. show: false,
  6317. h: ""
  6318. },
  6319. step: 0
  6320. };
  6321. },
  6322. computed: {
  6323. targetUserTags() {
  6324. return this.tags[window.targetUserName] ?? [];
  6325. },
  6326. isList() {
  6327. return [PageType.Home, PageType.Node].includes(this.pageType);
  6328. },
  6329. isPost() {
  6330. return this.pageType === PageType.Post;
  6331. },
  6332. isMember() {
  6333. return this.pageType === PageType.Member;
  6334. }
  6335. },
  6336. watch: {
  6337. config: {
  6338. handler(newVal) {
  6339. let config2 = { [window.user.username ?? "default"]: newVal };
  6340. localStorage.setItem("v2ex-config", JSON.stringify(config2));
  6341. window.config = newVal;
  6342. },
  6343. deep: true
  6344. },
  6345. tags(newVal) {
  6346. window.user.tags = newVal;
  6347. },
  6348. "config.viewType"(newVal) {
  6349. if (!newVal)
  6350. return;
  6351. if (newVal === "card") {
  6352. $(".post-item").each(function() {
  6353. $(this).addClass("preview");
  6354. });
  6355. } else {
  6356. $(".post-item").each(function() {
  6357. $(this).removeClass("preview");
  6358. });
  6359. }
  6360. },
  6361. "config.fontSizeType": {
  6362. handler(newVal) {
  6363. switch (newVal) {
  6364. case "small":
  6365. return $("html").css("font-size", "8px");
  6366. case "normal":
  6367. return $("html").css("font-size", "10px");
  6368. case "large":
  6369. return $("html").css("font-size", "12px");
  6370. case "big-large":
  6371. return $("html").css("font-size", "14px");
  6372. }
  6373. },
  6374. deep: true
  6375. },
  6376. show(n2) {
  6377. if (n2)
  6378. this.step++;
  6379. else
  6380. this.step--;
  6381. this.slide("post");
  6382. }
  6383. },
  6384. created() {
  6385. let that = this;
  6386. this.initEvent();
  6387. window.cb = this.winCb;
  6388. if (!window.canParseV2exPage)
  6389. return;
  6390. document.addEventListener("click", this.clickA, true);
  6391. $(document).on("click", ".post-item", function(e2) {
  6392. if (e2.currentTarget.getAttribute("script"))
  6393. return;
  6394. if (that.stopMe)
  6395. return true;
  6396. if (this.classList.contains("preview")) {
  6397. if (e2.target.tagName !== "A" && e2.target.tagName !== "IMG") {
  6398. console.log("点空白处", this);
  6399. let id = this.dataset["id"];
  6400. let href = this.dataset["href"];
  6401. if (id) {
  6402. that.clickPost(e2, id, href);
  6403. } else {
  6404. if (href)
  6405. location.href = href;
  6406. }
  6407. }
  6408. }
  6409. });
  6410. window.onpopstate = (event) => {
  6411. if (event.state) {
  6412. if (!this.show)
  6413. this.show = true;
  6414. } else {
  6415. if (this.show)
  6416. this.show = false;
  6417. }
  6418. };
  6419. window.onbeforeunload = () => {
  6420. };
  6421. window.deleteNotification = (nId, token) => {
  6422. console.log("deleteNotification", nId, token);
  6423. let item = $("#n_" + nId);
  6424. item.slideUp("fast");
  6425. $.post({
  6426. url: "/delete/notification/" + nId + "?once=" + token,
  6427. success() {
  6428. $.get({
  6429. url: "/notifications/below/" + window.notificationBottom,
  6430. success(data, status, request) {
  6431. item.remove();
  6432. $("#notifications").append(data);
  6433. window.notificationBottom = request.getResponseHeader("X-V2EX-New-Notification-Bottom");
  6434. },
  6435. error() {
  6436. item.slideDown("fast");
  6437. }
  6438. });
  6439. },
  6440. error() {
  6441. item.slideDown("fast");
  6442. }
  6443. });
  6444. };
  6445. },
  6446. beforeUnmount() {
  6447. eventBus.clear();
  6448. document.removeEventListener("click", this.clickA, true);
  6449. },
  6450. methods: {
  6451. async getUnreadMessagesCount() {
  6452. var _a, _b;
  6453. const res = await fetch(`${location.origin}/mission`);
  6454. const htmlText = await res.text();
  6455. const $page = $(htmlText);
  6456. const text = $page.find('#Rightbar a[href^="/notifications"]').text();
  6457. if (text.includes("未读提醒")) {
  6458. const countStr = (_a = text.match(/\d+/)) == null ? void 0 : _a.at(0);
  6459. if (countStr) {
  6460. return Number((_b = text.match(/\d+/)) == null ? void 0 : _b.at(0));
  6461. }
  6462. } else {
  6463. return 0;
  6464. }
  6465. throw new Error("无法获取未读消息数量");
  6466. },
  6467. clickA(e2) {
  6468. if (!(e2 == null ? void 0 : e2.target))
  6469. return;
  6470. if (e2.target.tagName !== "A")
  6471. return;
  6472. let that = this;
  6473. if (e2.target.getAttribute("script"))
  6474. return;
  6475. if (that.stopMe)
  6476. return true;
  6477. let { href, id, title } = functions.parseA(e2.target);
  6478. if (href.includes("/settings/night/toggle"))
  6479. return;
  6480. if (href.includes("/?tab="))
  6481. return;
  6482. if (href.includes("/go"))
  6483. return;
  6484. if (href === window.origin + "/#;")
  6485. return;
  6486. if (href === window.origin + "/")
  6487. return;
  6488. if (href === window.origin + "/recent")
  6489. return;
  6490. if (href.includes("/notifications"))
  6491. return;
  6492. if (href === window.origin + "/script-setting") {
  6493. window.functions.clickAvatar(this.show ? ".post-wrapper " : "");
  6494. this.slide("setting", this.step++);
  6495. that.stopEvent(e2);
  6496. return;
  6497. }
  6498. if (id) {
  6499. that.clickPost(e2, id, href, title);
  6500. } else {
  6501. if (that.config.newTabOpen) {
  6502. that.stopEvent(e2);
  6503. functions.openNewTab(href);
  6504. }
  6505. }
  6506. },
  6507. stopEvent(e2) {
  6508. e2.preventDefault();
  6509. e2.stopPropagation();
  6510. },
  6511. saveReadList() {
  6512. if (this.config.rememberLastReadFloor) {
  6513. window.parse.saveReadList(this.readList);
  6514. }
  6515. },
  6516. async clickPost(e2, id, href, title = "") {
  6517. if (id) {
  6518. if (this.config.clickPostItemOpenDetail) {
  6519. this.stopEvent(e2);
  6520. let index = this.list.findIndex((v) => v.id == id);
  6521. let postItem = this.clone(window.initPost);
  6522. if (index > -1) {
  6523. postItem = this.list[index];
  6524. }
  6525. if (!postItem.title) {
  6526. postItem.title = title ?? "加载中";
  6527. }
  6528. postItem.inList = index > -1;
  6529. if (postItem.inList) {
  6530. if (postItem.replyCount > MAX_REPLY_LIMIT) {
  6531. return functions.openNewTab(`${location.origin}/t/${id}?p=1&script=1`);
  6532. }
  6533. }
  6534. postItem.id = id;
  6535. postItem.href = href;
  6536. if (!postItem.headerTemplate) {
  6537. let template = `
  6538. <div class="cell">
  6539. <div class="topic_content">
  6540. <div class="markdown_body">
  6541. ${(postItem == null ? void 0 : postItem.content_rendered) ?? ""}
  6542. </div>
  6543. </div>
  6544. </div>
  6545. `;
  6546. postItem.headerTemplate = template;
  6547. }
  6548. this.getPostDetail(postItem);
  6549. return;
  6550. }
  6551. if (this.config.newTabOpen) {
  6552. this.stopEvent(e2);
  6553. functions.openNewTab(`https://www.v2ex.com/t/${id}?p=1`);
  6554. }
  6555. }
  6556. },
  6557. showPost() {
  6558. $(".slide-list").css("transition", `0s`);
  6559. setTimeout(() => {
  6560. $(".slide-list").css("transition", `transform .3s`);
  6561. }, 500);
  6562. this.show = true;
  6563. $("#site-header").css("margin-top", "-42px");
  6564. $(`#Wrapper .box:lt(5)`).each(function() {
  6565. $(this).hide();
  6566. });
  6567. },
  6568. slide(to = "post", v) {
  6569. if (this.step === 1) {
  6570. if (to === "post") {
  6571. $(".post-wrapper").css("z-index", 10);
  6572. $(".setting-wrapper").css("z-index", 9);
  6573. } else {
  6574. $(".post-wrapper").css("z-index", 9);
  6575. $(".setting-wrapper").css("z-index", 10);
  6576. }
  6577. }
  6578. $(".slide-list").css("transform", `translateX(-${this.step * 100}vw)`);
  6579. },
  6580. async winCb({ type, value }) {
  6581. console.log("回调的类型", type, value);
  6582. if (type === "syncData") {
  6583. this.list = window.postList;
  6584. this.config = window.config;
  6585. this.stopMe = window.stopMe;
  6586. this.tags = window.user.tags;
  6587. this.readList = window.user.readList;
  6588. this.current.read = this.readList[this.current.id] ?? {};
  6589. if (this.show && this.isPost && this.current.read.floor) {
  6590. this.$refs.postDetail.read = this.current.read;
  6591. }
  6592. }
  6593. if (type === "warningNotice") {
  6594. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: value });
  6595. }
  6596. if (this.stopMe)
  6597. return;
  6598. if (type === "restorePost") {
  6599. this.show = false;
  6600. this.loading = false;
  6601. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "脚本无法查看此页面!" });
  6602. $(`#Wrapper #Main .box:lt(3)`).each(function() {
  6603. $(this).show();
  6604. });
  6605. }
  6606. if (type === "postContent") {
  6607. this.current = Object.assign(this.current, value);
  6608. this.current.inList = true;
  6609. this.showPost();
  6610. }
  6611. if (type === "postReplies") {
  6612. this.current = Object.assign(this.current, value);
  6613. this.list.push(this.clone(this.current));
  6614. this.loading = false;
  6615. }
  6616. },
  6617. clone(val) {
  6618. return functions.clone(val);
  6619. },
  6620. regenerateReplyList() {
  6621. if (this.current.replyList.length) {
  6622. this.current.replyCount = this.current.replyList.length;
  6623. let res = functions.createNestedList(this.current.replyList);
  6624. if (res) {
  6625. this.current.nestedReplies = res;
  6626. }
  6627. let dup_res = functions.createNestedRedundantList(this.current.replyList);
  6628. if (dup_res) {
  6629. this.current.nestedRedundReplies = dup_res;
  6630. }
  6631. } else {
  6632. this.current.replyCount = 0;
  6633. this.current.nestedReplies = [];
  6634. this.current.nestedRedundReplies = [];
  6635. }
  6636. if (this.list.length) {
  6637. let rIndex = this.list.findIndex((i) => i.id === this.current.id);
  6638. if (rIndex > -1) {
  6639. this.list[rIndex] = this.clone(this.current);
  6640. }
  6641. }
  6642. },
  6643. initEvent() {
  6644. eventBus.on(CMD.CHANGE_COMMENT_THANK, (val) => {
  6645. console.log("CHANGE_COMMENT_THANK", val);
  6646. const { id, type } = val;
  6647. let currentI = this.current.replyList.findIndex((i) => i.id === id);
  6648. if (currentI > -1) {
  6649. this.current.replyList[currentI].isThanked = type === "add";
  6650. if (type === "add") {
  6651. this.current.replyList[currentI].thankCount++;
  6652. } else {
  6653. this.current.replyList[currentI].thankCount--;
  6654. }
  6655. this.regenerateReplyList();
  6656. }
  6657. });
  6658. eventBus.on(CMD.CHANGE_POST_THANK, (val) => {
  6659. const { id, type } = val;
  6660. this.current.isThanked = type === "add";
  6661. if (type === "add") {
  6662. this.current.thankCount++;
  6663. } else {
  6664. this.current.thankCount--;
  6665. }
  6666. let currentI = this.list.findIndex((i) => i.id === id);
  6667. if (currentI > -1) {
  6668. this.list[currentI].isThanked = type === "add";
  6669. if (type === "add") {
  6670. this.list[currentI].thankCount++;
  6671. } else {
  6672. this.list[currentI].thankCount++;
  6673. }
  6674. }
  6675. });
  6676. eventBus.on(CMD.REMOVE, (val) => {
  6677. let removeIndex = this.current.replyList.findIndex((i) => i.floor === val);
  6678. if (removeIndex > -1) {
  6679. this.current.replyList.splice(removeIndex, 1);
  6680. }
  6681. this.regenerateReplyList();
  6682. });
  6683. eventBus.on(CMD.IGNORE, () => {
  6684. this.show = false;
  6685. let rIndex = this.list.findIndex((i) => i.id === this.current.id);
  6686. if (rIndex > -1) {
  6687. this.list.splice(rIndex, 1);
  6688. }
  6689. let el = document.querySelector(`.id_${this.current.id}`);
  6690. if (el)
  6691. el.remove();
  6692. this.current = this.clone(window.initPost);
  6693. });
  6694. eventBus.on(CMD.MERGE, (val) => {
  6695. this.current = Object.assign(this.current, val);
  6696. let rIndex = this.list.findIndex((i) => i.id === this.current.id);
  6697. if (rIndex > -1) {
  6698. this.list[rIndex] = this.clone(this.current);
  6699. }
  6700. });
  6701. eventBus.on(CMD.MERGE_CONFIG, (val) => {
  6702. this.config = Object.assign(this.config, val);
  6703. });
  6704. eventBus.on(CMD.ADD_READ, (val) => {
  6705. this.readList[this.current.id] = val;
  6706. });
  6707. eventBus.on(CMD.ADD_REPLY, (item) => {
  6708. this.current.replyList.push(item);
  6709. this.regenerateReplyList();
  6710. });
  6711. eventBus.on(CMD.REFRESH_ONCE, async (once) => {
  6712. if (once) {
  6713. if (typeof once === "string") {
  6714. let res = once.match(/var once = "([\d]+)";/);
  6715. if (res && res[1]) {
  6716. this.current.once = Number(res[1]);
  6717. return;
  6718. }
  6719. }
  6720. if (typeof once === "number") {
  6721. this.current.once = once;
  6722. return;
  6723. }
  6724. }
  6725. window.fetchOnce().then((r2) => {
  6726. this.current.once = r2;
  6727. });
  6728. });
  6729. eventBus.on(CMD.REMOVE_TAG, async ({ username, tag }) => {
  6730. let oldTag = this.clone(this.tags);
  6731. let tags = this.tags[username] ?? [];
  6732. let rIndex = tags.findIndex((v) => v === tag);
  6733. if (rIndex > -1) {
  6734. tags.splice(rIndex, 1);
  6735. }
  6736. this.tags[username] = tags;
  6737. let res = await window.parse.saveTags(this.tags);
  6738. if (!res) {
  6739. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "标签删除失败!" });
  6740. this.tags = oldTag;
  6741. }
  6742. });
  6743. eventBus.on(CMD.REFRESH_POST, () => this.getPostDetail(this.current));
  6744. },
  6745. async getPostDetail(post) {
  6746. this.current = post;
  6747. this.current.read = this.readList[this.current.id] ?? { floor: 0, total: 0 };
  6748. this.show = true;
  6749. if (!this.current.inList) {
  6750. this.loading = true;
  6751. let r2 = await functions.checkPostReplies(post.id, true);
  6752. if (r2) {
  6753. eventBus.emit(CMD.SHOW_MSG, { type: "warning", text: "由于回复数量较多,已为您单独打开此主题" });
  6754. this.loading = this.show = false;
  6755. return;
  6756. }
  6757. }
  6758. let url = window.baseUrl + "/t/" + post.id;
  6759. this.current.url = url;
  6760. let alreadyHasReply = this.current.replyList.length;
  6761. if (alreadyHasReply) {
  6762. this.refreshLoading = true;
  6763. this.$refs.postDetail.jumpLastRead(this.current.read.floor);
  6764. } else {
  6765. this.loading = true;
  6766. }
  6767. let apiRes = await window.fetch(url + "?p=1");
  6768. if (apiRes.status === 404) {
  6769. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "主题未找到" });
  6770. return this.refreshLoading = this.loading = false;
  6771. }
  6772. if (apiRes.status === 403) {
  6773. this.refreshLoading = this.show = this.loading = false;
  6774. functions.openNewTab(`${location.origin}/t/${post.id}?p=1&script=0`);
  6775. return;
  6776. }
  6777. if (apiRes.redirected) {
  6778. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "没有权限" });
  6779. return this.refreshLoading = this.loading = false;
  6780. }
  6781. let htmlText = await apiRes.text();
  6782. let hasPermission = htmlText.search("你要查看的页面需要先登录");
  6783. if (hasPermission > -1) {
  6784. eventBus.emit(CMD.SHOW_MSG, { type: "error", text: "你要查看的页面需要先登录" });
  6785. return this.refreshLoading = this.loading = false;
  6786. }
  6787. let bodyText = htmlText.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  6788. let body = $(bodyText[0]);
  6789. decodeEmail(body);
  6790. await window.parse.getPostDetail(this.current, body, htmlText);
  6791. let index = this.list.findIndex((v) => v.id == this.current.id);
  6792. if (index > -1) {
  6793. this.list[index] = this.clone(this.current);
  6794. } else {
  6795. this.list.push(this.clone(this.current));
  6796. }
  6797. this.refreshLoading = this.loading = false;
  6798. if (!alreadyHasReply) {
  6799. vue.nextTick(() => {
  6800. this.$refs.postDetail.jumpLastRead(this.current.read.floor);
  6801. });
  6802. }
  6803. await window.parse.parseOp(this.current);
  6804. console.log("当前帖子", this.current);
  6805. },
  6806. addTargetUserTag() {
  6807. eventBus.emit(CMD.ADD_TAG, window.targetUserName);
  6808. },
  6809. removeTargetUserTag(tag) {
  6810. eventBus.emit(CMD.REMOVE_TAG, { username: window.targetUserName, tag });
  6811. }
  6812. }
  6813. };
  6814. const _withScopeId = (n2) => (vue.pushScopeId("data-v-f3ce1685"), n2 = n2(), vue.popScopeId(), n2);
  6815. const _hoisted_1 = {
  6816. key: 0,
  6817. class: "target-user-tags p1"
  6818. };
  6819. const _hoisted_2 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "标签:", -1));
  6820. const _hoisted_3 = { class: "my-tag" };
  6821. const _hoisted_4 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-tag" }, null, -1));
  6822. const _hoisted_5 = ["onClick"];
  6823. const _hoisted_6 = {
  6824. key: 1,
  6825. class: "my-box p2",
  6826. style: { "margin-top": "2rem" }
  6827. };
  6828. const _hoisted_7 = {
  6829. key: 0,
  6830. class: "flex flex-center"
  6831. };
  6832. const _hoisted_8 = {
  6833. key: 1,
  6834. class: "loaded"
  6835. };
  6836. const _hoisted_9 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "楼中楼解析完成", -1));
  6837. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  6838. const _component_Setting = vue.resolveComponent("Setting");
  6839. const _component_PostDetail = vue.resolveComponent("PostDetail");
  6840. const _component_TagModal = vue.resolveComponent("TagModal");
  6841. const _component_Base64Tooltip = vue.resolveComponent("Base64Tooltip");
  6842. const _component_MsgModal = vue.resolveComponent("MsgModal");
  6843. vue.resolveComponent("NotificationModal");
  6844. const _component_BaseLoading = vue.resolveComponent("BaseLoading");
  6845. const _component_BaseButton = vue.resolveComponent("BaseButton");
  6846. return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
  6847. vue.createVNode(_component_Setting, {
  6848. modelValue: $data.config,
  6849. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.config = $event),
  6850. onBack: _cache[1] || (_cache[1] = ($event) => $options.slide("post", $data.step--)),
  6851. to: ".setting-wrapper"
  6852. }, null, 8, ["modelValue"]),
  6853. vue.createVNode(_component_Setting, {
  6854. modelValue: $data.config,
  6855. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $data.config = $event),
  6856. onBack: _cache[3] || (_cache[3] = ($event) => $options.slide("post", $data.step--)),
  6857. to: ".setting-wrapper2"
  6858. }, null, 8, ["modelValue"]),
  6859. vue.createVNode(_component_PostDetail, {
  6860. modelValue: $data.show,
  6861. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $data.show = $event),
  6862. ref: "postDetail",
  6863. displayType: $data.config.commentDisplayType,
  6864. "onUpdate:displayType": _cache[5] || (_cache[5] = ($event) => $data.config.commentDisplayType = $event),
  6865. onSaveReadList: $options.saveReadList,
  6866. onRefresh: _cache[6] || (_cache[6] = ($event) => $options.getPostDetail($data.current)),
  6867. loading: $data.loading,
  6868. refreshLoading: $data.refreshLoading
  6869. }, null, 8, ["modelValue", "displayType", "onSaveReadList", "loading", "refreshLoading"]),
  6870. vue.createVNode(_component_TagModal, {
  6871. tags: $data.tags,
  6872. "onUpdate:tags": _cache[7] || (_cache[7] = ($event) => $data.tags = $event)
  6873. }, null, 8, ["tags"]),
  6874. vue.createVNode(_component_Base64Tooltip),
  6875. vue.createVNode(_component_MsgModal),
  6876. vue.createCommentVNode("", true),
  6877. !$data.stopMe ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  6878. $options.isMember && $data.isLogin && $data.config.openTag ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
  6879. _hoisted_2,
  6880. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.targetUserTags, (i) => {
  6881. return vue.openBlock(), vue.createElementBlock("span", _hoisted_3, [
  6882. _hoisted_4,
  6883. vue.createElementVNode("span", null, vue.toDisplayString(i), 1),
  6884. vue.createElementVNode("i", {
  6885. class: "fa fa-trash-o remove",
  6886. onClick: ($event) => $options.removeTargetUserTag(i)
  6887. }, null, 8, _hoisted_5)
  6888. ]);
  6889. }), 256)),
  6890. vue.createElementVNode("span", {
  6891. class: "add-tag ago",
  6892. onClick: _cache[9] || (_cache[9] = (...args) => $options.addTargetUserTag && $options.addTargetUserTag(...args)),
  6893. title: "添加标签"
  6894. }, "+")
  6895. ])) : vue.createCommentVNode("", true),
  6896. $options.isPost && !$data.show ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, [
  6897. $data.loading ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_7, [
  6898. vue.createVNode(_component_BaseLoading)
  6899. ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_8, [
  6900. _hoisted_9,
  6901. vue.createVNode(_component_BaseButton, {
  6902. size: "small",
  6903. onClick: $options.showPost
  6904. }, {
  6905. default: vue.withCtx(() => [
  6906. vue.createTextVNode("点击显示")
  6907. ]),
  6908. _: 1
  6909. }, 8, ["onClick"])
  6910. ]))
  6911. ])) : vue.createCommentVNode("", true)
  6912. ], 64)) : vue.createCommentVNode("", true)
  6913. ], 64);
  6914. }
  6915. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-f3ce1685"]]);
  6916. let isMobile = !document.querySelector("#Rightbar");
  6917. let $section = document.createElement("section");
  6918. $section.id = "app";
  6919. function run() {
  6920. window.baseUrl = location.origin;
  6921. window.initPost = DefaultPost;
  6922. window.win = function() {
  6923. return window;
  6924. };
  6925. window.win().doc = window.win().document;
  6926. window.win().query = (v) => window.win().document.querySelector(v);
  6927. window.query = (v) => window.win().document.querySelector(v);
  6928. window.clone = (val) => JSON.parse(JSON.stringify(val));
  6929. window.user = DefaultUser;
  6930. window.targetUserName = "";
  6931. window.pageType = void 0;
  6932. window.pageData = { pageNo: 1 };
  6933. window.config = DefaultConfig;
  6934. window.const = {
  6935. git: "https://github.com/zyronon/v2ex-script",
  6936. issue: "https://github.com/zyronon/v2ex-script/issues"
  6937. };
  6938. window.currentVersion = 1;
  6939. window.isNight = $(".Night").length === 1;
  6940. window.cb = null;
  6941. window.stopMe = false;
  6942. window.postList = [];
  6943. window.parse = {
  6944. //解析帖子内容
  6945. async parsePostContent(post, body, htmlText) {
  6946. var _a, _b;
  6947. let once = htmlText.match(/var once = "([\d]+)";/);
  6948. if (once && once[1]) {
  6949. post.once = once[1];
  6950. }
  6951. post.isReport = htmlText.includes("你已对本主题进行了报告");
  6952. let wrapperClass = "Wrapper";
  6953. let wrapper;
  6954. let boxs;
  6955. if (body.length > 1) {
  6956. body.each(function() {
  6957. if (this.id === wrapperClass) {
  6958. wrapper = $(this);
  6959. boxs = this.querySelectorAll(".box");
  6960. }
  6961. });
  6962. } else {
  6963. wrapper = body;
  6964. boxs = body.find(`#${wrapperClass} .box`);
  6965. }
  6966. let box1 = $(boxs[0]);
  6967. let header1 = wrapper.find(".header");
  6968. if (!post.title || !post.content_rendered) {
  6969. let h1 = wrapper.find("h1");
  6970. if (h1) {
  6971. post.title = h1[0].innerText;
  6972. }
  6973. }
  6974. let as = wrapper.find(".header > a");
  6975. if (as.length) {
  6976. post.node.title = as[1].innerText;
  6977. post.node.url = as[1].href;
  6978. }
  6979. let aName = header1.find("small.gray a:nth-child(1)");
  6980. if (aName) {
  6981. post.member.username = aName[0].innerText;
  6982. }
  6983. let small = header1.find("small.gray");
  6984. if (small[0]) {
  6985. let spanEl = (_b = (_a = small[0]) == null ? void 0 : _a.lastChild) == null ? void 0 : _b.nodeValue;
  6986. if (spanEl) {
  6987. let dianIndex = spanEl.indexOf("·");
  6988. post.createDateAgo = spanEl.substring(4, dianIndex - 1);
  6989. let text = spanEl.substring(dianIndex + 1).trim();
  6990. let reg3 = text.matchAll(/([\d]+)[\s]*次点击/g);
  6991. let clickCountReg = [...reg3];
  6992. if (clickCountReg.length) {
  6993. post.clickCount = Number(clickCountReg[0][1]);
  6994. }
  6995. reg3 = text.matchAll(/([\d]+)[\s]*views/g);
  6996. clickCountReg = [...reg3];
  6997. if (clickCountReg.length) {
  6998. post.clickCount = Number(clickCountReg[0][1]);
  6999. }
  7000. }
  7001. }
  7002. let avatarEl = header1.find(".avatar");
  7003. if (avatarEl) {
  7004. post.member.avatar_large = avatarEl[0].src;
  7005. }
  7006. let topic_buttons = box1.find(".inner .fr");
  7007. if (topic_buttons.length) {
  7008. let favoriteNode = topic_buttons.find(".op:first");
  7009. if (favoriteNode.length) {
  7010. post.isFavorite = favoriteNode[0].innerText === "取消收藏";
  7011. }
  7012. let ignoreNode = topic_buttons.find(".tb");
  7013. if (ignoreNode.length) {
  7014. post.isIgnore = ignoreNode[0].innerText === "取消忽略";
  7015. }
  7016. let thankNode = topic_buttons.find(".topic_thanked");
  7017. if (thankNode.length) {
  7018. post.isThanked = true;
  7019. }
  7020. let span = topic_buttons.find("span");
  7021. if (span.length) {
  7022. let text = span[0].innerText;
  7023. let reg1 = text.matchAll(/([\d]+)[\s]*人收藏/g);
  7024. let collectCountReg = [...reg1];
  7025. if (collectCountReg.length) {
  7026. post.collectCount = Number(collectCountReg[0][1]);
  7027. }
  7028. reg1 = text.matchAll(/([\d]+)[\s]*likes/g);
  7029. collectCountReg = [...reg1];
  7030. if (collectCountReg.length) {
  7031. post.collectCount = Number(collectCountReg[0][1]);
  7032. }
  7033. }
  7034. }
  7035. let header = $(boxs[0]);
  7036. let temp = header.clone();
  7037. temp.find(".topic_buttons").remove();
  7038. temp.find(".inner").remove();
  7039. temp.find(".header").remove();
  7040. let html = temp.html();
  7041. html = functions.checkPhotoLink2Img(html);
  7042. post.headerTemplate = html;
  7043. return post;
  7044. },
  7045. //解析OP信息
  7046. async parseOp(post) {
  7047. if (!post.member.id) {
  7048. let userRes = await fetch(window.baseUrl + "/api/members/show.json?username=" + post.member.username);
  7049. if (userRes.status === 200) {
  7050. post.member = await userRes.json();
  7051. }
  7052. }
  7053. if (post.member.id) {
  7054. let date = new Date(post.member.created * 1e3);
  7055. let createStr = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
  7056. date.setHours(0);
  7057. date.setMinutes(0);
  7058. date.setSeconds(0);
  7059. date.setMilliseconds(0);
  7060. let now = /* @__PURE__ */ new Date();
  7061. now.setHours(0);
  7062. now.setMinutes(0);
  7063. now.setSeconds(0);
  7064. now.setMilliseconds(0);
  7065. let d2 = now.getTime() - date.getTime();
  7066. let isNew = d2 <= 1e3 * 60 * 60 * 24 * 7;
  7067. post.member.createDate = createStr + " 注册";
  7068. post.member.isNew = isNew;
  7069. } else {
  7070. post.member.createDate = "用户已被注销/封禁";
  7071. post.member.isNew = true;
  7072. }
  7073. return post;
  7074. },
  7075. //获取帖子所有回复
  7076. async getPostAllReplies(post, body, htmlText, pageNo = 1) {
  7077. var _a, _b;
  7078. if (body.find("#no-comments-yet").length) {
  7079. return post;
  7080. }
  7081. let wrapperClass = "Wrapper";
  7082. let boxs;
  7083. let box;
  7084. if (body.length > 1) {
  7085. body.each(function() {
  7086. if (this.id === wrapperClass) {
  7087. boxs = this.querySelectorAll(".box");
  7088. box = boxs[2];
  7089. }
  7090. });
  7091. } else {
  7092. boxs = body.find(`#${wrapperClass} .box`);
  7093. box = boxs[2];
  7094. }
  7095. let cells = box.querySelectorAll(".cell");
  7096. if (cells && cells.length) {
  7097. post.fr = boxs[1].querySelector(".inner").innerHTML;
  7098. cells = Array.from(cells);
  7099. let snow = cells[0].querySelector(".snow");
  7100. post.createDate = ((_b = (_a = snow == null ? void 0 : snow.nextSibling) == null ? void 0 : _a.nodeValue) == null ? void 0 : _b.trim()) || "";
  7101. let repliesMap = [];
  7102. if (cells[1].id) {
  7103. repliesMap.push({ i: pageNo, replyList: this.parsePageReplies(cells.slice(1)) });
  7104. let replyList = functions.getAllReply(repliesMap);
  7105. post.replyList = replyList;
  7106. post.replyCount = replyList.length;
  7107. post.allReplyUsers = Array.from(new Set(replyList.map((v) => v.username)));
  7108. let nestedList = functions.createNestedList(replyList);
  7109. let nestedRedundantList = functions.createNestedRedundantList(replyList);
  7110. if (nestedList)
  7111. post.nestedReplies = nestedList;
  7112. if (nestedRedundantList)
  7113. post.nestedRedundReplies = nestedRedundantList;
  7114. return post;
  7115. } else {
  7116. let promiseList = [];
  7117. return new Promise((resolve, reject) => {
  7118. repliesMap.push({ i: pageNo, replyList: this.parsePageReplies(cells.slice(2, cells.length - 1)) });
  7119. let pages = cells[1].querySelectorAll("a.page_normal");
  7120. pages = Array.from(pages);
  7121. let url = window.baseUrl + "/t/" + post.id;
  7122. for (let i = 0; i < pages.length; i++) {
  7123. let currentPageNo = Number(pages[i].innerText);
  7124. promiseList.push(this.fetchPostOtherPageReplies(url + "?p=" + currentPageNo, currentPageNo));
  7125. }
  7126. Promise.allSettled(promiseList).then(
  7127. (results) => {
  7128. results.filter((result) => result.status === "fulfilled").map((v) => repliesMap.push(v.value));
  7129. let replyList = functions.getAllReply(repliesMap);
  7130. post.replyList = replyList;
  7131. post.replyCount = replyList.length;
  7132. post.allReplyUsers = Array.from(new Set(replyList.map((v) => v.username)));
  7133. let nestedList = functions.createNestedList(replyList);
  7134. let nestedRedundantList = functions.createNestedRedundantList(replyList);
  7135. if (nestedList)
  7136. post.nestedReplies = nestedList;
  7137. if (nestedRedundantList)
  7138. post.nestedRedundReplies = nestedRedundantList;
  7139. resolve(post);
  7140. }
  7141. );
  7142. });
  7143. }
  7144. }
  7145. },
  7146. //请求帖子其他页的回复
  7147. fetchPostOtherPageReplies(href, pageNo) {
  7148. return new Promise((resolve) => {
  7149. $.get(href).then((res) => {
  7150. let s = res.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  7151. let wrapperClass = "Wrapper";
  7152. let box;
  7153. $(s[0]).each(function() {
  7154. if (this.id === wrapperClass) {
  7155. box = this.querySelectorAll(".box")[2];
  7156. }
  7157. });
  7158. let cells = box.querySelectorAll(".cell");
  7159. cells = Array.from(cells);
  7160. resolve({ i: pageNo, replyList: this.parsePageReplies(cells.slice(2, cells.length - 1)) });
  7161. }).catch((r2) => {
  7162. if (r2.status === 403) {
  7163. functions.cbChecker({ type: "restorePost", value: null });
  7164. }
  7165. });
  7166. });
  7167. },
  7168. //解析页面的回复
  7169. parsePageReplies(nodes) {
  7170. let replyList = [];
  7171. nodes.forEach((node, index) => {
  7172. if (!node.id)
  7173. return;
  7174. let item = {
  7175. level: 0,
  7176. thankCount: 0,
  7177. isThanked: false,
  7178. isOp: false,
  7179. isDup: false,
  7180. id: node.id.replace("r_", "")
  7181. };
  7182. let reply_content = node.querySelector(".reply_content");
  7183. item.reply_content = functions.checkPhotoLink2Img(reply_content.innerHTML);
  7184. item.reply_text = reply_content.textContent;
  7185. let { users, floor } = this.parseReplyContent(item.reply_content);
  7186. item.hideCallUserReplyContent = item.reply_content;
  7187. if (users.length === 1) {
  7188. item.hideCallUserReplyContent = item.reply_content.replace(/@<a href="\/member\/[\s\S]+?<\/a>(\s#[\d]+)?\s(<br>)?/, () => "");
  7189. }
  7190. item.replyUsers = users;
  7191. item.replyFloor = floor;
  7192. let spans = node.querySelectorAll("span");
  7193. let ago = spans[1];
  7194. item.date = ago.textContent;
  7195. let userNode = node.querySelector("strong a");
  7196. item.username = userNode.textContent;
  7197. let avatar = node.querySelector("td img");
  7198. item.avatar = avatar.src;
  7199. let no = node.querySelector(".no");
  7200. item.floor = Number(no.textContent);
  7201. let thank_area = node.querySelector(".thank_area");
  7202. if (thank_area) {
  7203. item.isThanked = thank_area.classList.contains("thanked");
  7204. }
  7205. let small = spans[2];
  7206. if (small) {
  7207. item.thankCount = Number(small.textContent);
  7208. }
  7209. let op = node.querySelector(".op");
  7210. if (op) {
  7211. item.isOp = true;
  7212. }
  7213. let mod = node.querySelector(".mod");
  7214. if (mod) {
  7215. item.isMod = true;
  7216. }
  7217. replyList.push(item);
  7218. });
  7219. return replyList;
  7220. },
  7221. //解析回复内容,解析出@用户,回复楼层。用于后续生成嵌套楼层
  7222. parseReplyContent(str) {
  7223. if (!str)
  7224. return;
  7225. let users = [];
  7226. let getUsername = (userStr) => {
  7227. let endIndex = userStr.indexOf('">');
  7228. if (endIndex > -1) {
  7229. let user = userStr.substring(0, endIndex);
  7230. if (!users.find((i) => i === user)) {
  7231. users.push(user);
  7232. }
  7233. }
  7234. };
  7235. let userReg = /@<a href="\/member\/([\s\S]+?)<\/a>/g;
  7236. let has = str.matchAll(userReg);
  7237. let res2 = [...has];
  7238. if (res2.length > 1) {
  7239. res2.map((item) => {
  7240. getUsername(item[1]);
  7241. });
  7242. }
  7243. if (res2.length === 1) {
  7244. getUsername(res2[0][1]);
  7245. }
  7246. let floor = -1;
  7247. if (users.length === 1) {
  7248. let floorReg = /@<a href="\/member\/[\s\S]+?<\/a>[\s]+#([\d]+)/g;
  7249. let hasFloor = str.matchAll(floorReg);
  7250. let res = [...hasFloor];
  7251. if (res.length) {
  7252. floor = Number(res[0][1]);
  7253. }
  7254. }
  7255. return { users, floor };
  7256. },
  7257. //获取帖子详情
  7258. async getPostDetail(post, body, htmlText, pageNo = 1) {
  7259. post = await this.parsePostContent(post, body, htmlText);
  7260. return await this.getPostAllReplies(post, body, htmlText, pageNo);
  7261. },
  7262. //解析页面帖子列表
  7263. parsePagePostList(list, box) {
  7264. list.forEach((itemDom) => {
  7265. let item = window.clone(window.initPost);
  7266. let item_title = itemDom.querySelector(".item_title");
  7267. itemDom.classList.add("post-item");
  7268. if (!item_title)
  7269. return;
  7270. let a = item_title.querySelector("a");
  7271. let { href, id } = functions.parseA(a);
  7272. item.id = id;
  7273. a.href = item.href = href;
  7274. item.url = location.origin + "/api/topics/show.json?id=" + item.id;
  7275. itemDom.classList.add(`id_${id}`);
  7276. itemDom.dataset["href"] = href;
  7277. itemDom.dataset["id"] = id;
  7278. window.postList.push(item);
  7279. if (![PageType.Member].includes(window.pageType)) {
  7280. let headerWrap = $(`
  7281. <div class="new-item">
  7282. <div class="left">
  7283. <div class="top">
  7284. <div class="r">
  7285. <div class="small fade"></div>
  7286. <div class="small fade"></div>
  7287. </div>
  7288. </div>
  7289. <div class="bottom"></div>
  7290. </div>
  7291. <div class="right"></div>
  7292. </div>`);
  7293. headerWrap.find(".bottom").append(item_title);
  7294. headerWrap.find(".right").append(itemDom.querySelector(".count_livid"));
  7295. headerWrap.find(".top").prepend(itemDom.querySelector("td:first-child a"));
  7296. let info = itemDom.querySelector("td:nth-child(3)");
  7297. if (window.pageType === PageType.Node)
  7298. ;
  7299. if ([PageType.Changes, PageType.Home].includes(window.pageType)) {
  7300. let s1 = info.querySelector("span:first-child");
  7301. let t = headerWrap.find(".top .r div:first");
  7302. t.append(s1.querySelector("strong"));
  7303. t.append(` `);
  7304. t.append(s1.querySelector("a"));
  7305. }
  7306. let b = headerWrap.find(".top .r div:last");
  7307. b.append(info.querySelector("span:last-child").innerHTML);
  7308. itemDom.append(headerWrap[0]);
  7309. itemDom.querySelector("table").remove();
  7310. }
  7311. });
  7312. Promise.allSettled(window.postList.map((item) => $.get(item.url))).then((res) => {
  7313. let ok = res.filter((r2) => r2.status === "fulfilled").map((v) => v.value[0]);
  7314. if (window.config.viewType === "card") {
  7315. list.forEach((itemDom) => itemDom.classList.add("preview"));
  7316. }
  7317. ok.map((postItem) => {
  7318. var _a;
  7319. if (postItem == null ? void 0 : postItem.id) {
  7320. let itemDom = box.querySelector(`.id_${postItem.id}`);
  7321. let index = window.postList.findIndex((v) => v.id == postItem.id);
  7322. if (index > -1) {
  7323. let obj = window.postList[index];
  7324. postItem.replyCount = postItem.replies;
  7325. window.postList[index] = Object.assign({}, obj, postItem);
  7326. if (postItem.content_rendered) {
  7327. let a = document.createElement("a");
  7328. a.href = obj.href;
  7329. a.classList.add("post-content");
  7330. let div = document.createElement("div");
  7331. div.innerHTML = postItem.content_rendered;
  7332. a.append(div);
  7333. itemDom.append(a);
  7334. if (div.clientHeight < 300) {
  7335. a.classList.add("show-all");
  7336. } else {
  7337. let showMore = document.createElement("div");
  7338. showMore.classList.add("show-more");
  7339. showMore.innerHTML = "显示更多/收起";
  7340. showMore.onclick = function(e2) {
  7341. e2.stopPropagation();
  7342. a.classList.toggle("show-all");
  7343. };
  7344. (_a = a.parentNode) == null ? void 0 : _a.append(showMore);
  7345. }
  7346. }
  7347. }
  7348. }
  7349. });
  7350. functions.cbChecker({ type: "syncData" });
  7351. });
  7352. },
  7353. //创建记事本子条目
  7354. async createNoteItem(itemName) {
  7355. return new Promise(async (resolve) => {
  7356. let data = new FormData();
  7357. data.append("content", itemName);
  7358. data.append("parent_id", 0);
  7359. data.append("syntax", 0);
  7360. let apiRes = await window.win().fetch(`${window.baseUrl}/notes/new`, { method: "post", body: data });
  7361. if (apiRes.redirected && apiRes.status === 200) {
  7362. resolve(apiRes.url.substr(-5));
  7363. return;
  7364. }
  7365. resolve(null);
  7366. });
  7367. },
  7368. //编辑记事本子条目
  7369. async editNoteItem(val, id) {
  7370. let data = new FormData();
  7371. data.append("content", val);
  7372. data.append("syntax", 0);
  7373. let apiRes = await window.fetch(`${window.baseUrl}/notes/edit/${id}`, {
  7374. method: "post",
  7375. body: data
  7376. });
  7377. return apiRes.redirected && apiRes.status === 200;
  7378. },
  7379. //标签操作
  7380. async saveTags(val) {
  7381. for (const [key, value] of Object.entries(val)) {
  7382. if (!value.length)
  7383. delete val[key];
  7384. }
  7385. return await this.editNoteItem(window.user.tagPrefix + JSON.stringify(val), window.user.tagsId);
  7386. },
  7387. //已读楼层操作
  7388. async saveReadList(val) {
  7389. return await this.editNoteItem(window.user.readPrefix + JSON.stringify(val), window.user.readNoteItemId);
  7390. },
  7391. //imgur图片删除hash操作
  7392. async saveImgurList(val) {
  7393. return await this.editNoteItem(window.user.imgurPrefix + JSON.stringify(val), window.user.imgurNoteId);
  7394. }
  7395. };
  7396. window.vals = {};
  7397. window.functions = {
  7398. clickAvatar(prex) {
  7399. let menu = $(`${prex}#menu-body`);
  7400. if (menu.css("--show-dropdown") === "block") {
  7401. menu.css("--show-dropdown", "none");
  7402. } else {
  7403. menu.css("--show-dropdown", "block");
  7404. }
  7405. }
  7406. };
  7407. function initStyle() {
  7408. let style2 = `
  7409. }
  7410. `;
  7411. let addStyle2 = document.createElement("style");
  7412. addStyle2.rel = "stylesheet";
  7413. addStyle2.type = "text/css";
  7414. addStyle2.innerHTML = style2;
  7415. window.document.head.append(addStyle2);
  7416. }
  7417. function qianDao() {
  7418. let timeNow = (/* @__PURE__ */ new Date()).getUTCFullYear() + "/" + ((/* @__PURE__ */ new Date()).getUTCMonth() + 1) + "/" + (/* @__PURE__ */ new Date()).getUTCDate();
  7419. if (window.pageType === PageType.Home) {
  7420. let qiandao = window.query('.box .inner a[href="/mission/daily"]');
  7421. if (qiandao) {
  7422. qianDao_(qiandao, timeNow);
  7423. } else if (window.win().doc.getElementById("gift_v2excellent")) {
  7424. window.win().doc.getElementById("gift_v2excellent").click();
  7425. localStorage.setItem("menu_clockInTime", timeNow);
  7426. console.info("[V2EX - 超级增强] 自动签到完成!");
  7427. } else {
  7428. console.info("[V2EX - 超级增强] 自动签到完成!");
  7429. }
  7430. } else {
  7431. let timeOld = localStorage.getItem("menu_clockInTime");
  7432. if (!timeOld || timeOld != timeNow) {
  7433. qianDaoStatus_(timeNow);
  7434. } else {
  7435. console.info("[V2EX - 超级增强] 自动签到完成!");
  7436. }
  7437. }
  7438. }
  7439. function qianDao_(qiandao, timeNow) {
  7440. let url = window.baseUrl + "/mission/daily/redeem?" + RegExp("once\\=(\\d+)").exec(document.querySelector("div#Top .tools, #menu-body").innerHTML)[0];
  7441. console.log("url", url);
  7442. $.get(url).then((r2) => {
  7443. let bodyText = r2.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  7444. let html = $(bodyText[0]);
  7445. if (html.find("li.fa.fa-ok-sign").length) {
  7446. html = html.find("#Main").text().match(/已连续登录 (\d+?) 天/)[0];
  7447. localStorage.setItem("menu_clockInTime", timeNow);
  7448. console.info("[V2EX - 超级增强] 自动签到完成!");
  7449. if (qiandao) {
  7450. qiandao.textContent = `自动签到完成!${html}`;
  7451. qiandao.href = "javascript:void(0);";
  7452. }
  7453. } else {
  7454. _GM_notification({
  7455. text: "自动签到失败!请关闭其他插件或脚本。\n如果连续几天都签到失败,请联系作者解决!",
  7456. timeout: 4e3,
  7457. onclick() {
  7458. functions.feedback();
  7459. }
  7460. });
  7461. console.warn("[V2EX 增强] 自动签到失败!请关闭其他插件或脚本。如果连续几天都签到失败,请联系作者解决!");
  7462. if (qiandao)
  7463. qiandao.textContent = "自动签到失败!请尝试手动签到!";
  7464. }
  7465. });
  7466. }
  7467. function qianDaoStatus_(timeNow) {
  7468. $.get(window.baseUrl + "/mission/daily").then((r2) => {
  7469. let bodyText = r2.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  7470. let html = $(bodyText[0]);
  7471. if (html.find('input[value^="领取"]').length) {
  7472. qianDao_(null, timeNow);
  7473. } else {
  7474. console.info("[V2EX 增强] 已经签过到了。");
  7475. localStorage.setItem("menu_clockInTime", timeNow);
  7476. }
  7477. });
  7478. }
  7479. function checkPageType() {
  7480. let l = window.location;
  7481. if (l.pathname === "/") {
  7482. window.pageType = PageType.Home;
  7483. } else if (l.pathname === "/changes") {
  7484. window.pageType = PageType.Changes;
  7485. } else if (l.pathname === "/recent") {
  7486. window.pageType = PageType.Changes;
  7487. } else if (l.href.match(/.com\/?tab=/)) {
  7488. window.pageType = PageType.Home;
  7489. } else if (l.href.match(/.com\/go\//)) {
  7490. if (!l.href.includes("/links")) {
  7491. window.pageType = PageType.Node;
  7492. }
  7493. } else if (l.href.match(/.com\/member/)) {
  7494. window.pageType = PageType.Member;
  7495. } else {
  7496. let r2 = l.href.match(/.com\/t\/([\d]+)/);
  7497. if (r2) {
  7498. window.pageType = PageType.Post;
  7499. window.pageData.id = r2[1];
  7500. if (l.search) {
  7501. let pr = l.href.match(/\?p=([\d]+)/);
  7502. if (pr)
  7503. window.pageData.pageNo = Number(pr[1]);
  7504. }
  7505. }
  7506. }
  7507. }
  7508. function getNoteItemContent(id, prefix) {
  7509. return new Promise((resolve, reject) => {
  7510. $.get(window.baseUrl + "/notes/edit/" + id).then((r2) => {
  7511. let bodyText = r2.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  7512. let body = $(bodyText[0]);
  7513. let text = body.find(".note_editor").text();
  7514. if (text === prefix) {
  7515. resolve({});
  7516. } else {
  7517. let tagJson = text.substring(prefix.length);
  7518. try {
  7519. resolve(JSON.parse(tagJson));
  7520. } catch (e2) {
  7521. console.log("tage", tagJson);
  7522. resolve({});
  7523. }
  7524. }
  7525. });
  7526. });
  7527. }
  7528. async function initNoteData() {
  7529. $.get(window.baseUrl + "/notes").then(async (r2) => {
  7530. let bodyText = r2.match(/<body[^>]*>([\s\S]+?)<\/body>/g);
  7531. let body = $(bodyText[0]);
  7532. let items = body.find("#Main .box .note_item_title a");
  7533. if (window.config.openTag) {
  7534. let tagItem = Array.from(items).find((v) => v.innerText.includes(window.user.tagPrefix));
  7535. if (tagItem) {
  7536. window.user.tagsId = tagItem.href.substr(-5);
  7537. window.user.tags = await getNoteItemContent(window.user.tagsId, window.user.tagPrefix);
  7538. } else {
  7539. let r22 = await window.parse.createNoteItem(window.user.tagPrefix);
  7540. r22 && (window.user.tagsId = r22);
  7541. }
  7542. }
  7543. if (window.config.rememberLastReadFloor) {
  7544. let readItem = Array.from(items).find((v) => v.innerText.includes(window.user.readPrefix));
  7545. if (readItem) {
  7546. window.user.readNoteItemId = readItem.href.substr(-5);
  7547. window.user.readList = await getNoteItemContent(window.user.readNoteItemId, window.user.readPrefix);
  7548. } else {
  7549. let r22 = await window.parse.createNoteItem(window.user.readPrefix);
  7550. r22 && (window.user.readNoteItemId = r22);
  7551. }
  7552. }
  7553. functions.cbChecker({ type: "syncData" });
  7554. });
  7555. }
  7556. function initConfig() {
  7557. return new Promise((resolve) => {
  7558. let configStr = window.localStorage.getItem("v2ex-config");
  7559. if (configStr) {
  7560. let configObj = JSON.parse(configStr);
  7561. configObj = configObj[window.user.username ?? "default"];
  7562. if (configObj) {
  7563. window.config = Object.assign(window.config, configObj);
  7564. }
  7565. }
  7566. resolve(window.config);
  7567. });
  7568. }
  7569. function addSettingText() {
  7570. let setting = $(`<a href="/script-setting" class="top">脚本管理</a>`);
  7571. $("#menu-body .cell:first").append(setting);
  7572. }
  7573. async function init() {
  7574. window.addEventListener("error", (e2) => {
  7575. let dom = e2.target;
  7576. let originImgUrl = dom.getAttribute("data-originurl");
  7577. if (originImgUrl) {
  7578. let a = document.createElement("a");
  7579. a.href = originImgUrl;
  7580. a.setAttribute("notice", "此标签由v2ex超级增强脚本转换图片失败后恢复");
  7581. a.innerText = originImgUrl;
  7582. dom.parentNode.replaceChild(a, dom);
  7583. }
  7584. }, true);
  7585. if (window.isNight) {
  7586. document.documentElement.classList.add("dark");
  7587. }
  7588. checkPageType();
  7589. addSettingText();
  7590. functions.initMonkeyMenu();
  7591. let s = $(`
  7592. <div class="slide">
  7593. <div class="slide-list">
  7594. <div class="slide-item page0"></div>
  7595. <div class="slide-item page1">
  7596. <div class="post-wrapper"></div>
  7597. <div class="setting-wrapper"></div>
  7598. </div>
  7599. <div class="slide-item page2">
  7600. <div class="setting-wrapper2"></div>
  7601. </div>
  7602. </div>
  7603. </div>`);
  7604. $("body").append(s);
  7605. $("body").children().slice(0, 4).each(function() {
  7606. $(".page0").append(this);
  7607. });
  7608. $(".post-wrapper").append($("#site-header").clone());
  7609. let top2 = $("#menu-body .cell:first .top:first");
  7610. if (top2.length && ["个人主页", "Profile"].includes(top2.text())) {
  7611. window.user.username = top2.attr("href").replace("/member/", "");
  7612. window.user.avatar = $("#menu-entry .avatar").attr("src");
  7613. }
  7614. initConfig().then((r2) => {
  7615. initStyle();
  7616. try {
  7617. if (window.config.autoSignin && window.user.username) {
  7618. qianDao();
  7619. }
  7620. } catch (e2) {
  7621. console.log("签到失败");
  7622. }
  7623. if (window.user.username) {
  7624. initNoteData();
  7625. }
  7626. });
  7627. let box;
  7628. let list;
  7629. let first;
  7630. let last;
  7631. switch (window.pageType) {
  7632. case PageType.Node:
  7633. box = document.querySelectorAll("#Wrapper .box");
  7634. box[1].style.background = "unset";
  7635. box[1].style.borderBottom = "none";
  7636. box[1].style["border-radius"] = "0";
  7637. box[1].style["box-shadow"] = "none";
  7638. first = $(box[1]).children().first();
  7639. first.addClass("cell post-item");
  7640. if (window.config.viewType === "card")
  7641. first[0].classList.add("preview");
  7642. last = $(box[1]).children().last();
  7643. last.addClass("cell post-item");
  7644. if (window.config.viewType === "card")
  7645. last[0].classList.add("preview");
  7646. list = box[1].querySelectorAll(".cell");
  7647. box[0].before($section);
  7648. window.parse.parsePagePostList(list, box[1]);
  7649. break;
  7650. case PageType.Home:
  7651. box = document.querySelector("#Wrapper .box");
  7652. let headerWrap = $('<div class="cell post-item"></div>');
  7653. if (window.config.viewType === "card")
  7654. headerWrap[0].classList.add("preview");
  7655. $(box).prepend(headerWrap);
  7656. $(box).children().slice(1, 3).each(function() {
  7657. headerWrap.append(this);
  7658. });
  7659. last = $(box).children().last();
  7660. last.addClass("cell post-item");
  7661. if (window.config.viewType === "card")
  7662. last[0].classList.add("preview");
  7663. box.style.background = "unset";
  7664. box.style["border-radius"] = "0";
  7665. box.style["box-shadow"] = "none";
  7666. list = box.querySelectorAll(".item");
  7667. list[0].before($section);
  7668. window.parse.parsePagePostList(list, box);
  7669. break;
  7670. case PageType.Changes:
  7671. box = document.querySelector("#Wrapper .box");
  7672. box.style.background = "unset";
  7673. box.style["border-radius"] = "0";
  7674. box.style["box-shadow"] = "none";
  7675. first = $(box).children().first();
  7676. first.addClass("cell post-item");
  7677. if (window.config.viewType === "card")
  7678. first[0].classList.add("preview");
  7679. last = $(box).children().last();
  7680. last.addClass("cell post-item");
  7681. if (window.config.viewType === "card")
  7682. last[0].classList.add("preview");
  7683. list = box.querySelectorAll(".item");
  7684. list[0].before($section);
  7685. window.parse.parsePagePostList(list, box);
  7686. break;
  7687. case PageType.Post:
  7688. box = document.querySelector("#Wrapper .box");
  7689. box.after($section);
  7690. let r2 = await functions.checkPostReplies(window.pageData.id, false);
  7691. if (r2) {
  7692. window.stopMe = true;
  7693. functions.cbChecker({ type: "syncData" });
  7694. functions.cbChecker({ type: "warningNotice", value: "由于回复数量较多,脚本已停止解析楼中楼" });
  7695. return;
  7696. }
  7697. let post = functions.clone(window.initPost);
  7698. post.id = window.pageData.id;
  7699. let body = $(document.body);
  7700. let htmlText = document.documentElement.outerHTML;
  7701. window.parse.parsePostContent(
  7702. post,
  7703. body,
  7704. htmlText
  7705. ).then(async (res) => {
  7706. await functions.cbChecker({ type: "postContent", value: res });
  7707. await window.parse.parseOp(res);
  7708. });
  7709. window.parse.getPostAllReplies(
  7710. post,
  7711. body,
  7712. htmlText,
  7713. window.pageData.pageNo
  7714. ).then(async (res1) => {
  7715. await functions.cbChecker({ type: "postReplies", value: res1 });
  7716. });
  7717. break;
  7718. case PageType.Member:
  7719. box = document.querySelectorAll("#Wrapper .box");
  7720. window.targetUserName = box[0].querySelector("h1").textContent;
  7721. if (window.config.openTag) {
  7722. box[0].style.borderBottom = "none";
  7723. box[0].style["border-bottom-left-radius"] = "0";
  7724. box[0].style["border-bottom-right-radius"] = "0";
  7725. }
  7726. list = box[2].querySelectorAll(".cell");
  7727. box[0].after($section);
  7728. window.parse.parsePagePostList(list, box[2]);
  7729. break;
  7730. default:
  7731. window.stopMe = true;
  7732. functions.cbChecker({ type: "syncData" });
  7733. console.error("未知页面");
  7734. break;
  7735. }
  7736. }
  7737. window.canParseV2exPage = !window.location.search.includes("script");
  7738. if (window.canParseV2exPage) {
  7739. init();
  7740. } else {
  7741. let box = document.querySelector("#Wrapper #Main .box");
  7742. box.after($section);
  7743. window.stopMe = true;
  7744. functions.cbChecker({ type: "syncData" });
  7745. if (window.location.search.includes("script=0")) {
  7746. functions.cbChecker({ type: "warningNotice", value: "脚本无法查看此主题,已为您单独打开此主题" });
  7747. }
  7748. if (window.location.search.includes("script=1")) {
  7749. functions.cbChecker({ type: "warningNotice", value: "由于回复数量较多,已为您单独打开此主题并停止解析楼中楼" });
  7750. }
  7751. }
  7752. }
  7753. if (isMobile) {
  7754. console.log("V2EX 移动端");
  7755. (function() {
  7756. if (/eruda=1/.test(location.href) || localStorage.getItem("active-eruda")) {
  7757. let src = "//cdn.jsdelivr.net/npm/eruda@3.0.1";
  7758. console.log(1);
  7759. let s = document.createElement("script");
  7760. s.src = src;
  7761. s.onload = () => {
  7762. let s1 = document.createElement("script");
  7763. s1.innerText = `eruda.init();`;
  7764. document.body.append(s1);
  7765. };
  7766. document.body.append(s);
  7767. }
  7768. })();
  7769. run();
  7770. let vueApp = vue.createApp(App);
  7771. vueApp.config.unwrapInjectedRef = true;
  7772. vueApp.mount($section);
  7773. }
  7774.  
  7775. })(Vue);