9.19自定义消息,聊天相关页面

This commit is contained in:
zoujiandong
2025-09-19 17:37:19 +08:00
parent b884a8f6fc
commit ae08b222af
22 changed files with 4543 additions and 70 deletions
+234
View File
@@ -0,0 +1,234 @@
<template>
<div class="msg-custom" :style="{ fontSize: (fontSize || 16) + 'px' }">
<view
class="customCell cloumn"
v-if="JSON.parse(msg.attachment.raw).gdxz_ext_data == '[肝胆商城]'"
@click="goToDetail(JSON.parse(msg.attachment.raw).gdxz_url)"
>
<view class="title">{{ JSON.parse(msg.attachment.raw).gdxz_title }}</view>
<view class="row">
<view class="left"> 肝胆相照®肝胆病在线公共服务平台 </view>
<view class="right">
<image
src="http://doc.igandan.com/app/html/img/2016/20160714132557.png"
mode="widthFix"
></image>
</view>
</view>
</view>
<view
class="customCell cloumn"
v-else-if="JSON.parse(msg.attachment.raw).gdxz_ext_data == '[公益咨询]'"
@click="goDetail(JSON.parse(msg.attachment.raw).gdxz_id)"
>
<view class="title">{{ JSON.parse(msg.attachment.raw).gdxz_title }}</view>
<view class="row">
<view class="left"> 点击查看问题详情 </view>
<view class="right">
<image
src="http://doc.igandan.com/app/html/img/2016/20160714132557.png"
mode="widthFix"
></image>
</view>
</view>
</view>
<view
class="customCell cloumn"
v-else-if="JSON.parse(msg.attachment.raw).gdxz_ext_data == '[门诊公告]'"
@click="goToDetail(JSON.parse(msg.attachment.raw).gdxz_url)"
>
<view class="title">{{ JSON.parse(msg.attachment.raw).gdxz_title }}</view>
<view class="row">
<view class="left"> 肝胆相照®肝胆病在线公共服务平台 </view>
<view class="right">
<image
src="http://doc.igandan.com/app/html/img/2016/20160714132557.png"
mode="widthFix"
></image>
</view>
</view>
</view>
<view
class="customCell cloumn"
v-else-if="
JSON.parse(msg.attachment.raw).gdxz_ext_data == '[图文科普]' ||
JSON.parse(msg.attachment.raw).gdxz_ext_data == '[视频科普]'
"
@click="goToDetail(JSON.parse(msg.attachment.raw).gdxz_url)"
>
<view class="title">{{ JSON.parse(msg.attachment.raw).gdxz_title }}</view>
<view class="row">
<view class="left">
{{ JSON.parse(msg.attachment.raw).gdxz_content }}
</view>
<view class="right">
<image
src="http://doc.igandan.com/app/html/img/2016/20160714132557.png"
mode="widthFix"
></image>
</view>
</view>
</view>
<view
class="customCell cloumn"
v-else-if="JSON.parse(msg.attachment.raw).gdxz_ext_data == '[互联网医院]'"
@click="goToMiniProgram"
>
<view class="title">肝胆相照互联网医院</view>
<view class="row">
<view class="left">
{{ JSON.parse(msg.attachment.raw).gdxz_content }}
</view>
<view class="right">
<image
src="http://doc.igandan.com/app/html/img/2016/20160714132557.png"
mode="widthFix"
></image>
</view>
</view>
</view>
</div>
</template>
<script lang="ts" setup>
/**文本消息组件 */
import Icon from "@/components/Icon.vue";
// @ts-ignore
import UniLink from "@/components/uni-components/uni-link/components/uni-link/uni-link.vue";
import { parseText } from "@/utils/im/parseText";
import { EMOJI_ICON_MAP_CONFIG } from "@/utils/im/emoji";
import { V2NIMMessageForUI } from "@xkit-yx/im-store-v2/dist/types/types";
import { t } from "@/utils/im/i18n";
import { isHarmonyOs } from "@/utils/im/index";
import navTo from "@/utils/navTo";
const props = withDefaults(
defineProps<{
msg: V2NIMMessageForUI;
fontSize?: number;
}>(),
{}
);
const goToDetail = (url: string) => {
navTo({
url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}`,
});
};
const goDetail = (id: string) => {
navTo({
url: `/pages_app/consultDetail/consultDetail?uuid=${id}`,
});
};
// 跳转到微信小程序
const goToMiniProgram = () => {
// 检查是否在App端
// #ifdef APP-PLUS
// App端跳转小程序的逻辑
plus.share.getServices((res) => {
let sweixin = null;
for (let i in res) {
if (res[i].id == "weixin") {
sweixin = res[i];
}
}
//唤醒微信小程序
if (sweixin) {
uni.hideLoading();
sweixin.launchMiniProgram({
id: "wxc83296720404aa7b", // 小程序的原始ID,微信公众平台设置里有
type: 0, //小程序版本 0-正式版; 1-测试版; 2-体验版。
path: "Pages/index/index", //小程序的页面,用传的参数在小程序接值判断跳转指定页面
});
}
});
// #endif
// #ifdef MP-WEIXIN
// 微信小程序端跳转其他小程序
uni.navigateToMiniProgram({
appId: "wxc83296720404aa7b",
path: "Pages/index/index",
extraData: {
// 可以传递额外数据给小程序
},
envVersion: "release",
success: (res) => {
console.log("跳转小程序成功", res);
},
fail: (err) => {
console.log("跳转小程序失败", err);
uni.showToast({
title: "跳转失败",
icon: "none",
});
},
});
// #endif
};
/**解析文本 */
const textArr = parseText(props.msg?.text || "", props.msg?.serverExtension);
/**unilink 不支持鸿蒙 故提示在浏览器打开链接 */
const openInBrowser = (url: string) => {
uni.setClipboardData({
data: url,
showToast: false,
success: () => {
uni.showToast({
title: t("openUrlText"),
icon: "none",
});
},
});
};
</script>
<style lang="scss" scoped>
.msg-custom {
color: #333;
display: flex;
text-align: left;
overflow-y: auto;
word-break: break-all;
word-wrap: break-word;
white-space: break-spaces;
}
.customCell {
display: flex;
}
.customCell.cloumn {
flex-direction: column;
}
.customCell .title {
font-size: 30rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* 注意:这不是标准的CSS属性 */
-webkit-box-orient: vertical;
}
.customCell .row {
margin-top: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
font-size: 26rpx;
color: #999;
margin-right: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* 注意:这不是标准的CSS属性 */
-webkit-box-orient: vertical;
}
.right image {
width: 100rpx;
height: auto;
}
</style>
+298 -18
View File
@@ -78,9 +78,9 @@
<div class="msg-input-button">
<Icon @tap="handleSendMoreVisible" type="send-more" :size="20" />
</div>
<div class="msg-input-button">
<!-- <div class="msg-input-button">
<Icon @tap="handleSetting" type="icon-shezhi" :size="20" />
</div>
</div> -->
</div>
<div v-if="inputVisible" class="msg-input">
<!-- 当从表情面板切换到文字输入时,直接唤起键盘,会导致input框滚动消失,故此处需要用EmojiInput兼容下,保证先隐藏表情面板,再弹出键盘 -->
@@ -157,8 +157,54 @@
</div>
<div class="icon-text">{{ t('albumText') }}</div>
</div>
<div class="send-more-panel-item-wrapper">
<div
class="send-more-panel-item"
@tap="(event: any) => handleCustom('reply', event)"
>
<image :src="quickImg" mode="widthFix"></image>
</div>
<div class="icon-text">快捷回复</div>
</div>
<div class="send-more-panel-item-wrapper">
<div
class="send-more-panel-item"
@tap="(event: any) => handleCustom('hj', event)"
>
<image :src="quickImg" mode="widthFix"></image>
</div>
<div class="icon-text">患教</div>
</div>
<div class="send-more-panel-item-wrapper">
<div
class="send-more-panel-item"
@tap="(event: any) => handleCustom('outpatient', event)"
>
<image :src="chuzhenImg" mode="widthFix"></image>
</div>
<div class="icon-text">出/停诊公告</div>
</div>
<div class="send-more-panel-item-wrapper">
<div
class="send-more-panel-item"
@tap="(event: any) => handleCustom('mall', event)"
>
<image :src="mallImg" mode="widthFix"></image>
</div>
<div class="icon-text">商城</div>
</div>
<!-- <div class="send-more-panel-item-wrapper">
<div
class="send-more-panel-item"
@tap="(event: any) => handleCustom('hospital', event)"
>
<image :src="hospitalImg" mode="widthFix"></image>
</div>
<div class="icon-text">互联网医院</div>
</div> -->
<!-- 音频呼叫 -->
<div
<!-- <div
class="send-more-panel-item-wrapper"
v-if="
isAndroidOrIosApp &&
@@ -170,10 +216,10 @@
<Icon type="icon-audio-call" :size="30"></Icon>
</div>
<div class="icon-text">{{ t('voiceCallText') }}</div>
</div>
</div> -->
<!-- 视频呼叫 -->
<div
<!-- <div
class="send-more-panel-item-wrapper"
v-if="
isAndroidOrIosApp &&
@@ -185,8 +231,8 @@
<Icon type="icon-video-call" :size="30"></Icon>
</div>
<div class="icon-text">{{ t('videoCallText') }}</div>
</div>
<div
</div> -->
<!-- <div
v-if="isWeb"
class="send-more-panel-item-wrapper"
@tap="handleSendFileMsg"
@@ -195,7 +241,7 @@
<Icon type="icon-file" :size="30"></Icon>
</div>
<div class="icon-text">{{ t('fileText') }}</div>
</div>
</div> -->
</div>
</div>
<!-- @消息相关 popup -->
@@ -208,12 +254,38 @@
>
<MentionMemberList :team-id="to"></MentionMemberList>
</UniPopup>
<!-- 复制自 groupSend 的遮罩与弹窗 -->
<view v-if="showModal" class="mask" @tap="closeModal"></view>
<view v-if="showModal" class="center-modal">
<view class="modal-title">温馨提示</view>
<view class="modal-divider"></view>
<view class="modal-item" @tap="onSelectSince('article')">
<text>图文科普</text>
</view>
<view class="modal-divider"></view>
<view class="modal-item" @tap="onSelectSince('video')">
<text>视频科普</text>
</view>
</view>
<!-- 商城弹窗 -->
<view v-if="showMallModal" class="mask" @tap="closeMallModal"></view>
<view v-if="showMallModal" class="center-modal">
<view class="modal-title">温馨提示</view>
<view class="modal-divider"></view>
<view class="modal-item" @tap="sendMallMsg">
<text>纽娃复合营养素固体饮料</text>
</view>
<view class="modal-divider"></view>
<view class="modal-item" >
<text>更多商品正在准备中</text>
</view>
</view>
</div>
</template>
<script lang="ts" setup>
/** 消息页面输入框组件 */
import docUrl from '@/utils/docUrl'
import Face from './face.vue'
import VoicePanel from './voice-panel.vue'
import Icon from '@/components/Icon.vue'
@@ -242,6 +314,11 @@ import Appellation from '@/components/Appellation.vue'
import { AT_ALL_ACCOUNT } from '@/utils/im/constants'
import { replaceEmoji } from '@/utils/im/index'
import { autorun } from 'mobx'
import quickImg from '@/static/quck_message.png'
import chuzhenImg from '@/static/outpatient_true.png'
import mallImg from '@/static/ytx_chattingfooter_shopping.png'
import hospitalImg from '@/static/ytx_chatting_hospital.png'
import {onShow,onUnload} from '@dcloudio/uni-app'
import {
V2NIMTeam,
@@ -257,7 +334,30 @@ import {
import { V2NIMConst } from '@/utils/im/nim'
import { V2NIMMessage } from 'nim-web-sdk-ng/dist/esm/nim/src/V2NIMMessageService'
export type MentionedMember = { accountId: string; appellation: string }
import navTo from '@/utils/navTo'
import api from '@/api/api.js'
let userInfo=uni.getStorageSync('userInfo');
let expert_uuid=userInfo.uuid;
let expert_name=userInfo.realName;
let patient_uuid='';
const articleInfo=ref({});
const videoInfo=ref({});
const patientListByGBK = async () => {
const res = await api.patientListByGBK();
if(res.code == 1){
//patientList.value = res.data;
for (let i = 0; i < res.data.length; i++) {
if (res.data[i].uuid.toLowerCase() === props.to) {
patient_uuid = res.data[i].uuid;
break;
}
}
}
};
const props = withDefaults(
defineProps<{
conversationType: V2NIMConst.V2NIMConversationType
@@ -278,6 +378,10 @@ const conversationId =
/** 输入框内容 */
const inputText = ref('')
const extVisible = ref(false)
/** 群发选择弹窗 */
const showModal = ref(false)
/** 商城弹窗 */
const showMallModal = ref(false)
/** 音频面板flag */
const audioPanelVisible = ref(false)
/** 发送更多面板flag */
@@ -314,6 +418,39 @@ const handleCall = (type: number) => {
})
}
}
onShow(() => {
uni.$on('articelItem', (article) => {
console.log('article', article);
articleInfo.value = article;
senCustomMsg('article');
//handleSendTextMsg('article', article);
});
uni.$on('videoItem', (video) => {
videoInfo.value = video;
senCustomMsg('video');
//handleSendTextMsg('video', video);
});
uni.$on('quickReply', (reply) => {
inputText.value= reply;
});
});
onUnload(() => {
uni.$off('articelItem');
uni.$off('videoItem');
uni.$off('quickReply');
});
/** 商城弹窗 */
let rawStr="{\"gdxz_content\":\"我已入驻肝胆相照互联网医院,复诊购药一站式服务,快来看看吧\",\"gdxz_ext_data\":\"[互联网医院]\",\"gdxz_id\":\"1681174885629431808\",\"gdxz_img\":\"https://img.applets.igandanyiyuan.com/applet/admin/avatar/2023071813261420200708181049.png\",\"gdxz_title\":\"肝胆相照互联网医院\",\"gdxz_type\":\"[互联网医院]\",\"gdxz_url\":\"\"}";
const sendMallMsg = () => {
showMallModal.value = false;
handleSendTextMsg('mall');
}
/** 商城弹窗 */
const closeMallModal = () => {
showMallModal.value = false
}
/** 用于解决表情面板和键盘冲突,导致输入框滚动消失问题 */
const showEmojiInput = ref(false)
@@ -326,6 +463,7 @@ const replyMsg = ref<V2NIMMessageForUI>()
/** @ 消息相关 */
const ctx = getCurrentInstance()
const popupRef = ref(null)
/** @ 成员列表 */
const selectedAtMembers = ref<MentionedMember[]>([])
@@ -381,6 +519,26 @@ const onPopupChange = (e: any) => {
uni.$emit(events.HANDLE_MOVE_THROUGH, e.value)
}
/** 打开/关闭群发选择弹窗(与 groupSend 保持一致) */
const openModal = () => {
showModal.value = true;
}
const closeModal = () => {
showModal.value = false
}
const toggleModal = () => {
showModal.value = !showModal.value
}
const onSelectSince = (type: string) => {
showModal.value = false
if (type === 'article') {
navTo({ url: '/pages_chat/article/article' })
} else if (type === 'video') {
navTo({ url: '/pages_chat/video/video' })
}
}
/** 点击@ 群成员 */
const handleMentionItemClick = (member: MentionedMember) => {
//@ts-ignore
@@ -455,19 +613,21 @@ const handleInput = (event: any) => {
}
/** 发送文本消息 */
const handleSendTextMsg = () => {
const handleSendTextMsg = (type:string) => {
if (inputText.value.trim() === '') return
const ext = onAtMembersExtHandler()
let text = replaceEmoji(inputText.value)
let mallText='纽娃复合营养素固体饮料主要成分是:蜂花粉、乳清蛋白粉、灰树花粉、低聚木糖、蚕蛹氨基酸、麦芽粉、薏苡仁粉、烟酸、磷脂,以及其他调味品、辅助原料。科学配比制成,含有丰富的蛋白质、氨基酸、维生素、微量元素及其他营养元素,点击链接了解详情。'
let text = type==='mall'?mallText:replaceEmoji(inputText.value)
const textMsg = uni.$UIKitNIM.V2NIMMessageCreator.createTextMessage(text)
let serverExtension={"gdxz_nickName":"测试","gdxz_sessionType":"general"};
uni.$UIKitStore.msgStore
.sendMessageActive({
msg: textMsg as unknown as V2NIMMessage,
conversationId,
serverExtension: selectedAtMembers.value.length && (ext as any),
serverExtension:selectedAtMembers.value.length && (ext as any),
sendBefore: () => {
scrollBottom()
scrollBottom();
},
})
.catch(() => {
@@ -483,7 +643,10 @@ const handleSendTextMsg = () => {
inputText.value = ''
isReplyMsg.value = false
replyMsg.value = undefined
selectedAtMembers.value = []
selectedAtMembers.value = [];
if(type=='mall'){
senCustomMsg('mall');
}
}
/** 发送文件消息 */
@@ -629,7 +792,75 @@ const handleSendImageMsg = () => {
complete: handleNoPermission,
})
}
const senCustomMsg = (type:string) => {
let rawStr="";
let text="";
if(type == 'hospital'){
text="[互联网医院]";
rawStr=`{\"gdxz_content\":\"我已入驻肝胆相照互联网医院,复诊购药一站式服务,快来看看吧\",\"gdxz_ext_data\":\"[互联网医院]\",\"gdxz_id\":\"1681174885629431808\",\"gdxz_img\":\"https://img.applets.igandanyiyuan.com/applet/admin/avatar/2023071813261420200708181049.png\",\"gdxz_title\":\"肝胆相照互联网医院\",\"gdxz_type\":\"[互联网医院]\",\"gdxz_url\":\"\"}`;
}else if(type == 'mall'){
text="[肝胆商城]";
rawStr=`{\"gdxz_content\":\"肝胆相照®肝胆病在线公共服务平台\",\"gdxz_ext_data\":\"[肝胆商城]\",\"gdxz_id\":\"\",\"gdxz_img\":\"\",\"gdxz_title\":\"纽娃复合营养素固体饮料\",\"gdxz_type\":\"[肝胆商城]\",\"gdxz_url\":\"https://wx.igandan.com/shop_notify/setInfo?patient_uuid=${patient_uuid}&expert_uuid=${expert_uuid}\"}`;
}else if(type == 'outpatient'){
text="[门诊公告]";
rawStr=`{\"gdxz_content\":\"门诊详情\",\"gdxz_ext_data\":\"[门诊公告]\",\"gdxz_id\":\"\",\"gdxz_img\":\"\",\"gdxz_title\":\"${expert_name}医生门诊详情\",\"gdxz_type\":\"[门诊公告]\",\"gdxz_url\":\"https://dev-wx.igandan.com/wxPatient/index.htm#/outPatient?link=share&expertUuid=${expert_uuid}\"}`
}else if(type == 'article'){
text="[图文科普]";
let content='"'+articleInfo.value.summary+'"';
let id='"'+articleInfo.value.uuid+'"';
let title='"'+articleInfo.value.title+'"';
let path='"'+docUrl+articleInfo.value.path+'"';
rawStr=`{\"gdxz_content\":${content},\"gdxz_ext_data\":\"[图文科普]\",\"gdxz_id\":${id},\"gdxz_img\":\"http://doc.igandan.org/app/book/pdf/2019/20190613152617.png\",\"gdxz_title\":${title},\"gdxz_type\":\"[图文科普]\",\"gdxz_url\":${path}}`
}else if(type == 'video'){
let content='"'+videoInfo.value.note+'"';
let id='"'+videoInfo.value.uuid+'"';
let title='"'+videoInfo.value.name+'"';
let path='"'+docUrl+videoInfo.value.path+'"';
text="[视频科普]";
rawStr=`{\"gdxz_content\":${content},\"gdxz_ext_data\":\"[视频科普]\",\"gdxz_id\":${id},\"gdxz_img\":\"http://doc.igandan.org/app/book/pdf/2019/20190613152617.png\",\"gdxz_title\":${title},\"gdxz_type\":\"[视频科普]\",\"gdxz_url\":${path}}`
}
const customMsg = uni.$UIKitNIM.V2NIMMessageCreator.createCustomMessage(text,rawStr)
uni.$UIKitStore.msgStore
.sendMessageActive({
msg: customMsg as unknown as V2NIMMessage,
conversationId,
progress: () => true,
sendBefore: () => {
scrollBottom()
},
})
.then(() => {
scrollBottom();
})
.catch(() => {
scrollBottom()
uni.showToast({
icon: 'error',
title: '发送失败',
})
})
}
const handleCustom = (type: string, event: any) => {
if (isTeamMute.value) return
if(type == 'reply'){
navTo({
url: '/pages_chat/quickReply/quickReply',
})
}else if(type == 'hj'){
showModal.value = true
}else if(type == 'mall'){
showMallModal.value = true
patientListByGBK();
}else if(type == 'outpatient'){
senCustomMsg('outpatient');
// navTo({
// url: '/pages_chat/outpatient/outpatient',
// })
}else if(type == 'hospital'){
senCustomMsg('hospital');
}
}
/** 发送视频消息(使用相机或者从相册选择) */
const handleSendVideoMsg = (type: string, event: any) => {
if (isTeamMute.value) return
@@ -1073,12 +1304,18 @@ onUnmounted(() => {
.send-more-panel-item {
background-color: #fff;
border-radius: 8px;
width: 60px;
height: 60px;
width: 100rpx;
height: 100rpx;
display: flex;
overflow: hidden;
align-items: center;
margin: 0 15px;
justify-content: center;
image{
width: 100rpx;
height: 100rpx;
border-radius: 8px;
}
}
.icon-text {
font-size: 12px;
@@ -1178,4 +1415,47 @@ onUnmounted(() => {
height: 60px;
}
}
/* 复制自 groupSend 的遮罩与弹窗样式 */
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 1000;
}
.center-modal {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 650rpx;
background: #ffffff;
border-radius: 16rpx;
z-index: 1001;
overflow: hidden;
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.15);
}
.modal-title {
text-align: center;
font-size: 34rpx;
color: #d32f2f;
padding: 28rpx 20rpx;
}
.modal-item {
padding: 36rpx 28rpx;
font-size: 30rpx;
color: #333333;
background: #ffffff;
}
.modal-divider {
height: 2rpx;
background: #eeeeee;
}
</style>
+39 -1
View File
@@ -1,4 +1,5 @@
<template>
<!-- {{ props.msg }} -->
<div
:class="`msg-item-wrapper ${
props.msg.pinState &&
@@ -351,6 +352,42 @@
</div>
<!-- <MessageIsRead v-if="props.msg?.isSelf" :msg="props.msg"></MessageIsRead> -->
</div>
<!-- 自定义消息-->
<div
class="msg-common"
v-else-if="
props.msg.messageType ===
V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_CUSTOM
"
:style="{ flexDirection: !props.msg.isSelf ? 'row' : 'row-reverse' }"
>
<Avatar
:account="props.msg.senderId"
:teamId="
conversationType ===
V2NIMConst.V2NIMConversationType.V2NIM_CONVERSATION_TYPE_TEAM
? to
: ''
"
:goto-user-card="true"
/>
<div class="msg-content">
<div class="msg-name" v-if="!props.msg.isSelf">
{{ appellation }}
</div>
<MessageBubble
:msg="props.msg"
:tooltip-visible="true"
:bg-visible="true"
>
<ReplyMessage v-if="!!replyMsg" :replyMsg="replyMsg"></ReplyMessage>
<!-- <MessageText :msg="props.msg"></MessageText> -->
<MessageCustom :msg="props.msg"></MessageCustom>
</MessageBubble>
</div>
<MessageIsRead v-if="props.msg?.isSelf" :msg="props.msg"></MessageIsRead>
</div>
<!-- 通知消息-->
<MessageNotification
v-else-if="
@@ -383,7 +420,7 @@
:tooltip-visible="true"
:bg-visible="true"
>
[{{ t('unknowMsgText') }}]
[{{ t('unknowMsgText')}}]
</MessageBubble>
</div>
</div>
@@ -435,6 +472,7 @@ import MessageNotification from './message-notification.vue'
import MessageG2 from './message-g2.vue'
import { customNavigateTo } from '@/utils/im/customNavigate'
import MessageIsRead from './message-read.vue'
import MessageCustom from './message-custom.vue'
import Icon from '@/components/Icon.vue'
import Appellation from '@/components/Appellation.vue'
import { events, MSG_ID_FLAG } from '@/utils/im/constants'