Files
shanxia2.0/miniprogram/pages/common/contract-document.vue
T

76 lines
3.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="contract-document">
<text class="contract-document__title">{{ fileName }}</text>
<text>{{ message }}</text>
<button :disabled="busy || !documentInfo" @click="openDocument">{{ busy ? '正在打开…' : '打开文档' }}</button>
<text class="contract-document__hint">打开后可从右上角菜单转发文件;打印请将 PDF 交给支持打印的应用或电脑。</text>
<button @click="goBack">返回合同</button>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import { MINIO_BASE_URL } from '@/config/env'
import { validateContractDocument, contractDownloadErrorMessage } from '@/utils/contract-document'
const fileName = ref('合同文档')
const message = ref('正在准备文档…')
const busy = ref(false)
const documentInfo = ref(null)
let localPath = ''
let alive = true
let downloadTask
function removeTemp(path) {
if (!path) return
try { uni.getFileSystemManager().unlink({ filePath: path, fail() {} }) } catch {}
}
function goBack() { uni.navigateBack({ delta: 1 }) }
async function openDocument() {
if (busy.value || !documentInfo.value) return
busy.value = true
message.value = '正在下载并打开文档…'
try {
if (!localPath) {
localPath = await new Promise((resolve, reject) => {
downloadTask = uni.downloadFile({
url: documentInfo.value.url,
success: (res) => {
if (!alive) { removeTemp(res.tempFilePath); reject(new Error('已关闭')); return }
if (res.statusCode !== 200) { removeTemp(res.tempFilePath); reject(new Error('文件下载失败,请返回合同重新生成')); return }
resolve(res.tempFilePath)
},
fail: (error) => reject(new Error(contractDownloadErrorMessage(error, documentInfo.value.url)))
})
})
}
if (!alive) return
await new Promise((resolve, reject) => uni.openDocument({
filePath: localPath,
fileType: documentInfo.value.type,
showMenu: true,
success: resolve,
fail: () => reject(new Error('无法打开文档,请重试'))
}))
message.value = '文档已打开,可再次打开或返回继续编辑合同。'
} catch (error) {
if (alive) message.value = error.message || '打开失败,请重试'
} finally { if (alive) busy.value = false }
}
onLoad((query) => {
try {
// uni-app 页面参数按平台可能已解码,最多解码一次完整 URL。
const url = /^https?:\/\//.test(query?.url || '') ? query.url : decodeURIComponent(query?.url || '')
documentInfo.value = validateContractDocument({ ...query, url }, MINIO_BASE_URL)
fileName.value = documentInfo.value.name
try { fileName.value = decodeURIComponent(fileName.value) } catch { /* 参数可能已由宿主解码 */ }
void openDocument()
} catch (error) { message.value = error.message || '无效的文档地址' }
})
onUnload(() => { alive = false; downloadTask?.abort(); removeTemp(localPath) })
</script>
<style scoped>
.contract-document { padding: 24px 16px; display: flex; flex-direction: column; gap: 16px; color: #243b33; }
.contract-document__title { font-size: 18px; font-weight: 600; word-break: break-all; }
.contract-document button { width: 100%; min-height: 44px; color: #0a9f6d; background: #e9f9f2; }
.contract-document__hint { font-size: 13px; color: #6b7b74; line-height: 1.6; }
</style>