// ==UserScript== // @name Cmpedu Resource Downloader // @namespace http://tampermonkey.net/ // @version 3.0 // @description 机械工业出版社教育服务网资源下载,无需登录,无需教师权限,油猴脚本。 // @author yanyaoli // @match *://*.cmpedu.com/ziyuans/ziyuan/* // @match *://*.cmpedu.com/books/book/* // @connect *.cmpedu.com // @grant GM_xmlhttpRequest // @grant GM_addStyle // @downloadURL https://update.greasyfork.icu/scripts/483095/Cmpedu%20Resource%20Downloader.user.js // @updateURL https://update.greasyfork.icu/scripts/483095/Cmpedu%20Resource%20Downloader.meta.js // ==/UserScript== (function () { 'use strict'; // 样式注入 GM_addStyle(` @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); :root { --panel-bg: rgba(250, 250, 250, 0.95); --panel-border: rgba(0, 0, 0, 0.06); --header-bg: rgba(255, 255, 255, 0.8); --text-primary: #000000; --text-secondary: #6e6e73; --accent-color: #0071e3; --accent-hover: #0077ed; --item-hover: rgba(0, 0, 0, 0.03); --item-active: rgba(0, 0, 0, 0.05); --item-border: rgba(0, 0, 0, 0.06); --error-color: #ff3b30; --success-color: #34c759; } @media (prefers-color-scheme: dark) { :root { --panel-bg: rgba(40, 40, 40, 0.95); --panel-border: rgba(255, 255, 255, 0.1); --header-bg: rgba(50, 50, 50, 0.8); --text-primary: #ffffff; --text-secondary: #a1a1a6; --item-hover: rgba(255, 255, 255, 0.05); --item-active: rgba(255, 255, 255, 0.1); --item-border: rgba(255, 255, 255, 0.1); } } .cmp-panel { position: fixed; top: 20px; right: 20px; width: 320px; max-height: 75vh; background: var(--panel-bg); border-radius: 16px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); z-index: 99999; font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif; overflow: hidden; transition: left 0.1s ease-out, top 0.1s ease-out; border: 1px solid var(--panel-border); transform-origin: top right; opacity: 0; transform: scale(0.95); animation: panel-appear 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards; } @keyframes panel-appear { 0% { opacity: 0; transform: scale(0.95); } 100% { opacity: 1; transform: scale(1); } } .panel-header { padding: 16px 20px; background: var(--header-bg); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--item-border); display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; z-index: 1; } .panel-title { margin: 0; font-size: 16px; color: var(--text-primary); font-weight: 600; letter-spacing: -0.01em; } .close-btn { background: none; border: none; cursor: pointer; color: var(--text-secondary); font-size: 22px; line-height: 1; padding: 4px; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; margin: -4px; } .close-btn:hover { background-color: var(--item-hover); color: var(--text-primary); } .close-btn:active { background-color: var(--item-active); transform: scale(0.95); } .panel-content { padding: 8px 0; max-height: calc(75vh - 60px); overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; scrollbar-color: var(--text-secondary) transparent; } .panel-content::-webkit-scrollbar { width: 6px; } .panel-content::-webkit-scrollbar-track { background: transparent; } .panel-content::-webkit-scrollbar-thumb { background-color: var(--text-secondary); border-radius: 3px; opacity: 0.5; } .resource-item { padding: 12px 20px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--item-border); cursor: pointer; transition: all 0.15s ease; position: relative; color: var(--text-primary); } .resource-item:last-child { border-bottom: none; } .resource-item:hover { background-color: var(--item-hover); } .resource-item:active { background-color: var(--item-active); } .resource-item.disabled { opacity: 0.6; cursor: not-allowed; } .resource-item .title { flex: 1; font-weight: 500; font-size: 14px; margin-right: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .resource-item .download-icon { color: var(--accent-color); font-size: 16px; transition: color 0.2s ease; margin-left: 5px; } .resource-item .download-icon:hover { color: var(--accent-hover); } .skeleton { height: 20px; margin: 12px 20px; border-radius: 6px; background: linear-gradient(90deg, var(--item-border) 0%, var(--item-hover) 50%, var(--item-border) 100%); background-size: 200% 100%; animation: skeleton-loading 1.5s infinite; } .skeleton:nth-child(2) { width: 85%; } .skeleton:nth-child(3) { width: 70%; } @keyframes skeleton-loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .empty-state { padding: 40px 20px; text-align: center; color: var(--text-secondary); font-size: 14px; } .error-message { color: var(--error-color); display: flex; align-items: center; gap: 8px; padding: 12px 20px; background: rgba(255, 59, 48, 0.1); border-radius: 8px; margin: 12px 20px; font-size: 14px; } .success-message { color: var(--success-color); display: flex; align-items: center; gap: 8px; padding: 12px 20px; background: rgba(52, 199, 89, 0.1); border-radius: 8px; margin: 12px 20px; font-size: 14px; } .github-icon { width: 16px; height: 16px; cursor: pointer; transition: transform 0.2s ease; } .github-icon:hover { transform: scale(1.1); } .panel-footer { padding: 12px 20px; border-top: 1px solid var(--item-border); display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: var(--text-secondary); } @media (max-width: 480px) { .cmp-panel { width: calc(100% - 32px); right: 16px; left: 16px; top: 16px; max-height: 80vh; } } `); // 基础配置 const isMobile = window.location.host.startsWith('m.'); const baseUrl = isMobile ? 'http://m.cmpedu.com' : 'http://www.cmpedu.com'; const panelId = "downloadPanel"; function extractBookId() { if (window.location.href.includes('books/book')) { return window.location.pathname.split("/").pop().split(".")[0]; } if (window.location.href.includes('ziyuans/ziyuan')) { const el = document.getElementById('BOOK_ID'); return el ? el.value : null; } return null; } function createPanel() { const panel = document.createElement('div'); panel.id = panelId; panel.className = 'cmp-panel'; panel.innerHTML = `
未找到可下载的资源