# langgraph 前端 **Repository Path**: cy2015/langgraph---front-end ## Basic Information - **Project Name**: langgraph 前端 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-11-11 - **Last Updated**: 2025-11-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LangGraph 前端项目 基于 Vue 3 + TypeScript + TDesign 的类 ChatGPT 前端应用,支持多会话管理、消息展示、AI 对话和文件管理等功能。 ## 🚀 技术栈 - **Vue 3** - 使用 Composition API 和 ` ``` ## 🏗️ 系统架构 本项目采用分层架构设计,确保代码的可维护性、可扩展性和类型安全。 ### 架构层次 ``` ┌─────────────────────────────────────────────────────────────┐ │ 视图层 (Views) │ │ 页面组件和路由 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ 组件层 (Components) │ │ 可复用的 Vue 组件和业务组件 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ 状态管理层 (Stores) │ │ Pinia 全局状态管理 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ 数据转换层 (Transform) │ │ 前后端数据格式转换和处理 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ API 层 (API) │ │ HTTP 请求封装和接口定义 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ 数据结构层 (Beans) │ │ TypeScript 接口和类型定义 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ 配置层 (Config) │ │ 全局配置和常量定义 │ └─────────────────────────────────────────────────────────────┘ ``` ### 1. 数据结构层 (Beans) **位置**: `src/beans/` **职责**: 定义 TypeScript 接口和类型,确保整个应用的类型安全。 **核心接口**: ```typescript // 用户信息 interface UserInfo { id: string; token: string; username: string; } // 消息结构 interface Message { id: string; type: 'human' | 'ai' | 'system' | 'tool'; content: string; think?: string; // AI 思考过程 tools?: ToolCall[]; // 工具调用列表 name?: string; // 工具名称 toolCall?: ToolCall; // 工具调用信息 } // 会话信息 interface ThreadItem { thread_id: string; status: string; created_at: string; updated_at: string; metadata?: { name?: string; owner?: string; }; config?: any; values?: any; } // Assistant 信息 interface AssistantItem { assistant_id: string; name: string; graph_id: string; description?: string; version: number; created_at: string; updated_at: string; config?: any; metadata?: any; } ``` **特点**: - 严格的类型定义,避免运行时错误 - 支持可选属性,适应不同场景 - 与后端 API 数据结构保持一致 - 支持泛型和联合类型 ### 2. API 层 (API) **位置**: `src/api/` **职责**: 封装所有 HTTP 请求,提供统一的接口调用方式。 **核心模块**: #### HTTP 基础封装 (`http.ts`) ```typescript // 自动注入 token // 统一错误处理 // 请求/响应拦截器 // 支持泛型返回类型 ``` #### 健康检查 (`health.ts`) ```typescript export function checkHealth() { return http.get('/ok'); } ``` #### Assistants 管理 (`assistants.ts`) ```typescript export function searchAssistants(params: SearchAssistantsParams) { return http.post('/assistants/search', params); } ``` #### Threads 管理 (`threads.ts`) ```typescript // 搜索会话列表 export function searchThreads(params: SearchThreadsParams) { return http.post('/threads/search', params); } // 创建新会话 export function createThread(params: CreateThreadParams = {}) { return http.post('/threads', params); } // 更新会话信息 export function updateThread(threadId: string, params: UpdateThreadParams) { return http.patch(`/threads/${threadId}`, params); } // 删除会话 export function deleteThread(threadId: string) { return http.delete(`/threads/${threadId}`); } // 获取会话详情 export function getThread(threadId: string) { return http.get(`/threads/${threadId}`); } // 取消运行请求 export function cancelRun(threadId: string, runId: string, params: CancelRunParams = {}) { const { wait = false, action = 'interrupt' } = params; // 构建查询参数 const queryParams = new URLSearchParams(); queryParams.append('wait', String(wait)); queryParams.append('action', action); return http.post( `/threads/${threadId}/runs/${runId}/cancel?${queryParams.toString()}` ); } ``` **特点**: - 统一的错误处理机制 - 自动 token 注入 - TypeScript 类型支持 - RESTful API 设计 - 支持请求/响应拦截 ### 3. 数据转换层 (Transform) **位置**: `src/utils/transform.ts` **职责**: 处理前后端数据格式差异,确保数据在不同层之间的正确转换。 **核心功能**: #### 用户信息格式化 ```typescript export function formatUserInfo(data: any): UserInfo { return { id: data.id || '', token: data.token || '', username: data.username || data.name || '', }; } ``` #### Assistant 数据转换 ```typescript export function formatAssistant(item: AssistantItem): Assistant { return { id: item.assistant_id, name: item.name, graphId: item.graph_id, description: item.description || '', version: String(item.version), createdAt: item.created_at, updatedAt: item.updated_at, config: item.config, metadata: item.metadata, }; } ``` #### 会话数据转换 ```typescript export function formatThread(item: ThreadItem) { return { id: item.thread_id, title: item.metadata?.name || '未命名会话', owner: item.metadata?.owner || '', status: item.status, lastTime: formatTime(item.updated_at), createdAt: item.created_at, updatedAt: item.updated_at, config: item.config, values: item.values, }; } ``` #### 消息内容处理 ```typescript // 提取 AI 思考过程 export function extractThinkContent(content: string): string | undefined { const thinkMatch = content.match(/([\s\S]*?)<\/think>/); return thinkMatch ? thinkMatch[1].trim() : undefined; } // 清理 AI 消息内容 export function cleanAiContent(content: string): string { return content.replace(/[\s\S]*?<\/think>\s*/g, '').trim(); } // 格式化工具结果 export function formatToolResult(msg: any): string { // 智能处理不同类型的工具结果 // 特殊处理搜索工具结果 // 格式化 JSON 数据 } // 转换消息列表 export function formatMessages(messages: any[]): Message[] { // 处理不同类型的消息 // 提取工具调用信息 // 关联工具调用和结果 } ``` **特点**: - 智能数据转换,适应不同数据格式 - 支持复杂的消息解析(AI 思考过程、工具调用) - 时间格式标准化 - 容错处理,避免数据异常导致的错误 - 支持工具结果的特殊格式化 ### 4. 状态管理层 (Stores) **位置**: `src/stores/` **职责**: 使用 Pinia 管理全局状态,提供响应式数据和状态操作方法。 #### 用户状态管理 (`user.ts`) ```typescript export const useUserStore = defineStore('user', { state: (): UserInfo => ({ id: '', token: '', username: '', }), actions: { setUserInfo(user: Partial) { Object.assign(this, user); }, clearUserInfo() { this.id = ''; this.token = ''; this.username = ''; } } }); ``` **特点**: - 类型安全的状态管理 - 响应式数据更新 - 支持状态持久化 - 模块化状态组织 ### 5. 配置层 (Config) **位置**: `src/config/` **职责**: 统一管理应用配置,包括 API 地址、用户信息、常量定义等。 ```typescript // API 基础前缀 export const API_BASE_URL = '/langgraph'; // 静态用户信息(开发阶段) export const USER_INFO: UserInfo = { id: 'user1', token: 'user1', username: 'user1', }; ``` **特点**: - 集中化配置管理 - 环境变量支持 - 类型安全的配置定义 - 易于维护和修改 ### 架构优势 1. **分层清晰**: 每层职责明确,便于维护和扩展 2. **类型安全**: 全链路 TypeScript 支持,减少运行时错误 3. **数据一致性**: 统一的数据转换层确保数据格式一致 4. **可测试性**: 各层独立,便于单元测试 5. **可扩展性**: 模块化设计,易于添加新功能 6. **错误处理**: 统一的错误处理机制,提升用户体验 ### 数据流向 ``` 用户操作 → 组件事件 → API 调用 → 数据转换 → 状态更新 → 视图更新 ↑ ↓ └─────────────── 响应式更新 ←─────────────────────────────┘ ``` 这种架构设计确保了代码的高质量、可维护性和扩展性,为后续功能开发提供了坚实的基础。 ## ✨ 核心功能 ### 会话管理 - ✅ 会话列表展示(支持时间分组) - ✅ 会话重命名(集成后端 API) - ✅ 会话删除(包含确认对话框) - ✅ 无限滚动分页加载 - ✅ **会话详情获取**(新增功能) - ✅ **智能输入清空**(新增功能) - 切换会话时自动清空输入框内容 - 自动删除已上传的文件并调用删除API - 新建会话时重置输入状态 - 删除会话时清理相关数据 ### 消息系统 - ✅ 用户消息展示 - ✅ AI 消息展示(支持思考过程显示) - ✅ 系统消息展示 - ✅ **工具消息展示**(支持搜索工具专用组件) - ✅ 消息列表滚动 - ✅ **实时消息加载**(基于会话详情) ### 文件管理(新增功能) - ✅ **文件上传**(支持单文件和批量上传) - ✅ **文件下载**(支持直接下载和保存到本地) - ✅ **文件列表**(获取用户文件列表) - ✅ **文件删除**(删除指定文件) - ✅ **分片上传**(支持大文件分片上传) - ✅ **文件验证**(类型、大小、扩展名验证) - ✅ **进度跟踪**(上传进度实时反馈) - ✅ **文件预览**(图片预览、文件信息展示) ### 用户界面 - ✅ 响应式侧边栏 - ✅ 顶部工具栏(模型选择器) - ✅ 聊天输入框(支持文件上传、自动调整高度) - ✅ 加载状态提示 ### API 集成 - ✅ 健康检查接口 - ✅ Assistants 搜索接口 - ✅ Threads 搜索/更新/删除接口 - ✅ **Thread 详情获取接口**(新增) - ✅ **流式运行接口**(新增) - ✅ **文件管理接口**(新增) ### 消息操作按钮功能(Message Actions) 新增了完整的消息操作按钮功能,为不同类型的消息提供相应的操作选项: #### 核心特性 - **智能显示**:鼠标悬停时显示操作按钮,离开时自动隐藏 - **类型区分**:AI消息和用户消息显示不同的操作按钮 - **流畅动画**:按钮显示/隐藏带有平滑的过渡动画 - **响应式设计**:适配不同屏幕尺寸,移动端优化 #### AI消息操作 - **点赞**:为AI回复点赞,激活状态显示绿色 - **点踩**:为AI回复点踩,激活状态显示红色 - **复制**:复制AI回复内容到剪贴板 - **重新生成**:基于对应的用户消息重新生成AI回复 #### 用户消息操作 - **复制**:复制用户消息内容到剪贴板 - **修改**:将用户消息内容自动填入输入框供修改 #### 组件结构 ```typescript // 消息操作按钮组件 interface MessageActionsProps { message: Message; messageType: 'ai' | 'human' | 'system' | 'tool'; isVisible?: boolean; } // 支持的事件 interface MessageActionsEmits { (e: 'like', messageId: string): void; (e: 'dislike', messageId: string): void; (e: 'copy', content: string): void; (e: 'regenerate', messageId: string): void; (e: 'edit', message: Message): void; } ``` #### 使用方式 ```vue ``` #### 功能实现 - **复制功能**:支持现代浏览器的 Clipboard API,降级到传统复制方法 - **重新生成**:自动找到对应的用户消息并重新发送 - **消息编辑**:将用户消息内容填入输入框并自动聚焦 - **状态管理**:点赞/点踩状态互斥,提供视觉反馈 #### 样式设计 - **悬停效果**:按钮悬停时轻微上移和颜色变化 - **状态颜色**:点赞绿色、点踩红色、其他操作蓝色主题 - **响应式**:移动端按钮更大,便于触摸操作 - **动画过渡**:所有状态变化都有平滑的过渡效果 #### 集成方式 - **消息组件**:在用户消息和AI消息组件中集成 - **事件传递**:通过消息列表组件传递到页面级处理 - **状态同步**:与输入框和消息发送功能无缝集成 ### 智能输入清空功能(Smart Input Clearing) 新增了智能输入清空功能,在会话切换、新建会话或删除会话时自动清理输入状态,提供更好的用户体验。 #### 核心特性 - **自动触发**:在特定操作时自动执行清空逻辑 - **完整清理**:同时清空输入框内容和已上传文件 - **API集成**:自动调用文件删除API清理服务器文件 - **错误处理**:文件删除失败时提供友好的错误提示 - **状态同步**:确保前端状态与后端数据一致 #### 触发场景 1. **切换会话**:选择不同的会话时 2. **新建会话**:点击新会话按钮时 3. **删除会话**:删除当前会话时 #### 清空内容 - **输入框文本**:清空聊天输入框中的所有文本内容 - **已上传文件**:删除所有已上传的文件(本地状态 + 服务器文件) - **上传中文件**:清空正在上传的文件列表 - **文件状态**:重置所有文件相关的状态 #### 实现原理 ##### 核心函数 ```typescript // 位置:src/composables/useMessageHandler.ts async function clearInputAndFiles() { console.log('清空输入框和文件'); // 1. 清空输入框内容 inputMessage.value = ''; // 2. 删除已上传的文件 if (uploadedFiles.value.length > 0) { const filesToDelete = [...uploadedFiles.value]; for (const file of filesToDelete) { try { // 调用删除API const userId = USER_INFO.id; await deleteFile(userId, file.name); console.log('文件删除成功:', file.name); } catch (error) { console.error('删除文件失败:', error); // 即使删除失败也继续处理其他文件 } } // 清空本地文件列表 uploadedFiles.value = []; } // 3. 清空上传中的文件列表 uploadingFiles.value = []; } ``` ##### 集成调用 ```typescript // 位置:src/views/Home.vue // 新建会话时清空 async function handleNewChat() { stopStreamAndReset(); await clearInputAndFiles(); // 自动清空 startNewChat(); clearMessages(); } // 切换会话时清空 async function handleSelectThread(thread: Thread) { stopStreamAndReset(); await clearInputAndFiles(); // 自动清空 const messages = await selectThread(thread); setMessages(messages); } // 删除会话时清空 async function confirmDeleteThread() { if (!threadToDelete.value) return; stopStreamAndReset(); await clearInputAndFiles(); // 自动清空 // ... 删除逻辑 } ``` #### 用户体验优化 - **无感知操作**:用户无需手动清理,系统自动处理 - **数据一致性**:确保前端显示与后端数据保持同步 - **错误容错**:单个文件删除失败不影响整体流程 - **性能优化**:异步处理文件删除,不阻塞界面操作 #### 技术细节 - **异步处理**:使用 `async/await` 确保文件删除完成 - **错误隔离**:单个文件删除失败不影响其他文件 - **状态管理**:通过 Composition API 统一管理状态 - **API集成**:调用 `deleteFile` API 删除服务器文件 #### 配置选项 ```typescript // 文件删除API配置 const userId = USER_INFO.id; // 用户ID await deleteFile(userId, file.name); // 根据文件名删除 // 支持的文件操作 - uploadedFiles.value = []; // 清空已上传文件列表 - uploadingFiles.value = []; // 清空上传中文件列表 - inputMessage.value = ''; // 清空输入框内容 ``` #### 错误处理 - **网络错误**:文件删除API调用失败时的处理 - **权限错误**:用户无权限删除文件时的提示 - **文件不存在**:服务器文件已被删除的情况处理 - **批量处理**:多个文件删除时的错误隔离 这个功能大大提升了用户体验,避免了在切换会话时需要手动清理输入内容和文件的繁琐操作,同时确保了数据的一致性和系统的稳定性。 ### 智能文件消息处理(Smart File Message Handling) 新增了智能文件消息处理功能,当用户上传文件后发送消息时,系统会自动发送两条消息:系统消息(包含文件详细信息)和用户消息(包含用户输入的文本)。 #### 核心特性 - **双消息机制**:自动发送系统消息和用户消息 - **详细文件信息**:系统消息包含完整的文件元数据 - **真实路径**:使用服务器返回的实际文件路径,确保可访问性 - **美观显示**:系统消息采用特殊样式突出显示 - **API优化**:向模型发送结构化的文件信息 - **一次性文件消息**:只在首次发送时包含文件信息,避免重复发送 - **即时清理**:发送消息后立即清空输入框和文件显示,提升用户体验 - **智能清理**:发送消息后自动清空文件显示,切换会话时不删除服务器文件 - **会话隔离**:切换会话时不删除服务器文件,只清空显示 #### 消息发送逻辑 ##### 有文件上传时的消息流程 1. **系统消息**:包含所有上传文件的详细信息 2. **用户消息**:包含用户输入的文本内容 ##### 系统消息内容格式 ```typescript // 发送给AI模型的系统消息 const systemMessageContent = `用户上传了以下文件: 文件 1: - 文件名: document.pdf - 文件大小: 2.5 MB - 文件类型: pdf - 文件ID: 123e4567-e89b-12d3-a456-426614174000 - 上传时间: 2024-01-01T12:00:00.000Z - 文件路径: /deps/react-agent/user_files/chenlexiang/document_8l3jsd4hb.pdf 请根据用户上传的文件内容和后续的用户消息进行回复。`; ``` ##### 用户界面显示 ```typescript // 原始系统消息(发送给AI) const systemMessage = `用户上传了以下文件: 文件 1: - 文件名: 31-53汇总表-12723本(1)_jq1zrm9nf.xlsx - 文件大小: 4.09 MB - 文件类型: xlsx ...`; // 用户界面显示(智能格式化后) const displayMessage = `成功上传:31-53汇总表-12723本(1).xlsx`; // 多文件示例 const multiFileDisplay = `成功上传:文档1.pdf、表格2.xlsx、图片3.png`; ``` #### 实现细节 ##### 消息构建逻辑 ```typescript // 位置:src/composables/useMessageHandler.ts async function sendMessage(message: string, ...) { const apiMessages: Array<{ role: string; content: string }> = []; // 1. 如果有文件,先添加系统消息 if (uploadedFiles.value.length > 0) { const fileInfoList = uploadedFiles.value.map(file => ({ filename: file.name, size: file.size, extension: file.extension, id: file.id, uploadTime: file.uploadTime || new Date().toISOString(), // 使用上传响应中的完整路径 fullPath: file.fullPath || `/files/${USER_INFO.id}/${file.name}` })); // 构建详细的系统消息 const systemMessageContent = `用户上传了以下文件:...`; apiMessages.push({ role: 'system', content: systemMessageContent }); // 添加简化的显示消息 const systemMessage: Message = { id: `system-${Date.now()}`, type: 'system', content: `已上传 ${uploadedFiles.value.length} 个文件:${uploadedFiles.value.map(f => f.name).join(', ')}` }; addMessage(systemMessage); } // 2. 添加用户消息 if (userMessageContent) { apiMessages.push({ role: 'user', content: userMessageContent }); const userMessage: Message = { id: `user-${Date.now()}`, type: 'human', content: userMessageContent }; addMessage(userMessage); } // 3. 发送消息后立即清空输入框和文件显示 inputMessage.value = ''; uploadedFiles.value = []; } ``` #### 文件信息结构 - **文件名**:原始文件名 - **文件大小**:格式化的文件大小(如 2.5 MB) - **文件类型**:文件扩展名 - **文件ID**:唯一标识符 - **上传时间**:ISO格式的时间戳 - **文件路径**:上传响应中的 `full_path` 完整路径 #### 用户体验优化 - **视觉区分**:系统消息采用特殊的蓝色渐变背景 - **图标标识**:文件上传消息显示附件图标 - **信息精简**:界面显示简化信息,详细信息发送给AI - **智能格式化**:自动将详细文件信息格式化为简洁的文件名列表 - **ID自动去除**:自动去除文件名中的唯一标识符,显示原始文件名 - **响应式设计**:适配不同屏幕尺寸 #### 样式设计 ```scss // 文件上传系统消息的特殊样式 .system-content.file-upload-message { background: linear-gradient(135deg, #e8f4fd 0%, #f0f9ff 100%); border-color: var(--td-brand-color-light); color: var(--td-brand-color); font-weight: 500; .file-icon { color: var(--td-brand-color); font-size: 14px; } } ``` #### 技术优势 - **结构化信息**:AI模型接收到完整的文件元数据 - **真实路径**:使用服务器返回的实际文件路径,确保可访问性 - **类型安全**:完整的TypeScript类型支持 - **即时清理**:发送消息后立即清空输入框和文件显示,提升用户体验 - **一次性消息**:避免重复发送文件信息,减少API调用开销 - **智能清理**:发送消息后自动清空文件显示,切换会话时不删除服务器文件 - **错误处理**:支持仅文件或仅文本的消息发送 - **状态管理**:统一的消息状态管理 这个功能让AI模型能够更好地理解用户上传的文件,并根据文件信息提供更准确的回复。同时,用户界面保持简洁,只显示必要的文件信息。 #### 智能格式化功能 系统消息组件具备智能识别和格式化能力,能够自动处理不同类型的文件上传消息: ##### 消息类型识别 - **详细文件消息**:包含完整文件信息的系统消息(发送给AI) - **简化文件消息**:已经格式化的简洁消息(直接显示) ##### 格式化处理 ```typescript // 位置:src/components/comp-system-message.vue const displayMessage = computed(() => { // 1. 检测是否为详细文件消息 if (isDetailedFileMessage.value) { // 2. 提取文件名 const fileNameRegex = /- 文件名:\s*([^\r\n-]+)/g; // 3. 去除唯一ID fileName = fileName.replace(/_[a-z0-9]+(\.[a-zA-Z0-9]+)?$/i, (match, ext) => ext || ''); // 4. 格式化显示 return `成功上传:${fileNames.join('、')}`; } return props.message.content; }); ``` ##### 处理规则 - **文件名提取**:使用正则表达式精确匹配 `- 文件名:` 后的内容 - **ID去除**:自动识别并移除文件名末尾的唯一标识符(如 `_jq1zrm9nf`) - **多文件支持**:自动处理多个文件,用中文顿号分隔 - **容错处理**:解析失败时显示原始内容,确保信息不丢失 #### 技术优势