| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import { computed, ref } from 'vue' |
| | | |
| | | import { IconifyIcon as Icon } from '#/packages/icons/src' |
| | | |
| | | import { Modal } from 'ant-design-vue' |
| | | |
| | | import { UserAvatar } from '#/views/im/home/components/user' |
| | | import { useVoicePlayer } from '#/views/im/home/composables/useVoicePlayer' |
| | | import { type MergeMessage, parseMessage } from '#/views/im/utils/message' |
| | | import { formatMergeItemTime } from '#/views/im/utils/time' |
| | | |
| | | import { MessageBubble } from '..' |
| | | |
| | | defineOptions({ name: 'ImMessageMergeDetailDialog' }) |
| | | |
| | | const voicePlayer = useVoicePlayer() |
| | | const visible = ref(false) |
| | | |
| | | const stack = ref<MergeMessage[]>([]) // åµå¥å±çº§æ ï¼å parsed payload é¿å
åå±é parse |
| | | |
| | | defineExpose({ |
| | | /** æå¼è¯¦æ
å¼¹çªï¼ä¼ å
¥é¡¶å±åå¹¶æ¶æ¯ content */ |
| | | open(content: string) { |
| | | const payload = parseMessage<MergeMessage>(content) |
| | | stack.value = payload ? [payload] : [] |
| | | visible.value = true |
| | | } |
| | | }) |
| | | |
| | | /** å½åå± payload */ |
| | | const currentPayload = computed<MergeMessage | null>( |
| | | () => stack.value[stack.value.length - 1] ?? null |
| | | ) |
| | | |
| | | /** åµå¥åå¹¶æ°æ³¡ç¹å»ï¼è§£æ content ååæ è¿å
¥ä¸ä¸å± */ |
| | | function handleNestedOpen(content: string) { |
| | | const payload = parseMessage<MergeMessage>(content) |
| | | if (payload) { |
| | | stack.value.push(payload) |
| | | } |
| | | } |
| | | |
| | | /** é¡¶é¨è¿åç®å¤´ç¹å»ï¼å¼¹åºæ é¡¶åå°ä¸ä¸å± */ |
| | | function handleBack() { |
| | | if (stack.value.length > 1) { |
| | | stack.value.pop() |
| | | } |
| | | } |
| | | |
| | | /** å¼¹çªå
³éï¼æ¸
æ + åè¯é³ï¼ä¸æ¬¡æå¼ä»é¡¶å±éæ°å¼å§ */ |
| | | function handleClose() { |
| | | stack.value = [] |
| | | voicePlayer.stop() |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal |
| | | v-model:open="visible" |
| | | width="560px" |
| | | :footer="null" |
| | | :mask-closable="false" |
| | | class="im-merge-detail-dialog" |
| | | :closable="true" |
| | | @close="handleClose" |
| | | > |
| | | <template #header> |
| | | <div class="flex items-center gap-2"> |
| | | <Icon |
| | | v-if="stack.length > 1" |
| | | icon="ant-design:left-outlined" |
| | | class="cursor-pointer text-[var(--ant-color-text-secondary)] hover:text-[var(--ant-color-text)]" |
| | | @click="handleBack" |
| | | /> |
| | | <span class="text-base font-medium truncate">{{ currentPayload?.title || 'è天记å½' }}</span> |
| | | </div> |
| | | </template> |
| | | |
| | | <div v-if="currentPayload" class="flex flex-col h-[480px]"> |
| | | <div |
| | | class="px-4 py-2 text-12px text-[var(--ant-color-text-secondary)] border-b border-b-solid border-[var(--ant-color-border-secondary)]" |
| | | > |
| | | 以䏿¯ {{ currentPayload.messages.length }} æ¡æ¶æ¯ |
| | | </div> |
| | | <!-- overflow-y-autoï¼åå¹¶æ¶æ¯å¤æ¶å¨å®é«å¼¹çªå
坿»å¨ï¼å¯¹é½ Vue3 ç el-scrollbar --> |
| | | <div class="flex-1 overflow-y-auto"> |
| | | <div |
| | | v-for="(item, idx) in currentPayload.messages" |
| | | :key="idx" |
| | | class="flex gap-3 items-start px-4 py-3 border-b border-b-solid border-[var(--ant-color-border-secondary)]" |
| | | > |
| | | <UserAvatar |
| | | :url="item.senderAvatar" |
| | | :name="item.senderNickname" |
| | | :size="36" |
| | | :clickable="false" |
| | | /> |
| | | <div class="flex-1 min-w-0"> |
| | | <div class="flex gap-2 items-baseline"> |
| | | <span class="text-13px font-medium text-[var(--ant-color-text)] truncate"> |
| | | {{ item.senderNickname }} |
| | | </span> |
| | | <span class="text-12px text-[var(--ant-color-text-secondary)] flex-shrink-0"> |
| | | {{ formatMergeItemTime(item.sendTime) }} |
| | | </span> |
| | | </div> |
| | | <!-- å¤ç¨ä¸»èå¤©æ°æ³¡æ¸²æï¼MERGE åµå¥ç¹å» push å½åå± --> |
| | | <div class="mt-1.5"> |
| | | <MessageBubble |
| | | :type="item.type" |
| | | :content="item.content" |
| | | @open-merge="handleNestedOpen($event)" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </Modal> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | /* :deep ç©¿é el-dialog å
é¨ bodyï¼å»æé»è®¤å
è¾¹è·ï¼è®©æ»å¨åºè´´è¾¹ */ |
| | | .im-merge-detail-dialog :deep(.el-dialog__body) { |
| | | padding: 0; |
| | | } |
| | | </style> |