<template> <div class="emojiRoot"> <div @click="() => photoActionsSelect(0)" 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> </div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">照片</div> </div> <div @click="() => photoActionsSelect(1)" 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> </div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">视频</div> </div> <div @click="takePhoto" 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="photoGraph"></tm-image> </div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">拍摄</div> </div> <div @click="chooseFile" 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="folder"></tm-image> </div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">文件</div> </div> </div> </template> <script setup> import { ref, reactive, defineProps, defineEmits } from 'vue' import dayjs from 'dayjs' import { beautifyTime } from '@/utils/datetime' import { useDialogueListStore, useDialogueStore, useUserStore, useUploadsStore, } from '@/store' import { useSessionMenu } from '@/hooks' import photoAlbum from '@/static/image/chatList/photoAlbum.png' import photoGraph from '@/static/image/chatList/photoGraph.png' import videoImg from '@/static/image/chatList/video@2x.png' import folder from '@/static/image/chatList/folder.png' import { uploadImg } from '@/api/chat' import { uniqueId } from '@/utils' const props = defineProps({ sendUserInfo: { type: Object, default: {}, required: true, }, talkParams: { type: Object, default: {}, required: true, }, }) const state = reactive({ base64Url: '' }) const uploadsStore = useUploadsStore() const { addDialogueRecord, virtualList, updateUploadProgress, } = useDialogueListStore() const dialogueStore = useDialogueStore() const userStore = useUserStore() const emit = defineEmits(['selectImg']) const onProgressFn = (progress, id) => { console.log((progress.loaded / progress.total) * 100, 'progress') updateUploadProgress(id, (progress.loaded / progress.total) * 100) } const photoActionsSelect = (index) => { if (index === 0) { uni.chooseImage({ sourceType: ['album'], count: 9, success: async (res) => { console.log(res, 'res') res.tempFiles.forEach(async (file) => { let data = await onUploadImageVideo(file, 'image') emit('selectImg', data, data.file_num) }) }, }) } else { uni.chooseVideo({ sourceType: ['album'], compressed: true, maxDuration: 60, success: async (res) => { console.log(res, 'res') let data = await onUploadImageVideo( res.tempFile, 'video', res.tempFilePath, ) emit('selectImg', data, data.file_num) }, }) } } const onUploadImageVideo = async (file, type = 'image', fileUrl) => { console.log(file, 'file') return new Promise(async (resolve) => { if (type === 'image') { let image = new Image() image.src = URL.createObjectURL(file) image.onload = () => { const form = new FormData() form.append('file', file) form.append('source', 'fonchain-chat') form.append('urlParam', `width=${image.width}&height=${image.height}`) let randomId = uniqueId() let newItem = { avatar: userStore.avatar, created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), extra: { height: image.height, name: '', size: 0, url: image.src, width: image.width, }, float: 'right', isCheck: false, is_mark: 0, is_read: 0, is_revoke: 0, msg_id: randomId, file_num: randomId, msg_type: 3, nickname: userStore.nickname, receiver_id: dialogueStore.talk.receiver_id, sequence: -1, talk_type: dialogueStore.talk.talk_type, user_id: userStore.uid, uploadCurrent: 0, uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败 } virtualList.value.unshift(newItem) uploadImg(form, (e) => onProgressFn(e, randomId)).then( ({ status, data, msg }) => { if (status == 0) { resolve({ type: 'image', url: data.ori_url, size: file.size, width: image.width, height: image.height, file_num: randomId, }) } else { resolve('') message.error(msg) } }, ) } } else { uni.getVideoInfo({ src: fileUrl, success: (resp) => { console.log(resp) form.append('file', file) form.append('source', 'fonchain-chat') form.append('type', 'video') form.append('urlParam', `width=${resp.width}&height=${resp.height}`) let randomId = uniqueId() let newItem = { avatar: userStore.avatar, created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), extra: { duration: parseInt(resp.duration), height: resp.height, name: '', url: fileUrl, width: resp.width, }, float: 'right', isCheck: false, is_mark: 0, is_read: 0, is_revoke: 0, msg_id: randomId, file_num: randomId, msg_type: 5, nickname: userStore.nickname, receiver_id: dialogueStore.talk.receiver_id, sequence: -1, talk_type: dialogueStore.talk.talk_type, user_id: userStore.uid, uploadCurrent: 0, uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败 } virtualList.value.unshift(newItem) uploadImg(form, (e) => onProgressFn(e, randomId)).then( ({ status, data, msg }) => { if (status == 0) { console.log(data) resolve({ type: 'video', url: data.ori_url, cover: data.cover_url, duration: parseInt(resp.duration), size: file.size, file_num: randomId, }) } else { // resolve('') // message.error(msg) } }, ) }, }) const form = new FormData() } }) } const base64ToFile = (base64) => { // base64转file const [header, base64String] = base64.split(';base64,') const imageType = header.split(':')[1] const byteCharacters = atob(base64String) const byteArray = new Uint8Array( Array.from(byteCharacters, (char) => char.charCodeAt(0)), ) return new File([new Blob([byteArray], { type: imageType })], 'example.png', { type: imageType, }) } const choosePhoto = (filter = 'none', maximum = 9, multiple = true) => { window.plus?.gallery.pick( (res) => { console.log(res) res.files.reverse() res.files.forEach(async (filePath) => { const suffix = filePath.split('.').pop()?.toLowerCase() || '' if (['jpg', 'png'].includes(suffix)) { console.log('进入图片') window.plus?.io?.resolveLocalFileSystemURL( 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) } }) }, (err) => { console.log(err) }, ) } if (['mp4', 'flv'].includes(suffix)) { console.log(filePath, '进入视频') // const localUrl = plus.io.convertLocalFileSystemURL(filePath) // console.log(localUrl); plus.io.getVideoInfo({ filePath: filePath, success: (event) => { console.log(event) }, fail: (err) => { console.log(err) }, }) // window.plus?.io?.resolveLocalFileSystemURL(localUrl, async (entry) => { // entry.file((file) => { // console.log(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, 'video') // emit('selectImg', data) // }; // }) // }, // (err) => { // console.log(err); // } // ) } }) }, (err) => { console.log(err) }, { filter: filter, maximum: maximum, multiple: multiple, }, ) } const takePhoto = () => { if (typeof plus !== 'undefined') { getCamera() } else { document.addEventListener('plusready', () => { getCamera() }) } } const getCamera = () => { const cmr = plus.camera.getCamera() cmr.captureImage( (p) => { plus.io.resolveLocalFileSystemURL( p, (entry) => { compressAndShowImage(entry.toLocalURL(), entry.name) }, (err) => { console.log(err) }, ) }, () => {}, { index: '2' }, ) } const compressAndShowImage = (url, filename) => { const dst = `_doc/upload/${filename}` plus.zip.compressImage( { src: url, dst, quality: 10, overwrite: true }, (zip) => displayImage(zip.target), (err) => { console.log(err) }, ) } const displayImage = (url) => { plus.io.resolveLocalFileSystemURL(url, (entry) => { entry.file((file) => { const fileReader = new plus.io.FileReader() fileReader.readAsDataURL(file) fileReader.onloadend = async (e) => { state.base64Url = e.target.result const imageFile = base64ToFile(state.base64Url) let data = await onUploadImageVideo(imageFile, 'image') emit('selectImg', data, data.file_num) } }) }) } const chooseFile = () => { uni.chooseFile({ count: 1, extension: [''], success: (res) => { let randomId = uniqueId() let newItem = { avatar: userStore.avatar, created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), extra: { drive: 3, name: res.tempFiles[0].name, size: res.tempFiles[0].size, path: res.tempFilePaths[0], }, float: 'right', isCheck: false, is_mark: 0, is_read: 0, is_revoke: 0, msg_id: randomId, file_num: randomId, msg_type: 6, nickname: userStore.nickname, receiver_id: dialogueStore.talk.receiver_id, sequence: -1, talk_type: dialogueStore.talk.talk_type, user_id: userStore.uid, uploadCurrent: 0, uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败 } virtualList.value.unshift(newItem) uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId) }, }) } </script> <style lang="scss" scoped> .emojiRoot { width: 100%; height: 232rpx; padding: 20rpx 62rpx 0 62rpx; display: flex; justify-content: space-between; align-items: flex-start; } </style>