Greasy Fork

国家中小学智慧教育平台教材PDF链接工具

教材预览页面添加了PDF按钮,可免登录查看或下载电子课本

当前为 2023-07-06 提交的版本,查看 最新版本

// ==UserScript==
// @name         国家中小学智慧教育平台教材PDF链接工具
// @namespace    http://tampermonkey.net
// @version      1.2.1
// @description  教材预览页面添加了PDF按钮,可免登录查看或下载电子课本
// @match        *://basic.smartedu.cn/*
// @match        *://www.zxx.edu.cn/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const pattern = /contentId=([a-zA-Z0-9_-]+)/; // 匹配 contentId 的正则表达式
    const contentId = window.location.href.match(pattern)[1]; // 获取 contentId 的数值
    let link = `https://r3-ndr.ykt.cbern.com.cn/edu_product/esp/assets_document/${contentId}.pkg/pdf.pdf`;
    // window.location.href = link; // 直接重定向到该网址,经测试可用

    const maxTimeToCheck = 5000; // 最多检查 5000 毫秒,即 5 秒
    let elapsedTime = 0;

    function checkConfirmButtons() {
        const confirmBtns = document.querySelector(".fish-modal-confirm-btns");
        if (confirmBtns) {
            // 去除阻碍
            document.querySelector("body > div:nth-of-type(2)").remove(); // 去除遮罩
            const body = document.querySelector("html > body"); // 去除 body 属性
            body.removeAttribute("class");
            body.removeAttribute("style");
            // 添加阅读器
            const name = document.querySelector("#main-content > div.content > div.web-breadcrumb > div > span:nth-child(3) > span.fish-breadcrumb-link")?.textContent;
            const indexModuleWrapperECeCo = document.querySelector(".index-module_wrapper_ECeCo");
            if (indexModuleWrapperECeCo) {
                indexModuleWrapperECeCo.innerHTML = `
<div class="index-module_wrapper_ECeCo">
  <div class="index-module_header_tG-zz">
    <h3 class="index-module_title_bnE9V">${name}</h3>
    <div class="index-module_info_evO1d">
      <span class="index-module_origin_nuihE">
        <svg class="index-module_icon_dwVZ4">
          <use xlink:href="#icon_hotel_fill">
          </use>
        </svg>
        <span class="index-module_department_ewVZW">智慧中小学</span>
      </span>
      <div class="index-module_assesment-detail_jhGLz">
        <div class="index-module_assessment-content_06v6Z">
          <div class="fish-dropdown-trigger index-module_assessment-rate_euPTQ">
            <ul class="fish-rate fish-rate-disabled" tabindex="-1" role="radiogroup">
              <li class="fish-rate-star fish-rate-star-full">
                <div role="radio" aria-checked="true" aria-posinset="1" aria-setsize="5" tabindex="-1">
                  <div class="fish-rate-star-first">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                  <div class="fish-rate-star-second">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="fish-rate-star fish-rate-star-full">
                <div role="radio" aria-checked="true" aria-posinset="2" aria-setsize="5" tabindex="-1">
                  <div class="fish-rate-star-first">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                  <div class="fish-rate-star-second">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="fish-rate-star fish-rate-star-full">
                <div role="radio" aria-checked="true" aria-posinset="3" aria-setsize="5" tabindex="-1">
                  <div class="fish-rate-star-first">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                  <div class="fish-rate-star-second">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="fish-rate-star fish-rate-star-full">
                <div role="radio" aria-checked="true" aria-posinset="4" aria-setsize="5" tabindex="-1">
                  <div class="fish-rate-star-first">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                  <div class="fish-rate-star-second">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="fish-rate-star fish-rate-star-zero">
                <div role="radio" aria-checked="true" aria-posinset="5" aria-setsize="5" tabindex="-1">
                  <div class="fish-rate-star-first">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                  <div class="fish-rate-star-second">
                    <div class="custom-star-wrap" style="width: 100%;">
                      <div class="custom-star">
                      </div>
                    </div>
                  </div>
                </div>
              </li>
            </ul>
            <span class="index-module_text_rukZW">5.0分</span>
          </div>
        </div>
        <span class="fish-dropdown-trigger index-module_assessment-btn_6imdF ">
          <button type="button" class="fish-btn fish-btn-round">
            <svg class="index-module_rate-icon_YM1Lc">
              <use xlink:href="#icon_evaluate_fill">
              </use>
            </svg>
            <span class="index-module_assessment-btn-text_fw-+Z">评价</span>
          </button>
        </span>
      </div>
      <div class="index-module_extra_tUQog">
        <div class="index-module_like-wrap_NbyLe  ">
          <svg class="index-module_like_qOb9K">
            <use xlink:href="#icon_thumb_fill">
            </use>
          </svg>
          <div class="index-module_like-count_GXOGd">100w+点赞</div>
        </div>
        <div class="index-module_suggestion-wrap_s+Ii+ ">
          <svg class="index-module_suggestion-icon_IrRxU">
            <use xlink:href="#icon_feedback_fill">
            </use>
          </svg>
          <div>建议</div>
        </div>
      </div>
    </div>
  </div>
  <div class="index-module_divider_rI-lg">
  </div>
  <div class="imageList-module_special-edu-image-list-wrapper_18zfs">
    <div class="imageList-module_special-edu-image-list_+ywag">
      <div class="course-document">
        <div class="document-context">
          <embed src="${link}" width="100%" height="100%">
        </div>
        <div class="doc-toolbar">
          <div class="left">
          </div>
          <div class="center">
          </div>
          <div class="right">
            <div class="split-line">
            </div>
            <div class="tool-btn fullscreen" title="全屏">
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
                `;
            }
            // 全屏切换
            const fullscreenBtn = document.querySelector(".tool-btn.fullscreen");
            const courseDocument = document.querySelector(".course-document");
            const htmlElement = document.querySelector("html");
            fullscreenBtn.addEventListener("click", () => {
                if (courseDocument.classList.contains("full-screen")) { // 当前处于"全屏状态",切换为"非全屏状态"
                    courseDocument.classList.remove("full-screen");
                    htmlElement.style.overflow = "";
                } else { // 当前处于"非全屏状态",切换为"全屏状态"
                    courseDocument.classList.add("full-screen");
                    htmlElement.style.overflow = "hidden";
                }
            });
            // 重定向至登录页
            const toLogin = [
            document.querySelector("#main-content > div.content > div.index-module_special-edu-detail_aH1Nr > div > div > div > div.index-module_header_tG-zz > div > div.index-module_assesment-detail_jhGLz > span"),
            document.querySelector("#main-content > div.content > div.index-module_special-edu-detail_aH1Nr > div > div > div > div.index-module_header_tG-zz > div > div.index-module_extra_tUQog > div.index-module_like-wrap_NbyLe"),
            document.querySelector("#main-content > div.content > div.index-module_special-edu-detail_aH1Nr > div > div > div > div.index-module_header_tG-zz > div > div.index-module_extra_tUQog > div.index-module_suggestion-wrap_s\\+Ii\\+")
            ];
            toLogin.forEach(element => {
                element.addEventListener("click", () => {
                    window.open("https://auth.smartedu.cn/uias/login/");
                });
            });
            clearInterval(intervalId1); // 清除定时器
        } else {
            elapsedTime += 100;
            if (elapsedTime >= maxTimeToCheck) {
                clearInterval(intervalId1); // 清除定时器,停止检查
            }
        }
    }
    const intervalId1 = setInterval(checkConfirmButtons, 100); // 每隔 100 毫秒检查一次 fish-modal-confirm-btns 元素是否存在

    function checkIndexModule() {
        const container = document.querySelector(".index-module_extra_tUQog"); // 找到要添加按钮的容器元素
        if (container) {
            const a = document.createElement("a");
            a.innerHTML = "📓 查看PDF"; // 文本内容
            a.display = "flex"; // 弹性容器布局
            a.style.alignItems = "center"; // 居中对齐
            a.style.marginLeft = "24px"; // 左边距("点赞数"左右边距各 10,"建议"左边距 14,故按钮间距为 24)
            a.style.fontSize = "14px"; // 字体大小
            a.style.cursor = "pointer"; // 指针变手型
            a.style.color = "#888"; // 文本颜色
            a.href = link; // 链接
            // a.target = "_blank"; // 新标签页打开
            container.appendChild(a); // 将按钮添加到网页中
            a.addEventListener("mouseover", function() {
                this.innerHTML = "📘 查看PDF";
                this.style.color = "#226dec"; // 鼠标移入时修改元素的样式
            });
            a.addEventListener("mouseout", function() {
                this.innerHTML = "📓 查看PDF";
                this.style.color = "#888"; // 鼠标移出时恢复原来的样式
            });
            a.addEventListener("mousedown", function() {
                this.innerHTML = "📕 查看PDF";
                this.style.color = "#e82020"; // 鼠标按下时修改元素的样式
            });
            // a.addEventListener("mouseup", function() {
                // this.innerHTML = "📓 查看PDF";
                // this.style.color = "#888"; // 鼠标抬起时修改元素的样式
            // });
            clearInterval(intervalId2); // 清除定时器
        } else {
            elapsedTime += 100;
            if (elapsedTime >= maxTimeToCheck) {
                clearInterval(intervalId2); // 清除定时器,停止检查
            }
        }
    }
    const intervalId2 = setInterval(checkIndexModule, 100); // 每隔 100 毫秒检查一次 index-module_extra_tUQog 元素是否存在

    if (window.location.href.startsWith("https://basic.smartedu.cn/schoolService/")) {
        const originalFetch = window.fetch;
        window.fetch = function (url, options) {
            if (url.endsWith(".pdf")) {
                // window.location.href = url;
                const a = document.querySelector(".index-module_extra_tUQog > a"); // 按钮
                a && (a.href = url); // 修改按钮链接
            }
            return originalFetch(url, options);
        };
    }

})();