video plus
This commit is contained in:
parent
ed8da6cde9
commit
42c1b64a99
@ -1,39 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="emojiRoot">
|
<div class="emojiRoot">
|
||||||
<div
|
<div @click="() => photoActionsSelect(0)" class="flex flex-col items-center">
|
||||||
@click="() => photoActionsSelect(0)"
|
<div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
|
||||||
class="flex flex-col items-center"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
|
|
||||||
>
|
|
||||||
<tm-image :width="53" :height="44" :src="photoAlbum"></tm-image>
|
<tm-image :width="53" :height="44" :src="photoAlbum"></tm-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">照片</div>
|
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">照片</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div @click="() => photoActionsSelect(1)" class="flex flex-col items-center">
|
||||||
@click="() => photoActionsSelect(1)"
|
<div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
|
||||||
class="flex flex-col items-center"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
|
|
||||||
>
|
|
||||||
<tm-image :width="53" :height="44" :src="videoImg"></tm-image>
|
<tm-image :width="53" :height="44" :src="videoImg"></tm-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">视频</div>
|
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">视频</div>
|
||||||
</div>
|
</div>
|
||||||
<div @click="takePhoto" class="flex flex-col items-center">
|
<div @click="takePhoto" class="flex flex-col items-center">
|
||||||
<div
|
<div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
|
||||||
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
|
|
||||||
>
|
|
||||||
<tm-image :width="53" :height="44" :src="photoGraph"></tm-image>
|
<tm-image :width="53" :height="44" :src="photoGraph"></tm-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">拍摄</div>
|
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">拍摄</div>
|
||||||
</div>
|
</div>
|
||||||
<div @click="chooseFile" class="flex flex-col items-center">
|
<div @click="chooseFile" class="flex flex-col items-center">
|
||||||
<div
|
<div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
|
||||||
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
|
|
||||||
>
|
|
||||||
<tm-image :width="53" :height="44" :src="folder"></tm-image>
|
<tm-image :width="53" :height="44" :src="folder"></tm-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">文件</div>
|
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">文件</div>
|
||||||
@ -72,7 +58,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
base64Url: ''
|
base64Url: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const uploadsStore = useUploadsStore()
|
const uploadsStore = useUploadsStore()
|
||||||
@ -92,8 +78,9 @@ const onProgressFn = (progress, id) => {
|
|||||||
updateUploadProgress(id, (progress.loaded / progress.total) * 100)
|
updateUploadProgress(id, (progress.loaded / progress.total) * 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
const photoActionsSelect = (index) => {
|
const photoActionsSelect = async (index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
if (typeof plus === 'undefined') {
|
||||||
uni.chooseImage({
|
uni.chooseImage({
|
||||||
sourceType: ['album'],
|
sourceType: ['album'],
|
||||||
count: 9,
|
count: 9,
|
||||||
@ -106,22 +93,211 @@ const photoActionsSelect = (index) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
uni.chooseVideo({
|
plus?.gallery.pick(
|
||||||
sourceType: ['album'],
|
(res) => {
|
||||||
success: async (res) => {
|
|
||||||
console.log(res, 'res')
|
console.log(res, 'res')
|
||||||
let data = await onUploadImageVideo(
|
res.files.reverse()
|
||||||
res.tempFile,
|
res.files.forEach(async (filePath) => {
|
||||||
'video',
|
plus?.io?.resolveLocalFileSystemURL(
|
||||||
res.tempFilePath,
|
filePath,
|
||||||
)
|
async (entry) => {
|
||||||
|
entry.file((file) => {
|
||||||
|
const fileReader = new plus.io.FileReader()
|
||||||
|
fileReader.readAsDataURL(file)
|
||||||
|
fileReader.onloadend = async (e) => {
|
||||||
|
const base64Url = e.target.result
|
||||||
|
const fileObj = base64ToFile(base64Url)
|
||||||
|
let data = await onUploadImageVideo(fileObj, 'image')
|
||||||
emit('selectImg', data, data.file_num)
|
emit('selectImg', data, data.file_num)
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: 'image',
|
||||||
|
maximum: 9,
|
||||||
|
multiple: true,
|
||||||
|
onmaxed: () => {
|
||||||
|
plus.nativeUI.toast('最多只能选择9张图片')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// uni.chooseVideo({
|
||||||
|
// sourceType: ['album'],
|
||||||
|
// compressed: true,
|
||||||
|
// maxDuration: 60,
|
||||||
|
// success: async (res) => {
|
||||||
|
// console.log( 'chooseVideo res.tempFilePath',res.tempFilePath)
|
||||||
|
// console.log( 'chooseVideo res.tempFile',res.tempFile)
|
||||||
|
// return
|
||||||
|
// let data = await onUploadImageVideo(
|
||||||
|
// res.tempFile,
|
||||||
|
// 'video',
|
||||||
|
// res.tempFilePath,
|
||||||
|
// )
|
||||||
|
// emit('selectImg', data, data.file_num)
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
|
||||||
|
plus?.gallery.pick(
|
||||||
|
(res) => {
|
||||||
|
res.files.reverse()
|
||||||
|
res.files.forEach(async (filePath) => {
|
||||||
|
plus?.io?.resolveLocalFileSystemURL(
|
||||||
|
filePath,
|
||||||
|
async (entry) => {
|
||||||
|
entry.file(async (file) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('filePath', filePath)
|
||||||
|
// 获取文件内容并创建 Blob URL
|
||||||
|
playVideoWithNativeBridge(filePath)
|
||||||
|
const videoInfo = await getVideoInfo(filePath);
|
||||||
|
console.log('视频信息:', videoInfo);
|
||||||
|
|
||||||
|
console.log('文件详细信息:', {
|
||||||
|
name: file.name,
|
||||||
|
size: file.size,
|
||||||
|
type: file.type,
|
||||||
|
});
|
||||||
|
const fileInfo = await getFilePath(file);
|
||||||
|
console.log('fileInfo', fileInfo)
|
||||||
|
|
||||||
|
// 继续处理上传逻辑
|
||||||
|
let data = await onUploadImageVideo(file, 'video', videoInfo);
|
||||||
|
emit('selectImg', data, data.file_num);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('文件处理失败:', error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: 'video',
|
||||||
|
maximum: 2,
|
||||||
|
multiple: true,
|
||||||
|
onmaxed: () => {
|
||||||
|
plus.nativeUI.toast('最多只能选择2个视频')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
const playVideoWithNativeBridge = (filePath) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.playVideo) {
|
||||||
|
// iOS WebView 桥接
|
||||||
|
window.webkit.messageHandlers.playVideo.postMessage({
|
||||||
|
filePath: filePath
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
} else if (window.android && window.android.playVideo) {
|
||||||
|
// Android WebView 桥接
|
||||||
|
window.android.playVideo(filePath);
|
||||||
|
resolve();
|
||||||
|
} else if (window.plus) {
|
||||||
|
// 使用 plus API 创建本地 HTTP 服务
|
||||||
|
plus.bridge.exec('VideoPlayerModule', 'playVideoFromPath', [filePath],
|
||||||
|
(httpUrl) => {
|
||||||
|
console.log('获取到HTTP URL:', httpUrl);
|
||||||
|
resolve(httpUrl);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.error('原生方法调用失败:', error);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
reject(new Error('没有可用的原生桥接方法'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const getFilePath = async (file) => {
|
||||||
|
try {
|
||||||
|
// #ifdef H5
|
||||||
|
// 将 plus 文件对象转换为 Blob
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
|
||||||
|
const reader = new plus.io.FileReader();
|
||||||
|
|
||||||
|
reader.onload = function (e) {
|
||||||
|
// 将文件内容转换为 Blob
|
||||||
|
const blob = new Blob([e.target.result], { type: file.type || 'video/mp4' });
|
||||||
|
// 创建新的 File 对象
|
||||||
|
const newFile = new File([blob], file.name || 'video.mp4', {
|
||||||
|
type: file.type || 'video/mp4'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建新的 FormData
|
||||||
|
// const formData = new FormData();
|
||||||
|
// formData.append('file', newFile);
|
||||||
|
// 添加其他需要的字段
|
||||||
|
// formData.append('other_field', 'value');
|
||||||
|
|
||||||
|
resolve(newFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.onerror = function (error) {
|
||||||
|
console.error('读取文件失败:', error);
|
||||||
|
reject(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef H5
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
return formData;
|
||||||
|
// #endif
|
||||||
|
} catch (error) {
|
||||||
|
console.error('处理文件失败:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const onUploadImageVideo = async (file, type = 'image', resp) => {
|
||||||
console.log(file, 'file')
|
console.log(file, 'file')
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
if (type === 'image') {
|
if (type === 'image') {
|
||||||
@ -132,6 +308,7 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
form.append('urlParam', `width=${image.width}&height=${image.height}`)
|
form.append('urlParam', `width=${image.width}&height=${image.height}`)
|
||||||
|
|
||||||
let randomId = uniqueId()
|
let randomId = uniqueId()
|
||||||
let newItem = {
|
let newItem = {
|
||||||
avatar: userStore.avatar,
|
avatar: userStore.avatar,
|
||||||
@ -164,6 +341,12 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
||||||
({ status, data, msg }) => {
|
({ status, data, msg }) => {
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
// 更新上传状态为成功
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 2
|
||||||
|
virtualList.value[index].uploadCurrent = 100
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
type: 'image',
|
type: 'image',
|
||||||
url: data.ori_url,
|
url: data.ori_url,
|
||||||
@ -173,6 +356,11 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
file_num: randomId,
|
file_num: randomId,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
resolve('')
|
resolve('')
|
||||||
message.error(msg)
|
message.error(msg)
|
||||||
}
|
}
|
||||||
@ -180,14 +368,15 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.getVideoInfo({
|
const form = new FormData()
|
||||||
src: fileUrl,
|
|
||||||
success: (resp) => {
|
|
||||||
console.log(resp)
|
|
||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
form.append('type', 'video')
|
form.append('type', 'video')
|
||||||
form.append('urlParam', `width=${resp.width}&height=${resp.height}`)
|
form.append('urlParam', `width=${resp.width}&height=${resp.height}`)
|
||||||
|
// 打印 FormData 内容
|
||||||
|
for (let pair of form.entries()) {
|
||||||
|
console.log('video form', `${pair[0]}: ${pair[1]}`);
|
||||||
|
}
|
||||||
let randomId = uniqueId()
|
let randomId = uniqueId()
|
||||||
let newItem = {
|
let newItem = {
|
||||||
avatar: userStore.avatar,
|
avatar: userStore.avatar,
|
||||||
@ -196,7 +385,7 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
duration: parseInt(resp.duration),
|
duration: parseInt(resp.duration),
|
||||||
height: resp.height,
|
height: resp.height,
|
||||||
name: '',
|
name: '',
|
||||||
url: fileUrl,
|
url: resp.fileUrl,
|
||||||
width: resp.width,
|
width: resp.width,
|
||||||
},
|
},
|
||||||
float: 'right',
|
float: 'right',
|
||||||
@ -216,9 +405,16 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
|
console.log('uploadImg params', form)
|
||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
||||||
({ status, data, msg }) => {
|
({ status, data, msg }) => {
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
// 更新上传状态为成功
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 2
|
||||||
|
virtualList.value[index].uploadCurrent = 100
|
||||||
|
}
|
||||||
console.log(data)
|
console.log(data)
|
||||||
resolve({
|
resolve({
|
||||||
type: 'video',
|
type: 'video',
|
||||||
@ -229,18 +425,43 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
file_num: randomId,
|
file_num: randomId,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// resolve('')
|
// 更新上传状态为失败
|
||||||
// message.error(msg)
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
resolve('')
|
||||||
|
message.error(msg)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
|
||||||
})
|
|
||||||
const form = new FormData()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getVideoInfo = (filePath) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.io.getVideoInfo({
|
||||||
|
filePath: filePath,
|
||||||
|
success: (res) => {
|
||||||
|
resolve({
|
||||||
|
width: res.width,
|
||||||
|
height: res.height,
|
||||||
|
duration: res.duration,
|
||||||
|
fileUrl: filePath,
|
||||||
|
size: res.size
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log('获取视频信息失败:', err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const base64ToFile = (base64) => {
|
const base64ToFile = (base64) => {
|
||||||
// base64转file
|
// base64转file
|
||||||
const [header, base64String] = base64.split(';base64,')
|
const [header, base64String] = base64.split(';base64,')
|
||||||
@ -351,7 +572,7 @@ const getCamera = () => {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
() => {},
|
() => { },
|
||||||
{ index: '2' },
|
{ index: '2' },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -414,7 +635,23 @@ const chooseFile = () => {
|
|||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId)
|
uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId, (status, data, msg) => {
|
||||||
|
if (status === 0) {
|
||||||
|
// 更新上传状态为成功
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 2
|
||||||
|
virtualList.value[index].uploadCurrent = 100
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === randomId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user