feat: 添加会话标题自动生成功能
- 后端:首次 AI 回复后自动从用户消息提取标题 - 后端:通过 WebSocket 推送 session_updated 事件 - 前端:useChat hook 处理标题更新事件 - 前端:Sidebar 组件实时更新会话标题显示
This commit is contained in:
@@ -19,6 +19,8 @@ interface SidebarProps {
|
||||
onCreateSession: (session: Session) => void;
|
||||
/** 是否启用响应式布局(移动端抽屉式菜单) */
|
||||
responsive?: boolean;
|
||||
/** 会话标题更新事件(从 WebSocket 接收) */
|
||||
sessionTitleUpdate?: { sessionId: string; name: string } | null;
|
||||
}
|
||||
|
||||
export function Sidebar({
|
||||
@@ -26,6 +28,7 @@ export function Sidebar({
|
||||
onSelectSession,
|
||||
onCreateSession,
|
||||
responsive = false,
|
||||
sessionTitleUpdate,
|
||||
}: SidebarProps) {
|
||||
const [sessions, setSessions] = useState<Session[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -84,6 +87,19 @@ export function Sidebar({
|
||||
loadSessions();
|
||||
}, []);
|
||||
|
||||
// 处理会话标题更新
|
||||
useEffect(() => {
|
||||
if (sessionTitleUpdate) {
|
||||
setSessions((prev) =>
|
||||
prev.map((s) =>
|
||||
s.id === sessionTitleUpdate.sessionId
|
||||
? { ...s, name: sessionTitleUpdate.name }
|
||||
: s
|
||||
)
|
||||
);
|
||||
}
|
||||
}, [sessionTitleUpdate]);
|
||||
|
||||
const handleOverlayClick = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ interface UseChatOptions {
|
||||
sessionId: string;
|
||||
onError?: (error: Error) => void;
|
||||
onSessionNotFound?: () => void;
|
||||
onSessionUpdated?: (sessionId: string, name: string) => void;
|
||||
}
|
||||
|
||||
interface ChatState {
|
||||
@@ -20,7 +21,7 @@ interface ChatState {
|
||||
streamingContent: string;
|
||||
}
|
||||
|
||||
export function useChat({ sessionId, onError, onSessionNotFound }: UseChatOptions) {
|
||||
export function useChat({ sessionId, onError, onSessionNotFound, onSessionUpdated }: UseChatOptions) {
|
||||
const [state, setState] = useState<ChatState>({
|
||||
messages: [],
|
||||
isConnected: false,
|
||||
@@ -38,8 +39,10 @@ export function useChat({ sessionId, onError, onSessionNotFound }: UseChatOption
|
||||
// 用 ref 存储回调,避免依赖变化导致无限循环
|
||||
const onErrorRef = useRef(onError);
|
||||
const onSessionNotFoundRef = useRef(onSessionNotFound);
|
||||
const onSessionUpdatedRef = useRef(onSessionUpdated);
|
||||
onErrorRef.current = onError;
|
||||
onSessionNotFoundRef.current = onSessionNotFound;
|
||||
onSessionUpdatedRef.current = onSessionUpdated;
|
||||
|
||||
// 加载历史消息
|
||||
const loadMessages = useCallback(async () => {
|
||||
@@ -134,6 +137,13 @@ export function useChat({ sessionId, onError, onSessionNotFound }: UseChatOption
|
||||
onErrorRef.current?.(new Error(message.payload?.message || 'Unknown error'));
|
||||
setState((prev) => ({ ...prev, isLoading: false, streamingContent: '' }));
|
||||
break;
|
||||
|
||||
case 'session_updated':
|
||||
// 会话信息更新(如标题)
|
||||
if (message.payload?.id && message.payload?.name) {
|
||||
onSessionUpdatedRef.current?.(message.payload.id, message.payload.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch {
|
||||
// 忽略解析错误
|
||||
|
||||
Reference in New Issue
Block a user