diff --git a/mobile-oa-h5/src/oa/print/exportOaApprovalPdf.js b/mobile-oa-h5/src/oa/print/exportOaApprovalPdf.js index 668920a7..7e3affae 100644 --- a/mobile-oa-h5/src/oa/print/exportOaApprovalPdf.js +++ b/mobile-oa-h5/src/oa/print/exportOaApprovalPdf.js @@ -5,6 +5,8 @@ */ import html2canvas from 'html2canvas' import { jsPDF } from 'jspdf' +import { uploadAttachment, fetchAttachmentDownloadUrl } from '../../api/oa.js' +import { attachmentFullUrl } from '../../utils/attachment.js' import { formatDeptDisplay } from '../kit/oa-dept-value.js' import { formatPersonDisplay } from '../kit/oa-person-value.js' import { formatIdNameDisplay } from '../../utils/id-name-value.js' @@ -871,68 +873,110 @@ function isWeChatMiniWebView() { return false } +function navigateToHostPdfPreview({ url, fileName }) { + const q = + 'url=' + + encodeURIComponent(url) + + '&name=' + + encodeURIComponent(fileName || 'approval.pdf') + const path = '/pages/oa/pdf-preview/index?' + q + try { + if (typeof wx !== 'undefined' && wx.miniProgram?.navigateTo) { + wx.miniProgram.navigateTo({ url: path }) + return true + } + } catch { + /* ignore */ + } + try { + if (typeof uni !== 'undefined' && uni.webView?.navigateTo) { + uni.webView.navigateTo({ url: path }) + return true + } + } catch { + /* ignore */ + } + return false +} + /** - * 打开可打印 HTML 并调用 window.print()。 - * @returns {Promise<{ ok: boolean, message?: string }>} + * @returns {Promise<{ ok: boolean, message?: string, mode?: 'preview' | 'download' }>} */ export async function exportOaApprovalPdf(detail, opts = {}) { if (!detail) { - return { ok: false, message: '暂无审批详情,无法打印' } + return { ok: false, message: '暂无审批详情,无法导出 PDF' } } - const model = buildOaPrintModel(detail, { - printerName: opts.printerName || '' - }) - const html = buildPrintHtml(model) - - // 微信小程序 web-view 内系统打印能力普遍不可用 - if (isWeChatMiniWebView()) { - return { - ok: false, - message: '微信内暂不支持系统打印,请用手机浏览器打开或到电脑端导出' - } - } - - let frame = null + let blob + let filename try { - frame = document.createElement('iframe') - frame.setAttribute('title', 'oa-print') - frame.style.cssText = - 'position:fixed;right:0;bottom:0;width:0;height:0;border:0;opacity:0;pointer-events:none;' - document.body.appendChild(frame) - - const doc = frame.contentDocument || frame.contentWindow?.document - if (!doc || !frame.contentWindow) { - throw new Error('print frame unavailable') - } - doc.open() - doc.write(html) - doc.close() - - await new Promise((r) => setTimeout(r, 80)) - const win = frame.contentWindow - if (typeof win.print !== 'function') { - throw new Error('print not supported') - } - win.focus() - win.print() - return { ok: true } + ;({ blob, filename } = await generateOaApprovalPdfBlob(detail, opts)) } catch (e) { return { ok: false, - message: - (e && e.message) || - '当前环境无法调起打印,请用手机浏览器打开或到电脑端导出' + message: (e && e.message) || '生成 PDF 失败' } - } finally { - if (frame) { - setTimeout(() => { - try { - frame.remove() - } catch { - /* ignore */ + } + + if (isWeChatMiniWebView()) { + try { + const file = new File([blob], filename, { type: 'application/pdf' }) + const res = await uploadAttachment(file) + const fileUrl = String(res?.fileUrl || res?.data?.fileUrl || '').trim() + if (!fileUrl) { + return { ok: false, message: '上传 PDF 失败:无文件地址' } + } + + let openUrl = '' + try { + const dl = await fetchAttachmentDownloadUrl({ + fileUrl, + fileName: filename + }) + openUrl = String(dl?.downloadUrl || dl?.data?.downloadUrl || '').trim() + } catch { + /* fall through */ + } + if (!openUrl) { + openUrl = attachmentFullUrl(fileUrl) || fileUrl + } + if (!/^https?:\/\//i.test(openUrl)) { + return { ok: false, message: '无法打开 PDF:下载地址无效' } + } + + const navigated = navigateToHostPdfPreview({ + url: openUrl, + fileName: filename + }) + if (!navigated) { + return { + ok: false, + message: '无法跳转预览页,请升级微信后重试' } - }, 1500) + } + return { ok: true, mode: 'preview' } + } catch (e) { + return { + ok: false, + message: (e && e.message) || '上传或打开 PDF 失败' + } + } + } + + try { + const href = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = href + a.download = filename + document.body.appendChild(a) + a.click() + a.remove() + setTimeout(() => URL.revokeObjectURL(href), 2000) + return { ok: true, mode: 'download' } + } catch (e) { + return { + ok: false, + message: (e && e.message) || '下载 PDF 失败' } } }