更新组件和API,新增语音转文本功能,优化音频消息组件,调整右键菜单逻辑
This commit is contained in:
parent
419bde4db2
commit
478336c2fe
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -60,6 +60,7 @@ declare module 'vue' {
|
|||||||
NoticeTab: typeof import('./src/components/group/manage/NoticeTab.vue')['default']
|
NoticeTab: typeof import('./src/components/group/manage/NoticeTab.vue')['default']
|
||||||
NotificationApi: typeof import('./src/components/common/NotificationApi.vue')['default']
|
NotificationApi: typeof import('./src/components/common/NotificationApi.vue')['default']
|
||||||
NRadio: typeof import('naive-ui')['NRadio']
|
NRadio: typeof import('naive-ui')['NRadio']
|
||||||
|
NSpin: typeof import('naive-ui')['NSpin']
|
||||||
NVirtualList: typeof import('naive-ui')['NVirtualList']
|
NVirtualList: typeof import('naive-ui')['NVirtualList']
|
||||||
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
|
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
@ -9,7 +9,10 @@ export const ServeGetTalkList = (data = {}) => {
|
|||||||
export const ServeCreateTalkList = (data = {}) => {
|
export const ServeCreateTalkList = (data = {}) => {
|
||||||
return post('/api/v1/talk/create', data)
|
return post('/api/v1/talk/create', data)
|
||||||
}
|
}
|
||||||
|
// 聊天列表创建服务接口
|
||||||
|
export const voiceToText = (data = {}) => {
|
||||||
|
return post('/api/v1/talk/message/voice-to-text', data)
|
||||||
|
}
|
||||||
// 删除聊天列表服务接口
|
// 删除聊天列表服务接口
|
||||||
export const ServeDeleteTalkList = (data = {}) => {
|
export const ServeDeleteTalkList = (data = {}) => {
|
||||||
return post('/api/v1/talk/delete', data)
|
return post('/api/v1/talk/delete', data)
|
||||||
|
@ -3,7 +3,7 @@ import { ref, reactive } from 'vue'
|
|||||||
import { PlayOne, PauseOne } from '@icon-park/vue-next'
|
import { PlayOne, PauseOne } from '@icon-park/vue-next'
|
||||||
import { ITalkRecordExtraAudio, ITalkRecord } from '@/types/chat'
|
import { ITalkRecordExtraAudio, ITalkRecord } from '@/types/chat'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
extra: ITalkRecordExtraAudio
|
extra: ITalkRecordExtraAudio
|
||||||
data: ITalkRecord
|
data: ITalkRecord
|
||||||
maxWidth?: Boolean
|
maxWidth?: Boolean
|
||||||
@ -18,7 +18,8 @@ const state = reactive({
|
|||||||
progress: 0,
|
progress: 0,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
loading: true
|
loading: true,
|
||||||
|
showText: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const onPlay = () => {
|
const onPlay = () => {
|
||||||
@ -40,6 +41,12 @@ const onCanplay = () => {
|
|||||||
state.duration = audioRef.value.duration
|
state.duration = audioRef.value.duration
|
||||||
durationDesc.value = formatTime(parseInt(audioRef.value.duration))
|
durationDesc.value = formatTime(parseInt(audioRef.value.duration))
|
||||||
state.loading = false
|
state.loading = false
|
||||||
|
|
||||||
|
if (props.data.is_convert_text === 1 && props.data.extra.content) {
|
||||||
|
setTimeout(() => {
|
||||||
|
state.showText = true
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onError = (e: any) => {
|
const onError = (e: any) => {
|
||||||
@ -61,17 +68,12 @@ const formatTime = (value: number = 0) => {
|
|||||||
return '-'
|
return '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
const minutes = Math.floor(value / 60)
|
return `${Math.floor(value)}"`
|
||||||
let seconds = value
|
|
||||||
if (minutes > 0) {
|
|
||||||
seconds = Math.floor(value - minutes * 60)
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${minutes}'${seconds}"`
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="im-message-audio">
|
<div class="pointer w-200px bg-#f5f5f5 rounded-10px px-11px">
|
||||||
|
<div class="im-message-audio h-44px">
|
||||||
<audio
|
<audio
|
||||||
ref="audioRef"
|
ref="audioRef"
|
||||||
preload="auto"
|
preload="auto"
|
||||||
@ -98,20 +100,27 @@ const formatTime = (value: number = 0) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="time">{{ durationDesc }}</div>
|
<div class="time">{{ durationDesc }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<transition name="expand">
|
||||||
|
<div class="text-container py-12px border-t-2px border-t-solid border-t-#E0E0E4" v-if="data.is_convert_text===1">
|
||||||
|
<div class="flex justify-center items-center" v-if="data.is_convert_text===1&&!data.extra.content">
|
||||||
|
<n-spin :stroke-width="3" size="small" />
|
||||||
|
</div>
|
||||||
|
<transition name="fade">
|
||||||
|
<div class="text-content" v-if="data.extra.content">{{ data.extra.content }}</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.im-message-audio {
|
.im-message-audio {
|
||||||
--audio-bg-color: #f5f5f5;
|
--audio-bg-color: #f5f5f5;
|
||||||
--audio-btn-bg-color: #ffffff;
|
--audio-btn-bg-color: #ffffff;
|
||||||
|
|
||||||
width: 200px;
|
|
||||||
height: 45px;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--audio-bg-color);
|
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -132,6 +141,7 @@ const formatTime = (value: number = 0) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +240,7 @@ const formatTime = (value: number = 0) => {
|
|||||||
height: 70%;
|
height: 70%;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
background-color: #9b9595;
|
background-color: #9b9595;
|
||||||
|
transition: left 0.1s linear;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +252,40 @@ const formatTime = (value: number = 0) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expand-enter-active,
|
||||||
|
.expand-leave-active {
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-enter-from,
|
||||||
|
.expand-leave-to {
|
||||||
|
max-height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-top-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-content {
|
||||||
|
line-height: 1.5;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
html[theme-mode='dark'] {
|
html[theme-mode='dark'] {
|
||||||
.im-message-audio {
|
.im-message-audio {
|
||||||
--audio-bg-color: #2c2c32;
|
--audio-bg-color: #2c2c32;
|
||||||
|
@ -47,7 +47,10 @@ export interface ITalkRecord {
|
|||||||
extra: any
|
extra: any
|
||||||
isCheck: boolean
|
isCheck: boolean
|
||||||
send_status: number
|
send_status: number
|
||||||
float: string
|
float: string,
|
||||||
|
is_convert_text?:number//语音记录的 是否是在展示转文本状态 1:是 0:否,
|
||||||
|
erp_user_id:number
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITalkRecordExtraText {
|
export interface ITalkRecordExtraText {
|
||||||
|
@ -16,6 +16,7 @@ import { useInject, useTalkRecord, useUtil } from '@/hooks'
|
|||||||
import { ExclamationCircleFilled } from '@ant-design/icons-vue';
|
import { ExclamationCircleFilled } from '@ant-design/icons-vue';
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import RevokeMessage from '@/components/talk/message/RevokeMessage.vue'
|
import RevokeMessage from '@/components/talk/message/RevokeMessage.vue'
|
||||||
|
import { voiceToText } from '@/api/chat.js'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
uid: {
|
uid: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -45,16 +46,8 @@ const userStore = useUserStore()
|
|||||||
// const showUserInfoModal = (uid: number) => {
|
// const showUserInfoModal = (uid: number) => {
|
||||||
// userStore.getUserInfo(uid)
|
// userStore.getUserInfo(uid)
|
||||||
// }
|
// }
|
||||||
watch(() => records, (newValue, oldValue) => {
|
|
||||||
console.log(newValue);
|
|
||||||
|
|
||||||
}, { deep: true, immediate: true })
|
|
||||||
|
|
||||||
// 置底按钮
|
// 置底按钮
|
||||||
const skipBottom = ref(false)
|
const skipBottom = ref(false)
|
||||||
setTimeout(() => {
|
|
||||||
console.log(records.value, 'records.value');
|
|
||||||
}, 1000)
|
|
||||||
// 是否显示消息时间
|
// 是否显示消息时间
|
||||||
const isShowTalkTime = (index: number, datetime: string) => {
|
const isShowTalkTime = (index: number, datetime: string) => {
|
||||||
if (datetime == undefined) {
|
if (datetime == undefined) {
|
||||||
@ -243,6 +236,17 @@ const onContextMenu = (e: any, item: ITalkRecord) => {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onConvertText =async (data: ITalkRecord) => {
|
||||||
|
console.log('data',data)
|
||||||
|
data.is_convert_text = 1
|
||||||
|
const res = await voiceToText({msgId:data.msg_id,voiceUrl:data.extra.url})
|
||||||
|
if(res.code == 200){
|
||||||
|
data.extra.content = res.data.convText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onloseConvertText=(data: ITalkRecord)=>{
|
||||||
|
data.is_convert_text = 0
|
||||||
|
}
|
||||||
const evnets = {
|
const evnets = {
|
||||||
copy: onCopyText,
|
copy: onCopyText,
|
||||||
revoke: onRevokeTalk,
|
revoke: onRevokeTalk,
|
||||||
@ -250,7 +254,9 @@ const evnets = {
|
|||||||
multiSelect: onMultiSelect,
|
multiSelect: onMultiSelect,
|
||||||
download: onDownloadFile,
|
download: onDownloadFile,
|
||||||
quote: onQuoteMessage,
|
quote: onQuoteMessage,
|
||||||
collect: onCollectImage
|
collect: onCollectImage,
|
||||||
|
convertText: onConvertText,
|
||||||
|
closeConvertText:onloseConvertText
|
||||||
}
|
}
|
||||||
|
|
||||||
// 会话列表右键菜单回调事件
|
// 会话列表右键菜单回调事件
|
||||||
|
@ -30,9 +30,17 @@ export function useMenu() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const showDropdownMenu = (e: any, uid: number, item: any) => {
|
const showDropdownMenu = (e: any, uid: number, item: any) => {
|
||||||
dropdown.item = Object.assign({}, item)
|
// dropdown.item = Object.assign({}, item)
|
||||||
|
dropdown.item = item
|
||||||
dropdown.options = []
|
dropdown.options = []
|
||||||
|
if ([4].includes(item.msg_type)) {
|
||||||
|
if(item.is_convert_text === 1){
|
||||||
|
dropdown.options.push({ label: '关闭转文字', key: 'closeConvertText' })
|
||||||
|
}else{
|
||||||
|
dropdown.options.push({ label: '转文字', key: 'convertText' })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if ([1, 3].includes(item.msg_type)) {
|
if ([1, 3].includes(item.msg_type)) {
|
||||||
dropdown.options.push({ label: '复制', key: 'copy' })
|
dropdown.options.push({ label: '复制', key: 'copy' })
|
||||||
}
|
}
|
||||||
@ -54,6 +62,7 @@ export function useMenu() {
|
|||||||
dropdown.options.push({ label: '收藏', key: 'collect' })
|
dropdown.options.push({ label: '收藏', key: 'collect' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dropdown.x = e.clientX
|
dropdown.x = e.clientX
|
||||||
dropdown.y = e.clientY
|
dropdown.y = e.clientY
|
||||||
dropdown.show = true
|
dropdown.show = true
|
||||||
|
Loading…
Reference in New Issue
Block a user