customerService.ts 2.99 KB
import { defineStore } from "pinia";
import { csAsk, csStream, resetCsChat } from "@/api/customerService";

export interface CsMessage {
  id: string;
  role: "user" | "assistant";
  content: string;
  status: "done" | "streaming" | "error";
}

export const useCustomerServiceStore = defineStore("customerService", () => {
  const messages = ref<CsMessage[]>([]);
  const streaming = ref(false);
  const chatId = ref<number | null>(null);

  let abortController: AbortController | null = null;
  let streamHandle: { close: () => void } | null = null;

  function _uid(): string {
    return `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
  }

  /** 发送一条用户消息,并触发 AI 流式回答 */
  async function sendMessage(content: string): Promise<void> {
    if (streaming.value) return;

    // 添加用户消息
    messages.value.push({
      id: _uid(),
      role: "user",
      content,
      status: "done",
    });

    // 添加 AI 占位消息
    const aiId = _uid();
    messages.value.push({
      id: aiId,
      role: "assistant",
      content: "",
      status: "streaming",
    });

    streaming.value = true;
    abortController = new AbortController();

    try {
      const result = await csAsk(content, chatId.value ?? undefined);
      chatId.value = result.chatId;

      streamHandle = csStream({
        chatId: result.chatId,
        questionId: result.questionId,
        signal: abortController.signal,
        onChunk: (text) => {
          const msg = messages.value.find((m) => m.id === aiId);
          if (msg) msg.content += text;
        },
        onDone: () => {
          const msg = messages.value.find((m) => m.id === aiId);
          if (msg) msg.status = "done";
          streaming.value = false;
          streamHandle = null;
        },
        onError: (err) => {
          console.error("[CS] stream error", err);
          const msg = messages.value.find((m) => m.id === aiId);
          if (msg) {
            msg.status = "error";
            if (!msg.content) msg.content = "回答出现错误,请重试。";
          }
          streaming.value = false;
          streamHandle = null;
        },
      });
    } catch (err) {
      console.error("[CS] ask error", err);
      const msg = messages.value.find((m) => m.id === aiId);
      if (msg) {
        msg.status = "error";
        msg.content = "发送失败,请检查网络后重试。";
      }
      streaming.value = false;
    }
  }

  /** 中止当前流式输出 */
  function stopStreaming(): void {
    abortController?.abort();
    streamHandle?.close();
    streamHandle = null;
    abortController = null;
    const last = messages.value[messages.value.length - 1];
    if (last?.status === "streaming") last.status = "done";
    streaming.value = false;
  }

  /** 清空对话并重置会话 */
  function clearMessages(): void {
    stopStreaming();
    messages.value = [];
    chatId.value = null;
    resetCsChat();
  }

  return { messages, streaming, sendMessage, stopStreaming, clearMessages };
});