From 0b73422703ef7366c11c8cb20e08847c37e90057 Mon Sep 17 00:00:00 2001 From: "wangmingyong@163.com" Date: Fri, 28 Aug 2026 16:10:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B0=B4=E5=8D=B0=E5=8F=AA=E7=94=A8=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E3=80=81=E4=BA=91=E7=AC=94=E5=BD=95=E6=94=B9=E6=88=90?= =?UTF-8?q?=E5=BD=95=E8=A7=86=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/util/w6sMedia.js | 30 ++-- .../views/enterprise/nos/nosCloudRecord.vue | 162 +++++++++++------- 2 files changed, 114 insertions(+), 78 deletions(-) diff --git a/zdxt-web-client/zdxt-efcode-enterprise-app/src/util/w6sMedia.js b/zdxt-web-client/zdxt-efcode-enterprise-app/src/util/w6sMedia.js index 1b7cb6ba..90e32f46 100644 --- a/zdxt-web-client/zdxt-efcode-enterprise-app/src/util/w6sMedia.js +++ b/zdxt-web-client/zdxt-efcode-enterprise-app/src/util/w6sMedia.js @@ -102,29 +102,29 @@ const getTimeStr = () => { // 自己拼接时间+定位到 content,设 timeEnable/locationEnable 为 false 跳过 SDK 内部阻塞式 getLocation 调用 export const takePhotoWithWaterMark = async () => { await ensureW6sAuth() - console.log('[w6sMedia] 鉴权完成, 准备获取定位') + // console.log('[w6sMedia] 鉴权完成, 准备获取定位') - // 预获取定位(带缓存),第二次拍照起直接用缓存不搜星 - let locationStr = '' - try { - const loc = await getCachedLocation() - locationStr = (loc.city || '') + (loc.district || '') + (loc.street || '') - console.log('[w6sMedia] 定位地址:', locationStr) - } catch (e) { - console.warn('[w6sMedia] 获取定位失败, 水印不含地址:', e) - } + // // 预获取定位(带缓存),第二次拍照起直接用缓存不搜星 + // let locationStr = '' + // try { + // const loc = await getCachedLocation() + // locationStr = (loc.city || '') + (loc.district || '') + (loc.street || '') + // console.log('[w6sMedia] 定位地址:', locationStr) + // } catch (e) { + // console.warn('[w6sMedia] 获取定位失败, 水印不含地址:', e) + // } - const content = `${getTimeStr()} ${locationStr}`.trim() - console.log('[w6sMedia] 水印 content:', content, '准备调起拍照') + // const content = `${getTimeStr()} ${locationStr}`.trim() + // console.log('[w6sMedia] 水印 content:', content, '准备调起拍照') return new Promise((resolve, reject) => { w6s.image.takePhotoAndAddWaterMark({ - content, + content: '', fontSize: 14, color: '#FF5858', markDisable: false, - timeEnable: false, // 时间已自己拼入 content - locationEnable: false, // 定位已自己拼入 content,跳过 SDK 内部 getLocation 阻塞 + timeEnable: true, + locationEnable: false, success: (res) => { console.log('[w6sMedia] takePhotoAndAddWaterMark success 原始返回:', res) const result = res?.result || res || {} diff --git a/zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue b/zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue index c56cceee..380862d3 100644 --- a/zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue +++ b/zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue @@ -55,22 +55,19 @@ *云视频
- - - -
(仅支持视频,200MB以下)
+
+ + 上传中... +
+
+
+
+ +
+
(仅支持现场录制视频,200MB以下)
@@ -127,11 +124,9 @@ import { showConfirmDialog, showSuccessToast, showToast } from 'vant'; import noDataImg from '@/assets/images/nos/no-data.png'; import { submitCloudRecordApi, cloudRecordDetailApi } from '@/api/nos/index'; -import { uploadFile } from '@/util/fileUpload'; +import { startVideoRecorder, uploadLocalFileToBackend } from '@/util/w6sMedia'; import { toFullFileUrl, toRelativeFilePath } from '@/util/fileUrl'; -const VIDEO_MAX_SIZE = 200 * 1024 * 1024; - const router = useRouter(); const route = useRoute(); @@ -147,8 +142,8 @@ const cloudVideo = ref(''); const cloudText = ref(''); const suggestion = ref(''); const cloudVideoPath = ref(''); -const videoFileList = ref([]); const showVideoPreview = ref(false); +const videoUploading = ref(false); const applyDetailData = (data) => { cloudVideo.value = data.cloudVideo ? toFullFileUrl(data.cloudVideo) : ''; @@ -191,56 +186,40 @@ const onRefresh = () => { fetchDetail(); }; -const isVideo = (url) => { - if (!url) return false; - return /\.(mp4|webm|ogg|mov|avi|mkv)$/i.test(url); -}; - -const onVideoOversize = () => { - showToast('视频大小不能超过 200MB'); -}; - const onVideoDelete = () => { cloudVideoPath.value = ''; + cloudVideo.value = ''; }; -const onAfterReadVideo = (file) => { - const files = Array.isArray(file) ? file : [file]; - files.forEach((f) => { - if (f.file && !f.file.type.startsWith('video/')) { - showToast('请上传视频文件'); - f.status = 'failed'; - f.message = '格式错误'; - videoFileList.value = []; - cloudVideoPath.value = ''; +const onRecordVideo = async () => { + if (videoUploading.value) return; + try { + videoUploading.value = true; + const res = await startVideoRecorder(); + if (!res?.video_path) { + showToast('录制失败'); return; } - - uploadFile(f, (res) => { - const body = res?.data?.data ?? res?.data ?? res; - const filePath = - typeof body === 'string' - ? body - : (body && (body.url || body.fileUrl || body.path)) || ''; - - if (filePath) { - if (!isVideo(filePath) && f.file && !f.file.type.startsWith('video/')) { - showToast('请上传视频文件'); - videoFileList.value = []; - cloudVideoPath.value = ''; - return; - } - cloudVideoPath.value = filePath; - f.url = toFullFileUrl(filePath); - f.isImage = false; - f.status = 'done'; - } else { - f.status = 'failed'; - f.message = '上传失败'; - cloudVideoPath.value = ''; - } + const uploadRes = await uploadLocalFileToBackend({ + fileURL: res.video_path, + fileName: res.name || `video-${Date.now()}.mp4`, + mimeType: res.type || 'video/mp4', }); - }); + const filePath = uploadRes?.data || ''; + if (filePath) { + cloudVideoPath.value = filePath; + cloudVideo.value = toFullFileUrl(filePath); + } else { + showToast('上传失败'); + } + } catch (err) { + console.error('[nosCloudRecord] 视频录制/上传失败:', err); + if (err?.message !== '已取消录制') { + showToast(err?.message || '录制失败或已取消'); + } + } finally { + videoUploading.value = false; + } }; const validateForm = () => { @@ -495,6 +474,63 @@ onMounted(() => { justify-content: center; border-radius: 4px; border: 1px dashed #ebedf0; + cursor: pointer; +} + +.video-upload-state { + width: 80px; + height: 80px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + background-color: #f7f8fa; + border-radius: 4px; + border: 1px dashed #ebedf0; + + .upload-text { + font-size: 12px; + color: #969799; + } +} + +.video-preview-item { + position: relative; + width: 80px; + height: 80px; + border-radius: 4px; + overflow: hidden; + background: #000; + + .video-thumb { + width: 100%; + height: 100%; + object-fit: cover; + cursor: pointer; + } + + .play-icon { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 28px; + color: rgba(255, 255, 255, 0.9); + cursor: pointer; + } + + .delete-icon { + position: absolute; + top: 2px; + right: 2px; + font-size: 16px; + color: #fff; + background: rgba(0, 0, 0, 0.5); + border-radius: 50%; + padding: 2px; + cursor: pointer; + } } .form-tip {