<script lang="ts" setup> import { ref, onMounted } from 'vue' import Loading from '@/components/base/Loading.vue' import { ServeGetForwardRecords } from '@/api/chat' import { MessageComponents } from '@/constant/message' import { ITalkRecord } from '@/types/chat' import { useInject } from '@/hooks' import customModal from '@/components/common/customModal.vue' import { voiceToText } from '@/api/chat.js' const props = defineProps({ msgId: { type: String, required: true } }) const isShow=defineModel<boolean>('show') const { showUserInfoModal } = useInject() const items = ref<ITalkRecord[]>([]) const title = ref('会话记录') const onMaskClick = () => { isShow.value=false } const onLoadData = () => { ServeGetForwardRecords({ msg_id: props.msgId }).then((res) => { if (res.code == 200) { items.value = res.data.items || [] // title.value = `会话记录(${items.value.length})` } }) } const dropdown=ref({ show:false, x:'', y:'', options:[] as any, item:{} as ITalkRecord, }) const onConvertText =async (data: ITalkRecord) => { 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 = { convertText: onConvertText, closeConvertText:onloseConvertText } const onContextMenuHandle=(key:string)=>{ evnets[key] && evnets[key](dropdown.value.item) closeDropdownMenu() } const closeDropdownMenu=()=>{ dropdown.value.show=false } onMounted(() => { onLoadData() }) const onContextMenu = (e:any,item: ITalkRecord) => { dropdown.value.show=true dropdown.value.x=e.clientX dropdown.value.y=e.clientY if(item.is_convert_text === 1){ dropdown.value.options=[{ label: '关闭转文字', key: 'closeConvertText' }] }else{ dropdown.value.options=[{ label: '转文字', key: 'convertText' }] } dropdown.value.item=item } </script> <template> <customModal :closable="false" customCloseBtn v-model:show="isShow" :title="title" style="width: 997px;background-color: #F9F9FD;" :on-after-leave="onMaskClick"> <template #content> <div class="main-box bg-#fff me-scrollbar me-scrollbar-thumb"> <Loading v-if="items.length === 0" /> <div v-for="item in items" :key="item.msg_id" class="message-item"> <div class="left-box pointer" @click="showUserInfoModal(item.user_id)"> <im-avatar :src="item.avatar" :size="38" :username="item.nickname" /> </div> <div class="right-box"> <div class="msg-header"> <span class="name">{{ item.nickname }}</span> <span class="time"> {{ item.created_at }}</span> </div> <component @contextmenu.prevent="onContextMenu($event,item)" :is="MessageComponents[item.msg_type] || 'unknown-message'" :extra="item.extra" :data="item" /> </div> </div> </div> <!-- 右键菜单 --> <n-dropdown :show="dropdown.show" :x="dropdown.x" :y="dropdown.y" style="width: 142px;" :options="dropdown.options" @select="onContextMenuHandle" @clickoutside="closeDropdownMenu" /> </template> </customModal> <!-- <n-modal v-model:show="isShow" preset="card" :title="title" style="max-width: 500px" class="modal-radius" :on-after-leave="onMaskClick" :segmented="{ content: true }" :header-style="{ padding: '20px 15px' }" :content-style="{ padding: 0 }" > <div class="main-box me-scrollbar me-scrollbar-thumb"> <Loading v-if="items.length === 0" /> <div v-for="item in items" :key="item.msg_id" class="message-item"> <div class="left-box pointer" @click="showUserInfoModal(item.user_id)"> <im-avatar :src="item.avatar" :size="30" :username="item.nickname" /> </div> <div class="right-box"> <div class="msg-header"> <span class="name">{{ item.nickname }}</span> <span class="time"> {{ item.created_at }}</span> </div> <component :is="MessageComponents[item.msg_type] || 'unknown-message'" :extra="item.extra" :data="item" /> </div> </div> </div> </n-modal> --> </template> <style lang="less" scoped> .main-box { height: 600px; width: 100%; overflow-y: auto; } .message-item { min-height: 38px; display: flex; margin-bottom: 10px; padding: 24px 42px; .im-message-text{ background-color: #fff; } .left-box { width: 38px; display: flex; user-select: none; padding-top: 8px; } .right-box { width: 100%; overflow-x: auto; padding: 0px 5px 15px 5px; box-sizing: border-box; height: fit-content; .msg-header { height: 30px; line-height: 30px; font-size: 12px; position: relative; user-select: none; display: flex; justify-content: space-between; } } } </style>