自然资源标准PDF下载
// ==UserScript==
// @name 自然资源标准PDF下载
// @namespace http://tampermonkey.net/
// @version 2025.3.7
// @description 自然资源标准化信息服务平台下载pdf功能
// @author Shuaima
// @match *://www.nrsis.org.cn/mnr_kfs/file/read/*
// @require https://unpkg.com/pdf-lib@^1.17.1
// @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
// @grant GM_xmlhttpRequest
// @grant GM_download
// ==/UserScript==
(function() {
'use strict';
const { PDFDocument } = PDFLib;
let currentCode = '';
let totalPages = 0;
let loadedPages = 0;
// 创建进度条
function createProgressBar() {
const container = document.createElement('div');
container.style = `
position: fixed;
top: 70px;
left: 20px;
width: 200px;
background: #f1f1f1;
border-radius: 4px;
padding: 10px;
z-index: 9999;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
display: none;
`;
const progressBar = document.createElement('div');
progressBar.style = `
height: 20px;
background: #e0e0e0;
border-radius: 10px;
overflow: hidden;
margin-bottom: 8px;
`;
const progressFill = document.createElement('div');
progressFill.style = `
width: 0%;
height: 100%;
background: linear-gradient(90deg, #219677, #27ae60);
transition: width 0.3s ease;
`;
const progressText = document.createElement('div');
progressText.style = `
text-align: center;
font-size: 12px;
color: #666;
`;
progressText.textContent = '准备中...';
progressBar.appendChild(progressFill);
container.appendChild(progressBar);
container.appendChild(progressText);
document.body.appendChild(container);
return { container, progressFill, progressText };
}
// 创建下载按钮
function createDownloadBtn() {
const btn = document.createElement('button');
btn.style = `
position: fixed;
top: 20px;
left: 20px;
padding: 7px 15px;
background: #219677;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
z-index: 9999;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
transition: all 0.3s;
`;
btn.textContent = '下载PDF';
btn.onclick = startDownloadProcess;
document.body.appendChild(btn);
}
// 从URL获取code
function getCodeFromURL() {
const pathSegments = window.location.pathname.split('/');
const code = pathSegments[pathSegments.length - 1];
return code || '';
}
// 更新进度条
function updateProgress(progressData) {
progressData.progressFill.style.width = `${(loadedPages / totalPages * 100).toFixed(1)}%`;
progressData.progressText.textContent =
`已下载 ${loadedPages}/${totalPages} 页 (${(loadedPages / totalPages * 100).toFixed(1)}%)`;
}
// 获取全部页面数据
async function fetchAllPages(progressData) {
const pdfDoc = await PDFDocument.create();
totalPages = Page.size;
loadedPages = 0;
progressData.container.style.display = 'block';
updateProgress(progressData);
for (let i = 1; i <= totalPages; i++) {
const pageData = await fetchPage(i);
const pageDoc = await PDFDocument.load(pageData);
const [copiedPage] = await pdfDoc.copyPages(pageDoc, [0]);
pdfDoc.addPage(copiedPage);
loadedPages++;
updateProgress(progressData);
}
return await pdfDoc.save();
}
// 获取单页数据
function fetchPage(pageNum) {
return new Promise((resolve) => {
GM_xmlhttpRequest({
method: "POST",
url: "/mnr_kfs/file/readPage",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: `code=${currentCode}&page=${pageNum}`,
responseType: "text",
onload: (res) => {
const base64Data = res.response;
const binaryData = base64ToArrayBuffer(base64Data);
resolve(binaryData);
}
});
});
}
// 启动下载流程
async function startDownloadProcess() {
const progressData = createProgressBar();
try {
currentCode = getCodeFromURL();
if (!currentCode) {
alert('无法获取文档编号,请确认当前页面正确');
return;
}
const pdfBytes = await fetchAllPages(progressData);
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
GM_download({
url: URL.createObjectURL(blob),
name: `自然资源标准_${currentCode}.pdf`,
saveAs: true
});
// 下载完成后隐藏进度条
setTimeout(() => {
progressData.container.style.display = 'none';
}, 2000);
} catch (err) {
console.error('下载失败:', err);
progressData.progressText.textContent = '下载失败,请刷新重试';
progressData.progressFill.style.background = '#ff4757';
}
}
// 初始化
(function init() {
window.render = function() {}; // 禁用原渲染
createDownloadBtn();
})();
// Base64转换工具
function base64ToArrayBuffer(base64) {
const binaryString = atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
})();