// ==UserScript== // @name 新疆大学继续教育专业科目培训 // @namespace https://www.wlxy.live/ // @version 1.0 // @description 新疆大学继续教育学院(xjdxjxjy.xju.edu.cn):勾选课程、 常速免打开播放页面自动排队完成视频学时;免费体验 3 个视频章节,专业版激活后 30 天有效。 // @author 柠檬真酸 // @icon https://huaweicloudobs.ahjxjy.cn/895789f9086469785b846d30c0ed95f9.png // @match *://xjdxjxjy.xju.edu.cn/* // @exclude *://xjdxjxjy.xju.edu.cn/lms/web/course/view* // @exclude *://xjdxjxjy.xju.edu.cn/*/lms/web/course/view* // @noframes // @antifeature payment 免费体验3个视频章节,升级专业版激活后30天有效 // @antifeature membership 需会员授权 // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_openInTab // @connect xjdxjxjy.xju.edu.cn // @connect fs.cjnep.net // @connect huaweicloudobs.ahjxjy.cn // @connect oa31.ahzsksw.cn // @connect card.wlxy.live // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/vue/3.4.27/vue.global.prod.min.js // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/vue-demi/0.14.6/index.iife.js // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/dompurify/3.1.6/purify.min.js // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/crypto-js/4.2.0/crypto-js.min.js // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/pinia/2.2.4/pinia.iife.prod.js // @run-at document-idle // @tag 新疆大学继续教育学院 // @tag 学习辅助 // @license All Rights Reserved // ==/UserScript== (function(Vue,DOMPurify,Pinia,CryptoJS){ "use strict"; (() => { var Fe = "1.0", Ve = "\u65B0\u7586\u5927\u5B66\u7EE7\u7EED\u6559\u80B2\u4E13\u4E1A\u79D1\u76EE\u57F9\u8BAD", we = "__XJDXJXJY_WATCH_BOOT__", S = location.hostname.replace(/^www\./, ""), Y = location.origin, g = { enabled: `xjdx_enabled_${S}`, pace: `xjdx_pace_${S}`, onlyIncomplete: `xjdx_only_incomplete_${S}`, autoExam: `xjdx_auto_exam_${S}`, selected: `xjdx_selected_${S}`, panelPos: `xjdx_panel_pos_${S}`, collapsed: `xjdx_panel_collapsed_${S}`, examBank: `xjdx_exam_bank_${S}`, userId: `xjdx_user_id_${S}` }, j = { realtime: "realtime" }, W = 30; var ye = 0.8; var je = 300, Ge = "https://huaweicloudobs.ahjxjy.cn/895789f9086469785b846d30c0ed95f9.png", He = "\u514D\u8D39\u53EF\u4F53\u9A8C 3 \u4E2A\u89C6\u9891\u7AE0\u8282\uFF1B\u4E13\u4E1A\u7248\u6FC0\u6D3B\u540E 30 \u5929\u6709\u6548\u3002\u6309\u771F\u5B9E\u65F6\u957F\u5B66\u4E60\u3002", Be = "903117129", Je = "https://qun.qq.com/universal-share/share?ac=1&authKey=rxdL6YIJ0%2FxOEemjLqTGULvl5aAfJIVQcIvkvnwvmL%2FAmpFZnSafajYHgSXMUXvx&busi_data=eyJncm91cENvZGUiOiI5MDMxMTcxMjkiLCJ0b2tlbiI6IlB2dkFGSm5XRXBrSEhtQVFTUGQzdVNZakhNWDNMbW1kODA2enpoMi9obDh4SWp0YzBDODNFaGtwRU44Z0hyU0siLCJ1aW4iOiIxMjU0MzE1MTQifQ%3D%3D&data=9oyJixSPcigCQW-saV5eXlcMwV9C6J36XySx-rDHwVwNlofvRmd2ze5sLwFtHTbYbG4nAWIUrI0qftC6aTX9xg&svctype=4&tempid=h5_group_info", se = "https://oa31.ahzsksw.cn", Q = "xjdx_cloud_token_v1", le = "xjdx_cloud_lease_cache_v1", V = "https://card.wlxy.live/details/E97ED248", L = 3, Ce = 30, z = { courseIndex: "/lms/web/course/index", courseDetail: "/lms/web/course/detail", courseView: "/lms/web/course/view", startupXml: "/lms/web/course/startupxml", updStatus: "/lms/web/timing/updstatus", myInfo: "/lms/web/myinfo/index", home: "/lms/web/default/index" }; var ce = null; function Xe(e) { ce = e; } var K = { ws: null, hb: null }, n = { enabled: !1, stopFlag: !1, running: !1, pace: j.realtime, onlyIncomplete: !0, autoExam: !1, learningCourses: [], completedCourses: [], selectedIds: /* @__PURE__ */ new Set(), selectMode: "all", chapters: [], activeCourse: null, currentCourse: "", currentChapter: "", logs: [], task: "", panelHint: "", reportInterval: W, semester: (/* @__PURE__ */ new Date()).getFullYear(), userName: "", learningUserId: "", examBank: {}, queueVideoTotal: 0, queueVideoDone: 0, queueExamTotal: 0, queueExamDone: 0, queueChapterTotal: 0, queueChapterDone: 0, queueProgressPct: 0, queueMetricLabel: "\u95E8\u8BFE\u5DF2\u5B8C\u6210", studyModeHintTimer: null, cloudApiBase: se, cloudToken: String(localStorage.getItem(Q) || "").trim(), cloudLease: "", cloudLeaseExp: 0, cloudTier: "unknown", cloudProExpireAt: 0, freeCourseLimit: L, freeUsedCourses: 0, proActivationDays: 30, proBuyUrl: V, remotePanelNotice: "", cloudReady: !1 }, q = null; function Ye(e) { q = e; } function E(e) { return new Promise((t) => setTimeout(t, Math.max(0, e))); } function C(e) { return String(e ?? "").replace(/&/g, "&").replace(//g, ">"); } function R(e, t) { let r = String(e || ""); return r.length > t ? r.slice(0, t) + "\u2026" : r; } function w(e) { let t = Math.max(0, Math.floor(Number(e) || 0)), r = Math.floor(t / 60), i = t % 60; return `${r}:${String(i).padStart(2, "0")}`; } function Z(e, t) { try { let r = GM_getValue(e, null); return r == null ? t : typeof r == "string" ? JSON.parse(r) : r; } catch { return t; } } function de(e, t) { GM_setValue(e, JSON.stringify(t)); } function _e(e, t) { let r = e.startsWith("http") ? e : `${Y}${e}`; return fetch(r, { credentials: "include", ...t }).then(async (i) => { let o = await i.text(); if (!i.ok) throw new Error(`HTTP ${i.status}`); return { status: i.status, text: o, url: i.url }; }); } function ve(e, t, r, i) { let o = e.startsWith("http") ? e : `${Y}${e}`; return new Promise((a, s) => { if (typeof GM_xmlhttpRequest != "function") { _e(o, { method: t || "GET", headers: r, body: i }).then(a).catch(s); return; } GM_xmlhttpRequest({ method: t || "GET", url: o, headers: r || {}, data: i, withCredentials: !0, anonymous: !1, onload(l) { a({ status: l.status, text: l.responseText || "", url: l.finalUrl || o }); }, onerror() { s(new Error("\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25")); }, ontimeout() { s(new Error("\u8BF7\u6C42\u8D85\u65F6")); } }); }); } async function T(e) { try { return await _e(e, { method: "GET" }); } catch { return ve(e, "GET", { Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }); } } async function We(e, t, r) { let i = new URLSearchParams(); Object.keys(t || {}).forEach((a) => { t[a] != null && i.set(a, String(t[a])); }); let o = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", Accept: "application/xml, text/xml, */*; q=0.01", "X-Requested-With": "XMLHttpRequest" }; if (r && (o.Referer = r), r && typeof GM_xmlhttpRequest == "function") return ve(e, "POST", o, i.toString()); try { return await _e(e, { method: "POST", headers: o, body: i.toString() }); } catch { return ve(e, "POST", o, i.toString()); } } function v(e, t) { let r = String(e || "").match( new RegExp(`<${t}[^>]*>([\\s\\S]*?)${t}>`, "i") ); return r ? r[1].trim() : ""; } function Se(e) { let t = parseFloat(v(e, "maxViewedTime")) || 0, r = parseFloat(v(e, "lastViewedTime")) || 0, i = parseInt(v(e, "updInterval"), 10) || 30, o = v(e, "finish").toLowerCase(); return { userId: v(e, "userId"), courseId: v(e, "courseId"), scoId: v(e, "scoId"), scoTitle: v(e, "scoTitle"), historyId: v(e, "historyId"), maxViewedTime: t, lastViewedTime: r, updInterval: i, finish: o === "true" || o === "1", updStatusUrl: v(e, "updStatusUrl") || z.updStatus, status: v(e, "status"), raw: e }; } function ue(e) { let t = String(e || ""); if (/\/lms\/web\/default\/login/i.test(t) && /logincheck|验证码|登录/i.test(t) && !/default\/logout/i.test(t) && !/myinfo/i.test(t)) throw new Error("\u672A\u767B\u5F55\u6216\u4F1A\u8BDD\u5DF2\u5931\u6548\uFF0C\u8BF7\u5148\u767B\u5F55\u5E73\u53F0"); if (/请先登录|重新登录|会话已过期/i.test(t) && !/default\/logout/i.test(t)) throw new Error("\u672A\u767B\u5F55\u6216\u4F1A\u8BDD\u5DF2\u5931\u6548\uFF0C\u8BF7\u5148\u767B\u5F55\u5E73\u53F0"); } function O(e) { let t = String(e || "").trim(); if (t) { n.learningUserId = t; try { GM_setValue(g.userId, t); } catch { } } } function b() { if (n.learningUserId) return String(n.learningUserId); try { let e = String(GM_getValue(g.userId, "") || "").trim(); if (e) return n.learningUserId = e, e; } catch { } return ""; } function Qe() { return { userInfo: { id: b(), name: n.userName || "" }, token: { access_token: "cookie-session" } }; } async function pe() { try { let e = await T(z.home); ue(e.text); let t = e.text.match(/欢迎[^<]{0,6}([\u4e00-\u9fa5A-Za-z0-9_·]{2,20})/) || e.text.match(/class="[^"]*user[^"]*"[^>]*>([^<]{2,20}) { }; function Ze(e) { Ee = typeof e == "function" ? e : () => { }; } function et() { n.enabled = !!GM_getValue(g.enabled, !1), n.pace = j.realtime, GM_setValue(g.pace, j.realtime), n.onlyIncomplete = GM_getValue(g.onlyIncomplete, !0) !== !1, n.autoExam = !1, GM_setValue(g.autoExam, !1), n.examBank = Z(g.examBank, {}) || {}, n.learningUserId = String(GM_getValue(g.userId, "") || "").trim(); let e = Z(g.selected, null); e && typeof e == "object" && !Array.isArray(e) ? (n.selectMode = e.mode === "none" || e.mode === "partial" ? e.mode : "all", n.selectedIds = new Set(Array.isArray(e.ids) ? e.ids.map(String) : [])) : Array.isArray(e) ? (n.selectMode = e.length ? "partial" : "all", n.selectedIds = new Set(e.map(String))) : (n.selectMode = "all", n.selectedIds = /* @__PURE__ */ new Set()); } function fe() { de(g.selected, { mode: n.selectMode, ids: Array.from(n.selectedIds) }); } function Te(e) { let t = String(e); return n.selectMode === "none" ? !1 : n.selectMode === "all" ? !0 : n.selectedIds.has(t); } function D() { if (n.selectMode === "none") return []; let e = n.learningCourses; return n.selectMode === "all" ? e.slice() : e.filter((t) => n.selectedIds.has(String(t.id))); } function tt() { n.selectMode = "all", n.selectedIds = /* @__PURE__ */ new Set(), fe(), Ee(); } function nt() { n.selectMode = "none", n.selectedIds = /* @__PURE__ */ new Set(), fe(), Ee(); } function _(e, t) { if (t && t.completedView) return 100; let r = parseFloat(e.myCourseProgress ?? e.progress ?? 0) || 0; return r <= 0 && e.finished && (r = 100), Math.min(100, Math.max(0, r)); } function rt(e) { let t = parseFloat(e.credit); return Number.isFinite(t) && t > 0 ? t : 0; } function $t(e, t) { let r = rt(e), i = _(e, t); return r ? t && t.completedView || i >= 99.5 ? r : Math.round(r * i / 100 * 10) / 10 : null; } function Lt(e, t) { let r = _(e, t), i = rt(e), o = $t(e, t), a = []; return i > 0 && o != null ? a.push(`\u5B66\u65F6 ${o}/${i}`) : a.push(`\u5B66\u4E60\u8FDB\u5EA6 ${r.toFixed(0)}%`), e.lessonHours > 0 ? a.push(`\u5B66\u4E60\u65F6\u957F ${e.lessonHours} \u8BFE\u65F6`) : e.chapterTotal > 0 && a.push(`\u5171 ${e.chapterTotal} \u8BB2`), i > 0 && o != null && a.push(`\u8FDB\u5EA6 ${r.toFixed(0)}%`), a.join(" \xB7 "); } function Ie(e) { return _(e) >= 99.5 || !!e.finished; } function ke(e, t) { let r = t || {}, i = String(e.id), o = Te(i), a = _(e, r), s = !!(r.completedView || Ie(e)), l = C(e.name || e.title || `\u8BFE\u7A0B ${i}`), d = C(Lt(e, r)), u = s ? "#f1f5f9" : "#f8fafc", c = s ? "#64748b" : "#0f172a", p = r.completedView ? "disabled" : "", x = s ? '\u5DF2\u5B8C\u6210' : ""; return ``; } function Pt(e) { ue(e); let t = [], r = /* @__PURE__ */ new Set(), i = /class="[^"]*mycourse[^"]*"[\s\S]*?href="\/lms\/web\/course\/detail\?id=(\d+)"[\s\S]*?class="namediv">([^<]*)<\/div>\s*