110 lines
3.4 KiB
Vue
110 lines
3.4 KiB
Vue
<template>
|
|
<div v-if="showFriendlyCustom" class="chat-uikit-custom-msg">
|
|
<span v-if="friendlyCustom!.tag" class="chat-uikit-custom-msg__tag">{{ friendlyCustom!.tag }}</span>
|
|
<div class="chat-uikit-custom-msg__main">{{ friendlyCustom!.main }}</div>
|
|
<div v-if="friendlyCustom!.sub" class="chat-uikit-custom-msg__sub">{{ friendlyCustom!.sub }}</div>
|
|
</div>
|
|
<div v-else-if="isCustomType && customDescription" class="chat-uikit-custom-msg chat-uikit-custom-msg--plain">
|
|
<div class="chat-uikit-custom-msg__main">{{ customDescription }}</div>
|
|
</div>
|
|
<div v-else-if="isCustomType" class="chat-uikit-custom-msg chat-uikit-custom-msg--plain">
|
|
<div class="chat-uikit-custom-msg__main">系统消息</div>
|
|
<div v-if="customDataPreview" class="chat-uikit-custom-msg__sub">{{ customDataPreview }}</div>
|
|
</div>
|
|
<Message v-else v-bind="attrs" :message="message" />
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, useAttrs } from 'vue'
|
|
import { Message, MessageType } from '@tencentcloud/chat-uikit-vue3'
|
|
import type { MessageModel } from '@tencentcloud/chat-uikit-vue3'
|
|
import { parseImBusinessPayload } from '@/utils/im-business-message-parse'
|
|
|
|
defineOptions({ inheritAttrs: false })
|
|
|
|
const props = defineProps<{
|
|
message: MessageModel
|
|
}>()
|
|
|
|
const attrs = useAttrs()
|
|
|
|
function payloadDataString(payload: unknown): string | null {
|
|
if (!payload || typeof payload !== 'object') return null
|
|
const p = payload as Record<string, unknown>
|
|
const d = p.data
|
|
if (typeof d === 'string') return d
|
|
if (d && typeof d === 'object') return JSON.stringify(d)
|
|
const ext = p.extension
|
|
if (typeof ext === 'string' && ext.trim().startsWith('{')) return ext
|
|
return null
|
|
}
|
|
|
|
const isCustomType = computed(() => {
|
|
const t = props.message?.type as unknown
|
|
if (t === MessageType.CUSTOM) return true
|
|
if (typeof t === 'string' && /custom/i.test(t)) return true
|
|
return false
|
|
})
|
|
|
|
const friendlyCustom = computed(() => {
|
|
if (!isCustomType.value) return null
|
|
const raw = payloadDataString(props.message.payload)?.trim()
|
|
if (!raw) return null
|
|
return parseImBusinessPayload(raw)
|
|
})
|
|
|
|
const showFriendlyCustom = computed(() => isCustomType.value && !!friendlyCustom.value)
|
|
|
|
const customDescription = computed(() => {
|
|
const p = props.message.payload as Record<string, unknown> | undefined
|
|
const d = p?.description
|
|
return typeof d === 'string' && d.trim() ? d.trim() : ''
|
|
})
|
|
|
|
/** 无法识别结构时短预览,避免空白 */
|
|
const customDataPreview = computed(() => {
|
|
const raw = payloadDataString(props.message.payload)?.trim()
|
|
if (!raw || raw.length < 2) return ''
|
|
if (raw.length <= 120) return raw
|
|
return `${raw.slice(0, 117)}…`
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.chat-uikit-custom-msg {
|
|
max-width: 85%;
|
|
padding: 8px 12px;
|
|
border-radius: 8px;
|
|
background: var(--el-fill-color-light, #f4f4f5);
|
|
color: var(--el-text-color-primary, #303133);
|
|
font-size: 13px;
|
|
line-height: 1.45;
|
|
border: 1px solid var(--el-border-color-lighter, #ebeef5);
|
|
}
|
|
|
|
.chat-uikit-custom-msg--plain {
|
|
opacity: 0.95;
|
|
}
|
|
|
|
.chat-uikit-custom-msg__tag {
|
|
display: inline-block;
|
|
font-size: 11px;
|
|
padding: 0 6px;
|
|
border-radius: 4px;
|
|
background: var(--el-color-info-light-9, #f4f4f5);
|
|
color: var(--el-color-info, #909399);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.chat-uikit-custom-msg__main {
|
|
font-weight: 500;
|
|
}
|
|
|
|
.chat-uikit-custom-msg__sub {
|
|
margin-top: 4px;
|
|
font-size: 12px;
|
|
color: var(--el-text-color-secondary, #909399);
|
|
word-break: break-all;
|
|
}
|
|
</style>
|