Files
Alfred/docs/development/frontend.md

14 KiB
Raw Blame History

前端开发

开发规范见 开发规范文档

布局架构

两个布局入口共享 ConsoleShellsrc/web/shared/components/ConsoleShell/

  • AdminLayoutsrc/web/layouts/admin-layout/):路由 /(总览)、/projects/models/models/providers
  • WorkbenchLayoutsrc/web/layouts/workbench-layout/):路由 /workbench/:projectId/workbench/:projectId/chatWorkbenchProjectGate 从 URL 读 projectId通过 ProjectContext 提供项目上下文,仅 active 项目渲染。

ConsoleShell 包含:XProvider(zhCN + zhCN_X) + AntApp + Layout(Header/Sider/Content),主题配置由 shared/theme/theme-config.tsbuildThemeConfig(effectiveTheme) 集中构建(含 cssVarborderRadiuscontrolHeightcomponents.Layout 配色);侧边栏折叠。主题切换已迁移至设置页(/settings。Header 显示品牌名、版本号和布局标题。

Sidebarsrc/web/shared/components/Sidebar/)纯展示组件,通过 menuItems props 接收配置。

功能模块

功能模块 路径 说明
仪表盘 features/dashboard/ 总览页面
项目管理 features/projects/ 项目 CRUD、归档、搜索、排序
模型管理 features/models/ 供应商/模型管理、连通性测试
聊天 features/chat/ 会话管理、消息渲染、AI 对话
收集箱 features/inbox/ 素材 CRUD、持久化、列表管理
设置 features/settings/ 平台业务设置,卡片式布局

页面

页面 路径 入口
总览 / features/dashboard/index.tsx
项目管理 /projects features/projects/index.tsx — FilterToolbar状态 Select + 搜索 + 新建/归档恢复删除) + ProjectTable + ProjectFormModal。支持创建/编辑/归档/恢复/删除、列表排序、URL 同步筛选参数。
模型管理 /models/models/providers 独立路由页面:ModelListPage.tsxFilterToolbar + ModelTable + ProviderListPage.tsxFilterToolbar + ProviderTable。模型支持供应商/能力筛选和列表排序,供应商支持类型筛选和列表排序。模型表单使用 GET /api/providers/options。供应商表单支持预保存连通性测试(POST /api/providers/test)。
设置 /settings features/settings/index.tsx — 卡片式布局分区管理平台业务设置。当前包含"主题配置"卡片Segmented 切换系统/明亮/黑暗),使用 useSettings hook 通过 GET/PUT /api/settings 持久化,悲观更新策略。
聊天室 /workbench/:id features/chat/index.tsx
收集箱 /workbench/:id/inbox features/inbox/index.tsx — 协调层selectedId + modalOpen+ MaterialSidebar列表容器+ MaterialDetailPanel详情容器+ AddMaterialModal。素材 CRUD 通过 TanStack Query hooks 接入后端 API。
404 * features/not-found/index.tsx

聊天页面

ChatPage = ConversationSidebar(自定义组件)+ ChatPanel

  • ConversationSidebar会话侧边栏数据加载层useQuery + 错误处理)。内部渲染 ConversationList(搜索框 + OverlayScrollbars 滚动 + 日期分组 + ConversationCard 列表)。对话按 updatedAt 分组(今天/昨天/本周/本月/更早),支持搜索过滤和 hover 删除Popconfirm
  • ChatPaneluseChat@ai-sdk/react+ DefaultChatTransportai 包)与后端 SSE 通信。按 part.type 分派渲染TextPartmarkdown-to-jsx 含自定义 overridesCodeBlock 提供 Shiki 语法高亮和复制按钮、MarkdownTable 提供类 antd 表格样式、ReasoningPart、ToolPart四态。支持编辑重发、重新生成、复制。
  • Sender@ant-design/x输入框 + 发送/停止按钮 + 模型 Selectfooter slot

共享代码

共享组件

组件 路径 说明
ConsoleShell shared/components/ConsoleShell/ 全局布局外壳Provider + Layout
FilterToolbar shared/components/FilterToolbar.tsx 统一筛选工具条Select 筛选 + 搜索 + 重置 + 操作按钮)
Sidebar shared/components/Sidebar/ 侧边栏纯展示组件
SidebarGroup shared/components/SidebarGroup/ 可折叠日期分组(聊天室和收集箱共用)
ErrorBoundary shared/components/ErrorBoundary.tsx 生产环境错误边界

共享 Hooks

