新增revisionId参数到路由、服务及导出接口,实现不同评估版本的隔离访问。删除已废弃的需求相关服务文件,移除取消采集的融资金额、期限和用途字段,更新相关页面提示文本。同时更新文档,说明评估版本、最新资料及产品展示规则的调整,支持前台正常业务名称显示,去除环境标签。
65 lines
4.5 KiB
Plaintext
65 lines
4.5 KiB
Plaintext
import { API_BASE_URL, getSession, clearSession } from '@/services/api.uts'
|
|
import { APP_ENVIRONMENT } from '@/services/config.uts'
|
|
|
|
export type ReportDownload = { cancel: () => void, done: Promise<string> }
|
|
|
|
export function downloadReportPdf(id: string, revisionId: string = ''): ReportDownload {
|
|
// 首版仅开放普通浏览器H5;其他端明确提示,不生成假文件或成功回执。
|
|
// #ifndef H5
|
|
return { cancel: () => {}, done: new Promise<string>((_resolve, reject) => { reject(new Error('当前客户端暂未开放PDF下载,请在普通浏览器打开H5并登录后下载。')) }) }
|
|
// #endif
|
|
// #ifdef H5
|
|
const controller = new AbortController()
|
|
let cancelled = false
|
|
const cancel = () => { cancelled = true; controller.abort() }
|
|
const done = async (): Promise<string> => {
|
|
if (!/^[1-9][0-9]{0,9}$/.test(id)) throw new Error('报告编号无效,请重新打开本人报告。')
|
|
if (/MicroMessenger/i.test(navigator.userAgent)) throw new Error('微信内浏览器暂不支持此下载。请点右上角菜单,选择“在浏览器打开”,登录后重新点击下载PDF。')
|
|
const token = getSession()?.getString('token') ?? ''
|
|
if (token.length == 0) throw new Error('登录已过期,请重新登录后下载。')
|
|
if (API_BASE_URL.length == 0 || (APP_ENVIRONMENT == 'production' && !API_BASE_URL.startsWith('https://'))) throw new Error('下载服务地址尚未配置。')
|
|
const current = () => {
|
|
if (cancelled || getSession()?.getString('token') != token) throw new Error('页面或登录状态已变化,本次下载已取消。')
|
|
}
|
|
const timeout = setTimeout(() => controller.abort(), 45000)
|
|
try {
|
|
const response = await fetch(API_BASE_URL + '/assessments/' + id + '/report.pdf' + (revisionId.length > 0 ? '?revisionId=' + encodeURIComponent(revisionId) : ''), {
|
|
method: 'GET', headers: { Authorization: 'Bearer ' + token, 'X-Requested-With': 'XMLHttpRequest' },
|
|
cache: 'no-store', credentials: 'omit', redirect: 'error', signal: controller.signal
|
|
})
|
|
current()
|
|
if (response.status == 401) { clearSession(); throw new Error('登录已过期,请重新登录后下载。') }
|
|
const mime = (response.headers.get('Content-Type') ?? '').split(';')[0].trim().toLowerCase()
|
|
if (!response.ok || mime != 'application/pdf') {
|
|
let message = 'PDF暂不可下载,请稍后重试;已保存报告不受影响。'
|
|
if (mime == 'application/json') {
|
|
const body = await response.json()
|
|
if (typeof body.msg == 'string' && body.msg.length > 0 && body.msg.length < 200) message = body.msg
|
|
}
|
|
current(); throw new Error(message)
|
|
}
|
|
const declaredSize = Number(response.headers.get('Content-Length') ?? '0')
|
|
if (declaredSize > 20971520) throw new Error('PDF文件过大,请联系管理员。')
|
|
const bytes = await response.arrayBuffer()
|
|
current()
|
|
const start = new TextDecoder('ascii').decode(bytes.slice(0, 5))
|
|
const end = new TextDecoder('ascii').decode(bytes.slice(Math.max(0, bytes.byteLength - 1024)))
|
|
if (bytes.byteLength < 100 || bytes.byteLength > 20971520 || start != '%PDF-' || !end.includes('%%EOF')) throw new Error('下载内容不是完整PDF,请重试。')
|
|
// 验证响应后才创建本机Blob。令牌只放请求头,不写URL、文件名或本机存储。
|
|
const url = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }))
|
|
const link = document.createElement('a')
|
|
link.href = url; link.download = 'financing-report-' + id + '.pdf'; link.style.display = 'none'
|
|
document.body.appendChild(link); link.click(); link.remove()
|
|
setTimeout(() => URL.revokeObjectURL(url), 1000)
|
|
return 'PDF已交给浏览器处理,请查看下载列表;若打开预览,可使用浏览器的保存功能。'
|
|
} catch (err) {
|
|
if (cancelled) throw new Error('下载已取消。')
|
|
if (controller.signal.aborted) throw new Error('PDF生成超时,请稍后重试。')
|
|
if (err instanceof TypeError) throw new Error('网络连接失败,请检查网络后重试。')
|
|
throw err
|
|
} finally { clearTimeout(timeout) }
|
|
}
|
|
return { cancel, done: done() }
|
|
// #endif
|
|
}
|