// ==UserScript== // @name 超星学习通课件下载 // @namespace https://docs.scriptcat.org/ // @version 1.1 // @description 下载超星学习通课件原文件 // @match *://*.chaoxing.com/* // @match *://pan-yz.chaoxing.com/* // @icon http://pan-yz.chaoxing.com/favicon.ico // @run-at document-end // @license MIT // @noframes // ==/UserScript== (() => { const ID = 'cx-dl', GAP = 600, DELAY = 800, MAX = 10, DEPTH = 5; const isTarget = () => ['/mycourse/studentstudy', '/mooc-ans/knowledge/cards', 'pan-yz.chaoxing.com/screen/file_'].some(p => location.href.includes(p)); const scan = (doc = document, d = 0) => { if (d > DEPTH) return []; const r = []; try { const w = doc.defaultView || window; if (w?.fileinfo?.download) r.push(w.fileinfo); } catch {/**/} for (const f of doc.getElementsByTagName('iframe')) try { const w = f.contentWindow; if (w?.fileinfo?.download) r.push(w.fileinfo); if (w?.document) r.push(...scan(w.document, d + 1)); } catch {/**/} return r; }; const enableDrag = (el, h) => { let sx, sy, ol, ot; const mv = e => { e.preventDefault(); el.style.left = Math.max(0, Math.min(ol + e.clientX - sx, innerWidth - el.offsetWidth)) + 'px'; el.style.top = Math.max(0, Math.min(ot + e.clientY - sy, innerHeight - el.offsetHeight)) + 'px'; }; const up = e => { h.releasePointerCapture(e.pointerId); h.removeEventListener('pointermove', mv); h.removeEventListener('pointerup', up); h.removeEventListener('pointercancel', up); }; h.addEventListener('pointerdown', e => { e.preventDefault(); sx = e.clientX; sy = e.clientY; const r = el.getBoundingClientRect(); ol = r.left; ot = r.top; el.style.cssText += ';transition:none;right:auto;bottom:auto'; el.style.left = ol + 'px'; el.style.top = ot + 'px'; h.setPointerCapture(e.pointerId); h.addEventListener('pointermove', mv); h.addEventListener('pointerup', up); h.addEventListener('pointercancel', up); }); }; const render = list => { document.getElementById(ID)?.remove(); const seen = new Set(), files = list.filter(f => f.download && !seen.has(f.download) && seen.add(f.download)); if (!files.length) return; const el = document.createElement('div'); el.id = ID; el.innerHTML = `
${files.map((f, i) => `⇩ 下载资源 ${i + 1}`).join('')}
`; enableDrag(el, el.querySelector('.h')); document.body.appendChild(el); }; let timer; const start = () => { clearTimeout(timer); let n = 0; const tick = () => { const r = scan(); if (r.length) render(r); else if (++n < MAX) timer = setTimeout(tick, GAP); }; timer = setTimeout(tick, DELAY); }; const reset = () => { document.getElementById(ID)?.remove(); clearTimeout(timer); start(); }; if (!isTarget()) return; new MutationObserver(ml => { for (const m of ml) { if (m.target.id === ID) return; if (m.type === 'attributes' && m.attributeName === 'src' && m.target.nodeName === 'IFRAME') return reset(); if (m.addedNodes.length && [...m.addedNodes].some(n => n.nodeName === 'IFRAME' || [...(n.children || [])].some(c => c.nodeName === 'IFRAME'))) return reset(); } }).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] }); reset(); })();