0x3f-problem-solution

自定义分数区间显示题目 标记题目状态 配合灵茶山艾府题单解题

  1. // ==UserScript==
  2. // @name 0x3f-problem-solution
  3. // @namespace https://gf.qytechs.cn//zh-CN/scripts/501134-0x3f-problem-solution
  4. // @version 0.0.5.9
  5. // @author wuxin0011
  6. // @description 自定义分数区间显示题目 标记题目状态 配合灵茶山艾府题单解题
  7. // @license MIT
  8. // @icon https://assets.leetcode.cn/aliyun-lc-upload/users/endlesscheng/avatar_1690721039.png
  9. // @source https://github.com/wuxin0011/tampermonkey-script/tree/main/0x3f-leetcode
  10. // @supportURL https://gf.qytechs.cn//zh-CN/scripts/501134-0x3f-problem-solution/feedback
  11. // @match https://leetcode.cn/circle/discuss/*
  12. // @match https://leetcode.cn/discuss/*
  13. // @match https://leetcode.cn/
  14. // @match https://leetcode.cn/problems/*
  15. // @match https://leetcode.cn/contest/*/problems/*
  16. // @match https://leetcode.com
  17. // @match https://leetcode.com/circle/discuss/*
  18. // @match https://leetcode.com/discuss/*
  19. // @match https://leetcode.com/problems/*
  20. // @match https://leetcode.com/contest/*/problems/*
  21. // @require https://unpkg.com/vue@3.4.31/dist/vue.global.prod.js
  22. // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B
  23. // @require https://unpkg.com/element-plus@2.7.6/dist/index.full.js
  24. // @resource elementPlusCss https://unpkg.com/element-plus@2.7.6/dist/index.css
  25. // @grant GM_addStyle
  26. // @grant GM_deleteValue
  27. // @grant GM_getResourceText
  28. // @grant GM_getValue
  29. // @grant GM_registerMenuCommand
  30. // @grant GM_setValue
  31. // ==/UserScript==
  32.  
  33. (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const n=document.createElement("style");n.textContent=t,document.head.append(n)})(" h2[data-v-6b5a9c54]{color:#000!important;margin:10px 0!important;font-size:20px!important}.m-setting-button[data-v-3d821394]{position:fixed;top:200px;right:0;z-index:100000}.m-button[data-v-3d821394]{margin-left:16px!important;padding:5px!important;font-size:14px!important}.processs-flex[data-v-3d821394]{display:flex;justify-content:center;align-items:center}.m-setting-button[data-v-6868725a]{position:fixed;top:200px;right:0;z-index:100000}.m-button[data-v-6868725a]{margin-left:16px!important;padding:5px!important;font-size:14px!important}.processs-flex[data-v-6868725a]{display:flex;justify-content:center;align-items:center} ");
  34.  
  35. (function (ElementPlus, vue) {
  36. 'use strict';
  37.  
  38. var _GM_addStyle = /* @__PURE__ */ (() => typeof GM_addStyle != "undefined" ? GM_addStyle : void 0)();
  39. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  40. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  41. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  42. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  43. let Cache$1 = class Cache2 {
  44. set(k, v) {
  45. _GM_setValue(k, v);
  46. }
  47. get(k, parse = true, name = String.name) {
  48. try {
  49. let v = _GM_getValue(k);
  50. switch (name) {
  51. case String.name:
  52. if (v == null) {
  53. return "null";
  54. }
  55. return v;
  56. case Object.name:
  57. if (v == null || v == void 0 || typeof v != "object") {
  58. return {};
  59. }
  60. return v;
  61. case Boolean.name:
  62. if (v === null || v == void 0) {
  63. return false;
  64. }
  65. if (v == false || v == "false" || v == "" || v == "null") {
  66. return false;
  67. }
  68. return v;
  69. case Array.name:
  70. if (v === null || v == void 0 || !Array.isArray(v)) {
  71. return [];
  72. }
  73. return v;
  74. default:
  75. return v;
  76. }
  77. } catch (E) {
  78. return null;
  79. }
  80. }
  81. remove(k) {
  82. _GM_deleteValue(k);
  83. }
  84. };
  85. const Cache$2 = new Cache$1();
  86. function isEnglishENV() {
  87. return window.location.href.indexOf("https://leetcode.com") != -1;
  88. }
  89. const isHttp = (url) => /^https?:\/\/.*$/.test(url);
  90. const isLeetCodeCircleUrl = (url = window.location.href) => /^https?:\/\/leetcode\.(com|cn).*\/discuss\/.*/i.test(url);
  91. const isProblem = (url = window.location.href) => /^https?:\/\/leetcode\.(com|cn)\/problems\/.*/i.test(url);
  92. const isContest = (url = window.location.href) => /^https?:\/\/leetcode\.(com|cn)\/contest\/.*\/problems\/.*/.test(url);
  93. const isBilibili = (url = window.location.href) => /.*bilibili.*/.test(url);
  94. const isHome = () => window.location.href == "https://leetcode.cn/" || window.location.href == "https://leetcode.com/";
  95. const isZH = (url = window.location.href) => /^https?:\/\/leetcode\.cn/.test(url);
  96. const sleep = async (time = 500) => new Promise((resolove) => setTimeout(resolove, time));
  97. const EN_URL = "https://leetcode.com";
  98. const ZH_URL = "https://leetcode.cn";
  99. const LC_COPY_HTML_PLUGIN = "https://gf.qytechs.cn//zh-CN/scripts/491969-lc-to-markdown-txt-html";
  100. const EN_SOLUTION_DEMO = "https://leetcode.com/discuss/interview-question/6032972/leetcode";
  101. const CUR_URL = isEnglishENV() ? EN_URL : ZH_URL;
  102. const isDev = () => JSON.parse("false");
  103. const width = 14;
  104. const height = 14;
  105. const svg_css_style = () => isNewUI() ? "display:inline;margin-bottom:3px;" : "";
  106. const bilibiliSVG = () => {
  107. return `<svg width="${width}px" height="${height}px" style="${svg_css_style()}" status="bilibili" title="bilibili" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#00a3d9">
  108. <path fill="none" d="M0 0h24v24H0z"></path>
  109. <path d="M18.223 3.086a1.25 1.25 0 0 1 0 1.768L17.08 5.996h1.17A3.75 3.75 0 0 1 22 9.747v7.5a3.75 3.75 0 0 1-3.75 3.75H5.75A3.75 3.75 0 0 1 2 17.247v-7.5a3.75 3.75 0 0 1 3.75-3.75h1.166L5.775 4.855a1.25 1.25 0 1 1 1.767-1.768l2.652 2.652q.119.119.198.257h3.213q.08-.14.199-.258l2.651-2.652a1.25 1.25 0 0 1 1.768 0m.027 5.42H5.75a1.25 1.25 0 0 0-1.247 1.157l-.003.094v7.5c0 .659.51 1.199 1.157 1.246l.093.004h12.5a1.25 1.25 0 0 0 1.247-1.157l.003-.093v-7.5c0-.69-.56-1.25-1.25-1.25zm-10 2.5c.69 0 1.25.56 1.25 1.25v1.25a1.25 1.25 0 1 1-2.5 0v-1.25c0-.69.56-1.25 1.25-1.25m7.5 0c.69 0 1.25.56 1.25 1.25v1.25a1.25 1.25 0 1 1-2.5 0v-1.25c0-.69.56-1.25 1.25-1.25"></path>
  110. </svg>
  111. `;
  112. };
  113. const problemContenst = () => `
  114. <svg width="${width}px" height="${height}px" style="${svg_css_style()}" status="contest" title="竞赛题目专属图标" viewBox="-3.5 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
  115. <path d="M9.73795 18.8436L12.9511 20.6987L6.42625 32L4.55349 27.8233L9.73795 18.8436Z" fill="#CE4444"/>
  116. <path d="M9.73795 18.8436L6.52483 16.9885L0 28.2898L4.55349 27.8233L9.73795 18.8436Z" fill="#983535"/>
  117. <path d="M14.322 18.8436L11.1088 20.6987L17.6337 32L19.5064 27.8233L14.322 18.8436Z" fill="#983535"/>
  118. <path d="M14.322 18.8436L17.5351 16.9885L24.0599 28.2898L19.5064 27.8233L14.322 18.8436Z" fill="#CE4444"/>
  119. <path d="M22.9936 11.0622C22.9936 17.1716 18.0409 22.1243 11.9314 22.1243C5.82194 22.1243 0.869249 17.1716 0.869249 11.0622C0.869249 4.9527 5.82194 0 11.9314 0C18.0409 0 22.9936 4.9527 22.9936 11.0622Z" fill="url(#paint0_linear_103_1801)"/>
  120. <path d="M20.5665 11.0621C20.5665 15.8311 16.7004 19.6972 11.9315 19.6972C7.16247 19.6972 3.29645 15.8311 3.29645 11.0621C3.29645 6.29315 7.16247 2.42713 11.9315 2.42713C16.7004 2.42713 20.5665 6.29315 20.5665 11.0621Z" fill="#A88300"/>
  121. <path d="M21.0477 11.984C21.0477 16.7641 17.1727 20.6391 12.3926 20.6391C7.61251 20.6391 3.73748 16.7641 3.73748 11.984C3.73748 7.20389 7.61251 3.32887 12.3926 3.32887C17.1727 3.32887 21.0477 7.20389 21.0477 11.984Z" fill="#C28B37"/>
  122. <path d="M20.5868 11.0621C20.5868 15.8422 16.7118 19.7172 11.9317 19.7172C7.15159 19.7172 3.27656 15.8422 3.27656 11.0621C3.27656 6.28205 7.15159 2.40702 11.9317 2.40702C16.7118 2.40702 20.5868 6.28205 20.5868 11.0621Z" fill="#C09525"/>
  123. <path d="M11.9781 5.04096L13.8451 8.77502L17.5792 9.24178L15.0151 12.117L15.7122 16.2431L11.9781 14.3761L8.24404 16.2431L8.94729 12.117L6.37701 9.24178L10.1111 8.77502L11.9781 5.04096Z" fill="url(#paint1_linear_103_1801)"/>
  124. <defs>
  125. <linearGradient id="paint0_linear_103_1801" x1="11.1804" y1="4.03192" x2="12.6813" y2="31.965" gradientUnits="userSpaceOnUse">
  126. <stop stop-color="#FFC600"/>
  127. <stop offset="1" stop-color="#FFDE69"/>
  128. </linearGradient>
  129. <linearGradient id="paint1_linear_103_1801" x1="11.9783" y1="5.04096" x2="11.9783" y2="16.2431" gradientUnits="userSpaceOnUse">
  130. <stop stop-color="#FFFCDD"/>
  131. <stop offset="1" stop-color="#FFE896"/>
  132. </linearGradient>
  133. </defs>
  134. </svg>
  135.  
  136. `;
  137. const problemFinsh = () => `
  138.  
  139. <svg width="${width}px" height="${height}px" style="${svg_css_style()}" status="ac" title="AC专属图标" viewBox="0 0 1024 1024" version="1.1"
  140. xmlns="http://www.w3.org/2000/svg">
  141. <path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#4CAF50" />
  142. <path
  143. d="M738.133333 311.466667L448 601.6l-119.466667-119.466667-59.733333 59.733334 179.2 179.2 349.866667-349.866667z"
  144. fill="#CCFF90" />
  145. </svg>
  146.  
  147. `;
  148. const problemsTry = () => `
  149. <svg width="${width}px" height="${height}px" style="${svg_css_style()}" status="notac" title="尝试过" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
  150. xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
  151. style="enable-background:new 0 0 512 512;" xml:space="preserve">
  152. <path style="fill:#FEDEA1;" d="M256,12.8C121.899,12.8,12.8,121.899,12.8,256S121.899,499.2,256,499.2S499.2,390.101,499.2,256
  153. S390.101,12.8,256,12.8z" />
  154. <g>
  155. <path style="fill:#573A32;" d="M256,115.2c-49.271,0-92.561,25.353-117.726,63.676l18.859,18.859
  156. C177.178,163.806,213.734,140.8,256,140.8c63.625,0,115.2,51.567,115.2,115.2h-38.4l51.2,51.2l51.2-51.2h-38.4
  157. C396.8,178.244,333.764,115.2,256,115.2z" />
  158. <path style="fill:#573A32;" d="M256,0C114.62,0,0,114.62,0,256s114.62,256,256,256s256-114.62,256-256S397.38,0,256,0z M256,486.4
  159. C128.956,486.4,25.6,383.044,25.6,256S128.956,25.6,256,25.6S486.4,128.956,486.4,256S383.044,486.4,256,486.4z" />
  160. <path style="fill:#573A32;" d="M256,371.2c-63.625,0-115.2-51.567-115.2-115.2h38.4L128,204.8L76.8,256h38.4
  161. c0,77.756,63.036,140.8,140.8,140.8c49.272,0,92.561-25.353,117.726-63.676l-18.859-18.859
  162. C334.822,348.194,298.266,371.2,256,371.2z" />
  163. </g>
  164. </svg>
  165.  
  166. `;
  167. const resetSVG = (size = 20) => `
  168. <svg width="${size}px" height="${size}px" style="${svg_css_style()} 'cursor':'pointer'; " viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" transform="translate(2 2)"><path d="m4.5 1.5c-2.4138473 1.37729434-4 4.02194088-4 7 0 4.418278 3.581722 8 8 8s8-3.581722 8-8-3.581722-8-8-8"/><path d="m4.5 5.5v-4h-4"/></g></svg>
  169.  
  170. `;
  171. const updateSVG = (size = 20) => `
  172. <svg width="${size}px" height="${size}px" style="${svg_css_style()} 'cursor':'pointer'; " viewBox="0 0 17 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  173. <path d="M16.592 1.152c-0.053-0.010-1.321-0.244-2.981-0.244-2.105 0-3.828 0.366-5.125 1.088-1.518-0.765-3.264-1.152-5.196-1.152-1.681 0-2.866 0.302-2.915 0.315l-0.375 0.098 0.001 13.906 0.624-0.161c0.011-0.002 1.12-0.283 2.665-0.283 1.447 0 2.771 0.24 3.96 0.703v0.828h2.5v-0.856c1.281-0.488 2.747-0.611 3.86-0.611 1.562 0 2.786 0.225 2.798 0.227l0.592 0.11v-13.891l-0.408-0.077zM1 13.907v-11.858c0.451-0.084 1.277-0.205 2.29-0.205 1.761 0 3.339 0.36 4.71 1.044v11.776c-1.403-0.617-2.977-0.945-4.71-0.945-0.969 0-1.773 0.101-2.29 0.188zM16 13.938c-0.536-0.070-1.393-0.154-2.39-0.154-1.848 0-3.381 0.298-4.61 0.855v-11.773c1.422-0.78 3.271-0.958 4.61-0.958 1.023 0 1.902 0.097 2.39 0.164v11.866z" fill="#121212" />
  174. </svg>
  175. `;
  176. const problemsNo = () => install_pos() ? `
  177. <svg width="${width}px" height="${height}px" style="${svg_css_style()}" status="null" title="未尝试" viewBox="0 0 24 24" id="meteor-icon-kit__regular-circle" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0C18.6274 0 24 5.37258 24 12Z" fill="#758CA3"/></svg>
  178. ` : ``;
  179. const createStatus = (status, link, removeSvg = false) => {
  180. var _a;
  181. let node;
  182. if (!link) {
  183. return;
  184. }
  185. const curUrl = (link == null ? void 0 : link.href) ?? ((_a = link.querySelector("a")) == null ? void 0 : _a.href);
  186. node = link instanceof HTMLAnchorElement ? link.parentElement : link;
  187. if (node) {
  188. node.status = status;
  189. }
  190. if (removeSvg) {
  191. let svg2 = node.querySelector("svg");
  192. if (svg2) {
  193. svg2.remove();
  194. }
  195. }
  196. let installSVG = "";
  197. if (isContest(curUrl)) {
  198. installSVG = problemContenst();
  199. } else if (isLeetCodeCircleUrl(curUrl)) ;
  200. else if (isBilibili(curUrl)) {
  201. installSVG = bilibiliSVG();
  202. } else {
  203. if (status == STATUS["AC"]) {
  204. installSVG = problemFinsh();
  205. } else if (status == STATUS["notac"]) {
  206. installSVG = problemsTry();
  207. } else if (status == STATUS["NO"]) {
  208. installSVG = problemsNo();
  209. }
  210. }
  211. let svg = node.querySelector("svg");
  212. if (svg) {
  213. if (svg.getAttribute("status") == status || svg.getAttribute("status") == STATUS["AC"]) {
  214. return false;
  215. }
  216. svg.remove();
  217. }
  218. if (isBilibili(curUrl)) {
  219. node.innerHTML = node.innerHTML + "&nbsp;" + installSVG;
  220. } else {
  221. node.innerHTML = install_pos() ? installSVG + node.innerHTML : node.innerHTML + installSVG;
  222. }
  223. return true;
  224. };
  225. function Message(title = "确认操作", callback = () => {
  226. }, canlcelCallback = () => {
  227. }) {
  228. ElementPlus.ElMessageBox.confirm(
  229. `${title} ?`,
  230. "警告",
  231. {
  232. confirmButtonText: "确认",
  233. cancelButtonText: "取消",
  234. type: "warning"
  235. }
  236. ).then(() => {
  237. callback();
  238. }).catch(() => {
  239. ElementPlus.ElMessage({
  240. type: "info",
  241. message: "已取消"
  242. });
  243. canlcelCallback();
  244. });
  245. }
  246. function tips_message() {
  247. if (isEnglish() && isZH() && Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type_tips__"]) == "OK") {
  248. ElementPlus.ElMessageBox.alert(
  249. `<div>
  250. <p>检查到当前环境为国服,如果需要同步功能需要切换到美服,或者复制一份题单到美服自己使用 否则仅保留替换链接功能,没有同步功能 </p>
  251. <ul>
  252. <li>你可以使用<a style="color:blue;" target="_blank" href="${LC_COPY_HTML_PLUGIN}">lc-to-markdown-txt-html</a> 来复制题单 </li>
  253. <li><a style="color:red;" target="_blank" href="${EN_SOLUTION_DEMO}">查看美服题单示例</a> </li>
  254. <ul>
  255. <div>`,
  256. "提示",
  257. {
  258. dangerouslyUseHTMLString: true,
  259. showCancelButton: true,
  260. cancelButtonText: "下次再说",
  261. confirmButtonText: "不再提示"
  262. }
  263. ).then((e) => {
  264. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type_tips__"], "NO");
  265. }).catch((e) => {
  266. if (e == "cancel") {
  267. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type_tips__"]) == "OK_1";
  268. ElementPlus.ElMessage.warning({
  269. message: "下次切换到美服环境提示"
  270. });
  271. }
  272. });
  273. }
  274. }
  275. function update_version() {
  276. _GM_registerMenuCommand(`更新脚本🔗`, () => {
  277. ElementPlus.ElMessageBox.alert(
  278. `<div>
  279. <p>📣 提示:最近油猴需要科学工具才能访问,如果你使用油猴,可以到脚本猫中找到源代码,复制覆盖当前脚本也能更新 </p>
  280. <br/>
  281. <p><a style="color:blue;" target="_blank" href="https://scriptcat.org/zh-CN/script-show-page/1967/"> 脚本猫🐱 </a></p>
  282. <p><a style="color:blue;" target="_blank" href="https://gf.qytechs.cn//zh-CN/scripts/501134-0x3f-problem-solution"> 油猴🐒 </a>【需要科学工具访问】</p>
  283. <p><a style="color:blue;" target="_blank" href="https://gfork.dahi.icu/zh-CN/scripts/501134/"> 油猴镜像🐒 </a> 【不保证镜像存在】</p>
  284. <p><a style="color:blue;" target="_blank" href="https://github.com/wuxin0011/tampermonkey-script/blob/main/0x3f-leetcode/dist/0x3f-leetcode-problems.js"> github 源代码更新 </a> 【最直接方式】</p>
  285. <div>`,
  286. "更新☕",
  287. {
  288. dangerouslyUseHTMLString: true,
  289. showCancelButton: true,
  290. cancelButtonText: "取消",
  291. confirmButtonText: "确认"
  292. }
  293. );
  294. }, { title: "点击更新更新脚本" });
  295. }
  296. function stop_disscuss_command() {
  297. if (isLeetCodeCircleUrl()) {
  298. let is_stop = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_stop_discuss_"], true, String.name);
  299. is_stop = is_stop != "false" && is_stop != false;
  300. if (is_stop) {
  301. _GM_addStyle(".t6Fde{ display:none !important;}");
  302. }
  303. if (isDev()) {
  304. console.log("is_stop ", is_stop);
  305. }
  306. _GM_registerMenuCommand(`${is_stop ? "开启" : "关闭"}右侧讨论区📣`, () => {
  307. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_stop_discuss_"], !is_stop);
  308. window.location.reload();
  309. }, { title: "如果认为右侧讨论区太难看可以直接屏蔽😅" });
  310. }
  311. }
  312. const inf = 5e3;
  313. const mi = 800;
  314. const __0X3F_PROBLEM_KEYS__$1 = {
  315. "__0x3f_problmes_solution__": "__0x3f_problmes_solution__",
  316. // 基本信息
  317. "__0x3f_problmes_urls__": "__0x3f_problmes_urls__",
  318. // 题单key
  319. "__0x3f_problmes_update__": "__0x3f_problmes_update__",
  320. // 是否修改了默认题单key
  321. "__0x3f_problmes_button_is_none__": "__is_none_0x3f_problmes_button__",
  322. // 是否隐藏设置按钮
  323. "__0x3f_problmes_insert_pos__": "__0x3f_problmes_insert_pos__",
  324. // 安装位置
  325. "__0x3f_problmes_status_update__": "__0x3f_problmes_status_update__",
  326. "__0x3f_problmes_plugin_load_ok__": "__0x3f_problmes_plugin_load_ok__",
  327. // 是否使用插件
  328. "__0x3f_problmes_add_cur__": "__0x3f_problmes_add_cur__",
  329. // 添加 url
  330. "__0x3f_problmes_ac_key__": "__local_ok_problem_key__",
  331. // ac key
  332. "__0x3f_problmes_ac_version__": "__0x3f_problmes_ac_version__",
  333. // TODO ac key version
  334. "__0x3f_problmes_all_problems__": "__0x3f_problmes_all_problems__",
  335. // all problems
  336. "__0x3f_problmes_random_problems_key__": "__0x3f_problmes_random_problems_key__",
  337. //随机题目快捷键
  338. "__0x3f_problmes_random_problems__": "__0x3f_problmes_random_problems__",
  339. //随机题目
  340. "__0x3f_problme_support_type__": "__0x3f_problme_support_type__",
  341. //是否替换到com 默认cn
  342. "__0x3f_problme_support_type_tips__": "__0x3f_problme_support_type_tips__",
  343. //是否替换到com 默认cn 不再提示key
  344. "__0x3f_problme_stop_discuss_": "__0x3f_problme_default_stop_discuss_",
  345. //屏蔽讨论区 默认屏蔽
  346. "__0x3f_problme_score_": "__0x3f_problme_score_",
  347. // 显示题目分数 默认不显示
  348. "__0x3f_problme_score_tot_key": "__0x3f_problme_score_tot_key",
  349. // 题目分数 缓存
  350. "__0x3f_problme_rating": "__0x3f_problme_rating"
  351. // 0神分数rating
  352. };
  353. const STATUS = {
  354. "AC": "ac",
  355. "NO": "null",
  356. "notac": "notac",
  357. "Accepted": "ac",
  358. "Wrong Answer": "notac"
  359. };
  360. const defaultUrls = [
  361. { "title": "数学算法(数论/组合/概率期望/博弈/计算几何/随机算法", "link": "https://leetcode.cn/discuss/post/3584388/fen-xiang-gun-ti-dan-shu-xue-suan-fa-shu-gcai/", "tot": 0, "ac": 0, "id": 1, "disabled": false, "select": true, "version": 1 },
  362. { "title": "常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)", "link": "https://leetcode.cn/discuss/post/3583665/fen-xiang-gun-ti-dan-chang-yong-shu-ju-j-bvmv/", "tot": 0, "ac": 0, "id": 2, "disabled": false, "select": true, "version": 1 },
  363. { "title": "动态规划(入门/背包/状态机/划分/区间/状压/数位/树形/数据结构优化)", "link": "https://leetcode.cn/discuss/post/3581838/fen-xiang-gun-ti-dan-dong-tai-gui-hua-ru-007o/", "tot": 0, "ac": 0, "id": 3, "disabled": false, "select": true, "version": 1 },
  364. { "title": "图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)", "link": "https://leetcode.cn/discuss/post/3581143/fen-xiang-gun-ti-dan-tu-lun-suan-fa-dfsb-qyux/", "tot": 0, "ac": 0, "id": 4, "disabled": false, "select": true, "version": 1 },
  365. { "title": "位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)", "link": "https://leetcode.cn/discuss/post/3580371/fen-xiang-gun-ti-dan-wei-yun-suan-ji-chu-nth4/", "tot": 0, "ac": 0, "id": 5, "disabled": false, "select": true, "version": 1 },
  366. { "title": "网格图(DFS/BFS/综合应用)", "link": "https://leetcode.cn/discuss/post/3580371/fen-xiang-gun-ti-dan-wei-yun-suan-ji-chu-nth4/", "tot": 0, "ac": 0, "id": 6, "disabled": false, "select": true, "version": 1 },
  367. { "title": "单调栈(矩形面积/贡献法/最小字典序", "link": "https://leetcode.cn/discuss/post/3579480/ti-dan-dan-diao-zhan-ju-xing-xi-lie-zi-d-u4hk/", "tot": 0, "ac": 0, "id": 7, "disabled": false, "select": true, "version": 1 },
  368. { "title": "二分算法(二分答案/最小化最大值/最大化最小值/第K小", "link": "https://leetcode.cn/discuss/post/3579164/ti-dan-er-fen-suan-fa-er-fen-da-an-zui-x-3rqn/", "tot": 0, "ac": 0, "id": 8, "disabled": true, "select": true, "version": 1 },
  369. { "title": "滑动窗口(定长/不定长/多指针", "link": "https://leetcode.cn/discuss/post/3578981/ti-dan-hua-dong-chuang-kou-ding-chang-bu-rzz7/", "tot": 0, "ac": 0, "id": 9, "disabled": false, "select": true, "version": 1 },
  370. { "title": "贪心算法(基本贪心策略/反悔/区间/字典序/数学/思维/构造)", "link": "https://leetcode.cn/discuss/post/3091107/fen-xiang-gun-ti-dan-tan-xin-ji-ben-tan-k58yb/", "tot": 0, "ac": 0, "id": 10, "disabled": false, "select": true, "version": 1 },
  371. { "title": "链表、二叉树与一般树(前后指针/快慢指针/DFS/BFS/直径/LCA)", "link": "https://leetcode.cn/discuss/post/3142882/fen-xiang-gun-ti-dan-lian-biao-er-cha-sh-6srp/", "tot": 0, "ac": 0, "id": 11, "disabled": false, "select": true, "version": 1 },
  372. { "title": "字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)", "link": "https://leetcode.cn/discuss/post/3144832/fen-xiang-gun-ti-dan-zi-fu-chuan-kmpzhan-ugt4/", "tot": 0, "ac": 0, "id": 12, "disabled": false, "select": true, "version": 1 }
  373. // { 'title': '灵茶题单完成情况', 'link': 'https://leetcode.cn/u/endlesscheng/', 'tot': 0, 'ac': 0, 'id': 0x3f3f3f3f,'disabled':true,'select':false },
  374. ];
  375. const old_url_map = {
  376. "https://leetcode.cn/circle/discuss/IYT3ss/": "https://leetcode.cn/discuss/post/3584388/fen-xiang-gun-ti-dan-shu-xue-suan-fa-shu-gcai/",
  377. "https://leetcode.cn/circle/discuss/mOr1u6/": "https://leetcode.cn/discuss/post/3583665/fen-xiang-gun-ti-dan-chang-yong-shu-ju-j-bvmv/",
  378. "https://leetcode.cn/circle/discuss/tXLS3i/": "https://leetcode.cn/discuss/post/3581838/fen-xiang-gun-ti-dan-dong-tai-gui-hua-ru-007o/",
  379. "https://leetcode.cn/circle/discuss/01LUak/": "https://leetcode.cn/discuss/post/3581143/fen-xiang-gun-ti-dan-tu-lun-suan-fa-dfsb-qyux/",
  380. "https://leetcode.cn/circle/discuss/dHn9Vk/": "https://leetcode.cn/discuss/post/3580371/fen-xiang-gun-ti-dan-wei-yun-suan-ji-chu-nth4/",
  381. "https://leetcode.cn/circle/discuss/YiXPXW/": "https://leetcode.cn/discuss/post/3580195/fen-xiang-gun-ti-dan-wang-ge-tu-dfsbfszo-l3pa/",
  382. "https://leetcode.cn/circle/discuss/9oZFK9/": "https://leetcode.cn/discuss/post/3579480/ti-dan-dan-diao-zhan-ju-xing-xi-lie-zi-d-u4hk/",
  383. "https://leetcode.cn/circle/discuss/SqopEo/": "https://leetcode.cn/discuss/post/3579164/ti-dan-er-fen-suan-fa-er-fen-da-an-zui-x-3rqn/",
  384. "https://leetcode.cn/circle/discuss/0viNMK/": "https://leetcode.cn/discuss/post/3578981/ti-dan-hua-dong-chuang-kou-ding-chang-bu-rzz7/",
  385. "https://leetcode.cn/circle/discuss/g6KTKL/": "https://leetcode.cn/discuss/post/3091107/fen-xiang-gun-ti-dan-tan-xin-ji-ben-tan-k58yb/",
  386. "https://leetcode.cn/circle/discuss/K0n2gO/": "https://leetcode.cn/discuss/post/3142882/fen-xiang-gun-ti-dan-lian-biao-er-cha-sh-6srp/",
  387. "https://leetcode.cn/circle/discuss/SJFwQI/": "https://leetcode.cn/discuss/post/3144832/fen-xiang-gun-ti-dan-zi-fu-chuan-kmpzhan-ugt4/"
  388. };
  389. const defaultObj = {
  390. min: mi,
  391. max: inf,
  392. visiableMember: true,
  393. onlyUrls: false,
  394. useDefaultSetting: true,
  395. hiddenAc: false,
  396. showAcConfig: true,
  397. sortedType: 0
  398. };
  399. function install_pos() {
  400. return !Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_insert_pos__"], false, Boolean.name);
  401. }
  402. function isShow(text, min, max) {
  403. if (!text) {
  404. return true;
  405. }
  406. let res = text.match(/\d+/ig);
  407. if (!res) {
  408. return true;
  409. }
  410. if (Array.isArray(res) && res.length < 2) {
  411. return true;
  412. }
  413. let s = 0;
  414. for (let i = res.length - 1; i >= 0; i--) {
  415. s = res[i];
  416. if (s >= mi && s <= inf) {
  417. return s >= min && s <= max;
  418. }
  419. }
  420. return true;
  421. }
  422. let A = void 0;
  423. const isNewUI = () => !document.querySelector(isEnglishENV() ? ".discuss-markdown-container" : '#lc-content [class*="CollapsibleMarkdownContent"] [class*="MarkdownContent"]');
  424. const linkCssSelector_pre = () => {
  425. if (isEnglishENV()) {
  426. return isNewUI() ? ".break-words" : ".discuss-markdown-container";
  427. }
  428. return isNewUI() ? ".break-words" : `#lc-content [class*="CollapsibleMarkdownContent"] [class*="MarkdownContent"]`;
  429. };
  430. const linkCssSelector = `${linkCssSelector_pre()} li>a`;
  431. const queryProblem = () => Array.from(document.querySelectorAll(linkCssSelector)).filter((item) => item && item instanceof HTMLAnchorElement && (isProblem(item.href) || isContest(item.href)));
  432. function loadProblems() {
  433. A = queryProblem();
  434. return A;
  435. }
  436. function handlerProblem(data) {
  437. var _a;
  438. try {
  439. loadProblems();
  440. let { min, max, visiableMember, useDefaultSetting, onlyUrls, hiddenAc } = data;
  441. if (isNaN(min) || isNaN(max)) {
  442. min = mi;
  443. max = inf;
  444. }
  445. if (min < mi) {
  446. min = mi;
  447. }
  448. if (max < min) {
  449. max = inf;
  450. }
  451. min = Number(min);
  452. max = Number(max);
  453. data.min = min;
  454. data.max = max;
  455. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_solution__"], data);
  456. const cache = getLocalProblemStatus();
  457. if (isDev()) {
  458. console.log("data", data.hiddenAc);
  459. }
  460. for (let i = 0; i < A.length; i++) {
  461. if (!(A[i] instanceof HTMLAnchorElement)) {
  462. continue;
  463. }
  464. let d = (_a = A[i]) == null ? void 0 : _a.parentNode;
  465. if (!d) {
  466. continue;
  467. }
  468. let Nohidden = isShow(d.textContent, min, max);
  469. d.style.display = Nohidden ? "" : "none";
  470. if (!Nohidden) {
  471. continue;
  472. }
  473. if (hiddenAc) {
  474. const a = d.querySelector("a");
  475. const svg = d.querySelector("svg");
  476. d.style.display = a && a.href && STATUS["AC"] == cache[getId(a.href)] || svg && svg.getAttribute("status") && svg.getAttribute("status") == STATUS["AC"] ? "none" : "";
  477. } else {
  478. d.style.display = "";
  479. }
  480. let c = d.textContent && d.textContent.indexOf("会员") != -1;
  481. if (!c) {
  482. continue;
  483. }
  484. d.style.display = visiableMember ? "" : "none";
  485. }
  486. } catch (e) {
  487. console.log("error", e);
  488. }
  489. }
  490. function computeAcInfo(saveUrls = [], deleteOk = true) {
  491. let infos = [];
  492. let set = /* @__PURE__ */ new Set();
  493. for (let i = 0, u = null; Array.isArray(saveUrls) && i < saveUrls.length; i++) {
  494. try {
  495. u = saveUrls[i];
  496. if (!(u == null ? void 0 : u.link) || !(u == null ? void 0 : u.title) || !(u == null ? void 0 : u.id) || set.has(u.link)) {
  497. continue;
  498. }
  499. if (u["select"] == void 0) u.select = true;
  500. if (u["loading"] == void 0 || u["loading"]) u["loading"] = false;
  501. let s = Object.values(u).join("");
  502. if (s == "null" || !Cache$2.get(u.link) || !getAcCountKey(u.link) || !Cache$2.get(getAcCountKey(u.link))) {
  503. continue;
  504. }
  505. let o = Cache$2.get(getAcCountKey(u.link));
  506. u["ac"] = isNaN(o["ac"]) ? 0 : parseInt(o["ac"]);
  507. u["tot"] = isNaN(o["tot"]) ? 0 : parseInt(o["tot"]);
  508. u["version"] = isNaN(u["version"]) ? 1 : parseInt(u["version"]);
  509. set.add(u.link);
  510. } catch (e) {
  511. }
  512. infos.push(Object.assign({}, u));
  513. }
  514. if (deleteOk) {
  515. for (let i = 0; i < saveUrls[i]; i++) {
  516. delete saveUrls[i];
  517. }
  518. for (let info of infos) {
  519. saveUrls.push(info);
  520. }
  521. }
  522. if (isDev()) {
  523. console.log("{{ scope.row }}", infos);
  524. }
  525. return infos;
  526. }
  527. const initUrls = () => {
  528. var _a;
  529. let saveUrls = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_update__"], true, Boolean.name) ? Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], true, Array.name) : defaultUrls;
  530. for (let i = 0; i < saveUrls.length; i++) {
  531. if (((_a = saveUrls[i]) == null ? void 0 : _a.link) && old_url_map[`${saveUrls[i].link}`]) {
  532. saveUrls[i].link = old_url_map[saveUrls[i].link];
  533. }
  534. }
  535. return computeAcInfo(saveUrls);
  536. };
  537. const initObj = () => {
  538. let obj = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_solution__"]) ? Object.assign(defaultObj, Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_solution__"])) : defaultObj;
  539. if (obj["showAcConfig"] == null || obj["showAcConfig"] == void 0) {
  540. obj.showAcConfig = true;
  541. }
  542. if (obj["sortedType"] == null || obj["sortedType"] == void 0) {
  543. obj.sortedType = 0;
  544. }
  545. let temp = {};
  546. for (let key of Object.keys(obj)) {
  547. if (!isNaN(key) || defaultObj[`${key}`] == void 0) continue;
  548. temp[`${key}`] = obj[`${key}`];
  549. }
  550. return temp;
  551. };
  552. const support_plugins = () => {
  553. const u = initObj();
  554. if (!u || !u.onlyUrls) return true;
  555. let url = window.location.href;
  556. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  557. try {
  558. url = url.split("view")[0];
  559. } catch (e) {
  560. url = window.location.href;
  561. }
  562. }
  563. const urls = initUrls();
  564. for (let info of urls) {
  565. if (!info || !(info == null ? void 0 : info.link)) {
  566. continue;
  567. }
  568. if (info.link.indexOf(url) != -1) {
  569. return true;
  570. }
  571. }
  572. return false;
  573. };
  574. function getId(problemUrl) {
  575. if (isContest(problemUrl) || isProblem(problemUrl)) {
  576. try {
  577. return problemUrl.split("problems")[1].split("/")[1];
  578. } catch (e) {
  579. return "";
  580. }
  581. }
  582. return "";
  583. }
  584. function postData(ID2) {
  585. return {
  586. "query": "\n query userQuestionStatus($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n status\n }\n}\n ",
  587. "variables": {
  588. "titleSlug": ID2
  589. },
  590. "operationName": "userQuestionStatus"
  591. };
  592. }
  593. async function queryStatus(ID2 = "", cache = {}, cur = void 0, watch2 = false) {
  594. var _a, _b, _c;
  595. if (!ID2) {
  596. return;
  597. }
  598. if (cache[ID2] == void 0 || cache[ID2] != STATUS["AC"]) {
  599. const response = await getProblemAcInfo(ID2);
  600. if (isDev()) {
  601. console.log("query result response:", response);
  602. }
  603. if ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.question) {
  604. const status = (_c = (_b = response == null ? void 0 : response.data) == null ? void 0 : _b.question) == null ? void 0 : _c.status;
  605. if (cache[ID2] == void 0 || cache[ID2] != status) {
  606. cache[ID2] = status == null ? "null" : status;
  607. if (watch2) {
  608. if (isDev()) {
  609. console.log("save local status :", cache[ID2], "status = ", status, "get local status :", Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"])[ID2]);
  610. }
  611. watchSaveStatus(ID2, cache[ID2]);
  612. }
  613. createStatus(cache[ID2], cur);
  614. }
  615. } else {
  616. console.warn("query result is undefined");
  617. createStatus(cache[ID2], cur);
  618. }
  619. }
  620. }
  621. async function addProcess(reload = true, doms = void 0, asyncAc = false) {
  622. var _a;
  623. let problems_doms = Array.isArray(doms) ? doms : loadProblems();
  624. const cache = getLocalProblemStatus();
  625. let uid = 0, query_cnt = 0;
  626. const isReplaceEnglish = isEnglish();
  627. for (let i = 0; i < problems_doms.length; i++) {
  628. let cur = problems_doms[i].parentElement;
  629. if (!(cur instanceof HTMLElement)) {
  630. continue;
  631. }
  632. const ID2 = getId((_a = problems_doms[i]) == null ? void 0 : _a.href);
  633. if (!ID2) {
  634. continue;
  635. }
  636. if (install_pos()) {
  637. cur.style.listStyleType = "none";
  638. }
  639. if (isReplaceEnglish && problems_doms[i].href) {
  640. problems_doms[i].href = problems_doms[i].href.replace("leetcode.cn", "leetcode.com");
  641. }
  642. if (!cache[ID2] || cache[ID2] != STATUS["AC"] && asyncAc) {
  643. await sleep(20);
  644. await queryStatus(ID2, cache, cur, false);
  645. query_cnt++;
  646. if (query_cnt % 10 == 0) {
  647. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], cache);
  648. }
  649. } else {
  650. let status = cache[ID2];
  651. uid++;
  652. createStatus(status, cur);
  653. }
  654. }
  655. if (isDev()) {
  656. console.log("cache num :", uid, ",tot:", A.length);
  657. }
  658. getProcess();
  659. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], cache);
  660. let other = Array.from(document.querySelectorAll(`${linkCssSelector_pre()} p>a`)).filter((item) => item && item instanceof HTMLAnchorElement && isBilibili(item.href));
  661. for (let i = 0; i < other.length; i++) {
  662. createStatus("null", other[i]);
  663. }
  664. }
  665. const submitProblems = (url = window.location.href, timeout = 500) => {
  666. const ID2 = getId(url);
  667. if (!ID2) {
  668. return;
  669. }
  670. setTimeout(() => {
  671. const cache = getLocalProblemStatus();
  672. if (isDev()) {
  673. console.log("ID:", ID2, "query status: ", cache[ID2]);
  674. }
  675. queryStatus(ID2, cache, void 0, true);
  676. }, timeout);
  677. };
  678. const watchSaveStatus = (ID2, status) => {
  679. const cache = getLocalProblemStatus();
  680. if (cache[ID2] != "ac") {
  681. cache[ID2] = status;
  682. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], cache);
  683. window.localStorage.setItem(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_status_update__"], JSON.stringify({
  684. "id": ID2,
  685. "status": status
  686. }));
  687. }
  688. showProblemSolve();
  689. };
  690. const watchLinkStatusUpdate = (e) => {
  691. var _a;
  692. if (e.key != __0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_status_update__"]) {
  693. return;
  694. }
  695. let { id, status } = JSON.parse(e.newValue);
  696. if (!id || !status) {
  697. return;
  698. }
  699. let thisLink = `${CUR_URL}/problems/${id}`;
  700. if (isDev()) {
  701. console.log("update", thisLink, "status", status);
  702. }
  703. let link = document.querySelector(`${linkCssSelector}[href^="${CUR_URL}/problems/${id}"]`);
  704. if (!link || !(link == null ? void 0 : link.parentElement)) {
  705. let doms = loadProblems();
  706. for (let i = 0; i < doms.length; i++) {
  707. if (!doms[i] || !((_a = doms[i]) == null ? void 0 : _a.parentElement)) {
  708. continue;
  709. }
  710. if (doms[i].href.indexOf(thisLink) != -1) {
  711. link = doms[i];
  712. break;
  713. }
  714. }
  715. }
  716. createStatus(status, link);
  717. };
  718. function getAcCountKey(k) {
  719. if (!k) return "";
  720. return `0x3f_ac_key_${k}`;
  721. }
  722. async function getProcess() {
  723. var _a;
  724. loadProblems();
  725. const cache = getLocalProblemStatus();
  726. const config = initObj();
  727. const response = await githubProblem(true);
  728. const mapInfo = response[1];
  729. let cnt = 0;
  730. let tot = 0;
  731. for (let i = 0; i < A.length; i++) {
  732. let ID2 = getId(A[i].href);
  733. if (!(config == null ? void 0 : config.visiableMember) && ((_a = mapInfo.get(ID2)) == null ? void 0 : _a.member)) {
  734. continue;
  735. }
  736. if (ID2 && cache[ID2] == STATUS["AC"]) {
  737. cnt++;
  738. }
  739. tot++;
  740. }
  741. let url = window.location.href;
  742. if (A.length > 0 && getAcCountKey(url)) {
  743. Cache$2.set(getAcCountKey(url), { "tot": tot, "ac": cnt });
  744. }
  745. return [cnt, tot];
  746. }
  747. function getLocalProblemStatus() {
  748. return Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], true, Object.name);
  749. }
  750. function getRandomInfo(array) {
  751. if (!Array.isArray(array)) return void 0;
  752. return array[Math.floor(Math.random() * array.length)];
  753. }
  754. function isEnglish() {
  755. return Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type__"], Boolean.name) == true;
  756. }
  757. function changeEnglishType() {
  758. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type__"], !isEnglish());
  759. if (Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type_tips__"], String.name) != "NO") {
  760. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_support_type_tips__"], "OK");
  761. }
  762. window.location.reload();
  763. }
  764. function installEnglishLinkChangeCommand() {
  765. if (!isLeetCodeCircleUrl() || isEnglishENV()) {
  766. return;
  767. }
  768. _GM_registerMenuCommand(`题目链接切换到${isEnglish() ? "国服🎈" : "美服🌎"}`, () => {
  769. changeEnglishType();
  770. }, { title: "将题单链接替换为国服或者替换为美服" });
  771. }
  772. async function githubProblem(not_filter_member = true) {
  773. let allProbmems;
  774. if (!Array.isArray(allProbmems) || allProbmems.length == 0) {
  775. let response = await getProblemsJSON();
  776. if (Array.isArray(response)) {
  777. allProbmems = [...response];
  778. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_all_problems__"], [...response]);
  779. }
  780. if (isDev()) {
  781. console.log("response allProbmems", response, allProbmems);
  782. }
  783. } else {
  784. allProbmems = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_all_problems__"], true, Array.name);
  785. if (isDev()) {
  786. console.log("else allProbmems", allProbmems);
  787. }
  788. }
  789. if (!Array.isArray(allProbmems)) {
  790. ElementPlus.ElMessage({
  791. type: "error",
  792. message: "随机题目失败获取不到任何信息 !请如果出现这种情况,请前往 https://github.com/wuxin0011/tampermonkey-script/issues 反馈",
  793. duration: 6e3
  794. });
  795. return;
  796. }
  797. let config = initObj();
  798. let urlsData = initUrls();
  799. let set = /* @__PURE__ */ new Set();
  800. for (let info of urlsData) {
  801. if (info.link && info.select) {
  802. set.add(info.link);
  803. }
  804. }
  805. let acMap = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], true, Object.name);
  806. if (isDev()) {
  807. console.log("config and set", config, set);
  808. console.log("acMap", acMap);
  809. }
  810. let infos = [];
  811. let mapInfo = /* @__PURE__ */ new Map();
  812. let totInfo = [];
  813. for (let info of allProbmems) {
  814. if (!(info == null ? void 0 : info.problemUrl) || !set.has(info == null ? void 0 : info.problemUrl) || !Array.isArray(info.problems) || info.problems.length == 0) {
  815. continue;
  816. }
  817. if (isDev()) {
  818. console.log("check2");
  819. }
  820. let cur_infos = [];
  821. for (let i = 0; Array.isArray(info.problems) && i < info.problems.length; i++) {
  822. try {
  823. let { title, url, member, score, titleSlug: titleSlug2 } = info.problems[i];
  824. if (!url || !title) continue;
  825. if (!(config == null ? void 0 : config.visiableMember) && member || !not_filter_member && member) {
  826. continue;
  827. }
  828. let new_obj = { title, url, member, score, titleSlug: titleSlug2, "status": acMap[titleSlug2] };
  829. infos.push(new_obj);
  830. cur_infos.push(new_obj);
  831. mapInfo.set(titleSlug2, new_obj);
  832. } catch (e) {
  833. console.log("error", e);
  834. }
  835. }
  836. info.problems = cur_infos;
  837. totInfo.push(info);
  838. }
  839. return [infos, mapInfo, totInfo];
  840. }
  841. async function randomProblem() {
  842. let responseDatas = await githubProblem();
  843. let acMap = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], true, Object.name);
  844. let config = initObj();
  845. let problems = responseDatas[0];
  846. let infos = [];
  847. for (let i = 0; Array.isArray(problems) && i < problems.length; i++) {
  848. try {
  849. let { title, url, member, score, titleSlug: titleSlug2 } = problems[i];
  850. if (!url || !title) continue;
  851. if (isDev()) {
  852. }
  853. if (!(config == null ? void 0 : config.showAcConfig) && acMap[titleSlug2] == "ac") {
  854. continue;
  855. }
  856. if (!(config == null ? void 0 : config.visiableMember) && member) {
  857. continue;
  858. }
  859. if (score != 0 && (score < (config == null ? void 0 : config.min) || score > (config == null ? void 0 : config.max))) {
  860. continue;
  861. }
  862. infos.push({ title, url, member, score, titleSlug: titleSlug2, "status": acMap[titleSlug2] });
  863. } catch (e) {
  864. console.log("error", e);
  865. }
  866. }
  867. let data = getRandomInfo(infos);
  868. if (data.url && isEnglish()) {
  869. data.url = data.url.replace(ZH_URL, EN_URL);
  870. }
  871. ElementPlus.ElMessage({
  872. dangerouslyUseHTMLString: !!(data && (data == null ? void 0 : data.url) && (data == null ? void 0 : data.title)),
  873. type: (data == null ? void 0 : data.url) && (data == null ? void 0 : data.title) ? "success" : "error",
  874. message: (data == null ? void 0 : data.url) && (data == null ? void 0 : data.title) ? `<div>随机题目☕:&nbsp;<a href="${data.url}" target="_blank" style="color:#5d99f2;">${data.title}</a> ${(data == null ? void 0 : data.score) && (data == null ? void 0 : data.score) > 0 ? `&nbsp;分值${data.score}` : ""}</div>` : `没有符合条件的题目,请重新配置条件!`,
  875. duration: 6e3
  876. });
  877. }
  878. function getDom() {
  879. for (let target of ["easy", "medium", "hard"]) {
  880. let t = document.querySelector(`.gap-1 .text-difficulty-${target}`);
  881. if (t) return t;
  882. }
  883. return void 0;
  884. }
  885. async function handlerScore() {
  886. let ok = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_score_"], true, String.name);
  887. ok = ok != "false" && ok != false;
  888. _GM_registerMenuCommand(`${ok ? "关闭" : "显示"} 题目分数 🍳`, function() {
  889. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_score_"], !ok);
  890. window.location.reload();
  891. }, { title: "默认显示题目分数" });
  892. if (!ok) return;
  893. let url = window.location.href;
  894. if (!isProblem(url)) return;
  895. await sleep(1e3);
  896. let problemDom = getDom();
  897. if (!problemDom) return;
  898. let id = getId(url);
  899. let score = 0;
  900. let contestUrl = isEnglishENV() ? `https://leetcode.com/contest/` : `https://leetcode.cn/contest/`;
  901. let contestUrlFind = false;
  902. let curRating = null;
  903. try {
  904. let problemMap = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_score_tot_key"], true) ?? {};
  905. let problem = problemMap[id];
  906. if (!problem) {
  907. let p = await githubProblem(true);
  908. let new_temp = {};
  909. for (let obj of p[1]) {
  910. let k = obj[0];
  911. let v = obj[1];
  912. new_temp[k] = v;
  913. }
  914. problemMap = Object.assign({}, new_temp);
  915. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_score_tot_key"], problemMap);
  916. if (isDev()) {
  917. console.log("save __0x3f_problme_score_tot_key : 😺");
  918. }
  919. }
  920. problem = problemMap[id];
  921. score = problem == null ? void 0 : problem.score;
  922. let rating = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_rating"], true) ?? {};
  923. if (!rating[id]) {
  924. let p = await getRating();
  925. let temp = {};
  926. for (let i = 0; Array.isArray(p) && i < p.length; i++) {
  927. temp[p[i]["TitleSlug"]] = p[i];
  928. }
  929. rating = Object.assign({}, temp);
  930. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problme_rating"], rating);
  931. if (isDev()) {
  932. console.log("save __0x3f_problme_rating : 😺");
  933. }
  934. }
  935. if (rating[id]) {
  936. curRating = rating[id];
  937. contestUrlFind = true;
  938. contestUrl = contestUrl + rating[id]["ContestSlug"];
  939. if (!score) {
  940. score = Math.floor(rating[id]["Rating"]);
  941. }
  942. }
  943. } catch (e) {
  944. console.error(e);
  945. }
  946. if (isDev()) {
  947. console.log("problemDom", problemDom);
  948. console.log("score", score);
  949. }
  950. if (score != void 0 && score != null && score > 0 && problemDom) {
  951. if (contestUrlFind) {
  952. problemDom.innerHTML = `<a href="${contestUrl}" target="_blank" title="${isEnglishENV() ? curRating.ContestID_en : curRating.ContestID_zh} ${curRating.ProblemIndex}">${score}</a>`;
  953. } else {
  954. problemDom.textContent = score;
  955. }
  956. }
  957. }
  958. const LANG_LIST = [
  959. "java",
  960. "cpp",
  961. "python",
  962. "python3",
  963. "go",
  964. "javascript",
  965. "js",
  966. "c",
  967. "C",
  968. "C++",
  969. "ts",
  970. "typescript",
  971. "TypeScript",
  972. "Rust",
  973. "rust",
  974. "Go",
  975. "php",
  976. "PHP",
  977. "C#",
  978. "Python3",
  979. "Java",
  980. "Swift",
  981. "swift",
  982. "Kotion",
  983. "kotion",
  984. "dart",
  985. "Dart",
  986. "Ruby",
  987. "ruby",
  988. "scala",
  989. "Scala",
  990. "Racket",
  991. "racket",
  992. "Erlang",
  993. "erlang",
  994. "Elixir",
  995. "elixir",
  996. "Cangjie",
  997. "cangjie"
  998. ];
  999. function showProblemSolve() {
  1000. let url = window.location.href;
  1001. if (!isProblem(url)) return;
  1002. let t = document.querySelector("#qd-content .text-body.flex.flex-none.items-center");
  1003. if (isDev()) {
  1004. console.log("show", t.textContent);
  1005. }
  1006. if (!t) return;
  1007. let c = getLocalProblemStatus();
  1008. let id = getId(url);
  1009. if ((c[id] == "null" || c[id] == null) && t.textContent == "已解答") {
  1010. t.style.display = "none";
  1011. } else {
  1012. t.style.display = "inline-block";
  1013. }
  1014. }
  1015. async function resetProblemStatus(url, click) {
  1016. showProblemSolve();
  1017. function deleteAcLocalStorage(title) {
  1018. try {
  1019. let No = title.match(/\d+/)[0];
  1020. let keys = [];
  1021. for (let lang of LANG_LIST) {
  1022. keys.push(`${No}_0_${lang}`);
  1023. }
  1024. for (let key of keys) {
  1025. window.localStorage.removeItem(key);
  1026. }
  1027. } catch (_) {
  1028. }
  1029. }
  1030. async function fun(discuss_url, force = false) {
  1031. var _a;
  1032. let cache = getLocalProblemStatus();
  1033. if (isLeetCodeCircleUrl()) {
  1034. let problems_doms = loadProblems();
  1035. for (let i = 0; i < problems_doms.length; i++) {
  1036. let cur = problems_doms[i].parentElement;
  1037. if (!(cur instanceof HTMLElement)) {
  1038. continue;
  1039. }
  1040. const ID2 = getId((_a = problems_doms[i]) == null ? void 0 : _a.href);
  1041. if (!ID2) continue;
  1042. if (force) {
  1043. delete cache[ID2];
  1044. } else {
  1045. cache[ID2] = "null";
  1046. deleteAcLocalStorage(problems_doms[i].textContent);
  1047. }
  1048. }
  1049. } else {
  1050. let tot = await githubProblem();
  1051. tot = tot[0];
  1052. for (let p of tot) {
  1053. if (p["problemUrl"].indexOf(discuss_url) == -1) continue;
  1054. for (let info of p["problems"]) {
  1055. if (!(info == null ? void 0 : info.titleSlug)) continue;
  1056. let ID2 = titleSlug;
  1057. if (force) {
  1058. delete cache[ID2];
  1059. } else {
  1060. cache[ID2] = "null";
  1061. deleteAcLocalStorage(info == null ? void 0 : info.title);
  1062. }
  1063. }
  1064. break;
  1065. }
  1066. }
  1067. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], cache);
  1068. }
  1069. if (isLeetCodeCircleUrl()) {
  1070. _GM_registerMenuCommand(`重置进度 ⏱`, () => {
  1071. Message("确认重置进度?该操作不可恢复", async () => {
  1072. await fun(window.location.href, false);
  1073. window.location.reload();
  1074. });
  1075. }, { title: "如果需要重做题单,可以执行该操作" });
  1076. let tag = document.querySelector(".flex .flex-wrap.gap-1 .no-underline");
  1077. if (!tag) {
  1078. await sleep(3e3);
  1079. tag = document.querySelector(".flex .flex-wrap.gap-1 .no-underline");
  1080. }
  1081. if (tag) {
  1082. let createTag = function() {
  1083. let a = document.createElement("a");
  1084. a.className = `no-underline truncate bg-sd-accent text-sd-muted-foreground hover:text-sd-foreground dark:hover:text-sd-foreground items-center rounded-full px-2 py-1 text-xs`;
  1085. return a;
  1086. };
  1087. let p = tag.parentElement;
  1088. let reset = createTag();
  1089. reset.innerHTML = resetSVG(16);
  1090. reset.style.cursor = "pointer";
  1091. reset.title = "重置题单进度,如果需要多刷可以试试";
  1092. reset.addEventListener("click", async (e) => {
  1093. e.preventDefault();
  1094. Message("确认重置进度?该操作不可恢复", async () => {
  1095. await fun(window.location.href, false);
  1096. window.location.reload();
  1097. });
  1098. });
  1099. p.appendChild(reset);
  1100. let update = createTag();
  1101. update.innerHTML = updateSVG(16);
  1102. update.title = "强制更新题单,该操作会将历史ac记录统计其中";
  1103. update.style.cursor = "pointer";
  1104. update.addEventListener("click", async (e) => {
  1105. e.preventDefault();
  1106. Message("确认强制更新进度?", async () => {
  1107. await fun(window.location.href, true);
  1108. window.location.reload();
  1109. });
  1110. });
  1111. p.appendChild(update);
  1112. }
  1113. let dom = document.querySelector(".break-words");
  1114. if (dom) {
  1115. let get = function(index, runClear) {
  1116. var _a;
  1117. if (index + 1 >= titles.length) return;
  1118. let curCache = getLocalProblemStatus();
  1119. const currentH2 = titles[index];
  1120. const nextH2 = titles[index + 1];
  1121. const aLinks = [];
  1122. let nextSibling = currentH2.nextElementSibling;
  1123. while (nextSibling && nextSibling !== nextH2) {
  1124. if (nextSibling.tagName === "A") {
  1125. if (isProblem(nextSibling.href)) {
  1126. aLinks.push(nextSibling);
  1127. }
  1128. } else {
  1129. for (let a of Array.from(nextSibling.querySelectorAll("a") ?? { length: 0 })) {
  1130. if (a && isProblem(a.href)) {
  1131. aLinks.push(a);
  1132. }
  1133. }
  1134. }
  1135. nextSibling = nextSibling.nextElementSibling;
  1136. }
  1137. if (aLinks.length > 0 && runClear) {
  1138. for (let i = 0; i < aLinks.length; i++) {
  1139. const ID2 = getId((_a = aLinks[i]) == null ? void 0 : _a.href);
  1140. if (!ID2) continue;
  1141. curCache[ID2] = "null";
  1142. createStatus("null", aLinks[i], true);
  1143. deleteAcLocalStorage(aLinks[i].textContent);
  1144. }
  1145. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], curCache);
  1146. }
  1147. return aLinks;
  1148. };
  1149. let titles = Array.from(dom.querySelectorAll("h2"));
  1150. let uls = Array.from(dom.querySelectorAll("ul"));
  1151. if (isDev()) {
  1152. console.log("titles", titles.length, "uls", uls.length);
  1153. }
  1154. for (let i = 0; i < titles.length - 1; i++) {
  1155. let aLinks = get(i, false);
  1156. if (aLinks.length != 0) {
  1157. const span = document.createElement("span");
  1158. span.style.cursor = "pointer";
  1159. span.style.marginLeft = "20px";
  1160. span.title = `重刷《${titles[i].textContent}》章节 `;
  1161. span.addEventListener("click", () => {
  1162. Message(`确认${span.title}进度?该操作不可恢复`, () => {
  1163. get(i, true);
  1164. });
  1165. });
  1166. span.innerHTML = resetSVG(17);
  1167. titles[i].appendChild(span);
  1168. }
  1169. }
  1170. }
  1171. }
  1172. if (click) {
  1173. await fun(url, false);
  1174. }
  1175. }
  1176. async function GetHubJSONInfo(url) {
  1177. return fetch(url, {
  1178. method: "get",
  1179. mode: "cors"
  1180. }).then((res) => res.json());
  1181. }
  1182. async function getProblemsJSON() {
  1183. return GetHubJSONInfo("https://raw.githubusercontent.com/wuxin0011/tampermonkey-script/main/0x3f-leetcode/new_0x3f.json");
  1184. }
  1185. async function getRating() {
  1186. return GetHubJSONInfo("https://raw.githubusercontent.com/zerotrac/leetcode_problem_rating/main/data.json");
  1187. }
  1188. const LEETCODE_PROBLEM_API = `${CUR_URL}/graphql/`;
  1189. async function PostLeetCodeApi(data) {
  1190. return fetch(LEETCODE_PROBLEM_API, {
  1191. method: "POST",
  1192. credentials: "include",
  1193. headers: {
  1194. "Content-Type": "application/json"
  1195. },
  1196. body: JSON.stringify(data)
  1197. }).then((res) => res.json());
  1198. }
  1199. async function getProblemAcInfo(titleSlug2) {
  1200. return PostLeetCodeApi(postData(titleSlug2));
  1201. }
  1202. const _export_sfc = (sfc, props) => {
  1203. const target = sfc.__vccOpts || sfc;
  1204. for (const [key, val] of props) {
  1205. target[key] = val;
  1206. }
  1207. return target;
  1208. };
  1209. const _sfc_main$1 = {};
  1210. const _withScopeId = (n) => (vue.pushScopeId("data-v-6b5a9c54"), n = n(), vue.popScopeId(), n);
  1211. const _hoisted_1$1 = /* @__PURE__ */ vue.createStaticVNode('<h2 data-v-6b5a9c54> 🎈必读内容 </h2><ul data-v-6b5a9c54><li style="color:red !important;" data-v-6b5a9c54> 同步功能使用前请确保为登录(不可用)状态 </li></ul><h2 data-v-6b5a9c54> ❓ 题单进度不一致 </h2><ul data-v-6b5a9c54><li data-v-6b5a9c54> 防止一次性访问题单太多,对服务器产生压力,所以采用单个题单访问然后保存状态 , 这样避免访问量问题 </li><li data-v-6b5a9c54> 默认情况下会缓存访问的题单情况,对于没有访问的题单,可以手动在对应题单中同步 </li><li data-v-6b5a9c54> 题目状态根据用户提交题目情况会实时更新,只会在提交访问一次 </li></ul><h2 data-v-6b5a9c54> ❓ 如何使用随机题目? </h2><ul data-v-6b5a9c54><li data-v-6b5a9c54> 这个可以根据自己要求,配置好之后,可以使用 <em data-v-6b5a9c54> ctrl + alt + j </em> 触发 </li><li data-v-6b5a9c54> 如果这个快捷键影响,可以在命令设置中关闭 </li></ul><h2 data-v-6b5a9c54> ❓ 如何使用美服 </h2>', 7);
  1212. const _hoisted_8 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("h2", null, " 🔗 反馈更新 ", -1));
  1213. function _sfc_render(_ctx, _cache) {
  1214. const _component_el_link = vue.resolveComponent("el-link");
  1215. return vue.openBlock(), vue.createElementBlock("div", null, [
  1216. _hoisted_1$1,
  1217. vue.createElementVNode("ul", null, [
  1218. vue.createElementVNode("li", null, [
  1219. vue.createTextVNode(" 处于网络安全策略,对于不同网站请求有 "),
  1220. vue.createVNode(_component_el_link, {
  1221. underline: false,
  1222. href: "https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS",
  1223. type: "primary",
  1224. target: "_blank"
  1225. }, {
  1226. default: vue.withCtx(() => [
  1227. vue.createTextVNode("跨域机制保护")
  1228. ]),
  1229. _: 1
  1230. }),
  1231. vue.createTextVNode(" 美服和国服是两个不同网站,因此无法实现不同网站题单同步 。 ")
  1232. ]),
  1233. vue.createElementVNode("li", null, [
  1234. vue.createTextVNode(" 如果想使用美服,请复制一份题单到美服中 "),
  1235. vue.createVNode(_component_el_link, {
  1236. underline: false,
  1237. href: "https://gf.qytechs.cn//zh-CN/scripts/491969-lc-to-markdown-txt-html",
  1238. type: "primary",
  1239. target: "_blank"
  1240. }, {
  1241. default: vue.withCtx(() => [
  1242. vue.createTextVNode("lc-to-markdown-txt-html")
  1243. ]),
  1244. _: 1
  1245. }),
  1246. vue.createTextVNode(" 这个插件来复制题单 ")
  1247. ]),
  1248. vue.createElementVNode("li", null, [
  1249. vue.createVNode(_component_el_link, {
  1250. underline: false,
  1251. href: "https://leetcode.com/discuss/interview-question/6032972/leetcode",
  1252. type: "primary",
  1253. target: "_blank"
  1254. }, {
  1255. default: vue.withCtx(() => [
  1256. vue.createTextVNode("美服题单演示")
  1257. ]),
  1258. _: 1
  1259. })
  1260. ])
  1261. ]),
  1262. _hoisted_8,
  1263. vue.createElementVNode("ul", null, [
  1264. vue.createElementVNode("li", null, [
  1265. vue.createTextVNode(" 你可以在 "),
  1266. vue.createVNode(_component_el_link, {
  1267. underline: false,
  1268. href: "https://gf.qytechs.cn//zh-CN/scripts/501134-0x3f-problem-solution/feedback",
  1269. type: "success",
  1270. target: "_blank"
  1271. }, {
  1272. default: vue.withCtx(() => [
  1273. vue.createTextVNode("油猴")
  1274. ]),
  1275. _: 1
  1276. }),
  1277. vue.createTextVNode("   "),
  1278. vue.createVNode(_component_el_link, {
  1279. underline: false,
  1280. href: "https://scriptcat.org/zh-CN/script-show-page/1967",
  1281. type: "success",
  1282. target: "_blank"
  1283. }, {
  1284. default: vue.withCtx(() => [
  1285. vue.createTextVNode("脚本猫")
  1286. ]),
  1287. _: 1
  1288. }),
  1289. vue.createTextVNode(" 中更新或下载 ")
  1290. ]),
  1291. vue.createElementVNode("li", null, [
  1292. vue.createVNode(_component_el_link, {
  1293. underline: false,
  1294. href: "https://gf.qytechs.cn//zh-CN/scripts/501134-0x3f-problem-solution/feedback",
  1295. type: "primary",
  1296. target: "_blank"
  1297. }, {
  1298. default: vue.withCtx(() => [
  1299. vue.createTextVNode("点击")
  1300. ]),
  1301. _: 1
  1302. }),
  1303. vue.createTextVNode("这里反馈 或者 "),
  1304. vue.createVNode(_component_el_link, {
  1305. target: "_blank",
  1306. underline: false,
  1307. href: "https://github.com/wuxin0011/tampermonkey-script/issues",
  1308. type: "primary"
  1309. }, {
  1310. default: vue.withCtx(() => [
  1311. vue.createTextVNode("issues")
  1312. ]),
  1313. _: 1
  1314. })
  1315. ])
  1316. ])
  1317. ]);
  1318. }
  1319. const Q1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-6b5a9c54"]]);
  1320. const _hoisted_1 = { class: "dialog-footer" };
  1321. const _hoisted_2 = { class: "processs-flex" };
  1322. const _hoisted_3 = { style: { "text-align": "center", "color": "#121212" } };
  1323. const TARGET_URL = "https://leetcode.cn/u/endlesscheng/";
  1324. const formLabelWidth = "44px";
  1325. const _sfc_main = {
  1326. __name: "App",
  1327. setup(__props) {
  1328. const fromData = vue.reactive(initObj());
  1329. const tableButtonSize = vue.ref("default");
  1330. let tableData = vue.reactive(initUrls());
  1331. const keywords = vue.ref("");
  1332. const dialogTableVisible = vue.ref(false);
  1333. const showAddLocalButton = vue.computed(() => isLeetCodeCircleUrl());
  1334. let urlsData = vue.computed(() => {
  1335. let map = /* @__PURE__ */ new Map();
  1336. let infos = tableData.filter((info2) => {
  1337. if ((info2 == null ? void 0 : info2.title) && (info2 == null ? void 0 : info2.link) && !map.has(info2.link)) {
  1338. map.set(info2.link, info2);
  1339. return info2 && (info2.title && info2.title.indexOf(keywords.value) != -1 || info2.link && info2.link.indexOf(keywords.value) != -1);
  1340. } else {
  1341. return false;
  1342. }
  1343. });
  1344. let tot = 0, ac = 0;
  1345. for (let i = 0, c = info.length; i < infos.length; i++) {
  1346. let info2 = infos[i];
  1347. if (info2["ac"] && info2["tot"]) {
  1348. tot += info2["tot"];
  1349. ac += info2["ac"];
  1350. }
  1351. if (!info2["id"]) {
  1352. info2["id"] = c + 1;
  1353. c++;
  1354. }
  1355. }
  1356. let type = isNaN(fromData.sortType) ? 0 : fromData.sortType;
  1357. if (type == 0) {
  1358. infos.sort((info1, info2) => info2.id - info1.id);
  1359. } else if (type == 1) {
  1360. infos.sort((info1, info2) => info2.tot - info1.tot);
  1361. } else if (type == 2) {
  1362. infos.sort((info1, info2) => info2.ac - info1.ac);
  1363. } else if (type == 3) {
  1364. infos.sort((info1, info2) => computeProcess(info2.ac, info2.tot) - computeProcess(info1.ac, info1.tot));
  1365. }
  1366. infos.unshift({ "title": "灵茶题单完成情况", "link": TARGET_URL, "tot": tot, "ac": ac, "id": 67108863, "version": 1 });
  1367. return infos;
  1368. });
  1369. const rowIsDisabled = vue.computed(() => (info2) => asyncButtonLoad.value || info2 && info2.link == TARGET_URL);
  1370. const isDisabbled = vue.computed(() => !!tableData.find((v) => (v == null ? void 0 : v.link) && (v == null ? void 0 : v.link.indexOf(window.location.href)) != -1));
  1371. const dialogFormVisible = vue.ref(false);
  1372. const computeProcess = (ac = 0, tot = 0) => {
  1373. if (isNaN(ac) || isNaN(tot) || tot === 0) return 0;
  1374. let p = 0;
  1375. if (tot == ac) {
  1376. return 100;
  1377. }
  1378. const s = String(ac / tot);
  1379. try {
  1380. let x1 = s.split(".")[1] || "";
  1381. x1 = x1.padEnd(3, "0").substring(0, 3);
  1382. p = Math.min(100, Number(x1) / 10);
  1383. } catch (e) {
  1384. console.log("calc error", e.message, s == void 0, ac, tot);
  1385. p = (ac / tot).toFixed(3) * 100;
  1386. }
  1387. return isNaN(p) ? 0 : p;
  1388. };
  1389. const processColors = [
  1390. { color: "#f56c6c", percentage: 20 },
  1391. { color: "#1989fa", percentage: 40 },
  1392. { color: "#e6a23c", percentage: 60 },
  1393. { color: "#6f7ad3", percentage: 80 },
  1394. { color: "#67c23a", percentage: 100 }
  1395. ];
  1396. vue.watch(fromData, () => {
  1397. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  1398. });
  1399. const info = vue.reactive({
  1400. title: "",
  1401. link: "",
  1402. status: "add"
  1403. });
  1404. const addlocal = async () => {
  1405. if (!isDisabbled) {
  1406. return;
  1407. }
  1408. let [cur, tot] = await getProcess();
  1409. tableData.unshift({ title: document.title, link: window.location.href, "ac": cur, "tot": tot, "id": tableData.length + 10 });
  1410. };
  1411. const updateIndex = vue.ref(-1);
  1412. const handlerProblems = (status, updateInfo = { title: "", link: "", id: 0 }, index = -1) => {
  1413. dialogFormVisible.value = true;
  1414. info.status = status;
  1415. updateIndex.value = updateInfo.id;
  1416. Object.assign(info, updateInfo);
  1417. };
  1418. const handlerMessage = (u, title, link) => {
  1419. const a = u ? "添加" : "修改";
  1420. const error = !(!!title && isHttp(link));
  1421. if (error) {
  1422. ElementPlus.ElMessage.error(`${a} 失败 请保证标题或者链接有效 `);
  1423. } else {
  1424. ElementPlus.ElMessage.success(`${a} 成功 `);
  1425. }
  1426. return !error;
  1427. };
  1428. const addOrUpdate = () => {
  1429. if (!handlerMessage(info.status == "add", info.title, info.link)) {
  1430. return;
  1431. }
  1432. if (info.status == "add") {
  1433. tableData.unshift({ title: info.title, link: info.link, "ac": 0, "tot": 0, "id": tableData.length + 10 });
  1434. } else {
  1435. let id = updateIndex.value;
  1436. for (let i = 0; i < tableData.length; i++) {
  1437. if (tableData[i] && tableData[i].id && tableData[i]["id"] == id) {
  1438. tableData[i]["title"] = info.title;
  1439. tableData[i]["link"] = info.link;
  1440. break;
  1441. }
  1442. }
  1443. }
  1444. dialogFormVisible.value = false;
  1445. };
  1446. const deleteProblems = (id) => {
  1447. for (let i = 0; i < tableData.length; i++) {
  1448. if (tableData[i] && tableData[i].id && tableData[i]["id"] == id) {
  1449. delete tableData[i];
  1450. break;
  1451. }
  1452. }
  1453. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], vue.toRaw(tableData));
  1454. };
  1455. const handlerDefault = () => {
  1456. Message("确认使用默认题单,将会重置题单", () => {
  1457. for (let i = 0; i < tableData.length; i++) {
  1458. delete tableData[i];
  1459. }
  1460. let infos = computeAcInfo(defaultUrls);
  1461. for (let item of infos) {
  1462. tableData.unshift(item);
  1463. }
  1464. ElementPlus.ElMessage({
  1465. type: "success",
  1466. message: "重置成功"
  1467. });
  1468. });
  1469. };
  1470. window.addEventListener("beforeunload", () => {
  1471. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], vue.toRaw(tableData).filter((u) => u != null && u != void 0));
  1472. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_update__"], true);
  1473. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_add_cur__"], false);
  1474. });
  1475. vue.onMounted(async () => {
  1476. if (support_plugins()) {
  1477. let times = 30;
  1478. let loadTimeId = setInterval(() => {
  1479. let a = queryProblem();
  1480. times--;
  1481. if (Array.isArray(a) && a.length > 0) {
  1482. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  1483. addProcess();
  1484. window.clearInterval(loadTimeId);
  1485. }
  1486. if (times == 0) {
  1487. window.clearInterval(loadTimeId);
  1488. }
  1489. }, 200);
  1490. }
  1491. window.addEventListener("storage", (e) => {
  1492. watchLinkStatusUpdate(e);
  1493. });
  1494. });
  1495. _GM_registerMenuCommand(`题单配置信息🛠`, () => {
  1496. dialogTableVisible.value = !dialogTableVisible.value;
  1497. }, { title: "AC标记安装位置,默认左侧,刷新生效" });
  1498. const selectHandlerChange = (row) => {
  1499. let infos = [];
  1500. for (let i = 0; i < urlsData.value.length; i++) {
  1501. if (urlsData.value[i]["link"] == TARGET_URL) continue;
  1502. infos.push(vue.toRaw(Object.assign({}, urlsData.value[i])));
  1503. }
  1504. for (let i = 0; i < tableData.length; i++) {
  1505. if (row.id == tableData[i].id) {
  1506. tableData[i].select = row.select;
  1507. break;
  1508. }
  1509. }
  1510. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], infos);
  1511. };
  1512. const asyncButtonLoad = vue.ref(false);
  1513. const asyncButtonLoadBreak = vue.ref(false);
  1514. const showProcess = vue.ref(false);
  1515. const allProblemNum = vue.ref(0);
  1516. const asyncProblemNum = vue.ref(0);
  1517. const asyncVisableDialog = vue.ref(false);
  1518. const showProblemsProcessInfo = vue.reactive({
  1519. title: "",
  1520. link: "",
  1521. cnt: "",
  1522. ac: "",
  1523. id: "",
  1524. select: true
  1525. });
  1526. const showProblemsInfo = (info2 = {}) => {
  1527. asyncVisableDialog.value = !asyncVisableDialog.value;
  1528. Object.assign(showProblemsProcessInfo, info2);
  1529. };
  1530. const loadProcess = vue.computed(() => computeProcess(asyncProblemNum.value, allProblemNum.value));
  1531. const asyncProblemStatus = async (row = {}) => {
  1532. if (!(row == null ? void 0 : row.link)) return;
  1533. let callback = async () => {
  1534. var _a, _b, _c, _d, _e;
  1535. let rowData = void 0;
  1536. let asyncAll = (row == null ? void 0 : row.link) == TARGET_URL;
  1537. let cache = Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], true, Object.name);
  1538. if (isDev()) {
  1539. console.log("async ac cache:", cache);
  1540. }
  1541. let map = /* @__PURE__ */ new Map();
  1542. try {
  1543. for (let info2 of tableData) {
  1544. if ((info2 == null ? void 0 : info2.link) && (info2 == null ? void 0 : info2.title) && (info2 == null ? void 0 : info2.id)) {
  1545. if (rowData == void 0 && (info2 == null ? void 0 : info2.id) == row.id) {
  1546. rowData = info2;
  1547. }
  1548. if (!map.has(info2.link)) {
  1549. map.set(info2.link, info2);
  1550. }
  1551. }
  1552. }
  1553. if (rowData) {
  1554. rowData.loading = true;
  1555. }
  1556. asyncButtonLoad.value = true;
  1557. asyncButtonLoadBreak.value = false;
  1558. allProblemNum.value = 0;
  1559. asyncProblemNum.value = 0;
  1560. showProcess.value = true;
  1561. await sleep(500);
  1562. let githubInfo = await githubProblem(fromData.visiableMember);
  1563. let jsonInfo = githubInfo[2];
  1564. if (isDev()) {
  1565. console.log("githubInfo", githubInfo);
  1566. }
  1567. let datas = [];
  1568. for (let i = 0; Array.isArray(jsonInfo) && i < jsonInfo.length; i++) {
  1569. let key = `${(_a = jsonInfo[i]) == null ? void 0 : _a.problemUrl}`;
  1570. let origin = map.get(key);
  1571. if (!origin) {
  1572. continue;
  1573. }
  1574. if (asyncAll) {
  1575. for (let p of jsonInfo[i].problems) {
  1576. datas.push(Object.assign({ "origin": jsonInfo[i].problemUrl }, p));
  1577. }
  1578. origin.tot = Math.max(jsonInfo[i].problems.length, 0);
  1579. origin.ac = 0;
  1580. } else if (jsonInfo[i].problemUrl == row.link) {
  1581. for (let p of jsonInfo[i].problems) {
  1582. datas.push(Object.assign({ "origin": jsonInfo[i].problemUrl }, p));
  1583. }
  1584. origin.tot = Math.max(jsonInfo[i].problems.length, 0);
  1585. origin.ac = 0;
  1586. break;
  1587. }
  1588. }
  1589. if (Array.isArray(datas) && datas.length > 0) {
  1590. allProblemNum.value = datas.length;
  1591. asyncProblemNum.value = 0;
  1592. let pre = 0;
  1593. for (let i = 0; i < datas.length; i++) {
  1594. let info2 = datas[i];
  1595. try {
  1596. if (asyncButtonLoadBreak.value) {
  1597. break;
  1598. }
  1599. await sleep(20);
  1600. let ID2 = info2.titleSlug;
  1601. let key = `${info2.origin}`;
  1602. let origin = map.get(key);
  1603. if (cache[ID2] != "ac") {
  1604. let response = await getProblemAcInfo(ID2);
  1605. const status = (_c = (_b = response == null ? void 0 : response.data) == null ? void 0 : _b.question) == null ? void 0 : _c.status;
  1606. cache[ID2] = status == null ? "null" : status;
  1607. }
  1608. if (origin) {
  1609. if (cache[ID2] == "ac") {
  1610. origin.ac = origin.ac + 1;
  1611. }
  1612. }
  1613. asyncProblemNum.value += 1;
  1614. if (loadProcess.value < pre && isDev()) {
  1615. console.warn("calc result is error");
  1616. }
  1617. pre = loadProcess.value;
  1618. } catch (e) {
  1619. if (isDev()) {
  1620. console.log("process error", e.message, "asyncProblemNum.value", asyncProblemNum.value, "all", allProblemNum.value);
  1621. }
  1622. }
  1623. if (i % 100 == 0) {
  1624. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], Object.assign({}, cache));
  1625. }
  1626. }
  1627. }
  1628. } catch (e) {
  1629. console.log("error", e);
  1630. } finally {
  1631. if (rowData) {
  1632. rowData.loading = false;
  1633. }
  1634. asyncButtonLoad.value = false;
  1635. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], vue.toRaw(tableData));
  1636. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_ac_key__"], Object.assign({}, cache));
  1637. if (isDev()) {
  1638. console.log("同步完成🥰", asyncProblemNum.value, allProblemNum.value, loadProcess.value);
  1639. }
  1640. await sleep(500);
  1641. ElementPlus.ElMessage({
  1642. type: allProblemNum.value == asyncProblemNum.value ? "success" : asyncButtonLoadBreak.value ? "error" : "warning",
  1643. message: allProblemNum.value == asyncProblemNum.value ? `同步完成🥰` : asyncButtonLoadBreak.value ? `同步中断 ${loadProcess.value}% ` : `同步率 ${loadProcess.value}% `,
  1644. duration: 3e3
  1645. });
  1646. await sleep(6e3);
  1647. allProblemNum.value = 0;
  1648. asyncProblemNum.value = 0;
  1649. showProcess.value = false;
  1650. asyncButtonLoadBreak.value = false;
  1651. for (let i = 0; i < tableData.length; i++) {
  1652. if (getAcCountKey((_d = tableData[i]) == null ? void 0 : _d.link)) {
  1653. Cache$2.set(getAcCountKey(tableData[i].link), { "tot": tableData[i].tot, "ac": tableData[i].ac });
  1654. }
  1655. if ((_e = tableData[i]) == null ? void 0 : _e.loading) {
  1656. tableData[i].loading = false;
  1657. }
  1658. }
  1659. }
  1660. };
  1661. if (row.link == TARGET_URL) {
  1662. Message("该操作将同步所有题单,耗时可能较长 确认操作?", callback);
  1663. } else {
  1664. callback();
  1665. }
  1666. };
  1667. const q1 = vue.ref(false);
  1668. vue.ref(false);
  1669. return (_ctx, _cache) => {
  1670. const _component_el_dialog = vue.resolveComponent("el-dialog");
  1671. const _component_el_input = vue.resolveComponent("el-input");
  1672. const _component_el_form_item = vue.resolveComponent("el-form-item");
  1673. const _component_el_form = vue.resolveComponent("el-form");
  1674. const _component_el_button = vue.resolveComponent("el-button");
  1675. const _component_el_progress = vue.resolveComponent("el-progress");
  1676. const _component_el_col = vue.resolveComponent("el-col");
  1677. const _component_el_option = vue.resolveComponent("el-option");
  1678. const _component_el_select = vue.resolveComponent("el-select");
  1679. const _component_el_tooltip = vue.resolveComponent("el-tooltip");
  1680. const _component_el_row = vue.resolveComponent("el-row");
  1681. const _component_el_table_column = vue.resolveComponent("el-table-column");
  1682. const _component_el_link = vue.resolveComponent("el-link");
  1683. const _component_el_switch = vue.resolveComponent("el-switch");
  1684. const _component_el_table = vue.resolveComponent("el-table");
  1685. return vue.openBlock(), vue.createElementBlock("div", null, [
  1686. vue.createVNode(_component_el_dialog, {
  1687. modelValue: q1.value,
  1688. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => q1.value = $event)
  1689. }, {
  1690. default: vue.withCtx(() => [
  1691. vue.createVNode(Q1)
  1692. ]),
  1693. _: 1
  1694. }, 8, ["modelValue"]),
  1695. vue.createVNode(_component_el_dialog, {
  1696. modelValue: dialogFormVisible.value,
  1697. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => dialogFormVisible.value = $event),
  1698. title: `${info.status == "add" ? "添加" : "编辑"}`,
  1699. width: "700"
  1700. }, {
  1701. footer: vue.withCtx(() => [
  1702. vue.createElementVNode("div", _hoisted_1, [
  1703. vue.createVNode(_component_el_button, {
  1704. onClick: _cache[3] || (_cache[3] = ($event) => dialogFormVisible.value = false)
  1705. }, {
  1706. default: vue.withCtx(() => [
  1707. vue.createTextVNode("取消")
  1708. ]),
  1709. _: 1
  1710. }),
  1711. vue.createVNode(_component_el_button, { onClick: addOrUpdate }, {
  1712. default: vue.withCtx(() => [
  1713. vue.createTextVNode(" 确认 ")
  1714. ]),
  1715. _: 1
  1716. })
  1717. ])
  1718. ]),
  1719. default: vue.withCtx(() => [
  1720. vue.createVNode(_component_el_form, null, {
  1721. default: vue.withCtx(() => [
  1722. vue.createVNode(_component_el_form_item, {
  1723. label: "标题",
  1724. "label-width": formLabelWidth
  1725. }, {
  1726. default: vue.withCtx(() => [
  1727. vue.createVNode(_component_el_input, {
  1728. modelValue: info.title,
  1729. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => info.title = $event),
  1730. autocomplete: "off"
  1731. }, null, 8, ["modelValue"])
  1732. ]),
  1733. _: 1
  1734. }),
  1735. vue.createVNode(_component_el_form_item, {
  1736. label: "链接",
  1737. "label-width": formLabelWidth
  1738. }, {
  1739. default: vue.withCtx(() => [
  1740. vue.createVNode(_component_el_input, {
  1741. modelValue: info.link,
  1742. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => info.link = $event),
  1743. autocomplete: "off"
  1744. }, null, 8, ["modelValue"])
  1745. ]),
  1746. _: 1
  1747. })
  1748. ]),
  1749. _: 1
  1750. })
  1751. ]),
  1752. _: 1
  1753. }, 8, ["modelValue", "title"]),
  1754. vue.createVNode(_component_el_dialog, {
  1755. modelValue: dialogTableVisible.value,
  1756. "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => dialogTableVisible.value = $event),
  1757. title: asyncButtonLoadBreak.value ? `同步已中断 ${asyncProblemNum.value}/${allProblemNum.value}` : showProcess.value ? loadProcess.value < 100 ? `同步中...${asyncProblemNum.value}/${allProblemNum.value}` : "统计完成" : "题单信息",
  1758. width: "60%"
  1759. }, {
  1760. default: vue.withCtx(() => [
  1761. showProcess.value ? (vue.openBlock(), vue.createBlock(_component_el_progress, {
  1762. key: 0,
  1763. color: processColors,
  1764. percentage: loadProcess.value,
  1765. "stroke-width": 15,
  1766. striped: "",
  1767. "striped-flow": "",
  1768. style: { "margin-bottom": "20px" },
  1769. status: `${loadProcess.value == 100 ? "success" : ""}`
  1770. }, null, 8, ["percentage", "status"])) : vue.createCommentVNode("", true),
  1771. vue.createVNode(_component_el_row, { gutter: 10 }, {
  1772. default: vue.withCtx(() => [
  1773. vue.createVNode(_component_el_col, { span: 4 }, {
  1774. default: vue.withCtx(() => [
  1775. vue.createVNode(_component_el_input, {
  1776. modelValue: keywords.value,
  1777. "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => keywords.value = $event),
  1778. placeholder: "请输入关键词过滤",
  1779. clearable: ""
  1780. }, null, 8, ["modelValue"])
  1781. ]),
  1782. _: 1
  1783. }),
  1784. vue.createVNode(_component_el_col, { span: 20 }, {
  1785. default: vue.withCtx(() => [
  1786. showAddLocalButton.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1787. key: 0,
  1788. plain: "",
  1789. onClick: addlocal,
  1790. disabled: isDisabbled.value,
  1791. size: tableButtonSize.value
  1792. }, {
  1793. default: vue.withCtx(() => [
  1794. vue.createTextVNode(" 添加本页 ")
  1795. ]),
  1796. _: 1
  1797. }, 8, ["disabled", "size"])) : vue.createCommentVNode("", true),
  1798. showAddLocalButton.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1799. key: 1,
  1800. plain: "",
  1801. onClick: _cache[6] || (_cache[6] = ($event) => handlerProblems("add")),
  1802. size: tableButtonSize.value
  1803. }, {
  1804. default: vue.withCtx(() => [
  1805. vue.createTextVNode(" 自定义 ")
  1806. ]),
  1807. _: 1
  1808. }, 8, ["size"])) : vue.createCommentVNode("", true),
  1809. vue.createVNode(_component_el_select, {
  1810. modelValue: fromData.sortType,
  1811. "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => fromData.sortType = $event),
  1812. style: { "margin": "0 5px", "width": "100px" },
  1813. disabled: asyncButtonLoad.value
  1814. }, {
  1815. default: vue.withCtx(() => [
  1816. vue.createVNode(_component_el_option, {
  1817. label: "默认排序",
  1818. value: 0
  1819. }, {
  1820. default: vue.withCtx(() => [
  1821. vue.createTextVNode("默认排序")
  1822. ]),
  1823. _: 1
  1824. }),
  1825. vue.createVNode(_component_el_option, {
  1826. label: "题目数量",
  1827. value: 1
  1828. }, {
  1829. default: vue.withCtx(() => [
  1830. vue.createTextVNode("题目数量")
  1831. ]),
  1832. _: 1
  1833. }),
  1834. vue.createVNode(_component_el_option, {
  1835. label: "AC数量",
  1836. value: 2
  1837. }, {
  1838. default: vue.withCtx(() => [
  1839. vue.createTextVNode("AC数量")
  1840. ]),
  1841. _: 1
  1842. }),
  1843. vue.createVNode(_component_el_option, {
  1844. label: "完成度",
  1845. value: 3
  1846. }, {
  1847. default: vue.withCtx(() => [
  1848. vue.createTextVNode("完成度")
  1849. ]),
  1850. _: 1
  1851. })
  1852. ]),
  1853. _: 1
  1854. }, 8, ["modelValue", "disabled"]),
  1855. vue.createVNode(_component_el_tooltip, { content: "同步所有题单" }, {
  1856. default: vue.withCtx(() => [
  1857. vue.createVNode(_component_el_button, {
  1858. type: asyncButtonLoad.value ? "success" : "danger",
  1859. onClick: _cache[8] || (_cache[8] = ($event) => asyncProblemStatus({ "link": "https://leetcode.cn/u/endlesscheng/" })),
  1860. size: tableButtonSize.value,
  1861. loading: asyncButtonLoad.value
  1862. }, {
  1863. default: vue.withCtx(() => [
  1864. vue.createTextVNode(vue.toDisplayString(asyncButtonLoad.value ? "同步中" : "同步题单"), 1)
  1865. ]),
  1866. _: 1
  1867. }, 8, ["type", "size", "loading"])
  1868. ]),
  1869. _: 1
  1870. }),
  1871. asyncButtonLoad.value ? (vue.openBlock(), vue.createBlock(_component_el_tooltip, {
  1872. key: 2,
  1873. content: "点击中断同步"
  1874. }, {
  1875. default: vue.withCtx(() => [
  1876. asyncButtonLoad.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1877. key: 0,
  1878. type: "warning",
  1879. text: "",
  1880. onClick: _cache[9] || (_cache[9] = ($event) => asyncButtonLoadBreak.value = !asyncButtonLoadBreak.value),
  1881. size: tableButtonSize.value
  1882. }, {
  1883. default: vue.withCtx(() => [
  1884. vue.createTextVNode(" 中断同步 ")
  1885. ]),
  1886. _: 1
  1887. }, 8, ["size"])) : vue.createCommentVNode("", true)
  1888. ]),
  1889. _: 1
  1890. })) : vue.createCommentVNode("", true),
  1891. vue.createVNode(_component_el_tooltip, { content: "随机一道灵茶题单中题目,快捷键 Ctrl + Alt + J 可以触发" }, {
  1892. default: vue.withCtx(() => [
  1893. vue.createVNode(_component_el_button, {
  1894. type: "primary",
  1895. text: "",
  1896. onClick: vue.unref(randomProblem),
  1897. size: tableButtonSize.value
  1898. }, {
  1899. default: vue.withCtx(() => [
  1900. vue.createTextVNode(" 随机题目 ")
  1901. ]),
  1902. _: 1
  1903. }, 8, ["onClick", "size"])
  1904. ]),
  1905. _: 1
  1906. })
  1907. ]),
  1908. _: 1
  1909. })
  1910. ]),
  1911. _: 1
  1912. }),
  1913. vue.createVNode(_component_el_table, {
  1914. data: vue.unref(urlsData),
  1915. height: "300",
  1916. style: { "width": "100%", "margin-top": "10px" }
  1917. }, {
  1918. default: vue.withCtx(() => [
  1919. vue.createVNode(_component_el_table_column, { type: "index" }),
  1920. vue.createVNode(_component_el_table_column, {
  1921. label: "标题",
  1922. width: "auto",
  1923. align: "center"
  1924. }, {
  1925. default: vue.withCtx((scope) => [
  1926. vue.createVNode(_component_el_link, {
  1927. href: scope.row.link,
  1928. target: "_blank",
  1929. type: "default"
  1930. }, {
  1931. default: vue.withCtx(() => [
  1932. vue.createTextVNode(vue.toDisplayString(scope.row.title), 1)
  1933. ]),
  1934. _: 2
  1935. }, 1032, ["href"])
  1936. ]),
  1937. _: 1
  1938. }),
  1939. vue.createVNode(_component_el_table_column, {
  1940. label: "随机",
  1941. width: "70",
  1942. align: "center"
  1943. }, {
  1944. default: vue.withCtx((scope) => [
  1945. vue.createVNode(_component_el_switch, {
  1946. modelValue: scope.row.select,
  1947. "onUpdate:modelValue": ($event) => scope.row.select = $event,
  1948. onChange: ($event) => selectHandlerChange(scope.row),
  1949. disabled: rowIsDisabled.value(scope.row),
  1950. size: "small"
  1951. }, null, 8, ["modelValue", "onUpdate:modelValue", "onChange", "disabled"])
  1952. ]),
  1953. _: 1
  1954. }),
  1955. vue.createVNode(_component_el_table_column, {
  1956. label: "AC",
  1957. width: "70",
  1958. align: "center"
  1959. }, {
  1960. default: vue.withCtx((scope) => [
  1961. vue.createVNode(_component_el_link, {
  1962. type: "success",
  1963. underline: false,
  1964. onClick: ($event) => showProblemsInfo(scope.row)
  1965. }, {
  1966. default: vue.withCtx(() => [
  1967. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.ac) ? 0 : scope.row.ac), 1)
  1968. ]),
  1969. _: 2
  1970. }, 1032, ["onClick"])
  1971. ]),
  1972. _: 1
  1973. }),
  1974. vue.createVNode(_component_el_table_column, {
  1975. label: "Total",
  1976. width: "70",
  1977. align: "center"
  1978. }, {
  1979. default: vue.withCtx((scope) => [
  1980. vue.createVNode(_component_el_link, {
  1981. type: "primary",
  1982. underline: false,
  1983. onClick: ($event) => showProblemsInfo(scope.row)
  1984. }, {
  1985. default: vue.withCtx(() => [
  1986. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.tot) ? 0 : scope.row.tot), 1)
  1987. ]),
  1988. _: 2
  1989. }, 1032, ["onClick"])
  1990. ]),
  1991. _: 1
  1992. }),
  1993. vue.createVNode(_component_el_table_column, {
  1994. label: "进度",
  1995. width: "70",
  1996. align: "center"
  1997. }, {
  1998. default: vue.withCtx((scope) => [
  1999. vue.createVNode(_component_el_link, {
  2000. onClick: ($event) => showProblemsInfo(scope.row),
  2001. type: "warning",
  2002. underline: false
  2003. }, {
  2004. default: vue.withCtx(() => {
  2005. var _a, _b, _c;
  2006. return [
  2007. vue.createTextVNode(vue.toDisplayString(((_a = scope == null ? void 0 : scope.row) == null ? void 0 : _a.tot) == 0 ? 0 : `${computeProcess((_b = scope == null ? void 0 : scope.row) == null ? void 0 : _b.ac, (_c = scope == null ? void 0 : scope.row) == null ? void 0 : _c.tot)}%`), 1)
  2008. ];
  2009. }),
  2010. _: 2
  2011. }, 1032, ["onClick"])
  2012. ]),
  2013. _: 1
  2014. }),
  2015. vue.createVNode(_component_el_table_column, {
  2016. label: "操作",
  2017. width: "200px",
  2018. align: "center"
  2019. }, {
  2020. default: vue.withCtx((scope) => [
  2021. vue.createVNode(_component_el_button, {
  2022. loading: scope.row.loading,
  2023. onClick: ($event) => asyncProblemStatus(scope.row),
  2024. size: "small",
  2025. type: "success",
  2026. disabled: rowIsDisabled.value(scope.row),
  2027. link: ""
  2028. }, {
  2029. default: vue.withCtx(() => [
  2030. vue.createTextVNode(vue.toDisplayString(scope.row.loading ? "" : "同步"), 1)
  2031. ]),
  2032. _: 2
  2033. }, 1032, ["loading", "onClick", "disabled"]),
  2034. vue.createVNode(_component_el_button, {
  2035. onClick: ($event) => handlerProblems("update", scope.row, scope.$index),
  2036. size: "small",
  2037. type: "primary",
  2038. disabled: rowIsDisabled.value(scope.row),
  2039. link: ""
  2040. }, {
  2041. default: vue.withCtx(() => [
  2042. vue.createTextVNode("编辑")
  2043. ]),
  2044. _: 2
  2045. }, 1032, ["onClick", "disabled"]),
  2046. vue.createVNode(_component_el_button, {
  2047. onClick: ($event) => deleteProblems(scope.row.id),
  2048. size: "small",
  2049. type: "danger",
  2050. link: "",
  2051. disabled: rowIsDisabled.value(scope.row)
  2052. }, {
  2053. default: vue.withCtx(() => [
  2054. vue.createTextVNode("删除")
  2055. ]),
  2056. _: 2
  2057. }, 1032, ["onClick", "disabled"])
  2058. ]),
  2059. _: 1
  2060. })
  2061. ]),
  2062. _: 1
  2063. }, 8, ["data"]),
  2064. vue.createVNode(_component_el_row, {
  2065. gutter: 10,
  2066. style: { "margin": "10px 0" }
  2067. }, {
  2068. default: vue.withCtx(() => [
  2069. vue.createVNode(_component_el_col, { span: 10 }, {
  2070. default: vue.withCtx(() => [
  2071. vue.createTextVNode(" 会员  "),
  2072. vue.createVNode(_component_el_tooltip, { content: "过滤会员题目,会员题不会出现在随机题目中和讨论区显示。另外会员题目将不参与进度统计,默认显示" }, {
  2073. default: vue.withCtx(() => [
  2074. vue.createVNode(_component_el_switch, {
  2075. modelValue: fromData.visiableMember,
  2076. "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => fromData.visiableMember = $event)
  2077. }, null, 8, ["modelValue"])
  2078. ]),
  2079. _: 1
  2080. }),
  2081. showAddLocalButton.value ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  2082. vue.createTextVNode(" 隐藏AC  "),
  2083. vue.createVNode(_component_el_tooltip, { content: "是否在讨论区显示AC题目,默认显示 " }, {
  2084. default: vue.withCtx(() => [
  2085. vue.createVNode(_component_el_switch, {
  2086. modelValue: fromData.hiddenAc,
  2087. "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => fromData.hiddenAc = $event)
  2088. }, null, 8, ["modelValue"])
  2089. ]),
  2090. _: 1
  2091. })
  2092. ], 64)) : vue.createCommentVNode("", true),
  2093. vue.createTextVNode(" 随机ac  "),
  2094. vue.createVNode(_component_el_tooltip, { content: "随机题目配置: 过滤AC的题目,AC题目出现在随机题目中,默认不过滤" }, {
  2095. default: vue.withCtx(() => [
  2096. vue.createVNode(_component_el_switch, {
  2097. modelValue: fromData.showAcConfig,
  2098. "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => fromData.showAcConfig = $event)
  2099. }, null, 8, ["modelValue"])
  2100. ]),
  2101. _: 1
  2102. })
  2103. ]),
  2104. _: 1
  2105. }),
  2106. vue.createVNode(_component_el_col, { span: 8 }, {
  2107. default: vue.withCtx(() => [
  2108. vue.createTextVNode("   "),
  2109. vue.createVNode(_component_el_tooltip, { content: "随机题目和讨论区题目将会在这个区间(没有分数题目无法操作)" }, {
  2110. default: vue.withCtx(() => [
  2111. vue.createVNode(_component_el_link, {
  2112. underline: false,
  2113. type: "primary"
  2114. }, {
  2115. default: vue.withCtx(() => [
  2116. vue.createTextVNode("分数区间")
  2117. ]),
  2118. _: 1
  2119. })
  2120. ]),
  2121. _: 1
  2122. }),
  2123. vue.createTextVNode("   "),
  2124. vue.createVNode(_component_el_input, {
  2125. modelValue: fromData.min,
  2126. "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => fromData.min = $event),
  2127. "aria-placeholder": "",
  2128. placeholder: " min ",
  2129. style: { "width": "60px" }
  2130. }, null, 8, ["modelValue"]),
  2131. vue.createTextVNode("- "),
  2132. vue.createVNode(_component_el_input, {
  2133. modelValue: fromData.max,
  2134. "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => fromData.max = $event),
  2135. "aria-placeholder": "",
  2136. placeholder: " max",
  2137. style: { "width": "60px" }
  2138. }, null, 8, ["modelValue"])
  2139. ]),
  2140. _: 1
  2141. }),
  2142. vue.createVNode(_component_el_col, { span: 6 }, {
  2143. default: vue.withCtx(() => [
  2144. vue.createVNode(_component_el_tooltip, { content: "重置题单" }, {
  2145. default: vue.withCtx(() => [
  2146. vue.createVNode(_component_el_button, {
  2147. plain: "",
  2148. onClick: handlerDefault,
  2149. size: tableButtonSize.value,
  2150. disabled: showProcess.value
  2151. }, {
  2152. default: vue.withCtx(() => [
  2153. vue.createTextVNode(" 重置 ")
  2154. ]),
  2155. _: 1
  2156. }, 8, ["size", "disabled"])
  2157. ]),
  2158. _: 1
  2159. }),
  2160. vue.createVNode(_component_el_button, {
  2161. plain: "",
  2162. onClick: _cache[15] || (_cache[15] = ($event) => q1.value = !q1.value),
  2163. size: tableButtonSize.value
  2164. }, {
  2165. default: vue.withCtx(() => [
  2166. vue.createTextVNode(" 使用说明 ")
  2167. ]),
  2168. _: 1
  2169. }, 8, ["size"])
  2170. ]),
  2171. _: 1
  2172. })
  2173. ]),
  2174. _: 1
  2175. })
  2176. ]),
  2177. _: 1
  2178. }, 8, ["modelValue", "title"]),
  2179. vue.createVNode(_component_el_dialog, {
  2180. modelValue: asyncVisableDialog.value,
  2181. "onUpdate:modelValue": _cache[17] || (_cache[17] = ($event) => asyncVisableDialog.value = $event),
  2182. width: "35%"
  2183. }, {
  2184. default: vue.withCtx(() => [
  2185. vue.createElementVNode("p", null, [
  2186. vue.createVNode(_component_el_link, {
  2187. href: showProblemsProcessInfo.link,
  2188. type: "info",
  2189. underline: false
  2190. }, {
  2191. default: vue.withCtx(() => [
  2192. vue.createTextVNode(vue.toDisplayString(showProblemsProcessInfo.title), 1)
  2193. ]),
  2194. _: 1
  2195. }, 8, ["href"])
  2196. ]),
  2197. vue.createElementVNode("div", _hoisted_2, [
  2198. vue.createVNode(_component_el_progress, {
  2199. type: "circle",
  2200. percentage: computeProcess(showProblemsProcessInfo.ac, showProblemsProcessInfo.tot),
  2201. color: processColors
  2202. }, {
  2203. default: vue.withCtx(({ percentage }) => [
  2204. vue.createElementVNode("p", null, vue.toDisplayString(percentage) + "%", 1)
  2205. ]),
  2206. _: 1
  2207. }, 8, ["percentage"])
  2208. ]),
  2209. vue.createElementVNode("p", _hoisted_3, vue.toDisplayString(showProblemsProcessInfo.ac) + " / " + vue.toDisplayString(showProblemsProcessInfo.tot), 1)
  2210. ]),
  2211. _: 1
  2212. }, 8, ["modelValue"])
  2213. ]);
  2214. };
  2215. }
  2216. };
  2217. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-3d821394"]]);
  2218. const cssLoader = (e) => {
  2219. const t = GM_getResourceText(e);
  2220. return GM_addStyle(t), t;
  2221. };
  2222. cssLoader("elementPlusCss");
  2223. const stopRankingKey = "__is_stop_rating_ranking__";
  2224. let conetstTimeId = null;
  2225. function run$1() {
  2226. const container = document.querySelector(".contest-question-info .list-group");
  2227. if (!container) return;
  2228. const ls = Array.from(container.querySelectorAll(".list-group-item .pull-right"));
  2229. for (let i = 0; i < 4; i++) {
  2230. if (i >= ls.length) {
  2231. break;
  2232. }
  2233. if (ls[i] instanceof HTMLElement) {
  2234. ls[i].textContent = "0";
  2235. }
  2236. }
  2237. window.clearInterval(conetstTimeId);
  2238. }
  2239. function startStopRanking() {
  2240. if (!isContest(window.location.href)) {
  2241. return;
  2242. }
  2243. const isNext = !!document.querySelector("#__next");
  2244. if (isNext) {
  2245. return;
  2246. }
  2247. const use = Cache$2.get(stopRankingKey);
  2248. if (use) {
  2249. conetstTimeId = setInterval(() => {
  2250. run$1();
  2251. }, 10);
  2252. }
  2253. _GM_registerMenuCommand(`${use ? "使用" : "关闭"} 排行榜`, () => {
  2254. Cache$2.set(stopRankingKey, !use);
  2255. window.location.reload();
  2256. }, { title: "对于不想看到排行榜的可以使用此功能 默认开启" });
  2257. }
  2258. const local_url$1 = window.location.href;
  2259. let loadID = 0;
  2260. let submitCnt = 0;
  2261. let submitbutton = null;
  2262. function watchDom(dom) {
  2263. if (!(dom instanceof HTMLElement)) {
  2264. return;
  2265. }
  2266. let m = new MutationObserver(() => {
  2267. if (submitCnt % 2 == 1) {
  2268. submitProblems(local_url$1);
  2269. }
  2270. submitCnt++;
  2271. });
  2272. m.observe(dom, {
  2273. childList: true,
  2274. attributes: true
  2275. });
  2276. }
  2277. function handler() {
  2278. loadID++;
  2279. let findSubmitButton = function(sel) {
  2280. if (!sel) return null;
  2281. return Array.from(document.querySelectorAll(sel && { length: 0 })).find((e) => {
  2282. return e && e.innerText == "提交解答" || e.innerText == "提交";
  2283. });
  2284. };
  2285. const isNext = !!document.querySelector("#__next");
  2286. submitbutton = findSubmitButton(isProblem(local_url$1) || isNext ? "" : ".question-detail-bottom .pull-right button");
  2287. if (!submitbutton) {
  2288. submitbutton = document.querySelector('[data-e2e-locator="console-submit-button"]');
  2289. }
  2290. if (submitbutton) {
  2291. watchDom(submitbutton);
  2292. submitbutton.addEventListener("click", () => {
  2293. submitProblems(local_url$1, 10 * 1e3);
  2294. });
  2295. } else if (loadID < 10) {
  2296. setTimeout(() => {
  2297. handlerNotFound();
  2298. }, 3e3);
  2299. }
  2300. }
  2301. function watchSubmit() {
  2302. if (!isProblem()) {
  2303. return;
  2304. }
  2305. try {
  2306. if ((window == null ? void 0 : window.fetch) && (window == null ? void 0 : window.unsafeWindow)) {
  2307. let originalFetch = window == null ? void 0 : window.fetch;
  2308. window.unsafeWindow.fetch = function() {
  2309. return originalFetch.apply(this, arguments).then(function(response) {
  2310. let res = response.clone();
  2311. res.text().then(function(bodyText) {
  2312. let url = res.url;
  2313. if (isDev()) {
  2314. console.log("query result", bodyText);
  2315. }
  2316. if (!/https:\/\/leetcode\.(cn|com)\/submissions\/detail\/\d+\/check\/.*/.test(url)) {
  2317. return;
  2318. }
  2319. if (res.status == 200 && res.ok) {
  2320. let result = JSON.parse(bodyText);
  2321. const ID2 = getId(local_url$1);
  2322. const status = (result == null ? void 0 : result.status_msg) == "Accepted" ? "ac" : (result == null ? void 0 : result.status_msg) == "Wrong Answer" ? "notac" : "null";
  2323. watchSaveStatus(ID2, status);
  2324. }
  2325. const cache = Cache.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], true, Object.name);
  2326. if (cache[ID] == "null" || cache[ID] == null || cache[Id] == void 0) {
  2327. submitProblems(local_url$1);
  2328. }
  2329. });
  2330. return response;
  2331. });
  2332. };
  2333. } else {
  2334. console.warn("浏览器当前环境不支持 unsafeWindow 将做兼容处理 ");
  2335. handler();
  2336. }
  2337. } catch (e) {
  2338. console.error(e);
  2339. }
  2340. }
  2341. const local_url = window.location.href;
  2342. const randomProblemKey = () => Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_random_problems_key__"]) == void 0 ? true : Cache$2.get(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_random_problems_key__"]);
  2343. let Container = null;
  2344. if (isProblem() || isLeetCodeCircleUrl() || isHome()) {
  2345. if (isDev()) {
  2346. console.log("isHome================>");
  2347. }
  2348. const start = () => {
  2349. Container = document.createElement("div");
  2350. const body = document.querySelector("body");
  2351. body.append(Container);
  2352. Container.style.display = "block";
  2353. return Container;
  2354. };
  2355. let dom = start();
  2356. const VueApp = vue.createApp(App);
  2357. VueApp.use(ElementPlus).mount(dom);
  2358. }
  2359. if (isProblem() || isLeetCodeCircleUrl() || isHome()) {
  2360. _GM_registerMenuCommand(`随机一道题 ☕`, randomProblem, { title: "随机一道题目,你可以通过ctrl+atl+j显示一道题目" });
  2361. _GM_registerMenuCommand(`${randomProblemKey() ? "关闭" : "启用"} 随机题目快捷键 ☕`, () => {
  2362. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_random_problems_key__"], !randomProblemKey());
  2363. window.location.reload();
  2364. }, { title: "该功能是随机一道题的快捷键,你可以通过ctrl+atl+j显示一道题目" });
  2365. if (isLeetCodeCircleUrl()) {
  2366. installEnglishLinkChangeCommand();
  2367. }
  2368. if (randomProblemKey()) {
  2369. document.addEventListener("keydown", async function(event) {
  2370. if (event.ctrlKey && event.altKey && event.key === "j") {
  2371. randomProblem();
  2372. }
  2373. });
  2374. }
  2375. }
  2376. async function run() {
  2377. if (isProblem(local_url)) {
  2378. await sleep(3e3);
  2379. } else if (isLeetCodeCircleUrl(local_url)) {
  2380. stop_disscuss_command();
  2381. _GM_registerMenuCommand(`安装到${install_pos() ? "右侧" : "左侧"} 🎁`, () => {
  2382. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_insert_pos__"], install_pos());
  2383. window.location.reload();
  2384. }, { title: "AC标记安装位置,默认左侧,刷新生效" });
  2385. _GM_registerMenuCommand(`同步题目状态 🚀`, () => {
  2386. Message("确认同步题目状态", async () => {
  2387. await addProcess(true, void 0, true);
  2388. });
  2389. }, { title: "如果不在同一个浏览器答题,会出现ac题目状态没有及时同步,可以使用此功能" });
  2390. _GM_registerMenuCommand(`${initObj().onlyUrls ? "仅在收藏题单页面生效" : "所有题单生效"}`, () => {
  2391. const u = initObj();
  2392. u.onlyUrls = !u.onlyUrls;
  2393. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_solution__"], u);
  2394. }, { title: "插件默认会在所有讨论发布页生效,如果只想在收藏链接生效,可以使用此功能" });
  2395. _GM_registerMenuCommand(`添加本页`, () => {
  2396. const urls = initUrls();
  2397. let ok = false;
  2398. let url = window.location.href;
  2399. for (let info of urls) {
  2400. if (!info || !(info == null ? void 0 : info.link)) {
  2401. continue;
  2402. }
  2403. if (info.link.indexOf(url) != -1) {
  2404. ok = true;
  2405. break;
  2406. }
  2407. }
  2408. if (ok) {
  2409. ElementPlus.ElMessage({
  2410. message: "收藏失败,链接已经存在!",
  2411. type: "error"
  2412. });
  2413. } else {
  2414. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  2415. try {
  2416. url = url.split("view")[0];
  2417. } catch (e) {
  2418. url = window.location.href;
  2419. }
  2420. }
  2421. urls.unshift({
  2422. title: document.title,
  2423. link: url
  2424. });
  2425. Container.style.display = "block";
  2426. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_urls__"], urls);
  2427. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_update__"], true);
  2428. Cache$2.set(__0X3F_PROBLEM_KEYS__$1["__0x3f_problmes_add_cur__"], true);
  2429. ElementPlus.ElMessage({
  2430. message: "收藏成功!刷新生效",
  2431. type: "success"
  2432. });
  2433. }
  2434. });
  2435. }
  2436. }
  2437. async function startMain() {
  2438. for (let callback of [showProblemSolve, tips_message, update_version, watchSubmit, run, startStopRanking, handlerScore, resetProblemStatus]) {
  2439. try {
  2440. callback();
  2441. } catch (_) {
  2442. if (isDev()) {
  2443. console.error(_);
  2444. }
  2445. }
  2446. }
  2447. }
  2448. startMain();
  2449.  
  2450. })(ElementPlus, Vue);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址