0x3f-problem-solution

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

当前为 2024-07-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 0x3f-problem-solution
  3. // @namespace https://gf.qytechs.cn/zh-CN/scripts/501134-0x3f-problem-solution
  4. // @version 0.0.3
  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://gf.qytechs.cn/zh-CN/scripts/501134-0x3f-problem-solution
  10. // @match https://leetcode.cn/circle/discuss/*
  11. // @match https://leetcode.cn/problems/*
  12. // @match https://leetcode.cn/contest/weekly-contest-*/problems/*
  13. // @match https://leetcode.cn/contest/biweekly-contest-*/problems/*
  14. // @require https://cdn.jsdelivr.net/npm/vue@3.4.31/dist/vue.global.prod.js
  15. // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B
  16. // @require https://unpkg.com/element-plus@2.7.6/dist/index.full.js
  17. // @resource elementPlusCss https://unpkg.com/element-plus@2.7.6/dist/index.css
  18. // @grant GM_addStyle
  19. // @grant GM_getResourceText
  20. // @grant GM_registerMenuCommand
  21. // ==/UserScript==
  22.  
  23. (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const e=document.createElement("style");e.textContent=t,document.head.append(e)})(" .m-setting-button[data-v-1fb8b849]{position:fixed;top:200px;right:0;z-index:100000}.processs-flex[data-v-1fb8b849]{display:flex;justify-content:center;align-items:center} ");
  24.  
  25. (function (vue, ElementPlus) {
  26. 'use strict';
  27.  
  28. class Cache {
  29. set(k, v) {
  30. window.localStorage.setItem(k, v);
  31. }
  32. get(k, parse = true) {
  33. let o = window.localStorage.getItem(k);
  34. try {
  35. o = parse ? JSON.parse(o) : o;
  36. return o;
  37. } catch (E) {
  38. }
  39. return "";
  40. }
  41. remove(k) {
  42. window.localStorage.removeItem(k);
  43. }
  44. }
  45. const Cache$1 = new Cache();
  46. const _export_sfc = (sfc, props) => {
  47. const target = sfc.__vccOpts || sfc;
  48. for (const [key, val] of props) {
  49. target[key] = val;
  50. }
  51. return target;
  52. };
  53. const _sfc_main$1 = {};
  54. const _hoisted_1$1 = /* @__PURE__ */ vue.createElementVNode("p", null, " 1. 本人目前测试过,没有封号,但是对于查询过题目会缓存在本地,因此尽量不要清空浏览器缓存 ", -1);
  55. const _hoisted_2$1 = /* @__PURE__ */ vue.createElementVNode("p", null, " 2. 脚本会监控题做题提交状态 ,当题目提交时候会缓存题目状态,如果题单中有这个题目,会直接从缓存中获取 ", -1);
  56. const _hoisted_3$1 = [
  57. _hoisted_1$1,
  58. _hoisted_2$1
  59. ];
  60. function _sfc_render(_ctx, _cache) {
  61. return vue.openBlock(), vue.createElementBlock("div", null, _hoisted_3$1);
  62. }
  63. const Q1 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
  64. const isLeetCodeCircleUrl = (url = window.location.href) => url && url.indexOf("https://leetcode.cn/circle") != -1;
  65. const isProblem = (url = window.location.href) => /^https?:\/\/leetcode.cn\/problems\/.*/i.test(url);
  66. const isContest = (url = window.location.href) => url.indexOf("https://leetcode.cn/contest/weekly-contest") != -1 || url.indexOf("https://leetcode.cn/contest/biweekly-contest") != -1;
  67. const width = 14;
  68. const height = 14;
  69. const problemFinsh = `
  70.  
  71. <svg width="${width}px" height="${height}px" viewBox="0 0 1024 1024" version="1.1"
  72. xmlns="http://www.w3.org/2000/svg">
  73. <path d="M512 512m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#4CAF50" />
  74. <path
  75. d="M738.133333 311.466667L448 601.6l-119.466667-119.466667-59.733333 59.733334 179.2 179.2 349.866667-349.866667z"
  76. fill="#CCFF90" />
  77. </svg>
  78.  
  79. `;
  80. const problemsTry = `
  81. <svg width="${width}px" height="${height}px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
  82. xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
  83. style="enable-background:new 0 0 512 512;" xml:space="preserve">
  84. <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
  85. S390.101,12.8,256,12.8z" />
  86. <g>
  87. <path style="fill:#573A32;" d="M256,115.2c-49.271,0-92.561,25.353-117.726,63.676l18.859,18.859
  88. 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
  89. C396.8,178.244,333.764,115.2,256,115.2z" />
  90. <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
  91. 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" />
  92. <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
  93. 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
  94. C334.822,348.194,298.266,371.2,256,371.2z" />
  95. </g>
  96. </svg>
  97.  
  98. `;
  99. const problemsNo = `
  100.  
  101. `;
  102. const inf = 4e3;
  103. const mi = 1e3;
  104. const __0x3f_problmes_solution__ = "__0x3f_problmes_solution__";
  105. const __0x3f_problmes_urls__ = "__0x3f_problmes_urls__";
  106. const __0x3f_problmes_update__ = "__0x3f_problmes_update__";
  107. const __is_none_0x3f_problmes_button__ = "__is_none_0x3f_problmes_button__";
  108. const __add_cur__ = "__add_cur__";
  109. const Problems = () => Array.from(document.querySelectorAll(".css-1ayia3m-MarkdownContent li>a"));
  110. const defaultObj = {
  111. min: mi,
  112. max: inf,
  113. visiableMember: true,
  114. onlyUrls: false,
  115. useDefaultSetting: true
  116. };
  117. function isShow(text, min, max) {
  118. if (!text) {
  119. return true;
  120. }
  121. let res = text.match(/\d+/ig);
  122. if (!res) {
  123. return true;
  124. }
  125. if (Array.isArray(res) && res.length < 2) {
  126. return true;
  127. }
  128. let s = 0;
  129. for (let i = res.length - 1; i >= 0; i--) {
  130. s = res[i];
  131. if (s >= mi && s <= inf) {
  132. return s >= min && s <= max;
  133. }
  134. }
  135. return true;
  136. }
  137. let A = [];
  138. function loadProblems() {
  139. if (!Array.isArray(A) || Array.isArray(A) && A.length == 0) {
  140. A = Problems().filter((text) => {
  141. if (text instanceof HTMLAnchorElement) {
  142. return text.href.indexOf("https://leetcode.cn/problems") != -1;
  143. }
  144. return true;
  145. });
  146. }
  147. }
  148. function handlerProblem(data) {
  149. var _a;
  150. loadProblems();
  151. let { min, max, visiableMember, useDefaultSetting, onlyUrls } = data;
  152. if (isNaN(min) || isNaN(max)) {
  153. min = mi;
  154. max = inf;
  155. }
  156. if (min < mi) {
  157. min = mi;
  158. }
  159. if (max < min) {
  160. max = inf;
  161. }
  162. min = Number(min);
  163. max = Number(max);
  164. data.min = min;
  165. data.max = max;
  166. Cache$1.set(__0x3f_problmes_solution__, JSON.stringify(data));
  167. for (let i = 0; i < A.length; i++) {
  168. let d = (_a = A[i]) == null ? void 0 : _a.parentElement;
  169. if (!d) {
  170. continue;
  171. }
  172. let flag = isShow(d.textContent, min, max);
  173. d.style.display = flag ? "" : "none";
  174. let c = d.textContent && d.textContent.indexOf("会员") != -1;
  175. if (!c) {
  176. continue;
  177. }
  178. d.style.display = visiableMember ? "" : "none";
  179. }
  180. }
  181. const initUrls = () => Cache$1.get(__0x3f_problmes_update__) ? Array.isArray(Cache$1.get(__0x3f_problmes_urls__)) ? Cache$1.get(__0x3f_problmes_urls__) : [] : defaultUrls;
  182. const initObj = () => Cache$1.get(__0x3f_problmes_solution__) ? Object.assign(defaultObj, Cache$1.get(__0x3f_problmes_solution__)) : defaultObj;
  183. const support_plugins = () => {
  184. const u = initObj();
  185. if (!u || !u.onlyUrls) return true;
  186. const url = window.location.href;
  187. const urls = initUrls();
  188. for (let info of urls) {
  189. if (!info || !(info == null ? void 0 : info.link)) {
  190. continue;
  191. }
  192. console.log("url find", info.link.indexOf(url) != -1, info.link, url);
  193. if (info.link.indexOf(url) != -1) {
  194. return true;
  195. }
  196. }
  197. return false;
  198. };
  199. const defaultUrls = [
  200. {
  201. title: "贪心算法(基本贪心策略/反悔/区间/字典序/数学/思维/构造)",
  202. link: "https://leetcode.cn/circle/discuss/g6KTKL/"
  203. },
  204. {
  205. title: "滑动窗口(定长/不定长/多指针)",
  206. link: "https://leetcode.cn/circle/discuss/0viNMK/"
  207. },
  208. {
  209. title: "二分算法(二分答案/最小化最大值/最大化最小值/第K小)",
  210. link: "https://leetcode.cn/circle/discuss/SqopEo/"
  211. },
  212. {
  213. title: "单调栈(矩形面积/贡献法/最小字典序)",
  214. link: "https://leetcode.cn/circle/discuss/9oZFK9/"
  215. },
  216. {
  217. title: "网格图(DFS/BFS/综合应用)",
  218. link: "https://leetcode.cn/circle/discuss/YiXPXW/"
  219. },
  220. {
  221. title: "位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)",
  222. link: "https://leetcode.cn/circle/discuss/dHn9Vk/"
  223. },
  224. {
  225. title: "图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)",
  226. link: "https://leetcode.cn/circle/discuss/01LUak/"
  227. },
  228. {
  229. title: "动态规划(入门/背包/状态机/划分/区间/状压/数位/树形/数据结构优化)",
  230. link: "https://leetcode.cn/circle/discuss/tXLS3i/"
  231. },
  232. {
  233. title: "常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)",
  234. link: "https://leetcode.cn/circle/discuss/mOr1u6/"
  235. },
  236. {
  237. title: "数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)",
  238. link: "https://leetcode.cn/circle/discuss/IYT3ss/"
  239. }
  240. ];
  241. function getId(problemUrl) {
  242. if (isContest(problemUrl) || isProblem(problemUrl)) {
  243. try {
  244. return problemUrl.split("problems")[1].split("/")[1];
  245. } catch (e) {
  246. return "";
  247. }
  248. }
  249. return "";
  250. }
  251. const local_ok_problem_key = "__local_ok_problem_key__";
  252. const STATUS = {
  253. "AC": "ac",
  254. "NO": "null",
  255. "notac": "notac"
  256. };
  257. function postData(ID) {
  258. return {
  259. "query": "\n query userQuestionStatus($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n status\n }\n}\n ",
  260. "variables": {
  261. "titleSlug": ID
  262. },
  263. "operationName": "userQuestionStatus"
  264. };
  265. }
  266. function addProcess() {
  267. var _a;
  268. loadProblems();
  269. let problems_doms = A;
  270. const cache = Cache$1.get(local_ok_problem_key, true) ?? {};
  271. for (let i = 0; i < problems_doms.length; i++) {
  272. let cur = problems_doms[i].parentElement;
  273. if (!(cur instanceof HTMLElement) || (cur == null ? void 0 : cur.mark)) {
  274. continue;
  275. }
  276. const ID = getId((_a = problems_doms[i]) == null ? void 0 : _a.href);
  277. if (!ID) {
  278. continue;
  279. }
  280. if (cache[ID]) {
  281. let status = cache[ID];
  282. cur.innerHTML = cur.innerHTML + (status == STATUS["AC"] ? problemFinsh : status == STATUS["notac"] ? problemsTry : problemsNo);
  283. } else {
  284. fetch("https://leetcode.cn/graphql/", {
  285. method: "POST",
  286. credentials: "include",
  287. headers: {
  288. "Content-Type": "application/json"
  289. },
  290. body: JSON.stringify(postData(ID))
  291. }).then((res) => res.json()).then((response) => {
  292. var _a2, _b;
  293. const status = (_b = (_a2 = response == null ? void 0 : response.data) == null ? void 0 : _a2.question) == null ? void 0 : _b.status;
  294. if (status == STATUS["AC"]) {
  295. cur.innerHTML = cur.innerHTML + problemFinsh;
  296. } else if (status == STATUS["notac"]) {
  297. cur.innerHTML = cur.innerHTML + problemsTry;
  298. } else {
  299. {
  300. cur.innerHTML = cur.innerHTML + problemsNo;
  301. }
  302. }
  303. cache[ID] = status == null ? "null" : status;
  304. cur.status = cache[ID];
  305. Cache$1.set(local_ok_problem_key, JSON.stringify(cache));
  306. }).catch((ignore) => {
  307. });
  308. }
  309. cur.mark = true;
  310. }
  311. }
  312. const submitProblems = (url = window.location.href) => {
  313. const ID = getId(url);
  314. if (!ID) {
  315. return;
  316. }
  317. setTimeout(() => {
  318. const cache = Cache$1.get(local_ok_problem_key, true) ?? {};
  319. console.log("ID:", ID, "query status: ", cache[ID]);
  320. if (cache[ID] != STATUS["AC"]) {
  321. fetch("https://leetcode.cn/graphql/", {
  322. method: "POST",
  323. credentials: "include",
  324. headers: {
  325. "Content-Type": "application/json"
  326. },
  327. body: JSON.stringify(postData(ID))
  328. }).then((res) => res.json()).then((response) => {
  329. var _a, _b;
  330. const status = (_b = (_a = response == null ? void 0 : response.data) == null ? void 0 : _a.question) == null ? void 0 : _b.status;
  331. cache[ID] = status == null ? "null" : status;
  332. console.log("save local status :", cache[ID]);
  333. Cache$1.set(local_ok_problem_key, JSON.stringify(cache));
  334. }).catch((ignore) => {
  335. });
  336. }
  337. }, 3e3);
  338. };
  339. function getProcess() {
  340. loadProblems();
  341. const cache = Cache$1.get(local_ok_problem_key, true) ?? {};
  342. let cnt = 0;
  343. for (let i = 0; i < A.length; i++) {
  344. let ID = getId(A[i].href);
  345. if (ID && cache[ID] == STATUS["AC"]) {
  346. cnt++;
  347. }
  348. }
  349. return [cnt, A.length];
  350. }
  351. const _hoisted_1 = { class: "processs-flex" };
  352. const _hoisted_2 = { style: { "text-align": "center", "color": "#121212" } };
  353. const _hoisted_3 = { class: "dialog-footer" };
  354. const formLabelWidth = "44px";
  355. const _sfc_main = {
  356. __name: "App",
  357. setup(__props) {
  358. let totProblem = vue.ref(0);
  359. let finishProblem = vue.ref(0);
  360. const drawer = vue.ref(false);
  361. const viewSetting = () => {
  362. drawer.value = !drawer.value;
  363. let [cur, tot] = getProcess();
  364. finishProblem.value = cur;
  365. totProblem.value = tot;
  366. };
  367. const finishProcess = vue.computed(() => parseFloat((finishProblem.value / totProblem.value).toFixed(1)) * 100);
  368. const processStatus = vue.computed(
  369. () => {
  370. let val = finishProcess.value;
  371. console.log("value:", val, totProblem.value, finishProblem.value);
  372. if (val < 50) {
  373. return "";
  374. } else if (60 <= val && val < 70) {
  375. return "warning";
  376. } else if (70 <= val && val < 90) {
  377. return "exception";
  378. } else {
  379. return "success";
  380. }
  381. }
  382. );
  383. const fromData = vue.reactive(initObj());
  384. vue.watch(fromData, () => {
  385. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  386. });
  387. let tableData = vue.reactive(initUrls());
  388. const keywords = vue.ref("");
  389. const dialogTableVisible = vue.ref(false);
  390. const urlsData = vue.computed(() => tableData.filter((v) => v && v.title && v.title.indexOf(keywords.value) != -1));
  391. const dialogFormVisible = vue.ref(false);
  392. const info = vue.reactive({
  393. title: "",
  394. link: "",
  395. status: "add"
  396. });
  397. const addlocal = () => {
  398. let ok = false;
  399. for (let a of tableData) {
  400. if (a && a.link.indexOf(window.location.href) != -1) {
  401. ok = true;
  402. }
  403. }
  404. if (ok) {
  405. return;
  406. }
  407. tableData.unshift({ title: document.title, link: window.location.href });
  408. };
  409. const updateIndex = vue.ref(-1);
  410. const showProblems = () => {
  411. dialogTableVisible.value = true;
  412. let o = Cache$1.get(__add_cur__) == "true" || Cache$1.get(__add_cur__) == true;
  413. if (o) {
  414. addlocal();
  415. }
  416. };
  417. const handlerProblems = (status, updateInfo = { title: "", link: "" }, index = -1) => {
  418. dialogFormVisible.value = true;
  419. info.status = status;
  420. updateIndex.value = index;
  421. Object.assign(info, updateInfo);
  422. };
  423. const handlerMessage = (u, title, link) => {
  424. const a = u ? "添加" : "修改";
  425. const error = !title || !/https?:\/\/.*/.test(link);
  426. if (error) {
  427. ElementPlus.ElMessage.error(`${a} 失败 请保证标题或者链接有效 `);
  428. } else {
  429. ElementPlus.ElMessage.success(`${a} 成功 `);
  430. }
  431. return !error;
  432. };
  433. const addOrUpdate = () => {
  434. if (!handlerMessage(info.status == "add", info.title, info.link)) {
  435. return;
  436. }
  437. if (info.status == "add") {
  438. tableData.unshift({ title: info.title, link: info.link });
  439. } else {
  440. let index = updateIndex.value;
  441. if (index != -1 && index < tableData.length) {
  442. tableData[index].link = info.link;
  443. tableData[index].title = info.title;
  444. }
  445. }
  446. dialogFormVisible.value = false;
  447. };
  448. const deleteProblems = (index) => {
  449. tableData.splice(index, 1);
  450. Cache$1.set(__0x3f_problmes_urls__, vue.toRaw(tableData));
  451. };
  452. const handlerDefault = () => {
  453. ElementPlus.ElMessageBox.confirm(
  454. "确认使用默认题单,将会重置题单?",
  455. "警告",
  456. {
  457. confirmButtonText: "确认",
  458. cancelButtonText: "取消",
  459. type: "warning"
  460. }
  461. ).then(() => {
  462. for (let i = 0; i < tableData.length; i++) {
  463. delete tableData[i];
  464. }
  465. for (let item of defaultUrls) {
  466. tableData.unshift(item);
  467. }
  468. ElementPlus.ElMessage({
  469. type: "success",
  470. message: "重置成功"
  471. });
  472. }).catch(() => {
  473. ElementPlus.ElMessage({
  474. type: "info",
  475. message: "取消重置"
  476. });
  477. });
  478. };
  479. window.addEventListener("beforeunload", () => {
  480. Cache$1.set(__0x3f_problmes_urls__, JSON.stringify(vue.toRaw(tableData)));
  481. Cache$1.set(__0x3f_problmes_update__, true);
  482. Cache$1.set(__add_cur__, false);
  483. });
  484. vue.onMounted(() => {
  485. if (support_plugins()) {
  486. setTimeout(() => {
  487. handlerProblem(vue.toRaw(Object.assign({}, fromData)));
  488. addProcess();
  489. }, 3e3);
  490. }
  491. });
  492. const q1 = vue.ref(false);
  493. return (_ctx, _cache) => {
  494. const _component_el_button = vue.resolveComponent("el-button");
  495. const _component_el_progress = vue.resolveComponent("el-progress");
  496. const _component_el_divider = vue.resolveComponent("el-divider");
  497. const _component_el_input = vue.resolveComponent("el-input");
  498. const _component_el_col = vue.resolveComponent("el-col");
  499. const _component_el_form_item = vue.resolveComponent("el-form-item");
  500. const _component_el_switch = vue.resolveComponent("el-switch");
  501. const _component_el_tooltip = vue.resolveComponent("el-tooltip");
  502. const _component_el_form = vue.resolveComponent("el-form");
  503. const _component_el_dialog = vue.resolveComponent("el-dialog");
  504. const _component_el_row = vue.resolveComponent("el-row");
  505. const _component_el_link = vue.resolveComponent("el-link");
  506. const _component_el_table_column = vue.resolveComponent("el-table-column");
  507. const _component_el_table = vue.resolveComponent("el-table");
  508. const _component_el_drawer = vue.resolveComponent("el-drawer");
  509. return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
  510. vue.createElementVNode("div", null, [
  511. vue.createVNode(_component_el_button, {
  512. type: "primary",
  513. style: { "margin-left": "16px" },
  514. onClick: viewSetting,
  515. class: "m-setting-button"
  516. }, {
  517. default: vue.withCtx(() => [
  518. vue.createTextVNode(" 设置 ")
  519. ]),
  520. _: 1
  521. })
  522. ]),
  523. vue.createVNode(_component_el_drawer, {
  524. modelValue: drawer.value,
  525. "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => drawer.value = $event),
  526. "with-header": false,
  527. size: "30%"
  528. }, {
  529. default: vue.withCtx(() => [
  530. vue.createElementVNode("div", _hoisted_1, [
  531. vue.createVNode(_component_el_progress, {
  532. type: "circle",
  533. percentage: finishProcess.value,
  534. status: processStatus.value
  535. }, {
  536. default: vue.withCtx(({ percentage }) => [
  537. vue.createElementVNode("p", null, vue.toDisplayString(percentage) + "%", 1)
  538. ]),
  539. _: 1
  540. }, 8, ["percentage", "status"])
  541. ]),
  542. vue.createElementVNode("p", _hoisted_2, vue.toDisplayString(vue.unref(finishProblem)) + " / " + vue.toDisplayString(vue.unref(totProblem)), 1),
  543. vue.createVNode(_component_el_divider),
  544. vue.createVNode(_component_el_form, {
  545. "label-position": "left",
  546. "label-width": "auto",
  547. model: fromData,
  548. style: { "max-width": "600px" }
  549. }, {
  550. default: vue.withCtx(() => [
  551. vue.createVNode(_component_el_form_item, { label: "分数区间" }, {
  552. default: vue.withCtx(() => [
  553. vue.createVNode(_component_el_col, { span: 10 }, {
  554. default: vue.withCtx(() => [
  555. vue.createVNode(_component_el_input, {
  556. modelValue: fromData.min,
  557. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => fromData.min = $event),
  558. "aria-placeholder": "",
  559. placeholder: " min "
  560. }, null, 8, ["modelValue"])
  561. ]),
  562. _: 1
  563. }),
  564. vue.createVNode(_component_el_col, {
  565. class: "text-center",
  566. span: 1,
  567. style: { "margin": "0 0.5rem" }
  568. }, {
  569. default: vue.withCtx(() => [
  570. vue.createTextVNode("-")
  571. ]),
  572. _: 1
  573. }),
  574. vue.createVNode(_component_el_col, { span: 10 }, {
  575. default: vue.withCtx(() => [
  576. vue.createVNode(_component_el_input, {
  577. modelValue: fromData.max,
  578. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => fromData.max = $event),
  579. "aria-placeholder": "",
  580. placeholder: " max"
  581. }, null, 8, ["modelValue"])
  582. ]),
  583. _: 1
  584. })
  585. ]),
  586. _: 1
  587. }),
  588. vue.createVNode(_component_el_form_item, { label: "显示会员题" }, {
  589. default: vue.withCtx(() => [
  590. vue.createVNode(_component_el_switch, {
  591. modelValue: fromData.visiableMember,
  592. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => fromData.visiableMember = $event)
  593. }, null, 8, ["modelValue"])
  594. ]),
  595. _: 1
  596. }),
  597. vue.createVNode(_component_el_form_item, { label: "只在收藏题单中生效" }, {
  598. default: vue.withCtx(() => [
  599. vue.createVNode(_component_el_tooltip, {
  600. content: "插件只在收藏题单中生效,刷新生效 ",
  601. placement: "bottom-end"
  602. }, {
  603. default: vue.withCtx(() => [
  604. vue.createVNode(_component_el_switch, {
  605. modelValue: fromData.onlyUrls,
  606. "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => fromData.onlyUrls = $event)
  607. }, null, 8, ["modelValue"])
  608. ]),
  609. _: 1
  610. })
  611. ]),
  612. _: 1
  613. }),
  614. vue.createVNode(_component_el_form_item, { label: "使用题单" }, {
  615. default: vue.withCtx(() => [
  616. vue.createVNode(_component_el_switch, {
  617. modelValue: fromData.useDefaultSetting,
  618. "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => fromData.useDefaultSetting = $event)
  619. }, null, 8, ["modelValue"])
  620. ]),
  621. _: 1
  622. })
  623. ]),
  624. _: 1
  625. }, 8, ["model"]),
  626. fromData.useDefaultSetting ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  627. vue.createVNode(_component_el_divider),
  628. vue.createVNode(_component_el_button, {
  629. plain: "",
  630. onClick: showProblems
  631. }, {
  632. default: vue.withCtx(() => [
  633. vue.createTextVNode(" 查看收藏的题单 ")
  634. ]),
  635. _: 1
  636. }),
  637. vue.createVNode(_component_el_divider)
  638. ], 64)) : vue.createCommentVNode("", true),
  639. vue.createVNode(_component_el_divider),
  640. vue.createVNode(_component_el_button, {
  641. plain: "",
  642. onClick: _cache[5] || (_cache[5] = ($event) => q1.value = !q1.value)
  643. }, {
  644. default: vue.withCtx(() => [
  645. vue.createTextVNode(" 问题1 ")
  646. ]),
  647. _: 1
  648. }),
  649. vue.createVNode(_component_el_divider),
  650. vue.createVNode(_component_el_dialog, {
  651. modelValue: q1.value,
  652. "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => q1.value = $event),
  653. title: "会不会被封号 ?"
  654. }, {
  655. default: vue.withCtx(() => [
  656. vue.createVNode(Q1)
  657. ]),
  658. _: 1
  659. }, 8, ["modelValue"]),
  660. vue.createVNode(_component_el_dialog, {
  661. modelValue: dialogTableVisible.value,
  662. "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => dialogTableVisible.value = $event),
  663. title: "题单"
  664. }, {
  665. default: vue.withCtx(() => [
  666. vue.createVNode(_component_el_row, { gutter: 10 }, {
  667. default: vue.withCtx(() => [
  668. vue.createVNode(_component_el_col, { span: 8 }, {
  669. default: vue.withCtx(() => [
  670. vue.createVNode(_component_el_input, {
  671. modelValue: keywords.value,
  672. "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => keywords.value = $event),
  673. placeholder: "请输入关键词过滤",
  674. clearable: ""
  675. }, null, 8, ["modelValue"])
  676. ]),
  677. _: 1
  678. }),
  679. vue.createVNode(_component_el_col, { span: 16 }, {
  680. default: vue.withCtx(() => [
  681. vue.createVNode(_component_el_button, {
  682. plain: "",
  683. onClick: addlocal
  684. }, {
  685. default: vue.withCtx(() => [
  686. vue.createTextVNode(" 添加本页 ")
  687. ]),
  688. _: 1
  689. }),
  690. vue.createVNode(_component_el_button, {
  691. plain: "",
  692. onClick: _cache[8] || (_cache[8] = ($event) => handlerProblems("add"))
  693. }, {
  694. default: vue.withCtx(() => [
  695. vue.createTextVNode(" 自定义 ")
  696. ]),
  697. _: 1
  698. }),
  699. vue.createVNode(_component_el_button, {
  700. plain: "",
  701. onClick: handlerDefault
  702. }, {
  703. default: vue.withCtx(() => [
  704. vue.createTextVNode(" 默认 ")
  705. ]),
  706. _: 1
  707. })
  708. ]),
  709. _: 1
  710. })
  711. ]),
  712. _: 1
  713. }),
  714. vue.createVNode(_component_el_table, {
  715. data: urlsData.value,
  716. height: "300",
  717. style: { "width": "100%", "margin-top": "10px" }
  718. }, {
  719. default: vue.withCtx(() => [
  720. vue.createVNode(_component_el_table_column, {
  721. label: "标题",
  722. width: "auto",
  723. align: "center"
  724. }, {
  725. default: vue.withCtx((scope) => [
  726. vue.createVNode(_component_el_link, {
  727. href: scope.row.link,
  728. target: "_blank",
  729. type: "default"
  730. }, {
  731. default: vue.withCtx(() => [
  732. vue.createTextVNode(vue.toDisplayString(scope.row.title), 1)
  733. ]),
  734. _: 2
  735. }, 1032, ["href"])
  736. ]),
  737. _: 1
  738. }),
  739. vue.createVNode(_component_el_table_column, {
  740. label: "操作",
  741. width: "auto",
  742. align: "center"
  743. }, {
  744. default: vue.withCtx((scope) => [
  745. vue.createVNode(_component_el_button, {
  746. type: "primary",
  747. size: "small",
  748. onClick: ($event) => handlerProblems("update", scope.row, scope.$index)
  749. }, {
  750. default: vue.withCtx(() => [
  751. vue.createTextVNode("编辑")
  752. ]),
  753. _: 2
  754. }, 1032, ["onClick"]),
  755. vue.createVNode(_component_el_button, {
  756. type: "danger",
  757. size: "small",
  758. onClick: ($event) => deleteProblems(scope.$index)
  759. }, {
  760. default: vue.withCtx(() => [
  761. vue.createTextVNode("删除")
  762. ]),
  763. _: 2
  764. }, 1032, ["onClick"])
  765. ]),
  766. _: 1
  767. })
  768. ]),
  769. _: 1
  770. }, 8, ["data"])
  771. ]),
  772. _: 1
  773. }, 8, ["modelValue"]),
  774. vue.createVNode(_component_el_dialog, {
  775. modelValue: dialogFormVisible.value,
  776. "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => dialogFormVisible.value = $event),
  777. title: `${info.status == "add" ? "添加" : "编辑"}`,
  778. width: "400"
  779. }, {
  780. footer: vue.withCtx(() => [
  781. vue.createElementVNode("div", _hoisted_3, [
  782. vue.createVNode(_component_el_button, {
  783. onClick: _cache[12] || (_cache[12] = ($event) => dialogFormVisible.value = false)
  784. }, {
  785. default: vue.withCtx(() => [
  786. vue.createTextVNode("取消")
  787. ]),
  788. _: 1
  789. }),
  790. vue.createVNode(_component_el_button, {
  791. type: "primary",
  792. onClick: addOrUpdate
  793. }, {
  794. default: vue.withCtx(() => [
  795. vue.createTextVNode(" 确认 ")
  796. ]),
  797. _: 1
  798. })
  799. ])
  800. ]),
  801. default: vue.withCtx(() => [
  802. vue.createVNode(_component_el_form, null, {
  803. default: vue.withCtx(() => [
  804. vue.createVNode(_component_el_form_item, {
  805. label: "标题",
  806. "label-width": formLabelWidth
  807. }, {
  808. default: vue.withCtx(() => [
  809. vue.createVNode(_component_el_input, {
  810. modelValue: info.title,
  811. "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => info.title = $event),
  812. autocomplete: "off"
  813. }, null, 8, ["modelValue"])
  814. ]),
  815. _: 1
  816. }),
  817. vue.createVNode(_component_el_form_item, {
  818. label: "链接",
  819. "label-width": formLabelWidth
  820. }, {
  821. default: vue.withCtx(() => [
  822. vue.createVNode(_component_el_input, {
  823. modelValue: info.link,
  824. "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => info.link = $event),
  825. autocomplete: "off"
  826. }, null, 8, ["modelValue"])
  827. ]),
  828. _: 1
  829. })
  830. ]),
  831. _: 1
  832. })
  833. ]),
  834. _: 1
  835. }, 8, ["modelValue", "title"])
  836. ]),
  837. _: 1
  838. }, 8, ["modelValue"])
  839. ], 64);
  840. };
  841. }
  842. };
  843. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1fb8b849"]]);
  844. const cssLoader = (e) => {
  845. const t = GM_getResourceText(e);
  846. return GM_addStyle(t), t;
  847. };
  848. cssLoader("elementPlusCss");
  849. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  850. const stopRankingKey = "__is_stop_rating_ranking__";
  851. let conetstTimeId = null;
  852. function run$1() {
  853. const container = document.querySelector(".contest-question-info .list-group");
  854. if (!container) return;
  855. const ls = Array.from(container.querySelectorAll(".list-group-item .pull-right"));
  856. for (let i = 0; i < 4; i++) {
  857. if (i >= ls.length) {
  858. break;
  859. }
  860. if (ls[i] instanceof HTMLElement) {
  861. ls[i].textContent = "0";
  862. }
  863. }
  864. window.clearInterval(conetstTimeId);
  865. }
  866. function startStopRanking() {
  867. if (!isContest(window.location.href)) {
  868. return;
  869. }
  870. const isNext = !!document.querySelector("#__next");
  871. if (isNext) {
  872. return;
  873. }
  874. const use = Cache$1.get(stopRankingKey);
  875. _GM_registerMenuCommand(`${use ? "使用" : "关闭"} 排行榜`, () => {
  876. Cache$1.set(stopRankingKey, !use);
  877. window.location.reload();
  878. }, { title: "对于不想看到排行榜的可以使用此功能 默认开启" });
  879. if (!use) {
  880. return;
  881. }
  882. conetstTimeId = setInterval(() => {
  883. run$1();
  884. }, 10);
  885. }
  886. const local_url = window.location.href;
  887. let loadID = 0;
  888. function run() {
  889. loadID++;
  890. if (isProblem(local_url) || isContest(local_url)) {
  891. if (isProblem(local_url)) {
  892. submitProblems(local_url);
  893. }
  894. setTimeout(() => {
  895. let submitbutton = null;
  896. const isNext = !!document.querySelector("#__next");
  897. if (isProblem(local_url) || isNext) {
  898. submitbutton = document.querySelector("div [data-e2e-locator=console-submit-button]");
  899. } else {
  900. let buttons = Array.from(document.querySelectorAll(".question-detail-bottom .pull-right button"));
  901. for (let i = buttons.length - 1; i >= 0; i--) {
  902. if (buttons[i].textContent.indexOf("提交解答") != -1) {
  903. submitbutton = buttons[i];
  904. break;
  905. }
  906. }
  907. }
  908. if (submitbutton) {
  909. submitbutton.addEventListener("click", () => {
  910. submitProblems(local_url);
  911. });
  912. } else if (loadID < 10) {
  913. run();
  914. }
  915. }, 3e3);
  916. } else if (isLeetCodeCircleUrl(local_url)) {
  917. let Container = null;
  918. let ok = Cache$1.get(__is_none_0x3f_problmes_button__) == null ? true : Cache$1.get(__is_none_0x3f_problmes_button__);
  919. const start = () => {
  920. Container = document.createElement("div");
  921. const body = document.querySelector("body");
  922. body.append(Container);
  923. Container.style.display = ok && support_plugins() ? "block" : "none";
  924. return Container;
  925. };
  926. let dom = start();
  927. const VueApp = vue.createApp(App);
  928. _GM_registerMenuCommand(`${ok ? "隐藏按钮" : "显示按钮"}`, () => {
  929. ok = !ok;
  930. Container.style.display = ok ? "block" : "none";
  931. Cache$1.set(__is_none_0x3f_problmes_button__, ok);
  932. }, { title: "可以手动关闭或者显示按钮 默认显示 刷新生效" });
  933. _GM_registerMenuCommand(`${initObj().onlyUrls ? "仅在收藏题单页面生效" : "所有题单生效"}`, () => {
  934. const u = initObj();
  935. u.onlyUrls = !u.onlyUrls;
  936. Container.style.display = support_plugins() ? "block" : "none";
  937. Cache$1.set(__0x3f_problmes_solution__, JSON.stringify(u));
  938. });
  939. _GM_registerMenuCommand(`添加本页`, () => {
  940. const urls = initUrls();
  941. let ok2 = false;
  942. const url = window.location.href;
  943. for (let info of urls) {
  944. if (!info || !(info == null ? void 0 : info.link)) {
  945. continue;
  946. }
  947. if (info.link.indexOf(url) != -1) {
  948. ok2 = true;
  949. break;
  950. }
  951. }
  952. if (ok2) {
  953. ElementPlus.ElMessage({
  954. message: "收藏失败,链接已经存在!",
  955. type: "error"
  956. });
  957. } else {
  958. urls.unshift({
  959. title: document.title,
  960. link: url
  961. });
  962. Container.style.display = "block";
  963. Cache$1.set(__0x3f_problmes_urls__, JSON.stringify(urls));
  964. Cache$1.set(__add_cur__, true);
  965. ElementPlus.ElMessage({
  966. message: "收藏成功!刷新生效",
  967. type: "success"
  968. });
  969. }
  970. });
  971. VueApp.use(ElementPlus).mount(dom);
  972. }
  973. }
  974. run();
  975. startStopRanking();
  976.  
  977. })(Vue, ElementPlus);

QingJ © 2025

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