Hook 路径 说明
use-page-search-params shared/hooks/usePageSearchParams.ts URL 查询参数同步(筛选/分页/排序),批量更新 setParams 避免闭包覆盖
use-confirm-action shared/hooks/useConfirmAction.ts 包装异步操作 + toast 成功/失败通知
use-meta.ts shared/hooks/use-meta.ts /api/meta30s 轮询5s staleTime
use-providers.ts shared/hooks/use-providers.ts 供应商 CRUD + test connection
use-models.ts shared/hooks/use-models.ts 模型 CRUD + test connection
use-projects.ts shared/hooks/use-projects.ts 项目 CRUD + archive/restore
use-conversations.ts shared/hooks/use-conversations.ts 会话和消息 fetch 函数(不含 Query hooks
use-logger shared/hooks/use-logger.ts Logger hook组件内使用
use-theme-preference shared/hooks/use-theme-preference.ts 主题偏好管理localStorage + API 同步)
use-settings shared/hooks/use-settings.ts 平台设置读写react-query: GET/PUT /api/settings
use-sidebar-collapsed shared/hooks/use-sidebar-collapsed.ts 侧边栏折叠 localStorage 持久化
use-is-dark shared/hooks/use-is-dark.ts 当前是否暗色主题

共享主题配置

文件 导出
theme/theme-config.ts buildThemeConfig(effectiveTheme) — 构建 antd ThemeConfigalgorithm、cssVar、token、components.Layout
use-current-project shared/hooks/use-current-project.ts 当前工作台项目 + ProjectContext需在 ProjectProvider 内)
use-materials.ts shared/hooks/use-materials.ts 素材 CRUDcreate/delete/fetch/list + Query hooks

共享工具函数

文件 导出
utils/api.ts handleResponse(response, extract)handleVoidResponse(response)
utils/format.ts formatDatetime(iso: string) — 格式化 ISO 时间字符串为 YYYY-MM-DD HH:mm
utils/time.ts formatCountdownformatDurationUnitformatRelativeTimeisOlderThansubtractHours
utils/date-group.ts getDateGroupgroupByDateGROUP_LABELSGROUP_ORDERDateGroupDateGroupData

更新触发条件

修改前端技术栈、组件边界、数据流、样式规则、测试环境、前端验证方式、运行时代码结构、页面组成、组件索引、hooks/工具清单、目录结构或功能模块归属时,必须更新本文档。管理页面 CRUD 通用模式的详细约定见 crud.md

日志模块

Logger 接口

src/web/shared/utils/logger.ts 提供与后端镜像的 Logger 抽象:

export interface Logger {
  child(bindings: Record<string, unknown>): Logger;
  debug(message: string, data?: unknown): void;
  error(message: string, data?: unknown): void;
  info(message: string, data?: unknown): void;
  setLevel(level: LogLevel): void;
  warn(message: string, data?: unknown): void;
}

实现

实现 工厂函数 用途
DefaultLogger + Sinks useLogger(bindings?) / createDefaultLogger() 组件内使用ConsoleSink + AntdMessageSink 双流;传入 bindings 自动创建带作用域的子 Logger
ConsoleLogger createConsoleLogger() 非组件纯函数ErrorBoundary、工具函数仅 ConsoleSink
NoopLogger createNoopLogger() 测试中不需要日志的场景
MemoryLogger createMemoryLogger() 测试断言日志条目

使用方式

组件内(推荐):

import { useLogger } from "../../shared/hooks/use-logger";

function MyComponent() {
  const logger = useLogger({ component: "MyComponent" });
  logger.info("数据加载完成", { count: 42 });
  logger.warn("即将超时");
  logger.error("操作失败", { error: new Error("...") });
}

非组件纯函数:

import { createConsoleLogger } from "../../shared/utils/logger";

const logger = createConsoleLogger();
logger.debug("调试信息");

作用域绑定:

组件内直接通过 useLoggerbindings 参数传入hook 内部保证引用稳定(值不变时多次渲染返回同一 Logger

const logger = useLogger({ component: "ChatPanel", page: "workbench" });
logger.info("页面加载"); // [Alfred:INFO] 页面加载 [component=ChatPanel][page=workbench]

非组件场景仍可使用 logger.child()

const pageLogger = logger.child({ page: "projects" });
pageLogger.info("页面加载"); // [Alfred:INFO] 页面加载 [page=projects]

notification 红线

  • AntdMessageSink 仅对 warnmessage.warning)和 errormessage.error)触发用户可见通知。
  • debuginfo 级别绝不对用户弹出 notification仅在开发者控制台输出。
  • 错误详情通过 data 参数传入(如 logger.error("提交失败", { error })data 不经序列化透传,保留 Error 堆栈展开能力。

生产环境行为

生产环境(import.meta.env["PROD"])自动将 ConsoleSink 最小级别设为 warn,屏蔽 debug/info 输出。useLogger()createConsoleLogger() 自动处理此逻辑,调用方无需关心环境判断。

ErrorBoundary 特殊说明

ErrorBoundary 是 class 组件,无法使用 useLogger() hook。它以 createConsoleLogger() 直接创建独立的 ConsoleLogger 实例,仅输出到控制台不触发用户通知。

测试

  • 单元测试使用 createMemoryLogger() 断言日志记录,使用 createNoopLogger() 静默无关日志。
  • createDefaultLogger(sinks, isProduction) 接受 isProduction 参数,测试中可显式控制级别过滤行为,不依赖 import.meta.env