0x3f-problem-solution

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

当前为 2024-10-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 0x3f-problem-solution
  3. // @namespace https://gf.qytechs.cn/zh-CN/scripts/501134-0x3f-problem-solution
  4. // @version 0.0.4.6
  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/problems/*
  13. // @match https://leetcode.cn/contest/weekly-contest-*/problems/*
  14. // @match https://leetcode.cn/contest/biweekly-contest-*/problems/*
  15. // @require https://cdn.jsdelivr.net/npm/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-a8cfbf3e]{color:#000;margin:10px 0}p[data-v-a8cfbf3e]{text-decoration:underline;font-size:14px}em[data-v-a8cfbf3e]{color:red}.m-setting-button[data-v-0d8147ce]{position:fixed;top:200px;right:0;z-index:100000}.m-button[data-v-0d8147ce]{margin-left:16px!important;padding:5px!important;font-size:14px!important}.processs-flex[data-v-0d8147ce]{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 _export_sfc = (sfc, props) => {
  80. const target = sfc.__vccOpts || sfc;
  81. for (const [key, val] of props) {
  82. target[key] = val;
  83. }
  84. return target;
  85. };
  86. const _sfc_main$2 = {};
  87. const _hoisted_1$2 = /* @__PURE__ */ vue.createElementVNode("p", null, " 1. 本人目前测试过,没有封号,但是对于查询过题目会缓存在本地,因此尽量不要清空浏览器缓存 ", -1);
  88. const _hoisted_2$2 = /* @__PURE__ */ vue.createElementVNode("p", null, " 2. 脚本会监控题做题提交状态 ,当题目提交时候会缓存题目状态,如果题单中有这个题目,会直接从缓存中获取 ", -1);
  89. const _hoisted_3$2 = [
  90. _hoisted_1$2,
  91. _hoisted_2$2
  92. ];
  93. function _sfc_render$1(_ctx, _cache) {
  94. return vue.openBlock(), vue.createElementBlock("div", null, _hoisted_3$2);
  95. }
  96. const Q1 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1]]);
  97. const _sfc_main$1 = {};
  98. const _withScopeId = (n) => (vue.pushScopeId("data-v-a8cfbf3e"), n = n(), vue.popScopeId(), n);
  99. const _hoisted_1$1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("h2", null, [
  100. /* @__PURE__ */ vue.createTextVNode(" 1. 为什么部分题单出现统计数量为 "),
  101. /* @__PURE__ */ vue.createElementVNode("em", null, " 0 "),
  102. /* @__PURE__ */ vue.createTextVNode(" 情况 ? ")
  103. ], -1));
  104. const _hoisted_2$1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("p", null, "防止一次性访问题单太多,对服务器产生压力,所以采用单个题单访问然后保存状态 , 这样避免访问量问题", -1));
  105. const _hoisted_3$1 = [
  106. _hoisted_1$1,
  107. _hoisted_2$1
  108. ];
  109. function _sfc_render(_ctx, _cache) {
  110. return vue.openBlock(), vue.createElementBlock("div", null, _hoisted_3$1);
  111. }
  112. const Q2 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-a8cfbf3e"]]);
  113. function Message(title = "确认操作", callback = () => {
  114. }, canlcelCallback = () => {
  115. }) {
  116. ElementPlus.ElMessageBox.confirm(
  117. `${title} ?`,
  118. "警告",
  119. {
  120. confirmButtonText: "确认",
  121. cancelButtonText: "取消",
  122. type: "warning"
  123. }
  124. ).then(() => {
  125. callback();
  126. }).catch(() => {
  127. ElementPlus.ElMessage({
  128. type: "info",
  129. message: "已取消"
  130. });
  131. canlcelCallback();
  132. });
  133. }
  134. const isLeetCodeCircleUrl = (url = window.location.href) => url && url.indexOf("https://leetcode.cn/circle") != -1;
  135. const isProblem = (url = window.location.href) => /^https?:\/\/leetcode.cn\/problems\/.*/i.test(url);
  136. const isContest = (url = window.location.href) => url.indexOf("https://leetcode.cn/contest/weekly-contest") != -1 || url.indexOf("https://leetcode.cn/contest/biweekly-contest") != -1;
  137. const width = 14;
  138. const height = 14;
  139. const problemFinsh = () => `
  140.  
  141. <svg width="${width}px" height="${height}px" status="ac" viewBox="0 0 1024 1024" version="1.1"
  142. xmlns="http://www.w3.org/2000/svg">
  143. <path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#4CAF50" />
  144. <path
  145. d="M738.133333 311.466667L448 601.6l-119.466667-119.466667-59.733333 59.733334 179.2 179.2 349.866667-349.866667z"
  146. fill="#CCFF90" />
  147. </svg>
  148.  
  149. `;
  150. const problemsTry = () => `
  151. <svg width="${width}px" height="${height}px" status="notac" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
  152. xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
  153. style="enable-background:new 0 0 512 512;" xml:space="preserve">
  154. <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
  155. S390.101,12.8,256,12.8z" />
  156. <g>
  157. <path style="fill:#573A32;" d="M256,115.2c-49.271,0-92.561,25.353-117.726,63.676l18.859,18.859
  158. 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
  159. C396.8,178.244,333.764,115.2,256,115.2z" />
  160. <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
  161. 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" />
  162. <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
  163. 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
  164. C334.822,348.194,298.266,371.2,256,371.2z" />
  165. </g>
  166. </svg>
  167.  
  168. `;
  169. const problemsNo = () => install_pos() ? `
  170. <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>
  171. ` : ``;
  172. const createStatus = (status, link) => {
  173. let node;
  174. if (!link) {
  175. return;
  176. }
  177. node = link instanceof HTMLAnchorElement ? link.parentElement : link;
  178. if (node) {
  179. node.status = status;
  180. }
  181. let installSVG = "";
  182. if (status == STATUS["AC"]) {
  183. installSVG = problemFinsh();
  184. } else if (status == STATUS["notac"]) {
  185. installSVG = problemsTry();
  186. } else if (status == STATUS["NO"]) {
  187. installSVG = problemsNo();
  188. } else {
  189. installSVG = "";
  190. }
  191. let svg = node.querySelector("svg");
  192. if (svg) {
  193. if (svg.getAttribute("status") == status || svg.getAttribute("status") == STATUS["AC"]) {
  194. return false;
  195. }
  196. svg.remove();
  197. }
  198. node.innerHTML = install_pos() ? installSVG + node.innerHTML : node.innerHTML + installSVG;
  199. return true;
  200. };
  201. const inf = 4e3;
  202. const mi = 1e3;
  203. const __0X3F_PROBLEM_KEYS__ = {
  204. "__0x3f_problmes_solution__": "__0x3f_problmes_solution__",
  205. // 基本信息
  206. "__0x3f_problmes_urls__": "__0x3f_problmes_urls__",
  207. // 题单key
  208. "__0x3f_problmes_update__": "__0x3f_problmes_update__",
  209. // 是否修改了默认题单key
  210. "__0x3f_problmes_button_is_none__": "__is_none_0x3f_problmes_button__",
  211. // 是否隐藏设置按钮
  212. "__0x3f_problmes_insert_pos__": "__0x3f_problmes_insert_pos__",
  213. // 安装位置
  214. "__0x3f_problmes_status_update__": "__0x3f_problmes_status_update__",
  215. "__0x3f_problmes_plugin_load_ok__": "__0x3f_problmes_plugin_load_ok__",
  216. // 是否使用插件
  217. "__0x3f_problmes_add_cur__": "__0x3f_problmes_add_cur__",
  218. // 添加 url
  219. "__0x3f_problmes_ac_key__": "__local_ok_problem_key__",
  220. // ac key
  221. "__0x3f_problmes_ac_version__": "__0x3f_problmes_ac_version__"
  222. // TODO ac key version
  223. };
  224. const STATUS = {
  225. "AC": "ac",
  226. "NO": "null",
  227. "notac": "notac"
  228. };
  229. const defaultObj = {
  230. min: mi,
  231. max: inf,
  232. visiableMember: true,
  233. onlyUrls: false,
  234. useDefaultSetting: true,
  235. hiddenAc: false
  236. };
  237. function install_pos() {
  238. return !Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_insert_pos__"], false, Boolean.name);
  239. }
  240. function isShow(text, min, max) {
  241. if (!text) {
  242. return true;
  243. }
  244. let res = text.match(/\d+/ig);
  245. if (!res) {
  246. return true;
  247. }
  248. if (Array.isArray(res) && res.length < 2) {
  249. return true;
  250. }
  251. let s = 0;
  252. for (let i = res.length - 1; i >= 0; i--) {
  253. s = res[i];
  254. if (s >= mi && s <= inf) {
  255. return s >= min && s <= max;
  256. }
  257. }
  258. return true;
  259. }
  260. let A = void 0;
  261. const linkCssSelector = `#lc-content [class*="CollapsibleMarkdownContent"] [class*="MarkdownContent"] li>a`;
  262. const queryProblem = () => Array.from(document.querySelectorAll(linkCssSelector)).filter((item) => item && item instanceof HTMLAnchorElement && isProblem(item.href));
  263. function loadProblems() {
  264. A = queryProblem();
  265. return A;
  266. }
  267. function handlerProblem(data) {
  268. var _a;
  269. try {
  270. loadProblems();
  271. let { min, max, visiableMember, useDefaultSetting, onlyUrls, hiddenAc } = data;
  272. if (isNaN(min) || isNaN(max)) {
  273. min = mi;
  274. max = inf;
  275. }
  276. if (min < mi) {
  277. min = mi;
  278. }
  279. if (max < min) {
  280. max = inf;
  281. }
  282. min = Number(min);
  283. max = Number(max);
  284. data.min = min;
  285. data.max = max;
  286. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"], data);
  287. for (let i = 0; i < A.length; i++) {
  288. if (!(A[i] instanceof HTMLAnchorElement)) {
  289. continue;
  290. }
  291. let d = (_a = A[i]) == null ? void 0 : _a.parentNode;
  292. if (!d) {
  293. continue;
  294. }
  295. let none = false;
  296. let Nohidden = isShow(d.textContent, min, max);
  297. d.style.display = Nohidden ? "" : "none";
  298. if (!Nohidden) {
  299. continue;
  300. }
  301. if (hiddenAc) {
  302. const svg = d.querySelector("svg");
  303. if (svg && svg.getAttribute("status")) {
  304. d.style.display = svg.getAttribute("status") == STATUS["AC"] ? "none" : "";
  305. }
  306. } else {
  307. d.style.display = "";
  308. }
  309. let c = d.textContent && d.textContent.indexOf("会员") != -1;
  310. if (!c) {
  311. continue;
  312. }
  313. d.style.display = visiableMember ? "" : "none";
  314. }
  315. } catch (e) {
  316. console.log("error", e);
  317. }
  318. }
  319. function computeAcInfo(saveUrls = [], deleteOk = true) {
  320. let infos = [];
  321. for (let i = 0, u = null; Array.isArray(saveUrls) && i < saveUrls.length; i++) {
  322. try {
  323. u = saveUrls[i];
  324. if (!u || !(u == null ? void 0 : u.link)) continue;
  325. if (!u["id"]) {
  326. u["id"] = i + 1;
  327. }
  328. let s = Object.values(u).join("");
  329. if (s == "null" || !Cache$1.get(u.link) || !getAcCountKey(u.link) || !Cache$1.get(getAcCountKey(u.link))) {
  330. continue;
  331. }
  332. let o = Cache$1.get(getAcCountKey(u.link));
  333. u["ac"] = isNaN(o["ac"]) ? 0 : parseInt(o["ac"]);
  334. u["tot"] = isNaN(o["tot"]) ? 0 : parseInt(o["tot"]);
  335. } catch (e) {
  336. }
  337. infos.push(Object.assign({}, u));
  338. }
  339. if (deleteOk) {
  340. for (let i = 0; i < saveUrls[i]; i++) {
  341. delete saveUrls[i];
  342. }
  343. for (let info of infos) {
  344. saveUrls.push(info);
  345. }
  346. }
  347. return infos;
  348. }
  349. const initUrls = () => {
  350. 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;
  351. return computeAcInfo(saveUrls);
  352. };
  353. const initObj = () => Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"]) ? Object.assign(defaultObj, Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"])) : defaultObj;
  354. const support_plugins = () => {
  355. const u = initObj();
  356. if (!u || !u.onlyUrls) return true;
  357. let url = window.location.href;
  358. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  359. try {
  360. url = url.split("view")[0];
  361. } catch (e) {
  362. url = window.location.href;
  363. }
  364. }
  365. const urls = initUrls();
  366. for (let info of urls) {
  367. if (!info || !(info == null ? void 0 : info.link)) {
  368. continue;
  369. }
  370. if (info.link.indexOf(url) != -1) {
  371. return true;
  372. }
  373. }
  374. return false;
  375. };
  376. const defaultUrls = [
  377. {
  378. title: "数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)",
  379. link: "https://leetcode.cn/circle/discuss/IYT3ss/",
  380. cnt: 0,
  381. ac: 1
  382. },
  383. {
  384. title: "常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)",
  385. link: "https://leetcode.cn/circle/discuss/mOr1u6/",
  386. cnt: 0,
  387. ac: 0,
  388. id: 2
  389. },
  390. {
  391. title: "动态规划(入门/背包/状态机/划分/区间/状压/数位/树形/数据结构优化)",
  392. link: "https://leetcode.cn/circle/discuss/tXLS3i/",
  393. cnt: 0,
  394. ac: 0,
  395. id: 3
  396. },
  397. {
  398. title: "图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)",
  399. link: "https://leetcode.cn/circle/discuss/01LUak/",
  400. cnt: 0,
  401. ac: 0,
  402. id: 4
  403. },
  404. {
  405. title: "位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)",
  406. link: "https://leetcode.cn/circle/discuss/dHn9Vk/",
  407. cnt: 0,
  408. ac: 5
  409. },
  410. {
  411. title: "网格图(DFS/BFS/综合应用)",
  412. link: "https://leetcode.cn/circle/discuss/YiXPXW/",
  413. cnt: 0,
  414. ac: 0,
  415. id: 6
  416. },
  417. {
  418. title: "单调栈(矩形面积/贡献法/最小字典序)",
  419. link: "https://leetcode.cn/circle/discuss/9oZFK9/",
  420. cnt: 0,
  421. ac: 7
  422. },
  423. {
  424. title: "二分算法(二分答案/最小化最大值/最大化最小值/第K小)",
  425. link: "https://leetcode.cn/circle/discuss/SqopEo/",
  426. cnt: 0,
  427. ac: 0,
  428. id: 8
  429. },
  430. {
  431. title: "滑动窗口(定长/不定长/多指针)",
  432. link: "https://leetcode.cn/circle/discuss/0viNMK/",
  433. cnt: 0,
  434. ac: 0,
  435. id: 9
  436. },
  437. {
  438. title: "贪心算法(基本贪心策略/反悔/区间/字典序/数学/思维/构造)",
  439. link: "https://leetcode.cn/circle/discuss/g6KTKL/",
  440. cnt: 0,
  441. ac: 0,
  442. id: 10
  443. },
  444. {
  445. title: "链表、二叉树与一般树(前后指针/快慢指针/DFS/BFS/直径/LCA)",
  446. link: "https://leetcode.cn/circle/discuss/K0n2gO/",
  447. cnt: 0,
  448. ac: 0,
  449. id: 11
  450. },
  451. {
  452. title: "字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)",
  453. link: "https://leetcode.cn/circle/discuss/SJFwQI/",
  454. cnt: 0,
  455. ac: 0,
  456. id: 12
  457. }
  458. ];
  459. function getId(problemUrl) {
  460. if (isContest(problemUrl) || isProblem(problemUrl)) {
  461. try {
  462. return problemUrl.split("problems")[1].split("/")[1];
  463. } catch (e) {
  464. return "";
  465. }
  466. }
  467. return "";
  468. }
  469. function postData(ID) {
  470. return {
  471. "query": "\n query userQuestionStatus($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n status\n }\n}\n ",
  472. "variables": {
  473. "titleSlug": ID
  474. },
  475. "operationName": "userQuestionStatus"
  476. };
  477. }
  478. function queryStatus(ID = "", cache = {}, cur = void 0, watch2 = false) {
  479. if (!ID) {
  480. return;
  481. }
  482. if (cache[ID] == void 0 || cache[ID] != STATUS["AC"]) {
  483. fetch("https://leetcode.cn/graphql/", {
  484. method: "POST",
  485. credentials: "include",
  486. headers: {
  487. "Content-Type": "application/json"
  488. },
  489. body: JSON.stringify(postData(ID))
  490. }).then((res) => res.json()).then((response) => {
  491. var _a, _b, _c;
  492. if ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.question) {
  493. const status = (_c = (_b = response == null ? void 0 : response.data) == null ? void 0 : _b.question) == null ? void 0 : _c.status;
  494. if (cache[ID] == void 0 || cache[ID] != status) {
  495. cache[ID] = status == null ? "null" : status;
  496. if (watch2) {
  497. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], cache);
  498. window.localStorage.setItem(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_status_update__"], JSON.stringify({
  499. "id": ID,
  500. "status": cache[ID]
  501. }));
  502. }
  503. createStatus(cache[ID], cur);
  504. }
  505. } else {
  506. console.log("query result is undefined");
  507. }
  508. }).catch((ignore) => {
  509. console.error("query status error : ", ignore);
  510. });
  511. }
  512. }
  513. function addProcess(reload = true, doms = void 0, asyncAc = false) {
  514. var _a;
  515. let problems_doms = Array.isArray(doms) ? doms : loadProblems();
  516. const cache = getLocalProblemStatus();
  517. for (let i = 0; i < problems_doms.length; i++) {
  518. let cur = problems_doms[i].parentElement;
  519. if (!(cur instanceof HTMLElement)) {
  520. continue;
  521. }
  522. const ID = getId((_a = problems_doms[i]) == null ? void 0 : _a.href);
  523. if (!ID) {
  524. continue;
  525. }
  526. if (install_pos()) {
  527. cur.style.listStyleType = "none";
  528. }
  529. if (!cache[ID] || cache[ID] != STATUS["AC"] && asyncAc) {
  530. queryStatus(ID, cache, cur, false);
  531. } else {
  532. let status = cache[ID];
  533. createStatus(status, cur);
  534. }
  535. }
  536. getProcess();
  537. if (reload) {
  538. let cnt = 10;
  539. let timeId = setInterval(() => {
  540. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], cache);
  541. getProcess();
  542. cnt--;
  543. if (cnt == 0) {
  544. window.clearInterval(timeId);
  545. }
  546. }, 3e3);
  547. }
  548. }
  549. const submitProblems = (url = window.location.href, timeout = 500) => {
  550. const ID = getId(url);
  551. if (!ID) {
  552. return;
  553. }
  554. setTimeout(() => {
  555. const cache = getLocalProblemStatus();
  556. queryStatus(ID, cache, void 0, true);
  557. }, timeout);
  558. };
  559. const watchLinkStatusUpdate = (e) => {
  560. var _a;
  561. if (e.key != __0X3F_PROBLEM_KEYS__["__0x3f_problmes_status_update__"]) {
  562. return;
  563. }
  564. let { id, status } = JSON.parse(e.newValue);
  565. if (!id || !status) {
  566. return;
  567. }
  568. let thisLink = `https://leetcode.cn/problems/${id}`;
  569. let link = document.querySelector(`${linkCssSelector}[href^="https://leetcode.cn/problems/${id}"]`);
  570. if (!link || !(link == null ? void 0 : link.parentElement)) {
  571. let doms = loadProblems();
  572. for (let i = 0; i < doms.length; i++) {
  573. if (!doms[i] || !((_a = doms[i]) == null ? void 0 : _a.parentElement)) {
  574. continue;
  575. }
  576. if (doms[i].href.indexOf(thisLink) != -1) {
  577. link = doms[i];
  578. break;
  579. }
  580. }
  581. }
  582. createStatus(status, link);
  583. };
  584. function getAcCountKey(k) {
  585. if (!k) return "";
  586. return `0x3f_ac_key_${k}`;
  587. }
  588. function getProcess() {
  589. loadProblems();
  590. const cache = getLocalProblemStatus();
  591. let cnt = 0;
  592. for (let i = 0; i < A.length; i++) {
  593. let ID = getId(A[i].href);
  594. if (ID && cache[ID] == STATUS["AC"]) {
  595. cnt++;
  596. }
  597. }
  598. let url = window.location.href;
  599. Cache$1.set(getAcCountKey(url), { "tot": A.length, "ac": cnt });
  600. return [cnt, A.length];
  601. }
  602. function getLocalProblemStatus() {
  603. return Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"], true, Object.name);
  604. }
  605. const _hoisted_1 = { class: "processs-flex" };
  606. const _hoisted_2 = { style: { "text-align": "center", "color": "#121212" } };
  607. const _hoisted_3 = { class: "dialog-footer" };
  608. const formLabelWidth = "44px";
  609. const _sfc_main = {
  610. __name: "App",
  611. setup(__props) {
  612. const sortType = vue.ref(0);
  613. let tableData = vue.reactive(initUrls());
  614. const keywords = vue.ref("");
  615. const dialogTableVisible = vue.ref(false);
  616. let urlsData = vue.computed(() => {
  617. let infos = computeAcInfo(tableData, false).filter((info2) => info2 && (info2.title && info2.title.indexOf(keywords.value) != -1 || info2.link && info2.link.indexOf(keywords.value) != -1));
  618. let tot = 0, ac = 0, c = 0;
  619. for (let i = 0, c2 = info.length; i < infos.length; i++) {
  620. let info2 = infos[i];
  621. if (info2["ac"] && info2["tot"]) {
  622. tot += info2["tot"];
  623. ac += info2["ac"];
  624. }
  625. if (!info2["id"]) {
  626. info2["id"] = c2 + 1;
  627. c2++;
  628. }
  629. }
  630. let type = sortType.value;
  631. if (type == 0) {
  632. infos.sort((info1, info2) => info2.id - info1.id);
  633. } else if (type == 1) {
  634. infos.sort((info1, info2) => info2.tot - info1.tot);
  635. } else if (type == 2) {
  636. infos.sort((info1, info2) => info2.ac - info1.ac);
  637. } else if (type == 3) {
  638. infos.sort((info1, info2) => computeProcess(info2.ac, info2.tot) - computeProcess(info1.ac, info1.tot));
  639. }
  640. infos.unshift({ "title": "灵茶题单完成情况", "link": "https://leetcode.cn/u/endlesscheng/", "tot": tot, "ac": ac, "id": c + 10 });
  641. return infos;
  642. });
  643. const isDisabbled = vue.computed(() => !!tableData.find((v) => (v == null ? void 0 : v.link) && (v == null ? void 0 : v.link.indexOf(window.location.href)) != -1));
  644. const dialogFormVisible = vue.ref(false);
  645. let totProblem = vue.ref(0);
  646. let finishProblem = vue.ref(0);
  647. const drawer = vue.ref(false);
  648. const viewSetting = () => {
  649. drawer.value = !drawer.value;
  650. let [cur, tot] = getProcess();
  651. finishProblem.value = cur;
  652. totProblem.value = tot;
  653. computeAcInfo(tableData, false);
  654. };
  655. const computeProcess = (ac = 0, tot = 0) => {
  656. if (isNaN(ac) || isNaN(tot)) return 0;
  657. if (tot == 0) return 0;
  658. let p = 0;
  659. try {
  660. const s = String(ac / tot);
  661. let x1 = s.split(".")[1].padEnd(3).substring(0, 3);
  662. p = Math.min(100, Number(x1) / 10);
  663. } catch (e) {
  664. p = (ac / tot).toFixed(3) * 100;
  665. }
  666. return isNaN(p) ? 0 : p;
  667. };
  668. const finishProcess = vue.computed(() => computeProcess(finishProblem.value, totProblem.value));
  669. const processColors = [
  670. { color: "#f56c6c", percentage: 20 },
  671. { color: "#1989fa", percentage: 40 },
  672. { color: "#e6a23c", percentage: 60 },
  673. { color: "#6f7ad3", percentage: 80 },
  674. { color: "#5cb87a", percentage: 100 }
  675. ];
  676. const fromData = vue.reactive(initObj());
  677. vue.watch(fromData, () => {
  678. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  679. });
  680. const info = vue.reactive({
  681. title: "",
  682. link: "",
  683. status: "add"
  684. });
  685. const addlocal = () => {
  686. if (!isDisabbled) {
  687. return;
  688. }
  689. let [cur, tot] = getProcess();
  690. tableData.unshift({ title: document.title, link: window.location.href, "ac": cur, "tot": tot, "id": tableData.length + 10 });
  691. };
  692. const updateIndex = vue.ref(-1);
  693. const showProblems = () => {
  694. dialogTableVisible.value = true;
  695. let o = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"]) == "true" || Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"]) == true;
  696. if (o) {
  697. addlocal();
  698. }
  699. computeAcInfo(tableData, false);
  700. };
  701. const handlerProblems = (status, updateInfo = { title: "", link: "", id: 0 }, index = -1) => {
  702. dialogFormVisible.value = true;
  703. info.status = status;
  704. updateIndex.value = updateInfo.id;
  705. Object.assign(info, updateInfo);
  706. };
  707. const handlerMessage = (u, title, link) => {
  708. const a = u ? "添加" : "修改";
  709. const error = !title || !/https?:\/\/.*/.test(link);
  710. if (error) {
  711. ElementPlus.ElMessage.error(`${a} 失败 请保证标题或者链接有效 `);
  712. } else {
  713. ElementPlus.ElMessage.success(`${a} 成功 `);
  714. }
  715. return !error;
  716. };
  717. const addOrUpdate = () => {
  718. if (!handlerMessage(info.status == "add", info.title, info.link)) {
  719. return;
  720. }
  721. if (info.status == "add") {
  722. tableData.unshift({ title: info.title, link: info.link, "ac": 0, "tot": 0, "id": tableData.length + 10 });
  723. } else {
  724. let id = updateIndex.value;
  725. for (let i = 0; i < tableData.length; i++) {
  726. if (tableData[i]["id"] == id) {
  727. tableData[i]["title"] = info.title;
  728. tableData[i]["link"] = info.link;
  729. break;
  730. }
  731. }
  732. }
  733. dialogFormVisible.value = false;
  734. };
  735. const deleteProblems = (id) => {
  736. for (let i = 0; i < tableData.length; i++) {
  737. if (tableData[i]["id"] == id) {
  738. delete tableData[i];
  739. break;
  740. }
  741. }
  742. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], vue.toRaw(tableData));
  743. };
  744. const handlerDefault = () => {
  745. Message("确认使用默认题单,将会重置题单", () => {
  746. for (let i = 0; i < tableData.length; i++) {
  747. delete tableData[i];
  748. }
  749. let infos = computeAcInfo(defaultUrls);
  750. for (let item of infos) {
  751. tableData.unshift(item);
  752. }
  753. ElementPlus.ElMessage({
  754. type: "success",
  755. message: "重置成功"
  756. });
  757. });
  758. };
  759. const asyncLocalStatus = () => {
  760. Message("确认同步题单", () => {
  761. addProcess(true, void 0, true);
  762. });
  763. };
  764. window.addEventListener("beforeunload", () => {
  765. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], vue.toRaw(tableData).filter((u) => u != null && u != void 0));
  766. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_update__"], true);
  767. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"], false);
  768. });
  769. vue.onMounted(() => {
  770. if (support_plugins()) {
  771. let times = 30;
  772. let loadTimeId = setInterval(() => {
  773. let a = queryProblem();
  774. times--;
  775. if (Array.isArray(a) && a.length > 0) {
  776. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  777. addProcess();
  778. window.clearInterval(loadTimeId);
  779. }
  780. if (times == 0) {
  781. window.clearInterval(loadTimeId);
  782. }
  783. }, 200);
  784. window.addEventListener("storage", (e) => {
  785. watchLinkStatusUpdate(e);
  786. });
  787. }
  788. });
  789. const q1 = vue.ref(false);
  790. const q2 = vue.ref(false);
  791. return (_ctx, _cache) => {
  792. const _component_el_button = vue.resolveComponent("el-button");
  793. const _component_el_progress = vue.resolveComponent("el-progress");
  794. const _component_el_divider = vue.resolveComponent("el-divider");
  795. const _component_el_input = vue.resolveComponent("el-input");
  796. const _component_el_col = vue.resolveComponent("el-col");
  797. const _component_el_form_item = vue.resolveComponent("el-form-item");
  798. const _component_el_switch = vue.resolveComponent("el-switch");
  799. const _component_el_tooltip = vue.resolveComponent("el-tooltip");
  800. const _component_el_form = vue.resolveComponent("el-form");
  801. const _component_el_dialog = vue.resolveComponent("el-dialog");
  802. const _component_el_option = vue.resolveComponent("el-option");
  803. const _component_el_select = vue.resolveComponent("el-select");
  804. const _component_el_row = vue.resolveComponent("el-row");
  805. const _component_el_link = vue.resolveComponent("el-link");
  806. const _component_el_table_column = vue.resolveComponent("el-table-column");
  807. const _component_el_table = vue.resolveComponent("el-table");
  808. const _component_el_drawer = vue.resolveComponent("el-drawer");
  809. return vue.openBlock(), vue.createElementBlock("div", null, [
  810. vue.createVNode(_component_el_button, {
  811. type: "primary",
  812. style: {},
  813. onClick: viewSetting,
  814. class: "m-setting-button m-button",
  815. circle: "",
  816. size: "large"
  817. }, {
  818. default: vue.withCtx(() => [
  819. vue.createTextVNode(" 0X3F ")
  820. ]),
  821. _: 1
  822. }),
  823. vue.createVNode(_component_el_drawer, {
  824. modelValue: drawer.value,
  825. "onUpdate:modelValue": _cache[20] || (_cache[20] = ($event) => drawer.value = $event),
  826. size: "30%",
  827. "with-header": false,
  828. style: { "position": "fixed !important" },
  829. direction: "rtl"
  830. }, {
  831. default: vue.withCtx(() => [
  832. vue.createElementVNode("div", _hoisted_1, [
  833. vue.createVNode(_component_el_progress, {
  834. type: "circle",
  835. percentage: finishProcess.value,
  836. color: processColors
  837. }, {
  838. default: vue.withCtx(({ percentage }) => [
  839. vue.createElementVNode("p", null, vue.toDisplayString(percentage) + "%", 1)
  840. ]),
  841. _: 1
  842. }, 8, ["percentage"])
  843. ]),
  844. vue.createElementVNode("p", _hoisted_2, vue.toDisplayString(vue.unref(finishProblem)) + " / " + vue.toDisplayString(vue.unref(totProblem)), 1),
  845. vue.createCommentVNode("", true),
  846. vue.createVNode(_component_el_divider),
  847. vue.createVNode(_component_el_form, {
  848. "label-position": "left",
  849. "label-width": "auto",
  850. model: fromData,
  851. style: { "max-width": "600px" }
  852. }, {
  853. default: vue.withCtx(() => [
  854. vue.createVNode(_component_el_form_item, { label: "分数区间" }, {
  855. default: vue.withCtx(() => [
  856. vue.createVNode(_component_el_col, { span: 10 }, {
  857. default: vue.withCtx(() => [
  858. vue.createVNode(_component_el_input, {
  859. modelValue: fromData.min,
  860. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => fromData.min = $event),
  861. "aria-placeholder": "",
  862. placeholder: " min "
  863. }, null, 8, ["modelValue"])
  864. ]),
  865. _: 1
  866. }),
  867. vue.createVNode(_component_el_col, {
  868. class: "text-center",
  869. span: 1,
  870. style: { "margin": "0 0.5rem" }
  871. }, {
  872. default: vue.withCtx(() => [
  873. vue.createTextVNode("-")
  874. ]),
  875. _: 1
  876. }),
  877. vue.createVNode(_component_el_col, { span: 10 }, {
  878. default: vue.withCtx(() => [
  879. vue.createVNode(_component_el_input, {
  880. modelValue: fromData.max,
  881. "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => fromData.max = $event),
  882. "aria-placeholder": "",
  883. placeholder: " max"
  884. }, null, 8, ["modelValue"])
  885. ]),
  886. _: 1
  887. })
  888. ]),
  889. _: 1
  890. }),
  891. vue.createVNode(_component_el_form_item, { label: "显示会员题" }, {
  892. default: vue.withCtx(() => [
  893. vue.createVNode(_component_el_switch, {
  894. modelValue: fromData.visiableMember,
  895. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => fromData.visiableMember = $event)
  896. }, null, 8, ["modelValue"])
  897. ]),
  898. _: 1
  899. }),
  900. vue.createVNode(_component_el_form_item, { label: "隐藏AC题目" }, {
  901. default: vue.withCtx(() => [
  902. vue.createVNode(_component_el_switch, {
  903. modelValue: fromData.hiddenAc,
  904. "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => fromData.hiddenAc = $event)
  905. }, null, 8, ["modelValue"])
  906. ]),
  907. _: 1
  908. }),
  909. vue.createVNode(_component_el_form_item, { label: "收藏题单中生效" }, {
  910. default: vue.withCtx(() => [
  911. vue.createVNode(_component_el_tooltip, {
  912. content: "插件只在收藏题单中生效,刷新生效 ",
  913. placement: "bottom-end"
  914. }, {
  915. default: vue.withCtx(() => [
  916. vue.createVNode(_component_el_switch, {
  917. modelValue: fromData.onlyUrls,
  918. "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => fromData.onlyUrls = $event)
  919. }, null, 8, ["modelValue"])
  920. ]),
  921. _: 1
  922. })
  923. ]),
  924. _: 1
  925. }),
  926. vue.createVNode(_component_el_form_item, { label: "使用题单" }, {
  927. default: vue.withCtx(() => [
  928. vue.createVNode(_component_el_switch, {
  929. modelValue: fromData.useDefaultSetting,
  930. "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => fromData.useDefaultSetting = $event)
  931. }, null, 8, ["modelValue"])
  932. ]),
  933. _: 1
  934. })
  935. ]),
  936. _: 1
  937. }, 8, ["model"]),
  938. fromData.useDefaultSetting ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  939. vue.createVNode(_component_el_divider),
  940. vue.createVNode(_component_el_button, {
  941. plain: "",
  942. onClick: asyncLocalStatus
  943. }, {
  944. default: vue.withCtx(() => [
  945. vue.createTextVNode(" 同步本页题目状态 ")
  946. ]),
  947. _: 1
  948. }),
  949. vue.createVNode(_component_el_button, {
  950. plain: "",
  951. onClick: showProblems
  952. }, {
  953. default: vue.withCtx(() => [
  954. vue.createTextVNode(" 查看收藏的题单 ")
  955. ]),
  956. _: 1
  957. }),
  958. vue.createVNode(_component_el_divider)
  959. ], 64)) : vue.createCommentVNode("", true),
  960. vue.createVNode(_component_el_button, {
  961. plain: "",
  962. onClick: _cache[8] || (_cache[8] = ($event) => q1.value = !q1.value)
  963. }, {
  964. default: vue.withCtx(() => [
  965. vue.createTextVNode(" 问题1 ")
  966. ]),
  967. _: 1
  968. }),
  969. vue.createVNode(_component_el_tooltip, { content: "此功能是为了多刷题单,重置题目状态,敬请期待!" }, {
  970. default: vue.withCtx(() => [
  971. vue.createVNode(_component_el_button, {
  972. plain: "",
  973. type: "warning",
  974. disabled: true
  975. }, {
  976. default: vue.withCtx(() => [
  977. vue.createTextVNode(" 题单重置 ")
  978. ]),
  979. _: 1
  980. })
  981. ]),
  982. _: 1
  983. }),
  984. vue.createVNode(_component_el_dialog, {
  985. modelValue: q1.value,
  986. "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => q1.value = $event),
  987. title: "关于查询状态会不会被封号 ?"
  988. }, {
  989. default: vue.withCtx(() => [
  990. vue.createVNode(Q1)
  991. ]),
  992. _: 1
  993. }, 8, ["modelValue"]),
  994. vue.createVNode(_component_el_dialog, {
  995. modelValue: q2.value,
  996. "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => q2.value = $event),
  997. title: "相关问题 ?"
  998. }, {
  999. default: vue.withCtx(() => [
  1000. vue.createVNode(Q2)
  1001. ]),
  1002. _: 1
  1003. }, 8, ["modelValue"]),
  1004. vue.createVNode(_component_el_dialog, {
  1005. modelValue: dialogTableVisible.value,
  1006. "onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => dialogTableVisible.value = $event),
  1007. title: "题单"
  1008. }, {
  1009. default: vue.withCtx(() => [
  1010. vue.createVNode(_component_el_row, { gutter: 10 }, {
  1011. default: vue.withCtx(() => [
  1012. vue.createVNode(_component_el_col, { span: 5 }, {
  1013. default: vue.withCtx(() => [
  1014. vue.createVNode(_component_el_input, {
  1015. modelValue: keywords.value,
  1016. "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => keywords.value = $event),
  1017. placeholder: "请输入关键词过滤",
  1018. clearable: ""
  1019. }, null, 8, ["modelValue"])
  1020. ]),
  1021. _: 1
  1022. }),
  1023. vue.createVNode(_component_el_col, { span: 19 }, {
  1024. default: vue.withCtx(() => [
  1025. vue.createVNode(_component_el_button, {
  1026. plain: "",
  1027. onClick: addlocal,
  1028. disabled: isDisabbled.value
  1029. }, {
  1030. default: vue.withCtx(() => [
  1031. vue.createTextVNode(" 添加本页 ")
  1032. ]),
  1033. _: 1
  1034. }, 8, ["disabled"]),
  1035. vue.createVNode(_component_el_button, {
  1036. plain: "",
  1037. onClick: _cache[12] || (_cache[12] = ($event) => handlerProblems("add"))
  1038. }, {
  1039. default: vue.withCtx(() => [
  1040. vue.createTextVNode(" 自定义 ")
  1041. ]),
  1042. _: 1
  1043. }),
  1044. vue.createVNode(_component_el_button, {
  1045. plain: "",
  1046. onClick: handlerDefault
  1047. }, {
  1048. default: vue.withCtx(() => [
  1049. vue.createTextVNode(" 默认 ")
  1050. ]),
  1051. _: 1
  1052. }),
  1053. vue.createVNode(_component_el_button, {
  1054. plain: "",
  1055. onClick: _cache[13] || (_cache[13] = ($event) => q2.value = !q2.value)
  1056. }, {
  1057. default: vue.withCtx(() => [
  1058. vue.createTextVNode(" 相关问题 ")
  1059. ]),
  1060. _: 1
  1061. }),
  1062. vue.createVNode(_component_el_select, {
  1063. modelValue: sortType.value,
  1064. "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => sortType.value = $event),
  1065. style: { "margin-left": "5px", "width": "100px" }
  1066. }, {
  1067. default: vue.withCtx(() => [
  1068. vue.createVNode(_component_el_option, {
  1069. label: "默认排序",
  1070. value: 0
  1071. }, {
  1072. default: vue.withCtx(() => [
  1073. vue.createTextVNode("默认排序")
  1074. ]),
  1075. _: 1
  1076. }),
  1077. vue.createVNode(_component_el_option, {
  1078. label: "题目数量",
  1079. value: 1
  1080. }, {
  1081. default: vue.withCtx(() => [
  1082. vue.createTextVNode("题目数量")
  1083. ]),
  1084. _: 1
  1085. }),
  1086. vue.createVNode(_component_el_option, {
  1087. label: "AC数量",
  1088. value: 2
  1089. }, {
  1090. default: vue.withCtx(() => [
  1091. vue.createTextVNode("AC数量")
  1092. ]),
  1093. _: 1
  1094. }),
  1095. vue.createVNode(_component_el_option, {
  1096. label: "完成度",
  1097. value: 3
  1098. }, {
  1099. default: vue.withCtx(() => [
  1100. vue.createTextVNode("完成度")
  1101. ]),
  1102. _: 1
  1103. })
  1104. ]),
  1105. _: 1
  1106. }, 8, ["modelValue"])
  1107. ]),
  1108. _: 1
  1109. })
  1110. ]),
  1111. _: 1
  1112. }),
  1113. vue.createVNode(_component_el_table, {
  1114. data: vue.unref(urlsData),
  1115. height: "300",
  1116. style: { "width": "100%", "margin-top": "10px" }
  1117. }, {
  1118. default: vue.withCtx(() => [
  1119. vue.createVNode(_component_el_table_column, {
  1120. label: "标题",
  1121. width: "auto",
  1122. align: "center"
  1123. }, {
  1124. default: vue.withCtx((scope) => [
  1125. vue.createVNode(_component_el_link, {
  1126. disabled: scope.row.link == "https://leetcode.cn/u/endlesscheng/",
  1127. href: scope.row.link,
  1128. target: "_blank",
  1129. type: "default"
  1130. }, {
  1131. default: vue.withCtx(() => [
  1132. vue.createTextVNode(vue.toDisplayString(scope.row.title), 1)
  1133. ]),
  1134. _: 2
  1135. }, 1032, ["disabled", "href"])
  1136. ]),
  1137. _: 1
  1138. }),
  1139. vue.createVNode(_component_el_table_column, {
  1140. label: "AC",
  1141. width: "80",
  1142. align: "center"
  1143. }, {
  1144. default: vue.withCtx((scope) => [
  1145. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.ac) ? 0 : scope.row.ac), 1)
  1146. ]),
  1147. _: 1
  1148. }),
  1149. vue.createVNode(_component_el_table_column, {
  1150. label: "Total",
  1151. width: "80",
  1152. align: "center"
  1153. }, {
  1154. default: vue.withCtx((scope) => [
  1155. vue.createTextVNode(vue.toDisplayString(isNaN(scope.row.tot) ? 0 : scope.row.tot), 1)
  1156. ]),
  1157. _: 1
  1158. }),
  1159. vue.createVNode(_component_el_table_column, {
  1160. label: "process",
  1161. width: "80",
  1162. align: "center"
  1163. }, {
  1164. default: vue.withCtx((scope) => {
  1165. var _a, _b, _c;
  1166. return [
  1167. 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)
  1168. ];
  1169. }),
  1170. _: 1
  1171. }),
  1172. vue.createVNode(_component_el_table_column, {
  1173. label: "操作",
  1174. width: "150",
  1175. align: "center"
  1176. }, {
  1177. default: vue.withCtx((scope) => [
  1178. vue.createVNode(_component_el_button, {
  1179. type: "primary",
  1180. size: "small",
  1181. disabled: scope.row.link == "https://leetcode.cn/u/endlesscheng/",
  1182. onClick: ($event) => handlerProblems("update", scope.row, scope.$index)
  1183. }, {
  1184. default: vue.withCtx(() => [
  1185. vue.createTextVNode("编辑")
  1186. ]),
  1187. _: 2
  1188. }, 1032, ["disabled", "onClick"]),
  1189. vue.createVNode(_component_el_button, {
  1190. disabled: scope.row.link == "https://leetcode.cn/u/endlesscheng/",
  1191. type: "danger",
  1192. size: "small",
  1193. onClick: ($event) => deleteProblems(scope.row.id)
  1194. }, {
  1195. default: vue.withCtx(() => [
  1196. vue.createTextVNode("删除")
  1197. ]),
  1198. _: 2
  1199. }, 1032, ["disabled", "onClick"])
  1200. ]),
  1201. _: 1
  1202. })
  1203. ]),
  1204. _: 1
  1205. }, 8, ["data"])
  1206. ]),
  1207. _: 1
  1208. }, 8, ["modelValue"]),
  1209. vue.createVNode(_component_el_dialog, {
  1210. modelValue: dialogFormVisible.value,
  1211. "onUpdate:modelValue": _cache[19] || (_cache[19] = ($event) => dialogFormVisible.value = $event),
  1212. title: `${info.status == "add" ? "添加" : "编辑"}`,
  1213. width: "400"
  1214. }, {
  1215. footer: vue.withCtx(() => [
  1216. vue.createElementVNode("div", _hoisted_3, [
  1217. vue.createVNode(_component_el_button, {
  1218. onClick: _cache[18] || (_cache[18] = ($event) => dialogFormVisible.value = false)
  1219. }, {
  1220. default: vue.withCtx(() => [
  1221. vue.createTextVNode("取消")
  1222. ]),
  1223. _: 1
  1224. }),
  1225. vue.createVNode(_component_el_button, {
  1226. type: "primary",
  1227. onClick: addOrUpdate
  1228. }, {
  1229. default: vue.withCtx(() => [
  1230. vue.createTextVNode(" 确认 ")
  1231. ]),
  1232. _: 1
  1233. })
  1234. ])
  1235. ]),
  1236. default: vue.withCtx(() => [
  1237. vue.createVNode(_component_el_form, null, {
  1238. default: vue.withCtx(() => [
  1239. vue.createVNode(_component_el_form_item, {
  1240. label: "标题",
  1241. "label-width": formLabelWidth
  1242. }, {
  1243. default: vue.withCtx(() => [
  1244. vue.createVNode(_component_el_input, {
  1245. modelValue: info.title,
  1246. "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => info.title = $event),
  1247. autocomplete: "off"
  1248. }, null, 8, ["modelValue"])
  1249. ]),
  1250. _: 1
  1251. }),
  1252. vue.createVNode(_component_el_form_item, {
  1253. label: "链接",
  1254. "label-width": formLabelWidth
  1255. }, {
  1256. default: vue.withCtx(() => [
  1257. vue.createVNode(_component_el_input, {
  1258. modelValue: info.link,
  1259. "onUpdate:modelValue": _cache[17] || (_cache[17] = ($event) => info.link = $event),
  1260. autocomplete: "off"
  1261. }, null, 8, ["modelValue"])
  1262. ]),
  1263. _: 1
  1264. })
  1265. ]),
  1266. _: 1
  1267. })
  1268. ]),
  1269. _: 1
  1270. }, 8, ["modelValue", "title"])
  1271. ]),
  1272. _: 1
  1273. }, 8, ["modelValue"])
  1274. ]);
  1275. };
  1276. }
  1277. };
  1278. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0d8147ce"]]);
  1279. const cssLoader = (e) => {
  1280. const t = GM_getResourceText(e);
  1281. return GM_addStyle(t), t;
  1282. };
  1283. cssLoader("elementPlusCss");
  1284. const stopRankingKey = "__is_stop_rating_ranking__";
  1285. let conetstTimeId = null;
  1286. function run$1() {
  1287. const container = document.querySelector(".contest-question-info .list-group");
  1288. if (!container) return;
  1289. const ls = Array.from(container.querySelectorAll(".list-group-item .pull-right"));
  1290. for (let i = 0; i < 4; i++) {
  1291. if (i >= ls.length) {
  1292. break;
  1293. }
  1294. if (ls[i] instanceof HTMLElement) {
  1295. ls[i].textContent = "0";
  1296. }
  1297. }
  1298. window.clearInterval(conetstTimeId);
  1299. }
  1300. function startStopRanking() {
  1301. if (!isContest(window.location.href)) {
  1302. return;
  1303. }
  1304. const isNext = !!document.querySelector("#__next");
  1305. if (isNext) {
  1306. return;
  1307. }
  1308. const use = Cache$1.get(stopRankingKey);
  1309. if (use) {
  1310. conetstTimeId = setInterval(() => {
  1311. run$1();
  1312. }, 10);
  1313. }
  1314. _GM_registerMenuCommand(`${use ? "使用" : "关闭"} 排行榜`, () => {
  1315. Cache$1.set(stopRankingKey, !use);
  1316. window.location.reload();
  1317. }, { title: "对于不想看到排行榜的可以使用此功能 默认开启" });
  1318. }
  1319. const local_url = window.location.href;
  1320. let loadID = 0;
  1321. let submitCnt = 0;
  1322. function watchDom(dom) {
  1323. if (!(dom instanceof HTMLElement)) {
  1324. return;
  1325. }
  1326. let m = new MutationObserver(() => {
  1327. if (submitCnt % 2 == 1) {
  1328. submitProblems(local_url);
  1329. }
  1330. submitCnt++;
  1331. });
  1332. m.observe(dom, {
  1333. childList: true,
  1334. attributes: true
  1335. });
  1336. }
  1337. function run() {
  1338. loadID++;
  1339. if (isProblem(local_url) || isContest(local_url)) {
  1340. if (isProblem(local_url) && loadID == 1) {
  1341. submitProblems(local_url);
  1342. }
  1343. setTimeout(() => {
  1344. let submitbutton = null;
  1345. const isNext = !!document.querySelector("#__next");
  1346. if (isProblem(local_url) || isNext) {
  1347. submitbutton = document.querySelector("div [data-e2e-locator=console-submit-button]");
  1348. } else {
  1349. let buttons = Array.from(document.querySelectorAll(".question-detail-bottom .pull-right button"));
  1350. for (let i = buttons.length - 1; i >= 0; i--) {
  1351. if (buttons[i].textContent.indexOf("提交解答") != -1) {
  1352. submitbutton = buttons[i];
  1353. break;
  1354. }
  1355. }
  1356. }
  1357. if (submitbutton) {
  1358. submitbutton.addEventListener("click", () => {
  1359. submitProblems(local_url, 10 * 1e3);
  1360. });
  1361. watchDom(submitbutton);
  1362. } else if (loadID < 10) {
  1363. run();
  1364. }
  1365. }, 3e3);
  1366. } else if (isLeetCodeCircleUrl(local_url)) {
  1367. let Container = null;
  1368. let ok = Cache$1.get(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_button_is_none__"], true, Boolean.name);
  1369. const start = () => {
  1370. Container = document.createElement("div");
  1371. const body = document.querySelector("body");
  1372. body.append(Container);
  1373. Container.style.display = ok && support_plugins() ? "block" : "none";
  1374. return Container;
  1375. };
  1376. let dom = start();
  1377. const VueApp = vue.createApp(App);
  1378. _GM_registerMenuCommand(`${ok ? "隐藏按钮" : "显示按钮"}`, () => {
  1379. ok = !ok;
  1380. Container.style.display = ok ? "block" : "none";
  1381. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_button_is_none__"], ok);
  1382. }, { title: "可以手动关闭或者显示按钮 默认显示 刷新生效" });
  1383. _GM_registerMenuCommand(`安装到${install_pos() ? "右侧" : "左侧"}`, () => {
  1384. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_insert_pos__"], install_pos());
  1385. window.location.reload();
  1386. }, { title: "AC标记安装位置,默认左侧,刷新生效" });
  1387. _GM_registerMenuCommand(`清空题目状态缓存`, () => {
  1388. Message("确认清空题目状态缓存", () => {
  1389. Cache$1.remove(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_ac_key__"]);
  1390. window.location.reload();
  1391. });
  1392. }, { title: "如果题目状态出现问题,可以试试,一般情况下不建议使用" });
  1393. _GM_registerMenuCommand(`同步题目状态`, () => {
  1394. Message("确认同步题目状态", () => {
  1395. addProcess(true, void 0, true);
  1396. });
  1397. }, { title: "如果不在同一个浏览器答题,会出现ac题目状态没有及时同步,可以使用此功能" });
  1398. _GM_registerMenuCommand(`${initObj().onlyUrls ? "仅在收藏题单页面生效" : "所有题单生效"}`, () => {
  1399. const u = initObj();
  1400. u.onlyUrls = !u.onlyUrls;
  1401. Container.style.display = support_plugins() ? "block" : "none";
  1402. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_solution__"], u);
  1403. }, { title: "插件默认会在所有讨论发布页生效,如果只想在收藏链接生效,可以使用此功能" });
  1404. _GM_registerMenuCommand(`添加本页`, () => {
  1405. const urls = initUrls();
  1406. let ok2 = false;
  1407. let url = window.location.href;
  1408. for (let info of urls) {
  1409. if (!info || !(info == null ? void 0 : info.link)) {
  1410. continue;
  1411. }
  1412. if (info.link.indexOf(url) != -1) {
  1413. ok2 = true;
  1414. break;
  1415. }
  1416. }
  1417. if (ok2) {
  1418. ElementPlus.ElMessage({
  1419. message: "收藏失败,链接已经存在!",
  1420. type: "error"
  1421. });
  1422. } else {
  1423. if (isLeetCodeCircleUrl(url) && url.indexOf("view") != -1) {
  1424. try {
  1425. url = url.split("view")[0];
  1426. } catch (e) {
  1427. url = window.location.href;
  1428. }
  1429. }
  1430. urls.unshift({
  1431. title: document.title,
  1432. link: url
  1433. });
  1434. Container.style.display = "block";
  1435. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_urls__"], urls);
  1436. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_update__"], true);
  1437. Cache$1.set(__0X3F_PROBLEM_KEYS__["__0x3f_problmes_add_cur__"], true);
  1438. ElementPlus.ElMessage({
  1439. message: "收藏成功!刷新生效",
  1440. type: "success"
  1441. });
  1442. }
  1443. });
  1444. VueApp.use(ElementPlus).mount(dom);
  1445. }
  1446. }
  1447. run();
  1448. startStopRanking();
  1449.  
  1450. })(Vue, ElementPlus);

QingJ © 2025

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