一、编辑器端:插入 PDF 功能
1.1 在 createToolbar 中添加按钮
找到插入分组(图片、视频、链接、表格等附近),增加:
{ custom: () => this.insertPDF(), icon: '📄', title: '插入PDF' }
1.2 实现 insertPDF 方法
insertPDF() { const choice = confirm('点击"确定"上传本地PDF,点击"取消"输入PDF链接'); if (choice) { this.uploadLocalPDF(); } else { this.embedPDFUrl(); } } uploadLocalPDF() { const input = document.createElement('input'); input.type = 'file'; input.accept = 'application/pdf'; input.onchange = async () => { const file = input.files[0]; if (!file) return; const placeholder = `📄 PDF上传中: ${file.name}...`; document.execCommand('insertText', false, placeholder); const formData = new FormData(); formData.append('attachment', file); // 使用附件上传接口,但限制 PDF 类型(您可能需要单独的上传接口或修改现有接口) // 这里假设 /admin/upload_attachment.php 支持 PDF const res = await fetch(this.attachmentUploadUrl, { method: 'POST', body: formData }); const data = await res.json(); if (data.url) { const pdfHtml = `<div class="pdf-viewer" data-pdf="${data.url}" style="margin:10px 0; border:1px solid #ddd; padding:10px; background:#f9f9f9; text-align:center;">📄 PDF文件: <a href="${data.url}" target="_blank">${file.name}</a> <span style="color:#1abc9c;">(点击右侧按钮可在线预览)</span></div>`; this.editorDiv.innerHTML = this.editorDiv.innerHTML.replace(placeholder, pdfHtml); } else { alert('上传失败:' + (data.error || '未知错误')); this.editorDiv.innerHTML = this.editorDiv.innerHTML.replace(placeholder, ''); } this.syncToTextarea(); }; input.click(); } embedPDFUrl() { const url = prompt('请输入PDF文件链接(URL):', 'https://'); if (!url) return; const pdfHtml = `<div class="pdf-viewer" data-pdf="${this.escapeHtml(url)}" style="margin:10px 0; border:1px solid #ddd; padding:10px; background:#f9f9f9; text-align:center;">📄 PDF文件: <a href="${this.escapeHtml(url)}" target="_blank">点击下载</a> <span style="color:#1abc9c;">(加载中...)</span></div>`; document.execCommand('insertHTML', false, pdfHtml); this.syncToTextarea(); }
注意:您需要确保上传接口(upload_attachment.php)支持 PDF 文件(已经支持,因为之前 allowed 包含 application/pdf)。
二、前台使用 PDF.js 渲染 PDF,支持左右翻页
2.1 下载 PDF.js 并放置到您的项目中
从 https://mozilla.github.io/pdf.js/ 下载最新稳定版,解压后将 build/ 目录下的 pdf.js 和 pdf.worker.js 以及 web/ 下的 viewer.html 等资源放到您的 assets/js/pdfjs/ 目录。
但为了简化,我们可以在前台直接动态加载 PDF.js 的 CDN,并自定义一个轻量级查看器。
2.2 在前台 article.php 或 header.php 中添加 PDF.js 的加载(仅当页面包含 PDF 时加载)
在 article.php 的文章内容输出之后,添加以下脚本:
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script> <script> // 设置 worker pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js'; // 为所有 .pdf-viewer 元素渲染 PDF 预览 document.querySelectorAll('.pdf-viewer').forEach(container => { const pdfUrl = container.getAttribute('data-pdf'); if (!pdfUrl) return; // 创建画布和翻页按钮 container.innerHTML = ''; // 清空原有内容 container.style.cssText = 'position:relative; background:#f0f0f0; border:1px solid #ccc; border-radius:8px; padding:10px; text-align:center;'; const canvas = document.createElement('canvas'); canvas.style.maxWidth = '100%'; canvas.style.height = 'auto'; container.appendChild(canvas); const controls = document.createElement('div'); controls.style.marginTop = '10px'; controls.innerHTML = ` <button class="pdf-prev" disabled>◀ 上一页</button> <span class="pdf-page-info">第 0 / 0 页</span> <button class="pdf-next" disabled>下一页 ▶</button> <button class="pdf-download">⬇️ 下载</button> `; container.appendChild(controls); let pdfDoc = null; let currentPage = 1; let totalPages = 0; const renderPage = (num) => { pdfDoc.getPage(num).then(page => { const viewport = page.getViewport({ scale: 1.5 }); canvas.width = viewport.width; canvas.height = viewport.height; const ctx = canvas.getContext('2d'); page.render({ canvasContext: ctx, viewport: viewport }); controls.querySelector('.pdf-page-info').innerText = `第 ${num} / ${totalPages} 页`; controls.querySelector('.pdf-prev').disabled = (num === 1); controls.querySelector('.pdf-next').disabled = (num === totalPages); }); }; pdfjsLib.getDocument(pdfUrl).promise.then(doc => { pdfDoc = doc; totalPages = doc.numPages; renderPage(1); }).catch(err => { container.innerHTML = `<div style="color:red;">PDF加载失败: ${err.message}</div>`; }); controls.querySelector('.pdf-prev').onclick = () => { if (currentPage > 1) renderPage(--currentPage); }; controls.querySelector('.pdf-next').onclick = () => { if (currentPage < totalPages) renderPage(++currentPage); }; controls.querySelector('.pdf-download').onclick = () => { window.open(pdfUrl, '_blank'); }; }); </script>
2.3 注意事项
跨域问题:如果 PDF 链接是跨域的,PDF.js 可能无法加载。建议将 PDF 上传到本站,使用同源 URL。
性能:大 PDF 文件可能加载较慢,可增加 loading 提示。
移动端适配:画布宽度自适应,按钮大小适合触摸。
三、优化:在编辑器内预览 PDF(可选)
您也可以在编辑器内部实现 PDF 预览(使用相同的 PDF.js 逻辑),但考虑到编辑器复杂度,建议仅在前台展示即可。用户插入时看到的占位符足够清晰。
四、总结
编辑器:增加了“插入PDF”按钮,支持上传或链接。
前台:使用 PDF.js 渲染,提供翻页控件,左右翻页浏览。
兼容性:现代浏览器均支持,IE 忽略。
发表评论 (0)
留下你的足迹