mirror of
https://gitee.com/lijingbo-2021/open-anylink-web.git
synced 2025-12-30 11:02:25 +00:00
Image加载完成前的默认渲染处理
This commit is contained in:
@@ -84,10 +84,10 @@ const onSave = async () => {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const md5 = await getMd5(file)
|
||||
const thumbObj = await prehandleImage(file)
|
||||
const prehandleImageObj = await prehandleImage(file)
|
||||
const files = {
|
||||
originFile: file,
|
||||
thumbFile: thumbObj.thumbFile
|
||||
thumbFile: prehandleImageObj.thumbFile
|
||||
}
|
||||
const requestBody = {
|
||||
storeType: 0,
|
||||
@@ -95,10 +95,10 @@ const onSave = async () => {
|
||||
fileName: file.name,
|
||||
fileRawType: file.type,
|
||||
size: file.size,
|
||||
originWidth: thumbObj.originWidth,
|
||||
originHeight: thumbObj.originHeight,
|
||||
thumbWidth: thumbObj.thumbWidth,
|
||||
thumbHeight: thumbObj.thumbHeight
|
||||
originWidth: prehandleImageObj.originWidth,
|
||||
originHeight: prehandleImageObj.originHeight,
|
||||
thumbWidth: prehandleImageObj.thumbWidth,
|
||||
thumbHeight: prehandleImageObj.thumbHeight
|
||||
}
|
||||
const res = await mtsUploadServiceForImage(requestBody, files)
|
||||
emit('update:newAvatar', {
|
||||
|
||||
@@ -4,24 +4,40 @@ import { ElImage } from 'element-plus'
|
||||
import { formatFileSize } from '@/js/utils/common'
|
||||
import { useImageStore } from '@/stores'
|
||||
|
||||
const props = defineProps(['sessionId', 'imgId', 'isForMix'])
|
||||
const props = defineProps(['sessionId', 'imgId', 'isForMix', 'thumbWidth', 'thumbHeight'])
|
||||
const emits = defineEmits(['load'])
|
||||
|
||||
const imageData = useImageStore()
|
||||
|
||||
const onLoad = (e) => {
|
||||
const img = e.target
|
||||
const maxWidth = props.isForMix ? Math.min(img.naturalWidth, 360) : 360
|
||||
const maxHeight = props.isForMix ? Math.min(img.naturalHeight, 180) : 180
|
||||
const maxWidth = computed(() => {
|
||||
return props.isForMix ? Math.min(props.thumbWidth, 360) : 360
|
||||
})
|
||||
|
||||
if (img.naturalWidth / img.naturalHeight > maxWidth / maxHeight) {
|
||||
img.style.width = maxWidth + 'px'
|
||||
img.style.height = 'auto'
|
||||
const maxHeight = computed(() => {
|
||||
return props.isForMix ? Math.min(props.thumbHeight, 270) : 270
|
||||
})
|
||||
|
||||
const renderWidth = computed(() => {
|
||||
if (!props.thumbWidth || !props.thumbHeight) {
|
||||
return 360 // 如果拿不到缩略图大小,默认以 360*270 尺寸显示
|
||||
} else if (props.thumbWidth / props.thumbHeight > maxWidth.value / maxHeight.value) {
|
||||
return maxWidth.value
|
||||
} else {
|
||||
img.style.height = maxHeight + 'px'
|
||||
img.style.width = 'auto'
|
||||
return (props.thumbWidth / props.thumbHeight) * maxHeight.value
|
||||
}
|
||||
})
|
||||
|
||||
const renderHeight = computed(() => {
|
||||
if (!props.thumbWidth || !props.thumbHeight) {
|
||||
return 270 // 如果拿不到缩略图大小,默认以 360*270 尺寸显示
|
||||
} else if (props.thumbWidth / props.thumbHeight > maxWidth.value / maxHeight.value) {
|
||||
return (props.thumbHeight / props.thumbWidth) * maxWidth.value
|
||||
} else {
|
||||
return maxHeight.value
|
||||
}
|
||||
})
|
||||
|
||||
const onLoad = async () => {
|
||||
emits('load') //向父组件暴露load事件
|
||||
}
|
||||
|
||||
@@ -70,8 +86,15 @@ const formatSize = computed(() => {
|
||||
:infinite="false"
|
||||
:lazy="false"
|
||||
fit="contain"
|
||||
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
||||
@load="onLoad"
|
||||
>
|
||||
<template #placeholder>
|
||||
<div
|
||||
class="image-msg-placeholder loading"
|
||||
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
||||
></div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div v-if="fileName || size > 0" class="info">
|
||||
<span class="name item text-ellipsis" :title="fileName">
|
||||
@@ -125,4 +148,30 @@ const formatSize = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-msg-placeholder {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.image-msg-placeholder.loading::before {
|
||||
content: '';
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-top: -15px;
|
||||
margin-left: -15px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid #ccc;
|
||||
border-top-color: #007bff;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -118,23 +118,24 @@ const parseContent = async (callbacks) => {
|
||||
// base64编码的图片
|
||||
const file = base64ToFile(insert.image, uuidv4()) // base64转file
|
||||
const tempObjectId = new Date().getTime()
|
||||
contentFromLocal[index] = `{${tempObjectId}}`
|
||||
// 发送的时候设置本地缓存(非服务端数据),用于立即渲染
|
||||
const md5 = await getMd5(file)
|
||||
const prehandleImageObj = await prehandleImage(file)
|
||||
const localSrc = URL.createObjectURL(file)
|
||||
imageData.setImage({
|
||||
objectId: tempObjectId,
|
||||
originUrl: localSrc,
|
||||
thumbUrl: localSrc,
|
||||
thumbUrl: localSrc, // 本地缓存缩略图用的是原图
|
||||
fileName: file.name,
|
||||
size: file.size,
|
||||
thumbWidth: prehandleImageObj.originWidth,
|
||||
thumbHeight: prehandleImageObj.originHeight,
|
||||
createdTime: new Date()
|
||||
})
|
||||
contentFromLocal[index] = `{${tempObjectId}}`
|
||||
|
||||
const md5 = await getMd5(file)
|
||||
const thumbObj = await prehandleImage(file)
|
||||
const files = {
|
||||
originFile: file,
|
||||
thumbFile: thumbObj.thumbFile
|
||||
thumbFile: prehandleImageObj.thumbFile
|
||||
}
|
||||
const requestBody = {
|
||||
storeType: 0,
|
||||
@@ -142,10 +143,10 @@ const parseContent = async (callbacks) => {
|
||||
fileName: file.name,
|
||||
fileRawType: file.type,
|
||||
size: file.size,
|
||||
originWidth: thumbObj.originWidth,
|
||||
originHeight: thumbObj.originHeight,
|
||||
thumbWidth: thumbObj.thumbWidth,
|
||||
thumbHeight: thumbObj.thumbHeight
|
||||
originWidth: prehandleImageObj.originWidth,
|
||||
originHeight: prehandleImageObj.originHeight,
|
||||
thumbWidth: prehandleImageObj.thumbWidth,
|
||||
thumbHeight: prehandleImageObj.thumbHeight
|
||||
}
|
||||
|
||||
//上传图片至服务端
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Clock, Microphone } from '@element-plus/icons-vue'
|
||||
import { ElLoading, ElMessage } from 'element-plus'
|
||||
import { el_loading_options } from '@/const/commonConst'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import EmojiIcon from '@/assets/svg/emoji.svg'
|
||||
import FileIcon from '@/assets/svg/file.svg'
|
||||
import ImageIcon from '@/assets/svg/image.svg'
|
||||
@@ -41,25 +40,23 @@ const onSelectedFile = async (file) => {
|
||||
|
||||
let contentType = msgContentType.DOCUMENT
|
||||
let md5
|
||||
let thumbObj
|
||||
let videoObj
|
||||
let prehandleImageObj
|
||||
let prehandleVideoObj
|
||||
let msg = {}
|
||||
let loadingInstance
|
||||
|
||||
try {
|
||||
loadingInstance = ElLoading.service(el_loading_options)
|
||||
md5 = await getMd5(file.raw)
|
||||
if (file.raw.type.startsWith('image/')) {
|
||||
contentType = msgContentType.IMAGE
|
||||
thumbObj = await prehandleImage(file.raw)
|
||||
prehandleImageObj = await prehandleImage(file.raw)
|
||||
} else if (file.raw.type.startsWith('audio/')) {
|
||||
contentType = msgContentType.AUDIO
|
||||
} else if (file.raw.type.startsWith('video/')) {
|
||||
contentType = msgContentType.VIDEO
|
||||
videoObj = await prehandleVideo(file.raw)
|
||||
prehandleVideoObj = await prehandleVideo(file.raw)
|
||||
}
|
||||
|
||||
setLocalData(contentType, file, videoObj)
|
||||
setLocalData(contentType, file, prehandleImageObj, prehandleVideoObj)
|
||||
|
||||
emit('saveLocalMsg', {
|
||||
contentType: contentType,
|
||||
@@ -70,8 +67,6 @@ const onSelectedFile = async (file) => {
|
||||
})
|
||||
} catch (error) {
|
||||
return
|
||||
} finally {
|
||||
loadingInstance.close()
|
||||
}
|
||||
|
||||
let requestApi = mtsUploadService
|
||||
@@ -85,15 +80,15 @@ const onSelectedFile = async (file) => {
|
||||
const files = { originFile: file.raw }
|
||||
|
||||
if (contentType === msgContentType.IMAGE) {
|
||||
requestBody.originWidth = thumbObj.originWidth
|
||||
requestBody.originHeight = thumbObj.originHeight
|
||||
requestBody.thumbWidth = thumbObj.thumbWidth
|
||||
requestBody.thumbHeight = thumbObj.thumbHeight
|
||||
files.thumbFile = thumbObj.thumbFile
|
||||
requestBody.originWidth = prehandleImageObj.originWidth
|
||||
requestBody.originHeight = prehandleImageObj.originHeight
|
||||
requestBody.thumbWidth = prehandleImageObj.thumbWidth
|
||||
requestBody.thumbHeight = prehandleImageObj.thumbHeight
|
||||
files.thumbFile = prehandleImageObj.thumbFile
|
||||
requestApi = mtsUploadServiceForImage
|
||||
} else if (contentType === msgContentType.VIDEO) {
|
||||
requestBody.videoWidth = videoObj.width
|
||||
requestBody.videoHeight = videoObj.height
|
||||
requestBody.videoWidth = prehandleVideoObj.width
|
||||
requestBody.videoHeight = prehandleVideoObj.height
|
||||
}
|
||||
|
||||
messageData.updateMsg(msg.sessionId, msg.msgId, {
|
||||
@@ -130,16 +125,18 @@ const onSelectedFile = async (file) => {
|
||||
* @param contentType
|
||||
* @param file
|
||||
*/
|
||||
const setLocalData = (contentType, file, videoObj) => {
|
||||
const setLocalData = (contentType, file, prehandleImageObj, prehandleVideoObj) => {
|
||||
const localSrc = URL.createObjectURL(file.raw)
|
||||
switch (contentType) {
|
||||
case msgContentType.IMAGE:
|
||||
imageData.setImage({
|
||||
objectId: file.uid,
|
||||
originUrl: localSrc,
|
||||
thumbUrl: localSrc,
|
||||
thumbUrl: localSrc, // 本地缓存缩略图用的是原图
|
||||
fileName: file.name,
|
||||
size: file.raw.size,
|
||||
thumbWidth: prehandleImageObj.originWidth,
|
||||
thumbHeight: prehandleImageObj.originHeight,
|
||||
createdTime: new Date()
|
||||
})
|
||||
break
|
||||
@@ -157,8 +154,8 @@ const setLocalData = (contentType, file, videoObj) => {
|
||||
downloadUrl: localSrc,
|
||||
fileName: file.name,
|
||||
size: file.raw.size,
|
||||
width: videoObj.width,
|
||||
height: videoObj.height
|
||||
width: prehandleVideoObj.width,
|
||||
height: prehandleVideoObj.height
|
||||
})
|
||||
break
|
||||
case msgContentType.DOCUMENT:
|
||||
|
||||
@@ -177,6 +177,8 @@ const renderImage = (content, isForMix = false) => {
|
||||
sessionId: props.sessionId,
|
||||
imgId,
|
||||
isForMix,
|
||||
thumbWidth: imageData.image[imgId].thumbWidth,
|
||||
thumbHeight: imageData.image[imgId].thumbHeight,
|
||||
onLoad: () => {
|
||||
emit('loadFinished')
|
||||
}
|
||||
|
||||
@@ -17,19 +17,19 @@ const formatSize = computed(() => {
|
||||
|
||||
const renderWidth = computed(() => {
|
||||
if (!props.width || !props.height) {
|
||||
return 480
|
||||
return 480 // 如果拿不到视频大小,默认以 480*270 尺寸播放
|
||||
} else if (props.width > props.height) {
|
||||
return 480
|
||||
} else {
|
||||
return Math.floor((props.width / props.height) * 320)
|
||||
return (props.width / props.height) * 320
|
||||
}
|
||||
})
|
||||
|
||||
const renderHeight = computed(() => {
|
||||
if (!props.width || !props.height) {
|
||||
return 270
|
||||
return 270 // 如果拿不到视频大小,默认以 480*270 尺寸播放
|
||||
} else if (props.width > props.height) {
|
||||
return Math.floor((props.height / props.width) * 480)
|
||||
return (props.height / props.width) * 480
|
||||
} else {
|
||||
return 320
|
||||
}
|
||||
@@ -55,7 +55,7 @@ onMounted(() => {
|
||||
player.on('ready', () => {
|
||||
// 监听视频元数据加载完成事件
|
||||
const videoElement = player.root.querySelector('video')
|
||||
videoElement.addEventListener('loadedmetadata', async () => {
|
||||
videoElement.addEventListener('loadedmetadata', () => {
|
||||
videoWrapperRef.value.style.width = `${renderWidth.value}px`
|
||||
videoWrapperRef.value.style.height = `${renderHeight.value}px`
|
||||
videoWrapperRef.value.style.padding = 0
|
||||
@@ -68,7 +68,8 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="video-msg-wrapper loading"
|
||||
class="video-msg-wrapper"
|
||||
:class="{ loading: !isLoaded }"
|
||||
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
||||
>
|
||||
<div v-show="isLoaded" ref="videoWrapperRef" :id="`msg-xgplayer-${props.videoId}`"></div>
|
||||
|
||||
Reference in New Issue
Block a user