/** * 金蝶侧发票附件查看/下载公共工具 * * 票池发票附件为 {source:'piaozone', path, name}:path 是金蝶侧文件 id(非 http 直链), * 须由后端代理 A801-2 流式回源;OSS 直链附件(url/link/fileUrl)仍由前端直连下载/预览。 * 三处入口共用:票池弹窗、正式结算认领发票行、付款申请发票附件行。 */ import { ElMessage } from 'element-plus'; import { downloadFile } from '@/utils/util'; import { downloadInvoicePoolAttachment } from '@/api/payment/invoiceReceipt'; /** * 金蝶侧附件判定:source=piaozone,或有 path 且非 http(s) 直链 * @param {Object|Null} attachment 附件对象(attachmentsJson/attachmentJson 行内首项) * @returns {Boolean} */ export const isKingdeePathAttachment = attachment => { if (!attachment) return false; if (attachment.source === 'piaozone') return true; return Boolean(attachment.path) && !/^https?:\/\//i.test(attachment.path); }; /** * 请求金蝶文件流:成功返回 Blob;业务失败为 HTTP 200 + R.fail JSON(响应通道未写流时后端即失败), * 按 Content-Type 识别并抛出带 msg 的错误;网络级失败拦截器已提示,标记 silent 避免重复提示 * @param {String} invoiceNo 发票号码 * @returns {Promise} */ const requestKingdeeFile = async invoiceNo => { let res; try { res = await downloadInvoicePoolAttachment(invoiceNo); } catch (error) { throw Object.assign(new Error(error?.message || '附件下载失败'), { silent: true }); } const blob = res?.data; if (!(blob instanceof Blob)) { throw new Error('响应不是文件流'); } if (blob.type && blob.type.includes('application/json')) { let message = '附件下载失败'; try { const parsed = JSON.parse(await blob.text()); message = parsed.msg || parsed.message || message; } catch { // 错误体非 JSON 时按默认提示 } throw new Error(message); } return blob; }; /** * 下载金蝶侧发票附件(经 A801-2 后端代理),失败统一 ElMessage 提示 * @param {String} invoiceNo 发票号码 * @param {String} fileName 下载文件名(缺省按 发票号.pdf) */ export const downloadKingdeeInvoiceFile = async (invoiceNo, fileName) => { if (!invoiceNo) { ElMessage.warning('当前发票缺少发票号码,无法下载金蝶侧附件'); return; } try { const blob = await requestKingdeeFile(invoiceNo); downloadFile(blob, fileName || `${invoiceNo}.pdf`); } catch (error) { if (!error?.silent) ElMessage.error(error?.message || '金蝶附件下载失败'); } }; /** * 新窗口预览金蝶侧发票附件:拉取 Blob 转 objectURL(PDF 可预览;OFD 等浏览器不可预览的格式由浏览器触发下载) * @param {String} invoiceNo 发票号码 * @param {String} fileName 预览文件名(缺省按 发票号.pdf) */ export const viewKingdeeInvoiceFile = async (invoiceNo, fileName) => { if (!invoiceNo) { ElMessage.warning('当前发票缺少发票号码,无法预览金蝶侧附件'); return; } try { const blob = await requestKingdeeFile(invoiceNo); const url = URL.createObjectURL(blob); window.open(url, '_blank'); // 延迟释放 objectURL:立即回收可能导致新窗口尚未加载完成即失效 setTimeout(() => URL.revokeObjectURL(url), 60000); } catch (error) { if (!error?.silent) ElMessage.error(error?.message || '金蝶附件预览失败'); } };