diff --git a/package.json b/package.json index d5e3680..5e0ba18 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "protobufjs": "^7.4.0", "uuid": "^10.0.0", "vue": "^3.4.29", + "vue-audio-visual": "^3.0.10", "vue-cropper": "^1.1.1", "vue-router": "^4.3.3" }, diff --git a/src/api/mts.js b/src/api/mts.js index 29c832d..8a63f3e 100644 --- a/src/api/mts.js +++ b/src/api/mts.js @@ -7,3 +7,7 @@ export const mtsUploadService = (obj) => { export const mtsImageService = (obj) => { return request.get('/mts/image', { params: obj }) } + +export const mtsAudioService = (obj) => { + return request.get('/mts/audio', { params: obj }) +} diff --git a/src/assets/svg/pause.svg b/src/assets/svg/pause.svg new file mode 100644 index 0000000..b7359c7 --- /dev/null +++ b/src/assets/svg/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/play.svg b/src/assets/svg/play.svg new file mode 100644 index 0000000..f290141 --- /dev/null +++ b/src/assets/svg/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/stores/audio.js b/src/stores/audio.js new file mode 100644 index 0000000..dc2d563 --- /dev/null +++ b/src/stores/audio.js @@ -0,0 +1,41 @@ +import { mtsAudioService } from '@/api/mts' +import { defineStore } from 'pinia' +import { ref } from 'vue' + +// audio的缓存数据,不持久化存储 +export const audioStore = defineStore('anylink-audio', () => { + /** + * { + * objectId_01: {objectId: objectId_01, url: xxx}, + * objectId_02: {objectId: objectId_02, url: xxx}, + * } + */ + const audio = ref({}) + + /** + * 在同一个session中的audio(id)集合 + */ + const audioInSession = ref({}) + + const setAudio = (sessionId, obj) => { + audio.value[obj.objectId] = obj + if (!audioInSession.value[sessionId]) { + audioInSession.value[sessionId] = [] + } + audioInSession.value[sessionId].push(obj.objectId) + } + + const loadAudio = async (sessionId, objectId) => { + if (!(objectId in audio.value)) { + const res = await mtsAudioService({ objectId: objectId }) + setAudio(sessionId, res.data.data) // 缓存image数据 + } + } + + return { + audio, + audioInSession, + setAudio, + loadAudio + } +}) diff --git a/src/stores/index.js b/src/stores/index.js index e905ddc..f1870ef 100644 --- a/src/stores/index.js +++ b/src/stores/index.js @@ -13,3 +13,4 @@ export * from './search' export * from './userCard' export * from './groupCard' export * from './image' +export * from './audio' diff --git a/src/views/message/MessageLayout.vue b/src/views/message/MessageLayout.vue index d1ac626..52a8ae1 100644 --- a/src/views/message/MessageLayout.vue +++ b/src/views/message/MessageLayout.vue @@ -964,7 +964,7 @@ const onSendImage = ({ objectId }) => { } const onSendAudio = ({ objectId }) => { - console.log('onSendAudio: ', objectId) + handleSendMessage(JSON.stringify({ type: msgContentType.AUDIO, value: `(${objectId})` })) } diff --git a/src/views/message/components/AudioMessage.vue b/src/views/message/components/AudioMessage.vue deleted file mode 100644 index 0405a48..0000000 --- a/src/views/message/components/AudioMessage.vue +++ /dev/null @@ -1,180 +0,0 @@ - - - - - diff --git a/src/views/message/components/AudioMsgBox.vue b/src/views/message/components/AudioMsgBox.vue new file mode 100644 index 0000000..723fe5a --- /dev/null +++ b/src/views/message/components/AudioMsgBox.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/views/message/components/MessageItem.vue b/src/views/message/components/MessageItem.vue index fe52398..020f3cd 100644 --- a/src/views/message/components/MessageItem.vue +++ b/src/views/message/components/MessageItem.vue @@ -3,12 +3,19 @@ import { computed, onMounted, h, createApp, watch, nextTick, reactive } from 'vu import { ElImage } from 'element-plus' import { WarningFilled } from '@element-plus/icons-vue' import { MsgType } from '@/proto/msg' -import { userStore, messageStore, groupStore, groupCardStore, imageStore } from '@/stores' +import { + userStore, + messageStore, + groupStore, + groupCardStore, + imageStore, + audioStore +} from '@/stores' import { messageSysShowTime, showTimeFormat, jsonParseSafe } from '@/js/utils/common' import UserAvatarIcon from '@/components/common/UserAvatarIcon.vue' import { emojis } from '@/js/utils/emojis' import { msgContentType, msgSendStatus } from '@/const/msgConst' -import AudioMessage from '@/views/message/components/AudioMessage.vue' +import AudioMsgBox from '@/views/message/components/AudioMsgBox.vue' const props = defineProps([ 'sessionId', @@ -29,6 +36,7 @@ const messageData = messageStore() const groupData = groupStore() const groupCardData = groupCardStore() const imageData = imageStore() +const audioData = audioStore() onMounted(() => { rendering() @@ -71,7 +79,12 @@ const renderComponent = async (content) => { case msgContentType.TEXT: return renderText(value) case msgContentType.AUDIO: - return renderAudio(value) + if (value.startsWith('(') && value.endsWith(')')) { + await audioData.loadAudio(props.sessionId, value.slice(1, -1)) + return renderAudio(value) + } else { + return h('span', value) + } case msgContentType.IMAGE: if (value.startsWith('{') && value.endsWith('}')) { await imageData.loadImageInfoFromContent(props.sessionId, value) @@ -91,12 +104,6 @@ const renderComponent = async (content) => { } } -const renderAudio = (url) => { - return h(AudioMessage, { - audioUrl: url - }) -} - const renderText = (content) => { return h('span', content) } @@ -196,6 +203,21 @@ const renderImage = (content) => { } } +const renderAudio = (content) => { + const audioId = content.slice(1, -1) + const url = audioData.audio[audioId]?.url + if (url) { + return h(AudioMsgBox, { + audioUrl: import.meta.env.VITE_OSS_CORS_FLAG + url, + onLoad: () => { + emit('loadFinished') + } + }) + } else { + return h('span', content) + } +} + const msg = computed(() => { return reactive({ ...messageData.getMsg(props.sessionId, props.msgId) }) })