Files
xsh-assistant-next/components/aigc/chat/Message.vue
2024-04-03 16:16:37 +08:00

103 lines
2.8 KiB
Vue

<script setup lang="ts">
import type {PropType} from "vue";
import type {ChatMessage} from "~/typings/llm";
import MessageResponding from "~/components/Icon/MessageResponding.vue";
const props = defineProps({
message: {
type: Object as PropType<ChatMessage>,
required: true,
}
})
const dayjs = useDayjs()
const message_place_end = computed(() => props.message?.role !== 'assistant')
const message_avatar = computed(() => {
switch (props.message?.role) {
case 'user':
return 'i-fluent-emoji-slightly-smiling-face'
case 'assistant':
return 'i-fluent-emoji-robot'
case 'system':
return 'i-fluent-emoji-receipt'
}
})
const message_background = computed(() => {
if (props.message?.interrupted) {
return 'bg-red-200/50 dark:bg-red-800/20 border-red-300 dark:!border-red-500/50'
}
switch (props.message?.role) {
case 'user':
return 'bg-primary-100 dark:bg-primary-800'
case 'assistant':
case 'system':
return 'bg-neutral-100 dark:bg-neutral-800'
}
})
</script>
<template>
<div class="chat" :class="{'justify-end': message_place_end}">
<div class="chat-inside" :class="{'items-end': message_place_end}">
<div class="chat-inside-avatar">
<Icon :name="message_avatar" class="text-lg"/>
</div>
<div class="flex flex-col" :class="{'items-end': message_place_end}">
<Transition mode="out-in" name="message-content-change">
<div
class="chat-inside-content relative"
:class="message_background"
:key="message.content"
>
<div v-if="message.content">
<!-- TODO: 生成结果的代码添加复制按钮 -->
<Markdown :source="message.content"/>
</div>
<span v-else>
<MessageResponding class="text-xl text-neutral-500 dark:text-neutral-300 mx-2"/>
</span>
</div>
</Transition>
<div v-if="message.create_at" class="chat-inside-extra">
{{ dayjs(message.create_at * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.chat {
@apply w-full flex;
&-inside {
@apply w-fit flex flex-col gap-2;
@apply md:max-w-[80%];
&-avatar {
@apply w-8 h-8 flex justify-center items-center rounded-xl;
@apply bg-white border shadow-card;
@apply dark:bg-neutral-800 dark:border-neutral-700;
}
&-content {
@apply px-2 py-2.5 rounded-xl text-sm w-fit;
@apply border dark:border-neutral-700;
}
&-extra {
@apply px-1 text-xs text-neutral-300 dark:text-neutral-700;
}
}
}
.message-content-change-enter-active,
.message-content-change-leave-active {
@apply transition-all duration-300 overflow-hidden;
}
.message-content-change-enter-from {
@apply opacity-0 translate-y-4;
}
</style>