0x3f-problem-solution

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

2024-10-13 기준 버전입니다. 최신 버전을 확인하세요.

  1. // ==UserScript==
  2. // @name 0x3f-problem-solution
  3. // @namespace https://greatest.deepsurf.us/zh-CN/scripts/501134-0x3f-problem-solution
  4. // @version 0.0.5.1
  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://greatest.deepsurf.us/zh-CN/scripts/501134-0x3f-problem-solution/feedback
  11. // @match https://leetcode.cn/circle/discuss/*
  12. // @match https://leetcode.cn/problems/*
  13. // @match https://leetcode.cn/contest/weekly-contest-*/problems/*
  14. // @match https://leetcode.cn/contest/biweekly-contest-*/problems/*
  15. // @require https://unpkg.com/vue@3.4.31/dist/vue.global.prod.js
  16. // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B
  17. // @require https://unpkg.com/element-plus@2.7.6/dist/index.full.js
  18. // @resource elementPlusCss https://unpkg.com/element-plus@2.7.6/dist/index.css
  19. // @grant GM_addStyle
  20. // @grant GM_deleteValue
  21. // @grant GM_getResourceText
  22. // @grant GM_getValue
  23. // @grant GM_registerMenuCommand
  24. // @grant GM_setValue
  25. // ==/UserScript==
  26.  
  27. (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const e=document.createElement("style");e.textContent=t,document.head.append(e)})(" h2[data-v-49e5e62d]{color:#000;margin:10px 0}em[data-v-49e5e62d]{color:red}.m-setting-button[data-v-003e83a0]{position:fixed;top:200px;right:0;z-index:100000}.m-button[data-v-003e83a0]{margin-left:16px!important;padding:5px!important;font-size:14px!important}.processs-flex[data-v-003e83a0]{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} ");
  28.  
  29. (function (vue, ElementPlus) {
  30. 'use strict';
  31.  
  32. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  33. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  34. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  35. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  36. class Cache {
  37. set(k, v) {
  38. _GM_setValue(k, v);
  39. }
  40. get(k, parse = true, name = String.name) {
  41. try {
  42. let v = _GM_getValue(k);
  43. switch (name) {
  44. case String.name:
  45. if (v == null) {
  46. return "null";
  47. }
  48. return v;
  49. case Object.name:
  50. if (v == null || v == void 0 || typeof v != "object") {
  51. return {};
  52. }
  53. return v;
  54. case Boolean.name:
  55. if (v === null || v == void 0) {
  56. return false;
  57. }
  58. if (v == false || v == "false" || v == "" || v == "null") {
  59. return false;
  60. }
  61. return v;
  62. case Array.name:
  63. if (v === null || v == void 0 || !Array.isArray(v)) {
  64. return [];
  65. }
  66. return v;
  67. default:
  68. return v;
  69. }
  70. } catch (E) {
  71. return null;
  72. }
  73. }
  74. remove(k) {
  75. _GM_deleteValue(k);
  76. }
  77. }
  78. const Cache$1 = new Cache();
  79. const isHttp = (url) => /^https?:\/\/.*$/.test(url);
  80. const isLeetCodeCircleUrl = (url = window.location.href) => url && url.indexOf("https://leetcode.cn/circle") != -1;
  81. const isProblem = (url = window.location.href) => /^https?:\/\/leetcode.cn\/problems\/.*/i.test(url);
  82. const isContest = (url = window.location.href) => url.indexOf("https://leetcode.cn/contest/weekly-contest") != -1 || url.indexOf("https://leetcode.cn/contest/biweekly-contest") != -1;
  83. const sleep = async (time = 500) => new Promise((resolove) => setTimeout(resolove, time));
  84. const isDev = () => true;
  85. const width = 14;
  86. const height = 14;
  87. const problemFinsh = () => `
  88.  
  89. <svg width="${width}px" height="${height}px" status="ac" viewBox="0 0 1024 1024" version="1.1"
  90. xmlns="http://www.w3.org/2000/svg">
  91. <path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#4CAF50" />
  92. <path
  93. d="M738.133333 311.466667L448 601.6l-119.466667-119.466667-59.733333 59.733334 179.2 179.2 349.866667-349.866667z"
  94. fill="#CCFF90" />
  95. </svg>
  96.  
  97. `;
  98. const problemsTry = () => `
  99. <svg width="${width}px" height="${height}px" status="notac" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
  100. xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
  101. style="enable-background:new 0 0 512 512;" xml:space="preserve">
  102. <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
  103. S390.101,12.8,256,12.8z" />
  104. <g>
  105. <path style="fill:#573A32;" d="M256,115.2c-49.271,0-92.561,25.353-117.726,63.676l18.859,18.859
  106. 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
  107. C396.8,178.244,333.764,115.2,256,115.2z" />
  108. <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
  109. 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" />
  110. <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
  111. 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
  112. C334.822,348.194,298.266,371.2,256,371.2z" />
  113. </g>
  114. </svg>
  115.  
  116. `;
  117. const problemsNo = () => install_pos() ? `
  118. <svg width="${width}px" height="${height}px" status="null" 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>
  119. ` : ``;
  120. const createStatus = (status, link) => {
  121. let node;
  122. if (!link) {
  123. return;
  124. }
  125. node = link instanceof HTMLAnchorElement ? link.parentElement : link;
  126. if (node) {
  127. node.status = status;
  128. }
  129. let installSVG = "";
  130. if (status == STATUS["AC"]) {
  131. installSVG = problemFinsh();
  132. } else if (status == STATUS["notac"]) {
  133. installSVG = problemsTry();
  134. } else if (status == STATUS["NO"]) {
  135. installSVG = problemsNo();
  136. } else {
  137. installSVG = "";
  138. }
  139. let svg = node.querySelector("svg");
  140. if (svg) {
  141. if (svg.getAttribute("status") == status || svg.getAttribute("status") == STATUS["AC"]) {
  142. return false;
  143. }
  144. svg.remove();
  145. }
  146. node.innerHTML = install_pos() ? installSVG + node.innerHTML : node.innerHTML + installSVG;
  147. return true;
  148. };
  149. const inf = 4e3;
  150. const mi = 1e3;
  151. const __0X3F_PROBLEM_KEYS__ = {
  152. "__0x3f_problmes_solution__": "__0x3f_problmes_solution__",
  153. // 基本信息
  154. "__0x3f_problmes_urls__": "__0x3f_problmes_urls__",
  155. // 题单key
  156. "__0x3f_problmes_update__": "__0x3f_problmes_update__",
  157. // 是否修改了默认题单key
  158. "__0x3f_problmes_button_is_none__": "__is_none_0x3f_problmes_button__",
  159. // 是否隐藏设置按钮
  160. "__0x3f_problmes_insert_pos__": "__0x3f_problmes_insert_pos__",
  161. // 安装位置
  162. "__0x3f_problmes_status_update__": "__0x3f_problmes_status_update__",
  163. "__0x3f_problmes_plugin_load_ok__": "__0x3f_problmes_plugin_load_ok__",
  164. // 是否使用插件
  165. "__0x3f_problmes_add_cur__": "__0x3f_problmes_add_cur__",
  166. // 添加 url
  167. "__0x3f_problmes_ac_key__": "__local_ok_problem_key__",
  168. // ac key
  169. "__0x3f_problmes_ac_version__": "__0x3f_problmes_ac_version__",
  170. // TODO ac key version
  171. "__0x3f_problmes_all_problems__": "__0x3f_problmes_all_problems__",
  172. // all problems
  173. "__0x3f_problmes_random_problems_key__": "__0x3f_problmes_random_problems_key__",
  174. //随机题目快捷键
  175. "__0x3f_problmes_random_problems__": "__0x3f_problmes_random_problems__"
  176. //随机题目
  177. };
  178. const STATUS = {
  179. "AC": "ac",
  180. "NO": "null",
  181. "notac": "notac"
  182. };
  183. const defaultObj = {
  184. min: mi,
  185. max: inf,
  186. visiableMember: true,
  187. onlyUrls: false,
  188. useDefaultSetting: true,
  189. hiddenAc: false,
  190. showAcConfig: true
  191. };
  192. function install_pos() {
  193. return !Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_insert_pos__"], false, Boolean.name);
  194. }
  195. function isShow(text, min, max) {
  196. if (!text) {
  197. return true;
  198. }
  199. let res = text.match(/\d+/ig);
  200. if (!res) {
  201. return true;
  202. }
  203. if (Array.isArray(res) && res.length < 2) {
  204. return true;
  205. }
  206. let s = 0;
  207. for (let i = res.length - 1; i >= 0; i--) {
  208. s = res[i];
  209. if (s >= mi && s <= inf) {
  210. return s >= min && s <= max;
  211. }
  212. }
  213. return true;
  214. }
  215. let A = void 0;
  216. const linkCssSelector = `#lc-content [class*="CollapsibleMarkdownContent"] [class*="MarkdownContent"] li>a`;
  217. const queryProblem = () => Array.from(document.querySelectorAll(linkCssSelector)).filter((item) => item && item instanceof HTMLAnchorElement && isProblem(item.href));
  218. function loadProblems() {
  219. A = queryProblem();
  220. return A;
  221. }
  222. function handlerProblem(data) {
  223. var _a;
  224. try {
  225. loadProblems();
  226. let { min, max, visiableMember, useDefaultSetting, onlyUrls, hiddenAc } = data;
  227. if (isNaN(min) || isNaN(max)) {
  228. min = mi;
  229. max = inf;
  230. }
  231. if (min < mi) {
  232. min = mi;
  233. }
  234. if (max < min) {
  235. max = inf;
  236. }
  237. min = Number(min);
  238. max = Number(max);
  239. data.min = min;
  240. data.max = max;
  241. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"], data);
  242. for (let i = 0; i < A.length; i++) {
  243. if (!(A[i] instanceof HTMLAnchorElement)) {
  244. continue;
  245. }
  246. let d = (_a = A[i]) == null ? void 0 : _a.parentNode;
  247. if (!d) {
  248. continue;
  249. }
  250. let none = false;
  251. let Nohidden = isShow(d.textContent, min, max);
  252. d.style.display = Nohidden ? "" : "none";
  253. if (!Nohidden) {
  254. continue;
  255. }
  256. if (hiddenAc) {
  257. const svg = d.querySelector("svg");
  258. if (svg && svg.getAttribute("status")) {
  259. d.style.display = svg.getAttribute("status") == STATUS["AC"] ? "none" : "";
  260. }
  261. } else {
  262. d.style.display = "";
  263. }
  264. let c = d.textContent && d.textContent.indexOf("会员") != -1;
  265. if (!c) {
  266. continue;
  267. }
  268. d.style.display = visiableMember ? "" : "none";
  269. }
  270. } catch (e) {
  271. console.log("error", e);
  272. }
  273. }
  274. function computeAcInfo(saveUrls = [], deleteOk = true) {
  275. let infos = [];
  276. let set = /* @__PURE__ */ new Set();
  277. for (let i = 0, u = null; Array.isArray(saveUrls) && i < saveUrls.length; i++) {
  278. try {
  279. u = saveUrls[i];
  280. if (!(u == null ? void 0 : u.link) || !(u == null ? void 0 : u.title) || !(u == null ? void 0 : u.id) || set.has(u.link)) {
  281. continue;
  282. }
  283. if (u["select"] == void 0) u.select = true;
  284. if (u["loading"] == void 0 || u["loading"]) u["loading"] = false;
  285. let s = Object.values(u).join("");
  286. if (s == "null" || !Cache$1.get(u.link) || !getAcCountKey(u.link) || !Cache$1.get(getAcCountKey(u.link))) {
  287. continue;
  288. }
  289. let o = Cache$1.get(getAcCountKey(u.link));
  290. u["ac"] = isNaN(o["ac"]) ? 0 : parseInt(o["ac"]);
  291. u["tot"] = isNaN(o["tot"]) ? 0 : parseInt(o["tot"]);
  292. set.add(u.link);
  293. } catch (e) {
  294. }
  295. infos.push(Object.assign({}, u));
  296. }
  297. if (deleteOk) {
  298. for (let i = 0; i < saveUrls[i]; i++) {
  299. delete saveUrls[i];
  300. }
  301. for (let info of infos) {
  302. saveUrls.push(info);
  303. }
  304. }
  305. return infos;
  306. }
  307. const initUrls = () => {
  308. let saveUrls = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_update__"], true, Boolean.name) ? Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], true, Array.name) : defaultUrls;
  309. return computeAcInfo(saveUrls);
  310. };
  311. const initObj = () => {
  312. let obj = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"]) ? Object.assign(defaultObj, Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"])) : defaultObj;
  313. if (obj["showAcConfig"] == null || obj["showAcConfig"] == void 0) {
  314. obj.showAcConfig = true;
  315. }
  316. let temp = {};
  317. for (let key of Object.keys(obj)) {
  318. if (!isNaN(key) || defaultObj[`${key}`] == void 0) continue;
  319. temp[`${key}`] = obj[`${key}`];
  320. }
  321. return temp;
  322. };
  323. const support_plugins = () => {
  324. const u = initObj();
  325. if (!u || !u.onlyUrls) return true;
  326. let url = window.location.href;
  327. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  328. try {
  329. url = url.split("view")[0];
  330. } catch (e) {
  331. url = window.location.href;
  332. }
  333. }
  334. const urls = initUrls();
  335. for (let info of urls) {
  336. if (!info || !(info == null ? void 0 : info.link)) {
  337. continue;
  338. }
  339. if (info.link.indexOf(url) != -1) {
  340. return true;
  341. }
  342. }
  343. return false;
  344. };
  345. const defaultUrls = [
  346. { "title": "数学算法(数论/组合/概率期望/博弈/计算几何/随机算法", "link": "https://leetcode.cn/circle/discuss/IYT3ss/", "tot": 0, "ac": 0, "id": 1, "disabled": false, "select": true },
  347. { "title": "常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)", "link": "https://leetcode.cn/circle/discuss/mOr1u6/", "tot": 0, "ac": 0, "id": 2, "disabled": false, "select": true },
  348. { "title": "动态规划(入门/背包/状态机/划分/区间/状压/数位/树形/数据结构优化)", "link": "https://leetcode.cn/circle/discuss/tXLS3i/", "tot": 0, "ac": 0, "id": 3, "disabled": false, "select": true },
  349. { "title": "图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)", "link": "https://leetcode.cn/circle/discuss/01LUak/", "tot": 0, "ac": 0, "id": 4, "disabled": false, "select": true },
  350. { "title": "位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)", "link": "https://leetcode.cn/circle/discuss/dHn9Vk/", "tot": 0, "ac": 0, "id": 5, "disabled": false, "select": true },
  351. { "title": "网格图(DFS/BFS/综合应用)", "link": "https://leetcode.cn/circle/discuss/YiXPXW/", "tot": 0, "ac": 0, "id": 6, "disabled": false, "select": true },
  352. { "title": "单调栈(矩形面积/贡献法/最小字典序", "link": "https://leetcode.cn/circle/discuss/9oZFK9/", "tot": 0, "ac": 0, "id": 7, "disabled": false, "select": true },
  353. { "title": "二分算法(二分答案/最小化最大值/最大化最小值/第K小", "link": "https://leetcode.cn/circle/discuss/SqopEo/", "tot": 0, "ac": 0, "id": 8, "disabled": true, "select": true },
  354. { "title": "滑动窗口(定长/不定长/多指针", "link": "https://leetcode.cn/circle/discuss/0viNMK/", "tot": 0, "ac": 0, "id": 9, "disabled": false, "select": true },
  355. { "title": "贪心算法(基本贪心策略/反悔/区间/字典序/数学/思维/构造)", "link": "https://leetcode.cn/circle/discuss/g6KTKL/", "tot": 0, "ac": 0, "id": 10, "disabled": false, "select": true },
  356. { "title": "链表、二叉树与一般树(前后指针/快慢指针/DFS/BFS/直径/LCA)", "link": "https://leetcode.cn/circle/discuss/K0n2gO/", "tot": 0, "ac": 0, "id": 11, "disabled": false, "select": true },
  357. { "title": "字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)", "link": "https://leetcode.cn/circle/discuss/SJFwQI/", "tot": 0, "ac": 0, "id": 12, "disabled": false, "select": true }
  358. // { 'title': '灵茶题单完成情况', 'link': 'https://leetcode.cn/u/endlesscheng/', 'tot': 0, 'ac': 0, 'id': 0x3f3f3f3f,'disabled':true,'select':false },
  359. ];
  360. function getId(problemUrl) {
  361. if (isContest(problemUrl) || isProblem(problemUrl)) {
  362. try {
  363. return problemUrl.split("problems")[1].split("/")[1];
  364. } catch (e) {
  365. return "";
  366. }
  367. }
  368. return "";
  369. }
  370. function postData(ID) {
  371. return {
  372. "query": "\n query userQuestionStatus($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n status\n }\n}\n ",
  373. "variables": {
  374. "titleSlug": ID
  375. },
  376. "operationName": "userQuestionStatus"
  377. };
  378. }
  379. async function queryStatus(ID = "", cache = {}, cur = void 0, watch2 = false) {
  380. var _a, _b, _c;
  381. if (!ID) {
  382. return;
  383. }
  384. if (cache[ID] == void 0 || cache[ID] != STATUS["AC"]) {
  385. const response = await getProblemAcInfo(ID);
  386. if ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.question) {
  387. const status = (_c = (_b = response == null ? void 0 : response.data) == null ? void 0 : _b.question) == null ? void 0 : _c.status;
  388. if (cache[ID] == void 0 || cache[ID] != status) {
  389. cache[ID] = status == null ? "null" : status;
  390. if (watch2) {
  391. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], cache);
  392. {
  393. console.log("save local status :", cache[ID], "status = ", status, "get local status :", Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"])[ID]);
  394. }
  395. window.localStorage.setItem(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_status_update__"], JSON.stringify({
  396. "id": ID,
  397. "status": cache[ID]
  398. }));
  399. }
  400. createStatus(cache[ID], cur);
  401. }
  402. } else {
  403. console.log("query result is undefined");
  404. }
  405. }
  406. }
  407. async function addProcess(reload = true, doms = void 0, asyncAc = false) {
  408. var _a;
  409. let problems_doms = Array.isArray(doms) ? doms : loadProblems();
  410. const cache = getLocalProblemStatus();
  411. let uid = 0;
  412. for (let i = 0; i < problems_doms.length; i++) {
  413. let cur = problems_doms[i].parentElement;
  414. if (!(cur instanceof HTMLElement)) {
  415. continue;
  416. }
  417. const ID = getId((_a = problems_doms[i]) == null ? void 0 : _a.href);
  418. if (!ID) {
  419. continue;
  420. }
  421. if (install_pos()) {
  422. cur.style.listStyleType = "none";
  423. }
  424. if (!cache[ID] || cache[ID] != STATUS["AC"] && asyncAc) {
  425. await sleep(200);
  426. await queryStatus(ID, cache, cur, false);
  427. } else {
  428. let status = cache[ID];
  429. uid++;
  430. createStatus(status, cur);
  431. }
  432. }
  433. {
  434. console.log("cache num :", uid, ",tot:", A.length);
  435. }
  436. getProcess();
  437. if (reload) {
  438. let cnt = 10;
  439. let timeId = setInterval(() => {
  440. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], cache);
  441. getProcess();
  442. cnt--;
  443. if (cnt == 0) {
  444. window.clearInterval(timeId);
  445. }
  446. }, 3e3);
  447. }
  448. }
  449. const submitProblems = (url = window.location.href, timeout = 500) => {
  450. const ID = getId(url);
  451. if (!ID) {
  452. return;
  453. }
  454. setTimeout(() => {
  455. const cache = getLocalProblemStatus();
  456. {
  457. console.log("ID:", ID, "query status: ", cache[ID]);
  458. }
  459. queryStatus(ID, cache, void 0, true);
  460. }, timeout);
  461. };
  462. const watchLinkStatusUpdate = (e) => {
  463. var _a;
  464. if (e.key != __0X3F_PROBLEM_KEYS__["__0x3f_problmes_status_update__"]) {
  465. return;
  466. }
  467. let { id, status } = JSON.parse(e.newValue);
  468. if (!id || !status) {
  469. return;
  470. }
  471. let thisLink = `https://leetcode.cn/problems/${id}`;
  472. {
  473. console.log("update", thisLink, "status", status);
  474. }
  475. let link = document.querySelector(`${linkCssSelector}[href^="https://leetcode.cn/problems/${id}"]`);
  476. if (!link || !(link == null ? void 0 : link.parentElement)) {
  477. let doms = loadProblems();
  478. for (let i = 0; i < doms.length; i++) {
  479. if (!doms[i] || !((_a = doms[i]) == null ? void 0 : _a.parentElement)) {
  480. continue;
  481. }
  482. if (doms[i].href.indexOf(thisLink) != -1) {
  483. link = doms[i];
  484. break;
  485. }
  486. }
  487. }
  488. createStatus(status, link);
  489. };
  490. function getAcCountKey(k) {
  491. if (!k) return "";
  492. return `0x3f_ac_key_${k}`;
  493. }
  494. function deleteAllACCountKeys() {
  495. let urls = initUrls();
  496. let keys = [];
  497. for (let urlInfo of urls) {
  498. let key = getAcCountKey(urlInfo.link);
  499. Cache$1.remove(key);
  500. keys.push(key);
  501. }
  502. Cache$1.remove(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"]);
  503. return keys;
  504. }
  505. function getProcess() {
  506. loadProblems();
  507. const cache = getLocalProblemStatus();
  508. let cnt = 0;
  509. for (let i = 0; i < A.length; i++) {
  510. let ID = getId(A[i].href);
  511. if (ID && cache[ID] == STATUS["AC"]) {
  512. cnt++;
  513. }
  514. }
  515. let url = window.location.href;
  516. if (A.length > 0 && getAcCountKey(url)) {
  517. Cache$1.set(getAcCountKey(url), { "tot": A.length, "ac": cnt });
  518. }
  519. return [cnt, A.length];
  520. }
  521. function getLocalProblemStatus() {
  522. return Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], true, Object.name);
  523. }
  524. function getRandomInfo(array) {
  525. if (!Array.isArray(array)) return void 0;
  526. return array[Math.floor(Math.random() * array.length)];
  527. }
  528. async function randomProblem() {
  529. let allProbmems;
  530. if (!Array.isArray(allProbmems) || allProbmems.length == 0) {
  531. let response = await getProblemsJSON();
  532. if (Array.isArray(response)) {
  533. allProbmems = [...response];
  534. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_all_problems__"], [...response]);
  535. }
  536. } else {
  537. allProbmems = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_all_problems__"], true, Array.name);
  538. }
  539. if (!Array.isArray(allProbmems)) {
  540. ElementPlus.ElMessage({
  541. type: "error",
  542. message: "随机题目失败获取不到任何信息 !请如果出现这种情况,请前往 https://github.com/wuxin0011/tampermonkey-script/issues 反馈",
  543. duration: 6e3
  544. });
  545. return;
  546. }
  547. let config = initObj();
  548. let urlsData = initUrls();
  549. let set = /* @__PURE__ */ new Set();
  550. for (let info of urlsData) {
  551. if (info.link && info.select) {
  552. set.add(info.link);
  553. }
  554. }
  555. let infos = [];
  556. let acMap = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], true, Object.name);
  557. {
  558. console.log("config and set", config, set);
  559. console.log("acMap", acMap);
  560. }
  561. let count = 0;
  562. next:
  563. for (let info of allProbmems) {
  564. if (!(info == null ? void 0 : info.problemUrl) || !set.has(info == null ? void 0 : info.problemUrl) || !Array.isArray(info.problems) || info.problems.length == 0) {
  565. continue;
  566. }
  567. {
  568. console.log("info=>", info.problemUrl, info.title);
  569. }
  570. for (let i = 0; Array.isArray(info.problems) && i < info.problems.length; i++) {
  571. try {
  572. let { title, url, member, score, titleSlug } = info.problems[i];
  573. if (!url || !title) continue;
  574. if (isDev()) {
  575. }
  576. if (!(config == null ? void 0 : config.showAcConfig) && acMap[titleSlug] == "ac") {
  577. continue;
  578. }
  579. if (!(config == null ? void 0 : config.visiableMember) && member) {
  580. continue;
  581. }
  582. if (score != 0 && (score < (config == null ? void 0 : config.min) || score > (config == null ? void 0 : config.max))) {
  583. continue;
  584. }
  585. infos.push({ title, url, member, score, titleSlug, "status": acMap[titleSlug] });
  586. } catch (e) {
  587. console.log("error", e);
  588. }
  589. if (count >= 100) {
  590. break next;
  591. }
  592. count += 1;
  593. }
  594. }
  595. {
  596. console.log("filter infos = ", infos);
  597. }
  598. let data = getRandomInfo(infos);
  599. {
  600. console.log("your config:", config, set);
  601. console.log("randomInfo : ", data);
  602. }
  603. ElementPlus.ElMessage({
  604. dangerouslyUseHTMLString: !!(data && (data == null ? void 0 : data.url) && (data == null ? void 0 : data.title)),
  605. type: (data == null ? void 0 : data.url) && (data == null ? void 0 : data.title) ? "success" : "error",
  606. 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>` : `没有符合条件的题目,请重新配置条件!`,
  607. duration: 6e3
  608. });
  609. }
  610. async function GetHubJSONInfo(url) {
  611. return fetch(url, {
  612. method: "get",
  613. mode: "cors"
  614. }).then((res) => res.json());
  615. }
  616. async function getProblemsJSON() {
  617. return GetHubJSONInfo("https://raw.githubusercontent.com/wuxin0011/tampermonkey-script/main/0x3f-leetcode/0x3f.json");
  618. }
  619. async function PostLeetCodeApi(data) {
  620. return fetch("https://leetcode.cn/graphql/", {
  621. method: "POST",
  622. credentials: "include",
  623. headers: {
  624. "Content-Type": "application/json"
  625. },
  626. body: JSON.stringify(data)
  627. }).then((res) => res.json());
  628. }
  629. async function getProblemAcInfo(titleSlug) {
  630. return PostLeetCodeApi(postData(titleSlug));
  631. }
  632. const _export_sfc = (sfc, props) => {
  633. const target = sfc.__vccOpts || sfc;
  634. for (const [key, val] of props) {
  635. target[key] = val;
  636. }
  637. return target;
  638. };
  639. const _sfc_main$1 = {};
  640. const _hoisted_1$1 = /* @__PURE__ */ vue.createStaticVNode('<h2 style="color:red !important;" data-v-49e5e62d> 0. 同步功能使用前请确保为登录状态 </h2><h2 data-v-49e5e62d> 1. 为什么部分题单出现统计数量为 <em data-v-49e5e62d> 0 </em> 情况 ? </h2><p data-v-49e5e62d>防止一次性访问题单太多,对服务器产生压力,所以采用单个题单访问然后保存状态 , 这样避免访问量问题</p><p data-v-49e5e62d>默认情况下会缓存访问的题单情况,对于没有访问的题单,可以手动在对应题单中同步</p><h2 data-v-49e5e62d> 2.题单有时候会出现不同步 </h2><p data-v-49e5e62d>这个没啥问题,题目状态根据用户提交题目情况会实时更新,只会在提交访问一次</p><h2 data-v-49e5e62d> 3. 如何使用随机题目? </h2><p data-v-49e5e62d>这个可以根据自己喜好来配置,配置好之后,可以使用 <em data-v-49e5e62d> ctrl + alt + j </em> 触发 </p><h2 data-v-49e5e62d> 4.反馈 </h2>', 9);
  641. function _sfc_render(_ctx, _cache) {
  642. const _component_el_link = vue.resolveComponent("el-link");
  643. return vue.openBlock(), vue.createElementBlock("div", null, [
  644. _hoisted_1$1,
  645. vue.createElementVNode("p", null, [
  646. vue.createTextVNode("你可以"),
  647. vue.createVNode(_component_el_link, {
  648. underline: false,
  649. href: "https://greatest.deepsurf.us/zh-CN/scripts/501134-0x3f-problem-solution/feedback",
  650. type: "primary",
  651. target: "_blank"
  652. }, {
  653. default: vue.withCtx(() => [
  654. vue.createTextVNode("点击")
  655. ]),
  656. _: 1
  657. }),
  658. vue.createTextVNode("这里反馈 ,或者访问 github 提一个 "),
  659. vue.createVNode(_component_el_link, {
  660. target: "_blank",
  661. underline: false,
  662. href: "https://github.com/wuxin0011/tampermonkey-script/issues",
  663. type: "primary"
  664. }, {
  665. default: vue.withCtx(() => [
  666. vue.createTextVNode("issues")
  667. ]),
  668. _: 1
  669. })
  670. ])
  671. ]);
  672. }
  673. const Q1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-49e5e62d"]]);
  674. function Message(title = "确认操作", callback = () => {
  675. }, canlcelCallback = () => {
  676. }) {
  677. ElementPlus.ElMessageBox.confirm(
  678. `${title} ?`,
  679. "警告",
  680. {
  681. confirmButtonText: "确认",
  682. cancelButtonText: "取消",
  683. type: "warning"
  684. }
  685. ).then(() => {
  686. callback();
  687. }).catch(() => {
  688. ElementPlus.ElMessage({
  689. type: "info",
  690. message: "已取消"
  691. });
  692. canlcelCallback();
  693. });
  694. }
  695. const _hoisted_1 = { class: "dialog-footer" };
  696. const _hoisted_2 = { class: "processs-flex" };
  697. const _hoisted_3 = { style: { "text-align": "center", "color": "#121212" } };
  698. const TARGET_URL = "https://leetcode.cn/u/endlesscheng/";
  699. const formLabelWidth = "44px";
  700. const _sfc_main = {
  701. __name: "App",
  702. setup(__props) {
  703. const sortType = vue.ref(0);
  704. const tableButtonSize = vue.ref("default");
  705. let tableData = vue.reactive(initUrls());
  706. const keywords = vue.ref("");
  707. const dialogTableVisible = vue.ref(false);
  708. const showAddLocalButton = vue.computed(() => isLeetCodeCircleUrl());
  709. let urlsData = vue.computed(() => {
  710. let map = /* @__PURE__ */ new Map();
  711. let infos = tableData.filter((info2) => {
  712. if ((info2 == null ? void 0 : info2.title) && (info2 == null ? void 0 : info2.link) && !map.has(info2.link)) {
  713. map.set(info2.link, info2);
  714. return info2 && (info2.title && info2.title.indexOf(keywords.value) != -1 || info2.link && info2.link.indexOf(keywords.value) != -1);
  715. } else {
  716. return false;
  717. }
  718. });
  719. let tot = 0, ac = 0;
  720. for (let i = 0, c = info.length; i < infos.length; i++) {
  721. let info2 = infos[i];
  722. if (info2["ac"] && info2["tot"]) {
  723. tot += info2["tot"];
  724. ac += info2["ac"];
  725. }
  726. if (!info2["id"]) {
  727. info2["id"] = c + 1;
  728. c++;
  729. }
  730. }
  731. let type = sortType.value;
  732. if (type == 0) {
  733. infos.sort((info1, info2) => info2.id - info1.id);
  734. } else if (type == 1) {
  735. infos.sort((info1, info2) => info2.tot - info1.tot);
  736. } else if (type == 2) {
  737. infos.sort((info1, info2) => info2.ac - info1.ac);
  738. } else if (type == 3) {
  739. infos.sort((info1, info2) => computeProcess(info2.ac, info2.tot) - computeProcess(info1.ac, info1.tot));
  740. }
  741. infos.unshift({ "title": "灵茶题单完成情况", "link": TARGET_URL, "tot": tot, "ac": ac, "id": 67108863 });
  742. return infos;
  743. });
  744. const rowIsDisabled = vue.computed(() => (info2) => asyncButtonLoad.value || info2 && info2.link == TARGET_URL);
  745. const isDisabbled = vue.computed(() => !!tableData.find((v) => (v == null ? void 0 : v.link) && (v == null ? void 0 : v.link.indexOf(window.location.href)) != -1));
  746. const dialogFormVisible = vue.ref(false);
  747. const computeProcess = (ac = 0, tot = 0) => {
  748. if (isNaN(ac) || isNaN(tot) || tot === 0) return 0;
  749. let p = 0;
  750. if (tot == ac) {
  751. return 100;
  752. }
  753. const s = String(ac / tot);
  754. try {
  755. let x1 = s.split(".")[1] || "";
  756. x1 = x1.padEnd(3, "0").substring(0, 3);
  757. p = Math.min(100, Number(x1) / 10);
  758. } catch (e) {
  759. console.log("calc error", e.message, s == void 0, ac, tot);
  760. p = (ac / tot).toFixed(3) * 100;
  761. }
  762. return isNaN(p) ? 0 : p;
  763. };
  764. const processColors = [
  765. { color: "#f56c6c", percentage: 20 },
  766. { color: "#1989fa", percentage: 40 },
  767. { color: "#e6a23c", percentage: 60 },
  768. { color: "#6f7ad3", percentage: 80 },
  769. { color: "#67c23a", percentage: 100 }
  770. ];
  771. const fromData = vue.reactive(initObj());
  772. vue.watch(fromData, () => {
  773. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  774. });
  775. const info = vue.reactive({
  776. title: "",
  777. link: "",
  778. status: "add"
  779. });
  780. const addlocal = () => {
  781. if (!isDisabbled) {
  782. return;
  783. }
  784. let [cur, tot] = getProcess();
  785. tableData.unshift({ title: document.title, link: window.location.href, "ac": cur, "tot": tot, "id": tableData.length + 10 });
  786. };
  787. const updateIndex = vue.ref(-1);
  788. const handlerProblems = (status, updateInfo = { title: "", link: "", id: 0 }, index = -1) => {
  789. dialogFormVisible.value = true;
  790. info.status = status;
  791. updateIndex.value = updateInfo.id;
  792. Object.assign(info, updateInfo);
  793. };
  794. const handlerMessage = (u, title, link) => {
  795. const a = u ? "添加" : "修改";
  796. const error = !(!!title && isHttp(link));
  797. if (error) {
  798. ElementPlus.ElMessage.error(`${a} 失败 请保证标题或者链接有效 `);
  799. } else {
  800. ElementPlus.ElMessage.success(`${a} 成功 `);
  801. }
  802. return !error;
  803. };
  804. const addOrUpdate = () => {
  805. if (!handlerMessage(info.status == "add", info.title, info.link)) {
  806. return;
  807. }
  808. if (info.status == "add") {
  809. tableData.unshift({ title: info.title, link: info.link, "ac": 0, "tot": 0, "id": tableData.length + 10 });
  810. } else {
  811. let id = updateIndex.value;
  812. for (let i = 0; i < tableData.length; i++) {
  813. if (tableData[i] && tableData[i].id && tableData[i]["id"] == id) {
  814. tableData[i]["title"] = info.title;
  815. tableData[i]["link"] = info.link;
  816. break;
  817. }
  818. }
  819. }
  820. dialogFormVisible.value = false;
  821. };
  822. const deleteProblems = (id) => {
  823. for (let i = 0; i < tableData.length; i++) {
  824. if (tableData[i] && tableData[i].id && tableData[i]["id"] == id) {
  825. delete tableData[i];
  826. break;
  827. }
  828. }
  829. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], vue.toRaw(tableData));
  830. };
  831. const handlerDefault = () => {
  832. Message("确认使用默认题单,将会重置题单", () => {
  833. for (let i = 0; i < tableData.length; i++) {
  834. delete tableData[i];
  835. }
  836. let infos = computeAcInfo(defaultUrls);
  837. for (let item of infos) {
  838. tableData.unshift(item);
  839. }
  840. ElementPlus.ElMessage({
  841. type: "success",
  842. message: "重置成功"
  843. });
  844. });
  845. };
  846. window.addEventListener("beforeunload", () => {
  847. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], vue.toRaw(tableData).filter((u) => u != null && u != void 0));
  848. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_update__"], true);
  849. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"], false);
  850. });
  851. vue.onMounted(async () => {
  852. if (support_plugins()) {
  853. let times = 30;
  854. let loadTimeId = setInterval(() => {
  855. let a = queryProblem();
  856. times--;
  857. if (Array.isArray(a) && a.length > 0) {
  858. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  859. addProcess();
  860. window.clearInterval(loadTimeId);
  861. }
  862. if (times == 0) {
  863. window.clearInterval(loadTimeId);
  864. }
  865. }, 200);
  866. }
  867. window.addEventListener("storage", (e) => {
  868. watchLinkStatusUpdate(e);
  869. });
  870. });
  871. _GM_registerMenuCommand(`题单配置信息🛠`, () => {
  872. dialogTableVisible.value = !dialogTableVisible.value;
  873. }, { title: "AC标记安装位置,默认左侧,刷新生效" });
  874. const selectHandlerChange = (row) => {
  875. let infos = [];
  876. for (let i = 0; i < urlsData.value.length; i++) {
  877. if (urlsData.value[i]["link"] == TARGET_URL) continue;
  878. infos.push(vue.toRaw(Object.assign({}, urlsData.value[i])));
  879. }
  880. for (let i = 0; i < tableData.length; i++) {
  881. if (row.id == tableData[i].id) {
  882. tableData[i].select = row.select;
  883. break;
  884. }
  885. }
  886. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], infos);
  887. };
  888. const asyncButtonLoad = vue.ref(false);
  889. const asyncButtonLoadBreak = vue.ref(false);
  890. const showProcess = vue.ref(false);
  891. const allProblemNum = vue.ref(0);
  892. const asyncProblemNum = vue.ref(0);
  893. const asyncVisableDialog = vue.ref(false);
  894. const showProblemsProcessInfo = vue.reactive({
  895. title: "",
  896. link: "",
  897. cnt: "",
  898. ac: "",
  899. id: "",
  900. select: true
  901. });
  902. const showProblemsInfo = (info2 = {}) => {
  903. asyncVisableDialog.value = !asyncVisableDialog.value;
  904. Object.assign(showProblemsProcessInfo, info2);
  905. };
  906. const loadProcess = vue.computed(() => computeProcess(asyncProblemNum.value, allProblemNum.value));
  907. const asyncProblemStatus = async (row = {}) => {
  908. if (!(row == null ? void 0 : row.link)) return;
  909. let callback = async () => {
  910. var _a, _b, _c, _d, _e;
  911. let rowData = void 0;
  912. let asyncAll = (row == null ? void 0 : row.link) == TARGET_URL;
  913. let cache = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], true, Object.name);
  914. {
  915. console.log("async ac cache:", cache);
  916. }
  917. let map = /* @__PURE__ */ new Map();
  918. try {
  919. for (let info2 of tableData) {
  920. if ((info2 == null ? void 0 : info2.link) && (info2 == null ? void 0 : info2.title) && (info2 == null ? void 0 : info2.id)) {
  921. if (rowData == void 0 && (info2 == null ? void 0 : info2.id) == row.id) {
  922. rowData = info2;
  923. }
  924. if (!map.has(info2.link)) {
  925. map.set(info2.link, info2);
  926. }
  927. }
  928. }
  929. if (rowData) {
  930. rowData.loading = true;
  931. }
  932. asyncButtonLoad.value = true;
  933. asyncButtonLoadBreak.value = false;
  934. allProblemNum.value = 0;
  935. asyncProblemNum.value = 0;
  936. showProcess.value = true;
  937. await sleep(500);
  938. let jsonInfo = await getProblemsJSON();
  939. if (!Array.isArray(jsonInfo)) {
  940. jsonInfo = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_all_problems__"], true, Array.name);
  941. } else {
  942. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_all_problems__"], jsonInfo);
  943. }
  944. let datas = [];
  945. for (let i = 0; Array.isArray(jsonInfo) && i < jsonInfo.length; i++) {
  946. let key = `${(_a = jsonInfo[i]) == null ? void 0 : _a.problemUrl}`;
  947. let origin = map.get(key);
  948. if (!origin) {
  949. continue;
  950. }
  951. if (asyncAll) {
  952. for (let p of jsonInfo[i].problems) {
  953. datas.push(Object.assign({ "origin": jsonInfo[i].problemUrl }, p));
  954. }
  955. origin.tot = Math.max(jsonInfo[i].problems.length, (origin == null ? void 0 : origin.tot) ?? 0);
  956. origin.ac = 0;
  957. } else if (jsonInfo[i].problemUrl == row.link) {
  958. for (let p of jsonInfo[i].problems) {
  959. datas.push(Object.assign({ "origin": jsonInfo[i].problemUrl }, p));
  960. }
  961. origin.tot = Math.max(jsonInfo[i].problems.length, (origin == null ? void 0 : origin.tot) ?? 0);
  962. origin.ac = 0;
  963. break;
  964. }
  965. }
  966. if (Array.isArray(datas) && datas.length > 0) {
  967. allProblemNum.value = datas.length;
  968. asyncProblemNum.value = 0;
  969. let pre = 0;
  970. for (let i = 0; i < datas.length; i++) {
  971. let info2 = datas[i];
  972. try {
  973. if (asyncButtonLoadBreak.value) {
  974. break;
  975. }
  976. await sleep(200);
  977. let ID = info2.titleSlug;
  978. let key = `${info2.origin}`;
  979. let origin = map.get(key);
  980. if (cache[ID] != "ac") {
  981. let response = await getProblemAcInfo(ID);
  982. const status = (_c = (_b = response == null ? void 0 : response.data) == null ? void 0 : _b.question) == null ? void 0 : _c.status;
  983. cache[ID] = status == null ? "null" : status;
  984. }
  985. if (origin) {
  986. if (cache[ID] == "ac") {
  987. origin.ac = origin.ac + 1;
  988. }
  989. }
  990. if (isDev()) {
  991. }
  992. asyncProblemNum.value += 1;
  993. if (loadProcess.value < pre && isDev()) {
  994. console.warn("calc result is error");
  995. }
  996. pre = loadProcess.value;
  997. } catch (e) {
  998. if (isDev()) {
  999. console.log("process error", e.message, "asyncProblemNum.value", asyncProblemNum.value, "all", allProblemNum.value);
  1000. }
  1001. }
  1002. if (i % 100 == 0) {
  1003. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], Object.assign({}, cache));
  1004. }
  1005. }
  1006. }
  1007. } catch (e) {
  1008. console.log("error", e);
  1009. } finally {
  1010. if (rowData) {
  1011. rowData.loading = false;
  1012. }
  1013. asyncButtonLoad.value = false;
  1014. for (let i = 0; i < tableData.length; i++) {
  1015. if (getAcCountKey((_d = tableData[i]) == null ? void 0 : _d.link)) {
  1016. Cache$1.set(getAcCountKey(tableData[i].link), { "tot": tableData[i].tot, "ac": tableData[i].ac });
  1017. }
  1018. if ((_e = tableData[i]) == null ? void 0 : _e.loading) {
  1019. tableData[i].loading = false;
  1020. }
  1021. }
  1022. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], vue.toRaw(tableData));
  1023. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], Object.assign({}, cache));
  1024. {
  1025. console.log("同步完成🥰", asyncProblemNum.value, allProblemNum.value, loadProcess.value);
  1026. }
  1027. await sleep(500);
  1028. ElementPlus.ElMessage({
  1029. type: allProblemNum.value == asyncProblemNum.value ? "success" : asyncButtonLoadBreak.value ? "error" : "warning",
  1030. message: allProblemNum.value == asyncProblemNum.value ? `同步完成🥰` : asyncButtonLoadBreak.value ? `同步中断 ${loadProcess.value}% ` : `同步率 ${loadProcess.value}% `,
  1031. duration: 3e3
  1032. });
  1033. await sleep(6e3);
  1034. allProblemNum.value = 0;
  1035. asyncProblemNum.value = 0;
  1036. showProcess.value = false;
  1037. asyncButtonLoadBreak.value = false;
  1038. }
  1039. };
  1040. if (row.link == TARGET_URL) {
  1041. Message("该操作将同步所有题单,耗时可能较长 确认操作?", callback);
  1042. } else {
  1043. callback();
  1044. }
  1045. };
  1046. const q1 = vue.ref(false);
  1047. vue.ref(false);
  1048. return (_ctx, _cache) => {
  1049. const _component_el_dialog = vue.resolveComponent("el-dialog");
  1050. const _component_el_input = vue.resolveComponent("el-input");
  1051. const _component_el_form_item = vue.resolveComponent("el-form-item");
  1052. const _component_el_form = vue.resolveComponent("el-form");
  1053. const _component_el_button = vue.resolveComponent("el-button");
  1054. const _component_el_progress = vue.resolveComponent("el-progress");
  1055. const _component_el_col = vue.resolveComponent("el-col");
  1056. const _component_el_option = vue.resolveComponent("el-option");
  1057. const _component_el_select = vue.resolveComponent("el-select");
  1058. const _component_el_tooltip = vue.resolveComponent("el-tooltip");
  1059. const _component_el_row = vue.resolveComponent("el-row");
  1060. const _component_el_table_column = vue.resolveComponent("el-table-column");
  1061. const _component_el_link = vue.resolveComponent("el-link");
  1062. const _component_el_switch = vue.resolveComponent("el-switch");
  1063. const _component_el_table = vue.resolveComponent("el-table");
  1064. return vue.openBlock(), vue.createElementBlock("div", null, [
  1065. vue.createVNode(_component_el_dialog, {
  1066. modelValue: q1.value,
  1067. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => q1.value = $event)
  1068. }, {
  1069. default: vue.withCtx(() => [
  1070. vue.createVNode(Q1)
  1071. ]),
  1072. _: 1
  1073. }, 8, ["modelValue"]),
  1074. vue.createVNode(_component_el_dialog, {
  1075. modelValue: dialogFormVisible.value,
  1076. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => dialogFormVisible.value = $event),
  1077. title: `${info.status == "add" ? "添加" : "编辑"}`,
  1078. width: "400"
  1079. }, {
  1080. footer: vue.withCtx(() => [
  1081. vue.createElementVNode("div", _hoisted_1, [
  1082. vue.createVNode(_component_el_button, {
  1083. onClick: _cache[3] || (_cache[3] = ($event) => dialogFormVisible.value = false)
  1084. }, {
  1085. default: vue.withCtx(() => [
  1086. vue.createTextVNode("取消")
  1087. ]),
  1088. _: 1
  1089. }),
  1090. vue.createVNode(_component_el_button, { onClick: addOrUpdate }, {
  1091. default: vue.withCtx(() => [
  1092. vue.createTextVNode(" 确认 ")
  1093. ]),
  1094. _: 1
  1095. })
  1096. ])
  1097. ]),
  1098. default: vue.withCtx(() => [
  1099. vue.createVNode(_component_el_form, null, {
  1100. default: vue.withCtx(() => [
  1101. vue.createVNode(_component_el_form_item, {
  1102. label: "标题",
  1103. "label-width": formLabelWidth
  1104. }, {
  1105. default: vue.withCtx(() => [
  1106. vue.createVNode(_component_el_input, {
  1107. modelValue: info.title,
  1108. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => info.title = $event),
  1109. autocomplete: "off"
  1110. }, null, 8, ["modelValue"])
  1111. ]),
  1112. _: 1
  1113. }),
  1114. vue.createVNode(_component_el_form_item, {
  1115. label: "链接",
  1116. "label-width": formLabelWidth
  1117. }, {
  1118. default: vue.withCtx(() => [
  1119. vue.createVNode(_component_el_input, {
  1120. modelValue: info.link,
  1121. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => info.link = $event),
  1122. autocomplete: "off"
  1123. }, null, 8, ["modelValue"])
  1124. ]),
  1125. _: 1
  1126. })
  1127. ]),
  1128. _: 1
  1129. })
  1130. ]),
  1131. _: 1
  1132. }, 8, ["modelValue", "title"]),
  1133. vue.createVNode(_component_el_dialog, {
  1134. modelValue: dialogTableVisible.value,
  1135. "onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => dialogTableVisible.value = $event),
  1136. title: asyncButtonLoadBreak.value ? `同步已中断 ${asyncProblemNum.value}/${allProblemNum.value}` : showProcess.value ? loadProcess.value < 100 ? `同步中...${asyncProblemNum.value}/${allProblemNum.value}` : "统计完成" : "题单信息",
  1137. width: "60%"
  1138. }, {
  1139. default: vue.withCtx(() => [
  1140. showProcess.value ? (vue.openBlock(), vue.createBlock(_component_el_progress, {
  1141. key: 0,
  1142. color: processColors,
  1143. percentage: loadProcess.value,
  1144. "stroke-width": 15,
  1145. striped: "",
  1146. "striped-flow": "",
  1147. style: { "margin-bottom": "20px" },
  1148. status: `${loadProcess.value == 100 ? "success" : ""}`
  1149. }, null, 8, ["percentage", "status"])) : vue.createCommentVNode("", true),
  1150. vue.createVNode(_component_el_row, { gutter: 10 }, {
  1151. default: vue.withCtx(() => [
  1152. vue.createVNode(_component_el_col, { span: 4 }, {
  1153. default: vue.withCtx(() => [
  1154. vue.createVNode(_component_el_input, {
  1155. modelValue: keywords.value,
  1156. "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => keywords.value = $event),
  1157. placeholder: "请输入关键词过滤",
  1158. clearable: ""
  1159. }, null, 8, ["modelValue"])
  1160. ]),
  1161. _: 1
  1162. }),
  1163. vue.createVNode(_component_el_col, { span: 20 }, {
  1164. default: vue.withCtx(() => [
  1165. showAddLocalButton.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1166. key: 0,
  1167. plain: "",
  1168. onClick: addlocal,
  1169. disabled: isDisabbled.value,
  1170. size: tableButtonSize.value
  1171. }, {
  1172. default: vue.withCtx(() => [
  1173. vue.createTextVNode(" 添加本页 ")
  1174. ]),
  1175. _: 1
  1176. }, 8, ["disabled", "size"])) : vue.createCommentVNode("", true),
  1177. showAddLocalButton.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1178. key: 1,
  1179. plain: "",
  1180. onClick: _cache[6] || (_cache[6] = ($event) => handlerProblems("add")),
  1181. size: tableButtonSize.value
  1182. }, {
  1183. default: vue.withCtx(() => [
  1184. vue.createTextVNode(" 自定义 ")
  1185. ]),
  1186. _: 1
  1187. }, 8, ["size"])) : vue.createCommentVNode("", true),
  1188. vue.createVNode(_component_el_select, {
  1189. modelValue: sortType.value,
  1190. "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => sortType.value = $event),
  1191. style: { "margin": "0 5px", "width": "100px" },
  1192. disabled: asyncButtonLoad.value
  1193. }, {
  1194. default: vue.withCtx(() => [
  1195. vue.createVNode(_component_el_option, {
  1196. label: "默认排序",
  1197. value: 0
  1198. }, {
  1199. default: vue.withCtx(() => [
  1200. vue.createTextVNode("默认排序")
  1201. ]),
  1202. _: 1
  1203. }),
  1204. vue.createVNode(_component_el_option, {
  1205. label: "题目数量",
  1206. value: 1
  1207. }, {
  1208. default: vue.withCtx(() => [
  1209. vue.createTextVNode("题目数量")
  1210. ]),
  1211. _: 1
  1212. }),
  1213. vue.createVNode(_component_el_option, {
  1214. label: "AC数量",
  1215. value: 2
  1216. }, {
  1217. default: vue.withCtx(() => [
  1218. vue.createTextVNode("AC数量")
  1219. ]),
  1220. _: 1
  1221. }),
  1222. vue.createVNode(_component_el_option, {
  1223. label: "完成度",
  1224. value: 3
  1225. }, {
  1226. default: vue.withCtx(() => [
  1227. vue.createTextVNode("完成度")
  1228. ]),
  1229. _: 1
  1230. })
  1231. ]),
  1232. _: 1
  1233. }, 8, ["modelValue", "disabled"]),
  1234. vue.createVNode(_component_el_tooltip, { content: "同步所有题单" }, {
  1235. default: vue.withCtx(() => [
  1236. vue.createVNode(_component_el_button, {
  1237. type: asyncButtonLoad.value ? "success" : "danger",
  1238. onClick: _cache[8] || (_cache[8] = ($event) => asyncProblemStatus({ "link": "https://leetcode.cn/u/endlesscheng/" })),
  1239. size: tableButtonSize.value,
  1240. loading: asyncButtonLoad.value
  1241. }, {
  1242. default: vue.withCtx(() => [
  1243. vue.createTextVNode(vue.toDisplayString(asyncButtonLoad.value ? "同步中" : "同步题单"), 1)
  1244. ]),
  1245. _: 1
  1246. }, 8, ["type", "size", "loading"])
  1247. ]),
  1248. _: 1
  1249. }),
  1250. asyncButtonLoad.value ? (vue.openBlock(), vue.createBlock(_component_el_tooltip, {
  1251. key: 2,
  1252. content: "点击中断同步"
  1253. }, {
  1254. default: vue.withCtx(() => [
  1255. asyncButtonLoad.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  1256. key: 0,
  1257. type: "warning",
  1258. text: "",
  1259. onClick: _cache[9] || (_cache[9] = ($event) => asyncButtonLoadBreak.value = !asyncButtonLoadBreak.value),
  1260. size: tableButtonSize.value
  1261. }, {
  1262. default: vue.withCtx(() => [
  1263. vue.createTextVNode(" 中断同步 ")
  1264. ]),
  1265. _: 1
  1266. }, 8, ["size"])) : vue.createCommentVNode("", true)
  1267. ]),
  1268. _: 1
  1269. })) : vue.createCommentVNode("", true),
  1270. vue.createVNode(_component_el_tooltip, { content: "随机一道灵茶题单中题目,快捷键 Ctrl + Alt + J 可以触发" }, {
  1271. default: vue.withCtx(() => [
  1272. vue.createVNode(_component_el_button, {
  1273. type: "primary",
  1274. text: "",
  1275. onClick: vue.unref(randomProblem),
  1276. size: tableButtonSize.value
  1277. }, {
  1278. default: vue.withCtx(() => [
  1279. vue.createTextVNode(" 随机题目 ")
  1280. ]),
  1281. _: 1
  1282. }, 8, ["onClick", "size"])
  1283. ]),
  1284. _: 1
  1285. })
  1286. ]),
  1287. _: 1
  1288. })
  1289. ]),
  1290. _: 1
  1291. }),
  1292. vue.createVNode(_component_el_table, {
  1293. data: vue.unref(urlsData),
  1294. height: "300",
  1295. style: { "width": "100%", "margin-top": "10px" }
  1296. }, {
  1297. default: vue.withCtx(() => [
  1298. vue.createVNode(_component_el_table_column, { type: "index" }),
  1299. vue.createVNode(_component_el_table_column, {
  1300. label: "标题",
  1301. width: "auto",
  1302. align: "center"
  1303. }, {
  1304. default: vue.withCtx((scope) => [
  1305. vue.createVNode(_component_el_link, {
  1306. href: scope.row.link,
  1307. target: "_blank",
  1308. type: "default"
  1309. }, {
  1310. default: vue.withCtx(() => [
  1311. vue.createTextVNode(vue.toDisplayString(scope.row.title), 1)
  1312. ]),
  1313. _: 2
  1314. }, 1032, ["href"])
  1315. ]),
  1316. _: 1
  1317. }),
  1318. vue.createVNode(_component_el_table_column, {
  1319. label: "随机",
  1320. width: "70",
  1321. align: "center"
  1322. }, {
  1323. default: vue.withCtx((scope) => [
  1324. vue.createVNode(_component_el_switch, {
  1325. modelValue: scope.row.select,
  1326. "onUpdate:modelValue": ($event) => scope.row.select = $event,
  1327. onChange: ($event) => selectHandlerChange(scope.row),
  1328. disabled: rowIsDisabled.value(scope.row),
  1329. size: "small"
  1330. }, null, 8, ["modelValue", "onUpdate:modelValue", "onChange", "disabled"])
  1331. ]),
  1332. _: 1
  1333. }),
  1334. vue.createVNode(_component_el_table_column, {
  1335. label: "AC",
  1336. width: "70",
  1337. align: "center"
  1338. }, {
  1339. default: vue.withCtx((scope) => [
  1340. vue.createVNode(_component_el_link, {
  1341. type: "success",
  1342. underline: false,
  1343. onClick: ($event) => showProblemsInfo(scope.row)
  1344. }, {
  1345. default: vue.withCtx(() => [
  1346. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.ac) ? 0 : scope.row.ac), 1)
  1347. ]),
  1348. _: 2
  1349. }, 1032, ["onClick"])
  1350. ]),
  1351. _: 1
  1352. }),
  1353. vue.createVNode(_component_el_table_column, {
  1354. label: "Total",
  1355. width: "70",
  1356. align: "center"
  1357. }, {
  1358. default: vue.withCtx((scope) => [
  1359. vue.createVNode(_component_el_link, {
  1360. type: "primary",
  1361. underline: false,
  1362. onClick: ($event) => showProblemsInfo(scope.row)
  1363. }, {
  1364. default: vue.withCtx(() => [
  1365. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.tot) ? 0 : scope.row.tot), 1)
  1366. ]),
  1367. _: 2
  1368. }, 1032, ["onClick"])
  1369. ]),
  1370. _: 1
  1371. }),
  1372. vue.createVNode(_component_el_table_column, {
  1373. label: "进度",
  1374. width: "70",
  1375. align: "center"
  1376. }, {
  1377. default: vue.withCtx((scope) => [
  1378. vue.createVNode(_component_el_link, {
  1379. onClick: ($event) => showProblemsInfo(scope.row),
  1380. type: "warning",
  1381. underline: false
  1382. }, {
  1383. default: vue.withCtx(() => {
  1384. var _a, _b, _c;
  1385. return [
  1386. 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)
  1387. ];
  1388. }),
  1389. _: 2
  1390. }, 1032, ["onClick"])
  1391. ]),
  1392. _: 1
  1393. }),
  1394. vue.createVNode(_component_el_table_column, {
  1395. label: "操作",
  1396. width: "200px",
  1397. align: "center"
  1398. }, {
  1399. default: vue.withCtx((scope) => [
  1400. vue.createVNode(_component_el_button, {
  1401. loading: scope.row.loading,
  1402. onClick: ($event) => asyncProblemStatus(scope.row),
  1403. size: "small",
  1404. type: "success",
  1405. disabled: rowIsDisabled.value(scope.row),
  1406. link: ""
  1407. }, {
  1408. default: vue.withCtx(() => [
  1409. vue.createTextVNode(vue.toDisplayString(scope.row.loading ? "" : "同步"), 1)
  1410. ]),
  1411. _: 2
  1412. }, 1032, ["loading", "onClick", "disabled"]),
  1413. vue.createVNode(_component_el_button, {
  1414. onClick: ($event) => handlerProblems("update", scope.row, scope.$index),
  1415. size: "small",
  1416. type: "primary",
  1417. disabled: rowIsDisabled.value(scope.row),
  1418. link: ""
  1419. }, {
  1420. default: vue.withCtx(() => [
  1421. vue.createTextVNode("编辑")
  1422. ]),
  1423. _: 2
  1424. }, 1032, ["onClick", "disabled"]),
  1425. vue.createVNode(_component_el_button, {
  1426. onClick: ($event) => deleteProblems(scope.row.id),
  1427. size: "small",
  1428. type: "danger",
  1429. link: "",
  1430. disabled: rowIsDisabled.value(scope.row)
  1431. }, {
  1432. default: vue.withCtx(() => [
  1433. vue.createTextVNode("删除")
  1434. ]),
  1435. _: 2
  1436. }, 1032, ["onClick", "disabled"])
  1437. ]),
  1438. _: 1
  1439. })
  1440. ]),
  1441. _: 1
  1442. }, 8, ["data"]),
  1443. vue.createVNode(_component_el_row, {
  1444. gutter: 10,
  1445. style: { "margin": "10px 0" }
  1446. }, {
  1447. default: vue.withCtx(() => [
  1448. vue.createVNode(_component_el_col, { span: 6 }, {
  1449. default: vue.withCtx(() => [
  1450. vue.createTextVNode(" 会员  "),
  1451. vue.createVNode(_component_el_tooltip, { content: "过滤会员题目,会员题不会出现在随机题目中,默认过滤" }, {
  1452. default: vue.withCtx(() => [
  1453. vue.createVNode(_component_el_switch, {
  1454. modelValue: fromData.visiableMember,
  1455. "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => fromData.visiableMember = $event)
  1456. }, null, 8, ["modelValue"])
  1457. ]),
  1458. _: 1
  1459. }),
  1460. vue.createTextVNode(" ac  "),
  1461. vue.createVNode(_component_el_tooltip, { content: "过滤AC的题目,AC题目出现在随机题目中,默认不过滤" }, {
  1462. default: vue.withCtx(() => [
  1463. vue.createVNode(_component_el_switch, {
  1464. modelValue: fromData.showAcConfig,
  1465. "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => fromData.showAcConfig = $event)
  1466. }, null, 8, ["modelValue"])
  1467. ]),
  1468. _: 1
  1469. })
  1470. ]),
  1471. _: 1
  1472. }),
  1473. vue.createVNode(_component_el_col, { span: 10 }, {
  1474. default: vue.withCtx(() => [
  1475. vue.createTextVNode("   "),
  1476. vue.createVNode(_component_el_tooltip, { content: "随机题目将会随机在这个区间中的题目" }, {
  1477. default: vue.withCtx(() => [
  1478. vue.createVNode(_component_el_link, {
  1479. underline: false,
  1480. type: "primary"
  1481. }, {
  1482. default: vue.withCtx(() => [
  1483. vue.createTextVNode("分数区间")
  1484. ]),
  1485. _: 1
  1486. })
  1487. ]),
  1488. _: 1
  1489. }),
  1490. vue.createTextVNode("   "),
  1491. vue.createVNode(_component_el_input, {
  1492. modelValue: fromData.min,
  1493. "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => fromData.min = $event),
  1494. "aria-placeholder": "",
  1495. placeholder: " min ",
  1496. style: { "width": "60px" }
  1497. }, null, 8, ["modelValue"]),
  1498. vue.createTextVNode("- "),
  1499. vue.createVNode(_component_el_input, {
  1500. modelValue: fromData.max,
  1501. "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => fromData.max = $event),
  1502. "aria-placeholder": "",
  1503. placeholder: " max",
  1504. style: { "width": "60px" }
  1505. }, null, 8, ["modelValue"])
  1506. ]),
  1507. _: 1
  1508. }),
  1509. vue.createVNode(_component_el_col, { span: 8 }, {
  1510. default: vue.withCtx(() => [
  1511. vue.createVNode(_component_el_tooltip, { content: "重置题单" }, {
  1512. default: vue.withCtx(() => [
  1513. vue.createVNode(_component_el_button, {
  1514. plain: "",
  1515. onClick: handlerDefault,
  1516. size: tableButtonSize.value,
  1517. disabled: showProcess.value
  1518. }, {
  1519. default: vue.withCtx(() => [
  1520. vue.createTextVNode(" 默认 ")
  1521. ]),
  1522. _: 1
  1523. }, 8, ["size", "disabled"])
  1524. ]),
  1525. _: 1
  1526. }),
  1527. vue.createVNode(_component_el_button, {
  1528. plain: "",
  1529. onClick: _cache[14] || (_cache[14] = ($event) => q1.value = !q1.value),
  1530. size: tableButtonSize.value
  1531. }, {
  1532. default: vue.withCtx(() => [
  1533. vue.createTextVNode(" 使用说明 ")
  1534. ]),
  1535. _: 1
  1536. }, 8, ["size"])
  1537. ]),
  1538. _: 1
  1539. })
  1540. ]),
  1541. _: 1
  1542. })
  1543. ]),
  1544. _: 1
  1545. }, 8, ["modelValue", "title"]),
  1546. vue.createVNode(_component_el_dialog, {
  1547. modelValue: asyncVisableDialog.value,
  1548. "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => asyncVisableDialog.value = $event),
  1549. width: "35%"
  1550. }, {
  1551. default: vue.withCtx(() => [
  1552. vue.createElementVNode("p", null, [
  1553. vue.createVNode(_component_el_link, {
  1554. href: showProblemsProcessInfo.link,
  1555. type: "info",
  1556. underline: false
  1557. }, {
  1558. default: vue.withCtx(() => [
  1559. vue.createTextVNode(vue.toDisplayString(showProblemsProcessInfo.title), 1)
  1560. ]),
  1561. _: 1
  1562. }, 8, ["href"])
  1563. ]),
  1564. vue.createElementVNode("div", _hoisted_2, [
  1565. vue.createVNode(_component_el_progress, {
  1566. type: "circle",
  1567. percentage: computeProcess(showProblemsProcessInfo.ac, showProblemsProcessInfo.tot),
  1568. color: processColors
  1569. }, {
  1570. default: vue.withCtx(({ percentage }) => [
  1571. vue.createElementVNode("p", null, vue.toDisplayString(percentage) + "%", 1)
  1572. ]),
  1573. _: 1
  1574. }, 8, ["percentage"])
  1575. ]),
  1576. vue.createElementVNode("p", _hoisted_3, vue.toDisplayString(showProblemsProcessInfo.ac) + " / " + vue.toDisplayString(showProblemsProcessInfo.tot), 1)
  1577. ]),
  1578. _: 1
  1579. }, 8, ["modelValue"])
  1580. ]);
  1581. };
  1582. }
  1583. };
  1584. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-003e83a0"]]);
  1585. const cssLoader = (e) => {
  1586. const t = GM_getResourceText(e);
  1587. return GM_addStyle(t), t;
  1588. };
  1589. cssLoader("elementPlusCss");
  1590. const stopRankingKey = "__is_stop_rating_ranking__";
  1591. let conetstTimeId = null;
  1592. function run$1() {
  1593. const container = document.querySelector(".contest-question-info .list-group");
  1594. if (!container) return;
  1595. const ls = Array.from(container.querySelectorAll(".list-group-item .pull-right"));
  1596. for (let i = 0; i < 4; i++) {
  1597. if (i >= ls.length) {
  1598. break;
  1599. }
  1600. if (ls[i] instanceof HTMLElement) {
  1601. ls[i].textContent = "0";
  1602. }
  1603. }
  1604. window.clearInterval(conetstTimeId);
  1605. }
  1606. function startStopRanking() {
  1607. if (!isContest(window.location.href)) {
  1608. return;
  1609. }
  1610. const isNext = !!document.querySelector("#__next");
  1611. if (isNext) {
  1612. return;
  1613. }
  1614. const use = Cache$1.get(stopRankingKey);
  1615. if (use) {
  1616. conetstTimeId = setInterval(() => {
  1617. run$1();
  1618. }, 10);
  1619. }
  1620. _GM_registerMenuCommand(`${use ? "使用" : "关闭"} 排行榜`, () => {
  1621. Cache$1.set(stopRankingKey, !use);
  1622. window.location.reload();
  1623. }, { title: "对于不想看到排行榜的可以使用此功能 默认开启" });
  1624. }
  1625. const local_url = window.location.href;
  1626. let loadID = 0;
  1627. let submitCnt = 0;
  1628. function watchDom(dom2) {
  1629. if (!(dom2 instanceof HTMLElement)) {
  1630. return;
  1631. }
  1632. let m = new MutationObserver(() => {
  1633. if (submitCnt % 2 == 1) {
  1634. submitProblems(local_url);
  1635. }
  1636. submitCnt++;
  1637. });
  1638. m.observe(dom2, {
  1639. childList: true,
  1640. attributes: true
  1641. });
  1642. }
  1643. const randomProblemKey = () => Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_random_problems_key__"]) == void 0 ? true : Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_random_problems_key__"]);
  1644. let Container = null;
  1645. Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_button_is_none__"], true, Boolean.name);
  1646. const start = () => {
  1647. Container = document.createElement("div");
  1648. const body = document.querySelector("body");
  1649. body.append(Container);
  1650. Container.style.display = "block";
  1651. return Container;
  1652. };
  1653. let dom = start();
  1654. const VueApp = vue.createApp(App);
  1655. VueApp.use(ElementPlus).mount(dom);
  1656. if (isProblem() || isLeetCodeCircleUrl()) {
  1657. _GM_registerMenuCommand(`随机一道题 ☕`, randomProblem, { title: "随机一道题目,你可以通过ctrl+atl+j显示一道题目" });
  1658. _GM_registerMenuCommand(`${randomProblemKey() ? "关闭" : "启用"} 随机题目快捷键 ☕`, () => {
  1659. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_random_problems_key__"], !randomProblemKey());
  1660. window.location.reload();
  1661. }, { title: "该功能是随机一道题的快捷键,你可以通过ctrl+atl+j显示一道题目" });
  1662. if (randomProblemKey()) {
  1663. document.addEventListener("keydown", async function(event) {
  1664. if (event.ctrlKey && event.altKey && event.key === "j") {
  1665. randomProblem();
  1666. }
  1667. });
  1668. }
  1669. }
  1670. function run() {
  1671. loadID++;
  1672. if (isProblem(local_url) || isContest(local_url)) {
  1673. if (isProblem(local_url) && loadID == 1) {
  1674. submitProblems(local_url);
  1675. }
  1676. setTimeout(() => {
  1677. let submitbutton = null;
  1678. const isNext = !!document.querySelector("#__next");
  1679. if (isProblem(local_url) || isNext) {
  1680. submitbutton = document.querySelector("div [data-e2e-locator=console-submit-button]");
  1681. } else {
  1682. let buttons = Array.from(document.querySelectorAll(".question-detail-bottom .pull-right button"));
  1683. for (let i = buttons.length - 1; i >= 0; i--) {
  1684. if (buttons[i].textContent.indexOf("提交解答") != -1) {
  1685. submitbutton = buttons[i];
  1686. break;
  1687. }
  1688. }
  1689. }
  1690. if (submitbutton) {
  1691. submitbutton.addEventListener("click", () => {
  1692. submitProblems(local_url, 10 * 1e3);
  1693. });
  1694. watchDom(submitbutton);
  1695. } else if (loadID < 10) {
  1696. run();
  1697. }
  1698. }, 3e3);
  1699. } else if (isLeetCodeCircleUrl(local_url)) {
  1700. _GM_registerMenuCommand(`安装到${install_pos() ? "右侧" : "左侧"} 🎁`, () => {
  1701. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_insert_pos__"], install_pos());
  1702. window.location.reload();
  1703. }, { title: "AC标记安装位置,默认左侧,刷新生效" });
  1704. _GM_registerMenuCommand(`清空题目状态缓存 🚀`, () => {
  1705. Message("确认清空题目状态缓存", () => {
  1706. deleteAllACCountKeys();
  1707. window.location.reload();
  1708. });
  1709. }, { title: "如果题目状态出现问题,可以试试,一般情况下不建议使用" });
  1710. _GM_registerMenuCommand(`同步题目状态 🚀`, () => {
  1711. Message("确认同步题目状态", async () => {
  1712. await addProcess(true, void 0, true);
  1713. });
  1714. }, { title: "如果不在同一个浏览器答题,会出现ac题目状态没有及时同步,可以使用此功能" });
  1715. _GM_registerMenuCommand(`${initObj().onlyUrls ? "仅在收藏题单页面生效" : "所有题单生效"}`, () => {
  1716. const u = initObj();
  1717. u.onlyUrls = !u.onlyUrls;
  1718. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"], u);
  1719. }, { title: "插件默认会在所有讨论发布页生效,如果只想在收藏链接生效,可以使用此功能" });
  1720. _GM_registerMenuCommand(`添加本页`, () => {
  1721. const urls = initUrls();
  1722. let ok = false;
  1723. let url = window.location.href;
  1724. for (let info of urls) {
  1725. if (!info || !(info == null ? void 0 : info.link)) {
  1726. continue;
  1727. }
  1728. if (info.link.indexOf(url) != -1) {
  1729. ok = true;
  1730. break;
  1731. }
  1732. }
  1733. if (ok) {
  1734. ElementPlus.ElMessage({
  1735. message: "收藏失败,链接已经存在!",
  1736. type: "error"
  1737. });
  1738. } else {
  1739. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  1740. try {
  1741. url = url.split("view")[0];
  1742. } catch (e) {
  1743. url = window.location.href;
  1744. }
  1745. }
  1746. urls.unshift({
  1747. title: document.title,
  1748. link: url
  1749. });
  1750. Container.style.display = "block";
  1751. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], urls);
  1752. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_update__"], true);
  1753. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"], true);
  1754. ElementPlus.ElMessage({
  1755. message: "收藏成功!刷新生效",
  1756. type: "success"
  1757. });
  1758. }
  1759. });
  1760. }
  1761. }
  1762. run();
  1763. startStopRanking();
  1764.  
  1765. })(Vue, ElementPlus);