From 059b0922f532e59536fb6dd9e72b259c36689d23 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期五, 24 四月 2026 16:58:06 +0800
Subject: [PATCH] 优化文件预览功能,新增视频文件播放逻辑,改进文件URL处理,确保视频播放的稳定性和兼容性。
---
src/pages/inspectionUpload/index.vue | 251 +++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 205 insertions(+), 46 deletions(-)
diff --git a/src/pages/inspectionUpload/index.vue b/src/pages/inspectionUpload/index.vue
index a843715..cb07466 100644
--- a/src/pages/inspectionUpload/index.vue
+++ b/src/pages/inspectionUpload/index.vue
@@ -16,7 +16,7 @@
<text class="task-location">{{ item.inspectionLocation }}</text>
</view>
<view class="task-actions">
- <u-button type="primary"
+ <!-- <u-button type="primary"
size="small"
@click.stop="startScanForTask(item)"
:customStyle="{
@@ -26,6 +26,17 @@
marginRight: '8px'
}">
鎵爜涓婁紶
+ </u-button> -->
+ <u-button type="primary"
+ size="small"
+ @click.stop="startUploadForTask(item)"
+ :customStyle="{
+ borderRadius: '15px',
+ height: '30px',
+ fontSize: '12px',
+ marginRight: '8px'
+ }">
+ 鍥剧墖涓婁紶
</u-button>
<u-button type="success"
size="small"
@@ -177,12 +188,13 @@
<view v-for="(file, index) in getCurrentFiles()"
:key="index"
class="file-item">
- <view class="file-preview-container">
- <image v-if="file.type === 'image' || (file.type !== 'video' && !file.type)"
- :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
+ <view class="file-preview-container"
+ @click="previewUploadedMedia(file)">
+ <image v-if="isImageFile(file)"
+ :src="getFileAccessUrl(file)"
class="file-preview"
mode="aspectFill" />
- <view v-else-if="file.type === 'video'"
+ <view v-else-if="isVideoFile(file)"
class="video-preview">
<uni-icons type="videocam"
name="videocam"
@@ -200,7 +212,7 @@
</view>
</view>
<view class="file-info">
- <text class="file-name">{{ file.bucketFilename || file.name || (file.type === 'image' ? '鍥剧墖' : '瑙嗛')
+ <text class="file-name">{{ file.bucketFilename || file.name || (isImageFile(file) ? '鍥剧墖' : '瑙嗛')
}}</text>
<text class="file-size">{{ formatFileSize(file.size) }}</text>
</view>
@@ -280,7 +292,7 @@
@click="previewAttachment(file)">
<view class="attachment-preview-container">
<image v-if="file.type === 'image' || isImageFile(file)"
- :src="file.url || file.downloadUrl"
+ :src="getFileAccessUrl(file)"
class="attachment-preview"
mode="aspectFill" />
<view v-else
@@ -324,7 +336,7 @@
</view>
<view class="video-modal-body">
<video v-if="currentVideoFile"
- :src="currentVideoFile.url || currentVideoFile.downloadUrl"
+ :src="currentVideoFile._playUrl"
class="video-player"
controls
autoplay
@@ -855,6 +867,12 @@
}
};
+ // 鍥剧墖涓婁紶(鍙�夋嫨鍥剧墖涓婁紶鎴栬�呮槸鐩告満鎷嶇収)
+ const startUploadForTask = async (task, type) => {
+ // 鐩存帴鎵撳紑涓婁紶寮圭獥
+ openUploadDialog(task);
+ };
+
// 鏌ョ湅闄勪欢
const viewAttachments = async task => {
try {
@@ -883,11 +901,11 @@
: allList.filter(f => f?.type === 12);
const mapToViewFile = (file, viewType) => {
- const u = normalizeFileUrl(file?.url || file?.downloadUrl || "");
+ const u = getFileAccessUrl(file);
return {
...file,
// 鐢ㄤ簬涓夋爣绛鹃〉鍒嗙粍锛�0=鐢熶骇鍓� 1=鐢熶骇涓� 2=鐢熶骇鍚�
- type: viewType,
+ viewType,
name: file?.name || file?.originalFilename || file?.bucketFilename,
bucketFilename: file?.bucketFilename || file?.name,
originalFilename: file?.originalFilename || file?.name,
@@ -925,7 +943,7 @@
// 鏍规嵁type鑾峰彇瀵瑰簲鍒嗙被鐨勯檮浠�
const getAttachmentsByType = typeValue => {
- return attachmentList.value.filter(file => file.type === typeValue) || [];
+ return attachmentList.value.filter(file => file.viewType === typeValue) || [];
};
// 鑾峰彇type鍊�
const getTabType = () => {
@@ -961,8 +979,8 @@
return true;
}
- // 妫�鏌ュ師鏈夌殑type瀛楁
- if (file.type === "image") return true;
+ // 妫�鏌ュ師鏈夌殑type瀛楁锛堟垨淇濈暀鐨勫獟浣撶被鍨嬶級
+ if (file.type === "image" || file.mediaType === "image") return true;
// 妫�鏌ユ枃浠舵墿灞曞悕
const name = file.bucketFilename || file.originalFilename || file.name || "";
@@ -970,38 +988,104 @@
return ["jpg", "jpeg", "png", "gif", "webp"].includes(ext);
};
+ // 鍒ゆ柇鏄惁涓鸿棰戞枃浠�
+ const isVideoFile = file => {
+ if (!file) return false;
+ if (file.type === "video" || file.mediaType === "video") return true;
+ const name = file.bucketFilename || file.originalFilename || file.name || "";
+ const ext = name.split(".").pop()?.toLowerCase();
+ return ["mp4", "mov", "avi", "wmv", "mkv", "webm"].includes(ext);
+ };
+
// 鏂囦欢璁块棶鍩虹鍩燂紙鍚庣瑕佹眰鍓嶇紑锛�
const filePreviewBase = config.fileUrl;
- // 灏嗗悗绔繑鍥炵殑鏂囦欢鍦板潃瑙勮寖鎴愬彲璁块棶URL
- // 鍏煎鍦烘櫙锛�
- // - 宸茬粡鏄� http/https锛氱洿鎺ヨ繑鍥�
- // - 浠� / 寮�澶达細鎷兼帴 filePreviewBase
- // - Windows 鏈湴璺緞锛堝 D:\ruoyi\prod\uploads...\xx.jpg锛夛細灏濊瘯鎴彇 prod 涔嬪悗鐨勭浉瀵硅矾寰勫苟鎷兼帴 filePreviewBase
- const normalizeFileUrl = rawUrl => {
- try {
- if (!rawUrl || typeof rawUrl !== "string") return "";
- const url = rawUrl.trim();
- if (!url) return "";
- if (/^https?:\/\//i.test(url)) return url;
- if (url.startsWith("/")) return `${filePreviewBase}${url}`;
+ const normalizeFileUrl = (rawUrl = "") => {
+ let fileUrl = rawUrl || "";
+ if (typeof fileUrl === "string") {
+ fileUrl = fileUrl.trim().replace(/^['"]|['"]$/g, "");
+ }
+ const javaApi = filePreviewBase;
+ const localPrefixes = ["wxfile://", "file://", "content://", "blob:", "data:"];
- // Windows path -> web path
- if (/^[a-zA-Z]:\\/.test(url)) {
- const normalized = url.replace(/\\/g, "/");
- const idx = normalized.indexOf("/prod/");
- if (idx >= 0) {
- const relative = normalized.slice(idx + "/prod/".length);
- return `${filePreviewBase}/${relative}`;
- }
- // 鍏滃簳锛氭棤娉曟帹鏂槧灏勮鍒欐椂锛岃嚦灏戞妸鍙嶆枩鏉犲彉鎴愭鏂滄潬
- return normalized;
+ if (localPrefixes.some(prefix => fileUrl.startsWith(prefix))) {
+ return fileUrl;
+ }
+
+ if (fileUrl && fileUrl.indexOf("\\") > -1) {
+ const lowerPath = fileUrl.toLowerCase();
+ const uploadPathIndex = lowerPath.indexOf("uploadpath");
+ const prodIndex = lowerPath.indexOf("\\prod\\");
+
+ if (uploadPathIndex > -1) {
+ fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
+ } else if (prodIndex > -1) {
+ fileUrl = fileUrl
+ .substring(prodIndex + "\\prod\\".length)
+ .replace(/\\/g, "/");
+ } else {
+ fileUrl = fileUrl.replace(/\\/g, "/");
}
+ }
+ // /javaWork/.../file/prod/xxx -> /profile/prod/xxx
+ const normalizedLower = String(fileUrl).toLowerCase();
+ const fileProdIdx = normalizedLower.indexOf("/file/prod/");
+ if (fileProdIdx > -1) {
+ fileUrl = `/profile/prod/${fileUrl.substring(fileProdIdx + "/file/prod/".length)}`;
+ }
+ // /javaWork/.../file/temp/xxx -> /profile/temp/xxx
+ const fileTempIdx = normalizedLower.indexOf("/file/temp/");
+ if (fileTempIdx > -1) {
+ fileUrl = `/profile/temp/${fileUrl.substring(fileTempIdx + "/file/temp/".length)}`;
+ }
- // 鍏朵粬鐩稿璺緞锛氱洿鎺ョ敤 baseUrl 鎷间竴涓�
- return `${filePreviewBase}/${url.replace(/^\//, "")}`;
- } catch (e) {
- return rawUrl || "";
+ if (/^\/?uploadPath/i.test(fileUrl)) {
+ fileUrl = fileUrl.replace(/^\/?uploadPath/i, "/profile");
+ }
+
+ if (fileUrl && !fileUrl.startsWith("http")) {
+ if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
+ fileUrl = javaApi + fileUrl;
+ }
+
+ return fileUrl;
+ };
+
+ const getFileAccessUrl = (file = {}) => {
+ if (file?.link) {
+ if (String(file.link).startsWith("http")) return file.link;
+ return normalizeFileUrl(file.link);
+ }
+ const remoteUrl = normalizeFileUrl(
+ file?.url ||
+ file?.downloadUrl ||
+ file?.tempPath ||
+ ""
+ );
+ if (remoteUrl) return remoteUrl;
+ // 鍏滃簳鏈湴璺緞锛堜笂浼犲綋娆¢瑙堬級
+ if (file?._localPreviewUrl) return file._localPreviewUrl;
+ return normalizeFileUrl(file?.tempFilePath || file?.path || "");
+ };
+
+ // 涓婁紶寮圭獥鍐呯殑濯掍綋棰勮锛堝浘鐗�/瑙嗛锛�
+ const previewUploadedMedia = file => {
+ if (!file) return;
+ if (isImageFile(file)) {
+ const imageUrls = getCurrentFiles()
+ .filter(f => isImageFile(f))
+ .map(f => getFileAccessUrl(f))
+ .filter(Boolean);
+ const current = getFileAccessUrl(file);
+ if (!imageUrls.length || !current) return;
+ uni.previewImage({
+ urls: imageUrls,
+ current,
+ });
+ return;
+ }
+ if (isVideoFile(file)) {
+ playVideoFile(file);
}
};
@@ -1011,16 +1095,57 @@
// 棰勮鍥剧墖
const imageUrls = getCurrentViewAttachments()
.filter(f => isImageFile(f))
- .map(f => f.url || f.downloadUrl);
+ .map(f => getFileAccessUrl(f));
uni.previewImage({
urls: imageUrls,
- current: file.url || file.downloadUrl,
+ current: getFileAccessUrl(file),
});
} else {
- // 棰勮瑙嗛 - 鏄剧ず瑙嗛鎾斁寮圭獥
- showVideoPreview(file);
+ // 棰勮瑙嗛
+ playVideoFile(file);
}
+ };
+
+ const safeEncodeUrl = url => {
+ if (!url) return "";
+ if (!/^https?:\/\//i.test(url)) return url;
+ try {
+ return encodeURI(url);
+ } catch (e) {
+ return url;
+ }
+ };
+
+ const getPlayableVideoUrl = file => {
+ return safeEncodeUrl(getFileAccessUrl(file));
+ };
+
+ const getFallbackLocalVideoUrl = file => {
+ const local = file?._localPreviewUrl || file?.tempFilePath || file?.path || "";
+ return safeEncodeUrl(local);
+ };
+
+ const playVideoFile = file => {
+ const remoteSrc = getPlayableVideoUrl(file);
+ const localSrc = getFallbackLocalVideoUrl(file);
+ // 寮圭獥鎾斁鍣ㄤ紭鍏堣繙绋嬪湴鍧�锛屽け璐ュ啀鑷姩鍥為��鏈湴鍦板潃
+ const src = remoteSrc || localSrc;
+ if (!src) {
+ uni.showToast({
+ title: "瑙嗛鍦板潃鏃犳晥",
+ icon: "none",
+ });
+ return;
+ }
+
+ // 缁熶竴浣跨敤椤甸潰鍐� video 寮圭獥鎾斁
+ showVideoPreview({
+ ...file,
+ _playUrl: src,
+ _playUrlLocal: localSrc,
+ _playUrlRemote: remoteSrc,
+ });
};
// 鏄剧ず瑙嗛棰勮
@@ -1036,7 +1161,32 @@
};
// 瑙嗛鎾斁閿欒澶勭悊
- const handleVideoError = error => {
+ const handleVideoError = () => {
+ const localUrl = currentVideoFile.value?._playUrlLocal;
+ const remoteUrl = currentVideoFile.value?._playUrlRemote;
+ const currentUrl = currentVideoFile.value?._playUrl;
+ if (remoteUrl && currentUrl !== remoteUrl) {
+ currentVideoFile.value = {
+ ...currentVideoFile.value,
+ _playUrl: remoteUrl,
+ };
+ uni.showToast({
+ title: "宸插垏鎹㈣繙绋嬭棰戦噸璇曟挱鏀�",
+ icon: "none",
+ });
+ return;
+ }
+ if (localUrl && currentUrl !== localUrl) {
+ currentVideoFile.value = {
+ ...currentVideoFile.value,
+ _playUrl: localUrl,
+ };
+ uni.showToast({
+ title: "宸插垏鎹㈡湰鍦拌棰戦噸璇曟挱鏀�",
+ icon: "none",
+ });
+ return;
+ }
uni.showToast({
title: "瑙嗛鎾斁澶辫触",
icon: "error",
@@ -1469,13 +1619,20 @@
url:
uploadedFile.url ||
uploadedFile.downloadUrl ||
+ uploadedFile.tempPath ||
file.tempFilePath ||
file.path,
+ tempPath: uploadedFile.tempPath || file.tempPath || "",
+ _localPreviewUrl: file.tempFilePath || file.path || "",
bucketFilename:
- uploadedFile.bucketFilename || uploadedFile.originalFilename || file.name,
+ uploadedFile.bucketFilename ||
+ uploadedFile.originalFilename ||
+ uploadedFile.originalName ||
+ file.name,
downloadUrl: uploadedFile.downloadUrl || uploadedFile.url,
size: uploadedFile.size || uploadedFile.byteSize || file.size,
createTime: uploadedFile.createTime || new Date().getTime(),
+ mediaType: file.type || uploadedFile.mediaType,
type: typeValue, // 娣诲姞绫诲瀷瀛楁锛�0=鐢熶骇鍓�, 1=鐢熶骇涓�, 2=鐢熶骇鍚�
};
@@ -2184,8 +2341,10 @@
.video-player {
width: 100%;
- height: auto;
+ height: 56vh;
+ min-height: 260px;
max-height: 60vh;
display: block;
+ object-fit: contain;
}
</style>
\ No newline at end of file
--
Gitblit v1.9.3