|
|
|
@ -65,45 +65,32 @@ export const ensureW6sAuth = () => { |
|
|
|
return w6sAuthPromise |
|
|
|
} |
|
|
|
|
|
|
|
// 格式化当前时间为 yyyy-MM-dd HH:mm:ss
|
|
|
|
const formatDateTime = () => { |
|
|
|
const d = new Date() |
|
|
|
const pad = (n) => String(n).padStart(2, '0') |
|
|
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` |
|
|
|
} |
|
|
|
|
|
|
|
// 拍照并加水印(时间戳 + 经纬度自动叠加到照片)
|
|
|
|
export const takePhotoWithWaterMark = async ({ |
|
|
|
content = '', |
|
|
|
fontSize = 14, |
|
|
|
color = '#FF5858', |
|
|
|
timeEnable = true, |
|
|
|
locationEnable = true, |
|
|
|
} = {}) => { |
|
|
|
console.log('[w6sMedia] takePhotoWithWaterMark 开始, 入参:', { content, fontSize, color, timeEnable, locationEnable }) |
|
|
|
await ensureW6sAuth() |
|
|
|
export const takePhotoWithWaterMark = async () => { |
|
|
|
// 如果调用方未传 content,则默认显示当前时间作为水印文字
|
|
|
|
const watermarkContent = formatDateTime(); |
|
|
|
console.log('[w6sMedia] takePhotoWithWaterMark 开始, 入参:', { content: watermarkContent, fontSize, color, timeEnable, locationEnable }) |
|
|
|
await ensureW6sAuth(); |
|
|
|
console.log('[w6sMedia] 鉴权完成, 准备调起拍照') |
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
// w6s.image.takePicture({
|
|
|
|
// editable: false,
|
|
|
|
// success: function (res) {
|
|
|
|
// console.log('[w6sMedia] takePhotoAndAddWaterMark success 原始返回:', res)
|
|
|
|
// console.log('[w6sMedia] 返回字段 imageURL:', res?.imageURL, 'key:', res?.key, 'imageInfo:', res?.imageInfo)
|
|
|
|
// resolve(res)
|
|
|
|
// },
|
|
|
|
// fail: function (err) {
|
|
|
|
// console.error('[w6sMedia] takePhotoAndAddWaterMark fail:', err)
|
|
|
|
// reject(err)
|
|
|
|
// },
|
|
|
|
// });
|
|
|
|
w6s.image.takePhotoAndAddWaterMark({ |
|
|
|
content, |
|
|
|
fontSize, |
|
|
|
color, |
|
|
|
content: watermarkContent, |
|
|
|
fontSize: 14, |
|
|
|
color: '#FF5858', |
|
|
|
markDisable: false, |
|
|
|
timeEnable: true, |
|
|
|
locationEnable: true, |
|
|
|
success: (res) => { |
|
|
|
console.log('[w6sMedia] takePhotoAndAddWaterMark success 原始返回:', res) |
|
|
|
console.log('[w6sMedia] 返回字段 imageURL:', res?.result.imageURL, 'key:', res?.result.key, 'imageInfo:', res?.result.imageInfo) |
|
|
|
// getLocation().then((location) => {
|
|
|
|
// console.log('[w6sMedia] 获取定位成功:', location)
|
|
|
|
// res?.result.location = location
|
|
|
|
resolve(res) |
|
|
|
// })
|
|
|
|
resolve(res) |
|
|
|
}, |
|
|
|
fail: (err) => { |
|
|
|
console.error('[w6sMedia] takePhotoAndAddWaterMark fail:', err) |
|
|
|
@ -113,30 +100,75 @@ export const takePhotoWithWaterMark = async ({ |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// 将文件从公共目录复制到应用私有目录(解决 Android 11+ 分区存储导致的 EACCES 权限问题)
|
|
|
|
const copyFileToAppDir = async (sourcePath) => { |
|
|
|
if (!window.cordova?.file?.dataDirectory) { |
|
|
|
throw new Error('cordova.file.dataDirectory 不可用') |
|
|
|
} |
|
|
|
console.log('[w6sMedia] copyFileToAppDir sourcePath:', sourcePath) |
|
|
|
|
|
|
|
const sourceEntry = await new Promise((resolve, reject) => { |
|
|
|
window.resolveLocalFileSystemURL(sourcePath, resolve, reject) |
|
|
|
}) |
|
|
|
console.log('[w6sMedia] 源文件 entry:', sourceEntry.fullPath, 'name:', sourceEntry.name) |
|
|
|
|
|
|
|
const dataDirEntry = await new Promise((resolve, reject) => { |
|
|
|
window.resolveLocalFileSystemURL(window.cordova.file.dataDirectory, resolve, reject) |
|
|
|
}) |
|
|
|
console.log('[w6sMedia] 应用私有目录:', dataDirEntry.fullPath) |
|
|
|
// 将 MediaFile 从公共目录复制到应用私有目录(解决 Android 11+ 分区存储导致的 EACCES 权限问题)
|
|
|
|
// 直接使用 MediaFile.file() 获取 FileEntry,避免 resolveLocalFileSystemURL 在公共目录路径上的限制
|
|
|
|
const copyMediaFileToAppDir = (mediaFile) => { |
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
if (!window.cordova?.file?.dataDirectory) { |
|
|
|
reject(new Error('cordova.file.dataDirectory 不可用')) |
|
|
|
return |
|
|
|
} |
|
|
|
console.log('[w6sMedia] copyMediaFileToAppDir 开始, localURL:', mediaFile.localURL, 'fullPath:', mediaFile.fullPath) |
|
|
|
|
|
|
|
const newFileEntry = await new Promise((resolve, reject) => { |
|
|
|
sourceEntry.copyTo(dataDirEntry, sourceEntry.name, resolve, reject) |
|
|
|
// 通过 MediaFile.file() 获取 FileEntry(比 resolveLocalFileSystemURL 更可靠)
|
|
|
|
mediaFile.file( |
|
|
|
(sourceFileEntry) => { |
|
|
|
console.log('[w6sMedia] 获取源 FileEntry 成功:', sourceFileEntry.fullPath) |
|
|
|
window.resolveLocalFileSystemURL( |
|
|
|
window.cordova.file.dataDirectory, |
|
|
|
(dataDirEntry) => { |
|
|
|
console.log('[w6sMedia] 应用私有目录:', dataDirEntry.fullPath) |
|
|
|
sourceFileEntry.copyTo( |
|
|
|
dataDirEntry, |
|
|
|
mediaFile.name, |
|
|
|
(newFileEntry) => { |
|
|
|
const fileUrl = newFileEntry.toURL() |
|
|
|
console.log('[w6sMedia] 文件已复制到应用私有目录, fileUrl:', fileUrl) |
|
|
|
resolve(fileUrl) |
|
|
|
}, |
|
|
|
(copyErr) => { |
|
|
|
// 目标文件已存在时,先删除再复制
|
|
|
|
console.warn('[w6sMedia] copyTo 可能目标已存在,尝试移除后重试:', copyErr) |
|
|
|
window.resolveLocalFileSystemURL( |
|
|
|
window.cordova.file.dataDirectory + mediaFile.name, |
|
|
|
(existingEntry) => { |
|
|
|
existingEntry.remove( |
|
|
|
() => { |
|
|
|
sourceFileEntry.copyTo( |
|
|
|
dataDirEntry, |
|
|
|
mediaFile.name, |
|
|
|
(newFileEntry) => { |
|
|
|
const fileUrl = newFileEntry.toURL() |
|
|
|
console.log('[w6sMedia] 重试复制成功, fileUrl:', fileUrl) |
|
|
|
resolve(fileUrl) |
|
|
|
}, |
|
|
|
reject |
|
|
|
) |
|
|
|
}, |
|
|
|
() => { |
|
|
|
// 无法删除旧文件,直接 resolve 原始 localURL
|
|
|
|
console.warn('[w6sMedia] 无法删除旧文件,返回原始 localURL') |
|
|
|
resolve(mediaFile.localURL) |
|
|
|
} |
|
|
|
) |
|
|
|
}, |
|
|
|
() => { |
|
|
|
// 旧文件不存在,直接报错
|
|
|
|
reject(copyErr) |
|
|
|
} |
|
|
|
) |
|
|
|
} |
|
|
|
) |
|
|
|
}, |
|
|
|
reject |
|
|
|
) |
|
|
|
}, |
|
|
|
(fileErr) => { |
|
|
|
console.error('[w6sMedia] MediaFile.file() 失败:', fileErr) |
|
|
|
reject(fileErr) |
|
|
|
} |
|
|
|
) |
|
|
|
}) |
|
|
|
// toURL() 返回 file:// 格式的 URL,FileTransfer 可直接使用
|
|
|
|
const fileUrl = newFileEntry.toURL() |
|
|
|
console.log('[w6sMedia] 文件已复制到应用私有目录, fileUrl:', fileUrl, 'fullPath:', newFileEntry.fullPath) |
|
|
|
return fileUrl |
|
|
|
} |
|
|
|
|
|
|
|
// 录制视频(使用 Cordova 原生 Media Capture API)
|
|
|
|
@ -160,9 +192,10 @@ export const startVideoRecorder = async ({ |
|
|
|
console.log('[w6sMedia] captureVideo success, mediaFiles:', mediaFiles) |
|
|
|
if (mediaFiles && mediaFiles.length > 0) { |
|
|
|
const file = mediaFiles[0] |
|
|
|
console.log('[w6sMedia] 视频文件: fullPath=', file.fullPath, 'name=', file.name, 'size=', file.size, 'type=', file.type) |
|
|
|
console.log('[w6sMedia] 视频文件: fullPath=', file.fullPath, 'localURL=', file.localURL, 'name=', file.name, 'size=', file.size) |
|
|
|
try { |
|
|
|
const appDirPath = await copyFileToAppDir(file.fullPath) |
|
|
|
// 尝试将 MediaFile 复制到应用私有目录,获得可访问的 file:// URL
|
|
|
|
const appDirPath = await copyMediaFileToAppDir(file) |
|
|
|
console.log('[w6sMedia] 视频已复制到应用私有目录:', appDirPath) |
|
|
|
resolve({ |
|
|
|
video_path: appDirPath, |
|
|
|
@ -171,9 +204,9 @@ export const startVideoRecorder = async ({ |
|
|
|
type: file.type || 'video/mp4', |
|
|
|
}) |
|
|
|
} catch (copyErr) { |
|
|
|
console.warn('[w6sMedia] 复制视频失败,尝试使用原路径:', copyErr) |
|
|
|
console.warn('[w6sMedia] 复制视频失败,尝试使用 localURL:', copyErr) |
|
|
|
resolve({ |
|
|
|
video_path: file.fullPath, |
|
|
|
video_path: file.localURL, |
|
|
|
name: file.name, |
|
|
|
size: file.size, |
|
|
|
type: file.type || 'video/mp4', |
|
|
|
|