feat:前端修改(最后一次)
This commit is contained in:
@@ -58,7 +58,8 @@ export function AssistantLauncher() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [tab, setTab] = useState<"chat" | "drafts">("chat");
|
||||
|
||||
const [sessionId, setSessionId] = useState(() => newSessionId());
|
||||
/* 会话在「打开抽屉」时才建立(见 openAssistant),关闭时丢弃,不在挂载时就占用上下文 */
|
||||
const [sessionId, setSessionId] = useState<string | null>(null);
|
||||
const [customers, setCustomers] = useState<Customer[]>([]);
|
||||
const [customerId, setCustomerId] = useState<number | null>(null);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
@@ -87,7 +88,7 @@ export function AssistantLauncher() {
|
||||
return () => clearInterval(timer);
|
||||
}, [streaming]);
|
||||
|
||||
const sessionTag = useMemo(() => sessionId.slice(-6), [sessionId]);
|
||||
const sessionTag = useMemo(() => (sessionId ? sessionId.slice(-6) : "--------"), [sessionId]);
|
||||
|
||||
/* 客户列表只用于会话上下文选择,失败不阻断助手 */
|
||||
useEffect(() => {
|
||||
@@ -101,8 +102,18 @@ export function AssistantLauncher() {
|
||||
})();
|
||||
}, []);
|
||||
|
||||
/* 会话 ID 变化时恢复该会话的历史;新会话为空属正常,不报错。 */
|
||||
/*
|
||||
* 会话握手:打开抽屉(sessionId 就绪)后拉一次该会话的记录。
|
||||
* 投顾 Agent 没有独立的 session/create,后端按 (advisor_id, session_id) 惰性建立上下文,
|
||||
* 所以这个请求就是「打开助手时发出的会话请求」;关闭抽屉会把 sessionId 置空、丢弃上下文。
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!sessionId) {
|
||||
setMessages([]);
|
||||
setHistoryError(null);
|
||||
setHistoryLoading(false);
|
||||
return;
|
||||
}
|
||||
let alive = true;
|
||||
void (async () => {
|
||||
setHistoryLoading(true);
|
||||
@@ -182,7 +193,7 @@ export function AssistantLauncher() {
|
||||
const result = await assistantApi.chatOnce(
|
||||
{
|
||||
query,
|
||||
session_id: sessionId,
|
||||
session_id: sessionId ?? undefined,
|
||||
scope: customerId ? "customer" : "advisor",
|
||||
customer_id: customerId,
|
||||
},
|
||||
@@ -241,7 +252,7 @@ export function AssistantLauncher() {
|
||||
setStreaming(true);
|
||||
try {
|
||||
if (tool === "data-query") {
|
||||
const result = await assistantApi.dataQuery({ query, session_id: sessionId });
|
||||
const result = await assistantApi.dataQuery({ query, session_id: sessionId ?? undefined });
|
||||
pushPair(query, result.answer ?? result.summary ?? "查询完成,无文本摘要。", "data_query");
|
||||
} else if (tool === "fund-analysis") {
|
||||
const result = await assistantApi.fundAnalysis(query);
|
||||
@@ -272,7 +283,30 @@ export function AssistantLauncher() {
|
||||
[customerId, input, loadDrafts, pushPair, sessionId, toast]
|
||||
);
|
||||
|
||||
/** 结束会话:中止生成、清空上下文并启用新的 session_id。 */
|
||||
/**
|
||||
* 打开抽屉 = 建立会话。
|
||||
* 投顾 Agent 后端只有 chat/stream 与 session/{id}/history,没有独立的 session/create,
|
||||
* 所以这里生成会话键,由上面的 useEffect 调 history 完成握手(后端按需建立上下文)。
|
||||
*/
|
||||
const openAssistant = useCallback(() => {
|
||||
setOpen(true);
|
||||
setSessionId((current) => current ?? newSessionId());
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* 关闭抽屉 = 结束会话:中止生成、清空消息并丢弃上下文。
|
||||
* 投顾侧后端未提供 session/end,因此结束只能在前端完成(下次打开是新的 session_id)。
|
||||
*/
|
||||
const closeAssistant = useCallback(() => {
|
||||
abortRef.current?.abort();
|
||||
setOpen(false);
|
||||
setMessages([]);
|
||||
setInput("");
|
||||
setStreaming(false);
|
||||
setSessionId(null);
|
||||
}, []);
|
||||
|
||||
/** 抽屉内「结束会话」:不等关闭,立即换一个全新会话并重新握手。 */
|
||||
const endSession = useCallback(() => {
|
||||
abortRef.current?.abort();
|
||||
setMessages([]);
|
||||
@@ -328,7 +362,7 @@ export function AssistantLauncher() {
|
||||
<>
|
||||
{!open && (
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
onClick={openAssistant}
|
||||
aria-label="打开投顾助手"
|
||||
className="fixed bottom-6 right-6 z-40 flex h-14 w-14 items-center justify-center rounded-full bg-indigo-600 text-white shadow-lg shadow-indigo-600/30 transition-transform hover:scale-105 hover:bg-indigo-700"
|
||||
>
|
||||
@@ -345,7 +379,7 @@ export function AssistantLauncher() {
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 z-40 bg-slate-900/10"
|
||||
onClick={() => setOpen(false)}
|
||||
onClick={closeAssistant}
|
||||
aria-hidden
|
||||
/>
|
||||
<aside className="fixed inset-y-0 right-0 z-50 flex w-full max-w-[560px] flex-col bg-white shadow-2xl">
|
||||
@@ -370,7 +404,7 @@ export function AssistantLauncher() {
|
||||
结束会话
|
||||
</Button>
|
||||
<button
|
||||
onClick={() => setOpen(false)}
|
||||
onClick={closeAssistant}
|
||||
aria-label="收起助手"
|
||||
className="rounded-lg p-2 text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-600"
|
||||
>
|
||||
@@ -414,7 +448,7 @@ export function AssistantLauncher() {
|
||||
<>
|
||||
<div ref={scrollRef} className="flex-1 space-y-4 overflow-y-auto px-5 py-4">
|
||||
{historyLoading && messages.length === 0 && (
|
||||
<p className="py-8 text-center text-sm text-slate-400">正在恢复会话...</p>
|
||||
<p className="py-8 text-center text-sm text-slate-400">正在建立会话...</p>
|
||||
)}
|
||||
{historyError && (
|
||||
<p className="rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600">{historyError}</p>
|
||||
|
||||
Reference in New Issue
Block a user