帮助你直接下载国自然结题报告(userscript版)
当前为
// ==UserScript==
// @name NSFC conclusion downloader
// @namespace https://blog.rhilip.info/
// @version 0.1
// @description 帮助你直接下载国自然结题报告(userscript版)
// @author Rhilip
// @match http://output.nsfc.gov.cn/conclusionProject/*
// @require https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js
// @require https://unpkg.com/axios/dist/axios.min.js
// ==/UserScript==
(function() {
'use strict';
// 从 jspdf 库中获得jsPDF
const { jsPDF } = jspdf
function asyncImageLoader(url){
return new Promise((resolve, reject) => {
var image = new Image()
image.src = url
image.onload = () => resolve(image)
image.onerror = () => reject(new Error('could not load image'))
})
}
function cleanFilename(filename) {
return filename.replace(/[:\/]/ig, '_').replace(/\x00/ig,'_').replace(/[\n\\\*><?\"|\t]/ig,'')
}
/**
* @param obj - {
* sel: 'a', // the selector you want to wait for (optional)
* context: document.body, // scope of search for selector or mutations (optional, default document.body)
* stop: true, // stop waiting after first result (optional, default false)
* mode: 'M', // M to use mutation observer, S to use setInterval (optional, default M)
* onchange: func, // if using mode 'M' this function will be called whenever mutation handler triggers
* onmatch: func, // if selector is specified function will be called for each match with element as parameter
* config: { attributes: true } // if using mode 'M' this object will override settings passed to mutation observer
* }
*/
function waitForElems(obj) {
var tick;
var id = 'fke' + Math.floor(Math.random() * 12345);
var type = window.MutationObserver ? (obj.mode || 'M') : 'S';
var lastMutation = Date.now();
var lastCall = Date.now();
var context = obj.context || document.body;
var sel = obj.sel;
var config = obj.config || {
subtree: true,
childList: true
};
var onChange = obj.onchange;
var queuedCall;
function throttle(func) {
var now = Date.now();
clearTimeout(queuedCall);
// less than 100ms since last mutation
if (now - lastMutation < 100) {
// 500ms or more since last query
if (now - lastCall >= 500) {
func();
} else {
queuedCall = setTimeout(func, 100);
}
} else {
func();
}
lastMutation = now;
}
function findElem(sel) {
lastCall = Date.now();
var found = [].filter.call(context.querySelectorAll(sel), function(elem) {
return elem.dataset[id] !== 'y';
});
if (found.length > 0) {
if (obj.stop) {
type === 'M' ? tick.disconnect() : clearInterval(tick);
}
found.forEach(function(elem) {
elem.dataset[id] = 'y';
obj.onmatch(elem);
});
}
}
if (type === 'M') {
tick = new MutationObserver(function() {
if (sel) throttle.call(null, findElem.bind(null, sel));
if (onChange) onChange.apply(this, arguments);
});
tick.observe(context, config);
} else {
tick = setInterval(findElem.bind(null, sel), 300);
}
if (sel) findElem(sel);
return {
type: type,
stop: function() {
if (type === 'M') {
tick.disconnect();
} else {
clearInterval(tick);
}
},
resume: function() {
if (type === 'M') {
tick.observe(context, config);
} else {
tick = setInterval(findElem.bind(null, sel), 300);
}
}
};
}
// 由于页面是动态加载的,所以我们需要等我们需要的元素加载出来再添加交互逻辑
waitForElems({
sel: '#conclusion-report-tab > h3',
onmatch: () => {
$('#conclusion-report-tab > h3').before('<button id="download_report" type="button" class="btn btn-link pull-right">(下载全文PDF)</button>')
const downloadBtn = $('#download_report')
downloadBtn.click((async () => {
downloadBtn.prop('disabled', true)
// 获得项目信息: 编号(加密后)、批准号、项目名称
const dependUintID = location.pathname.match(/conclusionProject\/(.+)/)[1]
const projectID = $('#basic-tab > div:nth-child(1) > div.col-md-10').text()
const projectName = $('#basic-tab > div:nth-child(2) > div.col-md-10').text()
// 准备 jsPDF 对象
const doc = new jsPDF();
doc.deletePage(1); // 删除第一页
let i = 1;
let should_loop = true;
while (should_loop) {
downloadBtn.text(`正在下载第 ${i} 页`)
const postData = new URLSearchParams({id: dependUintID, index: i});
const req = await axios.post('http://output.nsfc.gov.cn/baseQuery/data/completeProjectReport', postData);
const image = await asyncImageLoader(req.data.data.url)
doc.addPage([image.width, image.height], image.width < image.height ? 'p' : 'l');
doc.addImage(image, "JPEG", 0, 0, image.width, image.height);
should_loop = req.data.data.hasnext !== false;
i++;
}
downloadBtn.text('正在生成PDF')
doc.save(`${projectID} ${projectName}.pdf`)
downloadBtn.text('下载完成')
downloadBtn.prop('disabled', false)
}))
}
})
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址