feat: 为审批和任务页面新增文件预览功能

添加文件预览组件到印章、报销、差旅审批详情页和任务详情页
移除旧版附件展示代码,统一使用新的文件预览组件
更新版本号至5.2.2
This commit is contained in:
砂糖
2026-02-25 10:53:06 +08:00
parent 53eb80dfed
commit f91ab6d45f
6 changed files with 271 additions and 4 deletions

View File

@@ -0,0 +1,227 @@
<template>
<view class="">
<view v-if="files" class="attachment-list">
<view v-for="(file, index) in attachmentFiles" :key="`${file.ossId}_${index}`" class="attachment-item"
@click="previewFile(file)">
<view class="file-icon">
<u-icon :name="getFileIcon(file.originalName)" size="24" color="#007aff"></u-icon>
</view>
<view class="file-info">
<text class="file-name">{{ getFileName(file.originalName) }}</text>
<text class="file-size">{{ formatFileSize(file.fileSize) }}</text>
</view>
<view class="file-action">
<u-icon @click.native.stop="downloadFile(file)" name="download" size="20" color="#007aff"></u-icon>
</view>
</view>
</view>
<view v-if="files && attachmentFiles.length === 0" class="no-attachment">
暂无附件
</view>
</view>
</template>
<script>
import {
getFilesByIds
} from '@/api/common/upload.js'
export default {
props: {
files: {
type: String,
required: true
}
},
data() {
return {
attachmentFiles: []
}
},
watch: {
files: {
handler(newVal) {
this.loadAttachmentFiles(newVal)
},
immediate: true,
}
},
methods: {
// 加载附件文件信息
async loadAttachmentFiles(accessory) {
try {
const ossIds = accessory.split(',').filter(id => id.trim())
if (ossIds.length > 0) {
const files = await getFilesByIds(ossIds)
this.attachmentFiles = files || []
} else {
this.attachmentFiles = []
}
} catch (error) {
console.error('加载附件失败:', error)
this.attachmentFiles = []
}
},
// 下载文件
downloadFile(file) {
// 使用uni.downloadFile下载文件
uni.downloadFile({
url: file.url,
success: (res) => {
if (res.statusCode === 200) {
// 保存文件到本地
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
uni.showToast({
title: '文件已保存到本地',
icon: 'success'
})
},
fail: (err) => {
console.error('保存文件失败:', err)
uni.showToast({
title: '保存文件失败',
icon: 'none'
})
}
})
}
},
fail: (err) => {
console.error('下载文件失败:', err)
uni.showToast({
title: '下载文件失败',
icon: 'none'
})
}
})
},
previewFile(file) {
console.log(file)
uni.showLoading({
title: '正在打开文件',
})
uni.downloadFile({
url: file.url,
success(res) {
uni.openDocument({
filePath: res.tempFilePath,
success() {
uni.hideLoading()
}
})
},
fail() {
uni.hideLoading()
}
})
},
// 获取文件图标
getFileIcon(fileName) {
const ext = fileName.split('.').pop().toLowerCase()
const iconMap = {
'pdf': 'file-text',
'doc': 'file-text',
'docx': 'file-text',
'xls': 'file-text',
'xlsx': 'file-text',
'ppt': 'file-text',
'pptx': 'file-text',
'txt': 'file-text',
'jpg': 'file-text',
'jpeg': 'file-text',
'png': 'file-text',
'gif': 'file-text',
'zip': 'folder',
'rar': 'folder',
'7z': 'folder',
'dwg': 'file-text'
}
return iconMap[ext] || 'file-text'
},
// 获取文件名
getFileName(fileName) {
if (!fileName) return ''
const name = fileName.includes('/') ? fileName.split('/').pop() : fileName
// 如果文件名超过20个字符截取前17个字符并添加省略号
if (name.length > 20) {
return name.substring(0, 17) + '...'
}
return name
},
// 格式化文件大小
formatFileSize(size) {
if (!size) return ''
if (size < 1024) {
return size + 'B'
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + 'KB'
} else {
return (size / (1024 * 1024)).toFixed(2) + 'MB'
}
},
},
}
</script>
<style>
.attachment-list {
margin-top: 16rpx;
}
.attachment-item {
display: flex;
align-items: center;
padding: 20rpx;
background-color: #f8f9fa;
border-radius: 8rpx;
margin-bottom: 16rpx;
cursor: pointer;
transition: background-color 0.2s;
}
.attachment-item:hover {
background-color: #e9ecef;
}
.file-icon {
margin-right: 16rpx;
}
.file-info {
flex: 1;
display: flex;
flex-direction: column;
}
.file-name {
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 400rpx;
}
.file-size {
font-size: 24rpx;
color: #999;
}
.file-action {
margin-left: 16rpx;
}
.no-attachment {
text-align: center;
color: #999;
font-size: 28rpx;
padding: 40rpx 0;
}
</style>