Greasy Fork is available in English.

🌱【免费版】新版辽宁省干部在线学习网|云南青海河北新疆干部网络学院|*收费版本见使用说明:http://doc.zhanyc.cn/pages/hbgb/

当前是免费版本,只包含了简单基本功能。广告:付费版本可解锁全自动无人值守,极速秒过,欢迎选购,请我喝一杯咖啡,保你无忧学习|接各类脚本开发工作,微信:zhanyc_cn 备用微信:zhanfengkuo 个人网站:http://doc.zhanyc.cn

  1. // ==UserScript==
  2. // @name 🌱【免费版】新版辽宁省干部在线学习网|云南青海河北新疆干部网络学院|*收费版本见使用说明:http://doc.zhanyc.cn/pages/hbgb/
  3. // @namespace http://jb.zhanyc.cn/
  4. // @icon https://js.zhanyc.cn/img/js-logo.svg
  5. // @version 1.6
  6. // @description 当前是免费版本,只包含了简单基本功能。广告:付费版本可解锁全自动无人值守,极速秒过,欢迎选购,请我喝一杯咖啡,保你无忧学习|接各类脚本开发工作,微信:zhanyc_cn 备用微信:zhanfengkuo 个人网站:http://doc.zhanyc.cn
  7. // @author zfk
  8. // @include *://*hebgb.gov.cn/*
  9. // @include *://*xjgbzx.cn/*
  10. // @include *://*gwypx.com.cn/*
  11. // @include *://*ynsgbzx.cn/*
  12. // @include *://*gbykt.com/*
  13. // @include *://*qhce.gov.cn/*
  14. // @include *://*lngbzx.gov.cn/*
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // @grant GM_addStyle
  18. // @grant GM_deleteValue
  19. // @grant GM_setClipboard
  20. // @grant GM_registerMenuCommand
  21. // @grant GM_getResourceURL
  22. // @grant GM_addValueChangeListener
  23. // @grant GM_removeValueChangeListener
  24. // @grant GM_getResourceText
  25. // @grant window.close
  26. // @run-at document-body
  27. // @require http://libs.baidu.com/jquery/2.0.0/jquery.min.js
  28. // @require https://update.greasyfork.org/scripts/502187/1419386/base_lib.js
  29. // @require https://greasyfork.org/scripts/434540-layerjs-gm-with-css/code/layerjs-gm-with-css.js?version=1065982
  30. // @antifeature
  31. // @license GPL
  32. // ==/UserScript==
  33. (function () {
  34. // @run-at document-start
  35. let $jq = $;
  36. unsafeWindow.$jq = $;
  37. unsafeWindow.layer = layer;
  38. let baseConfig = {
  39. project: {
  40. id: "1650871821559652353",
  41. version: "202405241831",
  42. },
  43. url: {
  44. login: "https://m.zhanyc.cn/simp/index.html",
  45. base: "https://m.zhanyc.cn/api",
  46. resource: "https://js.zhanyc.cn",
  47. },
  48. };
  49. let docUrl = "http://doc.zhanyc.cn/pages/hbgb/";
  50. let plugMain = Object.assign(baseConfig, {
  51. config: {
  52. maxComment: 100,
  53. },
  54. pageData: {
  55. userNameIndex: null,
  56. closeTipsIndex: null,
  57. confirmRunIndex: null,
  58. confirmRunZIndex: 19991018,
  59. waitTime: 0,
  60. index: {
  61. list: null,
  62. },
  63. video: {
  64. index: null,
  65. },
  66. },
  67. async init() {
  68. console.log("%c pg init", "background:rgb(0,0,0);color:#fff");
  69. var lockResolver;
  70. if (navigator && navigator.locks && navigator.locks.request) {
  71. const promise = new Promise((res) => {
  72. lockResolver = res;
  73. });
  74.  
  75. navigator.locks.request("unique_lock_name", { mode: "shared" }, () => {
  76. return promise;
  77. });
  78. }
  79. plugMain.addStyle();
  80. unsafeWindow.alert = function (msg) {
  81. layer.alert(msg);
  82. };
  83. let run = true;
  84. if (run) plugMain.firstRun();
  85. },
  86. async runByUrl(url) {
  87.  
  88. plugMain.pageData.tipsAndCloseMark = plugMain.now()
  89. if (url.includes("/study_play.do?")) {
  90. plugMain.page_video();
  91. } else if (
  92. url.includes("/study_center/sent_detail/tool_course")
  93. ) {
  94. plugMain.showPaidContent(`免费版本不包含自动换课功能,收费版本含全自动秒过换课功能,如需使用请安装收费版本`)
  95. } else if (
  96. url.includes("course_myselect.do?") ||
  97. url.includes("/course_myrequired.do?")
  98. ) {
  99.  
  100. plugMain.showPaidContent(`免费版本不包含自动换课功能,收费版本含全自动秒过换课功能,如需使用请安装收费版本`)
  101. } else if (url.includes("/portal/course_detail.do?")) {
  102. plugMain.page_course_detail();
  103. } else if (
  104. url.includes('/study_center/my_course')
  105. ) {
  106.  
  107. plugMain.showPaidContent(`免费版本不包含自动换课功能,收费版本含全自动秒过换课功能,如需使用请安装收费版本`)
  108. } else if (url.includes("/course_detail?")) {
  109. plugMain.page_course_detail2();
  110. } else if (url.includes("/video_detail?")) {
  111. plugMain.page_video2();
  112. } else if (url.includes("/study_center/curricula_variable")) {
  113. plugMain.page_curricula_variable();
  114. } else if (url.includes("/pc/index.html")) {
  115. plugMain.page_pcIndex();
  116. }
  117. },
  118. async page_pcIndex() {
  119. await plugMain.waitOf(a => $(`[aria-label="关于“专业技术人才在线学习专区”学习有关问题的通知"]`).length > 0)
  120. plugMain.confirmMsg("检测到倒计时弹窗,是否跳过", {
  121. title: "脚本提示(3秒后自动关闭本提示)", btn: ["跳过倒计时", "取消"], time: 3000,
  122. fun1(index) {
  123. $(`[aria-label="关于“专业技术人才在线学习专区”学习有关问题的通知"]`).next().remove()
  124. $(`[aria-label="关于“专业技术人才在线学习专区”学习有关问题的通知"]`).remove()
  125. layer.close(index)
  126. },
  127. fun2() { },
  128. fun3() { }
  129. })
  130. },
  131. async page_curricula_variable() {
  132. console.log("%c page_curricula_variable", "background:rgb(0,0,0);color:#fff");
  133. await plugMain.waitOf(a => $(".content_box_header").length > 0)
  134. $(".content_box_header").before(`<div text="text-center"><button class="zfk-btn" type="button" onclick="plugMain.xk()">脚本一键选课:本页可见课程</button></div>`)
  135.  
  136. },
  137. async page_course_detail() {
  138. console.log("%c page_course_detail", "background:rgb(0,0,0);color:#fff");
  139. plugMain.closeWaitConfrimWin();
  140. setTimeout(() => {
  141.  
  142. }, 20 * 1000);
  143. await plugMain.waitOf(
  144. (a) =>
  145. $("#cse_dtl_btn input").length > 0 || $("#cse_dtl_btn a").length > 0
  146. );
  147. plugMain.confirmRun().then((a) => {
  148. if ($("#cse_dtl_btn a").length > 0) {
  149. $("#cse_dtl_btn a")[0].click();
  150. }
  151. $("#cse_dtl_btn input").click();
  152. plugMain.openLjTips(true, true);
  153. });
  154. },
  155.  
  156. async page_course_detail2() {
  157. console.log("%c page_course_detail2", "background:rgb(0,0,0);color:#fff");
  158. plugMain.closeWaitConfrimWin();
  159. if (plugMain.pageData.courseDetailIndex == null) {
  160. plugMain.pageData.courseDetailIndex = setTimeout(() => {
  161. plugMain.confirmRun("网页卡住了,3秒后刷新页面").then(a => {
  162. location.reload()
  163. })
  164. }, 60 * 1000);
  165. }
  166. await plugMain.waitOf(
  167. (a) =>
  168. $(".select_course").length > 0
  169. );
  170. await plugMain.waitTimeout(2000)
  171. if ($(".select_course").text() != "开始学习") {
  172. plugMain.tipsMsg("卡住了,5秒后重试", 5000)
  173. await plugMain.waitTimeout(5000)
  174. plugMain.page_course_detail2()
  175. return
  176. }
  177. plugMain.confirmRun().then((a) => {
  178. $(".select_course").click()
  179. plugMain.openLjTips(true, true)
  180. // plugMain.checkUrlChangeAndRun()
  181. });
  182. },
  183.  
  184. async page_video2() {
  185. plugMain.closeWaitConfrimWin();
  186. console.log("%c page_video2", "background:rgb(0,0,0);color:#fff");
  187. let timeout = 2;
  188.  
  189. plugMain.showPaidContent(`收费版本含全自动秒过、自动换课功能,如需使用请安装收费版本`)
  190. if (plugMain.pageData.video.index != null) {
  191. return;
  192. }
  193. setTimeout(async () => {
  194. let time = plugMain.getCurTime()
  195. await plugMain.waitTimeout(5000)
  196. if (plugMain.getCurTime() == time) {
  197. plugMain.confirmRun("貌似卡主了,3秒后刷新页面").then(a => {
  198. location.reload()
  199. })
  200. }
  201. }, 60 * 1000);
  202. plugMain.pageData.video.index = setInterval(async () => {
  203. try {
  204. if (plugMain.pageData.waitTime > 0) {
  205. plugMain.pageData.waitTime -= timeout;
  206. return;
  207. }
  208. if (plugMain.getElByText($(".el-dialog__body"), "是否继续学习?") != null) {
  209. plugMain.getElByText($(".el-dialog__body"), "是否继续学习?").next().find('button').click()
  210. return
  211. }
  212. if (!plugMain.getVideo()) {
  213. console.log("%c zfk no video", "background:rgb(0,0,0);color:#fff");
  214. return;
  215. }
  216. // if (!location.href.includes("/video?")) {
  217. // return;
  218. // }
  219. plugMain.getVideo().volume = 0;
  220. let title = `进度:${plugMain.getCurTime().toFixed(0)}/${zfk
  221. .getTotalTime()
  222. .toFixed(0)}`;
  223. $("title").text(title);
  224. console.log("%c video run", "background:rgb(255,0,0);color:#fff");
  225.  
  226. let isFinish = await plugMain.isPlayFinish();
  227. if (isFinish) {
  228. plugMain.pageData.waitTime = 15;
  229. layer.msg("视频即将结束,等待下一步操作", { time: 10 * 1000 });
  230. // plugMain.pageData.waitTime = plugMain.getTotalTime() - plugMain.getCurTime() + 1;
  231.  
  232. return;
  233. }
  234. let isPlay = await plugMain.videoIsPlay();
  235. if (!isPlay) {
  236. if (!isFinish) {
  237. plugMain.play();
  238. }
  239. }
  240. } catch (e) {
  241. console.error("视频页面定时器出错", e);
  242. }
  243. }, timeout * 1000);
  244. },
  245. async page_video() {
  246. console.log("%c page_video", "background:rgb(0,0,0);color:#fff");
  247. let timeout = 2;
  248.  
  249. plugMain.showPaidContent(`收费版本含全自动秒过、自动换课功能,如需使用请安装收费版本`)
  250. plugMain.closeWaitConfrimWin();
  251. if (plugMain.pageData.video.index != null) {
  252. return;
  253. }
  254. setTimeout(async () => {
  255. let time = plugMain.getCurTime()
  256. await plugMain.waitTimeout(5000)
  257. if (plugMain.getCurTime() == time) {
  258. plugMain.confirmRun("貌似卡主了,3秒后刷新页面").then(a => {
  259. location.reload()
  260. })
  261. }
  262. }, 60 * 1000);
  263. plugMain.pageData.video.index = setInterval(async () => {
  264. try {
  265. if (plugMain.pageData.waitTime > 0) {
  266. plugMain.pageData.waitTime -= timeout;
  267. return;
  268. }
  269. if (plugMain.getElByText($("div.user_choise"), "开始学习") != null) {
  270. plugMain.getElByText($("div.user_choise"), "开始学习").click();
  271. return;
  272. }
  273. if (plugMain.getElByText($("div.user_choise"), "继续学习") != null) {
  274. plugMain.getElByText($("div.user_choise"), "继续学习").click();
  275. return;
  276. }
  277. if (!plugMain.getVideo()) {
  278. console.log("%c zfk no video", "background:rgb(0,0,0);color:#fff");
  279. return;
  280. }
  281. // if (!location.href.includes("/video?")) {
  282. // return;
  283. // }
  284. plugMain.getVideo().volume = 0;
  285. let title = `进度:${plugMain.getCurTime().toFixed(0)}/${zfk
  286. .getTotalTime()
  287. .toFixed(0)}`;
  288. $("title").text(title);
  289. console.log("%c video run", "background:rgb(255,0,0);color:#fff");
  290. let $tips = plugMain.getElByText(
  291. ".layui-layer-content p",
  292. "您好,本平台要求实时在线学习,点击按钮,继续学习课程。"
  293. );
  294.  
  295. if ($tips != null) {
  296. $tips.parents(".layui-layer").find(".layui-layer-btn0")[0].click();
  297. }
  298. let isFinish = await plugMain.isPlayFinish();
  299. if (isFinish) {
  300. plugMain.pageData.waitTime = 15;
  301. layer.msg("视频即将结束,等待下一步操作", { time: 10 * 1000 });
  302. return;
  303. }
  304. let isPlay = await plugMain.videoIsPlay();
  305. if (!isPlay) {
  306. if (!isFinish) {
  307. plugMain.play();
  308. }
  309. }
  310. } catch (e) {
  311. console.error("视频页面定时器出错", e);
  312. }
  313. }, timeout * 1000);
  314. },
  315. checkVideoPlay() {
  316. let lastTime = plugMain.getCurTime();
  317. return new Promise((resolve) => {
  318. setTimeout(() => {
  319. if (plugMain.getTotalTime() > 0 && plugMain.getCurTime() == lastTime) {
  320. plugMain.play();
  321. }
  322. lastTime = plugMain.getCurTime();
  323. resolve();
  324. }, 3000);
  325. });
  326. },
  327. listenerVideo() {
  328. console.log("%c listenerVideo", "background:rgb(255,0,0);color:#fff");
  329. let index = setInterval(() => {
  330. // 重播按钮(视频放完了,但是进度还没完)
  331. if ($(".xgplayer-replay:visible").length > 0) {
  332. document.querySelector("video").play();
  333. return;
  334. }
  335. if ($(".dialog-content") == "学时记录出现异常请检查网络") {
  336. location.reload();
  337. return;
  338. }
  339. }, 5000);
  340. },
  341. async page_viewerforccvideo() {
  342. console.log(
  343. "%c page_viewerforccvideo",
  344. "background:rgb(255,0,0);color:#fff"
  345. );
  346. plugMain.setGMData("closeLJTS", plugMain.now());
  347. plugMain.showPaidContent("当前是免费版本,收费版本可实现全自动看课换课,无人值守,更有5倍记录学时版本等你付费升级")
  348. plugMain.checkVideoPlay().then((a) => {
  349. plugMain.checkVideoPlay();
  350. });
  351.  
  352. plugMain.listenerVideo();
  353. setInterval(() => {
  354. let cIndex = $("li.cvtb-MCK-course-content").index(
  355. $("li.cvtb-MCK-course-content.current")
  356. );
  357. let progress = $("li.cvtb-MCK-course-content.current")
  358. .find(".cvtb-MCK-CsCt-studyProgress")
  359. .text()
  360. .trim();
  361. let key = cIndex + "_" + progress;
  362. if (plugMain.pageData.video.lastKey == key) {
  363. // layer.alert("貌似卡住了,刷新页面");
  364. plugMain.confirmRun("貌似卡住了,5秒后刷新页面").then((a) => {
  365. location.href = location.href;
  366. });
  367. }
  368. plugMain.pageData.video.lastKey = key;
  369. // }, 10 * 1000);
  370. }, 2 * 60 * 1000);
  371.  
  372. plugMain.checkVideoPlay().then((a) => {
  373. plugMain.checkVideoPlay();
  374. });
  375.  
  376. plugMain.listenerVideo();
  377.  
  378. setInterval(() => {
  379. if ($("#rest_tip").length > 0) {
  380. $("#rest_tip").find("button").click();
  381. }
  382. if ($(".xgplayer-volume-large").length > 0) {
  383. $(".xgplayer-volume .xgplayer-icon").click();
  384. }
  385. }, 1000);
  386.  
  387. unsafeWindow.window.on_spark_player_pause = function () {
  388. console.log(">>>ZFK on_spark_player_pause");
  389. // zfk
  390. // clearInterval(r)
  391. };
  392. unsafeWindow.on_spark_player_resume = function () {
  393. console.log(">>>ZFK on_spark_player_resume");
  394. // zfk
  395. // i()
  396. };
  397. },
  398. page_top() {
  399. GM_addValueChangeListener('openLjts', function (name, old_value, new_value, remote) {
  400. plugMain.openLjTips()
  401. })
  402. },
  403. firstRun() {
  404. if (top === window && plugMain.getGMData("showDoc", true)) {
  405. layer.confirm(
  406. "首次使用本脚本?点击下方按钮查看使用说明",
  407. { icon: 3, title: "首次使用?", btn: ["查看使用说明", "取消"] },
  408. function (index) {
  409. plugMain.openDoc();
  410. layer.close(index);
  411. plugMain.setGMData("showDoc", false);
  412. plugMain.begin();
  413. },
  414. function () {
  415. plugMain.setGMData("showDoc", false);
  416. plugMain.begin();
  417. }
  418. );
  419. } else {
  420. }
  421. plugMain.begin();
  422. },
  423. async begin() {
  424. if (window === top) {
  425. plugMain.registerMenuCommand();
  426. }
  427. let lastUrl = location.href;
  428.  
  429.  
  430. setInterval(async () => {
  431. if (lastUrl != location.href) {
  432. lastUrl = location.href;
  433. plugMain.runByUrl(location.href);
  434. }
  435. }, 500);
  436. plugMain.runByUrl(location.href);
  437. },
  438.  
  439. setSkip(event, courseId, skip) {
  440. event.stopPropagation()
  441. $(".skipContainer").remove();
  442. var sikpList = plugMain.getGMData("skipList", []);
  443. if (skip) {
  444. sikpList.push(courseId);
  445. plugMain.setGMData("skipList", sikpList);
  446. } else {
  447. plugMain.setGMData(
  448. "skipList",
  449. sikpList.filter((a) => a != courseId)
  450. );
  451. }
  452. layer.msg("操作成功");
  453. plugMain.setSkipBtn();
  454. },
  455. setSkipBtn() {
  456. var sikpList = plugMain.getGMData("skipList", []);
  457. $(".zfk-skipContainer").remove()
  458. $("#currentCourseDiv .course").each((i, el) => {
  459. let courseId = $(el).attr("courseid");
  460. let $btnContainer = $(el)
  461. if (sikpList.includes(courseId)) {
  462. $btnContainer.after(
  463. `<div class="text-center zfk-skipContainer"><button type="button" class="zfk-btn info" onclick="plugMain.setSkip(event,'${courseId}',false)">脚本:取消跳过</button></div>`
  464. );
  465. } else {
  466. $btnContainer.after(
  467. `<div class="text-center zfk-skipContainer"><button type="button" class="zfk-btn danger" onclick="plugMain.setSkip(event,'${courseId}',true)">脚本:跳过课程</button></div>`
  468. );
  469. }
  470. });
  471. },
  472. async showPaidContent(msg = "此页面未付费内容,免费脚本不包含", withPostfix = true) {
  473. if (withPostfix) {
  474. msg += "<span style='font-weight:bold;'>*重要:一个学员付费一次,永久使用,永久更新!</span>"
  475. }
  476. plugMain.confirmMsg(msg, {
  477. btn: ["查看收费版本", "关闭"],
  478. title: "免费版本提示",
  479. area: ["500px"],
  480. shade: 0,
  481. offset: "rb",
  482. fun1(index) { plugMain.openDoc() }
  483. })
  484. },
  485. localSaveQa(qaArr) {
  486. let list = plugMain.getGMData("qaList", []);
  487. qaArr.forEach((item) => {
  488. let old = list.find((a) => a.key == item.key);
  489. item.value = item.value.replace(/#split#/g, "|");
  490. if (!old) {
  491. list.push(item);
  492. } else {
  493. old.value = item.value;
  494. }
  495. });
  496. plugMain.setGMData("qaList", list);
  497. },
  498. play() {
  499. plugMain.getVideo().volume = 0;
  500. setTimeout(() => {
  501. plugMain.getVideo().play();
  502. }, 200);
  503. // });
  504. },
  505. setVideoVolume() {
  506. try {
  507. if (plugMain.getVideo().volume != 0) {
  508. plugMain.getVideo().volume = 0;
  509. }
  510. } catch (e) {
  511. console.error(e);
  512. }
  513. },
  514. isPlayFinish() {
  515. try {
  516. return (
  517. plugMain.getTotalTime() > 0 && plugMain.getCurTime() + 5 >= plugMain.getTotalTime()
  518. );
  519. } catch (e) {
  520. return false;
  521. }
  522. },
  523. getVideo() {
  524. return $("video")[0];
  525. },
  526. getCurTime() {
  527. let res = 0;
  528. try {
  529. res = $("video")[0].currentTime;
  530. } catch (e) {
  531. console.error(e);
  532. }
  533. return res;
  534. },
  535. getTotalTime() {
  536. let res = 0;
  537. try {
  538. res = $("video")[0].duration;
  539. } catch (e) {
  540. console.error(e);
  541. }
  542. return res;
  543. },
  544. // 题库方法
  545. formatAnswerOption(option) {
  546. // 检查输入是否是单个字母且在 A-Z 范围内
  547. if (/^[a-zA-Z]$/.test(option)) {
  548. option = option.toUpperCase();
  549. return option.charCodeAt(0) - 'A'.charCodeAt(0);
  550. } else {
  551. let arr = [
  552. ["正确", "错误"],
  553. ["对", "错"],
  554. ];
  555. let opt = option.toUpperCase();
  556. let res = -1;
  557. arr.forEach((subArr) => {
  558. if (subArr.includes(opt)) {
  559. res = subArr.indexOf(opt);
  560. return false;
  561. }
  562. });
  563. return res;
  564. }
  565. },
  566.  
  567. // 题库方法
  568. formatAnswerOptionNo(index) {
  569. return ["A", "B", "C", "D", "E", "F", "G", "H"][index]
  570. },
  571. isMatchQAText(txt1, txt2) {
  572. return (
  573. txt1 == txt2 ||
  574. plugMain.simpleHtml(txt1) == plugMain.simpleHtml(txt2) ||
  575. plugMain.simpleText(txt1) == plugMain.simpleText(txt2)
  576. );
  577. },
  578. simpleHtml(html) {
  579. html = html.replace(/&nbsp;|<br\/>|<br>|\n|\r/gi, "");
  580. html = html.trim();
  581. if (!html) return html;
  582. if (html.startsWith("<") && html.endsWith(">")) {
  583. return $(html).text().trim();
  584. }
  585. return html.trim();
  586. },
  587. simpleText(text) {
  588. return text
  589. .replace(/[^\u4e00-\u9fa5a-zA-Z0-9#split#√×]/g, "")
  590. .replace(/[的]/g, "");
  591. },
  592. async videoIsPlay() {
  593. return new Promise((resolve) => {
  594. try {
  595. let curTime = $("video")[0].currentTime;
  596. setTimeout(() => {
  597. let time1 = $("video")[0].currentTime;
  598. let res = time1 > curTime;
  599. if (res) {
  600. setTimeout(() => {
  601. let time2 = $("video")[0].currentTime;
  602. let res2 = time2 > time1;
  603. resolve(res2);
  604. }, 100);
  605. } else {
  606. return resolve(false);
  607. }
  608. }, 100);
  609. } catch (e) {
  610. resolve(false);
  611. }
  612. });
  613. },
  614. beginMan() {
  615. console.log("%c beginMan", "background:rgb(0,0,0);color:#fff");
  616. },
  617. stop() {
  618. location.href = location.href;
  619. },
  620.  
  621. openDoc() {
  622. if (docUrl) {
  623. window.open(docUrl);
  624. } else {
  625. window.open("http://doc.zhanyc.cn/pages/auth/");
  626. }
  627. },
  628. isDZKFMode() {
  629. let res = typeof (loadFun) == 'function' && loadFun.toString().includes('var data = res.response;')
  630. if (!res)
  631. res = typeof isDZKF == "boolean" && !!isDZKF;
  632. return res
  633. },
  634. registerMenuCommand() {
  635. GM_registerMenuCommand("当前是免费版", plugMain.openDoc);
  636. GM_registerMenuCommand("点此安装付费版本", plugMain.openDoc);
  637. GM_registerMenuCommand("联系脚本客服", plugMain.linkAuthor);
  638. },
  639. linkAuthor() {
  640. window.open("http://doc.zhanyc.cn/contact-me/");
  641. },
  642. setClip(txt) {
  643. GM_setClipboard(txt, "text");
  644. layer.msg("复制成功");
  645. },
  646. addStyle() {
  647. GM_addStyle(`
  648. .zfk-btn{background-color:#0fbcf9;color:white;padding:4px 12px;border:none;box-sizing:content-box;font-size:14px;height:20px;border-radius:4px;cursor:pointer;display:inline-block;border:1px solid transparent;white-space:nowrap;user-select:none;text-align:center;vertical-align:middle}.zfk-btn:hover{opacity:.8}.zfk-btn.success{background-color:#38b03f}.zfk-btn.warning{background-color:#f1a325}.zfk-btn.info{background-color:#03b8cf}.zfk-btn.danger{background-color:#ea644a}.zfk-form-tips{font-size:1.2em;color:red}.tips{color:red}.zfk-form textarea,.zfk-form input[type=text],.zfk-form input[type=number],.zfk-form input[type=password]{border:1px solid #888;border-radius:4px;padding:5px;box-sizing:border-box}.zfk-form textarea{width:100%}.zfk-form-item{margin-bottom:10px}.zfk-form-item>label:first-child{width:7em;text-align:right;display:inline-block;padding-right:5px;margin-right:0}.zfk-form-item label{margin-right:4px}.zfk-form-item.block>label:first-child{text-align:left;display:block;width:100%;font-weight:bold}.text-l{text-align:left !important}.text-c{text-align:center !important}.text-r{text-align:right !important}.p-0{padding:0px !important}.p-5{padding:5px !important}.p-10{padding:10px !important}.p-15{padding:15px !important}.p-20{padding:20px !important}.p-t-0{padding-top:0px !important}.p-t-5{padding-top:5px !important}.p-t-10{padding-top:10px !important}.p-t-15{padding-top:15px !important}.p-t-20{padding-top:20px !important}.p-b-0{padding-bottom:0px !important}.p-b-5{padding-bottom:5px !important}.p-b-10{padding-bottom:10px !important}.p-b-15{padding-bottom:15px !important}.p-b-20{padding-bottom:20px !important}.p-l-0{padding-left:0px !important}.p-l-5{padding-left:5px !important}.p-l-10{padding-left:10px !important}.p-l-15{padding-left:15px !important}.p-l-20{padding-left:20px !important}.p-r-0{padding-right:0px !important}.p-r-5{padding-right:5px !important}.p-r-10{padding-right:10px !important}.p-r-15{padding-right:15px !important}.p-r-20{padding-right:20px !important}.p-0{padding:0px !important}.p-5{padding:5px !important}.p-10{padding:10px !important}.p-15{padding:15px !important}.p-20{padding:20px !important}.m-t-0{margin-top:0px !important}.m-t-5{margin-top:5px !important}.m-t-10{margin-top:10px !important}.m-t-15{margin-top:15px !important}.m-t-20{margin-top:20px !important}.m-b-0{margin-bottom:0px !important}.m-b-5{margin-bottom:5px !important}.m-b-10{margin-bottom:10px !important}.m-b-15{margin-bottom:15px !important}.m-b-20{margin-bottom:20px !important}.m-l-0{margin-left:0px !important}.m-l-5{margin-left:5px !important}.m-l-10{margin-left:10px !important}.m-l-15{margin-left:15px !important}.m-l-20{margin-left:20px !important}.m-r-0{margin-right:0px !important}.m-r-5{margin-right:5px !important}.m-r-10{margin-right:10px !important}.m-r-15{margin-right:15px !important}.m-r-20{margin-right:20px !important}.bold{font-weight:bold !important}.tips-box{padding:10px;border:1px solid red;background-color:#fff0f0;color:red}.bold{font-weight:bold}.font-l{font-size:1.2em}.font-xl{font-size:40px}.font-l{font-size:25px}.color-default{color:#ea644a !important}.color-success{color:#38b03f !important}.color-warning{color:#f1a325 !important}.color-danger{color:#ea644a !important}.bg-default{background-color:#ea644a !important}.bg-success{background-color:#38b03f !important}.bg-warning{background-color:#f1a325 !important}.bg-danger{background-color:#ea644a !important}.zfk-table{border-collapse:collapse}.zfk-table thead{background-color:#1abc9c}.zfk-table td,.zfk-table th{text-align:center;padding:6px;border:1px solid #888}.zfk-table tr:nth-child(2n){background-color:#f2f2f2}.zfk-table tr:hover{background-color:#fff799}.zfk-container *{font-size:17px}
  649. `);
  650. }, // plugMain.setGMData("closeLJTS", plugMain.now());
  651. openLjTips(tipsAndClose = true, checkUrlBeforeClose = false) {
  652. let index = layer.open({
  653. type: 1,
  654. title: "请确认",
  655. offset: "100px",
  656. content: `
  657. <div style="padding:10px">
  658. <p>已经为你打开下一门课程,如果没有打开窗口,请检查浏览器地址栏右侧是否有拦截提示,请选择【永久允许】或者在浏览器设置中设置本网站【弹出式窗口和重定向】设置为允许</p>
  659. <p style="color:red;">如下图所示:</p>
  660. <img src="https://js.zhanyc.cn/img/ljts.jpg"/>
  661. </div>
  662. `,
  663. });
  664. if (!plugMain.pageData.ljtsIndexArr) {
  665. plugMain.pageData.ljtsIndexArr = []
  666. }
  667. plugMain.pageData.ljtsIndexArr.push(index)
  668. let url = checkUrlBeforeClose ? location.href : "";
  669. if (plugMain.pageData.closeTipsIndex != null) return;
  670. plugMain.pageData.closeTipsIndex = GM_addValueChangeListener(
  671. "closeLJTS",
  672. function (name, old_value, new_value, remote) {
  673. plugMain.pageData.ljtsIndexArr.forEach(item => {
  674. layer.close(item);
  675. })
  676. plugMain.pageData.ljtsIndexArr = []
  677. tipsAndClose && plugMain.tipsAndClose && plugMain.tipsAndClose(url);
  678. }
  679. );
  680. },
  681. tipsAndClose(checkUrl, timeout = 5000) {
  682. let mark = plugMain.now()
  683. plugMain.pageData.tipsAndCloseMark = mark
  684. plugMain.confirmRun("准备关闭当前页面,如果不想关闭请点击下面【取消执行】按钮", timeout).then((a) => {
  685. if (plugMain.pageData.tipsAndCloseMark != mark) {
  686. isDev && console.log("页面标识变更,取消关闭窗口");
  687. return
  688. }
  689. if (!checkUrl || location.href == checkUrl) window.close();
  690. });
  691. },
  692. closeWaitConfrimWin() {
  693. plugMain.setGMData("closeLJTS", plugMain.now());
  694. },
  695. removeArrEmpty(arr) {
  696. let res = [];
  697. arr.forEach((item) => {
  698. if (!!item && item.trim() != "") {
  699. res.push(item);
  700. }
  701. });
  702. return res;
  703. },
  704. confirmRun(msg = "脚本:3秒后执行下一步操作", time = 3000) {
  705. return new Promise((resolve, reject) => {
  706. let isRun = true;
  707. // clearTimeout(plugMain.pageData.confirmRunIndex);
  708. let confirmRunIndex =
  709. layer.open({
  710. type: '1',
  711. title: '脚本:是否继续执行?',
  712. closeBtn: 0,
  713. zIndex: plugMain.pageData.confirmRunZIndex++,
  714. btn: '取消执行',
  715. offset: "100px",
  716. content: `<div style="padding:20px;">${msg}</div>`,
  717. yes: function (index) {
  718. isRun = false;
  719. reject();
  720. layer.close(confirmRunIndex);
  721. }
  722. });
  723.  
  724. // layer.alert(
  725. // msg,
  726. // { icon: 3, title: "是否继续?", btn: ["取消执行"], offset: "100px" },
  727. // function (index) {
  728. // isRun = false;
  729. // reject();
  730. // layer.close(plugMain.pageData.confirmRunIndex);
  731. // }
  732. // );
  733. setTimeout(() => {
  734. layer.close(confirmRunIndex);
  735. resolve(true);
  736. }, time);
  737. });
  738. },
  739. waitTimeout(timeout) {
  740. return new Promise((resolve, reject) => {
  741. setTimeout(() => {
  742. resolve();
  743. }, timeout);
  744. });
  745. },
  746. waitOf(fun, interval = 1000, timeout = 30) {
  747. console.log("%c waitOf", "background:rgb(0,0,0);color:#fff", fun);
  748. return new Promise((resolve, reject) => {
  749. let _timeOut = timeout * 1000;
  750. try {
  751. if (fun()) {
  752. return resolve();
  753. }
  754. } catch (e) {
  755. console.error(e);
  756. }
  757. let index = setInterval(() => {
  758. try {
  759. if (timeout != -1) {
  760. _timeOut -= interval;
  761. if (_timeOut < 0) {
  762. clearInterval(index);
  763. return reject();
  764. }
  765. }
  766. if (fun()) {
  767. clearInterval(index);
  768. return resolve();
  769. }
  770. } catch (e) {
  771. console.error(e);
  772. }
  773. }, interval);
  774. });
  775. },
  776. getUrlParam(url, name) {
  777. if (arguments.length == 1) {
  778. name = url;
  779. url = window.location;
  780. }
  781. var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
  782. var r = url.search.substr(1).match(reg);
  783. if (r != null) return unescape(r[2]);
  784. return "";
  785. },
  786. objectToQueryString(obj) {
  787. var queryParams = [];
  788. for (var key in obj) {
  789. if (obj.hasOwnProperty(key)) {
  790. var value = obj[key];
  791. // 如果值为数组,则将其转换为多个参数
  792. if (Array.isArray(value)) {
  793. for (var i = 0; i < value.length; i++) {
  794. queryParams.push(
  795. encodeURIComponent(key) + "=" + encodeURIComponent(value[i])
  796. );
  797. }
  798. } else {
  799. queryParams.push(
  800. encodeURIComponent(key) + "=" + encodeURIComponent(value)
  801. );
  802. }
  803. }
  804. }
  805. return queryParams.join("&");
  806. },
  807. parseQueryString(url = window.location.href) {
  808. //url参数转对象
  809. url = !url ? window.location.href : url;
  810. if (url.indexOf("?") === -1) {
  811. return {};
  812. }
  813. let search =
  814. url[0] === "?"
  815. ? url.substr(1)
  816. : url.substring(url.lastIndexOf("?") + 1);
  817. if (search === "") {
  818. return {};
  819. }
  820. search = search.split("&");
  821. let query = {};
  822. for (let i = 0; i < search.length; i++) {
  823. let pair = search[i].split("=");
  824. query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
  825. }
  826. return query;
  827. },
  828. getAttrName(el, key) {
  829. if (el.jquery) el = el.get(0);
  830. let propName = Object.keys(el).find((a) => a.startsWith(key));
  831. return propName;
  832. },
  833. getAttrNameList(el, key) {
  834. if (el.jquery) el = el.get(0);
  835. let propName = Object.keys(el).filter((a) => a.startsWith(key));
  836. return propName;
  837. },
  838. alertMsg(msg, timeout = 0) {
  839. layer.open(
  840. {
  841. type: "1",
  842. content: `<div style="padding:14px;">${msg}</div>`,
  843. title: "脚本提示" + (timeout == 0 ? '' : `(${(timeout / 1000).toFixed(2)}秒后自动关闭})`),
  844. offset: "100px",
  845. time: timeout,
  846. btn: "关闭"
  847. })
  848. },
  849. tipsMsg(msg, timeout = 3000) {
  850. layer.msg(msg, { offset: "100px", time: timeout });
  851. },
  852. confirmMsg(msg = "请确认", option = {}) {
  853. let defConfig = {
  854. title: "脚本提示", btn: ["确定", "关闭"],
  855. offset: "100px",
  856. area: ["500px"],
  857. shade: 0.3,
  858. fun1(index) { layer.close(index) },
  859. fun2() { },
  860. fun3() { }
  861. }
  862. Object.assign(defConfig, option)
  863. layer.open(
  864. {
  865. type: "1",
  866. content: `<div style="padding:14px;">${msg}</div>`,
  867. title: option.title,
  868. offset: defConfig.offset,
  869. area: defConfig.area,
  870. btn: defConfig.btn,
  871. shade: defConfig.shade,
  872. yes: defConfig.fun1,
  873. btn2: defConfig.fun2,
  874. btn3: defConfig.fun3
  875. })
  876. },
  877. matchUrl(urlKeyword, mode = "like", url = location.href) {
  878. let res = false;
  879. switch (mode) {
  880. case "eq":
  881. res = urlKeyword == url;
  882. break;
  883. case "like":
  884. res = url.indexOf(urlKeyword) != -1;
  885. break;
  886. case "left":
  887. res = url.startsWith(urlKeyword);
  888. break;
  889. case "right":
  890. res = url.endsWith(urlKeyword);
  891. break;
  892. }
  893. return res;
  894. },
  895. getPromiseWithAbort(p) {
  896. let obj = {};
  897. let p1 = new Promise(function (resolve, reject) {
  898. obj.abort = reject;
  899. });
  900. obj.promise = Promise.race([p, p1]);
  901. return obj;
  902. },
  903. page_yhwelcome() {
  904. console.log("%c page_yhwelcome", "background:rgb(255,0,0);color:#fff");
  905. var token = sessionStorage.getItem("token");
  906. this.setGMData("token", token);
  907. this.setGMData("login", { login: true, time: plugMain.now() });
  908. },
  909. createWorker(f) {
  910. var blob = new Blob(["(" + f + ")()"]);
  911. var url = window.URL.createObjectURL(blob);
  912. var worker = new Worker(url);
  913. return worker;
  914. },
  915. createIntervalWorker(callback, time) {
  916. var pollingWorker = plugMain.createWorker(`async function (e) {
  917. setInterval(async function () {
  918. this.postMessage(null)
  919. }, ${time})
  920. }`);
  921. pollingWorker.onmessage = callback;
  922. return pollingWorker;
  923. },
  924. createTimeoutWorker(callback, time) {
  925. var pollingWorker = plugMain.createWorker(`async function (e) {
  926. setTimeout(async function () {
  927. this.postMessage(null)
  928. }, ${time})
  929. }`);
  930. pollingWorker.onmessage = function () {
  931. callback();
  932. plugMain.stopWorker(pollingWorker);
  933. };
  934. return pollingWorker;
  935. },
  936. stopWorker(vm) {
  937. try {
  938. vm && vm.terminate();
  939. } catch (err) {
  940. console.log(err);
  941. }
  942. },
  943. getGMData(item, def) {
  944. return GM_getValue(item, def);
  945. },
  946. setGMData(item, val) {
  947. return GM_setValue(item, val);
  948. },
  949. delGMData(item, val) {
  950. return GM_deleteValue(item);
  951. },
  952. generateRandomString(length) {
  953. const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  954. let randomString = "";
  955.  
  956. for (let i = 0; i < length; i++) {
  957. const randomIndex = Math.floor(Math.random() * charset.length);
  958. randomString += charset.charAt(randomIndex);
  959. }
  960.  
  961. return randomString;
  962. },
  963. timeSecondsFormat(seconds) {
  964. // 确保秒数为非负整数
  965. seconds = Math.floor(Math.abs(seconds));
  966.  
  967. // 计算小时、分钟和秒
  968. var hours = Math.floor(seconds / 3600);
  969. var minutes = Math.floor((seconds % 3600) / 60);
  970. var secs = seconds % 60;
  971.  
  972. // 如果小时、分钟或秒小于10,则在其前面添加一个0
  973. hours = (hours < 10) ? "0" + hours : hours;
  974. minutes = (minutes < 10) ? "0" + minutes : minutes;
  975. secs = (secs < 10) ? "0" + secs : secs;
  976.  
  977. // 返回格式化的时间字符串
  978. return hours + ":" + minutes + ":" + secs;
  979. },
  980. // 时间转换成秒
  981. timeStringToSeconds(timeString) {
  982. if (!timeString.includes("时")) {
  983. timeString = '0时' + timeString
  984. }
  985. timeString = timeString
  986. .replace("小时", ":")
  987. .replace("时", ":")
  988. .replace("分钟", ":")
  989. .replace("分", ":")
  990. .replace("秒", "");
  991. if (timeString.endsWith(":")) {
  992. timeString = timeString.substring(0, timeString.length - 1);
  993. }
  994. const parts = timeString.split(":");
  995. if (parts.length !== 3) {
  996. if (parts.length == 2) {
  997. parts.push(0);
  998. } else {
  999. throw new Error("Invalid time string format. Expected 'hh:mm:ss'.");
  1000. }
  1001. }
  1002.  
  1003. const hours = parseInt(parts[0]);
  1004. const minutes = parseInt(parts[1]);
  1005. const seconds = parseInt(parts[2]);
  1006.  
  1007. if (isNaN(hours) || isNaN(minutes) || isNaN(seconds)) {
  1008. throw new Error("Invalid time string format. Expected numeric values.");
  1009. }
  1010.  
  1011. return hours * 3600 + minutes * 60 + seconds;
  1012. },
  1013. getLocalData(item, def) {
  1014. var val = localStorage.getItem(item);
  1015. if (val == null) return def;
  1016.  
  1017. return JSON.parse(val).val;
  1018. },
  1019. setLocalData(item, val) {
  1020. return localStorage.setItem(item, JSON.stringify({ val: val }));
  1021. },
  1022. setFormVal(selector, formVal) {
  1023. $.each(formVal, function (key, val) {
  1024. let $el = $(selector).find(`[name="${key}"]`);
  1025. // console.log($el);
  1026. // console.log(key, $el.eq(0).attr("type"));
  1027. if ($el.length == 0) return true;
  1028. else if ($el.length == 1) {
  1029. let type = $el.eq(0).attr("type");
  1030. switch (type) {
  1031. case "radio":
  1032. case "checkbox":
  1033. if ($el.val() == val) $el.prop("checked", true);
  1034. break;
  1035. default:
  1036. $el.val(val);
  1037. break;
  1038. }
  1039. } else {
  1040. $el.each((i, el) => {
  1041. // console.log($(el), $(el).val());
  1042. if (val.includes($(el).val())) {
  1043. $(el).prop("checked", true);
  1044. }
  1045. });
  1046. }
  1047. });
  1048. },
  1049. getFormVal(selector) {
  1050. let formVal = {};
  1051. var arr = $(selector).serializeArray();
  1052. let tempArr = [];
  1053. $.each(arr, function () {
  1054. console.log(this);
  1055. if (!tempArr.includes(this.name)) {
  1056. tempArr.push(this.name);
  1057. formVal[this.name] = this.value;
  1058. } else {
  1059. let oldVal = formVal[this.name];
  1060. if (Array.isArray(oldVal)) {
  1061. formVal[this.name].push(this.value);
  1062. } else {
  1063. formVal[this.name] = [formVal[this.name], this.value];
  1064. }
  1065. }
  1066. });
  1067. return formVal;
  1068. },
  1069. now() {
  1070. return new Date().getTime();
  1071. },
  1072. getElByText(query, text, mode = "eq", visible = true) {
  1073. let $el = null;
  1074. $(query).each((i, el) => {
  1075. if (visible && !$(el).is(":visible")) {
  1076. return true;
  1077. }
  1078. if (mode == "eq" && $(el).text().trim() == text) {
  1079. $el = $(el);
  1080. return false;
  1081. } else if (
  1082. mode == "startsWith" &&
  1083. $(el).text().trim().startsWith(text)
  1084. ) {
  1085. $el = $(el);
  1086. return false;
  1087. } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) {
  1088. $el = $(el);
  1089. return false;
  1090. }
  1091. });
  1092. return $el;
  1093. },
  1094. getElListByText(query, text, mode = "eq", visible = true) {
  1095. let arr = [];
  1096. $(query).each((i, el) => {
  1097. if (visible && !$(query).is(":visible")) {
  1098. return true;
  1099. }
  1100. if (mode == "eq" && $(el).text().trim() == text) {
  1101. arr.push($(el));
  1102. } else if (
  1103. mode == "startsWith" &&
  1104. $(el).text().trim().startsWith(text)
  1105. ) {
  1106. arr.push($(el));
  1107. } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) {
  1108. arr.push($(el));
  1109. }
  1110. });
  1111. return arr;
  1112. },
  1113. random(min, max) {
  1114. // 生成随机数范围
  1115. if (arguments.length === 2) {
  1116. return Math.floor(min + Math.random() * (max + 1 - min));
  1117. } else {
  1118. return null;
  1119. }
  1120. },
  1121. downloadTxt(filename, text) {
  1122. var element = document.createElement("a");
  1123. element.setAttribute(
  1124. "href",
  1125. "data:text/plain;charset=utf-8," + encodeURIComponent(text)
  1126. );
  1127. element.setAttribute("download", filename);
  1128.  
  1129. element.style.display = "none";
  1130. document.body.appendChild(element);
  1131.  
  1132. element.click();
  1133.  
  1134. document.body.removeChild(element);
  1135. },
  1136. dateFormat(date = new Date(), fmt = "yyyy-MM-dd HH:mm") {
  1137. let ret;
  1138. if (typeof date === "number") date = new Date(date);
  1139. const opt = {
  1140. "y+": date.getFullYear().toString(), // 年
  1141. "M+": (date.getMonth() + 1).toString(), // 月
  1142. "d+": date.getDate().toString(), // 日
  1143. "H+": date.getHours().toString(), // 时
  1144. "m+": date.getMinutes().toString(), // 分
  1145. "s+": date.getSeconds().toString(), // 秒
  1146. // 有其他格式化字符需求可以继续添加,必须转化成字符串
  1147. };
  1148. for (let k in opt) {
  1149. ret = new RegExp("(" + k + ")").exec(fmt);
  1150. if (ret) {
  1151. fmt = fmt.replace(
  1152. ret[1],
  1153. ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
  1154. );
  1155. }
  1156. }
  1157. return fmt;
  1158. },
  1159. });
  1160. setTimeout(() => {
  1161. if (!unsafeWindow.zfk) {
  1162. plugMain.init();
  1163. } else {
  1164. console.log('skip init');
  1165. }
  1166. }, 3000);
  1167. if (!unsafeWindow.plugMain) unsafeWindow.plugMain = plugMain;
  1168. })();