add AiConversationList.vue

This commit is contained in:
Timi
2026-09-16 21:32:03 +08:00
parent 91938f2427
commit a0fac39c99
6 changed files with 663 additions and 8 deletions
+64 -2
View File
@@ -1,5 +1,5 @@
<template>
<section class="ai-chat-panel" aria-label="门店经营助手">
<section class="ai-chat-panel" :aria-label="`${props.storeName || '当前门店'}经营助手`">
<ai-chat-message-list
ref="messageList"
:messages="messages"
@@ -15,6 +15,7 @@
<ai-chat-composer
v-model="draft"
:is-generating="isGenerating"
:disabled="isLoadingConversation"
:last-error="lastError"
:can-retry="canRetry"
@send="submitMessage"
@@ -23,12 +24,25 @@
/>
</div>
</section>
<ai-conversation-list
v-model:visible="conversationVisible"
:active-conversation-id="conversationId"
:disabled="isBusy"
:session-key="props.sessionKey"
@select="selectConversation"
@delete="handleConversationDelete"
/>
</template>
<script setup lang="ts">
import { useAiChat } from "@/composables/useAiChat";
import type { GaoAiConversation } from "@/api/GaoAiAPI";
import AiChatComposer from "@/pages/ai/components/AiChatComposer.vue";
import AiConversationList from "@/pages/ai/components/AiConversationList.vue";
import AiChatMessageList from "@/pages/ai/components/AiChatMessageList.vue";
import { aiQuickQuestionList } from "@/pages/ai/aiChatQuestions";
import { useNavBarStore } from "@/store/navBarStore";
import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message";
defineOptions({
name: "AiChatPanel"
@@ -41,22 +55,61 @@ interface Props {
}
const props = defineProps<Props>();
const navBarStore = useNavBarStore();
type MessageListExpose = {
scrollToBottom: () => Promise<void>;
};
const messageListRef = useTemplateRef<MessageListExpose>("messageList");
const draft = shallowRef("");
const { messages, isGenerating, activeToolStatus, lastError, canRetry, sendMessage, stopGeneration, retryLastMessage } = useAiChat({
const conversationVisible = ref(false);
const {
messages,
conversationId,
isGenerating,
isLoadingConversation,
activeToolStatus,
lastError,
canRetry,
sendMessage,
loadConversation,
stopGeneration,
retryLastMessage,
resetConversation
} = useAiChat({
sessionKey: () => props.sessionKey,
storeId: () => props.storeId,
scrollToBottom
});
const isBusy = computed(() => isGenerating.value || isLoadingConversation.value);
async function submitMessage(message: string): Promise<void> {
await sendMessage(message);
}
function openConversationList(): void {
if (!isBusy.value) {
conversationVisible.value = true;
}
}
async function selectConversation(conversation: GaoAiConversation): Promise<void> {
if (isBusy.value || !conversation.id) {
return;
}
try {
await loadConversation(conversation.id);
} catch (error) {
Message.error(getErrorMessage(error, "历史会话读取失败"));
}
}
function handleConversationDelete(deletedConversationId: string): void {
if (deletedConversationId === conversationId.value) {
resetConversation();
}
}
function selectQuestion(question: string): void {
draft.value = question;
}
@@ -64,6 +117,15 @@ function selectQuestion(question: string): void {
async function scrollToBottom(): Promise<void> {
await messageListRef.value?.scrollToBottom();
}
onMounted(() => {
navBarStore.clearRight();
navBarStore.setRightText("历史", "var(--td-brand-color)", openConversationList);
});
watch(isBusy, value => navBarStore.setRightDisabled(value));
onUnmounted(() => navBarStore.clearRight());
</script>
<style scoped lang="less">
.ai-chat-panel {