mirror of
https://gitee.com/lijingbo-2021/open-anylink-web.git
synced 2025-12-30 02:52:26 +00:00
同一session中共用一个preview-src-list
This commit is contained in:
@@ -44,7 +44,7 @@ export const onReceiveChatMsg = (updateScroll, capacity) => {
|
||||
content: msg.body.content,
|
||||
msgTime: now
|
||||
}
|
||||
await messageData.preloadResource(sessionId, [showMsg])
|
||||
await messageData.preloadResource([showMsg])
|
||||
messageData.addMsgRecords(sessionId, [showMsg])
|
||||
messageData.updateMsgIdSort(sessionId)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ export const onReceiveGroupChatMsg = (updateScroll, capacity) => {
|
||||
content: msg.body.content,
|
||||
msgTime: now
|
||||
}
|
||||
await messageData.preloadResource(sessionId, [showMsg])
|
||||
await messageData.preloadResource([showMsg])
|
||||
messageData.addMsgRecords(sessionId, [showMsg])
|
||||
messageData.updateMsgIdSort(sessionId)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export const onReceiveGroupSystemMsg = (updateScroll, capacity) => {
|
||||
content: msg.body.content,
|
||||
msgTime: now
|
||||
}
|
||||
await messageData.preloadResource(sessionId, [showMsg])
|
||||
await messageData.preloadResource([showMsg])
|
||||
messageData.addMsgRecords(sessionId, [showMsg])
|
||||
messageData.updateMsgIdSort(sessionId)
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ export const useAudioStore = defineStore('anylink-audio', () => {
|
||||
*/
|
||||
const audio = ref({})
|
||||
|
||||
const setAudio = (sessionId, obj) => {
|
||||
const setAudio = (obj) => {
|
||||
audio.value[obj.objectId] = obj
|
||||
}
|
||||
|
||||
const preloadAudio = async (sessionId, msgRecords) => {
|
||||
const preloadAudio = async (msgRecords) => {
|
||||
const audioIds = new Set()
|
||||
msgRecords.forEach((item) => {
|
||||
const content = item.content
|
||||
@@ -37,7 +37,7 @@ export const useAudioStore = defineStore('anylink-audio', () => {
|
||||
if (audioIds.size > 0) {
|
||||
const res = await mtsAudioService({ objectIds: [...audioIds].join(',') })
|
||||
res.data.data.forEach((item) => {
|
||||
setAudio(sessionId, item)
|
||||
setAudio(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ export const useDocumentStore = defineStore('anylink-document', () => {
|
||||
*/
|
||||
const document = ref({})
|
||||
|
||||
const setDocument = (sessionId, obj) => {
|
||||
const setDocument = (obj) => {
|
||||
document.value[obj.objectId] = obj
|
||||
}
|
||||
|
||||
const preloadDocument = async (sessionId, msgRecords) => {
|
||||
const preloadDocument = async (msgRecords) => {
|
||||
const documentIds = new Set()
|
||||
msgRecords.forEach((item) => {
|
||||
const content = item.content
|
||||
@@ -34,7 +34,7 @@ export const useDocumentStore = defineStore('anylink-document', () => {
|
||||
if (documentIds.size > 0) {
|
||||
const res = await mtsDocumentService({ objectIds: [...documentIds].join(',') })
|
||||
res.data.data.forEach((item) => {
|
||||
setDocument(sessionId, item)
|
||||
setDocument(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,24 +17,25 @@ export const useImageStore = defineStore('anylink-image', () => {
|
||||
const image = ref({})
|
||||
|
||||
/**
|
||||
* 在同一个session中的image(id)集合
|
||||
* 在同一个session中的需要渲染的image对象数组
|
||||
*/
|
||||
const imageInSession = ref({})
|
||||
|
||||
/**
|
||||
* 本地图片只是临时的,不用放进imageInSession
|
||||
* @param {*} obj
|
||||
*/
|
||||
const setLocalImage = (obj) => {
|
||||
const setImage = (obj) => {
|
||||
image.value[obj.objectId] = obj
|
||||
}
|
||||
|
||||
const setServerImage = (sessionId, obj) => {
|
||||
image.value[obj.objectId] = obj
|
||||
const setImageInSession = (sessionId, obj) => {
|
||||
if (!imageInSession.value[sessionId]) {
|
||||
imageInSession.value[sessionId] = []
|
||||
}
|
||||
imageInSession.value[sessionId].push(obj.objectId)
|
||||
imageInSession.value[sessionId].push(obj)
|
||||
}
|
||||
|
||||
const clearImageInSession = (sessionId) => {
|
||||
if (imageInSession.value[sessionId]) {
|
||||
imageInSession.value[sessionId] = []
|
||||
}
|
||||
}
|
||||
|
||||
const imageTrans = (content, maxWidth = 360, maxHeight = 180) => {
|
||||
@@ -60,7 +61,7 @@ export const useImageStore = defineStore('anylink-image', () => {
|
||||
return content
|
||||
}
|
||||
|
||||
const loadImageInfoFromContent = async (sessionId, content) => {
|
||||
const loadImageInfoFromContent = async (content) => {
|
||||
const imageIds = new Set()
|
||||
const matches = content.match(pattern)
|
||||
if (matches && matches.length > 0) {
|
||||
@@ -76,12 +77,12 @@ export const useImageStore = defineStore('anylink-image', () => {
|
||||
if (imageIds.size > 0) {
|
||||
const res = await mtsImageService({ objectIds: [...imageIds].join(',') })
|
||||
res.data.data.forEach((item) => {
|
||||
setServerImage(sessionId, item) // 缓存image数据
|
||||
setImage(item) // 缓存image数据
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const preloadImage = async (sessionId, msgRecords) => {
|
||||
const preloadImage = async (msgRecords) => {
|
||||
const imageIds = new Set()
|
||||
msgRecords.forEach((item) => {
|
||||
const content = item.content
|
||||
@@ -109,7 +110,7 @@ export const useImageStore = defineStore('anylink-image', () => {
|
||||
if (imageIds.size > 0) {
|
||||
const res = await mtsImageService({ objectIds: [...imageIds].join(',') })
|
||||
res.data.data.forEach((item) => {
|
||||
setServerImage(sessionId, item)
|
||||
setImage(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -117,8 +118,9 @@ export const useImageStore = defineStore('anylink-image', () => {
|
||||
return {
|
||||
image,
|
||||
imageInSession,
|
||||
setLocalImage,
|
||||
setServerImage,
|
||||
setImage,
|
||||
setImageInSession,
|
||||
clearImageInSession,
|
||||
imageTrans,
|
||||
loadImageInfoFromContent,
|
||||
preloadImage
|
||||
|
||||
@@ -121,11 +121,11 @@ export const useMessageStore = defineStore('anylink-message', () => {
|
||||
* @param {*} sessionId
|
||||
* @param {*} msgRecords
|
||||
*/
|
||||
const preloadResource = async (sessionId, msgRecords) => {
|
||||
await useImageStore().preloadImage(sessionId, msgRecords)
|
||||
await useAudioStore().preloadAudio(sessionId, msgRecords)
|
||||
await useVideoStore().preloadVideo(sessionId, msgRecords)
|
||||
await useDocumentStore().preloadDocument(sessionId, msgRecords)
|
||||
const preloadResource = async (msgRecords) => {
|
||||
await useImageStore().preloadImage(msgRecords)
|
||||
await useAudioStore().preloadAudio(msgRecords)
|
||||
await useVideoStore().preloadVideo(msgRecords)
|
||||
await useDocumentStore().preloadDocument(msgRecords)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +239,7 @@ export const useMessageStore = defineStore('anylink-message', () => {
|
||||
addSession(res.data.data[item].session)
|
||||
const msgList = res.data.data[item].msgList
|
||||
if (msgList) {
|
||||
await preloadResource(item, msgList)
|
||||
await preloadResource(msgList)
|
||||
addMsgRecords(item, msgList)
|
||||
updateMsgIdSort(item)
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ export const useVideoStore = defineStore('anylink-video', () => {
|
||||
*/
|
||||
const video = ref({})
|
||||
|
||||
const setVideo = (sessionId, obj) => {
|
||||
const setVideo = (obj) => {
|
||||
video.value[obj.objectId] = obj
|
||||
}
|
||||
|
||||
const preloadVideo = async (sessionId, msgRecords) => {
|
||||
const preloadVideo = async (msgRecords) => {
|
||||
const videoIds = new Set()
|
||||
msgRecords.forEach((item) => {
|
||||
const content = item.content
|
||||
@@ -34,7 +34,7 @@ export const useVideoStore = defineStore('anylink-video', () => {
|
||||
if (videoIds.size > 0) {
|
||||
const res = await mtsVideoService({ objectIds: [...videoIds].join(',') })
|
||||
res.data.data.forEach((item) => {
|
||||
setVideo(sessionId, item)
|
||||
setVideo(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
useMessageStore,
|
||||
useUserCardStore,
|
||||
useGroupCardStore,
|
||||
useGroupStore
|
||||
useGroupStore,
|
||||
useImageStore
|
||||
} from '@/stores'
|
||||
import backgroupImage from '@/assets/svg/messagebx_bg.svg'
|
||||
import {
|
||||
@@ -57,6 +58,7 @@ const messageData = useMessageStore()
|
||||
const userCardData = useUserCardStore()
|
||||
const groupCardData = useGroupCardStore()
|
||||
const groupData = useGroupStore()
|
||||
const imageData = useImageStore()
|
||||
const sessionListRef = ref()
|
||||
|
||||
const asideWidth = ref(0)
|
||||
@@ -180,6 +182,7 @@ const initSession = (sessionId) => {
|
||||
}
|
||||
isShowRecorder.value = false // 麦克风输入状态重置
|
||||
inputRecorderRef.value?.cancelSend() // 取消音频发送
|
||||
imageData.clearImageInSession(sessionId) // 清除待渲染的图片队列
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,9 +329,9 @@ const sessionListSorted = computed(() => {
|
||||
if (!b_msgIds_len) return -1
|
||||
const b_lastMsg = messageData.getMsg(b.sessionId, b_msgIds[b_msgIds_len - 1])
|
||||
const bTime = new Date(b_lastMsg.msgTime).getTime()
|
||||
const aTIme = new Date(a_lastMsg.msgTime).getTime()
|
||||
if (bTime !== aTIme) {
|
||||
return bTime - aTIme
|
||||
const aTime = new Date(a_lastMsg.msgTime).getTime()
|
||||
if (bTime !== aTime) {
|
||||
return bTime - aTime
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,7 +419,7 @@ const pullMsg = async (endMsgId = null) => {
|
||||
const res = await msgChatPullMsgService(params)
|
||||
const msgCount = res.data.data.count
|
||||
if (msgCount > 0) {
|
||||
await messageData.preloadResource(sessionId, res.data.data.msgList)
|
||||
await messageData.preloadResource(res.data.data.msgList)
|
||||
messageData.addMsgRecords(sessionId, res.data.data.msgList)
|
||||
messageData.updateMsgIdSort(sessionId)
|
||||
}
|
||||
@@ -1191,7 +1194,6 @@ const onShowRecorder = () => {
|
||||
<el-container v-if="isShowRecorder">
|
||||
<InputRecorder
|
||||
ref="inputRecorderRef"
|
||||
:sessionId="selectedSessionId"
|
||||
@exit="isShowRecorder = false"
|
||||
@saveLocalMsg="handleLocalMsg"
|
||||
@sendMessage="handleSendMessage"
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
import { computed } from 'vue'
|
||||
import { ElImage } from 'element-plus'
|
||||
import { formatFileSize } from '@/js/utils/common'
|
||||
import { useImageStore } from '@/stores'
|
||||
|
||||
const props = defineProps(['url', 'imgId', 'srcList', 'initialIndex', 'fileName', 'size'])
|
||||
const props = defineProps(['sessionId', 'imgId', 'isForMix'])
|
||||
const emits = defineEmits(['load'])
|
||||
|
||||
const imageData = useImageStore()
|
||||
|
||||
const onLoad = (e) => {
|
||||
const img = e.target
|
||||
const maxWidth = 360
|
||||
@@ -24,27 +27,57 @@ const onLoad = (e) => {
|
||||
emits('load') //向父组件暴露load事件
|
||||
}
|
||||
|
||||
const url = computed(() => {
|
||||
return imageData.image[props.imgId]?.thumbUrl
|
||||
})
|
||||
|
||||
const imageInSessionSort = computed(() => {
|
||||
const imageList = 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.isForMix ? '' : imageData.image[props.imgId].fileName
|
||||
})
|
||||
|
||||
const size = computed(() => {
|
||||
return props.isForMix ? '' : imageData.image[props.imgId].size
|
||||
})
|
||||
|
||||
const formatSize = computed(() => {
|
||||
return formatFileSize(props.size)
|
||||
return formatFileSize(size.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="image-msg-wrapper">
|
||||
<el-image
|
||||
:src="props.url"
|
||||
:src="url"
|
||||
:alt="props.imgId"
|
||||
:preview-src-list="props.srcList"
|
||||
:initial-index="props.initialIndex"
|
||||
:preview-src-list="srcList"
|
||||
:initial-index="initialIndex"
|
||||
:infinite="false"
|
||||
:lazy="false"
|
||||
fit="contain"
|
||||
@load="onLoad"
|
||||
>
|
||||
</el-image>
|
||||
<div v-if="props.fileName || props.size > 0" class="info">
|
||||
<span class="name item text-ellipsis" :title="props.fileName">
|
||||
{{ props.fileName || '' }}
|
||||
<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 }}
|
||||
|
||||
@@ -24,7 +24,7 @@ const getQuill = () => {
|
||||
onMounted(async () => {
|
||||
// 给组件增加滚动条样式
|
||||
document.querySelector('.ql-editor').classList.add('my-scrollbar')
|
||||
await imageData.loadImageInfoFromContent(props.sessionId, props.draft)
|
||||
await imageData.loadImageInfoFromContent(props.draft)
|
||||
formatContent(props.draft)
|
||||
getQuill().on('composition-start', () => {
|
||||
// 当用户使用拼音输入法开始输入汉字时,这个事件就会被触发
|
||||
@@ -43,7 +43,7 @@ onBeforeUnmount(async () => {
|
||||
someUploadedFailFn: () => {},
|
||||
allUploadedSuccessFn: () => {}
|
||||
}
|
||||
const contentObj = parseContent(props.sessionId, callbacks)
|
||||
const contentObj = parseContent(callbacks)
|
||||
|
||||
const fn = (content) => {
|
||||
// 草稿若发生变动,则触发存储
|
||||
@@ -72,7 +72,7 @@ onUnmounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const parseContent = (sessionId, callbacks) => {
|
||||
const parseContent = (callbacks) => {
|
||||
const delta = getQuill().getContents()
|
||||
let contentFromLocal = new Array(delta.ops.length).fill('')
|
||||
let contentFromServer = new Array(delta.ops.length).fill('')
|
||||
@@ -114,19 +114,20 @@ const parseContent = (sessionId, callbacks) => {
|
||||
const tempObjectId = new Date().getTime()
|
||||
// 发送的时候设置本地缓存(非服务端数据),用于立即渲染
|
||||
const localSrc = URL.createObjectURL(file)
|
||||
imageData.setLocalImage({
|
||||
imageData.setImage({
|
||||
objectId: tempObjectId,
|
||||
originUrl: localSrc,
|
||||
thumbUrl: localSrc,
|
||||
fileName: file.name,
|
||||
size: file.size
|
||||
size: file.size,
|
||||
createdTime: new Date()
|
||||
})
|
||||
contentFromLocal[index] = `{${tempObjectId}}`
|
||||
|
||||
//上传图片至服务端
|
||||
mtsUploadService({ file: file, storeType: 1 })
|
||||
.then((res) => {
|
||||
imageData.setServerImage(sessionId, res.data.data) // 缓存image数据
|
||||
imageData.setImage(res.data.data) // 缓存image数据
|
||||
uploadSuccessCount++
|
||||
contentFromServer[index] = `{${res.data.data.objectId}}`
|
||||
callbacks.someOneUploadedSuccessFn()
|
||||
@@ -166,7 +167,7 @@ watch(
|
||||
someUploadedFailFn: () => {},
|
||||
allUploadedSuccessFn: () => {}
|
||||
}
|
||||
const contentObj = parseContent(oldSessionId, callbacks)
|
||||
const contentObj = parseContent(callbacks)
|
||||
|
||||
const fn = (content) => {
|
||||
// 草稿若发生变动,则触发存储
|
||||
@@ -205,7 +206,7 @@ const handleEnter = async () => {
|
||||
allUploadedSuccessFn: () => {}
|
||||
}
|
||||
|
||||
const contentObj = parseContent(props.sessionId, callbacks)
|
||||
const contentObj = parseContent(callbacks)
|
||||
|
||||
const content = contentObj.contentFromLocal.join('').trim()
|
||||
if (!content) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { mtsUploadService } from '@/api/mts'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { msgContentType, msgFileUploadStatus } from '@/const/msgConst'
|
||||
|
||||
const props = defineProps(['sessionId'])
|
||||
const emit = defineEmits(['exit', 'sendMessage', 'saveLocalMsg'])
|
||||
|
||||
const audioData = useAudioStore()
|
||||
@@ -151,7 +150,7 @@ const uploadRecord = () => {
|
||||
const duration = Math.floor(recordDuration / 1000)
|
||||
const localSrc = URL.createObjectURL(file)
|
||||
const tempObjectId = new Date().getTime()
|
||||
audioData.setAudio(props.sessionId, {
|
||||
audioData.setAudio({
|
||||
objectId: tempObjectId,
|
||||
duration: duration,
|
||||
url: localSrc,
|
||||
@@ -172,7 +171,7 @@ const uploadRecord = () => {
|
||||
mtsUploadService({ file, storeType: 1, duration: duration })
|
||||
.then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
audioData.setAudio(props.sessionId, res.data.data) // 缓存服务端响应的audio数据
|
||||
audioData.setAudio(res.data.data) // 缓存服务端响应的audio数据
|
||||
msg.uploadStatus = msgFileUploadStatus.UPLOAD_SUCCESS
|
||||
msg.uploadProgress = 100
|
||||
msg.content = JSON.stringify({
|
||||
|
||||
@@ -81,16 +81,17 @@ const setLocalData = (contentType, file) => {
|
||||
const localSrc = URL.createObjectURL(file.raw)
|
||||
switch (contentType) {
|
||||
case msgContentType.IMAGE:
|
||||
imageData.setLocalImage({
|
||||
imageData.setImage({
|
||||
objectId: file.uid,
|
||||
originUrl: localSrc,
|
||||
thumbUrl: localSrc,
|
||||
fileName: file.name,
|
||||
size: file.raw.size
|
||||
size: file.raw.size,
|
||||
createdTime: new Date()
|
||||
})
|
||||
break
|
||||
case msgContentType.AUDIO:
|
||||
audioData.setAudio(props.sessionId, {
|
||||
audioData.setAudio({
|
||||
objectId: file.uid,
|
||||
url: localSrc,
|
||||
fileName: file.name,
|
||||
@@ -98,7 +99,7 @@ const setLocalData = (contentType, file) => {
|
||||
})
|
||||
break
|
||||
case msgContentType.VIDEO:
|
||||
videoData.setVideo(props.sessionId, {
|
||||
videoData.setVideo({
|
||||
objectId: file.uid,
|
||||
url: localSrc,
|
||||
fileName: file.name,
|
||||
@@ -107,7 +108,7 @@ const setLocalData = (contentType, file) => {
|
||||
break
|
||||
case msgContentType.DOCUMENT:
|
||||
default:
|
||||
documentData.setDocument(props.sessionId, {
|
||||
documentData.setDocument({
|
||||
objectId: file.uid,
|
||||
documentType: file.raw.type,
|
||||
url: localSrc,
|
||||
@@ -125,17 +126,17 @@ const setLocalData = (contentType, file) => {
|
||||
const setStoreData = (contentType, data) => {
|
||||
switch (contentType) {
|
||||
case msgContentType.IMAGE:
|
||||
imageData.setServerImage(props.sessionId, data)
|
||||
imageData.setImage(data)
|
||||
break
|
||||
case msgContentType.AUDIO:
|
||||
audioData.setAudio(props.sessionId, data)
|
||||
audioData.setAudio(data)
|
||||
break
|
||||
case msgContentType.VIDEO:
|
||||
videoData.setVideo(props.sessionId, data)
|
||||
videoData.setVideo(data)
|
||||
break
|
||||
case msgContentType.DOCUMENT:
|
||||
default:
|
||||
documentData.setDocument(props.sessionId, data)
|
||||
documentData.setDocument(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,18 +168,13 @@ const renderVideo = (content) => {
|
||||
|
||||
const renderImage = (content, isForMix = false) => {
|
||||
const imgId = content
|
||||
const url = imageData.image[imgId]?.thumbUrl
|
||||
if (url) {
|
||||
const imgIdList = imageData.imageInSession[props.sessionId] || []
|
||||
const imgIdListSorted = imgIdList.includes(imgId) ? imgIdList.sort((a, b) => a - b) : [imgId]
|
||||
const srcList = imgIdListSorted.map((item) => imageData.image[item].originUrl)
|
||||
if (imageData.image[imgId]) {
|
||||
// 只要这里渲染,就收集该session下的所有image,用于preview-src-list
|
||||
imageData.setImageInSession(props.sessionId, imageData.image[imgId])
|
||||
return h(ImageMsgBox, {
|
||||
url,
|
||||
sessionId: props.sessionId,
|
||||
imgId,
|
||||
srcList,
|
||||
initialIndex: imgIdListSorted.indexOf(imgId),
|
||||
fileName: isForMix ? '' : imageData.image[imgId].fileName,
|
||||
size: isForMix ? '' : imageData.image[imgId].size,
|
||||
isForMix,
|
||||
onLoad: () => {
|
||||
emit('loadFinished')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user