2026-01-26 11:16:56 +08:00
|
|
|
<script>
|
|
|
|
|
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
|
|
|
|
|
import ChatCard from 'shared/components/ChatCard.vue';
|
|
|
|
|
import ChatForm from 'shared/components/ChatForm.vue';
|
|
|
|
|
import ChatOptions from 'shared/components/ChatOptions.vue';
|
|
|
|
|
import ChatTable from 'shared/components/ChatTable.vue';
|
|
|
|
|
import ChatArticle from './template/Article.vue';
|
|
|
|
|
import EmailInput from './template/EmailInput.vue';
|
|
|
|
|
import CustomerSatisfaction from 'shared/components/CustomerSatisfaction.vue';
|
|
|
|
|
import IntegrationCard from './template/IntegrationCard.vue';
|
|
|
|
|
import OrderList from 'shared/components/OrderList.vue';
|
|
|
|
|
import OrderDetail from 'shared/components/OrderDetail.vue';
|
|
|
|
|
import Logistics from 'shared/components/Logistics.vue';
|
2026-01-27 19:03:46 +08:00
|
|
|
import ProductList from 'shared/components/ProductList.vue';
|
2026-01-26 11:16:56 +08:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'AgentMessageBubble',
|
|
|
|
|
components: {
|
|
|
|
|
ChatArticle,
|
|
|
|
|
ChatCard,
|
|
|
|
|
ChatForm,
|
|
|
|
|
ChatOptions,
|
|
|
|
|
ChatTable,
|
|
|
|
|
EmailInput,
|
|
|
|
|
CustomerSatisfaction,
|
|
|
|
|
IntegrationCard,
|
|
|
|
|
OrderList,
|
|
|
|
|
OrderDetail,
|
|
|
|
|
Logistics,
|
2026-01-27 19:03:46 +08:00
|
|
|
ProductList,
|
2026-01-26 11:16:56 +08:00
|
|
|
},
|
|
|
|
|
props: {
|
|
|
|
|
message: { type: String, default: null },
|
|
|
|
|
contentType: { type: String, default: null },
|
|
|
|
|
messageType: { type: Number, default: null },
|
|
|
|
|
messageId: { type: Number, default: null },
|
|
|
|
|
messageContentAttributes: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => {},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
setup() {
|
|
|
|
|
const { formatMessage, getPlainText, truncateMessage, highlightContent } =
|
|
|
|
|
useMessageFormatter();
|
|
|
|
|
return {
|
|
|
|
|
formatMessage,
|
|
|
|
|
getPlainText,
|
|
|
|
|
truncateMessage,
|
|
|
|
|
highlightContent,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
isTemplate() {
|
|
|
|
|
return this.messageType === 3;
|
|
|
|
|
},
|
|
|
|
|
isTemplateEmail() {
|
|
|
|
|
return this.contentType === 'input_email';
|
|
|
|
|
},
|
|
|
|
|
isCards() {
|
|
|
|
|
return this.contentType === 'cards';
|
|
|
|
|
},
|
|
|
|
|
isOptions() {
|
|
|
|
|
return this.contentType === 'input_select';
|
|
|
|
|
},
|
|
|
|
|
isForm() {
|
|
|
|
|
return this.contentType === 'form';
|
|
|
|
|
},
|
|
|
|
|
isArticle() {
|
|
|
|
|
return this.contentType === 'article';
|
|
|
|
|
},
|
|
|
|
|
isCSAT() {
|
|
|
|
|
return this.contentType === 'input_csat';
|
|
|
|
|
},
|
|
|
|
|
isIntegrations() {
|
|
|
|
|
return this.contentType === 'integrations';
|
|
|
|
|
},
|
|
|
|
|
isTable() {
|
|
|
|
|
return this.contentType === 'data_table';
|
|
|
|
|
},
|
|
|
|
|
isOrderList() {
|
|
|
|
|
return this.contentType === 'order_list';
|
|
|
|
|
},
|
|
|
|
|
isOrderDetail() {
|
|
|
|
|
return this.contentType === 'order_detail';
|
|
|
|
|
},
|
|
|
|
|
isLogistics() {
|
|
|
|
|
return this.contentType === 'logistics';
|
|
|
|
|
},
|
2026-01-27 19:03:46 +08:00
|
|
|
isProductList() {
|
|
|
|
|
return this.contentType === 'product_list';
|
|
|
|
|
},
|
2026-01-26 11:16:56 +08:00
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
onResponse(messageResponse) {
|
|
|
|
|
this.$store.dispatch('message/update', messageResponse);
|
|
|
|
|
},
|
|
|
|
|
onOptionSelect(selectedOption) {
|
|
|
|
|
this.onResponse({
|
|
|
|
|
submittedValues: [selectedOption],
|
|
|
|
|
messageId: this.messageId,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
onFormSubmit(formValues) {
|
|
|
|
|
const formValuesAsArray = Object.keys(formValues).map(key => ({
|
|
|
|
|
name: key,
|
|
|
|
|
value: formValues[key],
|
|
|
|
|
}));
|
|
|
|
|
this.onResponse({
|
|
|
|
|
submittedValues: formValuesAsArray,
|
|
|
|
|
messageId: this.messageId,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="chat-bubble-wrap">
|
|
|
|
|
<div
|
|
|
|
|
v-if="
|
2026-01-27 19:03:46 +08:00
|
|
|
!isCards && !isOptions && !isForm && !isArticle && !isCards && !isCSAT && !isTable && !isOrderList && !isOrderDetail && !isLogistics && !isProductList
|
2026-01-26 11:16:56 +08:00
|
|
|
"
|
|
|
|
|
class="chat-bubble agent bg-n-background dark:bg-n-solid-3 text-n-slate-12"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
v-dompurify-html="formatMessage(message, false)"
|
|
|
|
|
class="message-content text-n-slate-12"
|
|
|
|
|
/>
|
|
|
|
|
<EmailInput
|
|
|
|
|
v-if="isTemplateEmail"
|
|
|
|
|
:message-id="messageId"
|
|
|
|
|
:message-content-attributes="messageContentAttributes"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<IntegrationCard
|
|
|
|
|
v-if="isIntegrations"
|
|
|
|
|
:message-id="messageId"
|
|
|
|
|
:meeting-data="messageContentAttributes.data"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="isOptions">
|
|
|
|
|
<ChatOptions
|
|
|
|
|
:title="message"
|
|
|
|
|
:options="messageContentAttributes.items"
|
|
|
|
|
:hide-fields="!!messageContentAttributes.submitted_values"
|
|
|
|
|
@option-select="onOptionSelect"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<ChatForm
|
|
|
|
|
v-if="isForm && !messageContentAttributes.submitted_values"
|
|
|
|
|
:items="messageContentAttributes.items"
|
|
|
|
|
:button-label="messageContentAttributes.button_label"
|
|
|
|
|
:submitted-values="messageContentAttributes.submitted_values"
|
|
|
|
|
@submit="onFormSubmit"
|
|
|
|
|
/>
|
|
|
|
|
<div v-if="isCards">
|
|
|
|
|
<ChatCard
|
|
|
|
|
v-for="item in messageContentAttributes.items"
|
|
|
|
|
:key="item.title"
|
|
|
|
|
:media-url="item.media_url"
|
|
|
|
|
:title="item.title"
|
|
|
|
|
:description="item.description"
|
|
|
|
|
:actions="item.actions"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="isArticle">
|
|
|
|
|
<ChatArticle :items="messageContentAttributes.items" />
|
|
|
|
|
</div>
|
|
|
|
|
<CustomerSatisfaction
|
|
|
|
|
v-if="isCSAT"
|
|
|
|
|
:message-content-attributes="messageContentAttributes.submitted_values"
|
|
|
|
|
:display-type="messageContentAttributes.display_type"
|
|
|
|
|
:message="message"
|
|
|
|
|
:message-id="messageId"
|
|
|
|
|
/>
|
|
|
|
|
<ChatTable
|
|
|
|
|
v-if="isTable"
|
|
|
|
|
:title="messageContentAttributes.title"
|
|
|
|
|
:headers="messageContentAttributes.headers"
|
|
|
|
|
:rows="messageContentAttributes.rows"
|
|
|
|
|
/>
|
|
|
|
|
<OrderList
|
|
|
|
|
v-if="isOrderList"
|
|
|
|
|
:orders="messageContentAttributes.orders"
|
|
|
|
|
/>
|
|
|
|
|
<OrderDetail
|
|
|
|
|
v-if="isOrderDetail"
|
|
|
|
|
:status="messageContentAttributes.status"
|
|
|
|
|
:status-text="messageContentAttributes.statusText"
|
|
|
|
|
:status-color="messageContentAttributes.statusColor"
|
|
|
|
|
:order-id="messageContentAttributes.orderId"
|
|
|
|
|
:order-time="messageContentAttributes.orderTime"
|
|
|
|
|
:items="messageContentAttributes.items"
|
|
|
|
|
:show-total="messageContentAttributes.showTotal"
|
|
|
|
|
:total-label="messageContentAttributes.totalLabel"
|
|
|
|
|
:amount-label="messageContentAttributes.amountLabel"
|
|
|
|
|
:actions="messageContentAttributes.actions"
|
|
|
|
|
/>
|
|
|
|
|
<Logistics
|
|
|
|
|
v-if="isLogistics"
|
|
|
|
|
:logistics-name="messageContentAttributes.logisticsName"
|
|
|
|
|
:tracking-number="messageContentAttributes.trackingNumber"
|
|
|
|
|
:current-step="messageContentAttributes.currentStep"
|
|
|
|
|
:is-urgent="messageContentAttributes.isUrgent"
|
|
|
|
|
:latest-log="messageContentAttributes.latestLog"
|
|
|
|
|
:latest-time="messageContentAttributes.latestTime"
|
|
|
|
|
:steps="messageContentAttributes.steps"
|
|
|
|
|
:actions="messageContentAttributes.actions"
|
|
|
|
|
/>
|
2026-01-27 19:03:46 +08:00
|
|
|
<ProductList
|
|
|
|
|
v-if="isProductList"
|
|
|
|
|
:title="messageContentAttributes.title"
|
|
|
|
|
:products="messageContentAttributes.products"
|
|
|
|
|
:actions="messageContentAttributes.actions"
|
|
|
|
|
/>
|
2026-01-26 11:16:56 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|