// ==UserScript== // @name 网易云课堂/腾讯课堂课时计算 // @namespace dawsonenjoy_course_count // @version 0.0.1 // @description 右边标题栏显示当前课程总课时(如果没有显示成功,请点击标题栏刷新) // @author dawsonenjoy // @homepageURL https://github.com/dawsonenjoy/tampermonkey_script // @match https://study.163.com/course/* // @match https://ke.qq.com/course/* // @run-at document-body // @grant none // @downloadURL https://update.greasyfork.icu/scripts/408857/%E7%BD%91%E6%98%93%E4%BA%91%E8%AF%BE%E5%A0%82%E8%85%BE%E8%AE%AF%E8%AF%BE%E5%A0%82%E8%AF%BE%E6%97%B6%E8%AE%A1%E7%AE%97.user.js // @updateURL https://update.greasyfork.icu/scripts/408857/%E7%BD%91%E6%98%93%E4%BA%91%E8%AF%BE%E5%A0%82%E8%85%BE%E8%AE%AF%E8%AF%BE%E5%A0%82%E8%AF%BE%E6%97%B6%E8%AE%A1%E7%AE%97.meta.js // ==/UserScript== (function () { "use strict"; // Your code here... const config = { // 页面相关配置,可自定义 pages: { // 相关配置参数: // nodes: 课程节点, // preprocess: 节点数据处理方式, // watcherNode: 监听节点选择器, // watcherConfig: 监听配置, // pageStyle: 对应页面样式, // ---------------------------------------------------------- // 腾讯课堂 qq: { nodes: ".tt-suffix", preprocess: node => parseFloat(node.innerText.slice(1, -3)) * 60 || 0, watcherNode: "#js_dir_tab", watcherConfig: { attributes: true } }, // 网易云课堂 "study.163": { nodes: ".kstime", preprocess: node => TimeUtils.timeToSecond(node.innerText || 0), watcherNode: "#j-chapter-list", watcherConfig: { childList: true } } // ---------------------------------------------------------- }, // 默认配置 defaultConfig: { nodes: "", watcherNode: "", watcherConfig: {}, preprocess: node => parseFloat(node.innerText) || 0, pageStyle: `` }, // 获取配置属性 getConfig(attr) { return this.pageConfig[attr] || this.defaultConfig[attr]; }, // 属性缓存 getCacheAttr(attr, getMethod) { if (this[`_${attr}`] !== undefined) return this[`_${attr}`]; this[`_${attr}`] = getMethod instanceof Function && getMethod(); return this[`_${attr}`]; }, // 获取页面配置 get pageConfig() { return this.getCacheAttr("pageConfig", () => { for (let page in this.pages) { if (location.href.includes(page)) return this.pages[page]; } return this.defaultConfig; }); }, get nodes() { let nodes = this.getConfig("nodes"); if (!nodes) return []; return Array.from(document.querySelectorAll(nodes)); }, get preprocess() { return this.getConfig("preprocess"); }, get watcherNode() { let watcherNode = this.getConfig("watcherNode"); if (!watcherNode) return ""; return document.querySelector(watcherNode); }, get watcherConfig() { return this.getConfig("watcherConfig"); }, get root() { return this.getCacheAttr("root", () => document.querySelector(".time-bar") ); }, get body() { return this.getCacheAttr("body", () => document.querySelector(".time-body") ); }, get close() { return this.getCacheAttr("close", () => document.querySelector(".time-close") ); } }; // 展示的标题栏 const timeBar = { // 所有要生成的元素配置 element: { styleElement: { tag: "style", innerHTML: ` div.time-bar { position: fixed; top: 100px; left: 0px; height: 50px; width: 230px; display: flex; justify-content: center; align-items: center; background: #303541 !important; color: white; border-radius: 3px; font-size: 1.5em; cursor: pointer; z-index: 999; } div.time-bar:hover { opacity: 0.8; } .time-body { background: inherit; padding: 0; } .time-close { position: absolute; top: 0; right: 2px; margin-top: -2px; color: white; } .time-close:hover { background: rgba(255, 255, 255, .3) } `, parent: "head" }, divElement: { tag: "div", className: "time-bar", title: "点击刷新", innerHTML: `