# 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`)
- **多文件支持**:自动处理多个文件,用中文顿号分隔
- **容错处理**:解析失败时显示原始内容,确保信息不丢失
#### 技术优势