support attach

This commit is contained in:
Timi
2026-09-26 14:20:18 +08:00
parent 2b92012c39
commit a20e051e8a
7 changed files with 140 additions and 53 deletions
+37 -2
View File
@@ -2,6 +2,7 @@
<section class="ai-chat-panel" :aria-label="props.ariaLabel">
<ai-chat-message-list
ref="messageList"
:style="messageListStyle"
:messages="props.messages"
:is-generating="props.isGenerating"
:loading="props.isLoading"
@@ -40,7 +41,7 @@
</template>
</ai-chat-message-list>
<div class="bottom-area">
<div ref="bottomArea" class="bottom-area">
<slot name="tool-status" :status="props.activeToolStatus">
<div v-if="props.activeToolStatus" class="tool-status">
<t-icon name="loading" size="1rem" />
@@ -58,6 +59,7 @@
:on-stop="() => emit('stop')"
:on-retry="() => emit('retry')"
:on-new-conversation="() => emit('new-conversation')"
:on-add-attachment="() => emit('add-attachment')"
>
<ai-chat-composer
v-model="draft"
@@ -74,6 +76,7 @@
@stop="emit('stop')"
@retry="emit('retry')"
@new-conversation="emit('new-conversation')"
@add-attachment="emit('add-attachment')"
/>
</slot>
</div>
@@ -81,7 +84,7 @@
</template>
<script setup lang="ts">
import { shallowRef, useTemplateRef } from "vue";
import { computed, onBeforeUnmount, onMounted, ref, shallowRef, useTemplateRef } from "vue";
import type {
AiChatMessage,
AiChatMessageStatusFormatter,
@@ -144,10 +147,23 @@ const emit = defineEmits<{
stop: [];
retry: [];
"new-conversation": [];
"add-attachment": [];
}>();
const messageListRef = useTemplateRef<{ scrollToBottom: () => Promise<void> }>("messageList");
const bottomAreaRef = useTemplateRef<HTMLElement>("bottomArea");
const bottomAreaHeight = ref<number>();
const draft = shallowRef("");
let bottomAreaObserver: ResizeObserver | undefined;
const messageListStyle = computed(() => {
if (bottomAreaHeight.value === undefined) {
return {};
}
return {
"--ai-chat-bottom-area-height": `${bottomAreaHeight.value}px`
};
});
function submitMessage(message: string): void {
emit("send", message);
@@ -157,6 +173,23 @@ async function scrollToBottom(): Promise<void> {
await messageListRef.value?.scrollToBottom();
}
onMounted(() => {
const bottomArea = bottomAreaRef.value;
if (!bottomArea) {
return;
}
const updateBottomAreaHeight = () => {
bottomAreaHeight.value = Math.ceil(bottomArea.getBoundingClientRect().height);
};
updateBottomAreaHeight();
bottomAreaObserver = new ResizeObserver(updateBottomAreaHeight);
bottomAreaObserver.observe(bottomArea);
});
onBeforeUnmount(() => {
bottomAreaObserver?.disconnect();
});
defineExpose({
scrollToBottom
});
@@ -188,6 +221,8 @@ defineExpose({
z-index: 2;
position: absolute;
max-width: 40rem;
display: flex;
flex-direction: column;
.tool-status {
gap: .375rem;