Browse Source

水印只用时间、云笔录改成录视频

dev
wangmingyong@163.com 2 weeks ago
parent
commit
0b73422703
  1. 30
      zdxt-web-client/zdxt-efcode-enterprise-app/src/util/w6sMedia.js
  2. 162
      zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue

30
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 || {}

162
zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/nos/nosCloudRecord.vue

@ -55,22 +55,19 @@
<span class="required-mark">*</span>云视频
</div>
<div class="form-value">
<van-uploader
v-model="videoFileList"
:max-count="1"
:max-size="VIDEO_MAX_SIZE"
accept="video/*"
:after-read="onAfterReadVideo"
@oversize="onVideoOversize"
@delete="onVideoDelete"
>
<template #default>
<div class="uploader-btn">
<van-icon name="plus" size="24" color="#dcdee0" />
</div>
</template>
</van-uploader>
<div class="form-tip">仅支持视频200MB以下</div>
<div v-if="videoUploading" class="video-upload-state">
<van-loading type="spinner" color="#2b7de9" />
<span class="upload-text">上传中...</span>
</div>
<div v-else-if="cloudVideo" class="video-preview-item">
<video :src="cloudVideo" muted preload="metadata" class="video-thumb" @click="showVideoPreview = true" />
<van-icon name="play-circle-o" class="play-icon" @click="showVideoPreview = true" />
<van-icon name="cross" class="delete-icon" @click="onVideoDelete" />
</div>
<div v-else class="uploader-btn" @click="onRecordVideo">
<van-icon name="plus" size="24" color="#dcdee0" />
</div>
<div class="form-tip">仅支持现场录制视频200MB以下</div>
</div>
</div>
@ -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 {

Loading…
Cancel
Save