mirror of
https://gitee.com/lijingbo-2021/open-anylink-web.git
synced 2025-12-30 11:02:25 +00:00
文件方式上传音频消息重做
This commit is contained in:
1
src/assets/svg/audiofile.svg
Normal file
1
src/assets/svg/audiofile.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742888981247" class="svg-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10532" id="mx_n_1742888981248" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M945.587697 291.972171v653.744416c0 42.592457-35.23398 77.439766-78.306847 77.439766H156.812889C113.740022 1023.156353 78.506042 988.309044 78.506042 945.716587V78.916148C78.506042 36.323691 113.751739 1.476382 156.812889 1.476382h503.141706" fill="#409eff" p-id="10533" data-spm-anchor-id="a313x.search_index.0.i24.20d13a81QCpEmN" class=""></path><path d="M659.954595 1.476382L945.587697 291.983889H691.884291s-25.778103-9.830831-31.929696-39.335042z" fill="#f5f5f5" p-id="10534"></path><path d="M666.153057 358.268766l-266.53387 41.549616a5.143903 5.143903 0 0 0-2.343464 0.632735h-9.502746c-6.456243 0-11.881362 4.757232-11.881362 11.096302v284.379348a73.44416 73.44416 0 0 0-35.316002-8.881729c-39.053826 0-70.632003 29.480776-70.632003 65.945076s31.636763 65.945075 70.632003 65.945075 70.632003-29.480776 70.632003-65.945075c0-2.530941-0.339802-5.389967-0.339802-7.932626a10.05346 10.05346 0 0 0 0.339802-3.163676V510.781399l247.551813-40.893446v160.093739a73.39729 73.39729 0 0 0-35.339436-8.870011c-39.053826 0-70.632003 29.480776-70.632003 65.945075s31.636763 65.945075 70.632003 65.945075 70.632003-29.480776 70.632003-65.945075c0-2.530941-0.339802-5.389967-0.339803-7.920908a10.10033 10.10033 0 0 0 0.339803-3.175394V368.439399c0-5.389967-4.077627-9.830831-9.842549-10.779934a10.70963 10.70963 0 0 0-7.135848-1.26547l-6.11644 0.949103h-0.679605z m0 0" fill="#F5F5F5" p-id="10535"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -16,9 +16,10 @@ export const msgContentType = {
|
||||
MIX: 0, // 组合,包含多种类型
|
||||
TEXT: 1, // 文本
|
||||
IMAGE: 2, // 图片
|
||||
AUDIO: 3, // 音频
|
||||
VIDEO: 4, // 视频
|
||||
EMOJI: 5 //表情
|
||||
RECORDING: 3, // 录音
|
||||
AUDIO: 4, // 音频文件
|
||||
VIDEO: 5, // 视频
|
||||
EMOJI: 6 //表情
|
||||
}
|
||||
|
||||
// 消息发送状态
|
||||
|
||||
@@ -227,3 +227,15 @@ export const base64ToFile = (base64Data, fileName) => {
|
||||
}
|
||||
return new File([u8arr], fileName, { type: mimeType })
|
||||
}
|
||||
|
||||
export const formatFileSize = (size) => {
|
||||
if (!size) {
|
||||
return ''
|
||||
} else if (size < 1024) {
|
||||
return size + ' B'
|
||||
} else if (size < 1024 * 1024) {
|
||||
return (size / 1024).toFixed(2) + ' KB'
|
||||
} else {
|
||||
return (size / (1024 * 1024)).toFixed(2) + ' MB'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ export const audioStore = defineStore('anylink-audio', () => {
|
||||
msgRecords.forEach((item) => {
|
||||
const content = item.content
|
||||
const contentJson = jsonParseSafe(content)
|
||||
if (contentJson && contentJson['type'] === msgContentType.AUDIO) {
|
||||
if (
|
||||
(contentJson && contentJson['type'] === msgContentType.RECORDING) ||
|
||||
(contentJson && contentJson['type'] === msgContentType.AUDIO)
|
||||
) {
|
||||
const objectId = contentJson['value'].slice(1, -1)
|
||||
if (!audio.value[objectId]) {
|
||||
audioIds.add(objectId)
|
||||
|
||||
@@ -968,6 +968,10 @@ const onSendAudio = ({ objectId }) => {
|
||||
handleSendMessage(JSON.stringify({ type: msgContentType.AUDIO, value: `(${objectId})` }))
|
||||
}
|
||||
|
||||
const onSendRecording = ({ objectId }) => {
|
||||
handleSendMessage(JSON.stringify({ type: msgContentType.RECORDING, value: `(${objectId})` }))
|
||||
}
|
||||
|
||||
const isShowRecorder = ref(false)
|
||||
const onShowRecorder = () => {
|
||||
isShowRecorder.value = true
|
||||
@@ -1157,7 +1161,7 @@ const onShowRecorder = () => {
|
||||
<InputRecorder
|
||||
:sessionId="selectedSessionId"
|
||||
@exit="isShowRecorder = false"
|
||||
@sendRecord="onSendAudio"
|
||||
@sendRecording="onSendRecording"
|
||||
></InputRecorder>
|
||||
</el-container>
|
||||
<el-container v-else class="input-box-container">
|
||||
|
||||
62
src/views/message/components/AudioMsgBox.vue
Normal file
62
src/views/message/components/AudioMsgBox.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<script setup>
|
||||
import { onMounted, computed } from 'vue'
|
||||
import AudioFileIcon from '@/assets/svg/audiofile.svg'
|
||||
import { formatFileSize } from '@/js/utils/common'
|
||||
|
||||
const props = defineProps(['url', 'fileName', 'size'])
|
||||
const emits = defineEmits(['load'])
|
||||
|
||||
const formatSize = computed(() => {
|
||||
return formatFileSize(props.size)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
emits('load') //向父组件暴露load事件
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="audio-msg-wrapper">
|
||||
<AudioFileIcon />
|
||||
<div class="main">
|
||||
<span class="file-name text-ellipsis" :title="props.fileName || '未知'">
|
||||
{{ props.fileName || '未知' }}
|
||||
</span>
|
||||
<div class="footer">
|
||||
<div class="size" :title="formatSize">{{ formatSize }}</div>
|
||||
<a :href="props.url" :download="props.fileName">下载</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.audio-msg-wrapper {
|
||||
padding: 4px 8px 4px 8px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
||||
.svg-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 140px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
gap: 8px;
|
||||
|
||||
.file-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { ElImage } from 'element-plus'
|
||||
import { formatFileSize } from '@/js/utils/common'
|
||||
|
||||
const props = defineProps(['url', 'imgId', 'srcList', 'initialIndex', 'fileName', 'size'])
|
||||
const emits = defineEmits(['load'])
|
||||
@@ -28,15 +29,7 @@ const onLoad = (e) => {
|
||||
}
|
||||
|
||||
const formatSize = computed(() => {
|
||||
if (!props.size) {
|
||||
return ''
|
||||
} else if (props.size < 1024) {
|
||||
return props.size + ' B'
|
||||
} else if (props.size < 1024 * 1024) {
|
||||
return (props.size / 1024).toFixed(2) + ' KB'
|
||||
} else {
|
||||
return (props.size / (1024 * 1024)).toFixed(2) + ' MB'
|
||||
}
|
||||
return formatFileSize(props.size)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { el_loading_options } from '@/const/commonConst'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
const props = defineProps(['sessionId'])
|
||||
const emit = defineEmits(['exit', 'sendRecord'])
|
||||
const emit = defineEmits(['exit', 'sendRecording'])
|
||||
|
||||
const audioData = audioStore()
|
||||
const spaceDown = ref(false) // 空格键是否被按下
|
||||
@@ -151,7 +151,7 @@ const uploadRecord = () => {
|
||||
.then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
audioData.setAudio(props.sessionId, res.data.data) // 缓存audio的数据
|
||||
emit('sendRecord', res.data.data)
|
||||
emit('sendRecording', res.data.data)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { emojis } from '@/js/utils/emojis'
|
||||
import { msgContentType, msgSendStatus } from '@/const/msgConst'
|
||||
import RecordingMsgBox from '@/views/message/components/RecordingMsgBox.vue'
|
||||
import ImageMsgBox from '@/views/message/components/ImageMsgBox.vue'
|
||||
import AudioMsgBox from '@/views/message/components/AudioMsgBox.vue'
|
||||
|
||||
const props = defineProps([
|
||||
'sessionId',
|
||||
@@ -78,6 +79,8 @@ const renderComponent = async (content) => {
|
||||
return await renderMix(value)
|
||||
case msgContentType.TEXT:
|
||||
return renderText(value)
|
||||
case msgContentType.RECORDING:
|
||||
return renderRecording(value)
|
||||
case msgContentType.AUDIO:
|
||||
return renderAudio(value)
|
||||
case msgContentType.IMAGE:
|
||||
@@ -162,7 +165,7 @@ const renderImage = (content, ishowInfo = true) => {
|
||||
}
|
||||
}
|
||||
|
||||
const renderAudio = (content) => {
|
||||
const renderRecording = (content) => {
|
||||
const audioId = content.slice(1, -1)
|
||||
const url = audioData.audio[audioId]?.url
|
||||
const duration = audioData.audio[audioId]?.duration
|
||||
@@ -179,6 +182,23 @@ const renderAudio = (content) => {
|
||||
}
|
||||
}
|
||||
|
||||
const renderAudio = (content) => {
|
||||
const audioId = content.slice(1, -1)
|
||||
const url = audioData.audio[audioId]?.url
|
||||
if (url) {
|
||||
return h(AudioMsgBox, {
|
||||
url: import.meta.env.VITE_OSS_CORS_FLAG + url,
|
||||
fileName: audioData.audio[audioId].fileName,
|
||||
size: audioData.audio[audioId].size,
|
||||
onLoad: () => {
|
||||
emit('loadFinished')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return h('span', content)
|
||||
}
|
||||
}
|
||||
|
||||
const msg = computed(() => {
|
||||
return reactive({ ...messageData.getMsg(props.sessionId, props.msgId) })
|
||||
})
|
||||
|
||||
@@ -226,7 +226,9 @@ const showDetailContent = computed(() => {
|
||||
const jsonContent = jsonParseSafe(lastMsg.value.content)
|
||||
if (
|
||||
jsonContent &&
|
||||
(jsonContent['type'] == msgContentType.IMAGE || jsonContent['type'] == msgContentType.AUDIO)
|
||||
(jsonContent['type'] == msgContentType.IMAGE ||
|
||||
jsonContent['type'] == msgContentType.AUDIO ||
|
||||
jsonContent['type'] == msgContentType.RECORDING)
|
||||
) {
|
||||
return jsonContent['value'].replace(/\{\d+\}/g, '{图片}').replace(/\(\d+\)/g, '(音频)')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user