您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
爬取课件url
当前为
// ==UserScript== // @name 小雅爬爬爬 // @match *://ccnu.ai-augmented.com/* // @grant none // @description 爬取课件url // @license MIT // @author Yi // @version 1.1.0 // @namespace https://gf.qytechs.cn/users/1268039 // ==/UserScript== (function() { 'use strict'; // 动态导入dotlottie-player模块 const script = document.createElement('script'); script.src = 'https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs'; script.type = 'module'; // 指定导入类型为module document.head.appendChild(script); // 将脚本添加到<head>中 // 监听脚本的加载事件以确认导入成功 script.onload = () => { console.log('dotlottie-player模块已导入成功!'); // 在此处添加脚本加载后需要执行的任何代码 }; // 监听错误事件以确认导入失败 script.onerror = () => { console.error('无法导入dotlottie-player模块!'); }; })(); let course_resources; // 附件下载实现细节 function parseContent() { console.oldLog("::parseContent"); var download_url = 'https://ccnu.ai-augmented.com/api/jx-oresource/cloud/file_url/'; var download_list = document.getElementById("download_list"); download_list.innerHTML = '<h3 style="color:#fcbb34; font-weight:bold;">课程附件清单</h3>'; for (let i in course_resources) { let file_name = course_resources[i].name; if (course_resources[i].mimetype) { fetch(download_url + course_resources[i].quote_id).then(function(response) { return response.json(); }).then(function(data) { if (data.success) { let file_url = data.data.url; // 创建一个包含链接和勾选框的容器 var file_container = document.createElement('div'); file_container.style.display = 'flex'; file_container.style.alignItems = 'center'; // 创建勾选框 var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.style.marginRight = '10px'; checkbox.setAttribute('data-visible', 'true'); // 默认设置为可见 // 创建链接元素 var file_info = document.createElement('a'); file_info.innerHTML = file_name; file_info.href = file_url; file_info.target = "_blank"; file_info.className = 'link-style'; // 应用初始样式 file_info.style.textDecoration = 'none'; // 去掉下划线 file_info.addEventListener('mouseover', () => { file_info.style.textDecoration = 'underline'; file_info.style.color = '#000'; file_info.style.fontWeight = "bold"; }); file_info.addEventListener('mouseout', function() { file_info.style.textDecoration = 'none'; file_info.style.color = ''; }); // 将勾选框和链接添加到容器中 file_container.appendChild(checkbox); file_container.appendChild(file_info); file_container.style.borderBottom = '1px solid #eee'; // 每个项目间画一条分隔线 file_container.style.fontWeight = "bold"; file_container.style.padding = '5px 10px'; file_container.style.justifyContent = 'space-between'; file_container.style.alignItems = 'center'; file_container.style.display = 'flex'; console.oldLog('::parse', file_name, file_url); // 将包含勾选框和链接的容器添加到下载列表 download_list.append(file_container); } }).catch(function(e) { console.oldLog('!!error', e); }); } } } // 在文档中创建一个容器来放置所有下载进度条 let downloadsContainer = document.getElementById('downloadsContainer'); if (!downloadsContainer) { downloadsContainer = document.createElement('div'); downloadsContainer.id = 'downloadsContainer'; downloadsContainer.style.position = 'fixed'; downloadsContainer.style.bottom = '10px'; downloadsContainer.style.left = '50%'; downloadsContainer.style.transform = 'translateX(-50%)'; downloadsContainer.style.zIndex = '9999'; downloadsContainer.style.backgroundColor = '#FFF3E0'; downloadsContainer.style.boxShadow = '0 4px 6px rgba(255, 165, 0, 0.3)'; downloadsContainer.style.borderRadius = '8px'; downloadsContainer.style.padding = '15px'; downloadsContainer.style.width = 'auto'; downloadsContainer.style.maxWidth = '500px'; downloadsContainer.style.boxSizing = 'border-box'; downloadsContainer.style.margin = '0 auto'; downloadsContainer.style.border = '1px solid #FFD180'; // 设置最大高度限制和溢出滚动 downloadsContainer.style.maxHeight = '400px'; // 根据实际需求调整此值 downloadsContainer.style.overflowY = 'auto'; // 当内容超出容器时显示垂直滚动条 document.body.appendChild(downloadsContainer); // 创建 dotlottie-player 容器 let lottieContainer = document.createElement('div'); lottieContainer.style.position = 'absolute'; lottieContainer.style.top = '0'; lottieContainer.style.left = '0'; lottieContainer.style.width = '100%'; lottieContainer.style.height = '100%'; lottieContainer.style.zIndex = '-1'; // 确保 lottie 在底层 lottieContainer.innerHTML = ` <dotlottie-player src="https://lottie.host/21dfc4c5-2d42-4f18-b67b-e3c8e50a2ce5/YYdHUeyfW2.json" background="transparent" speed="1" style="width: 100%; height: 100%;" loop autoplay> </dotlottie-player>`; // 将 dotlottie-player 容器添加到 downloadsContainer 的顶部 downloadsContainer.prepend(lottieContainer); } // 确保 downloadsContainer 被添加到文档中 if (!document.body.contains(downloadsContainer)) { document.body.appendChild(downloadsContainer); } // 初始化拖动功能的变量 let isDragging = false; let dragStartX = 0; let dragStartY = 0; // 函数:开始拖动 function dragStart(e) { // 记录初始拖动位置 isDragging = true; dragStartX = e.clientX - downloadsContainer.getBoundingClientRect().left; dragStartY = e.clientY - downloadsContainer.getBoundingClientRect().top; document.addEventListener('mousemove', dragMove); document.addEventListener('mouseup', dragEnd); } // 函数:拖动时调用 function dragMove(e) { if (!isDragging) return; // 如果不是拖动状态,则退出 // 计算容器新的位置 let leftPos = e.clientX - dragStartX; let topPos = e.clientY - dragStartY; // 更新容器位置 downloadsContainer.style.left = `${leftPos}px`; downloadsContainer.style.top = `${topPos}px`; downloadsContainer.style.bottom = 'auto'; // 当开始拖动时,移除bottom样式以允许自由定位 downloadsContainer.style.transform = 'none'; // 移除transform样式,因为已经改为绝对定位 } // 函数:停止拖动时调用 function dragEnd() { // 更新状态 isDragging = false; document.removeEventListener('mousemove', dragMove); document.removeEventListener('mouseup', dragEnd); } // 添加鼠标按下时的事件监听器来初始化拖拽 downloadsContainer.addEventListener('mousedown', dragStart); function updateDownloadsContainerVisibility() { downloadsContainer.style.display = downloadsContainer.children.length > 0 ? 'block' : 'none'; } function courseDownload(file_url, file_name) { const downloadsContainer = document.getElementById('downloadsContainer'); downloadsContainer.style.display = 'block'; // 创建进度条相关元素。 let progressText = document.createElement('span'); let progressBar = document.createElement('div'); let progressBarContainer = document.createElement('div'); let progressContainer = document.createElement('div'); // 设置文本。 progressText.innerText = `正在下载: ${file_name}`; progressText.style.color = '#FF9800'; progressText.style.fontWeight = 'bold'; progressText.style.fontSize = '16px'; progressText.style.fontFamily = 'Microsoft YaHei'; progressText.style.textShadow = '1px 1px 2px rgba(0, 0, 0, 0.1)'; progressText.style.padding = '5px 0'; progressText.style.borderRadius = '4px'; // 设置progressBar。 progressBar.style.height = '18px'; progressBar.style.width = '0%'; progressBar.style.borderRadius = '8px'; progressBar.className = 'progressBar' // 设置progressBarContainer。 progressBarContainer.style.background = '#E0E0E0'; progressBarContainer.style.borderRadius = '8px'; progressBarContainer.style.height = '18px'; progressBarContainer.style.width = '100%'; progressBarContainer.style.overflow = 'hidden'; progressBarContainer.appendChild(progressBar); // 设置 progressContainer。 progressContainer.style.display = 'flex'; progressContainer.style.flexDirection = 'column'; // 子元素垂直排列 progressContainer.style.alignItems = 'center'; // 子元素在交叉轴上居中对齐 progressContainer.style.justifyContent = 'space-around'; // 子元素沿着主轴均匀分布 progressContainer.appendChild(progressText); // 创建一个用来显示下载百分比的span元素 let progressPercentText = document.createElement('span'); progressPercentText.style.fontFamily = 'Arial Rounded MT Bold, Helvetica Rounded, Arial, sans-serif'; progressPercentText.style.fontSize = '16px'; progressPercentText.style.marginLeft = '10px'; // 与进度条保持一定距离 progressPercentText.style.position = 'absolute'; progressPercentText.style.left = '0'; progressPercentText.style.top = '0'; progressPercentText.style.width = '100%'; progressPercentText.style.textAlign = 'center'; progressPercentText.style.lineHeight = '18px'; progressPercentText.style.zIndex = '1'; // 调整字体粗细 progressPercentText.style.fontWeight = 'bold'; // 设置 progressBarContainer 的样式并添加到 progressContainer progressContainer.appendChild(progressBarContainer); // 插入用于显示百分比的 DOM 元素到 progressContainer progressBarContainer.style.position = 'relative'; // 相对定位,以便内部的百分比文本能正确定位 progressBarContainer.appendChild(progressPercentText); // 添加 progressContainer 到 downloadsContainer downloadsContainer.appendChild(progressContainer); const controller = new AbortController(); const signal = controller.signal; window.abortControllers = window.abortControllers || {}; window.abortControllers[file_name] = controller; // 添加文件大小和停止按钮到一个新的横向排列的容器 let controlContainer = document.createElement('div'); controlContainer.style.display = 'flex'; controlContainer.style.justifyContent = 'space-between'; // 在主轴线上实现两端对齐 controlContainer.style.alignItems = 'center'; // 在交叉轴上实现居中对齐 controlContainer.style.width = '100%'; // 确保容器宽度与进度条相匹配 // 创建文件大小显示元素 let fileSizeSpan = document.createElement('span'); // 设置样式为微软雅黑和圆润 fileSizeSpan.style.fontFamily = 'Microsoft YaHei'; fileSizeSpan.style.fontSize = '14px'; fileSizeSpan.style.marginRight = 'auto'; fileSizeSpan.style.fontWeight = 'bold'; let stopButton = document.createElement('button'); stopButton.textContent = '停止'; stopButton.style.padding = '5px 10px'; stopButton.style.border = 'none'; stopButton.style.borderRadius = '5px'; stopButton.style.backgroundColor = '#FF4136'; stopButton.style.color = 'white'; stopButton.style.cursor = 'pointer'; stopButton.style.fontSize = '14px'; stopButton.style.fontWeight = 'bold'; stopButton.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)'; stopButton.style.transition = 'transform 0.3s ease'; stopButton.style.marginTop = '10px'; // 增加顶部外边距以调整与进度条的距离 stopButton.onmouseover = function() { stopButton.style.transform = 'scale(1.2)'; }; stopButton.onmouseout = function() { stopButton.style.transform = 'scale(1)'; }; stopButton.onclick = function() { console.log(file_name + ' 的下载已经停止了'); controller.abort(); progressContainer.remove(); delete window.abortControllers[file_name]; updateDownloadsContainerVisibility(); }; controlContainer.appendChild(fileSizeSpan); controlContainer.appendChild(stopButton); progressContainer.appendChild(controlContainer); let styleElement = document.getElementById('progress-bar-styles'); if (!styleElement) { let styles = document.createElement('style'); styles.id = 'progress-bar-styles'; styles.textContent = ` .progressBar { background-color: #FF9800; background-image: repeating-linear-gradient( 45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent ); background-size: 40px 40px; animation: moveBackground 2s linear infinite; } @keyframes moveBackground { from { background-position: 0 0; } to { background-position: 40px 0; } } `; document.head.appendChild(styles); } function bytesToSize(bytes) { const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 Byte'; const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i]; } // 使用fetch API开始下载文件 fetch(file_url, { signal }) .then(response => { // 获取文件大小信息 const contentLength = response.headers.get('Content-Length'); if (contentLength) { // 更新文件大小显示 const fileSize = bytesToSize(contentLength); fileSizeSpan.innerText = `文件大小: ${fileSize}`; } else { // 如果无法获取文件大小,则显示消息 fileSizeSpan.innerText = `无法获取文件大小`; } const reader = response.body.getReader(); let receivedBytes = 0; let chunks = []; reader.read().then(function processResult(result) { if (result.done) { // 下载完成后的处理 const blob = new Blob(chunks, { type: 'application/octet-stream' }); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = file_name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); downloadsContainer.removeChild(progressContainer); updateDownloadsContainerVisibility(); // 确保定义了这个函数来更新下载容器元素的显示 return; } // 存储接收到的数据块 chunks.push(result.value); receivedBytes += result.value.length; // 计算下载的百分比并更新UI let percentComplete = (receivedBytes / contentLength) * 100; progressBar.style.width = `${percentComplete.toFixed(2)}%`; // 更新进度条的宽度 progressPercentText.innerText = `${percentComplete.toFixed(2)}%`; // 读取下一部分数据 reader.read().then(processResult); }) .catch(e => { // 下载失败或被中止时的处理 if (e.name === 'AbortError') { console.error(`${file_name} 的下载被用户取消了`); } else { console.error(e); } progressContainer.remove(); updateDownloadsContainerVisibility(); // 确保定义了这个函数来更新下载容器元素的显示 }); }); } window.showList = function () { var download_list = document.getElementById("download_list"); if (!document.getElementById("lottie-animation-container")) { var lottieContainer = document.createElement("div"); lottieContainer.id = "lottie-animation-container"; lottieContainer.innerHTML = ` <dotlottie-player src="https://lottie.host/f6cfdc36-5c9a-4dac-bb71-149cdf2e7d92/VRIhn9vXE5.json" background="transparent" speed="1" style="width: 300px; height: 300px; transform: scaleX(-1);" loop autoplay> </dotlottie-player>`; // 使用 transform: scaleX(-1); 实现水平翻转 lottieContainer.style.position = "absolute"; lottieContainer.style.top = "50%"; lottieContainer.style.right = "0"; lottieContainer.style.transform = "translateY(-50%)"; // 垂直居中 lottieContainer.style.zIndex = "-1"; // 确保它在内容之后作为背景 download_list.style.position = "relative"; // 确保下载列表具有相对位置 download_list.appendChild(lottieContainer); // 将动画容器插入为子元素 } // 创建或获取容器,用于并排放置搜索框和快速筛选下拉框 var container = document.getElementById("searchAndFilterContainer"); if (!container) { container = document.createElement("div"); container.id = "searchAndFilterContainer"; container.style.display = "flex"; // 应用 Flexbox 布局 container.style.marginBottom = '10px'; // 添加一点底部外边距 download_list.prepend(container); // 将容器添加到下载列表的最前面 } // 检查是否已经存在搜索框 var searchInput = document.getElementById("searchInput"); if (!searchInput) { // 如果不存在,则创建搜索框 searchInput = document.createElement("input"); searchInput.type = "text"; searchInput.placeholder = "搜索文件名"; searchInput.id = "searchInput"; searchInput.style.padding = '5px'; searchInput.style.marginRight = '10px'; searchInput.style.border = '1px solid #ddd'; searchInput.style.borderRadius = '4px'; searchInput.addEventListener("input", function () { filterList(this.value); }); container.appendChild(searchInput); // 将搜索框添加到容器中 } var quickFilterSelect = document.getElementById("quickFilterSelect"); if (!quickFilterSelect) { // 如果还没有快速筛选下拉框,则创建 quickFilterSelect = document.createElement("select"); quickFilterSelect.id = "quickFilterSelect"; quickFilterSelect.style.padding = '5px'; quickFilterSelect.style.marginRight = '10px'; quickFilterSelect.style.border = '1px solid #ddd'; quickFilterSelect.style.borderRadius = '4px'; window.quickFilters.forEach(function (filter) { var option = document.createElement("option"); option.value = filter.value; option.text = filter.label; quickFilterSelect.appendChild(option); }); quickFilterSelect.addEventListener("change", function () { filterListByCategory(this.value); }); container.appendChild(quickFilterSelect); // 将快速筛选下拉框添加到容器中 } // 检查是否已存在全选复选框 var existingSelectAllCheckbox = document.getElementById("selectAllCheckbox"); if (!existingSelectAllCheckbox) { // 创建全选复选框 var selectAllCheckbox = document.createElement('input'); selectAllCheckbox.type = 'checkbox'; selectAllCheckbox.id = 'selectAllCheckbox'; selectAllCheckbox.style.marginRight = '10px'; var selectAllLabel = document.createElement('label'); selectAllLabel.htmlFor = 'selectAllCheckbox'; selectAllLabel.textContent = '全选'; selectAllLabel.style.userSelect = 'none'; // 防止点击标签时选中文字 var checkboxContainer = document.createElement('div'); checkboxContainer.appendChild(selectAllCheckbox); checkboxContainer.appendChild(selectAllLabel); download_list.prepend(checkboxContainer); checkboxContainer.style.display = 'flex'; checkboxContainer.style.alignItems = 'center'; checkboxContainer.style.justifyContent = 'space-between'; checkboxContainer.style.padding = '5px 10px'; checkboxContainer.style.borderBottom = '2px solid #fcbb34'; // 用主题颜色画分隔线 checkboxContainer.style.marginBottom = '10px'; // 给全选复选框添加事件监听器,当改变时,全选/取消全选所有当前可见的文件 selectAllCheckbox.addEventListener('change', function() { var checkboxes = document.querySelectorAll("#download_list input[type='checkbox']:not(#selectAllCheckbox)"); checkboxes.forEach(function(checkbox) { if (checkbox.getAttribute('data-visible') === 'true') { checkbox.checked = selectAllCheckbox.checked; // 手动触发 change 事件 var event = new Event('change', { 'bubbles': true, // 使事件冒泡 'cancelable': true // 使事件可以被取消 }); checkbox.dispatchEvent(event); } }); }); } if (download_list.style.display == "none") { download_list.style.display = "flex"; download_list.style.overflowY = "auto"; // 添加垂直滚动条 download_list.style.backgroundColor = "#ffffff"; download_list.style.maxHeight = "300px"; // 设置最大高度,根据需要调整 } else { download_list.style.display = "none"; } // 检查是否已经创建了批量下载按钮 var existingbulkDownloadButton = document.getElementById("bulkDownloadButton"); if (!existingbulkDownloadButton) { // 检查是否已经创建了批量下载按钮 var existingBulkDownloadButton = document.getElementById("bulkDownloadButton"); if (!existingBulkDownloadButton) { // 添加批量下载按钮 window.bulkDownloadButton = document.createElement('button'); window.bulkDownloadButton.innerHTML = '批量下载'; window.bulkDownloadButton.id = "bulkDownloadButton"; window.bulkDownloadButton.title = '点击下载所选文件'; // 添加提示文本 window.bulkDownloadButton.style = ` position: fixed; top: 20px; right: 20px; background-color: #fcbb34; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.2); transition: background-color 0.3s, transform 0.3s; `; window.bulkDownloadButton.addEventListener('mouseover', function() { this.style.transform = 'scale(1.05)'; this.style.backgroundColor = '#ffd564'; }); window.bulkDownloadButton.addEventListener('mouseout', function() { this.style.transform = 'scale(1)'; this.style.backgroundColor = '#fcbb34'; }); } window.bulkDownloadButton.addEventListener('click', function() { var checkboxes = document.querySelectorAll("#download_list input[type='checkbox']:checked"); checkboxes.forEach(function(checkbox) { // 检查是否真的勾选了复选框,并且复选框是可见的 if (checkbox.checked && checkbox.getAttribute('data-visible') === 'true') { var container = checkbox.closest('div'); var link = container.querySelector('a'); var file_name = link.textContent; var file_url = link.href; // 调用下载函数 courseDownload(file_url, file_name); } }); }); // 将批量下载按钮添加到下载列表 download_list.appendChild(window.bulkDownloadButton); } } function filterList(keyword) { keyword = keyword.toLowerCase(); var files = document.querySelectorAll("#download_list a"); files.forEach(function(file) { var container = file.parentElement; var fileName = file.textContent.toLowerCase(); var checkbox = container.querySelector("input[type='checkbox']"); if (fileName.includes(keyword)) { container.style.display = ""; checkbox.setAttribute('data-visible', 'true'); } else { container.style.display = "none"; checkbox.setAttribute('data-visible', 'false'); // 当文件被过滤掉时,设置复选框为不可见 } }); } function filterListByCategory(categoryValue) { var files = document.querySelectorAll("#download_list a"); var extensions = categoryValue.split(',').map(ext => ext.trim()); // 通过逗号分隔并移除空格得到后缀名数组 files.forEach(function(file) { var container = file.parentElement; var checkbox = container.querySelector("input[type='checkbox']"); // 提取文件扩展名 var fileName = file.textContent.toLowerCase(); var fileExtension = fileName.slice(((fileName.lastIndexOf(".") - 1) >>> 0) + 2); // 检查文件扩展名是否在分类中 var isVisible = categoryValue === "" || extensions.includes(fileExtension); container.style.display = isVisible ? "" : "none"; checkbox.setAttribute('data-visible', isVisible.toString()); }); // 如果快速筛选后,全选复选框仍然选中,且不对应任何选项时,取消其勾选状态 var selectAllCheckbox = document.getElementById('selectAllCheckbox'); if (selectAllCheckbox && selectAllCheckbox.checked) { var anyCheckboxVisible = Array.from(document.querySelectorAll("#download_list input[type='checkbox']")).some(checkbox => checkbox.getAttribute('data-visible') === 'true'); if (!anyCheckboxVisible) { selectAllCheckbox.checked = false; } } } function add_download_button() { // 全局变量用于保存批量下载按钮 window.bulkDownloadButton = null; var down_button = document.createElement('div'); down_button.innerHTML = ` <div id="download_list" style="z-index:999;backdrop-filter: blur(10px);border: 2px solid #fcbb34;border-radius: 5px;display: none;padding: 20px;flex-direction: column;align-items: flex-start;"> <h3 style="color:#fcbb34; font-weight:bold;">课程附件清单</h3> </div> <dotlottie-player src="https://lottie.host/67403f9b-b050-4414-9307-1096cb6088f2/lb6v8cv81d.json" background="transparent" speed="1" style="width: 100px; height: 100px; margin: -15px;" loop autoplay onclick="showList()"></dotlottie-player> `; // 添加下载图标的样式 var downloadIconStyle = document.createElement('style'); downloadIconStyle.innerHTML = ` .download-icon { padding: 2px; margin: -20px; background-color: rgba(255, 255, 255, 0); border-radius: 10px; } transition: transform 0.3s ease; cursor: pointer; } .download-icon:hover { background-color: rgba(255, 255, 255, 0.3); transform: scale(1.1); } `; document.head.appendChild(downloadIconStyle); down_button.style.cssText = ` position: fixed; right: 20px; bottom: -5px; z-index: 9000; cursor: pointer; `; // 确保已经有这样的代码来设置图标的悬停动画 var existingStyles = document.getElementById('download-icon-styles'); if (!existingStyles) { document.head.appendChild(downloadIconStyle); } document.body.appendChild(down_button); } window.onload = ()=> { console.oldLog = console.log; console.log = (...data) =>{ if (data[0] == 'nodesToData') { course_resources = data[1]; console.oldLog('::', course_resources); parseContent(); } }; // 定义快速筛选的类别选项 window.quickFilters = [ { label: "全部", value: "" }, { label: "文档", value: "doc,docx,pdf,txt,odt,rtf,html,htm,xls,xlsx,ppt,pptx,odp" }, { label: "图片", value: "jpg,jpeg,png,gif,bmp,tiff,svg,webp" }, { label: "压缩包", value: "zip,rar,7z,gz,bz2,tar" }, // 可以继续添加其他类别 ]; window.abortControllers = {}; // 创建一个 MutationObserver 实例 const observer = new MutationObserver(function(mutationsList, observer) { // 在每次发生 DOM 变化时触发这个回调函数 for(let mutation of mutationsList) { if (mutation.type === 'childList' && mutation.target.id === 'download_list') { // 如果发生了子节点的变化,并且变化的目标是下载列表 // 重新添加搜索框和批量下载按钮 window.showList(); break; // 处理完毕后退出循环 } } }); // 配置需要观察的目标节点和观察的类型 observer.observe(document.body, { childList: true, subtree: true }); // 添加下载按钮并延迟显示 setTimeout(() => { add_download_button(); }, 2000); }; // 定义要抓取的后缀名 var extensions = [".doc",".pdf",".docx",".ppt",".pptx",".xls",".xlsx",".txt",".odt",".rtf",".jpg",".jpeg",".png",".gif",".bmp",".tiff",".svg",".webp",".zip",".rar",".7z",".tar",".gz",".bz2",".xz"]; // 创建一个元素,用于显示抓取到的 URL var list = document.createElement("div"); initializeListStyles(list); // 监听 xhr 请求,检查响应的 URL 是否符合条件 var open = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { this.addEventListener("load", function() { // 如果 URL 包含指定的后缀名之一 for (var i = 0; i < extensions.length; i++) { if (url.includes(extensions[i])) { // 发送一个新的 xhr 请求,获取真正的下载地址 handleXhrResponse(url); break; } } }); open.call(this, method, url, async, user, pass); }; // 初始化列表样式 function initializeListStyles(element) { element.style.position = "fixed"; element.style.top = "10px"; element.style.right = "0"; element.style.width = "350px"; element.style.height = "10%"; element.style.overflow = "auto"; element.style.zIndex = "9997"; element.style.padding = "10px"; // 为元素添加渐变背景色 element.style.background = "linear-gradient(270deg, #ffc700, #ff8c00, #ff6500)"; element.style.backgroundSize = "400% 400%"; // 添加动态背景动画的 CSS 规则 var animStyle = document.createElement("style"); animStyle.textContent = ` @keyframes gradientBgAnimation { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .dynamic-gradient { animation: gradientBgAnimation 15s ease infinite; } `; document.head.appendChild(animStyle); // 为元素添加动态渐变背景的类 element.classList.add("dynamic-gradient"); // 为元素添加阴影效果 element.style.boxShadow = "0 4px 8px 0 rgba(0, 0, 0, 0.2)"; // 为元素添加圆角效果 element.style.borderRadius = "10px"; // 为元素添加动画效果,悬停时放大 element.style.transition = "transform 0.3s"; element.addEventListener("mouseover", function() { element.style.transform = "scale(1.1)"; }); element.addEventListener("mouseout", function() { element.style.transform = "scale(1)"; }); element.innerHTML = "<h3><span style=\"font-family: '微软雅黑', 'Microsoft YaHei', sans-serif; font-weight: bold; font-style: italic; font-size: 16px;\">抓取到的课件</span></h3>"; // 添加 draggable 属性,可拖动 element.setAttribute("draggable", "true"); // 添加 resize 属性,可调整大小 element.style.resize = "both"; // 创建一个容器来存放Lottie动画 var lottieContainer = document.createElement('div'); lottieContainer.style.position = "absolute"; lottieContainer.style.top = "-20px"; lottieContainer.style.left = "95px"; lottieContainer.style.width = "120%"; lottieContainer.style.height = "120%"; lottieContainer.style.zIndex = "9998"; lottieContainer.style.pointerEvents = "none"; // 确保动画不会拦截鼠标事件 // 创建并配置Lottie播放器 var lottiePlayer = document.createElement('dotlottie-player'); lottiePlayer.setAttribute('src', "https://lottie.host/995b71c8-b7aa-45b0-bb77-94b850da5d5d/dyezqbvtia.json"); lottiePlayer.setAttribute('background', "transparent"); lottiePlayer.setAttribute('speed', "1"); lottiePlayer.setAttribute('style', "width: 100%; height: 100%;"); lottiePlayer.setAttribute('loop', ""); lottiePlayer.setAttribute('autoplay', ""); // 将Lottie播放器添加到动画容器中 lottieContainer.appendChild(lottiePlayer); // 将动画容器添加为列表元素的子元素 element.appendChild(lottieContainer); // 添加拖动事件监听器 element.addEventListener("dragstart", function(e) { // 设置拖动元素的透明度 e.target.style.opacity = "0.5"; // 设置拖动元素的 id e.dataTransfer.setData("text/plain", e.target.id); // 记录拖动元素的初始位置和鼠标的初始位置 e.target.startX = e.clientX; e.target.startY = e.clientY; e.target.offsetX = e.target.offsetLeft; e.target.offsetY = e.target.offsetTop; }); element.addEventListener("drag", function(e) { // 如果鼠标的位置有效,根据鼠标的移动距离,更新拖动元素的位置 if (e.clientX > 0 && e.clientY > 0) { e.target.style.left = e.target.offsetX + e.clientX - e.target.startX + "px"; e.target.style.top = e.target.offsetY + e.clientY - e.target.startY + "px"; } }); element.addEventListener("dragend", function(e) { // 恢复拖动元素的透明度 e.target.style.opacity = "1"; }); document.body.appendChild(element); } // 全局变量,用于存储唯一的预览链接元素 var previewLink; // 全局变量,用于标志是否有异步操作正在进行中 var isDownloading = false; function handleXhrResponse(url) { if (isDownloading) { return; // 如果已经有下载在进行中,则跳过 } isDownloading = true; // 清除之前的预览链接元素 if (previewLink) { previewLink.parentNode.removeChild(previewLink); previewLink = null; } var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onload = function () { // 如果响应的文本中包含一个以 http 或 https 开头的 URL,将其添加到列表中 // 在此之前,先将响应的文本中的 "}}" 和引号替换为空字符串,去掉多余的符号 var text = xhr.responseText.replace("}}", "").replace(/"/g, ""); var match = text.match(/(http|https):\/\/\S+/); var titleBannerElement = document.querySelector('.common_node_content_banner h5.title'); var content; if (titleBannerElement && titleBannerElement.getAttribute('title')) { content = titleBannerElement.getAttribute('title').trim(); } else { content = titleBannerElement.textContent.trim(); } if (match) { // 如果预览链接不存在,则创建 if (!previewLink) { previewLink = document.createElement("a"); previewLink.style.background = "#06566f"; // 使用背景剪裁 previewLink.style.webkitBackgroundClip = "text"; previewLink.style.backgroundClip = "text"; // 设置文字颜色为透明以使渐变可见 previewLink.style.color = "transparent"; previewLink.style.fontFamily = "'微软雅黑', 'Microsoft YaHei', sans-serif"; previewLink.style.fontWeight = "bold"; // 悬停时的样式变化 previewLink.addEventListener('mouseover', () => { previewLink.style.backgroundColor = '#ffffff'; // 更改背景色 }); previewLink.addEventListener('mouseout', () => { previewLink.style.backgroundColor = '#06566f'; // 恢复背景色 }); // 将预览链接添加到列表中 list.appendChild(previewLink); list.appendChild(document.createElement("br")); } // 更新预览链接的属性 previewLink.href = match[0]; previewLink.target = "_blank"; previewLink.textContent = content; // 添加点击事件监听器,在点击时进行下载 previewLink.addEventListener("click", function (event) { event.preventDefault(); // 阻止默认的点击行为 // 直接使用 courseDownload 函数进行下载 courseDownload(match[0], content); }); } isDownloading = false; // 将新创建的元素插入到列表的最前面 var titleElement = list.querySelector("h3"); if (titleElement) { list.insertBefore(previewLink, titleElement.nextSibling); } else { list.appendChild(previewLink); } } xhr.send(); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址