知网CNKI搜索页批量下载PDF_单个下载_下载进度_新窗口无感下载_调整下载时间_cnki_search_download_helper

知网cnki搜索结果页快捷下载PDF,支持批量下载(支持进度查看),支持后台新窗口无感下载,支持下载间隔时间调整,cnki_search_download_helper

// ==UserScript==
// @name         知网CNKI搜索页批量下载PDF_单个下载_下载进度_新窗口无感下载_调整下载时间_cnki_search_download_helper
// @namespace    http://ilxdh.com/
// @icon         https://kdoc.cnki.net/favicon.ico
// @version      0.4
// @description  知网cnki搜索结果页快捷下载PDF,支持批量下载(支持进度查看),支持后台新窗口无感下载,支持下载间隔时间调整,cnki_search_download_helper
// @author       longxuan
// @match        *://kns.cnki.net/*
// @match        *://tra.oversea.cnki.net/*
// @match        *://chn.oversea.cnki.net/*
// @grant        GM_addStyle
// @grant        GM_openInTab
// ==/UserScript==

(function () {
  "use strict";

  // 批量下载新窗口打开间隔
  let defaultOpenInterval = 5;
  // 是否聚焦下载窗口;默认-1:不聚焦
  let isDownActive = "-1";
  const icon =
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAABpElEQVQ4T8WUsWtTURTGv+9EKELeix1cxf4HycssutguLoU6u9sOAQfz4pDE4b2HQqGUZncTp06lQ0vr1Cn3FQV11aVDhpoESoe8d+SCCSWSm9DFO13uPfzu932ccwkAQb3fAtm0e/fiLzB/Z6LS3nQd7UElHJyIspNh1HOByEJTiL7mTE3itW/WTkCqWfs8WT51geyDVP0MchVkZiLv0bjeCbKWlXwMcDONvW9jkElKrSAcfAH0wsSlNQubC4LgjNBeN7pnJoomMlhT4G0a+9tuUNivKWRFeJ10o/sXlfrgFYhnU9k8NLG/4gSVG5dl0ULqL3l3T1u8ns6vXL98IiycmNinE1R9ffVAZfRTVZ6mSfHo1qBKOOwI8h8KeWFir3orULXxO1AVK7sUhP2PUPk+3TsLWQvC4S6gVyQPFfkGVNYBvQNwBGgRiq85sjfOjMYvKfCBQE8ph2lUPL5pLWgMPuV51pkJ+qtki8B6N/b3XZ0+05pI4SUUz6HcMYlXmzfCM0F2KKk4MIn/fh7E3i8U9v8FBfVhE9TWIir+qVFt29/gD1lcPiK25hu5AAAAAElFTkSuQmCC";
  let progressFlag = false;
  // 当前页所有PDF地址
  let pdfDownLoadUrlArr = [];
  // 待下载PDF地址
  let curDownUrlArr = []
  let isDownloading = false;
  const diyBulkDownPdfStyle = `
    .diy-down-wrap{
      text-align: right;
      margin-top: 10px;
      color: #0f5de5;
      font-size: 0;
    }
    .diy-select-opentype{
      display: inline-block;
      color: #0f5de5;
      margin-right: 10px;
    }
    .diy-select-opentype-select{
      color: #0f5de5;
    }
    .diy-select-opentype span{
      display: inline-block;
      font-size: 12px;
    }
    .diy-download-interval-wrap{
      margin-right: 10px;
      display: inline-block;
      font-size: 12px;
    }
    .diy-download-interval-input{
      font-size: 10px;
      color: #0f5de5;
      width: 50px;
      padding-left: 5px;
    }
    .diy-progress-bar{
      display: inline-block;
      font-size: 12px;
      color: #0f5de5;
      margin-right: 10px;
    }
    .diy-bulk-down-pdf{
      display: inline-block;
      padding: 2px 8px;
      line-height: 18px;
      color: #0f5de5;
      font-size: 12px;
      text-align: center;
      background-color: #e3ecfd;
      border: 1px solid #fff;
      cursor: pointer;
    }
    .diy-bulk-down-pdf:hover{
      color: #fff;
      background-color: #0c5de4;
    }`;

  GM_addStyle(diyBulkDownPdfStyle);

  function sleep(timeout) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve();
      }, timeout * 1000);
    });
  }

  function domChange() {
    if (progressFlag) {
      return;
    }
    progressFlag = true;
    waitForEle(".result-table-list", startHandle);
  }

  // 获取到元素
  function waitForEle(name, callback) {
    const ele = $(name);
    if (!ele.size()) {
      setTimeout(() => {
        waitForEle(name, callback);
      }, 1000);
    } else {
      callback && callback();
    }
  }

  function startHandle() {
    addBulkDownloadBtn();
    handleDownlinks();
  }

  function handleStyle() {
    $(".result-table-list .operat").css("min-width", "112px");
  }

  // 添加批量下载PDF按钮
  function addBulkDownloadBtn() {
    if ($(".diy-down-wrap").length) {
      return;
    }
    const btnEle = $(
      `<div class="diy-down-wrap">
        <div class="diy-select-opentype">
          <span>是否聚焦下载窗口:</span>
          <select class="diy-select-opentype-select" style="border:0.5px solid #0f5de5">
            <option value="-1">否</option>
            <option value="1">是</option>
          </select>
        </div>
        <div class="diy-download-interval-wrap">下载间隔:<input value="${defaultOpenInterval}" class="diy-download-interval-input" style="border:0.5px solid #0f5de5"> 秒</div>
        <div class="diy-progress-bar">进度:0/0</div>
        <div class="diy-bulk-down-pdf">批量下载(PDF)</div>
      </div>`
    );
    $(".result-table-list").before(btnEle);
    $(".diy-select-opentype-select").val(isDownActive);
  }

  function joinUrl(url){
    return window.location.origin + url
  }

  // 下载链接添加后缀
  function handleDownlinks() {
    const links = $(".downloadlink");
    if (links.length) {
      handleStyle();
      const tempRes = [];
      links.each(function () {
        const $this = $(this);
        if ($this.parent().find(".diy-pdf-download").length > 0) {
          return;
        }
        const curHref = $this.attr("href");
        const curPdfHref = `${curHref}&dflag=pdfdown`;
        $this.after(
          $(
            `<a href="${curPdfHref}" title="下载PDF" target="_blank" class="diy-pdf-download"><i style="background-image: url('${icon}');background-position:0 0;background-size: 14px;position:relative;top:3px;left:2px;"></i></a>`
          )
        );
        tempRes.push(joinUrl(curPdfHref));
      });
      if (tempRes.length) {
        pdfDownLoadUrlArr = tempRes;
        curDownUrlArr = pdfDownLoadUrlArr
        setProgressBarText(0);
      }
    }
    progressFlag = false;
  }

  function setProgressBarText(value) {
    const text =
      value < curDownUrlArr.length
        ? `${value}/${curDownUrlArr.length}`
        : "已完成";
    $(".diy-progress-bar").text(`进度:${text}`);
  }

  function downPdfClick() {
    $("#briefBox").on("click", ".diy-bulk-down-pdf", function () {
      if (isDownloading) {
        alert("正在下载,请勿重复点击");
        return;
      }
      const inputValue = $(".diy-download-interval-input").val();
      const intReg = /^[1-9]\d*$/;
      if (!intReg.test(inputValue)) {
        alert("打开间隔必须为正整数");
        return;
      }
      if (!pdfDownLoadUrlArr.length) {
        alert("未检测到下载地址");
        return;
      }
      const tempCheckedInput = []
      const tempCheckedUrl = []
      $(".result-table-list").find("input:checkbox").each(function () {
        if ($(this).prop("checked") == true) {
          tempCheckedInput.push($(this))
          const pdfItem = $(this).parents('tr').find('.operat').find('.diy-pdf-download')
          if(pdfItem.length){
            tempCheckedUrl.push(joinUrl(pdfItem.attr('href')))
          }
        }
      });
      if(tempCheckedInput.length && !tempCheckedUrl.length){
        alert('已勾选的内容,未检测到有效下载地址!')
        return
      }
      curDownUrlArr = tempCheckedUrl.length ? tempCheckedUrl : pdfDownLoadUrlArr
      startDownload(inputValue);
    });
  }

  function changeOpenInterval() {
    $("#briefBox").delegate(
      ".diy-download-interval-input",
      "propertychange input",
      function () {
        defaultOpenInterval = parseInt($(this).val());
      }
    );
  }

  function changeDownActive() {
    $("#briefBox").on("change", ".diy-select-opentype-select", function () {
      isDownActive = $(this).val();
    });
  }

  function bindEvents() {
    downPdfClick();
    changeOpenInterval();
    changeDownActive();
  }

  // 新窗口打开下载
  async function startDownload(timeout) {
    isDownloading = true;
    const isActive =
      parseInt($(".diy-select-opentype-select").val()) === 1 ? true : false;
    for (let i = 0; i < curDownUrlArr.length; i++) {
      const url = curDownUrlArr[i];
      GM_openInTab(url, { active: isActive });
      setProgressBarText(i + 1);
      if (curDownUrlArr.length === i + 1) {
        isDownloading = false;
      }
      await sleep(timeout);
    }
  }

  window.onload = function () {
    const briefBoxEl = document.getElementById("briefBox");
    if (briefBoxEl) {
      const observer = new MutationObserver(domChange);
      observer.observe(briefBoxEl, {
        attributes: true,
        subtree: true,
      });
      bindEvents();
      // 兼容
      domChange();
    }
  };
})();