页面结构修改
This commit is contained in:
1 parent
efc4d89fdf
commit
2e4bdf122e
21 files changed
+1266
-133
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,140 @@
|
||||
# App.tsx 路由与页面结构重构需求(首页与业务页分离)
|
||||
|
||||
## 一、需求背景
|
||||
|
||||
当前 `frontend-web/src/App.tsx` 同时承载了:
|
||||
|
||||
1. 登录/首页相关路由(如 `/login`、`/landing`)
|
||||
2. 工作台业务相关路由(如 `/workspace/chats`、`/workspace/agents`、`/workspace/scheduled/*`)
|
||||
3. 业务页所需布局与运行时包装(`WorkspaceLayout`、`ChatRuntime`)
|
||||
|
||||
这会导致 `App.tsx` 过重,职责不够单一,不利于后续维护和扩展。
|
||||
|
||||
---
|
||||
|
||||
## 二、目标(你提出的核心诉求)
|
||||
|
||||
你希望:
|
||||
|
||||
1. **除了登录与首页入口内容外**,将 `App.tsx` 中其余业务页面路由整体迁移到 `pages` 下一个新组件中。
|
||||
2. 再创建一个“承接导航/入口”的页面(或路由容器),用于放置这些导航逻辑。
|
||||
3. `App.tsx` 最终只保留顶层路由分发和基础 Provider,变得更薄。
|
||||
|
||||
> 你提到“`App.tsx 74-75 login`”,可理解为:保留登录/首页相关入口,其他工作台内容抽离。
|
||||
|
||||
---
|
||||
|
||||
## 三、重构范围
|
||||
|
||||
### 1)保留在 `App.tsx` 的内容
|
||||
|
||||
- 全局 Provider:`HashRouter`、`AppProviders`
|
||||
- 登录/首页路由:
|
||||
- `/`
|
||||
- `/login`
|
||||
- `/login/:username`
|
||||
- `/landing`
|
||||
- 404 路由(可留在 `App.tsx` 或交给新路由容器统一处理,二选一)
|
||||
|
||||
### 2)迁移出 `App.tsx` 的内容
|
||||
|
||||
将以下与工作台有关的路由从 `App.tsx` 抽离:
|
||||
|
||||
- `/workspace`(重定向)
|
||||
- `/workspace/chats`
|
||||
- `/workspace/chats/:thread_id`
|
||||
- `/workspace/agents`
|
||||
- `/workspace/agents/new`
|
||||
- `/workspace/agents/:agent_id/chats`(重定向)
|
||||
- `/workspace/agents/:agent_id/chats/:thread_id`
|
||||
- `/workspace/scheduled`
|
||||
- `/workspace/scheduled/tasks`
|
||||
- `/workspace/scheduled/runs/:run_id`
|
||||
|
||||
以及配套的包装组件职责:
|
||||
|
||||
- `WorkspaceLayout`
|
||||
- `ChatRuntime`
|
||||
|
||||
---
|
||||
|
||||
## 四、建议的新结构(方案)
|
||||
|
||||
## 方案 A(推荐):新增“业务路由容器组件”
|
||||
|
||||
在 `pages` 下新增一个路由容器组件,例如:
|
||||
|
||||
- `src/pages/WorkspaceRoutes.tsx`(或 `src/pages/AppWorkspaceRoutes.tsx`)
|
||||
|
||||
职责:
|
||||
- 专门维护 `/workspace/*` 相关路由
|
||||
- 内部统一使用 `WorkspaceLayout` 与 `ChatRuntime`
|
||||
- 输出一个可被 `App.tsx` 挂载的路由节点
|
||||
|
||||
同时在 `App.tsx` 里只保留:
|
||||
- 登录/首页/404
|
||||
- 一个 `Route path="/workspace/*" element={<WorkspaceRoutes />} />`
|
||||
|
||||
---
|
||||
|
||||
## 五、“再建立一个页面放置导航”的落地解释
|
||||
|
||||
你说的“建立一个页面放置这些导航”,可以有两种理解:
|
||||
|
||||
1. **路由容器页(推荐)**:
|
||||
- 不强调视觉 UI,重点是集中管理导航与路由跳转规则。
|
||||
- 即上面的 `WorkspaceRoutes.tsx`。
|
||||
|
||||
2. **可见的导航页(可选)**:
|
||||
- 例如新建 `WorkspaceHomePage.tsx`,展示聊天/Agents/定时任务入口按钮。
|
||||
- 路由上把 `/workspace` 指向该页,而不是直接重定向到 `/workspace/chats/new`。
|
||||
|
||||
当前从你的描述看,优先建议第 1 种(先做结构整理),之后若有产品需求再做第 2 种可见导航页。
|
||||
|
||||
---
|
||||
|
||||
## 六、实施步骤(开发任务拆解)
|
||||
|
||||
1. 新建 `WorkspaceRoutes` 组件(`pages` 目录下)。
|
||||
2. 把所有 `/workspace/*` 路由从 `App.tsx` 搬入该组件。
|
||||
3. 把 `WorkspaceLayout` 与 `ChatRuntime` 移入该组件(或抽到共享 layout/runtime 文件)。
|
||||
4. 在 `App.tsx` 中保留登录/首页路由,并挂载 `/workspace/*` 到新组件。
|
||||
5. 校验以下访问路径行为一致:
|
||||
- `/workspace` 重定向
|
||||
- chats/agents/scheduled 各页面可正常进入
|
||||
- 动态参数路由(`thread_id`、`agent_id`、`run_id`)正常
|
||||
- 404 不受影响
|
||||
6. 运行前端并做手工回归。
|
||||
|
||||
---
|
||||
|
||||
## 七、验收标准
|
||||
|
||||
1. `App.tsx` 明显瘦身,主要负责顶层入口路由。
|
||||
2. `/workspace/*` 全部由新建组件统一管理。
|
||||
3. 功能行为与改造前一致(或符合新定义)。
|
||||
4. 代码可读性提升:登录入口与业务入口职责分离。
|
||||
|
||||
---
|
||||
|
||||
## 八、注意事项
|
||||
|
||||
1. 当前项目使用 `HashRouter`,路由写法需保持兼容。
|
||||
2. `Navigate` 重定向逻辑要完整迁移,避免出现死循环或空白页。
|
||||
3. `WorkspaceLayout` 与 `ChatRuntime` 的包裹层级不能错,否则可能影响侧边栏、输入区、子任务/Artifacts 状态。
|
||||
4. 若后续再加模块(例如 `/workspace/settings`),优先在 `WorkspaceRoutes` 中扩展。
|
||||
|
||||
---
|
||||
|
||||
## 九、建议的命名(可直接采用)
|
||||
|
||||
- 新增组件文件:`src/pages/WorkspaceRoutes.tsx`
|
||||
- (可选)可见导航页:`src/pages/WorkspaceHomePage.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 十、后续可选优化
|
||||
|
||||
1. 将 `WorkspaceLayout` 抽到 `src/layouts/WorkspaceLayout.tsx`。
|
||||
2. 将 `ChatRuntime` 抽到 `src/runtime/ChatRuntime.tsx`。
|
||||
3. 把路由常量集中到 `src/core/router/paths.ts`,减少硬编码路径。
|
||||
@@ -0,0 +1,975 @@
|
||||
# DeerFlow 前端开发文档
|
||||
|
||||
## 目录
|
||||
|
||||
1. [整体目录结构](#1-整体目录结构)
|
||||
2. [路由结构](#2-路由结构)
|
||||
3. [核心数据流与状态管理](#3-核心数据流与状态管理)
|
||||
4. [主要页面组件](#4-主要页面组件)
|
||||
5. [核心业务组件](#5-核心业务组件)
|
||||
6. [核心 Hooks 与工具函数](#6-核心-hooks-与工具函数)
|
||||
7. [API 调用层](#7-api-调用层)
|
||||
8. [国际化机制](#8-国际化机制)
|
||||
9. [主题与样式体系](#9-主题与样式体系)
|
||||
10. [关键业务流程](#10-关键业务流程)
|
||||
11. [项目配置与依赖](#11-项目配置与依赖)
|
||||
12. [常见开发模式](#12-常见开发模式)
|
||||
|
||||
---
|
||||
|
||||
## 1. 整体目录结构
|
||||
|
||||
```
|
||||
frontend-web/src/
|
||||
├── App.tsx # 应用入口,顶层路由 + Provider
|
||||
├── env.ts # 环境变量类型定义
|
||||
├── pages/ # 路由级页面组件
|
||||
│ ├── PageRoutes.tsx # /page/* 根路由容器(含外部系统预留位)
|
||||
│ ├── WorkspaceRoutes.tsx # /page/workspace/* 工作区路由
|
||||
│ ├── LoginPage.tsx # 登录页
|
||||
│ ├── LandingPage.tsx # 营销落地页(强制 dark 主题)
|
||||
│ ├── ChatsPage.tsx # 对话列表
|
||||
│ ├── ChatPage.tsx # 单条对话(核心页面)
|
||||
│ ├── AgentsPage.tsx # 智能体库
|
||||
│ ├── AgentChatPage.tsx # 与智能体对话
|
||||
│ ├── NewAgentPage.tsx # 创建智能体(两步流程)
|
||||
│ ├── ScheduledTasksPage.tsx # 定时任务管理
|
||||
│ ├── ScheduledTaskRunDetailPage.tsx # 定时任务执行详情
|
||||
│ ├── ScheduledChatPage.tsx # 定时任务对话跳转页
|
||||
│ └── NotFoundPage.tsx # 404 页面
|
||||
├── components/ # 业务组件库
|
||||
│ ├── ui/ # shadcn/ui 基础组件(Button、Card、Dialog 等 40+)
|
||||
│ ├── ai-elements/ # AI 交互可视化组件
|
||||
│ │ ├── prompt-input/ # 输入框 Context + 子组件系统
|
||||
│ │ ├── artifact.tsx # 制品展示
|
||||
│ │ ├── canvas.tsx
|
||||
│ │ ├── conversation.tsx # 虚拟滚动对话容器
|
||||
│ │ ├── message.tsx
|
||||
│ │ ├── model-selector.tsx
|
||||
│ │ ├── code-block.tsx
|
||||
│ │ └── shimmer.tsx
|
||||
│ ├── workspace/ # 工作区业务组件(详见第 5 节)
|
||||
│ └── landing/ # 落地页组件
|
||||
├── core/ # 核心业务逻辑层(非 UI)
|
||||
│ ├── api/ # API 客户端(LangGraph SDK + Fetch)
|
||||
│ ├── auth/ # 认证管理
|
||||
│ ├── config/ # 环境配置 & Base URL
|
||||
│ ├── i18n/ # 国际化(上下文、翻译文件、语言检测)
|
||||
│ ├── threads/ # 对话线程管理(最核心)
|
||||
│ ├── agents/ # 智能体 CRUD
|
||||
│ ├── models/ # 模型列表
|
||||
│ ├── settings/ # 本地设置(LocalStorage 发布订阅)
|
||||
│ ├── uploads/ # 文件上传
|
||||
│ ├── artifacts/ # 制品管理
|
||||
│ ├── memory/ # 用户记忆
|
||||
│ ├── skills/ # 技能管理
|
||||
│ ├── scheduled-tasks/ # 定时任务
|
||||
│ ├── messages/ # 消息处理工具函数
|
||||
│ ├── tasks/ # 子任务 Context
|
||||
│ ├── notification/ # 系统通知
|
||||
│ └── utils/ # 通用工具(文件下载、日期格式化等)
|
||||
└── hooks/ # 全局自定义 hooks
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 路由结构
|
||||
|
||||
> 项目使用 **HashRouter**,所有路由访问形如 `http://host/#/xxx`
|
||||
|
||||
### 2.1 App.tsx 顶层路由
|
||||
|
||||
| 路径 | 组件 | 说明 |
|
||||
|------|------|------|
|
||||
| `/` | Navigate | 重定向到 `/login` |
|
||||
| `/login` | LoginPage | 登录(自动登录,无表单) |
|
||||
| `/login/:username` | LoginPage | 带用户名登录 |
|
||||
| `/landing` | LandingPage | 营销落地页(固定 dark 主题) |
|
||||
| `/page/*` | PageRoutes | 应用内容根容器 |
|
||||
| `*` | NotFoundPage | 404 |
|
||||
|
||||
### 2.2 PageRoutes.tsx(`/page/*`)
|
||||
|
||||
```
|
||||
/page/
|
||||
├── index → Navigate to "workspace"
|
||||
├── workspace/* → WorkspaceRoutes
|
||||
└── [TODO 预留] → 外部系统路由挂载位置
|
||||
```
|
||||
|
||||
### 2.3 WorkspaceRoutes.tsx(`/page/workspace/*`)
|
||||
|
||||
| 路径 | 页面组件 | 布局包裹 |
|
||||
|------|---------|--------|
|
||||
| `index` | Navigate → `chats/new` | - |
|
||||
| `chats` | ChatsPage | WorkspaceLayout |
|
||||
| `chats/:thread_id` | ChatPage | WorkspaceLayout + ChatRuntime |
|
||||
| `agents` | AgentsPage | WorkspaceLayout |
|
||||
| `agents/new` | NewAgentPage | WorkspaceLayout |
|
||||
| `agents/:agent_id/chats` | Navigate → `/page/workspace/agents` | - |
|
||||
| `agents/:agent_id/chats/:thread_id` | AgentChatPage | WorkspaceLayout + ChatRuntime |
|
||||
| `scheduled` | Navigate → `.../scheduled/tasks` | - |
|
||||
| `scheduled/tasks` | ScheduledTasksPage | WorkspaceLayout |
|
||||
| `scheduled/runs/:run_id` | ScheduledTaskRunDetailPage | WorkspaceLayout |
|
||||
|
||||
### 2.4 布局 Provider 层级结构
|
||||
|
||||
```
|
||||
WorkspaceLayout
|
||||
├── SidebarProvider(侧边栏展开/收起状态)
|
||||
│ ├── WorkspaceSidebar
|
||||
│ │ ├── WorkspaceHeader(Logo、新建按钮)
|
||||
│ │ ├── WorkspaceNavChatList(Chats / Agents / Scheduled 导航)
|
||||
│ │ ├── RecentChatList(最近会话列表)
|
||||
│ │ └── WorkspaceNavMenu(Settings / About / GitHub)
|
||||
│ ├── SidebarInset(主内容区)
|
||||
│ │ └── [Page Content]
|
||||
│ ├── CommandPalette(快捷命令面板)
|
||||
│ └── Toaster(全局通知)
|
||||
|
||||
ChatRuntime(仅 ChatPage / AgentChatPage 使用)
|
||||
├── SubtasksProvider(子任务执行状态)
|
||||
├── ArtifactsProvider(制品选中/打开状态)
|
||||
└── PromptInputProvider(输入框内容/附件状态)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心数据流与状态管理
|
||||
|
||||
### 3.1 全局 Provider 架构
|
||||
|
||||
```
|
||||
App
|
||||
└── HashRouter
|
||||
└── AppProviders(useLocation 驱动主题判断)
|
||||
├── NextThemesProvider
|
||||
│ └── attribute="class",/landing 强制 forcedTheme="dark"
|
||||
├── I18nProvider
|
||||
│ └── initialLocale = detectLocale()(从 cookie 或浏览器语言)
|
||||
└── QueryClientProvider(TanStack React Query 全局缓存)
|
||||
```
|
||||
|
||||
### 3.2 全局 Context 列表
|
||||
|
||||
| Context | 文件 | 职责 | 消费 Hook |
|
||||
|---------|------|------|-----------|
|
||||
| `I18nContext` | `core/i18n/context.tsx` | 当前语言 + 翻译对象 | `useI18n()` |
|
||||
| `SubtaskContext` | `core/tasks/context.tsx` | 实时子任务执行状态 | `useSubtaskContext()` |
|
||||
| `ArtifactsContext` | `components/workspace/artifacts/context.tsx` | 制品选中/面板开关 | `useArtifacts()` |
|
||||
| `PromptInputContext` | `components/ai-elements/prompt-input/` | 输入框内容、附件列表 | `usePromptInputController()` |
|
||||
| `ThreadContext` | `components/workspace/messages/context.tsx` | 当前 thread 对象下传 | 直接读 context.thread |
|
||||
|
||||
### 3.3 LocalStorage 数据
|
||||
|
||||
**操作层:** `core/settings/store.ts`(发布-订阅,`useSyncExternalStore` 驱动响应式)
|
||||
|
||||
| Key | 内容 |
|
||||
|-----|------|
|
||||
| `deerflow.auth` | `{ access_token, token_type, user_id, email }` |
|
||||
| `deerflow.local-settings` | `{ notification, context: { model_name, mode, reasoning_effort } }` |
|
||||
| `deerflow.thread-model.{threadId}` | 每条线程的模型覆盖 |
|
||||
|
||||
### 3.4 SessionStorage 数据
|
||||
|
||||
| Key | 内容 |
|
||||
|-----|------|
|
||||
| `deerflow.run-id.{threadId}` | WebSocket run_id,用于断线重连 |
|
||||
|
||||
### 3.5 React Query 缓存 Key
|
||||
|
||||
| Query Key | 数据 |
|
||||
|-----------|------|
|
||||
| `["threads"]` | 线程列表 |
|
||||
| `["thread", threadId]` | 单条线程 |
|
||||
| `["agents"]` | 智能体列表 |
|
||||
| `["models"]` | 模型列表 |
|
||||
| `["skills"]` | 技能列表 |
|
||||
| `["memory"]` | 用户记忆 |
|
||||
| `["scheduled-tasks"]` | 定时任务列表 |
|
||||
| `["scheduled-runs", taskId]` | 任务执行记录 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 主要页面组件
|
||||
|
||||
### 4.1 ChatPage.tsx — 单条对话页面
|
||||
|
||||
**职责:** 管理单条聊天线程的完整交互,包括消息流、输入、工具调用展示、制品等。
|
||||
|
||||
**关键状态:**
|
||||
|
||||
```typescript
|
||||
const [threadId, setThreadId] = useState(routeThreadId || uuid());
|
||||
const [isNewThread, setIsNewThread] = useState(!routeThreadId || routeThreadId === "new");
|
||||
const [hasStartedConversation, setHasStartedConversation] = useState(false);
|
||||
const [showFollowups, setShowFollowups] = useState(false);
|
||||
const [settings, setSettings] = useThreadSettings(threadId);
|
||||
```
|
||||
|
||||
**核心 Hook:**
|
||||
|
||||
```typescript
|
||||
const [thread, sendMessage, isUploading] = useThreadStream({
|
||||
threadId: isNewThread ? undefined : threadId,
|
||||
context: settings.context,
|
||||
onStart: (createdThreadId) => {
|
||||
setThreadId(createdThreadId);
|
||||
setIsNewThread(false);
|
||||
// 不刷新页面,直接更新 URL hash
|
||||
history.replaceState(null, "", `...#/page/workspace/chats/${createdThreadId}`);
|
||||
},
|
||||
onFinish: (state) => {
|
||||
// 后台通知
|
||||
showNotification(state.title, { body: lastMessageText });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**主要子组件:**
|
||||
|
||||
| 组件 | 职责 |
|
||||
|------|------|
|
||||
| `<MessageList>` | 消息渲染(含工具调用、子任务、制品) |
|
||||
| `<Welcome>` | 新对话欢迎屏 |
|
||||
| `<InputBox>` | 输入框(模式选择、附件、发送) |
|
||||
| `<ThreadTitle>` | 线程标题(自动生成后同步更新) |
|
||||
| `<ExportTrigger>` | 导出对话按钮 |
|
||||
| `<ArtifactTrigger>` | 制品面板开关 |
|
||||
| `<TokenUsageIndicator>` | Token 用量展示(可选) |
|
||||
| `<TodoList>` | 任务清单 |
|
||||
| `<Suggestions>` | 追问建议 |
|
||||
|
||||
**数据流:**
|
||||
|
||||
```
|
||||
用户输入 (InputBox)
|
||||
↓ handleSubmit(message: PromptInputMessage)
|
||||
↓ sendMessage(threadId, message)
|
||||
↓ [内部] 上传文件 → 提交到 LangGraph API
|
||||
↓ WebSocket 流返回消息
|
||||
↓ thread.messages 更新 → MessageList 重渲染
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2 AgentChatPage.tsx — 与智能体对话
|
||||
|
||||
与 ChatPage 结构基本一致,差异点:
|
||||
|
||||
- 从路由获取 `agent_id`,传入 `useThreadStream({ assistantId: agent_id })`
|
||||
- Header 展示智能体名称 Badge
|
||||
- "新建对话"跳转到 `/page/workspace/agents/${agent_id}/chats/new`
|
||||
- URL 更新为 `#/page/workspace/agents/${agent_id}/chats/${threadId}`
|
||||
|
||||
---
|
||||
|
||||
### 4.3 NewAgentPage.tsx — 创建智能体(两步流程)
|
||||
|
||||
**Step 1:name(命名 + 选技能)**
|
||||
|
||||
```typescript
|
||||
// 自动预选前 3 个启用的技能
|
||||
useEffect(() => {
|
||||
if (!isSkillSelectionTouched) {
|
||||
setSelectedSkills(enabledSkills.slice(0, 3).map(s => s.name));
|
||||
}
|
||||
}, [enabledSkills]);
|
||||
|
||||
// 提交:验证名称 → 创建智能体
|
||||
await checkAgentName(name); // 检查重名
|
||||
await createAgent(request); // 创建,返回 agent.id
|
||||
setStep("chat"); // 进入 Step 2
|
||||
```
|
||||
|
||||
**Step 2:chat(初始化对话)**
|
||||
|
||||
```typescript
|
||||
// 发送 bootstrap 消息触发智能体初始化
|
||||
sendMessage(threadId, bootstrapMessage, { agent_id: agentId });
|
||||
|
||||
// 监听 setup_agent 工具完成事件
|
||||
onToolEnd: (event) => {
|
||||
if (event.name === "setup_agent") {
|
||||
// 带重试轮询加载 agent 最新信息
|
||||
retryLoadAgent(agentId);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.4 ChatsPage.tsx — 对话列表
|
||||
|
||||
```typescript
|
||||
const { data: threads } = useThreads({ limit: 50, sortBy: "updated_at" });
|
||||
|
||||
// 客户端过滤:排除定时任务线程 + 搜索关键词
|
||||
const filteredThreads = useMemo(() =>
|
||||
threads?.filter(t =>
|
||||
t.metadata?.thread_type !== "scheduler" &&
|
||||
titleOfThread(t).toLowerCase().includes(search)
|
||||
), [threads, search]
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.5 LoginPage.tsx — 登录
|
||||
|
||||
```typescript
|
||||
// 自动登录,无需用户操作
|
||||
useEffect(() => {
|
||||
loginByUsername(username || "guest")
|
||||
.then(auth => {
|
||||
setStoredAuth(auth);
|
||||
router.replace("/page/workspace/chats/new");
|
||||
})
|
||||
.catch(err => setStatus("error"));
|
||||
}, [username]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.6 ScheduledTasksPage.tsx — 定时任务
|
||||
|
||||
**功能:** 创建/编辑/发布/暂停/恢复定时任务,查看执行历史。
|
||||
|
||||
**Cron 表达式构建:**
|
||||
|
||||
```typescript
|
||||
type ScheduleFreq = "hourly" | "daily" | "weekly" | "monthly";
|
||||
|
||||
function buildCron(config): string {
|
||||
// hourly → "15 * * * *"
|
||||
// daily → "0 9 * * *"
|
||||
// weekly → "0 9 * * 1"
|
||||
// monthly → "0 9 1 * *"
|
||||
}
|
||||
```
|
||||
|
||||
**核心操作:**
|
||||
|
||||
```typescript
|
||||
const actions = useScheduledTaskActions();
|
||||
actions.create.mutateAsync(payload);
|
||||
actions.publish.mutateAsync(taskId);
|
||||
actions.pause.mutateAsync(taskId);
|
||||
actions.trigger.mutateAsync(taskId); // 立即执行一次
|
||||
actions.subscribe.mutateAsync(params); // 订阅推送
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心业务组件
|
||||
|
||||
### 5.1 消息系统(`components/workspace/messages/`)
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `message-list.tsx` | 消息列表容器,调用 `groupMessages` 分组后渲染 |
|
||||
| `message-list-item.tsx` | 单条消息渲染(含 role 判断) |
|
||||
| `message-group.tsx` | 消息组(human / assistant / processing 等) |
|
||||
| `markdown-content.tsx` | Markdown 渲染(rehype 系列插件) |
|
||||
| `subtask-card.tsx` | 子任务状态卡片 |
|
||||
| `message-token-usage.tsx` | 单条消息 Token 用量 |
|
||||
| `skeleton.tsx` | 流式加载骨架屏 |
|
||||
| `context.tsx` | ThreadContext,向下传递 thread 对象 |
|
||||
|
||||
**消息分组类型(`groupMessages`):**
|
||||
|
||||
```typescript
|
||||
type MessageGroup =
|
||||
| "human" // 用户输入
|
||||
| "assistant:processing" // 推理/工具调用中
|
||||
| "assistant" // 最终响应
|
||||
| "assistant:clarification" // 澄清请求
|
||||
| "assistant:present-files" // 文件呈现
|
||||
| "assistant:subagent"; // 子智能体消息
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.2 输入框(`components/workspace/input-box.tsx`)
|
||||
|
||||
**子组件层级:**
|
||||
|
||||
```
|
||||
InputBox
|
||||
└── PromptInput(Context Provider)
|
||||
├── PromptInputBody
|
||||
│ ├── PromptInputTextarea(文本输入)
|
||||
│ ├── PromptInputAttachments(附件列表)
|
||||
│ └── PromptInputTools(工具栏:附件上传、模式选择)
|
||||
├── PromptInputFooter
|
||||
│ ├── PromptInputSubmit(发送/停止按钮)
|
||||
│ └── Suggestions(追问建议列表)
|
||||
└── ModelSelector(模型下拉选择)
|
||||
```
|
||||
|
||||
**四种会话模式:**
|
||||
|
||||
| Mode | 说明 |
|
||||
|------|------|
|
||||
| `flash` | 快速模式,无推理步骤 |
|
||||
| `thinking` | 推理模式,开启深度思考 |
|
||||
| `pro` | 专业模式,多模态 + 规划 |
|
||||
| `ultra` | 超级模式,启用子智能体 |
|
||||
|
||||
**推理努力等级(mode ≠ flash 时可选):** `minimal` / `low` / `medium` / `high`
|
||||
|
||||
---
|
||||
|
||||
### 5.3 侧边栏(`components/workspace/workspace-sidebar.tsx`)
|
||||
|
||||
```
|
||||
WorkspaceSidebar
|
||||
├── SidebarHeader → WorkspaceHeader
|
||||
│ ├── Logo(可点击,跳转 /page/workspace/chats/new)
|
||||
│ └── 新建对话按钮
|
||||
├── SidebarContent
|
||||
│ ├── WorkspaceNavChatList
|
||||
│ │ ├── 新建对话(/page/workspace/chats/new)
|
||||
│ │ ├── 所有对话(/page/workspace/chats)
|
||||
│ │ ├── 智能体(/page/workspace/agents)
|
||||
│ │ └── 任务管理(/page/workspace/scheduled/tasks)
|
||||
│ └── RecentChatList(最近会话,含搜索)
|
||||
└── SidebarFooter → WorkspaceNavMenu
|
||||
├── Settings(打开设置 Dialog)
|
||||
├── About
|
||||
└── GitHub
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.4 制品管理(`components/workspace/artifacts/`)
|
||||
|
||||
```typescript
|
||||
interface ArtifactsContextType {
|
||||
artifacts: string[]; // artifact ID 列表
|
||||
selectedArtifact: string | null;
|
||||
autoSelect: boolean; // 是否自动选中最新制品
|
||||
open: boolean; // 面板是否展开
|
||||
autoOpen: boolean;
|
||||
select(artifact: string, autoSelect?: boolean): void;
|
||||
deselect(): void;
|
||||
setOpen(open: boolean): void;
|
||||
}
|
||||
```
|
||||
|
||||
**文件:**
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `context.tsx` | ArtifactsContext + Provider |
|
||||
| `artifact-trigger.tsx` | 面板展开/收起按钮 |
|
||||
| `artifact-file-list.tsx` | 制品文件列表 |
|
||||
| `artifact-file-detail.tsx` | 单个制品详情(含代码编辑器) |
|
||||
|
||||
---
|
||||
|
||||
### 5.5 设置面板(`components/workspace/settings/`)
|
||||
|
||||
| 页面文件 | 内容 |
|
||||
|---------|------|
|
||||
| `appearance-settings-page.tsx` | 主题切换(light/dark/system)、语言切换 |
|
||||
| `memory-settings-page.tsx` | 用户记忆(事实列表、总结管理) |
|
||||
| `notification-settings-page.tsx` | 桌面通知开关 |
|
||||
| `skill-settings-page.tsx` | 技能启用/禁用 |
|
||||
| `tool-settings-page.tsx` | 工具配置 |
|
||||
| `about-settings-page.tsx` | 版本号、仓库链接 |
|
||||
|
||||
---
|
||||
|
||||
### 5.6 命令面板(`components/workspace/command-palette.tsx`)
|
||||
|
||||
通过 `Cmd/Ctrl + K` 触发,提供快速导航和操作入口。
|
||||
|
||||
```typescript
|
||||
const handleNewChat = useCallback(() => {
|
||||
router.push("/page/workspace/chats/new");
|
||||
setOpen(false);
|
||||
}, [router]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 核心 Hooks 与工具函数
|
||||
|
||||
### 6.1 useThreadStream(最核心 Hook)
|
||||
|
||||
**位置:** `core/threads/hooks.ts`
|
||||
|
||||
管理 LangGraph WebSocket 连接、消息流、乐观更新。
|
||||
|
||||
**签名:**
|
||||
|
||||
```typescript
|
||||
const [thread, sendMessage, isUploading] = useThreadStream({
|
||||
threadId?: string, // 有值则连接现有线程,无值表示新建
|
||||
context: LocalSettings["context"], // 模型、模式等
|
||||
isMock?: boolean,
|
||||
assistantId?: string, // 默认 "lead_agent"
|
||||
onStart?: (threadId: string) => void,
|
||||
onFinish?: (state: AgentThreadState) => void,
|
||||
onToolEnd?: (event: ToolEndEvent) => void,
|
||||
});
|
||||
```
|
||||
|
||||
**thread 对象关键属性:**
|
||||
|
||||
```typescript
|
||||
thread: {
|
||||
messages: Message[], // 含乐观消息的完整列表
|
||||
isLoading: boolean, // 流是否进行中
|
||||
isThreadLoading: boolean, // 初始线程数据是否加载中
|
||||
values: AgentThreadState, // 线程最终状态
|
||||
error?: Error,
|
||||
stop: async () => void, // 终止当前流
|
||||
}
|
||||
```
|
||||
|
||||
**sendMessage 签名:**
|
||||
|
||||
```typescript
|
||||
sendMessage(
|
||||
threadId: string | undefined,
|
||||
message: PromptInputMessage,
|
||||
extraContext?: Partial<AgentThreadContext>,
|
||||
options?: { isMock?: boolean }
|
||||
): Promise<void>
|
||||
```
|
||||
|
||||
**内部机制:**
|
||||
- **乐观更新:** 用户发送后立即本地展示消息,不等服务端响应
|
||||
- **文件上传:** 自动调用 `uploadFiles()` 后再提交
|
||||
- **run_id 持久化:** sessionStorage 保存,支持页面刷新后断线重连
|
||||
- **消息同步:** 流结束后通过 `queryClient.invalidateQueries(["threads"])` 刷新列表
|
||||
|
||||
---
|
||||
|
||||
### 6.2 useThreadSettings
|
||||
|
||||
**位置:** `core/settings/hooks.ts`
|
||||
|
||||
```typescript
|
||||
const [settings, setSettings] = useThreadSettings(threadId);
|
||||
|
||||
// settings 结构
|
||||
{
|
||||
notification: { enabled: boolean },
|
||||
context: {
|
||||
model_name?: string,
|
||||
mode: "flash" | "thinking" | "pro" | "ultra",
|
||||
reasoning_effort?: "minimal" | "low" | "medium" | "high"
|
||||
}
|
||||
}
|
||||
|
||||
// 修改(合并更新)
|
||||
setSettings("context", { mode: "pro" });
|
||||
setSettings("notification", { enabled: true });
|
||||
```
|
||||
|
||||
**工作原理:** `useSyncExternalStore` 监听 localStorage 变化,跨标签页同步。
|
||||
|
||||
---
|
||||
|
||||
### 6.3 useI18n
|
||||
|
||||
**位置:** `core/i18n/hooks.ts`
|
||||
|
||||
```typescript
|
||||
const { t, locale, changeLocale } = useI18n();
|
||||
|
||||
t.sidebar.newChat // "New Chat"
|
||||
t.agents.createPageTitle // "Create Agent"
|
||||
t.toolCalls.moreSteps(3) // "Show 3 more steps"
|
||||
|
||||
changeLocale("zh-CN"); // 切换语言,自动存 cookie
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.4 useScheduledTaskActions
|
||||
|
||||
**位置:** `core/scheduled-tasks/hooks.ts`
|
||||
|
||||
```typescript
|
||||
const actions = useScheduledTaskActions();
|
||||
|
||||
// 所有返回值均为 TanStack Query Mutation
|
||||
actions.create // 创建定时任务
|
||||
actions.update // 更新任务配置
|
||||
actions.remove // 删除任务
|
||||
actions.removeRun // 删除执行记录
|
||||
actions.pause // 暂停
|
||||
actions.resume // 恢复
|
||||
actions.trigger // 立即触发一次
|
||||
actions.publish // 发布(激活)
|
||||
actions.unpublish // 取消发布
|
||||
actions.subscribe // 订阅推送
|
||||
actions.updateSubscription
|
||||
actions.unsubscribe
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.5 工具函数
|
||||
|
||||
**消息处理(`core/messages/utils.ts`):**
|
||||
|
||||
```typescript
|
||||
groupMessages(messages, mapper) // 按类型分组消息列表
|
||||
extractTextFromMessage(message) // 提取纯文本
|
||||
extractContentFromMessage(message) // 提取 Markdown/图像内容
|
||||
extractReasoningContentFromMessage(msg) // 提取推理过程
|
||||
hasToolCalls(message) // 是否含工具调用
|
||||
hasPresentFiles(message) // 是否包含文件呈现
|
||||
extractPresentFilesFromMessage(message) // 获取文件列表
|
||||
isClarificationToolMessage(message) // 是否为澄清请求
|
||||
```
|
||||
|
||||
**线程路由(`core/threads/utils.ts`):**
|
||||
|
||||
```typescript
|
||||
pathOfThread(thread, context?)
|
||||
// → "/page/workspace/agents/{agentRef}/chats/{threadId}"
|
||||
// 或 "/page/workspace/chats/{threadId}"
|
||||
|
||||
titleOfThread(thread)
|
||||
// → thread.values?.title ?? "Untitled"
|
||||
|
||||
textOfMessage(message)
|
||||
// → 消息文本内容(string 或 content 数组中第一个 text)
|
||||
```
|
||||
|
||||
**其他工具:**
|
||||
|
||||
```typescript
|
||||
// core/utils/files.tsx
|
||||
downloadFile(blob: Blob, filename: string)
|
||||
|
||||
// core/utils/datetime.ts
|
||||
formatTimeAgo(dateString: string) // → "2 小时前" / "3 days ago"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. API 调用层
|
||||
|
||||
### 7.1 API 客户端架构
|
||||
|
||||
**两层设计:**
|
||||
|
||||
**第一层:LangGraph SDK Client**(`core/api/api-client.ts`)
|
||||
|
||||
```typescript
|
||||
const client = new LangGraphClient({
|
||||
apiUrl: getLangGraphBaseURL(isMock),
|
||||
onRequest(url, init) {
|
||||
const headers = new Headers(init.headers ?? {});
|
||||
headers.set("Authorization", getAuthorizationHeaderValue());
|
||||
return { ...init, headers };
|
||||
}
|
||||
});
|
||||
|
||||
export function getAPIClient(isMock?: boolean): LangGraphClient
|
||||
```
|
||||
|
||||
**第二层:Fetch Client**(`core/api/fetch-client.ts`)
|
||||
|
||||
```typescript
|
||||
function apiFetch(input: RequestInfo, init?: RequestInit): Promise<Response> {
|
||||
return fetch(input, {
|
||||
...init,
|
||||
headers: withAuthHeaders(init?.headers)
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 主要 API 模块
|
||||
|
||||
| 模块 | 文件 | 关键函数 |
|
||||
|------|------|---------|
|
||||
| **Auth** | `core/auth/api.ts` | `loginByUsername(username)` → `LoginByUsernameResponse` |
|
||||
| **Agents** | `core/agents/api.ts` | `createAgent()`, `updateAgent()`, `listAgents()`, `deleteAgent()`, `checkAgentName()` |
|
||||
| **Models** | `core/models/api.ts` | `loadModels()` → `Model[]` |
|
||||
| **Threads** | (via LangGraph SDK) | `useThreadStream()`, `useThreads()`, `useDeleteThread()`, `useRenameThread()` |
|
||||
| **Skills** | `core/skills/api.ts` | `loadSkills()`, `enableSkill(name, enabled)` |
|
||||
| **Uploads** | `core/uploads/api.ts` | `uploadFiles(threadId, files[])`, `listUploadedFiles()`, `deleteUploadedFile()` |
|
||||
| **Memory** | `core/memory/api.ts` | `loadMemory()`, `createMemoryFact()`, `updateMemoryFact()`, `deleteMemoryFact()` |
|
||||
| **Scheduled Tasks** | `core/scheduled-tasks/api.ts` | CRUD、publish、pause、resume、trigger、subscribe |
|
||||
|
||||
### 7.3 Base URL 配置
|
||||
|
||||
**文件:** `core/config/index.ts`
|
||||
|
||||
```typescript
|
||||
export function getBackendBaseURL(): string {
|
||||
// env.NEXT_PUBLIC_BACKEND_BASE_URL
|
||||
// 默认:""(当前域名根路径)
|
||||
}
|
||||
|
||||
export function getLangGraphBaseURL(isMock?: boolean): string {
|
||||
// mock 模式:${origin}/mock/api
|
||||
// 正常:${origin}/api/langgraph
|
||||
// 或读取 env.NEXT_PUBLIC_LANGGRAPH_BASE_URL
|
||||
}
|
||||
```
|
||||
|
||||
### 7.4 认证流程
|
||||
|
||||
```
|
||||
LoginPage 调用 loginByUsername(username)
|
||||
↓ POST /api/auth/login
|
||||
↓ 返回 { access_token, token_type, user_id, email }
|
||||
↓ setStoredAuth() 存入 localStorage["deerflow.auth"]
|
||||
↓
|
||||
后续所有 API 请求
|
||||
↓ getAuthorizationHeaderValue()
|
||||
↓ → "Bearer {access_token}"
|
||||
↓ 自动添加到 Authorization header
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 国际化机制
|
||||
|
||||
### 8.1 文件结构
|
||||
|
||||
```
|
||||
core/i18n/
|
||||
├── context.tsx # I18nProvider(包裹 App)
|
||||
├── hooks.ts # useI18n()
|
||||
├── locale.ts # detectLocale(),Locale = "en-US" | "zh-CN"
|
||||
├── cookies.ts # cookie 读写(持久化语言选择)
|
||||
├── translations.ts # 翻译映射表入口
|
||||
└── locales/
|
||||
├── types.ts # Translations 接口定义(所有翻译 key 的类型)
|
||||
├── en-US.ts # 英文翻译
|
||||
└── zh-CN.ts # 简体中文翻译
|
||||
```
|
||||
|
||||
### 8.2 Translations 接口分类
|
||||
|
||||
```typescript
|
||||
interface Translations {
|
||||
locale: { localName: string } // 语言自身名称
|
||||
common: { ... } // 通用词汇(确认、取消等)
|
||||
welcome: { ... } // 欢迎屏
|
||||
inputBox: { ... } // 输入框(模式、占位符)
|
||||
sidebar: { ... } // 侧边栏导航
|
||||
agents: { ... } // 智能体相关
|
||||
chats: { ... } // 对话相关
|
||||
workspace: { ... } // 工作区通用
|
||||
settings: { ... } // 设置面板
|
||||
toolCalls: { ... } // 工具调用展示
|
||||
uploads: { ... } // 文件上传
|
||||
subtasks: { ... } // 子任务
|
||||
tokenUsage: { ... } // Token 用量
|
||||
shortcuts: { ... } // 快捷键说明
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 语言检测优先级
|
||||
|
||||
1. 读取 cookie `deerflow.locale`
|
||||
2. 读取浏览器 `navigator.language`
|
||||
3. 回退到 `en-US`
|
||||
|
||||
---
|
||||
|
||||
## 9. 主题与样式体系
|
||||
|
||||
### 9.1 主题系统
|
||||
|
||||
**库:** `next-themes`
|
||||
|
||||
```typescript
|
||||
// App.tsx
|
||||
<NextThemesProvider
|
||||
attribute="class" // 通过 <html class="dark"> 应用主题
|
||||
enableSystem // 跟随系统偏好
|
||||
disableTransitionOnChange // 切换时禁用过渡动画
|
||||
forcedTheme={pathname === "/landing" ? "dark" : undefined}
|
||||
>
|
||||
```
|
||||
|
||||
**可选主题值:** `light` / `dark` / `system`
|
||||
|
||||
### 9.2 样式方案
|
||||
|
||||
**基础:** Tailwind CSS
|
||||
|
||||
**组件库:** shadcn/ui(`components/ui/` 目录,40+ 基础组件)
|
||||
|
||||
**主要 CSS 自定义属性:**
|
||||
|
||||
```css
|
||||
--container-width-sm /* 小容器宽度 */
|
||||
--container-width-md /* 中等容器宽度(对话主区域) */
|
||||
--primary /* 主色 */
|
||||
--background /* 页面背景 */
|
||||
--foreground /* 主文本色 */
|
||||
--muted-foreground /* 次要文本色 */
|
||||
--border /* 边框色 */
|
||||
--sidebar-foreground /* 侧边栏文本 */
|
||||
```
|
||||
|
||||
### 9.3 样式使用规范
|
||||
|
||||
- 工具类优先(Tailwind)
|
||||
- 动态样式用 `cn()` 工具函数合并(基于 `clsx` + `tailwind-merge`)
|
||||
- 主题感知样式使用 CSS 变量(如 `text-muted-foreground`)
|
||||
|
||||
---
|
||||
|
||||
## 10. 关键业务流程
|
||||
|
||||
### 10.1 新建对话流程
|
||||
|
||||
```
|
||||
1. 点击"新建对话" → navigate("/page/workspace/chats/new")
|
||||
2. ChatPage 挂载,threadId = uuid(),isNewThread = true
|
||||
3. 用户输入消息,点击发送
|
||||
4. sendMessage(undefined, message) 调用
|
||||
5. useThreadStream 内部:
|
||||
a. 上传文件(若有)
|
||||
b. 创建 LangGraph 线程,后端返回 threadId
|
||||
c. onStart(threadId) 回调:
|
||||
- setIsNewThread(false)
|
||||
- history.replaceState 更新 URL hash
|
||||
6. WebSocket 流开始接收 AI 消息
|
||||
7. MessageList 实时渲染消息
|
||||
8. 流结束,onFinish 回调,可能触发桌面通知
|
||||
```
|
||||
|
||||
### 10.2 创建智能体流程
|
||||
|
||||
```
|
||||
Step 1(name 步骤)
|
||||
↓ 用户输入名称
|
||||
↓ checkAgentName(name) → 验证是否重名
|
||||
↓ createAgent({ name, skills: selectedSkills })
|
||||
↓ 后端返回 agent.id,setStep("chat")
|
||||
|
||||
Step 2(chat 步骤)
|
||||
↓ 生成临时 threadId
|
||||
↓ useThreadStream({ assistantId: agent.id })
|
||||
↓ 发送 bootstrap 消息(触发智能体自我设置)
|
||||
↓ onToolEnd 监听:event.name === "setup_agent"
|
||||
↓ 指数退避重试加载 agent 信息,确认已保存
|
||||
↓ 显示"Agent Created"完成界面
|
||||
↓ 用户可点击"开始对话"或"返回列表"
|
||||
```
|
||||
|
||||
### 10.3 文件上传流程
|
||||
|
||||
```
|
||||
1. 用户在 InputBox 选择/粘贴文件
|
||||
2. PromptInputAttachments 展示预览列表
|
||||
3. 用户点击发送
|
||||
4. sendMessage 内部调用 uploadFiles(threadId, files)
|
||||
5. POST /api/threads/{threadId}/upload
|
||||
6. 后端返回 { files: [{ filename, size, virtual_path }] }
|
||||
7. 构建 Message additional_kwargs.files
|
||||
8. 完整 Message 提交到 LangGraph
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 项目配置与依赖
|
||||
|
||||
### 11.1 主要依赖
|
||||
|
||||
| 包 | 版本 | 用途 |
|
||||
|----|------|------|
|
||||
| `react` | ^18 | 核心框架 |
|
||||
| `react-router-dom` | ^6 | 客户端路由(HashRouter) |
|
||||
| `@tanstack/react-query` | - | 服务端状态缓存 |
|
||||
| `@langchain/langgraph-sdk` | - | LangGraph WebSocket 连接 |
|
||||
| `next-themes` | - | 主题管理 |
|
||||
| `sonner` | - | Toast 通知 |
|
||||
| `lucide-react` | - | 图标库 |
|
||||
| `tailwindcss` | - | CSS 框架 |
|
||||
| `rehype` 系列 | - | Markdown 渲染 |
|
||||
| `uuid` | - | 生成临时 thread ID |
|
||||
|
||||
### 11.2 环境变量
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
|------|------|--------|
|
||||
| `NEXT_PUBLIC_BACKEND_BASE_URL` | 后端接口基础 URL | `""` (当前域名) |
|
||||
| `NEXT_PUBLIC_LANGGRAPH_BASE_URL` | LangGraph API URL | `/api/langgraph` |
|
||||
| `NEXT_PUBLIC_STATIC_WEBSITE_ONLY` | 纯静态演示模式 | `"false"` |
|
||||
|
||||
---
|
||||
|
||||
## 12. 常见开发模式
|
||||
|
||||
### 12.1 添加新工作区页面
|
||||
|
||||
```
|
||||
1. 创建 src/pages/MyPage.tsx
|
||||
2. 在 WorkspaceRoutes.tsx 中添加路由:
|
||||
<Route path="my-page" element={<WorkspaceLayout><MyPage /></WorkspaceLayout>} />
|
||||
3. 在 workspace-nav-chat-list.tsx 中添加导航入口(如需要)
|
||||
4. 更新相关的跳转路径
|
||||
```
|
||||
|
||||
### 12.2 添加新 API 接口
|
||||
|
||||
```
|
||||
1. 在 core/xxx/api.ts 中定义 API 函数(使用 apiFetch 或 getAPIClient())
|
||||
2. 在 core/xxx/hooks.ts 中封装 useQuery / useMutation
|
||||
3. 在页面或组件中调用 hook
|
||||
```
|
||||
|
||||
### 12.3 添加新 Context
|
||||
|
||||
```
|
||||
1. 创建 core/xxx/context.tsx:定义 Context + Provider + 默认值
|
||||
2. 创建消费 hook(如 useXxx())
|
||||
3. 在合适的组件树根部插入 Provider(WorkspaceRoutes 或 ChatRuntime)
|
||||
```
|
||||
|
||||
### 12.4 添加国际化文本
|
||||
|
||||
```
|
||||
1. 在 core/i18n/locales/types.ts 的 Translations 接口中添加字段
|
||||
2. 在 core/i18n/locales/en-US.ts 添加英文内容
|
||||
3. 在 core/i18n/locales/zh-CN.ts 添加中文内容
|
||||
4. 组件中通过 useI18n() 访问:const { t } = useI18n(); t.xxx.yyy
|
||||
```
|
||||
|
||||
### 12.5 引入外部系统路由
|
||||
|
||||
在 `src/pages/PageRoutes.tsx` 中找到 TODO 注释位置,填入:
|
||||
|
||||
```typescript
|
||||
import AnotherSystemRoutes from "外部系统路径";
|
||||
|
||||
// 在 Routes 中添加:
|
||||
<Route path="other/*" element={<AnotherSystemRoutes />} />
|
||||
```
|
||||
|
||||
如外部系统有独立 Provider 依赖,在此文件或 App.tsx 中包裹。
|
||||
|
||||
---
|
||||
|
||||
## 附:关键文件速查
|
||||
|
||||
| 需求 | 关键文件 |
|
||||
|------|---------|
|
||||
| 修改路由结构 | `App.tsx`, `PageRoutes.tsx`, `WorkspaceRoutes.tsx` |
|
||||
| 修改侧边栏导航 | `components/workspace/workspace-nav-chat-list.tsx` |
|
||||
| 修改对话逻辑 | `pages/ChatPage.tsx`, `core/threads/hooks.ts` |
|
||||
| 修改输入框 | `components/workspace/input-box.tsx`, `components/ai-elements/prompt-input/` |
|
||||
| 修改消息渲染 | `components/workspace/messages/` |
|
||||
| 添加 API 接口 | `core/xxx/api.ts` + `core/xxx/hooks.ts` |
|
||||
| 修改全局设置 | `core/settings/store.ts`, `core/settings/hooks.ts` |
|
||||
| 修改翻译文本 | `core/i18n/locales/en-US.ts`, `core/i18n/locales/zh-CN.ts` |
|
||||
| 修改主题 | `App.tsx` (NextThemesProvider) |
|
||||
| 修改认证逻辑 | `core/auth/api.ts`, `pages/LoginPage.tsx` |
|
||||
| 定时任务 | `pages/ScheduledTasksPage.tsx`, `core/scheduled-tasks/` |
|
||||
| 智能体管理 | `pages/NewAgentPage.tsx`, `core/agents/` |
|
||||
Reference in new issue
Block a user