191 lines
4.3 KiB
Vue
191 lines
4.3 KiB
Vue
|
|
<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>
|