fix: fallback to file icon when thumbnail load fails
This commit is contained in:
@@ -1693,9 +1693,10 @@
|
||||
<div v-for="file in files" :key="file.name" class="file-grid-item" @click="handleFileClick(file)" @contextmenu.prevent.stop="showFileContextMenu(file, $event)" @touchstart="handleLongPressStart(file, $event)" @touchmove="handleLongPressMove($event)" @touchend="handleLongPressEnd" @touchcancel="handleLongPressEnd" @selectstart.prevent @dragstart.prevent>
|
||||
<div class="file-icon">
|
||||
<!-- 图片缩略图 -->
|
||||
<img v-if="file.name.match(/\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i) && getThumbnailUrl(file)"
|
||||
<img v-if="file.name.match(/\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i) && getThumbnailUrl(file) && !isThumbnailLoadFailed(file)"
|
||||
:src="getThumbnailUrl(file)"
|
||||
:alt="file.name"
|
||||
@error="markThumbnailLoadFailed(file)"
|
||||
class="file-thumbnail">
|
||||
<!-- 视频图标(不预加载,避免慢) -->
|
||||
<div v-else-if="file.name.match(/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/i)"
|
||||
@@ -1742,9 +1743,10 @@
|
||||
<td class="file-list-name-cell">
|
||||
<div class="file-list-name-wrap">
|
||||
<!-- 图片缩略图 -->
|
||||
<img v-if="file.name.match(/\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i) && getThumbnailUrl(file)"
|
||||
<img v-if="file.name.match(/\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i) && getThumbnailUrl(file) && !isThumbnailLoadFailed(file)"
|
||||
:src="getThumbnailUrl(file)"
|
||||
:alt="file.name"
|
||||
@error="markThumbnailLoadFailed(file)"
|
||||
class="file-list-thumb">
|
||||
<!-- 视频图标 -->
|
||||
<div v-else-if="file.name.match(/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/i)"
|
||||
|
||||
@@ -260,6 +260,7 @@ createApp({
|
||||
currentMediaUrl: '',
|
||||
currentMediaName: '',
|
||||
currentMediaType: '', // 'image', 'video', 'audio'
|
||||
thumbnailLoadErrors: {}, // 缩略图加载失败标记(按文件路径)
|
||||
longPressDuration: 420, // 长按时间(毫秒)
|
||||
// 管理员编辑用户存储权限
|
||||
showEditStorageModal: false,
|
||||
@@ -1474,6 +1475,7 @@ handleDragLeave(e) {
|
||||
|
||||
if (response.data.success) {
|
||||
this.files = response.data.items;
|
||||
this.thumbnailLoadErrors = {};
|
||||
|
||||
// 更新存储类型信息
|
||||
if (response.data.storageType) {
|
||||
@@ -1886,6 +1888,25 @@ handleDragLeave(e) {
|
||||
|
||||
// ===== 媒体预览功能 =====
|
||||
|
||||
getCurrentFilePath(file) {
|
||||
if (!file || !file.name) return '';
|
||||
return this.currentPath === '/' ? `/${file.name}` : `${this.currentPath}/${file.name}`;
|
||||
},
|
||||
|
||||
isThumbnailLoadFailed(file) {
|
||||
const filePath = this.getCurrentFilePath(file);
|
||||
return !!(filePath && this.thumbnailLoadErrors[filePath]);
|
||||
},
|
||||
|
||||
markThumbnailLoadFailed(file) {
|
||||
const filePath = this.getCurrentFilePath(file);
|
||||
if (!filePath || this.thumbnailLoadErrors[filePath]) return;
|
||||
this.thumbnailLoadErrors = {
|
||||
...this.thumbnailLoadErrors,
|
||||
[filePath]: true
|
||||
};
|
||||
},
|
||||
|
||||
// 获取媒体文件URL(OSS直连或后端代理)
|
||||
async getMediaUrl(file) {
|
||||
const filePath = this.currentPath === '/'
|
||||
@@ -1922,12 +1943,18 @@ handleDragLeave(e) {
|
||||
|
||||
if (!isImage && !isVideo) return null;
|
||||
|
||||
const downloadQuota = Number(this.user?.download_traffic_quota);
|
||||
const downloadUsed = Number(this.user?.download_traffic_used || 0);
|
||||
if (Number.isFinite(downloadQuota) && downloadQuota >= 0) {
|
||||
if (downloadQuota === 0 || downloadUsed >= downloadQuota) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 本地存储模式:返回同步的下载 URL
|
||||
// OSS 模式下缩略图功能暂不支持(需要预签名 URL,建议点击文件预览)
|
||||
if (this.storageType !== 'oss') {
|
||||
const filePath = this.currentPath === '/'
|
||||
? `/${file.name}`
|
||||
: `${this.currentPath}/${file.name}`;
|
||||
const filePath = this.getCurrentFilePath(file);
|
||||
return `${this.apiBase}/api/files/download?path=${encodeURIComponent(filePath)}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user