// ==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))}
${u}>`;
}
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 '
';
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 `