hookehuyr

feat(favorites): 新增收藏列表项下载功能

- 在删除按钮旁新增下载按钮
- 实现文件下载预览功能(支持 PDF、Office 文档等)
- 智能文件类型识别,针对 Office 文档提供预览限制提示
- 优化下载失败和文件无法预览时的用户提示
- 添加文件下载地址字段到数据模型

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -39,9 +39,16 @@
</view>
</view>
<!-- Delete Button -->
<view class="p-[10rpx]" @tap.stop="onDelete(item)">
<IconFont name="Del" size="18" color="#999" />
<!-- Action Buttons -->
<view class="flex items-center gap-[16rpx]">
<!-- Download Button -->
<view class="p-[10rpx]" @tap.stop="onDownload(item)">
<IconFont name="Download" size="18" color="#007AFF" />
</view>
<!-- Delete Button -->
<view class="p-[10rpx]" @tap.stop="onDelete(item)">
<IconFont name="Del" size="18" color="#999" />
</view>
</view>
</view>
......@@ -85,7 +92,9 @@ const list = ref([
type: 'onboarding',
icon: 'Order', // Represents a document
iconColor: '#EF4444', // Red for PDF
iconBgClass: 'bg-red-50'
iconBgClass: 'bg-red-50',
// 使用真实的可下载 PDF 文件(W3C 测试文件)
downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/1_%E7%BE%8E%E4%B9%90%E7%88%B1%E8%A7%89%E6%95%99%E8%82%B22024%E9%A1%B9%E7%9B%AE%E5%9B%BE%E5%BD%B1%E4%BB%8B%E7%BB%8D_.pdf'
},
{
id: 2,
......@@ -95,7 +104,9 @@ const list = ref([
type: 'signing',
icon: 'Order', // Represents a document
iconColor: '#2563EB', // Blue for Word
iconBgClass: 'bg-blue-50'
iconBgClass: 'bg-blue-50',
// 使用真实的可下载图片(作为文档示例)
downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/%E8%80%81%E6%9D%A5%E8%B5%9B%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96.docx'
},
{
id: 3,
......@@ -105,7 +116,9 @@ const list = ref([
type: 'product',
icon: 'Order', // Represents a document
iconColor: '#F59E0B', // Orange for PPT
iconBgClass: 'bg-orange-50'
iconBgClass: 'bg-orange-50',
// 使用另一个图片作为示例
downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/%E8%82%A1%E5%88%A4%E5%90%88%E5%8F%8B%E7%94%A8%E7%9F%A5%E8%AF%86%E8%AF%B4%E6%98%8E20240112110417414.pptx'
},
{
id: 4,
......@@ -115,7 +128,8 @@ const list = ref([
type: 'other',
icon: 'Edit', // Represents text
iconColor: '#10B981', // Green for TXT
iconBgClass: 'bg-green-50'
iconBgClass: 'bg-green-50',
downloadUrl: '' // 空下载地址,用于测试无地址情况
}
])
......@@ -128,6 +142,67 @@ const onView = (item) => {
Taro.showToast({ title: `打开: ${item.title}`, icon: 'none' })
}
// 打开文件的通用函数
const openFile = async (filePath, item) => {
try {
await Taro.openDocument({
filePath: filePath,
showMenu: true, // 显示右上角菜单,用户可以转发、保存等
success: () => {
console.log('文件打开成功')
// 文件打开后,延迟提示用户如果看不到内容该如何操作
const fileExt = item.title.split('.').pop()?.toLowerCase() || ''
const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls']
if (unsupportedFormats.includes(fileExt)) {
setTimeout(() => {
Taro.showToast({
title: '如无法预览,请使用右上角菜单分享',
icon: 'none',
duration: 3000
})
}, 1500)
}
},
fail: (err) => {
console.error('打开文件失败:', err)
// 获取文件扩展名
const fileExt = item.title.split('.').pop()?.toLowerCase() || ''
// 根据文件类型给出提示
let message = '文件打开失败'
let suggestion = ''
if (['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'].includes(fileExt)) {
message = '暂不支持预览 Office 文档'
suggestion = '\n\n建议:\n1. 点击右上角"..."菜单\n2. 选择"发送给朋友"\n3. 在电脑或支持的应用中打开'
} else if (['pdf'].includes(fileExt)) {
message = 'PDF 文件打开失败'
suggestion = '\n\n文件可能已损坏,请联系管理员'
} else {
message = `暂不支持预览 ${fileExt.toUpperCase()} 格式文件`
suggestion = '\n\n请在电脑或其他应用中打开'
}
Taro.showModal({
title: '提示',
content: message + suggestion,
showCancel: false,
confirmText: '我知道了'
})
}
})
} catch (error) {
console.error('打开文件异常:', error)
Taro.showToast({
title: '打开文件失败',
icon: 'none',
duration: 2000
})
}
}
const onDelete = (item) => {
Taro.showModal({
title: '提示',
......@@ -140,6 +215,97 @@ const onDelete = (item) => {
}
})
}
const onDownload = (item) => {
// 检查是否有下载地址
if (!item.downloadUrl) {
Taro.showToast({
title: '该文件暂无下载地址',
icon: 'none',
duration: 2000
})
return
}
// 显示确认弹窗
Taro.showModal({
title: '下载确认',
content: `确定要下载"${item.title}"吗?`,
confirmText: '下载',
cancelText: '取消',
success: async (res) => {
if (res.confirm) {
// 显示加载提示
Taro.showLoading({
title: '下载中...',
mask: true
})
try {
// 下载文件
const downloadResult = await Taro.downloadFile({
url: item.downloadUrl
})
// 检查下载结果
if (downloadResult.statusCode !== 200) {
throw new Error(`下载失败: HTTP ${downloadResult.statusCode}`)
}
if (!downloadResult.tempFilePath) {
throw new Error('下载失败: 未获取到文件')
}
// 隐藏加载提示
Taro.hideLoading()
// 获取文件扩展名
const fileExt = item.title.split('.').pop()?.toLowerCase() || ''
// 微信小程序对 Office 文档支持有限,提前提示用户
const unsupportedFormats = ['docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls']
if (unsupportedFormats.includes(fileExt)) {
// 对于 Office 文档,先提示用户,但仍尝试打开
Taro.showModal({
title: '预览提示',
content: `小程序对 ${fileExt.toUpperCase()} 文档的预览支持有限,如果显示为空白,请点击右上角"..."菜单,选择"发送给朋友"后在电脑或其他应用中打开。\n\n是否继续尝试预览?`,
confirmText: '继续',
cancelText: '取消',
success: (modalRes) => {
if (modalRes.confirm) {
openFile(downloadResult.tempFilePath, item)
}
}
})
} else {
// 其他格式直接打开
await openFile(downloadResult.tempFilePath, item)
}
} catch (error) {
// 确保隐藏加载提示
Taro.hideLoading()
console.error('下载过程出错:', error)
// 根据错误类型显示不同的提示
let errorMessage = '下载失败,请重试'
if (error.errMsg && error.errMsg.includes('network')) {
errorMessage = '网络连接失败,请检查网络'
} else if (error.errMsg && error.errMsg.includes('TLS')) {
errorMessage = '安全连接失败,请检查网络'
}
Taro.showToast({
title: errorMessage,
icon: 'none',
duration: 2000
})
}
}
}
})
}
</script>
<style lang="less">
......