<template>
<view class="card_box">
<view class="card_body" @tap="toFileReport">
<view class="data">
<view class="title"> {{ item.name }} </view>
<view class="text">备注:{{ item.remark}}</view>
</view>
<view class="state">
<view
class="report"
>
{{ item.status }}
</view>
<view class="line">
<u-icon name="arrow-right"></u-icon>
</view>
</view>
</view>
<view class="progress-container" v-if="isShowProgress">
<view class="progress-box">
<view class="text">文件下载中,请稍后......</view>
<progress
style="margin-bottom: 10px"
:percent="progress"
show-info
stroke-width="3"
/>
<u-button
type="primary"
shape="circle"
text="取消下载"
size="small"
@tap="cancelDownload"
></u-button>
</view>
</view>
</view>
</template>
<script>
import { openPdfFileByBusKey } from '具体的接口文件路径'
export default {
data() {
return {
injectData: '',
isShowProgress: false,
progress: 0,
isCancelling: false,
// 添加一个防抖动的定时器
cancelDebounceTimer: null,
downloadTask: null // 添加下载任务对象
}
},
props: {
item: {
type: Object,
default: () => ({})
}
},
methods: {
cancelDownload() {
if (this.cancelDebounceTimer) {
clearTimeout(this.cancelDebounceTimer)
}
this.cancelDebounceTimer = setTimeout(() => {
if (this.downloadTask && !this.isCancelling) {
this.isCancelling = true
this.downloadTask.abort()
this.downloadTask = null
// 延迟更新状态,确保取消操作完成
setTimeout(() => {
this.isShowProgress = false
this.progress = 0
uni.showToast({
title: '下载已取消',
icon: 'none'
})
this.isCancelling = false
}) // 延迟100毫秒更新状态
} else if (!this.isCancelling) {
this.isShowProgress = false
this.progress = 0
uni.showToast({
title: '没有正在进行的下载',
icon: 'none'
})
}
}, 300) // 防抖动时间设置为300毫秒
},
downloadFile(flag) {
if (this.injectData == '') {
uni.showToast({
title: '文件路径为空',
icon: 'none'
})
return
}
// 获取文件名和类型信息
const fileInfo = this.parseFilenameAndType(this.injectData)
const fileName = `${fileInfo.fileName}.${fileInfo.fileType}`
// 检查文件是否已存在于本地缓存中
const fileManager = uni.getFileSystemManager()
const userPath = uni.env.USER_DATA_PATH
const filePath = `${userPath}/${fileName}`
try {
// 尝试获取文件信息,检查文件是否存在
fileManager.accessSync(filePath)
// 如果文件存在,直接使用缓存文件
console.log('文件已存在,直接使用缓存')
this.handleExistingFile(filePath, fileInfo.fileType, flag)
} catch (e) {
// 文件不存在,需要下载
console.log('文件不存在,开始下载')
this.downloadAndSaveFile(filePath, fileInfo, flag)
}
},
// 处理已存在的文件
handleExistingFile(filePath, fileType, flag) {
let that = this
if (flag) {
// 分享到微信
uni.showModal({
title: '提示',
content: '确定分享吗?',
cancelText: '取消',
confirmText: '确定',
success: function (res) {
if (res.confirm) {
const result = that.parseFilenameAndType(
that.injectData
)
uni.shareFileMessage({
filePath: filePath,
fileType: fileType,
fileName: `${result.fileName}.${result.fileType}`,
success: () => {
console.log('分享文件成功')
},
fail: (err) => {
uni.showToast({
title: '分享文件失败',
icon: 'none'
})
}
})
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else {
// 打开文档预览
uni.openDocument({
filePath: filePath,
fileType: fileType,
showMenu: true,
success: (sus) => {
console.log('成功打开')
},
fail: (err) => {
uni.showToast({
title: '文件打开失败',
icon: 'none'
})
}
})
}
},
// 下载并保存文件
downloadAndSaveFile(targetFilePath, fileInfo, flag) {
let that = this
this.downloadTask = uni.downloadFile({
url: this.injectData.replace(/\\/g, '/'), // 下载url
success: (res) => {
if (res.statusCode === 200) {
// 直接保存到指定路径,而不是使用系统临时路径
uni.getFileSystemManager().saveFile({
tempFilePath: res.tempFilePath,
filePath: targetFilePath,
success: function (red) {
that.isShowProgress = false
that.handleExistingFile(
targetFilePath,
fileInfo.fileType,
flag
)
},
fail: function (err) {
that.isShowProgress = false
uni.showToast({
title: '文件保存失败!',
icon: 'none'
})
console.error('文件保存失败', err)
}
})
} else {
that.isShowProgress = false
uni.showToast({
title: '文件下载失败!',
icon: 'none'
})
}
},
fail: (err) => {
that.isShowProgress = false
uni.showToast({
title: '文件下载失败!',
icon: 'none'
})
console.error('下载失败', err)
}
})
this.downloadTask.onProgressUpdate((res) => {
if (res.progress > 0) {
this.isShowProgress = true
}
this.progress = res.progress
// console.log('下载进度:' + res.progress)
// console.log('已下载长度:' + res.totalBytesWritten)
// console.log('文件总长度:' + res.totalBytesExpectedToWrite)
})
},
parseFilenameAndType(filePath) {
// 获取文件名称(包括扩展名)
const fileNameWithExtension = filePath.split('/').pop()
// 分离文件名称和扩展名
const fileNameParts = fileNameWithExtension.split('.')
const fileName = fileNameParts
.slice(0, fileNameParts.length - 1)
.join('.')
const fileType = fileNameParts[fileNameParts.length - 1]
return {
fileName: fileName,
fileType: fileType
}
},
toFileReport() {
if (!this.item.busKey) {
uni.showToast({
title: '暂无文件',
icon: 'none'
})
return
}
openPdfFileByBusKey({
busKey: this.item.busKey
}).then((res) => {
this.injectData = res.data.result
? JSON.parse(res.data.result).path
: ''
this.$nextTick(() => {
this.downloadFile()
})
})
}
}
}
</script>
<style lang="scss" scoped>
.card_box {
margin: 20upx 0;
padding: 20upx;
background-color: #fff;
border-radius: 12upx;
.card_body {
display: flex;
justify-content: space-between;
.data {
width: 75%;
height: 100%;
display: flex;
flex-direction: column;
view {
flex: 1;
padding: 10upx 0;
}
.title {
white-space: nowrap; // 使文本不换行显示
overflow: hidden;
text-overflow: ellipsis; // 显示省略号
}
.text {
color: #999999;
font-size: 26upx;
white-space: nowrap; // 使文本不换行显示
overflow: hidden;
text-overflow: ellipsis; // 显示省略号
}
}
.state {
width: 15%;
height: 100%;
text-align: right;
display: flex;
flex-direction: column;
.color {
color: #ff7a00;
}
.report {
padding: 10upx 0;
}
.line {
flex: 1;
height: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 160upx;
}
}
}
.card_action {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 10upx 0;
}
}
.customStyle {
width: 170upx;
margin: 0 10upx;
}
.progress-container {
position: fixed;
top: 0;
left: 0;
z-index: 99;
background: rgba(0, 0, 0, 0.2);
width: 750rpx;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
.progress-box {
background: #ffffff;
border-radius: 20rpx;
padding: 30rpx;
.text {
margin-bottom: 20rpx;
}
}
}
</style>
uniapp开发微信小程序实现文件分享及预览功能(带进度条)
于 2025-06-18 15:18:35 首次发布