108 lines
2.8 KiB
Vue
108 lines
2.8 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
import { useTheme } from 'vuetify';
|
|
import { themes } from '@/plugins/vuetify/theme';
|
|
|
|
const props = defineProps({
|
|
message: Object,
|
|
activeModelColor: String,
|
|
activeModelBgColor: String,
|
|
models: Array,
|
|
selectedModelIdentifier: String,
|
|
});
|
|
|
|
const getFileIcon = (fileType) => {
|
|
if (fileType.startsWith('image/')) return 'tabler-photo';
|
|
if (fileType.includes('pdf')) return 'tabler-file-type-pdf';
|
|
if (fileType.includes('word')) return 'tabler-file-type-doc';
|
|
if (fileType.includes('text')) return 'tabler-file-text';
|
|
return 'tabler-file';
|
|
};
|
|
|
|
const getFileSize = (size) => {
|
|
if (size < 1024) return `${size} B`;
|
|
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`;
|
|
return `${(size / (1024 * 1024)).toFixed(1)} MB`;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<li
|
|
class="my-3 d-flex"
|
|
:class="[
|
|
message.sender === 'user' ? 'justify-end' : 'justify-start',
|
|
message.isAnimating ? 'is-animating' : '',
|
|
message.sender === 'user' ? 'user-message' : 'bot-message',
|
|
message.isSystemMessage ? 'system-message' : '',
|
|
]"
|
|
>
|
|
<template v-if="message.sender !== 'user'">
|
|
<VAvatar
|
|
size="32"
|
|
:color="message.isSystemMessage ? 'grey' : activeModelColor"
|
|
variant="tonal"
|
|
class="me-2 message-avatar"
|
|
>
|
|
<VIcon
|
|
:icon="message.isSystemMessage ? 'tabler-info-circle' : 'tabler-robot'"
|
|
/>
|
|
</VAvatar>
|
|
</template>
|
|
|
|
<div
|
|
class="pa-3 rounded-lg message-bubble"
|
|
:class="[
|
|
message.sender === 'user'
|
|
? 'bg-primary text-white'
|
|
: message.isSystemMessage
|
|
? 'bg-grey-lighten-3 text-grey-darken-3'
|
|
: `bg-${activeModelBgColor} text-white`,
|
|
message.isAnimating ? 'animate-message' : '',
|
|
]"
|
|
>
|
|
<div v-if="!message.form && !message.multiForm && !message.type">
|
|
{{ message.text }}
|
|
</div>
|
|
|
|
<div v-if="message.isAttachment && message.files" class="attachment-preview mt-2">
|
|
<div
|
|
v-for="(file, fileIndex) in message.files"
|
|
:key="fileIndex"
|
|
class="d-flex align-center mb-1"
|
|
>
|
|
<VIcon :icon="getFileIcon(file.type)" size="small" class="me-1"></VIcon>
|
|
<span class="text-caption">{{ file.name }} ({{ getFileSize(file.size) }})</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<template v-if="message.sender === 'user'">
|
|
<VAvatar size="32" color="grey" variant="tonal" class="ms-2 message-avatar">
|
|
<VIcon icon="tabler-user" />
|
|
</VAvatar>
|
|
</template>
|
|
</li>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.message-avatar {
|
|
opacity: 0;
|
|
animation: fade-in 0.3s ease forwards;
|
|
animation-delay: 0.15s;
|
|
}
|
|
|
|
@keyframes fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.attachment-preview {
|
|
font-size: 0.85rem;
|
|
opacity: 0.9;
|
|
}
|
|
</style>
|