// ==UserScript== // @name 甘肃专业技术人员继续教育(沃尔德·平凉市教育培训中心)学习助手 // @namespace https://www.wlxy.live/ // @version 1.2 // @description 甘肃专技继续教育·沃尔德(www.w2dzx.com)与平凉市教育培训中心等分站(*.brjxjy.com):勾选课程、自动完成视频学时;免费体验 2 个章节课时(不含自动考试),专业版激活后不限课时与考试。 // @author 柠檬真酸 // @icon https://huaweicloudobs.ahjxjy.cn/895789f9086469785b846d30c0ed95f9.png // @match *://www.w2dzx.com/* // @match *://w2dzx.com/* // @match *://*.brjxjy.com/* // @noframes // @antifeature payment 免费体验2个章节课时(不含自动考试),升级专业版不限 // @antifeature membership 需会员授权 // @antifeature tracking 为授权绑定向云端发送平台用户标识 // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_openInTab // @connect www.w2dzx.com // @connect w2dzx.com // @connect *.brjxjy.com // @connect huaweicloudobs.ahjxjy.cn // @connect oa29.ahzsksw.cn // @connect oa33.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 it = "1.2"; var st = "\u7518\u8083\u4E13\u6280\u7EE7\u7EED\u6559\u80B2(\u6C83\u5C14\u5FB7\xB7\u5E73\u51C9\u5E02\u6559\u80B2\u57F9\u8BAD\u4E2D\u5FC3)\u52A9\u624B", Z = "__W2DZX_WATCH_BOOT__", R = location.hostname.replace(/^www\./, ""), ee = location.origin, h = /\.brjxjy\.com$/i.test(String(location.hostname || "")) ? "pl" : "wed", w = { enabled: `w2dzx_enabled_${R}`, pace: `w2dzx_pace_${R}`, onlyIncomplete: `w2dzx_only_incomplete_${R}`, autoExam: `w2dzx_auto_exam_${R}`, selected: `w2dzx_selected_${R}`, panelPos: `w2dzx_panel_pos_${R}`, collapsed: `w2dzx_collapsed_${R}`, examBank: `w2dzx_exam_bank_${R}` }, V = { efficiency: "efficiency", turbo: "turbo", realtime: "realtime", player: "player" }; var ct = 30, K = 5, lt = 12, dt = 1600, Re = 200; var ut = "https://huaweicloudobs.ahjxjy.cn/895789f9086469785b846d30c0ed95f9.png", pt = "\u5B66\u6EE1\u8BFE\u7A0B\u5BF9\u5E94\u5B66\u65F6\u5373\u53EF\uFF0C\u65E0\u9700\u770B\u5B8C\u6240\u6709\u7AE0\u8282\u3002\u514D\u8D39\u7248\u4E0D\u542B\u81EA\u52A8\u8003\u8BD5\uFF1B\u4E13\u4E1A\u7248\u53EF\u5B66\u5B8C\u8BA1\u5212\u540E\u81EA\u52A8\u8003\u8BD5\u3002\u8BF7\u52FF\u540C\u65F6\u6253\u5F00\u591A\u4E2A\u64AD\u653E\u9875\u3002", ft = "903117129", mt = "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", Ce = "https://oa33.ahzsksw.cn", ce = "w2dzx_cloud_token_v1", Ee = "w2dzx_cloud_lease_cache_v1", le = "w2dzx_client_cfg_v1", H = "https://card.wlxy.live/details/AC690A57", q = 2; var xt = "", gt = "", bt = "wed_token", ht = "20180227110419WB", yt = "ZZWBKJ_ZHIHUAWEI", je = h === "pl" ? ["pl_token", "wed_token"] : ["wed_token", "pl_token"], zt = h === "pl" ? ["pl_userinfo", "wed_userinfo"] : ["wed_userinfo", "pl_userinfo"], P = { videoDonePct: 99.99, courseDonePct: 99.5, courseCreditRatio: 0.99, progressLogIntervalMs: 12e4, defaultTicktok: 30 }; var $e = null; function _t(e) { $e = e; } var r = { enabled: !1, stopFlag: !1, running: !1, pace: "efficiency", onlyIncomplete: !0, autoExam: !1, studyPlans: [], planGroups: [], learningCourses: [], completedCourses: [], selectedIds: /* @__PURE__ */ new Set(), selectMode: "all", chapters: [], activeCourse: null, activeVideoId: "", currentCourse: "", currentChapter: "", logs: [], task: "", panelHint: "", reportInterval: ct, semester: (/* @__PURE__ */ new Date()).getFullYear(), userName: "", examBank: {}, queueVideoTotal: 0, queueVideoDone: 0, queueExamTotal: 0, queueExamDone: 0, studyModeHintTimer: null, cloudApiBase: Ce, cloudToken: String(localStorage.getItem(ce) || "").trim(), cloudLease: "", cloudLeaseExp: 0, cloudTier: "unknown", cloudProExpireAt: 0, freeCourseLimit: q, freeUsedCourses: 0, proBuyUrl: H, remotePanelNotice: "", canExam: !1, freeCanExam: !1, cloudReady: !1, activationTtlDays: 30, videoDonePct: P.videoDonePct, courseDonePct: P.courseDonePct, courseCreditRatio: P.courseCreditRatio, progressLogIntervalMs: P.progressLogIntervalMs, defaultTicktok: P.defaultTicktok }, J = null; function wt(e) { J = e; } function j(e) { return new Promise((t) => setTimeout(t, Math.max(0, e))); } function z(e) { return String(e ?? "").replace(/&/g, "&").replace(//g, ">"); } function C(e, t) { let n = String(e || ""); return n.length > t ? n.slice(0, t) + "\u2026" : n; } function Y(e) { let t = Math.max(0, Math.floor(Number(e) || 0)), n = Math.floor(t / 60), o = t % 60; return `${n}:${String(o).padStart(2, "0")}`; } function de(e, t) { try { let n = GM_getValue(e, null); return n == null ? t : typeof n == "string" ? JSON.parse(n) : n; } catch { return t; } } function ue(e, t) { GM_setValue(e, JSON.stringify(t)); } function St(e) { if (e == null || e === "") return 0; if (typeof e == "number" && Number.isFinite(e)) return Math.max(0, e); let t = String(e).trim(); if (/^\d+(\.\d+)?$/.test(t)) return parseFloat(t) || 0; let n = t.split(":").map((o) => parseInt(o, 10) || 0); return n.length === 3 ? n[0] * 3600 + n[1] * 60 + n[2] : n.length === 2 ? n[0] * 60 + n[1] : 0; } var pe = [], te = String(xt || ""), ne = String(gt || ""); function kt(e) { pe.unshift({ ...e, at: Date.now() }), pe.length > 120 && (pe.length = 120); let t = window[Z]; t && typeof t == "object" ? t.netLog = pe : window[Z] = { netLog: pe }; } function bn(e, t) { let n = {}; try { for (let [o, a] of e.entries()) t && o === "token" ? n[o] = `${String(a).slice(0, 8)}\u2026` : n[o] = a; } catch { } return n; } function qe(e) { let t = document.cookie.match( new RegExp( `(?:^|;\\s*)${e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)` ) ); return t ? decodeURIComponent(t[1]) : ""; } function fe(e, t) { let n = String(e || "").trim(), o = String(t || "").trim(); n && (te = n), o && (ne = o); } function hn() { try { let e = localStorage.getItem(le); if (!e) return !1; let t = JSON.parse(e); return fe(t.aesKey, t.aesIv), !!(te && ne); } catch { return !1; } } function vt() { if (!te || !ne) throw new Error("\u4E91\u7AEF\u914D\u7F6E\u672A\u5C31\u7EEA\uFF08\u7F3A\u5C11\u5E73\u53F0\u5BC6\u94A5\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u68C0\u67E5\u7F51\u7EDC"); } function y(e) { vt(); let t = CryptoJS.enc.Utf8.parse(te), n = CryptoJS.enc.Utf8.parse(ne); return CryptoJS.AES.encrypt(String(e), t, { iv: n, padding: CryptoJS.pad.Pkcs7 }).toString(); } function Ne(e) { if (!e) return ""; vt(); let t = CryptoJS.enc.Utf8.parse(te), n = CryptoJS.enc.Utf8.parse(ne); return CryptoJS.AES.decrypt(String(e), t, { iv: n, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8); } function Ct(e) { let t = Array.isArray(e) ? e : [e]; for (let n of [sessionStorage, localStorage]) for (let o of t) try { let a = n.getItem(o); if (a) return String(a).trim(); } catch { } return ""; } function yn() { let e = Ct(je); if (e) return e; for (let n of je) { let o = qe(n); if (o) return o.trim(); } let t = qe(bt); if (t) return t.trim(); try { if (typeof window.$cookies?.get == "function") for (let n of je) { let o = window.$cookies.get(n); if (o) return String(o).trim(); } } catch { } return ""; } function Pe() { let e = ""; for (let t of zt) { if (e = qe(t) || Ct([t]), e) break; try { if (e = window.$cookies?.get?.(t) || "", e) break; } catch { } } if (!e) return null; try { let t = Ne(e); return t ? JSON.parse(t) : null; } catch { try { return JSON.parse(e); } catch { return null; } } } function Be() { let e = Pe(), t = e?.stu_id ?? e?.user_id ?? e?.id ?? ""; return String(t || "").trim(); } function zn() { let e = yn(); if (!e) throw new Error("\u672A\u767B\u5F55\u6216 token \u5931\u6548\uFF0C\u8BF7\u5148\u767B\u5F55\u5E73\u53F0"); let t = Pe(); return t && (r.userName = t.stu_name || t.name || "", r.semester = Number(t.stu_year) || Number((/* @__PURE__ */ new Date()).getFullYear())), e; } function _(e, t, n) { let a = { token: zn(), ...t || {} }; Object.keys(a).forEach((u) => { a[u] == null && delete a[u]; }); let i = new FormData(); Object.entries(a).forEach(([u, c]) => i.append(u, String(c))); let s = `${ee}${e}`, l = {}, f = n && n.referer; f && (l.Referer = f, l.Origin = ee); let d = bn(i, !0); kt({ phase: "request", path: e, url: s, fields: d }); let m = (u) => { let c = {}; try { c = JSON.parse(u.responseText || "{}"); } catch ($) { throw new Error(`\u54CD\u5E94\u89E3\u6790\u5931\u8D25: ${$.message}`); } kt({ phase: "response", path: e, status: u.status, code: c.code, msg: c.msg, data: c.data }); let b = c.code === 1 || c.code === 0; if (u.status >= 200 && u.status < 300 && b) return c; let x = new Error(c.msg || c.message || `HTTP ${u.status}`); throw x.code = c.code, x.data = c.data, x; }; return new Promise((u, c) => { GM_xmlhttpRequest({ method: "POST", url: s, data: i, headers: l, onload(b) { try { u(m(b)); } catch (x) { c(x); } }, onerror() { c(new Error("\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25")); } }); }); } hn(); h === "pl" && (!te || !ne) && fe(ht, yt); var Ge = () => { }; function Et(e) { Ge = typeof e == "function" ? e : () => { }; } function _n(e, t) { return `${e}:${t}`; } function me(e) { let t = y(String(e.courseId || e.rawId)); if (h === "pl" || e._site === "pl") { let a = y("course"); return `${ee}/web/videoPlay?course_id=${encodeURIComponent(t)}&source=${encodeURIComponent(a)}`; } let n = y(String(e.planId)), o = y("myPlan"); return `${ee}/web/planVideoPlay?ids=${encodeURIComponent(n)}&course_id=${encodeURIComponent(t)}&source=${encodeURIComponent(o)}`; } function wn(e) { let t = String(e?.alerdy_courseware ?? e?.already_courseware ?? "").trim(), n = t.match(/([\d.]+)\s*%/); if (n) return Math.min(100, Math.max(0, parseFloat(n[1]) || 0)); let o = parseFloat(t); return Number.isFinite(o) && o >= 0 && o <= 100 ? o : 0; } function Sn(e) { let t = e.cou_id ?? e.id, n = Number(e.already_sum_time) || 0, o = Number(e.cou_sumtime) || 0, a = wn(e); !(a > 0) && o > 0 && (a = Math.min(100, n / o * 100)); let i = String(e.sig_passtext || "").toLowerCase() === "yes", s = o > 0 ? o / 3600 : 0, l = n / 3600; return { ...e, _site: "pl", rawId: t, id: `pl:${t}`, courseId: t, name: e.cou_name || e.courseName || String(t), title: e.cou_name || e.courseName || String(t), planId: "pl", sigId: "", planName: "\u6211\u7684\u8BFE\u7A0B", progress: a, completedPeriodPercent: a, completedPeriod: s > 0 ? Math.min(s, l) : l, courseStudyDuration: s > 0 ? s : 0, isCompleted: i ? "\u5DF2\u5B8C\u6210" : !1, alreadySumTime: n, _plNeedSec: o, _plAlreadySec: n }; } function kn(e) { let t = Array.isArray(e) ? e : [], n = (o, a) => { let i = o.cow_id ?? o.id ?? `cow${a}`, s = Number(o.cow_duration ?? o.duration ?? 0) || 0, l = Number(o.progress ?? 0) || 0, f = Number(o.isStudy), d = f === 2 || s > 0 && l > 0 && l >= s - 1; return { id: i, videoName: o.cow_name || o.name || String(i), videoDuration: s, durationSec: s, progressPercent: d ? 100 : s > 0 ? Math.min(100, l / s * 100) : 0, _progressSec: d ? s : l, studyStatus: d ? "\u5DF2\u5B8C\u6210" : f === 1 || l > 0 ? "\u5B66\u4E60\u4E2D" : "", isStudy: f }; }; return t.some((o) => Array.isArray(o.chapter_list)) ? t.map((o, a) => ({ id: o.cow_id || o.id || o.chapter_id || `ch${a}`, chapterName: o.cow_name || o.chapter_name || o.name || `\u7AE0\u8282${a + 1}`, children: (o.chapter_list || []).map(n) })) : [ { id: "all", chapterName: "\u8BFE\u4EF6", children: t.filter((o) => o && (o.cow_id || o.id)).map(n) } ]; } function vn(e) { if (!e || !e.id) return; let t = (n) => !n || String(n.id) !== String(e.id) ? n : { ...n, ...e, id: n.id, children: e.children || n.children }; r.learningCourses = (r.learningCourses || []).map(t), r.completedCourses = (r.completedCourses || []).map(t), r.planGroups = (r.planGroups || []).map((n) => ({ ...n, courses: (n.courses || []).map(t) })), r.activeCourse && String(r.activeCourse.id) === String(e.id) && (r.activeCourse = { ...r.activeCourse, ...e }); } function jt() { r.enabled = !!GM_getValue(w.enabled, !1), r.pace = V.efficiency, GM_setValue(w.pace, V.efficiency), r.onlyIncomplete = GM_getValue(w.onlyIncomplete, !0) !== !1, r.autoExam = !0, GM_setValue(w.autoExam, !0), r.examBank = de(w.examBank, {}) || {}; let e = de(w.selected, null); e && typeof e == "object" && !Array.isArray(e) ? (r.selectMode = e.mode === "none" || e.mode === "partial" ? e.mode : "all", r.selectedIds = new Set(Array.isArray(e.ids) ? e.ids : [])) : Array.isArray(e) ? (r.selectMode = e.length ? "partial" : "all", r.selectedIds = new Set(e)) : (r.selectMode = "all", r.selectedIds = /* @__PURE__ */ new Set()); } function Le() { ue(w.selected, { mode: r.selectMode, ids: Array.from(r.selectedIds) }); } function $t(e) { return r.selectMode === "none" ? !1 : r.selectMode === "all" ? !0 : r.selectedIds.has(e); } function L() { if (r.selectMode === "none") return []; let e = F(); return r.selectMode === "all" ? e.slice() : e.filter((t) => r.selectedIds.has(t.id)); } function Nt() { r.selectMode = "all", r.selectedIds = /* @__PURE__ */ new Set(), Le(), Ge(); } function Pt() { r.selectMode = "none", r.selectedIds = /* @__PURE__ */ new Set(), Le(), Ge(); } function M(e) { let t = Ie(e), n = parseFloat(e.completedPeriod); if (t > 0 && Number.isFinite(n) && n >= 0) return Math.min(100, Math.max(0, n / t * 100)); let o = e.completedPeriodPercent ?? e.progress ?? 0, a = parseFloat(String(o)) || 0; return a <= 0 && (e.isCompleted === "\u5DF2\u5B8C\u6210" || e.isCompleted === !0) && (a = 100), Math.min(100, Math.max(0, a)); } function Ie(e) { let t = parseFloat(e.courseStudyDuration ?? e.period); return Number.isFinite(t) && t > 0 ? t : 0; } function Cn(e) { let t = Ie(e), n = parseFloat(e.completedPeriod); if (Number.isFinite(n) && n >= 0) return t > 0 ? Math.min(t, n) : n; let o = M(e); return t ? o >= (r.courseDonePct || 99.5) ? t : Math.round(t * o / 100 * 10) / 10 : null; } function Lt(e) { let t = M(e); if (e && (e._site === "pl" || h === "pl")) { let a = Number(e._plAlreadySec ?? e.alreadySumTime) || 0, i = Number(e._plNeedSec) || 0; if (i > 0) { let s = (a / 3600).toFixed(1), l = (i / 3600).toFixed(1); return `\u5DF2\u5B66 ${s}/${l} \u5C0F\u65F6 \xB7 ${t.toFixed(0)}%`; } return `\u5B66\u4E60\u8FDB\u5EA6 ${t.toFixed(0)}%`; } let n = Ie(e), o = Cn(e); return n > 0 && o != null ? `\u5B66\u65F6 ${o}/${n} \xB7 \u5B66\u4E60 ${t.toFixed(0)}%` : `\u5B66\u4E60\u8FDB\u5EA6 ${t.toFixed(0)}%`; } function En(e) { return S(e) ? "\u5B66\u65F6\u5DF2\u6EE1" : "\u5B66\u65F6\u672A\u6EE1"; } function jn(e) { return S(e) ? "#16a34a" : "#64748b"; } function $n(e, t) { let n = e || {}, o = Array.isArray(t) ? t : [], a = o.length > 0 && o.every((f) => S(f)), i = Number(n.sig_remain_num); if (n.sig_passtext === "yes") return { text: "\u5DF2\u901A\u8FC7", hint: "\u8BA1\u5212\u8003\u8BD5\u5DF2\u901A\u8FC7", ready: !1, passed: !0, color: "#16a34a" }; if (n.is_can_exam === 1 || a) return { text: "\u53EF\u8003\u8BD5", hint: `\u8BFE\u7A0B\u5DF2\u5B66\u5B8C\uFF0C\u70B9\u5F00\u59CB\u540E\u81EA\u52A8\u56E4\u9898\u5E76\u8003\u8BD5${Number.isFinite(i) ? ` \xB7 \u5269\u4F59 ${i} \u6B21` : ""}`, ready: !0, passed: !1, color: "#b45309" }; if (n.is_can_exam_message) return { text: "\u672A\u5F00\u653E", hint: String(n.is_can_exam_message), ready: !1, passed: !1, color: "#64748b" }; let s = parseFloat(n.sig_alerdy_video), l = parseFloat(n.stp_period); return Number.isFinite(s) && Number.isFinite(l) && l > 0 ? { text: "\u5B66\u5B8C\u53EF\u8003", hint: `\u8BA1\u5212\u8FDB\u5EA6 ${s.toFixed(1)}/${l} \u5B66\u65F6`, ready: !1, passed: !1, color: "#64748b" } : { text: "\u5B66\u5B8C\u53EF\u8003", hint: "\u5B66\u5B8C\u672C\u7EC4\u8BFE\u7A0B\u540E\u5F00\u653E\u8003\u8BD5", ready: !1, passed: !1, color: "#64748b" }; } function xe() { ue(w.examBank, r.examBank || {}); } function ge(e) { let t = []; for (let n of e.children || []) for (let o of n.children || []) !o || !o.id || t.push({ ...o, chapterId: n.id, chapterName: n.chapterName || "", durationSec: St(o.videoDuration), courseId: e.courseId || e.rawId, planId: e.planId }); return t; } function S(e) { if (!e) return !1; if (e.isCompleted === "\u5DF2\u5B8C\u6210" || e.isCompleted === !0) return !0; if (e._site === "pl" || h === "pl" && e._plNeedSec != null) { let o = Number(e._plNeedSec) || 0, a = Number(e._plAlreadySec ?? e.alreadySumTime) || 0; return o > 0 && a >= o * (r.courseCreditRatio || 0.99) ? !0 : M(e) >= (r.courseDonePct || 99.5); } let t = Ie(e), n = parseFloat(e.completedPeriod); return t > 0 && Number.isFinite(n) && n >= t * (r.courseCreditRatio || 0.99) ? !0 : M(e) >= (r.courseDonePct || 99.5); } async function be() { if (h === "pl") return r.studyPlans = [{ stp_id: "pl", stp_name: "\u6211\u7684\u8BFE\u7A0B", _site: "pl" }], r.studyPlans; let e = [], t = 1, n = 20; for (; !r.stopFlag; ) { let o = await _("/api/v2.Order/getMyStudyPlanList", { page: String(t), limit: String(n) }), a = o && o.data || {}, i = a.data || []; if (e.push(...i), !i.length || t >= (a.last_page || 1)) break; t += 1; } return r.studyPlans = e, e; } async function Nn() { let e = [], t = 1, n = 20; for (; !r.stopFlag; ) { let o = await _("/api/student.Info/myCourse.html", { cou_typeid: "", page: String(t), limit: String(n) }), a = o && o.data || {}, i = Array.isArray(a.data) ? a.data : Array.isArray(a) ? a : []; e.push(...i.map(Sn)); let s = Number(a.total) || 0; if (!i.length || s > 0 && e.length >= s || i.length < n || (t += 1, t > 50)) break; } return e; } async function Pn(e) { if (h === "pl" || e?._site === "pl") return Nn(); let t = e.stp_id, n = await _("/api/v2.Order/getMyStudyPlanCourseList", { ids: y(String(t)) }); return ((n && n.data || {}).data || []).map((a) => ({ ...a, rawId: a.id, id: _n(t, a.id), courseId: a.id, name: a.courseName || a.name || a.id, title: a.courseName || a.name || a.id, planId: t, sigId: e.sig_id, planName: e.stp_name || "", _plan: e })); } async function he() { let e = await be(), t = [], n = [], o = []; for (let a of e) { if (r.stopFlag) break; let i = await Pn(a); o.push({ plan: a, planId: String(a.stp_id), name: a.stp_name || `\u8BA1\u5212${a.stp_id}`, courses: i }); for (let s of i) S(s) ? n.push(s) : t.push(s); } return r.planGroups = o, r.learningCourses = t, r.completedCourses = n, { learning: t, completed: n, plans: e, planGroups: o }; } async function W(e) { if (h === "pl" || e._site === "pl") { let a = await _("/api/student.Order/courseWareList.html", { course_id: y(String(e.courseId || e.rawId)) }), i = a && a.data || [], s = kn(i), l = { ...e, children: s, _site: "pl" }; return vn(l), l; } let t = await _("/api/v2.Order/getMyStudyPlanCourseList", { ids: y(String(e.planId)) }), o = ((t && t.data || {}).data || []).find((a) => String(a.id) === String(e.courseId)); return o ? { ...e, ...o, rawId: o.id, id: e.id, courseId: o.id, name: o.courseName || e.name, title: o.courseName || e.name, planId: e.planId, sigId: e.sigId, planName: e.planName, _plan: e._plan } : e; } async function Ae(e, t, n) { if (h === "pl") { let a = await _( "/api/student.Order/video.html", { cow_id: y(String(e)) }, n ? { referer: n } : void 0 ), i = a && a.data || {}, s = Number(i.cow_duration) || 0, l = Number(i.progress) || 0, f = Number.isFinite(l) && l > 0 ? s > 0 ? Math.min(l, s) : l : 0; return { videoDuration: s, progress: f, con_video_speed_open: 1, video_id: String(e), tiktok_time: Number(i.tiktok_time) || void 0, cow_thumb: i.cow_thumb }; } let o = await _( "/api/v2.Order/getMyStudyPlanCourseVideo", { video_id: y(String(e)), plan_id: y(String(t)) }, n ? { referer: n } : void 0 ); return o && o.data || null; } async function It(e) { let t = Array.isArray(e) ? e : []; for (let n of t) if (!(!n || n.children && n.children.length)) try { await W(n); } catch (o) { console.warn("[w2dzx] preload courseware", n.name, o?.message || o); } } function F() { return r.planGroups && r.planGroups.length ? r.planGroups.flatMap((e) => e.courses || []) : [...r.learningCourses, ...r.completedCourses]; } function At(e, t) { let n = t || {}, o = !!n.checkable, a = !!n.checked, i = !!n.isActive, s = e.name || e.title || e.courseName || e.id, l = M(e), f = S(e), d = jn(e), m = o ? `` : "", u = o ? "label" : "div"; return `<${u} class="w2-course-card${i ? " is-active" : ""}${f ? " is-done" : ""}"> ${m} ${z(s)} ${f ? '\u5B66\u65F6\u5DF2\u6EE1' : ""} ${z(Lt(e))} ${z(En(e))} `; } function Ln(e, t) { let n = $n(e, t), o = n.ready ? " is-ready" : "", a = n.passed ? " is-passed" : ""; return `
\u8BA1\u5212\u8003\u8BD5 ${z(n.hint)} ${z(n.text)}
`; } function In(e, t) { let o = (t || {}).activeId, a = e.plan || {}, i = e.courses || [], s = e.name || a.stp_name || `\u8BA1\u5212${e.planId}`, l = i.filter((d) => S(d)).length, f = i.map( (d) => At(d, { checkable: !0, checked: $t(d.id), isActive: d.id === o }) ).join(""); return `
${z(s)} ${l}/${i.length} \u95E8
${f}${Ln(a, i)}
`; } function Tt(e) { let t = r.planGroups || []; if (!t.length) { let n = F(); return n.length ? n.map( (o) => At(o, { checkable: !0, checked: $t(o.id), isActive: o.id === e }) ).join("") : ""; } return t.map((n) => In(n, { activeId: e })).join(""); } function An(e) { let t = parseFloat(e); if (!Number.isFinite(t) || t <= 0) return "0"; if (t >= 100) return "100"; let n = Math.round(t * 100) / 100; return String(n); } function Tn(e) { if (Te(e)) return "\u5DF2\u5B8C\u6210"; let t = parseFloat(e.progressPercent) || 0; return e.studyStatus === "\u5B66\u4E60\u4E2D" || t > 0 ? `\u5B66\u4E60\u4E2D ${An(t)}%` : "\u672A\u5F00\u59CB"; } function Te(e) { if (!e) return !1; if (e.studyStatus === "\u5DF2\u5B8C\u6210" || Number(e.isStudy) === 2) return !0; let t = Number(e.durationSec || e.videoDuration) || 0, n = Number(e._progressSec) || 0; if (t > 0 && n >= t - 1) return !0; let o = parseFloat(e.progressPercent); return !!(Number.isFinite(o) && o >= (r.videoDonePct || 99.99)); } function re(e, t, n, o) { let a = o || {}, i = Number(n) || 0, s = Math.max(0, Number(t) || 0), l = i > 0 ? Math.min(100, s / i * 100) : 0, d = a.finished === !0 || l >= (r.videoDonePct || 99.99), m = String(e), u = 0, c = (x) => { !x || String(x.id) !== m || (x.progressPercent = d ? 100 : Math.round(l * 100) / 100, x._progressSec = s, i > 0 && (x.durationSec = i), d ? (x.studyStatus = "\u5DF2\u5B8C\u6210", x.progressPercent = 100) : l > 0 && (x.studyStatus = "\u5B66\u4E60\u4E2D"), u += 1); }, b = (x) => { if (x) for (let $ of x.children || []) for (let k of $.children || []) c(k); }; b(r.activeCourse); for (let x of r.planGroups || []) for (let $ of x.courses || []) b($); for (let x of r.learningCourses || []) b(x); for (let x of r.completedCourses || []) b(x); return u; } function Mt(e) { let t = Array.isArray(e) ? e : []; if (!t.length) return '
\u6682\u65E0\u8BFE\u7A0B\u7AE0\u8282
\u8BF7\u5148\u5237\u65B0\u8BFE\u7A0B\u5217\u8868
'; let n = String(r.activeVideoId || ""); return t.map((o) => { let a = o.name || o.title || o.id, i = o.children || [], s = ge(o), l = Lt(o), f = i.length > 0 ? i.map((d) => { let m = d.children || [], u = m.map((c) => { let b = Tn(c), x = Te(c), $ = n && String(c.id) === n; return `
${z(c.videoName || c.id)} ${z(c.videoDuration || "")} \xB7 ${z(b)}
`; }).join(""); return `
${z(d.chapterName || "\u7AE0\u8282")} \xB7 ${m.length} \u8282
${u || '
\u6682\u65E0\u8BFE\u4EF6
'}
`; }).join("") : `
\u6682\u65E0\u7AE0\u8282\uFF08\u5171 ${s.length} \u4E2A\u8BFE\u4EF6\uFF09
`; return `
${z(a)} ${z(l)}
${f}
`; }).join(""); } var Ft = () => { }; function Dt(e) { Ft = typeof e == "function" ? e : () => { }; } function p(e, t) { let n = { t: Date.now(), msg: String(e || ""), type: t || "info" }; r.logs.unshift(n), r.logs.length > Re && (r.logs.length = Re), Ft(); } function g(e) { if ($e) { let t = $e.querySelector("#" + e); if (t) return t; } return document.getElementById(e); } function ye(e, t) { if (!e) return; let n = typeof DOMPurify < "u" && DOMPurify.sanitize ? DOMPurify.sanitize(t, { USE_PROFILES: { html: !0 } }) : t; e.innerHTML = n; } var Ot = () => { }; function Ut(e) { Ot = typeof e == "function" ? e : () => { }; } function Mn() { return String(r.cloudApiBase || Ce).replace(/\/+$/, ""); } function Ve() { return String(r.proBuyUrl || H).trim() || H; } function Fn() { return r.cloudTier === "pro"; } function Rt(e) { if (!e || typeof e != "object") return; let t = (n, o) => { let a = Number(n); return Number.isFinite(a) ? a : o; }; e.videoDonePct != null && (r.videoDonePct = t(e.videoDonePct, P.videoDonePct)), e.courseDonePct != null && (r.courseDonePct = t(e.courseDonePct, P.courseDonePct)), e.courseCreditRatio != null && (r.courseCreditRatio = t(e.courseCreditRatio, P.courseCreditRatio)), e.progressLogIntervalMs != null && (r.progressLogIntervalMs = Math.max( 1e3, t(e.progressLogIntervalMs, P.progressLogIntervalMs) )), e.defaultTicktok != null && (r.defaultTicktok = Math.max(1, t(e.defaultTicktok, P.defaultTicktok))), e.activationTtlDays != null && (r.activationTtlDays = Math.max(1, t(e.activationTtlDays, 30))), e.freeCanExam != null && (r.freeCanExam = !!e.freeCanExam); } function Dn(e) { try { localStorage.setItem(le, JSON.stringify(e || {})); } catch { } } function qt() { try { let e = localStorage.getItem(le); if (!e) return !1; let t = JSON.parse(e); fe(t.aesKey, t.aesIv), Rt(t), t.cloudApiBase && (r.cloudApiBase = String(t.cloudApiBase).replace(/\/+$/, "")); let n = t.freeChapterLimit ?? t.freeCourseLimit; return n != null && (r.freeCourseLimit = Number(n) || q), t.proBuyUrl && (r.proBuyUrl = String(t.proBuyUrl).trim() || H), !0; } catch { return !1; } } function On() { try { let e = JSON.parse(localStorage.getItem(Ee) || "null"), t = String(e?.lease || "").trim(), n = Number(e?.exp || 0); return !t || !Number.isFinite(n) || n * 1e3 <= Date.now() + 15e3 ? null : e; } catch { return null; } } function ze(e, t, n) { if (!e || !t) { localStorage.removeItem(Ee); return; } localStorage.setItem( Ee, JSON.stringify(Object.assign({ lease: e, exp: t }, n || {})) ); } function Un(e) { let t = String(e || "").trim(), n = { "invalid token": "\u6FC0\u6D3B\u7801\u65E0\u6548", revoked: "\u6FC0\u6D3B\u7801\u5DF2\u505C\u7528", expired: "\u6FC0\u6D3B\u7801\u5DF2\u8FC7\u671F", expired_after_activation: "\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u5F00\u901A", token_bound_to_other_learning_user: "\u6FC0\u6D3B\u7801\u5DF2\u7ED1\u5B9A\u5176\u4ED6\u8D26\u53F7", free_quota_exhausted: "\u514D\u8D39\u4F53\u9A8C\u7AE0\u8282\u8BFE\u65F6\u5DF2\u7528\u5B8C\uFF0C\u8BF7\u5347\u7EA7\u4E13\u4E1A\u7248", free_course_quota_exceeded: "\u514D\u8D39\u4F53\u9A8C\u7AE0\u8282\u8BFE\u65F6\u5DF2\u7528\u5B8C\uFF0C\u8BF7\u5347\u7EA7\u4E13\u4E1A\u7248", invalid_lease: "\u4F1A\u8BDD\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u8BD5", rate_limited: "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5" }; return n[t] || n[t.toLowerCase()] || t || "\u64CD\u4F5C\u5931\u8D25"; } function Bt(e, t, n) { let a = `${Mn()}${e.startsWith("/") ? e : `/${e}`}`, i = { Accept: "application/json", "Content-Type": "application/json" }, s = Be(); s && (i["x-learning-user-id"] = s), r.cloudToken && (i.Authorization = `Bearer ${r.cloudToken}`); let l = n == null ? null : JSON.stringify(n); return new Promise((f, d) => { let m = { method: t || "GET", url: a, headers: i, timeout: 3e4, withCredentials: !1, responseType: "text", onload: (u) => f({ status: u.status, text: u.responseText || "" }), onerror: () => d(new Error("\u7F51\u7EDC\u5F02\u5E38")), ontimeout: () => d(new Error("\u8BF7\u6C42\u8D85\u65F6")) }; if (l != null && (m.data = l), typeof GM_xmlhttpRequest == "function") { GM_xmlhttpRequest(m); return; } fetch(a, { method: m.method, headers: i, body: l }).then(async (u) => f({ status: u.status, text: await u.text() })).catch(() => d(new Error("\u7F51\u7EDC\u5F02\u5E38"))); }); } async function _e(e, t, n) { let o = await Bt(e, t, n), a = String(o.text || "").trim(), i = null; if (a) try { i = JSON.parse(a); } catch { throw new Error(`\u670D\u52A1\u5F02\u5E38(HTTP ${o.status})`); } if (o.status >= 400) { let s = i?.message || i?.detail || `HTTP ${o.status}`, l = new Error(Un(s)); throw l.status = o.status, l.data = i, l; } return i || {}; } async function Gt() { return r.cloudToken && await _e("/api/license/verify", "GET", null), !0; } async function I(e) { let t = e ? null : On(); if (t?.lease) return r.cloudLease = t.lease, r.cloudLeaseExp = Number(t.exp || 0), t.tier && (r.cloudTier = String(t.tier)), t.free_course_limit != null && (r.freeCourseLimit = Number(t.free_course_limit) || q), t.free_used_courses != null && (r.freeUsedCourses = Number(t.free_used_courses) || 0), t.pro_expires_at && (r.cloudProExpireAt = Number(t.pro_expires_at) || 0), t.can_exam != null ? r.canExam = !!t.can_exam : r.canExam = r.cloudTier === "pro", r.cloudReady = !0, D(), !0; let n = Be(); if (!n) throw new Error("\u672A\u767B\u5F55\uFF0C\u8BF7\u5148\u767B\u5F55\u5E73\u53F0"); let o = Pe(), a = await _e("/api/w2dzx/lease", "POST", { learning_user_id: n, name: r.userName || o?.stu_name || o?.name || "", userName: r.userName || o?.stu_name || o?.name || "" }), i = String(a.lease || ""), s = Number(a.exp || 0); if (!i) throw new Error("\u5F00\u901A\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"); if (r.cloudLease = i, r.cloudLeaseExp = s, r.cloudTier = String(a.tier || "free"), r.freeCourseLimit = Number( a.free_chapter_limit != null ? a.free_chapter_limit : a.free_course_limit != null ? a.free_course_limit : q ) || q, r.freeUsedCourses = Number( a.free_used_chapters != null ? a.free_used_chapters : a.free_used_courses != null ? a.free_used_courses : 0 ) || 0, r.cloudProExpireAt = Number(a.pro_expires_at || 0) || 0, r.canExam = a.can_exam === !0 || r.cloudTier === "pro", a.proBuyUrl) { let l = String(a.proBuyUrl).trim(); l && (r.proBuyUrl = l); } return ze(i, s, { tier: r.cloudTier, free_course_limit: r.freeCourseLimit, free_used_courses: r.freeUsedCourses, pro_expires_at: r.cloudProExpireAt, can_exam: r.canExam }), r.cloudReady = !0, D(), !0; } async function Vt(e) { await I(!1); let t = String( e?.id || e?.videoId || e?.courseId || e?.rawId || "" ).trim(), n = await _e("/api/w2dzx/chapter/consume", "POST", { lease: r.cloudLease, chapter_id: t, video_id: t, course_id: String(e?.courseId || e?.rawId || ""), chapter_name: String( e?.videoName || e?.name || e?.title || "" ) }); return n.tier && (r.cloudTier = String(n.tier)), (n.free_used_chapters != null || n.free_used_courses != null) && (r.freeUsedCourses = Number(n.free_used_chapters ?? n.free_used_courses) || 0), (n.free_chapter_limit != null || n.free_course_limit != null) && (r.freeCourseLimit = Number(n.free_chapter_limit ?? n.free_course_limit) || r.freeCourseLimit), n.can_exam != null && (r.canExam = !!n.can_exam), ze(r.cloudLease, r.cloudLeaseExp, { tier: r.cloudTier, free_course_limit: r.freeCourseLimit, free_used_courses: r.freeUsedCourses, pro_expires_at: r.cloudProExpireAt, can_exam: r.canExam }), D(), n; } async function Kt(e) { let t = Math.max(1, Number(e?.tiktok_time) || r.defaultTicktok || 30); if (await I(!1), !r.cloudLease) throw new Error("\u672A\u83B7\u5F97\u4E91\u7AEF\u6388\u6743\uFF0C\u65E0\u6CD5\u5B66\u4E60"); let n = await _e("/api/w2dzx/study/plan", "POST", { lease: r.cloudLease, pace: "efficiency", tiktok_time: t, video_id: String(e?.video_id || e?.id || ""), course_id: String(e?.course_id || "") }), o = n.plan || {}, a = Number(o.interval_sec), i = Number(o.times), s = Number(o.delta_sec); if (!Number.isFinite(a) || a < 1 || !Number.isFinite(i) || i < 1) throw new Error("\u4E91\u7AEF\u672A\u4E0B\u53D1\u6709\u6548\u5B66\u4E60\u53C2\u6570"); return n.tier && (r.cloudTier = String(n.tier)), n.can_exam != null && (r.canExam = !!n.can_exam), n.free_used_chapters != null && (r.freeUsedCourses = Number(n.free_used_chapters) || 0), n.free_chapter_limit != null && (r.freeCourseLimit = Number(n.free_chapter_limit) || r.freeCourseLimit), D(), { intervalSec: a, times: i, deltaSec: Number.isFinite(s) && s > 0 ? s : t, label: String(o.label || "cloud") }; } async function Ht() { try { let e = await Bt("/api/w2dzx/panel-notice", "GET", null); if (e.status === 200 && e.text) { r.remotePanelNotice = String(e.text).trim(); let t = g("nmg-panel-notice-text"); t && r.remotePanelNotice && (t.textContent = r.remotePanelNotice); } } catch { } } async function Jt() { try { let e = await _e("/api/w2dzx/client-config", "GET", null); fe(e.aesKey, e.aesIv), Rt(e), e.cloudApiBase && (r.cloudApiBase = String(e.cloudApiBase).replace(/\/+$/, "")); let t = e.freeChapterLimit ?? e.freeCourseLimit; t != null && (r.freeCourseLimit = Number(t) || q), e.proBuyUrl && (r.proBuyUrl = String(e.proBuyUrl).trim() || H), Dn({ aesKey: e.aesKey, aesIv: e.aesIv, cloudApiBase: r.cloudApiBase, freeChapterLimit: r.freeCourseLimit, freeCourseLimit: r.freeCourseLimit, freeCanExam: r.freeCanExam, proBuyUrl: r.proBuyUrl, activationTtlDays: r.activationTtlDays, videoDonePct: r.videoDonePct, courseDonePct: r.courseDonePct, courseCreditRatio: r.courseCreditRatio, progressLogIntervalMs: r.progressLogIntervalMs, defaultTicktok: r.defaultTicktok }); } catch { } } function D() { let e = r.activationTtlDays || 30, t = r.cloudTier === "pro" ? r.cloudProExpireAt ? `\u4E13\u4E1A\u7248\uFF08\u81F3 ${new Date(r.cloudProExpireAt * 1e3).toLocaleDateString()}\uFF09` : `\u4E13\u4E1A\u7248\uFF08\u6FC0\u6D3B\u540E${e}\u5929\uFF09` : r.cloudTier === "unknown" ? "\u52A0\u8F7D\u4E2D\u2026" : `\u514D\u8D39\u7248\uFF08\u5DF2\u7528 ${r.freeUsedCourses}/${r.freeCourseLimit} \u4E2A\u7AE0\u8282\u8BFE\u65F6${r.canExam || r.freeCanExam ? "" : " \xB7 \u4E0D\u542B\u8003\u8BD5"}\uFF09`, n = g("nmg-cloud-tier"); n && (n.textContent = t); let o = g("nmg-pro-buy"); o && (o.href = Ve()); let a = g("nmg-pro-banner"); a && (a.style.display = Fn() ? "none" : ""), Ot(); } var Yt = () => { }; function oe() { let e = document.getElementById("w2dzx-player-frame"); e && e.remove(); } function Rn(e) { oe(); let t = document.createElement("iframe"); return t.id = "w2dzx-player-frame", t.src = e, t.setAttribute("allow", "autoplay; encrypted-media; fullscreen"), t.style.cssText = "position:fixed;left:-9999px;top:0;width:360px;height:240px;opacity:0;pointer-events:none;border:0;z-index:-1;", document.body.appendChild(t), t; } function Wt(e, t) { try { let n = e.contentDocument; if (!n) return !1; let o = n.querySelector("video"); return o ? (o.muted = !0, o.playbackRate = t, o.paused && o.play().catch(() => { }), !0) : !1; } catch { return !1; } } async function qn(e, t) { let n = Date.now() + (t || 9e4); for (; Date.now() < n && !r.stopFlag; ) { if (Wt(e, 1)) return !0; await j(800); } return !1; } async function Bn(e, t) { let n = t.find((o) => o.studyStatus !== "\u5DF2\u5B8C\u6210" && (parseFloat(o.progressPercent) || 0) < (r.videoDonePct || 99.99)) || t[0]; if (!n) return 1; try { let o = await Ae(n.id, e.planId, me(e)); return Number(o?.con_video_speed_open) === 1 ? 2 : 1; } catch { return 1; } } function Gn(e) { try { let t = e.contentDocument; if (!t) return !1; let n = t.querySelectorAll( ".chapter .children li, .chapter li, [class*='video'] li, .mlItem-chapter li" ); for (let o of n) { let a = (o.textContent || "").trim(); if (a && !/已完成/.test(a) && (/未开始|学习中/.test(a) || o.querySelector(".progress"))) return o.click(), !0; } } catch { } return !1; } async function Qt(e) { let t = me(e), n = ge(e), o = await Bn(e, n); r.currentCourse = e.name || e.title || "", r.currentChapter = "\u64AD\u653E\u5668\u6258\u7BA1", r.task = `${C(r.currentCourse, 14)} \xB7 \u539F\u751F\u64AD\u653E`, Yt(), p( `\u64AD\u653E\u5668\u6258\u7BA1 \xB7 ${o === 2 ? "2\u500D\u901F" : "1\u500D\u901F"} \xB7 ${C(r.currentCourse, 18)}`, "info" ); let a = Rn(t); try { if (!await qn(a, 9e4)) throw new Error("\u64AD\u653E\u9875\u52A0\u8F7D\u8D85\u65F6\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u62A5\u540D\u8BE5\u8BA1\u5212\u8BFE\u7A0B"); let s = 0; for (; !r.stopFlag; ) { Wt(a, o); let l = await W(e), f = M(l), d = S(l), m = Date.now(); if ((d || !s || m - s >= (r.progressLogIntervalMs || 12e4)) && (s = m, p(`\u8FDB\u5EA6 ${f.toFixed(0)}% \xB7 ${C(e.name || e.title || "", 18)}`, "progress")), r.currentChapter = `\u64AD\u653E\u5668 ${f.toFixed(0)}%`, Yt(), d) { p(`\u8BFE\u7A0B\u5B8C\u6210 \xB7 ${e.name || e.title}`, "info"); return; } Gn(a), await j(12e3); } } finally { oe(); } } var ae = () => { }; function Zt(e) { e && typeof e.upd == "function" && (ae = e.upd); } function He() { oe(); } function Vn(e) { return me(e); } function Kn(e, t) { if (Te(e)) return !0; let n = t || e.durationSec || 0, o = parseFloat(e._progressSec) || 0; return n > 0 && o >= n; } function Hn(e, t, n) { return n || t > 0 && e >= t ? 100 : t > 0 ? Math.round(e / t * 1e4) / 100 : 0; } function Jn(e) { let t = ge(e); return r.onlyIncomplete ? t.filter((n) => !Kn(n)) : t; } function Yn(e) { return y(String(e)); } async function Wn(e, t, n, o, a) { if (h === "pl") { let s = typeof n == "number" && Number.isFinite(n) ? String(Math.round(n * 1e6) / 1e6) : String(n), l = await _( "/api/student.time/add.html", { courseware_id: y(String(e)), progress: s, times: "1" }, { referer: a } ), f = l && l.data || {}; return { ...typeof f == "object" && f ? f : {}, code: l && l.code, msg: l && l.msg }; } let i = await _( "/api/v2.student_time/add", { video_id: y(String(e)), plan_id: Yn(t), progress: String(n), times: String(o ?? 1) }, { referer: a } ); return i && i.data || {}; } function Xt(e) { let t = String(e?.message || e || ""); return e?.code === -2 || /同时观看多门课程|关闭其他播放页/.test(t); } function Qn(e) { let t = String(e?.message || e || ""); return e?.code === -1 || /学时记录异常|刷新当前页面/.test(t); } async function Ke(e, t, n, o, a) { try { return await Wn(e, t, n, o, a); } catch (i) { if (i.code === -2) { let s = new Error("\u4E0D\u5141\u8BB8\u540C\u65F6\u89C2\u770B\u591A\u95E8\u8BFE\u7A0B\uFF0C\u8BF7\u5173\u95ED\u5176\u4ED6\u64AD\u653E\u9875"); throw s.code = -2, s; } if (i.code === -3 && i.data && i.data.progress != null) return { progress: i.data.progress, reset: !0, msg: i.message }; throw i; } } async function Xn(e, t) { let n = e.planId, o = Vn(e), a = async () => await Ae(t.id, n, o), i = await a(); if (h === "pl") { let N = Number(i && i.videoDuration) || Number(t.durationSec || t.videoDuration) || 0, v = Number(i && i.progress) || Number(t._progressSec) || 0, O = Number.isFinite(v) && v > 0 ? N > 0 ? Math.min(v, N) : v : 0; i = { ...i || {}, videoDuration: N, progress: O, con_video_speed_open: 1, video_id: String(t.id || "") }; } i && (t._speedOpen = Number(i.con_video_speed_open) === 1); let s = Number(i && i.videoDuration) || t.durationSec || parseFloat(t.videoDuration) || 0; if (s <= 0) throw new Error(`\u89C6\u9891 ${t.videoName || t.id} \u65E0\u6709\u6548\u65F6\u957F\uFF08\u8BF7\u66F4\u65B0\u811A\u672C\u540E\u91CD\u8BD5\uFF09`); await Vt({ id: t.id, videoId: t.id, courseId: e.courseId || e.rawId, videoName: t.videoName || t.id }); let l = await Kt(i), f = Math.max(1, Number(l.intervalSec) || 1), d = Math.max(1, Number(l.times) || 1), m = Math.max(1, Number(l.deltaSec) || r.defaultTicktok || 30); h === "pl" && (d = 1); let u = f * 1e3, c = Number(i && i.progress); (!Number.isFinite(c) || c < 0) && (c = parseFloat(t.progressPercent) / 100 * s || 0), c = Math.max(0, Math.min(c, s)), r.currentCourse = e.name || e.title || "", r.currentChapter = t.videoName || t.chapterName || "", r.activeVideoId = String(t.id || ""), r.task = `${C(r.currentCourse, 14)} \xB7 ${C(t.videoName || "", 12)}`, re(t.id, c, s), ae(); let b = Math.max(1, Math.round(s / 60)), x = Math.max(0, Math.round(c / 60)); p( `\u5F00\u59CB\u5B66\u4E60 \xB7 ${t.videoName || t.id}\uFF08\u7247\u957F\u7EA6 ${b} \u5206\u949F${x > 0 ? ` \xB7 \u5DF2\u64AD\u7EA6 ${x} \u5206\u949F` : ""}\uFF09`, "progress" ); let $ = 0, k = !1, De = 0, nt = !1, B = c >= s - 1 ? Date.now() : Date.now() + u; for (; c < s && !r.stopFlag; ) { let N = Date.now(), v = Math.min(1e3, Math.max(50, B - N)); if (await j(v), r.stopFlag) break; if (Date.now() < B) continue; let O = Math.min(m, s - c); if (O <= 0) break; let Oe = s - c <= Math.max(m, 2) ? s : Math.min(h === "pl" ? c + O : Math.ceil(c + O), s), G; try { G = await Ke(t.id, n, Oe, d, o); } catch (E) { let T = String(E?.message || E || ""); p(`\u5B66\u65F6\u4E0A\u62A5\u672A\u6210\u529F\uFF1A${T.slice(0, 80)}\uFF0C\u5C06\u91CD\u8BD5`, "warn"); try { oe(); } catch { } try { if (i = await a(), h === "pl" && i) { let U = Number(i.videoDuration) || s, Ue = Number(i.progress); Number.isFinite(Ue) && Ue >= 0 && (c = Math.min(Ue, U), re(t.id, c, U), ae()); } else { let U = Number(i && i.progress); Number.isFinite(U) && U >= 0 && (c = Math.min(U, s), re(t.id, c, s), ae()); } } catch { } let gn = Xt(E) ? Math.max(u, 2e3) : u; B = Date.now() + gn; continue; } if (B += u, B < Date.now() - u && (B = Date.now() + u), G.reset) c = Number(G.progress) || c, p(`\u8FDB\u5EA6\u88AB\u540C\u6B65\u4E3A ${Y(c)}\uFF0C\u4FDD\u6301\u539F\u901F\u5EA6\u7EE7\u7EED`, "info"), B = Date.now() + u; else { let E = Number(G.progress); Number.isFinite(E) && E >= 0 ? E + 0.5 < c ? (c = E, p(`\u8FDB\u5EA6\u88AB\u540C\u6B65\u4E3A ${Y(c)}\uFF0C\u4FDD\u6301\u539F\u901F\u5EA6\u7EE7\u7EED`, "info")) : c = Math.max(Oe, E) : c = Oe; } if (h === "pl" && (De += 1, De === 1 && G.msg && p(`\u5E73\u53F0\u5DF2\u786E\u8BA4\u5B66\u65F6 \xB7 ${String(G.msg).slice(0, 40)}`, "info"), De % 5 === 0)) try { let E = await a(), T = Number(E && E.progress); Number.isFinite(T) && T >= 0 && (T + 5 < c ? (nt || (nt = !0, p( `\u5E73\u53F0\u8FDB\u5EA6\u843D\u540E\uFF08\u5E73\u53F0 ${Y(T)} / \u672C\u5730 ${Y(c)}\uFF09\uFF0C\u5DF2\u6309\u5E73\u53F0\u4E3A\u51C6\u7EE7\u7EED`, "warn" )), c = Math.min(T, s)) : T > c && (c = Math.min(T, s))); } catch { } let rt = Number(G.is_finished) === 1; k = rt || c >= s; let ot = Hn(c, s, k); re(t.id, c, s, { finished: rt || c >= s }), r.currentChapter = `${t.videoName || t.id} ${ot}%`, ae(); let at = Date.now(); if ((k || !$ || at - $ >= (r.progressLogIntervalMs || 12e4)) && ($ = at, p(`\u8FDB\u5EA6 ${Y(c)}/${Y(s)} ${ot}%`, "progress")), k) break; } if (!r.stopFlag && !k) try { let N = await Ke(t.id, n, s, d, o); k = Number(N.is_finished) === 1; let v = Number(N.progress); c = Number.isFinite(v) && v >= 0 ? Math.min(v, s) : s, !k && c >= s && (k = !0); } catch (N) { if (Xt(N) || Qn(N)) try { oe(), i = await a(); let v = Number(i && i.progress); Number.isFinite(v) && v >= 0 && (c = Math.min(v, s)), await j(1500); let O = await Ke(t.id, n, s, d, o); k = Number(O.is_finished) === 1 || c >= s; let ve = Number(O.progress); Number.isFinite(ve) && ve >= 0 && (c = Math.min(ve, s)), !k && c >= s && (k = !0); } catch { p(`\u7247\u5C3E\u4E0A\u62A5\u672A\u6210\u529F \xB7 ${t.videoName || t.id}\uFF0C\u4E0B\u6B21\u5C06\u7EE7\u7EED`, "warn"); } else p(`\u7247\u5C3E\u4E0A\u62A5\u672A\u6210\u529F \xB7 ${t.videoName || t.id}\uFF0C\u4E0B\u6B21\u5C06\u7EE7\u7EED`, "warn"); } return k && (re(t.id, s, s, { finished: !0 }), ae()), k && !r.stopFlag ? p(`\u89C6\u9891\u5B8C\u6210 \xB7 ${t.videoName || t.id}`, "info") : r.stopFlag ? p(`\u5DF2\u6682\u505C \xB7 ${t.videoName || t.id}`, "info") : k || p(`\u672A\u8FBE\u5B8C\u6210 \xB7 ${t.videoName || t.id}\uFF0C\u5C06\u7EE7\u7EED\u8865\u5B66`, "warn"), k; } async function en(e) { let t = await W(e); if (S(t)) { p(`\u5B66\u65F6\u5DF2\u6EE1\uFF0C\u8DF3\u8FC7 \xB7 ${t.name || t.title}`, "info"); return; } if (r.pace === V.player) { await Qt(t); return; } r.activeCourse = t; let n = 0; for (; !r.stopFlag; ) { if (t = await W(t), r.activeCourse = t, S(t)) { n === 0 ? p(`\u5B66\u65F6\u5DF2\u6EE1\uFF0C\u8DF3\u8FC7 \xB7 ${t.name || t.title}`, "info") : p(`\u5B66\u65F6\u5DF2\u6EE1\uFF0C\u505C\u6B62\u672C\u8BFE\u5269\u4F59\u7AE0\u8282 \xB7 ${t.name || t.title}`, "info"); break; } let o = Jn(t)[0]; if (!o) { p(`\u6682\u65E0\u5F85\u5B66\u8BFE\u4EF6 \xB7 ${t.name || t.title}`, "info"); break; } let a = await Xn(t, o); if (n += 1, !a && !r.stopFlag) break; } t = await W(t), S(t) && p(`\u8BFE\u7A0B\u5B66\u65F6\u8FBE\u6807 \xB7 ${t.name || t.title}`, "info"); } var Q = () => { }; function nn(e) { Q = typeof e == "function" ? e : () => { }; } function tn(e, t) { return e.serialNumber || e.label || e.option || e.name || String.fromCharCode(65 + t); } function Zn(e) { let t = e.options || e.option || e.answers || []; return Array.isArray(t) ? t.map((n, o) => ({ label: tn(n, o), value: n.value ?? tn(n, o) })) : []; } function ie(e) { return e == null ? "" : String(e).trim().replace(/\s+/g, "").replace(/,/g, ",").toUpperCase(); } function er() { return Object.keys(r.examBank || {}).length; } function we(e, t, n) { let o = ie(t); if (!e || !o) return !1; let a = `plan:${e}`, i = r.examBank[a]; return i && ie(i.answer) === o ? !1 : (r.examBank[a] = { type: n ?? (i && i.type), answer: o }, !0); } function tr(e) { let t = 0; for (let n of e || []) { if (!n) continue; let o = n.id || n.question_id || n.que_id, a = n.answer ?? n.correct_answer; we(o, a, n.questionType ?? n.question_type) && (t += 1); } return t && xe(), t; } function nr(e) { let t = 0, n = e && e.exam_results || []; for (let o of n) { let a = o.question_id || o.id || o.que_id, i = o.correct_answer ?? o.answer; we(a, i, o.question_type ?? o.questionType) && (t += 1); } return t && xe(), t; } function rr(e) { let t = e.id, n = r.examBank[`plan:${t}`] || r.examBank[t]; if (n && n.answer) return ie(n.answer); let o = Zn(e); return o.length && o[0].label || "A"; } function or(e) { let t = 0; for (let n of e || []) { if (!n || !n.id) continue; let o = r.examBank[`plan:${n.id}`] || r.examBank[n.id]; o && o.answer && (t += 1); } return t; } function ar(e) { e.sig_passtext = "yes", r.queueExamDone = Math.min((r.queueExamDone || 0) + 1, r.queueExamTotal || 1), Q(); } async function Je(e) { try { await be(); let t = (r.studyPlans || []).find( (n) => String(n.stp_id) === String(e.stp_id) ); t && (e.sig_passtext = t.sig_passtext, e.is_can_exam = t.is_can_exam, e.sig_remain_num = t.sig_remain_num); } catch { } return e.sig_passtext === "yes"; } function rn(e, t, n) { return e.pass === 0 || e.pass === !1 || e.pass === "0" ? !1 : !!(e.pass === 1 || e.pass === !0 || e.pass === "1" || e.isPass === !0 || e.is_pass === !0 || String(e.pass_text || "").includes("\u901A\u8FC7") || String(e.exam_status || e.status || "").includes("\u901A\u8FC7") || Number.isFinite(Number(t)) && Number(t) >= n); } async function ir(e, t) { let n = lt, o = 0; r.task = `\u7EC3\u4E60\u56E4\u9898 \xB7 ${C(t, 14)}`, r.currentChapter = "\u6A21\u62DF\u7EC3\u4E60", Q(); for (let a = 1; a <= n && !r.stopFlag; a++) { try { let i = await _("/api/v2.Order/getMyStudyPlanAnalogExam", { sig_id: y(String(e)) }), s = (i && i.data || {}).questions || [], l = tr(s); o += l; } catch { } a < n && !r.stopFlag && await j(dt); } return { added: o, size: er() }; } async function sr(e) { try { await _("/api/v2.Order/getMyStudyPlanExamBefore", { sig_id: y(String(e)) }); } catch { } let t = await _("/api/v2.Order/getMyStudyPlanExam", { sig_id: y(String(e)) }), n = t && t.data || {}, o = (n.questions || []).filter((c) => c && c.id); if (!o.length) { let c = new Error("\u8BD5\u5377\u65E0\u9898\u76EE"); throw c.code = "empty_paper", c; } let a = n.stex_exam_id; if (!a) { let c = new Error("\u53D6\u5377\u5931\u8D25"); throw c.code = "no_exam_id", c; } let i = or(o); p(`\u6B63\u5F0F\u53D6\u5377 \xB7 ${o.length} \u9898 \xB7 \u9898\u5E93\u547D\u4E2D ${i}`, "info"); let s = {}; for (let c of o) { if (r.stopFlag) break; s[c.id] = rr(c), await j(80); } let l = { stex_exam_id: String(a) }; Object.entries(s).forEach(([c, b]) => { l[`exam_answers[${c}]`] = b; }); let f = await _("/api/v2.Order/submitMyStudyPlanExam", l), d = f && f.data || {}, m = d.totalScore ?? d.score ?? (d.examData && d.examData.totalScore) ?? 0, u = nr(d); return { result: d, score: Number(m) || 0, questions: o.length, known: i, harvested: u }; } async function on(e) { let t = e.stp_name || e.planName || `\u8BA1\u5212${e.stp_id}`, n = e.sig_id || e.sigId; if (!n) return { ok: !0, skipped: !0 }; if (e.sig_passtext === "yes") return p(`\u8003\u8BD5\u5B8C\u6210\u901A\u8FC7 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }; if (e.is_can_exam !== 1) return await Je(e) ? (p(`\u8003\u8BD5\u5B8C\u6210\u901A\u8FC7 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }) : { ok: !0, skipped: !0 }; let o = 60; try { let s = await _("/api/v2.Order/getMyStudyPlanExamRule", { sig_id: y(String(n)) }); o = parseFloat(s.data && s.data.exac_pass_score || 60) || 60; } catch { } let a = Math.min( K, Number(e.sig_remain_num || e.sig_examinations || K) || K ); r.task = `\u8BA1\u5212\u8003\u8BD5 \xB7 ${C(t, 16)}`, r.currentCourse = t, r.currentChapter = "\u7ED3\u4E1A\u8003\u8BD5", Q(), p(`\u5F00\u59CB\u8BA1\u5212\u8003\u8BD5 \xB7 ${t}`, "info"), r.stopFlag || await ir(n, t); let i = !1; for (let s = 1; s <= a && !r.stopFlag; s++) { r.task = `\u6B63\u5F0F\u8003\u8BD5 \xB7 \u7B2C${s}\u6B21`, r.currentChapter = `\u6B63\u5F0F\u8003\u8BD5(${s}/${a})`, Q(); try { let { result: l, score: f } = await sr(n); if (rn(l, f, o)) { i = !0; break; } } catch (l) { if (l.code === "empty_paper" || l.code === "no_exam_id" || /试卷无题目|取卷失败/.test(l.message || "")) break; throw l; } if (await Je(e)) { i = !0; break; } await j(800); } return i || (i = await Je(e)), i || e.sig_passtext === "yes" ? (ar(e), p(`\u8003\u8BD5\u5B8C\u6210\u901A\u8FC7 \xB7 ${t}`, "info"), { ok: !0 }) : { ok: !1, msg: "\u8003\u8BD5\u672A\u901A\u8FC7" }; } function Ye(e) { if (!e) return ""; let t = e.que_answer ?? e.answer ?? e.correct_answer; if (t == null || t === "") return ""; try { let n = Ne(String(t)); if (n) return ie(n); } catch { } return ie(t); } function an(e) { let t = 0; for (let n of e || []) { if (!n) continue; let o = n.que_id || n.id || n.question_id, a = Ye(n); we(o, a, n.type_text || n.questionType) && (t += 1); } return t && xe(), t; } function cr(e) { let t = e?.que_id || e?.id, n = r.examBank[`plan:${t}`] || r.examBank[t]; if (n && n.answer) return ie(n.answer); let o = Ye(e); return o || "A"; } async function lr() { let e = await _("/api/student.Info/waitExam.html", { page: "1", limit: "50" }), t = e && e.data || {}, n = t.list && t.list.data || t.data || []; return { list: Array.isArray(n) ? n : [], info: t.info || {} }; } async function dr(e, t) { let n = 0, o = t || e; for (let a = 0; a < 3 && !r.stopFlag; a++) { try { let i = await _("/api/student.Info/mockExam.html", { course_id: y(String(o)) }), s = Array.isArray(i?.data) ? i.data : i?.data?.data || []; n += an(s); } catch { } await j(600); } return n; } async function ur(e) { try { await _("/api/student.Info/paperdataBefore.html", { course_id: y(String(e)) }); } catch { } let t = await _("/api/student.Info/paperdata.html", { course_id: y(String(e)) }), n = t && t.data || {}, a = (Array.isArray(n.data) ? n.data : Array.isArray(n) ? n : []).filter((u) => u && (u.que_id || u.id)); if (!a.length) { let u = new Error("\u8BD5\u5377\u65E0\u9898\u76EE"); throw u.code = "empty_paper", u; } an(a); let i = 0, s = { course_id: y(String(e)) }; for (let u of a) { if (r.stopFlag) break; let c = u.que_id || u.id, b = cr(u); (Ye(u) || r.examBank[`plan:${c}`]) && (i += 1), s[`answerdb[${c}]`] = b, await j(50); } p(`\u6B63\u5F0F\u53D6\u5377 \xB7 ${a.length} \u9898 \xB7 \u53EF\u4F5C\u7B54 ${i}`, "info"); let l = await _("/api/student.Info/submitExam.html", s), f = l && l.data || {}, d = f.examData || f, m = d.totalScore ?? d.score ?? d.stex_score ?? f.score ?? 0; try { let u = f.records || []; for (let c of u) { let b = c.que_id || c.question_id, x = c.que_answer || c.correct_answer; if (b && x) try { we(b, Ne(String(x)) || x); } catch { we(b, x); } } xe(); } catch { } return { result: f, score: Number(m) || 0, questions: a.length, known: i }; } async function sn(e) { let t = e.name || e.title || e.courseId, n = e.courseId || e.rawId; if (!n) return { ok: !0, skipped: !0 }; if (String(e.sig_passtext || "").toLowerCase() === "yes") return p(`\u8003\u8BD5\u5DF2\u901A\u8FC7 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }; let o = null, a = {}; try { let d = await lr(); a = d.info || {}, o = (d.list || []).find( (m) => String(m.cou_id) === String(n) ); } catch (d) { p(`\u5F85\u8003\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF1A${d.message || d}`, "warn"); } if (a && a.exac_isexam === 0) return p(`\u5E73\u53F0\u672A\u5F00\u653E\u8003\u8BD5 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }; if (o) { if (String(o.sig_passtext || "").toLowerCase() === "yes") return p(`\u8003\u8BD5\u5DF2\u901A\u8FC7 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }; if (Number(o.is_can) !== 1) return p( `\u6682\u4E0D\u53EF\u8003 \xB7 ${t}${o.msg ? `\uFF1A${o.msg}` : ""}`, "info" ), { ok: !0, skipped: !0 }; } else if (!S(e) && Number(e.is_kaishi_code) !== 2) return p(`\u5B66\u65F6\u672A\u6EE1\uFF0C\u6682\u4E0D\u8003\u8BD5 \xB7 ${t}`, "info"), { ok: !0, skipped: !0 }; r.task = `\u8BFE\u7A0B\u8003\u8BD5 \xB7 ${C(t, 16)}`, r.currentCourse = t, r.currentChapter = "\u7ED3\u4E1A\u8003\u8BD5", Q(), p(`\u5F00\u59CB\u8BFE\u7A0B\u8003\u8BD5 \xB7 ${t}`, "info"); let i = Number(o?.shengyu ?? o?.sig_examinations ?? K) || K, s = Math.min(K, Math.max(1, i)); try { await dr(n, o?.sig_course_id); } catch { } let l = !1, f = 0; for (let d = 1; d <= s && !r.stopFlag; d++) { r.task = `\u6B63\u5F0F\u8003\u8BD5 \xB7 \u7B2C${d}\u6B21`, r.currentChapter = `\u6B63\u5F0F\u8003\u8BD5(${d}/${s})`, Q(); try { let { score: m, result: u } = await ur(n); if (f = m, rn(u, m, 60) || m >= 60) { l = !0; break; } p(`\u8003\u8BD5\u5F97\u5206 ${m}\uFF0C\u672A\u8FBE\u6807\u5C06\u91CD\u8BD5`, "warn"); } catch (m) { if (m.code === "empty_paper" || /试卷无题目/.test(m.message || "")) { p(`\u53D6\u5377\u5931\u8D25\uFF1A${m.message || m}`, "error"); break; } p(`\u8003\u8BD5\u5F02\u5E38\uFF1A${m.message || m}`, "error"); break; } await j(1e3); } return l ? (e.sig_passtext = "yes", p(`\u8003\u8BD5\u5B8C\u6210\u901A\u8FC7 \xB7 ${t}\uFF08${f}\u5206\uFF09`, "info"), { ok: !0 }) : { ok: !1, msg: `\u8003\u8BD5\u672A\u901A\u8FC7\uFF08\u6700\u8FD1 ${f} \u5206\uFF09` }; } var se = () => { }, We = () => { }, ln = () => { }, Qe = () => { }; function dn(e) { e && (e.upd && (se = e.upd), e.hint && (We = e.hint), e.clear && (ln = e.clear), e.lists && (Qe = e.lists)); } async function cn(e) { if (r.autoExam) { if (await I(!1), r.cloudTier !== "pro" && !r.canExam) { p("\u8003\u8BD5\u9700\u4E13\u4E1A\u7248\uFF08\u514D\u8D39\u7248\u4E0D\u542B\u81EA\u52A8\u8003\u8BD5\uFF09\uFF0C\u5DF2\u8DF3\u8FC7", "info"); return; } if (h === "pl") { let t = L().filter( (n) => S(n) || Number(n.is_kaishi_code) === 2 || String(n.sig_passtext || "").toLowerCase() === "yes" ); if (!t.length) { p("\u6682\u65E0\u8FBE\u5230\u8003\u8BD5\u6761\u4EF6\u7684\u8BFE\u7A0B\uFF08\u9700\u5148\u5B66\u6EE1\u5B66\u65F6\uFF09", "info"); return; } for (let n of t) { if (r.stopFlag) break; try { let o = await sn(n); o && o.ok === !1 && o.msg && p(`\u8BFE\u7A0B\u8003\u8BD5\u672A\u901A\u8FC7 \xB7 ${n.name || n.title}\uFF1A${o.msg}`, "error"); } catch (o) { p(`\u8BFE\u7A0B\u8003\u8BD5\u5931\u8D25: ${o.message || o}`, "error"); } } return; } if (!(!e || !e.size)) { await be(); for (let t of r.studyPlans || []) { if (r.stopFlag) break; if (e.has(String(t.stp_id))) try { let n = await on(t); n && n.ok === !1 && n.msg && p(`\u8BA1\u5212\u8003\u8BD5\u672A\u901A\u8FC7 \xB7 ${t.stp_name || t.stp_id}`, "error"); } catch (n) { p(`\u8BA1\u5212\u8003\u8BD5\u5931\u8D25: ${n.message || n}`, "error"); } } } } } async function Xe() { if (r.running) return; r.running = !0, r.stopFlag = !1; let e = /* @__PURE__ */ new Set(); try { p("\u5237\u65B0\u5B66\u4E60\u8BA1\u5212\u4E0E\u8BFE\u7A0B\u2026", "info"), await he(), Qe(); let t = L().filter((n) => r.onlyIncomplete ? !S(n) : !0); if (!t.length) { if (r.autoExam) { if (p("\u52FE\u9009\u8BFE\u7A0B\u5B66\u65F6\u5DF2\u6EE1\uFF0C\u8F6C\u5165\u8BA1\u5212\u8003\u8BD5", "info"), L().forEach( (n) => e.add(String(n.planId)) ), !e.size) for (let n of r.studyPlans || []) n.sig_passtext !== "yes" && n.is_can_exam === 1 && e.add(String(n.stp_id)); await cn(e); } else p("\u52FE\u9009\u8BFE\u7A0B\u5747\u5DF2\u5B66\u5B8C\uFF0C\u65E0\u9700\u7EE7\u7EED", "info"); return; } p( `\u5F00\u59CB\u987A\u5E8F\u5B66\u4E60 \xB7 ${t.length} \u95E8\u8BFE${r.autoExam ? "\uFF08\u542B\u8BA1\u5212\u8003\u8BD5\uFF09" : ""}`, "info" ); for (let n of t) { if (r.stopFlag) break; e.add(String(n.planId)); try { await I(!1); } catch (o) { p(`\u65E0\u6CD5\u7EE7\u7EED: ${o.message || o}`, "error"); break; } await en(n); } r.stopFlag || (await cn(e), p("\u5168\u90E8\u4EFB\u52A1\u5B8C\u6210", "info"), await he(), Qe()); } catch (t) { p(`\u9519\u8BEF: ${t.message || t}`, "error"); } finally { r.running = !1, r.enabled = !1, GM_setValue(w.enabled, !1), He(), r.stopFlag || (r.task = "", r.currentCourse = "", r.currentChapter = "", r.activeCourse = null), se(); } } function un() { r.stopFlag = !0, r.enabled = !1, GM_setValue(w.enabled, !1), He(), r.task = "\u5DF2\u505C\u6B62", se(), p("\u81EA\u52A8\u770B\u8BFE\u5DF2\u6682\u505C", "info"); } function pn() { if (r.running || r.enabled) return; r.pace = V.efficiency, GM_setValue(w.pace, r.pace); let e = L(); if (r.selectMode === "none" || !e.length) { F().length && r.selectMode === "none" ? We("\u8BFE\u7A0B\u5DF2\u5B66\u5B8C\uFF0C\u8BF7\u70B9\u300C\u4E00\u952E\u52FE\u9009\u300D\u540E\u518D\u5F00\u59CB\u8003\u8BD5") : We("\u8BF7\u5148\u52FE\u9009\u81F3\u5C11\u4E00\u95E8\u8BFE\u7A0B"), se(); return; } let t = e.some((n) => !S(n)); ln(), I(!1).then(() => { r.enabled = !0, r.stopFlag = !1, GM_setValue(w.enabled, !0), se(), p( t ? "\u81EA\u52A8\u770B\u8BFE\u5DF2\u5F00\u542F\uFF08\u6548\u7387\u6A21\u5F0F\uFF09" : "\u8BFE\u7A0B\u5DF2\u5B66\u5B8C\uFF0C\u5F00\u59CB\u81EA\u52A8\u8003\u8BD5", "info" ), Xe(); }).catch((n) => { p(`\u65E0\u6CD5\u5F00\u59CB: ${n.message || n}`, "error"), se(); }); } function Se() { J && (J.cloudTier = r.cloudTier, J.freeUsedCourses = r.freeUsedCourses, J.freeCourseLimit = r.freeCourseLimit, J.running = !!(r.running || r.enabled)); } function fn(e, t) { if (!(!e || !t || typeof t.createPinia != "function")) try { let { createPinia: n, defineStore: o } = t, a = o("nmg12371", { state: () => ({ cloudTier: r.cloudTier, freeUsedCourses: r.freeUsedCourses, freeCourseLimit: r.freeCourseLimit, running: !1 }) }), i = n(), s = e.createApp({ render: () => null }); s.use(i); let l = document.createElement("div"); l.style.display = "none", document.body.appendChild(l), s.mount(l), wt(a()), Se(); } catch { } } var mn = null, xn = null; function pr() { let e = g("nmg-start"), t = g("nmg-stop"); e && (e.disabled = !!r.enabled || !!r.running, e.classList.toggle("zjzx-btn-off", !!r.enabled || !!r.running)), t && (t.disabled = !r.enabled && !r.running, t.classList.toggle("zjzx-btn-off", !r.enabled && !r.running)); } function et(e) { r.panelHint = String(e || ""); let t = g("nmg-start-hint"); t && (r.panelHint ? (t.style.display = "", t.textContent = r.panelHint) : (t.style.display = "none", t.textContent = "")); } function Fe() { et(""); } function fr() { let e = L(), t = 0, n = 0, o = 0, a = 0; for (let i of e) t += 1, (S(i) || M(i) >= (r.courseDonePct || 99.5)) && (n += 1), i._plan && i._plan.sig_examinations && (o += 1, i._plan.sig_passtext === "yes" && (a += 1)); r.queueVideoTotal = t, r.queueVideoDone = n, r.queueExamTotal = r.autoExam ? o : 0, r.queueExamDone = r.autoExam ? a : 0; } function A() { fr(); let e = g("nmg-auto-status"); e && (r.running || r.enabled ? (e.textContent = r.running ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u5F00\u542F", e.style.background = "#dcfce7", e.style.borderColor = "#86efac", e.style.color = "#166534") : (e.textContent = "\u5DF2\u505C\u6B62", e.style.background = "#fff", e.style.borderColor = "#cbd5e1", e.style.color = "#334155")); let t = r.queueVideoDone, n = r.queueVideoTotal, o = n > 0 ? Math.round(t / n * 100) : 0, a = (m, u) => { let c = g(m); c && (c.textContent = u); }; a("nmg-queue-done", String(t)), a("nmg-queue-total", String(n)), a("nmg-queue-percent", `${o}%`), a( "nmg-queue-exam", r.autoExam ? `${r.queueExamDone} / ${r.queueExamTotal || "\u2014"}` : "\u2014" ); let i = g("nmg-queue-progress"); i && (i.style.width = `${o}%`), a("nmg-current-course", C(r.currentCourse || "\u65E0", 28)), a("nmg-current-chapter", C(r.currentChapter || "\u65E0", 28)), a("nmg-current-task", C(r.task || "\u70B9\u5F00\u59CB\u540E\u81EA\u52A8\u63D0\u4EA4", 36)); let s = g("nmg-current-course"), l = g("nmg-current-chapter"), f = g("nmg-current-task"); s && (s.title = r.currentCourse || ""), l && (l.title = r.currentChapter || ""), f && (f.title = r.task || ""); let d = g("nmg-queue-text"); if (d) { let u = L().length; r.selectMode === "none" ? d.textContent = "\u672A\u52FE\u9009\u4EFB\u4F55\u8BFE\u7A0B" : r.selectMode === "all" && r.learningCourses.length ? d.textContent = `\u5DF2\u9009\u5168\u90E8 ${u} \u95E8 \xB7 \u5B66\u65F6\u6EE1 ${t}/${n}${r.autoExam && r.queueExamTotal ? ` \xB7 \u8003\u8BD5 ${r.queueExamDone}/${r.queueExamTotal}` : r.autoExam ? " \xB7 \u81EA\u52A8\u8003\u8BD5" : ""}` : d.textContent = u ? `\u5DF2\u9009 ${u} \u95E8 \xB7 \u5B66\u65F6\u6EE1 ${t}/${n}${r.autoExam && r.queueExamTotal ? ` \xB7 \u8003\u8BD5 ${r.queueExamDone}/${r.queueExamTotal}` : r.autoExam ? " \xB7 \u81EA\u52A8\u8003\u8BD5" : ""}` : "\u672A\u52FE\u9009\u4EFB\u4F55\u8BFE\u7A0B"; } pr(), Se(); try { X(); } catch { } } function mr(e) { let t = g("nmg-auto-panel"); t && (t.querySelectorAll(".zjzx-tab-btn").forEach((n) => { n.classList.toggle("active", n.dataset.tab === e); }), t.querySelectorAll(".zjzx-pane").forEach((n) => { n.classList.toggle("active", n.dataset.pane === e); }), e === "chapters" && X()); } function Ze(e, t) { let n = e.querySelector("#nmg-btn-min"), o = e.querySelector("#nmg-btn-max"); e.classList.toggle("zjzx-panel-min", !!t), e.classList.toggle("zjzx-panel-max", !t), n && (n.style.display = t ? "none" : ""), o && (o.style.display = t ? "" : "none"); } function xr(e) { let t = e.querySelector("#nmg-panel-header"); if (!t) return; let n = !1, o = 0, a = 0, i = 0, s = 0; t.addEventListener("mousedown", (l) => { if (l.target?.closest("#nmg-panel-controls, .zjzx-panel-ctl")) return; n = !0, o = l.clientX, a = l.clientY; let f = e.getBoundingClientRect(); i = f.left, s = f.top, e.style.right = "auto", e.style.bottom = "auto", l.preventDefault(); }), document.addEventListener("mousemove", (l) => { if (!n) return; let f = Math.max( 0, Math.min(window.innerWidth - e.offsetWidth, i + (l.clientX - o)) ), d = Math.max( 0, Math.min(window.innerHeight - e.offsetHeight, s + (l.clientY - a)) ); e.style.left = `${f}px`, e.style.top = `${d}px`; }), document.addEventListener("mouseup", () => { if (!n) return; n = !1; let l = e.getBoundingClientRect(); ue(w.panelPos, { left: l.left, top: l.top }); }); } function gr(e) { let t = document.createElement("style"); t.textContent = ` :host{all:initial;} #nmg-auto-panel{position:fixed;right:20px;top:80px;z-index:999999;width:412px;display:flex;flex-direction:column;background:#f4f7fb;border:1px solid #dbe4f0;border-radius:16px;box-shadow:0 16px 40px rgba(15,23,42,.17);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;font-size:12px;color:#0f172a;overflow:hidden;transition:max-height .22s ease,box-shadow .22s ease;} #nmg-auto-panel.zjzx-panel-max{max-height:min(92vh,780px);} #nmg-auto-panel.zjzx-panel-min{max-height:none;box-shadow:0 10px 28px rgba(15,23,42,.14);} #nmg-auto-panel.zjzx-panel-min #nmg-panel-header{border-bottom:none;} #nmg-auto-panel.zjzx-panel-min #nmg-panel-body,#nmg-auto-panel.zjzx-panel-min #nmg-panel-footer,#nmg-auto-panel.zjzx-panel-min .zjzx-footer-extra{display:none !important;} #nmg-panel-header{flex:0 0 auto;padding:8px 11px;background:linear-gradient(180deg,#f8ecd5,#f4e8cf);border-bottom:1px solid #e5dbc6;display:flex;justify-content:space-between;align-items:center;cursor:move;user-select:none;} #nmg-panel-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:8px;} .zjzx-footer-extra{flex:0 0 auto;} #nmg-panel-footer{flex:0 0 auto;padding:7px 11px;background:#eef2f7;border-top:1px solid #dbe4f0;font-size:12px;} #nmg-panel-brand{display:flex;align-items:center;gap:9px;min-width:0;flex:1;} #nmg-panel-logo{width:30px;height:30px;border-radius:9px;object-fit:cover;box-shadow:0 2px 9px rgba(15,23,42,.11);border:1px solid rgba(148,163,184,.45);background:#fff;flex:0 0 auto;} #nmg-panel-title{font-size:13px;font-weight:900;color:#9a3412;line-height:1.26;display:flex;align-items:flex-start;gap:5px;flex-wrap:wrap;} .zjzx-panel-title-text{flex:1 1 12em;min-width:0;letter-spacing:-0.01em;} #nmg-panel-sub{display:flex;flex-wrap:wrap;align-items:center;gap:3px 5px;margin-top:3px;line-height:1.32;} .zjzx-sub-chip{font-size:11px;color:#7c2d12;background:rgba(255,255,255,.62);padding:2px 7px;border-radius:999px;border:1px solid rgba(180,83,9,.18);font-weight:700;} .zjzx-sub-chip-em{color:#0f766e;background:rgba(236,253,245,.9);border-color:rgba(15,118,110,.28);} .zjzx-sub-dot{color:#d6d3d1;font-size:10px;font-weight:400;} .zjzx-panel-ctl .zjzx-ctl-ico{display:block;box-sizing:border-box;margin:0 auto;} .zjzx-ctl-min{width:10px;height:2px;background:#64748b;border-radius:1px;} .zjzx-ctl-plus{font-size:16px;line-height:1;font-weight:700;color:#64748b;} .zjzx-panel-version{font-size:11px;font-weight:900;color:#64748b;padding:2px 7px;border-radius:999px;background:#f1f5f9;border:1px solid #e2e8f0;} #nmg-panel-controls{display:flex;align-items:center;gap:5px;flex:0 0 auto;} .zjzx-panel-ctl{border:none;background:#fff;color:#64748b;width:28px;height:28px;border-radius:999px;cursor:pointer;box-shadow:0 1px 2px rgba(15,23,42,.1);font-size:15px;line-height:1;font-weight:900;padding:0;} .zjzx-card{background:#fff;border:1px solid #d9e2ee;border-radius:12px;padding:7px 9px;margin-bottom:7px;} .zjzx-card-status{padding:6px 8px;margin-bottom:6px;} .zjzx-status-row{display:flex;justify-content:space-between;align-items:center;gap:7px;line-height:1.28;} .zjzx-status-label{font-size:11px;color:#64748b;font-weight:700;} .zjzx-status-main{margin-top:3px;} .zjzx-status-metrics{display:flex;align-items:center;gap:5px;font-size:12px;color:#475569;min-width:0;flex:1;} .zjzx-status-metrics em{font-style:normal;font-weight:900;color:#0f172a;} .zjzx-metric-div{color:#cbd5e1;} .zjzx-card-status .zjzx-progress-pct{font-size:14px;font-weight:900;color:#0369a1;flex:0 0 auto;} .zjzx-card-status .zjzx-progress-bar{height:5px;margin-top:4px;margin-bottom:0;} .zjzx-progress-bar{height:9px;border-radius:999px;background:#e2e8f0;overflow:hidden;margin-top:5px;} .zjzx-progress-bar>span{display:block;height:100%;width:0;background:linear-gradient(90deg,#22d3ee,#2563eb);transition:width .2s ease;} .zjzx-list-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;} .zjzx-list-head-actions{display:flex;align-items:center;gap:5px;} .zjzx-log-clear-btn{border:1px solid #cbd5e1;background:#fff;color:#64748b;padding:1px 7px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer;line-height:1.4;} .zjzx-plan-select{width:100%;border:1px solid #cbd5e1;border-radius:8px;padding:6px 9px;font-size:12px;background:#fff;color:#0f172a;} .zjzx-list-title{font-size:12px;color:#64748b;font-weight:700;} .zjzx-list-tag{font-size:11px;color:#92400e;background:#ffedd5;border:1px solid #fdba74;border-radius:999px;padding:2px 7px;} .zjzx-empty-state{padding:12px 7px;text-align:center;color:#94a3b8;font-size:12px;font-weight:900;} #nmg-course-list,#nmg-chapter-list,#nmg-run-log{max-height:220px;overflow-y:auto;background:#f1f5f9;border:1px solid #dbe4f0;border-radius:11px;padding:6px;} .w2-course-card{display:flex;gap:8px;align-items:flex-start;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:8px;margin-bottom:6px;cursor:pointer;} .w2-course-card.is-active{border-color:#86efac;background:#f0fdf4;} .w2-course-card.is-done{opacity:.92;} .w2-course-card:last-child{margin-bottom:0;} .w2-plan-group{margin-bottom:8px;border:1px solid #dbe4f0;border-radius:10px;background:#fff;overflow:hidden;} .w2-plan-group:last-child{margin-bottom:0;} .w2-plan-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;padding:8px 10px;background:#eaf1ff;border-bottom:1px solid #dbe4f0;} .w2-plan-name{font-size:12px;font-weight:800;color:#1d4ed8;line-height:1.35;flex:1;min-width:0;} .w2-plan-count{flex:0 0 auto;font-size:10px;font-weight:700;color:#64748b;background:#fff;border:1px solid #cbd5e1;border-radius:999px;padding:1px 7px;margin-top:1px;} .w2-plan-body{padding:7px;} .w2-plan-exam{display:flex;align-items:center;gap:6px;margin-top:6px;padding:7px 8px;border:1px dashed #cbd5e1;border-radius:8px;background:#f8fafc;} .w2-plan-exam.is-ready{border-color:#fdba74;background:#fff7ed;} .w2-plan-exam.is-passed{border-color:#86efac;background:#f0fdf4;} .w2-plan-exam-label{font-size:11px;font-weight:800;color:#334155;flex:0 0 auto;} .w2-plan-exam-hint{flex:1;min-width:0;font-size:10px;color:#64748b;line-height:1.35;} .w2-plan-exam-badge{flex:0 0 auto;font-size:10px;font-weight:800;} .w2-course-check{margin-top:3px;accent-color:#2563eb;width:15px;height:15px;flex:0 0 auto;} .w2-course-main{flex:1;min-width:0;} .w2-course-title-row{display:flex;flex-wrap:wrap;align-items:center;gap:4px;line-height:1.35;} .w2-course-name{font-size:12px;color:#0f172a;font-weight:700;} .w2-done-tag{display:inline-block;font-size:10px;color:#166534;background:#dcfce7;border:1px solid #86efac;border-radius:999px;padding:0 6px;font-weight:800;} .w2-course-meta{display:block;font-size:11px;color:#64748b;margin-top:3px;} .w2-course-status{display:block;font-size:11px;margin-top:2px;font-weight:700;} .w2-course-bar{display:block;height:4px;background:#e2e8f0;border-radius:2px;margin-top:6px;overflow:hidden;} .w2-course-bar>span{display:block;height:100%;background:#3b82f6;border-radius:2px;} .zjzx-chapter-course{margin-bottom:7px;border:1px solid #dbe4f0;border-radius:9px;background:#fff;overflow:hidden;} .zjzx-chapter-title{padding:6px 9px;background:#eaf1ff;border-bottom:1px solid #dbe4f0;color:#1d4ed8;font-size:12px;font-weight:700;display:flex;justify-content:space-between;gap:8px;align-items:flex-start;} .zjzx-chapter-block{border-bottom:1px solid #eef2f7;} .zjzx-chapter-block:last-child{border-bottom:none;} .zjzx-chapter-h{padding:5px 9px;font-size:11px;font-weight:700;color:#334155;background:#f8fafc;} .zjzx-chapter-item{padding:5px 9px;font-size:11px;display:flex;justify-content:space-between;gap:7px;border-bottom:1px dashed #eef2f7;color:#0f172a;} .zjzx-chapter-item:last-child{border-bottom:none;} .zjzx-chapter-item.is-current{background:#eff6ff;border-color:#bfdbfe;} .zjzx-chapter-item.is-current .zjzx-chapter-vmeta{color:#1d4ed8;font-weight:800;} .zjzx-chapter-vname{flex:1;min-width:0;line-height:1.35;} .zjzx-chapter-vmeta{flex:0 0 auto;color:#64748b;white-space:nowrap;font-size:10px;} .zjzx-footer-extra{padding:6px 9px;background:#f8fafc;border-top:1px solid #e2e8f0;opacity:.95;} .zjzx-ann{position:relative;font-size:12px;color:#334155;line-height:1.42;background:linear-gradient(180deg,#fffdf5,#fff7e6);border:1px solid #fcd34d;border-radius:11px;padding:8px 9px 8px 11px;margin-bottom:0;} .zjzx-ann-text{display:block;word-break:break-word;} .zjzx-ann::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(180deg,#f59e0b,#ef4444);border-top-left-radius:11px;border-bottom-left-radius:11px;} .zjzx-qq-row{display:flex;align-items:center;justify-content:space-between;gap:9px;margin-top:5px;} .zjzx-qq-text{font-size:12px;color:#475569;} .zjzx-qq-title{font-size:13px;font-weight:800;color:#0f172a;} .zjzx-qq-btn{border:none;background:linear-gradient(135deg,#1d4ed8,#0ea5e9);color:#fff;padding:5px 12px;border-radius:999px;font-size:12px;font-weight:800;cursor:pointer;} .zjzx-study-mode-hint{margin-top:5px;padding:7px 9px;border-radius:9px;border:1px solid #e2e8f0;font-size:11px;line-height:1.42;} .zjzx-study-mode-hint-title{display:block;font-weight:800;margin-bottom:3px;} .zjzx-study-mode-hint-body{margin:0;color:#475569;} .zjzx-study-mode-hint-efficiency{background:linear-gradient(135deg,#eff6ff,#f0f9ff);border-color:#bfdbfe;color:#1e3a8a;} .zjzx-study-mode-hint-realtime{background:linear-gradient(135deg,#fffbeb,#fef3c7);border-color:#f59e0b;color:#78350f;} .zjzx-start-hint{font-size:11px;color:#b45309;background:#fffbeb;border:1px solid #fcd34d;border-radius:7px;padding:5px 7px;margin-bottom:5px;line-height:1.32;text-align:center;font-weight:600;} .zjzx-tabbar{display:flex;gap:6px;margin-bottom:7px;} .zjzx-tab-btn{flex:1;border:1px solid #cbd5e1;background:#f8fafc;color:#475569;padding:4px 4px;border-radius:9px;cursor:pointer;font-weight:700;font-size:11px;} .zjzx-tab-btn.active{background:linear-gradient(135deg,#1d4ed8,#0ea5e9);color:#fff;border-color:transparent;} .zjzx-pane{display:none;}.zjzx-pane.active{display:block;} .zjzx-btn-row{display:flex;gap:7px;margin-bottom:6px;flex-wrap:wrap;} .zjzx-btn-row-nowrap{flex-wrap:nowrap;} .zjzx-btn{flex:1;border:none;color:#fff;padding:7px 9px;border-radius:10px;cursor:pointer;font-weight:800;font-size:12px;min-width:68px;} .zjzx-btn-action{min-width:0 !important;flex:1 1 0 !important;} .zjzx-btn-ico{font-size:13px;line-height:1;display:inline-flex;align-items:center;margin-right:5px;} .zjzx-btn-label{white-space:nowrap;} .zjzx-btn-start{background:#16a34a;}.zjzx-btn-stop{background:#ef4444;} .zjzx-btn-start.zjzx-btn-off,.zjzx-btn-start:disabled{background:#cbd5e1 !important;color:#64748b !important;cursor:not-allowed;box-shadow:none;pointer-events:none;} .zjzx-btn-stop.zjzx-btn-off,.zjzx-btn-stop:disabled{background:#e2e8f0 !important;color:#94a3b8 !important;cursor:not-allowed;box-shadow:none;pointer-events:none;} .zjzx-btn-ghost{border:1px solid #cbd5e1;background:#fff;color:#0f172a;flex:0 0 auto;} .zjzx-meta-row{display:flex;justify-content:space-between;gap:7px;font-size:12px;margin-bottom:5px;align-items:center;} .zjzx-meta-label{color:#64748b;}.zjzx-meta-value{font-weight:700;text-align:right;} .zjzx-card-current{padding:5px 8px;margin-bottom:6px;} .zjzx-card-current .zjzx-meta-row{font-size:11px;margin-bottom:2px;gap:5px;line-height:1.28;align-items:flex-start;} .zjzx-card-current .zjzx-meta-row:last-child{margin-bottom:0;} .zjzx-card-current .zjzx-meta-label{flex:0 0 auto;font-size:10px;white-space:nowrap;} .zjzx-card-current .zjzx-meta-value{flex:1 1 auto;min-width:0;font-size:11px;font-weight:600;text-align:right;word-break:break-all;line-height:1.28;} .zjzx-card-actions{padding:6px 8px;} .zjzx-study-mode-block{margin-bottom:5px;} .zjzx-study-mode-block .zjzx-study-mode-row{display:flex;align-items:center;gap:5px;margin-bottom:0;} .zjzx-study-mode-block .zjzx-plan-select{flex:1 1 auto;min-width:0;width:auto;padding:3px 22px 3px 7px;font-size:11px;line-height:1.25;border-radius:7px;} #nmg-auto-status{padding:2px 7px;border-radius:999px;font-weight:900;font-size:11px;background:#fff;border:1px solid #cbd5e1;} .zjzx-log-row{padding:4px 6px;border-bottom:1px dashed #d4deea;font-size:12px;line-height:1.42;} .zjzx-log-row.err{color:#b91c1c}.zjzx-log-row.prog{color:#0369a1} .zjzx-settings-check{display:flex;gap:6px;align-items:center;margin:6px 0;font-size:12px;font-weight:700;color:#334155;} .zjzx-pro-banner{margin:0 0 8px;padding:9px 10px;border-radius:11px;background:linear-gradient(135deg,#fff7ed,#fef3c7);border:1px solid #fdba74;} .zjzx-pro-banner-title{font-size:12px;font-weight:900;color:#9a3412;margin-bottom:3px;} .zjzx-pro-banner-desc{font-size:11px;color:#78350f;line-height:1.38;margin-bottom:7px;} .zjzx-btn-pro{display:inline-block;text-decoration:none;background:linear-gradient(135deg,#ea580c,#f59e0b);color:#fff;padding:6px 12px;border-radius:999px;font-size:11px;font-weight:800;} .zjzx-token-input{flex:1;min-width:0;border:1px solid #cbd5e1;border-radius:8px;padding:5px 8px;font-size:12px;} `, e.appendChild(t); } function Me() { let e = g("nmg-run-log"); e && ye( e, r.logs.slice(0, 80).map((t) => { let n = t.type === "error" ? "err" : t.type === "progress" ? "prog" : "", o = new Date(t.t).toLocaleTimeString(); return `
[${o}] ${z(t.msg)}
`; }).join("") ); } function ke() { let e = g("nmg-course-list"); if (!e) return; if (!F().length) { ye( e, '
\u6682\u65E0\u8BFE\u7A0B
\u8BF7\u5148\u767B\u5F55\u5E76\u5237\u65B0\u5217\u8868
' ), A(); return; } let n = r.activeCourse && r.activeCourse.id; ye(e, Tt(n)), e.querySelectorAll('input[type="checkbox"]').forEach((o) => { o.addEventListener("change", () => { let a = []; e.querySelectorAll('input[type="checkbox"]').forEach((s) => { s.checked && a.push(s.getAttribute("data-id")); }); let i = r.learningCourses.length; a.length ? i > 0 && a.length === i ? (r.selectMode = "all", r.selectedIds = /* @__PURE__ */ new Set()) : (r.selectMode = "partial", r.selectedIds = new Set(a)) : (r.selectMode = "none", r.selectedIds = /* @__PURE__ */ new Set()), Le(), Fe(), A(); }); }), A(); } function X() { let e = g("nmg-chapter-list"); if (!e) return; let t = L().length > 0 ? L() : F(); ye(e, Mt(t)); } async function br() { await he(), ke(), h === "pl" && (p("\u6B63\u5728\u62C9\u53D6\u8BFE\u4EF6\u76EE\u5F55\u2026", "info"), await It(F())), X(); let e = F().reduce( (t, n) => t + (n.children || []).reduce((o, a) => o + (a.children || []).length, 0), 0 ); p( `\u5DF2\u5237\u65B0 \xB7 ${r.planGroups.length} \u4E2A\u8BA1\u5212 \xB7 \u5F85\u5B66 ${r.learningCourses.length} \u95E8 \xB7 \u5DF2\u5B8C\u6210 ${r.completedCourses.length} \u95E8 \xB7 \u8BFE\u4EF6 ${e}`, "info" ), A(); } function tt(e, t, n) { let o = document.getElementById("nmg-panel-host"); o && o.remove(); let a = document.createElement("div"); a.id = "nmg-panel-host", document.body.appendChild(a); let i = a.attachShadow({ mode: "closed" }); gr(i); let s = document.createElement("div"); i.appendChild(s), _t(s); let l = r.remotePanelNotice || pt, f = String( typeof GM_info < "u" && GM_info?.script?.version || "" ).trim(), d = document.createElement("div"); d.id = "nmg-auto-panel", d.className = "zjzx-panel-max", d.innerHTML = `
${z(st)}v${z(f)}
\u4E00\u952E\u5B8C\u6210\u89C6\u9891\u5B66\u65F6\xB7\u4E13\u4E1A\u7248\u81EA\u52A8\u8003\u8BD5\xB7\u7701\u65F6\u7701\u5FC3
\u8FD0\u884C\u72B6\u6001 \u5DF2\u505C\u6B62
0/0 \u8BFE\u7A0B\u5B66\u65F6\u5DF2\u6EE1 \xB7 \u8003\u8BD5 \u2014
0%
\u6309\u8BA1\u5212\u5206\u7EC4 \xB7 \u52FE\u9009\u5F85\u5B66\u8BFE\u7A0B
\u8BA1\u5212
\u767B\u5F55\u540E\u5C06\u81EA\u52A8\u52A0\u8F7D\u8BFE\u7A0B
\u7AE0\u8282 / \u8BFE\u4EF6\u9884\u89C8 \u52FE\u9009\u8BFE\u7A0B\u4F18\u5148
\u5237\u65B0\u8BFE\u7A0B\u540E\u663E\u793A\u7AE0\u8282
\u8FD0\u884C\u65E5\u5FD7
\u5B9E\u65F6\u65E5\u5FD7
\u5347\u7EA7\u4E13\u4E1A\u7248
\u514D\u8D39\u53EF\u4F53\u9A8C ${r.freeCourseLimit} \u4E2A\u7AE0\u8282\u8BFE\u65F6\uFF08\u4E0D\u542B\u81EA\u52A8\u8003\u8BD5\uFF09\uFF1B\u4E13\u4E1A\u7248\u6FC0\u6D3B\u540E ${r.activationTtlDays || 30} \u5929\u6709\u6548\uFF0C\u4E0D\u9650\u8BFE\u65F6\u4E0E\u8003\u8BD5\u3002
\u7ACB\u5373\u8D2D\u4E70\u4E13\u4E1A\u7248
\u4E13\u4E1A\u7248\u4F1A\u5458
\u4F1A\u5458\u72B6\u6001\u52A0\u8F7D\u4E2D\u2026
\u6FC0\u6D3B\u7801
\u5F53\u524D\u8BFE\u7A0B\u65E0
\u5F53\u524D\u7AE0\u8282\u65E0
\u5F53\u524D\u4EFB\u52A1\u70B9\u5F00\u59CB\u540E\u81EA\u52A8\u63D0\u4EA4
`, s.appendChild(d); let m = de(w.panelPos, null); m && m.left != null && (d.style.left = `${m.left}px`, d.style.top = `${m.top}px`, d.style.right = "auto"), Ze(d, !!GM_getValue(w.collapsed, !1)), xr(d), g("nmg-btn-min")?.addEventListener("click", (c) => { c.stopPropagation(), GM_setValue(w.collapsed, !0), Ze(d, !0); }), g("nmg-btn-max")?.addEventListener("click", (c) => { c.stopPropagation(), GM_setValue(w.collapsed, !1), Ze(d, !1); }), d.querySelectorAll(".zjzx-tab-btn").forEach((c) => { c.addEventListener("click", () => mr(c.dataset.tab)); }), g("nmg-clear-log")?.addEventListener("click", () => { r.logs = [], Me(); }), g("nmg-select-all")?.addEventListener("click", Nt), g("nmg-deselect-all")?.addEventListener("click", Pt), g("nmg-start").addEventListener("click", pn), g("nmg-stop").addEventListener("click", un), g("nmg-join-qq")?.addEventListener("click", () => { try { window.open(mt, "_blank"); } catch { } }); let u = g("nmg-cloud-token"); u && (u.value = r.cloudToken || ""), g("nmg-save-token")?.addEventListener("click", async () => { let c = String(u?.value || "").trim(); r.cloudToken = c, localStorage.setItem(ce, c), ze("", 0), r.cloudLease = ""; try { c && await Gt(), await I(!0), p("\u6FC0\u6D3B\u7801\u5DF2\u4FDD\u5B58", "info"); } catch (b) { p(`\u4FDD\u5B58\u5931\u8D25: ${b.message || b}`, "error"); } D(); }), g("nmg-clear-token")?.addEventListener("click", async () => { r.cloudToken = "", localStorage.removeItem(ce), ze("", 0), r.cloudLease = "", r.cloudTier = "free", u && (u.value = ""); try { await I(!0), p("\u5DF2\u5207\u6362\u4E3A\u514D\u8D39\u7248", "info"); } catch (c) { p(`\u5237\u65B0\u5931\u8D25: ${c.message || c}`, "error"); } D(); }), Me(), A(), D(), mn = e, xn = t, fn(mn, xn), Jt().then(() => Ht()).then(() => I(!1).catch(() => { })).then(() => D()).finally(() => { br().catch((c) => p(`\u52A0\u8F7D\u8BFE\u7A0B\u5931\u8D25: ${c.message}`, "error")), r.enabled && !r.running && Xe(); }); } function hr(e, t, n, o) { window.top === window.self && (window[Z] || (window[Z] = it, qt(), Dt(Me), Ut(Se), Zt({ upd: () => { A(), X(), (r.enabled || r.running) && ke(); } }), nn(A), dn({ upd: A, hint: et, clear: Fe, lists: () => { ke(), X(); } }), Et(() => { Fe(), ke(), X(), A(); }), jt(), document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => tt(e, n, t)) : tt(e, n, t))); } hr(Vue, DOMPurify, Pinia, CryptoJS); })(); })(Vue,DOMPurify,Pinia,CryptoJS);