mirror of
https://gitee.com/lijingbo-2021/open-anylink-web.git
synced 2026-05-11 18:02:46 +00:00
196 lines
4.7 KiB
Vue
196 lines
4.7 KiB
Vue
<script setup>
|
|
import { computed } from 'vue'
|
|
import { ElImage } from 'element-plus'
|
|
import { formatFileSize } from '@/js/utils/common'
|
|
import { useImageStore } from '@/stores'
|
|
import ImageloadfailedIcon from '@/assets/svg/imageloadfailed.svg'
|
|
|
|
const props = defineProps(['sessionId', 'imgId', 'isScreenShot', 'thumbWidth', 'thumbHeight'])
|
|
const emits = defineEmits(['load'])
|
|
|
|
const imageData = useImageStore()
|
|
|
|
const maxWidth = computed(() => {
|
|
return props.isScreenShot ? Math.min(props.thumbWidth, 360) : 360
|
|
})
|
|
|
|
const maxHeight = computed(() => {
|
|
return props.isScreenShot ? 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 {
|
|
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事件
|
|
}
|
|
|
|
const url = computed(() => {
|
|
return imageData.image[props.imgId]?.thumbUrl
|
|
})
|
|
|
|
const imageInSessionSort = computed(() => {
|
|
const imageList = Object.values(imageData.imageInSession[props.sessionId])
|
|
return imageList.sort((a, b) => {
|
|
const bTime = new Date(b.createdTime).getTime()
|
|
const aTime = new Date(a.createdTime).getTime()
|
|
return aTime - bTime
|
|
})
|
|
})
|
|
|
|
const srcList = computed(() => {
|
|
return imageInSessionSort.value.map((item) => item.originUrl)
|
|
})
|
|
|
|
const initialIndex = computed(() => {
|
|
const imgIdList = imageInSessionSort.value.map((item) => item.objectId.toString())
|
|
return imgIdList.indexOf(props.imgId.toString())
|
|
})
|
|
|
|
const fileName = computed(() => {
|
|
return props.isScreenShot ? '' : imageData.image[props.imgId]?.fileName
|
|
})
|
|
|
|
const size = computed(() => {
|
|
return props.isScreenShot ? '' : imageData.image[props.imgId]?.size
|
|
})
|
|
|
|
const formatSize = computed(() => {
|
|
return formatFileSize(size.value)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="image-msg-wrapper">
|
|
<el-image
|
|
:src="url"
|
|
:alt="props.imgId"
|
|
:preview-src-list="srcList"
|
|
hide-on-click-modal
|
|
preview-teleported
|
|
:initial-index="initialIndex"
|
|
:infinite="false"
|
|
:lazy="false"
|
|
fit="contain"
|
|
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
|
@load="onLoad"
|
|
>
|
|
<template #placeholder>
|
|
<div
|
|
class="image-msg-bgc loading"
|
|
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
|
></div>
|
|
</template>
|
|
<template #error>
|
|
<div
|
|
class="image-msg-bgc error"
|
|
:style="{ width: `${renderWidth}px`, height: `${renderHeight}px` }"
|
|
>
|
|
<ImageloadfailedIcon style="width: 48px; height: 48px; fill: #fff" />
|
|
</div>
|
|
</template>
|
|
</el-image>
|
|
<div v-if="fileName || size > 0" class="info">
|
|
<span class="name item text-ellipsis" :title="fileName">
|
|
{{ fileName || '' }}
|
|
</span>
|
|
<span class="size item text-ellipsis" :title="formatSize">
|
|
{{ formatSize }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.image-msg-wrapper {
|
|
display: flex;
|
|
position: relative;
|
|
|
|
.el-image {
|
|
width: auto;
|
|
height: auto;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
|
|
:deep(.el-image__inner) {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
.info {
|
|
width: 100%;
|
|
height: 32px;
|
|
line-height: 32px;
|
|
left: 0;
|
|
bottom: 0;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5));
|
|
position: absolute;
|
|
|
|
.item {
|
|
max-width: 40%;
|
|
color: #fff;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.name {
|
|
margin-left: 8px;
|
|
}
|
|
|
|
.size {
|
|
margin-right: 8px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.image-msg-bgc {
|
|
background-color: #000;
|
|
}
|
|
|
|
.image-msg-bgc.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;
|
|
}
|
|
|
|
.image-msg-bgc.error {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
</style>
|