hn-hlw-app/components/custom-message/consult-message-custom.vue
2026-07-27 11:26:39 +08:00

191 lines
4.3 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view v-if="shouldRender">
<pass-rx-card v-if="payload && payload.data === 'AUDIPASS'" :extension="payload.extension" />
<view
v-else-if="isVideoConsult && videoConsultDisplayText"
class="chat-row"
:class="[messageFlow === 'out' ? 'chat-row--end' : '']"
>
<image
:src="avatarSrc"
class="chat-avatar chat-avatar--square"
:class="[messageFlow === 'out' ? 'chat-avatar--right' : '']"
/>
<view class="chat-row-content">
<view
class="video-record-bubble"
:class="[messageFlow === 'out' ? 'my-message' : '']"
>
<image class="video-record-icon" :src="videoIconSrc" mode="aspectFit" />
<text class="video-record-text">{{ videoConsultDisplayText }}</text>
</view>
</view>
</view>
<view
v-else-if="showSystemTip"
class="message-item"
>
系统提示{{ payload.extension }}
</view>
</view>
</template>
<script setup>
import { computed } from "vue";
import PassRxCard from "./rx-pass-card.vue";
// messageItem.payload data: 消息类型 startChat 会话开始 , endChat 会话结束 ,
const props = defineProps({
messageItem: {
type: Object,
default: () => ({}),
},
partnerAvatar: {
type: String,
default: "",
},
});
const payload = computed(() => {
return props.messageItem.payload;
});
const messageFlow = computed(() => {
return props.messageItem && typeof props.messageItem.flow === "string"
? props.messageItem.flow
: "";
});
const isVideoConsult = computed(() => {
return !!(payload.value && payload.value.description === "VIDEO_CONSULT");
});
function parseVideoRecordExtension(ext) {
if (!ext || typeof ext !== "string") return null;
try {
const obj = JSON.parse(ext);
if (!obj || typeof obj !== "object") return null;
if (!obj.doctorText || !obj.patientText) return null;
return obj;
} catch (e) {
return null;
}
}
const videoConsultDisplayText = computed(() => {
const pl = payload.value || {};
const ext = typeof pl.extension === "string" ? pl.extension.trim() : "";
if (!ext) return "";
const record = parseVideoRecordExtension(ext);
if (!record) {
// 兼容历史extension 直接是文案
return ext;
}
// 同一条消息在医生端/患者端展示不同文案:发送方(out)=doctorText接收方(in)=patientText
return messageFlow.value === "in" ? record.patientText : record.doctorText;
});
const showSystemTip = computed(() => {
const pl = payload.value || {};
return !!(
pl.extension &&
pl.data !== "ACCEPTCONSULT" &&
pl.data !== "REPEATMEDICALADVICE"
);
});
const shouldRender = computed(() => {
const pl = payload.value || {};
return (
(pl && pl.data === "AUDIPASS") ||
(isVideoConsult.value && !!videoConsultDisplayText.value) ||
showSystemTip.value
);
});
const avatarSrc = computed(() => {
const msg = props.messageItem || {};
if (messageFlow.value === "in" && props.partnerAvatar) return props.partnerAvatar;
return (
msg.avatar ||
(msg.payload && msg.payload.avatar) ||
"https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png"
);
});
const videoIconSrc = "/static/icons/video-consult.svg";
</script>
<style scoped lang="scss">
//灰色 字体颜色
.message-item {
padding: 10px;
color: #666;
// border-radius: 10px;
margin: 0px 0 10px 0;
text-align: center;
font-size: 14px;
}
/* Align with existing chat bubble layout (see pages/chat/chat-message.vue) */
.chat-row {
display: flex;
padding-bottom: 10px;
width: 100%;
}
.chat-row--end {
justify-content: flex-end;
}
.chat-row-content {
max-width: 80%;
margin: 0 10px;
overflow: hidden;
order: 2;
}
.chat-avatar {
flex-shrink: 0;
width: 36px;
height: 36px;
order: 1;
}
.chat-avatar--right {
order: 3;
}
.chat-avatar--square {
border-radius: 4px;
}
.video-record-bubble {
display: inline-flex;
align-items: center;
max-width: 100%;
padding: 10px 12px;
background: #f2f2f2;
color: #333;
border-radius: 6px;
font-size: 14px;
line-height: 1.2;
}
.video-record-bubble.my-message {
background: #dceafd;
}
.video-record-icon {
width: 16px;
height: 16px;
flex: 0 0 auto;
}
.video-record-text {
margin-left: 6px;
white-space: normal;
word-break: break-word;
overflow: visible;
}
</style>