chore:H5正常

This commit is contained in:
2026-08-26 18:13:00 +08:00
parent 3ca1ca8cd7
commit e3171ef7ad
2 changed files with 149 additions and 0 deletions

View File

@@ -38,12 +38,31 @@
<view class="content">
<!-- PDF 文件预览 -->
<view v-if="fileType === 'pdf'" class="file-viewer">
<!-- #ifdef H5 -->
<!-- H5 端:web-view 渲染为 iframe,若被 X-Frame-Options/CORS 拦截则显示空白;额外提供"新标签页打开"与"下载"按钮兜底 -->
<view class="h5-action-bar">
<view class="h5-action-tip">如页面空白,请使用下方按钮:</view>
<view class="h5-action-btns">
<button class="h5-action-btn primary" @click="openInNewTab">新标签页打开</button>
<button class="h5-action-btn" @click="triggerDownload">下载文件</button>
</view>
</view>
<!-- #endif -->
<web-view v-if="fileUrl" :src="fileUrl"></web-view>
<view v-else class="error-message">{{ $lang('file-preview.file-preview.fileUrlNotExist') }}</view>
</view>
<!-- Word 文件预览 -->
<view v-else-if="fileType === 'word'" class="file-viewer">
<!-- #ifdef H5 -->
<view class="h5-action-bar">
<view class="h5-action-tip">浏览器可能无法直接内嵌预览 Word,建议下载后查看:</view>
<view class="h5-action-btns">
<button class="h5-action-btn primary" @click="triggerDownload">下载文件</button>
<button class="h5-action-btn" @click="openInNewTab">新标签页打开</button>
</view>
</view>
<!-- #endif -->
<web-view v-if="fileUrl" :src="fileUrl"></web-view>
<view v-else class="error-message">{{ $lang('file-preview.file-preview.fileUrlNotExist') }}</view>
</view>
@@ -56,7 +75,19 @@
<!-- 其他文件类型 -->
<view v-else class="file-viewer">
<!-- #ifdef H5 -->
<view v-if="fileUrl" class="h5-action-bar">
<view class="h5-action-tip">{{ $lang('file-preview.file-preview.unsupportedFileType') }}</view>
<view class="h5-action-btns">
<button class="h5-action-btn primary" @click="triggerDownload">下载文件</button>
<button class="h5-action-btn" @click="openInNewTab">新标签页打开</button>
</view>
</view>
<view v-else class="error-message">{{ $lang('file-preview.file-preview.fileUrlNotExist') }}</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="error-message">{{ $lang('file-preview.file-preview.unsupportedFileType') }}</view>
<!-- #endif -->
</view>
</view>
</view>
@@ -195,7 +226,39 @@ export default {
uni.navigateBack();
});
}
},
// #ifdef H5
// H5 端:新标签页打开文件(绕过 iframe X-Frame-Options/CORS 限制)
openInNewTab() {
if (!this.fileUrl) return;
try {
window.open(this.fileUrl, '_blank', 'noopener,noreferrer');
} catch (e) {
uni.showToast({ title: '打开失败,请稍后重试', icon: 'none' });
}
},
// H5 端:通过 <a download> 触发浏览器下载(最稳定的跨浏览器方案)
triggerDownload() {
if (!this.fileUrl) return;
try {
const link = document.createElement('a');
link.href = this.fileUrl;
link.target = '_blank';
link.rel = 'noopener noreferrer';
if (this.fileName) {
// 仅提示浏览器用这个名字;受 CORS 影响,跨域文件时 download 属性可能被忽略,
// 此时浏览器会直接按服务器返回的文件名/直接显示,但不会丢失文件本身
link.download = this.fileName;
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (e) {
// 兜底:新标签页打开
this.openInNewTab();
}
}
// #endif
}
};
</script>
@@ -353,6 +416,50 @@ export default {
color: #999;
font-size: 28rpx;
}
/* #ifdef H5 */
/* H5 兜底操作栏(PDF/Word 被 X-Frame-Options 拦截时显示)*/
.h5-action-bar {
padding: 24rpx 28rpx 20rpx;
background: linear-gradient(180deg, #fffbe6 0%, #ffffff 100%);
border-bottom: 1rpx solid #f0e9c8;
.h5-action-tip {
font-size: 26rpx;
color: #8a6d1b;
margin-bottom: 18rpx;
line-height: 1.5;
}
.h5-action-btns {
display: flex;
gap: 20rpx;
.h5-action-btn {
flex: 1;
height: 72rpx;
line-height: 72rpx;
padding: 0;
font-size: 28rpx;
border-radius: 36rpx;
background: #f2f3f5;
color: #333;
border: 1rpx solid #e2e4e8;
margin: 0;
&::after { border: none; }
&.primary {
background: linear-gradient(90deg, #ff7e47 0%, #f73131 100%);
color: #fff;
border-color: transparent;
font-weight: 600;
box-shadow: 0 4rpx 12rpx rgba(247, 49, 49, 0.25);
}
}
}
}
/* #endif */
}
.video-viewer {

View File

@@ -140,6 +140,28 @@ export default {
const matched = clean.match(/\.([a-zA-Z0-9]+)$/);
if (matched) ext = matched[1].toLowerCase();
}
const fileName = `${title}.${ext}`;
const fileType =
['pdf'].includes(ext) ? 'pdf'
: ['doc', 'docx'].includes(ext) ? 'word'
: ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'].includes(ext) ? 'video'
: 'pdf';
const previewPage = `/pages_tool/file-preview/file-preview?fileName=${encodeURIComponent(fileName)}&fileUrl=${encodeURIComponent(item.files_url)}&fileType=${encodeURIComponent(fileType)}`;
// ========== H5 端:跳转预览页(web-view 走 iframe);失败则新标签页打开原链接 ==========
// #ifdef H5
uni.navigateTo({
url: previewPage,
fail: () => {
try { window.open(item.files_url, '_blank'); } catch (e) {
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
}
}
});
return;
// #endif
// ========== 非 H5 端:下载文件后按平台分支打开 ==========
uni.showLoading({ title: this.$lang('files.list.loading'), mask: true });
uni.downloadFile({
url: item.files_url,
@@ -149,6 +171,9 @@ export default {
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
return;
}
// ----- 微信小程序:saveFile 重命名 + openDocument(短文件名标题)-----
// #ifdef MP-WEIXIN
const fs = uni.getFileSystemManager();
// 重命名临时文件到用户目录,用短文件名 —— openDocument 的标题会取 filePath 的文件名部分,从而显示短名"乐瑞固企业介绍"而非 tmp_xxx
const targetPath = `${wx.env.USER_DATA_PATH}/fs_${Date.now()}_${title}.${ext}`;
@@ -193,6 +218,23 @@ export default {
fail: () => uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' })
});
}
// #endif
// ----- App / 其他小程序:直接 openDocument 打开临时文件;失败兜底跳转预览页 -----
// #ifndef MP-WEIXIN
uni.hideLoading();
uni.openDocument({
filePath: res.tempFilePath,
fileType: ext,
showMenu: true,
fail: () => {
uni.navigateTo({
url: previewPage,
fail: () => uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' })
});
}
});
// #endif
},
fail: () => {
uni.hideLoading();