跳转至

Web 前端技术参考

Web 前端是 TTD 的用户交互入口,提供会话式自然语言查询实时流式结果展示多维数据可视化管理台 (Admin Panel) 能力。

定位

本文档为 Web 前端的技术参考手册,涵盖架构设计、核心模块、开发规范。 面向前端开发者和全栈工程师。

相关设计规范

本文档聚焦前端架构、模块职责与工程实现。 若需查看统一 UI 设计语言与实现约束,请同时参考 Handbook 中新增的 Web Design System 分组: - Web UI 设计语言总览 - Design Tokens 规范 - 组件规范 - 页面模板规范 - 代码治理与评审约束


1. 技术栈 (Technology Stack)

1.1 核心框架

分类 技术 版本 职责
Framework Next.js 16.2.0 App Router + Turbopack
UI Library React 19.2.4 组件渲染引擎
Language TypeScript 5.x 类型安全
Client State Zustand 5.0.12 轻量客户端状态管理
Server State TanStack React Query 5.91.2 异步数据缓存与同步
Form react-hook-form 7.72.1 表单状态与验证
Validation Zod 4.3.6 Schema 验证(SSE + 表单)

1.2 UI 组件与样式

分类 技术 说明
Primitive Radix UI 30+ 无样式可访问性原语
Component System shadcn/ui 54 个预构建组件(见 components/ui/
Styling Tailwind CSS 4 Utility-first CSS
Animation Framer Motion 12.38 声明式动画
Icons Lucide React 0.577 一致性图标集
Theme next-themes 0.4.6 Dark/Light 主题切换
Toast Sonner 2.0.7 通知提示
Panels react-resizable-panels 4.9 可拖拽面板分割

1.3 数据可视化

版本 用途
ECharts 6.0.0 主力图表渲染(bar, line, pie, scatter, heatmap 等)
echarts-for-react 3.0.6 React 封装层
Recharts 3.8.0 辅助图表(简单场景)
@antv/g6 5.0.51 知识图谱可视化
D3 7.9.0 底层数据变换
force-graph 1.51.2 力导向图

1.4 工具链

工具 用途
Turbopack 开发态构建(Next.js 内置)
Biome 2.2 格式化 + Lint(替代 ESLint + Prettier)
@hey-api/openapi-ts 0.94 OpenAPI 代码生成
bun 包管理与脚本执行

1.5 认证 (Authentication)

技术 版本 职责
Better Auth latest 统一身份源 (Email/Password, GitHub OAuth)
better-auth/react React 客户端 SDK (hooks + session)
better-auth/plugins (jwt, admin) JWT 签发 + Admin 角色管理
pg 8.x Better Auth 数据库适配器 (PostgreSQL)

2. 路由与页面结构 (Routes & Pages)

2.1 目录结构

app/
├── layout.tsx                      # Root layout (providers, fonts, theme)
├── globals.css                     # Tailwind 入口
├── page.tsx                        # Landing page (hero + features + CTA)
├── api/auth/[...all]/route.ts      # Better Auth API route handler
├── health/
│   └── page.tsx                    # Backend 健康检查面板
├── results/
│   └── page.tsx                    # Query results workspace (legacy)
├── (auth)/                         # Auth route group (无认证保护)
│   ├── layout.tsx                  # Auth shell (双栏:左侧品牌 + 右侧表单)
│   ├── auth-left-panel.tsx         # 左栏:网格背景、光晕、统计卡片、testimonial
│   ├── login/page.tsx              # 登录页 (Email/Password + GitHub)
│   └── signup/page.tsx             # 注册页
├── (chat)/                         # Chat feature route group (需认证)
│   ├── layout.tsx                  # Chat shell (sidebar + main) + auth guard
│   ├── page.tsx                    # → /chat redirect
│   ├── chat/
│   │   └── page.tsx               # Chat home (示例问题 + Composer)
│   │   └── c/[id]/page.tsx        # 单条对话详情页
│   └── admin/                     # Admin Panel (需 admin 角色)
│       ├── layout.tsx             # Admin shell + role gate
│       ├── page.tsx               # Dashboard (统计概览)
│       ├── knowledge-bases/       # 知识库管理 (CRUD)
│       ├── chat-engines/          # Chat Engine 配置
│       ├── models/                # LLM / Embedding / Reranker 模型管理
│       ├── evaluation/            # 评测任务管理
│       ├── conversations/         # 历史对话浏览
│       ├── feedbacks/             # 用户反馈审核
│       ├── few-shots/             # 动态 Few-Shot 质量审核
│       └── settings/              # 站点设置
└── sessions/                      # Legacy query workspace
    ├── page.tsx                   # Sessions 列表
    └── [sessionId]/page.tsx       # Session 详情与 replay

2.2 路由分组说明

graph LR
    A["/"] --> B["Landing Page"]
    A --> C["/health"]
    A --> D["/results"]
    A --> AUTH["/(auth)"]
    AUTH --> AUTH_LOGIN["/login"]
    AUTH --> AUTH_SIGNUP["/signup"]
    A --> E["/(chat)"]
    E --> F["/chat"]
    F --> G["/chat/c/:id"]
    E --> H["/admin"]
    H --> I["/admin/knowledge-bases"]
    H --> J["/admin/chat-engines"]
    H --> K["/admin/models"]
    H --> L["/admin/evaluation"]
    H --> M["/admin/conversations"]
    H --> N["/admin/feedbacks"]
    H --> O["/admin/few-shots"]
    H --> P["/admin/settings"]
    A --> Q["/sessions"]
    Q --> R["/sessions/:sessionId"]
    A --> API_AUTH["/api/auth/*"]

Route Group (auth)

认证页面使用独立的 Route Group (auth),共享 Auth Shell 布局(左侧品牌面板 + 右侧表单区)。 该组不做认证保护,允许未登录用户访问。

Route Group (chat) — 需认证

使用 Next.js Route Group 机制,(chat) 目录不体现在 URL 中,但共享统一的 Chat Layout(含侧边栏和导航)。 该布局内置认证守卫,未登录用户会被重定向到 /login

2.3 Admin Panel 功能页面

路由 功能 说明
/admin Dashboard 系统统计概览
/admin/knowledge-bases 知识库管理 CRUD,关联数据源与文档
/admin/chat-engines Chat Engine 配置 关联 LLM + 知识库
/admin/models 模型管理 LLM / Embedding / Reranker
/admin/evaluation 评测任务 批量评估任务管理
/admin/conversations 历史对话 对话浏览与重放
/admin/feedbacks 反馈审核 用户 👍/👎 反馈管理
/admin/few-shots Few-Shot 审核 动态 few-shot 质量审核(见下)
/admin/settings 站点设置 品牌、示例问题、全局配置

/admin/few-shots — 动态 Few-Shot 质量审核

页面文件:app/(chat)/admin/few-shots/page.tsx Hook:hooks/use-few-shots.tsuseFewShots, useFewShotStats, reviewFewShot, exportSingleYaml, exportBulkYaml

功能:

  1. 统计看板 — Pending / Approved / Rejected 三卡片,实时展示各状态数量
  2. 分 Tab 列表 — 按 pending_review / approved / rejected 筛选,每页 20 条
  3. 审批操作(仅 Pending Tab):
  4. Approve — 条目状态改为 approved,下次 RAG 查询时若 similarity ≥ 0.95 即被注入
  5. Reject — 条目状态改为 rejected,永久排除出 RAG
  6. YAML 导出(仅 Approved Tab):
  7. 单条导出(下载 .yaml 文件)
  8. Export All Approved as YAML — 批量导出全部已审批条目,格式与 semantic-plane/few_shots/ 完全一致,可直接提交 PR 晋升为正式资产
  9. 信息横幅 — Pending Tab 明确提示"pending 条目不参与 SQL 生成";Approved Tab 说明注入条件(admin approval + sim ≥ 95%)

SQL 预览 — 每条记录的 SQL 字段支持折叠/展开,超过 120 字符时默认截断显示。


3. 认证与会话 (Authentication & Session)

3.1 架构概览

Web 前端托管 Better Auth 作为统一身份源,管理用户注册、登录、会话和 JWT 签发。

flowchart TB
    subgraph "Next.js (Web)"
        AUTH_API["api/auth/[...all]/route.ts<br/>Better Auth Handler"]
        AUTH_LIB["lib/auth.ts<br/>Server Config"]
        AUTH_CLI["lib/auth-client.ts<br/>Client SDK"]
        PROV["providers.tsx<br/>AuthProvider + useAuth()"]
    end
    subgraph "Browser"
        LOGIN["login/page.tsx"]
        SIGNUP["signup/page.tsx"]
        GUARD["(chat)/layout.tsx<br/>Auth Guard"]
    end
    subgraph "PostgreSQL"
        DB[(auth tables:<br/>user, session, account,<br/>verification, jwks)]
    end

    LOGIN -->|"signIn.email / signIn.social"| AUTH_CLI
    AUTH_CLI -->|"HTTP"| AUTH_API
    AUTH_API --> AUTH_LIB
    AUTH_LIB --> DB
    GUARD -->|"useAuth() → session check"| PROV
    PROV --> AUTH_CLI

3.2 关键文件

文件 职责
lib/auth.ts Better Auth 服务端配置(plugins, DB pool, providers)
lib/auth-client.ts 客户端 auth 实例(jwtClient + adminClient plugins)
app/api/auth/[...all]/route.ts Next.js App Router catch-all handler,暴露 /api/auth/*
app/(auth)/layout.tsx Auth Shell 布局(双栏:品牌面板 + 表单区)
app/(auth)/auth-left-panel.tsx 左侧品牌面板(网格背景、光晕、统计、testimonial)
app/(auth)/login/page.tsx 登录页(Email/Password + 条件 GitHub)
app/(auth)/signup/page.tsx 注册页(同上表单模式)
components/ui/providers.tsx AuthProvider + useAuth() hook

3.3 会话管理

概念 实现 说明
Browser Session Better Auth cookie (better-auth.session_token) 7 天有效,自动刷新 (updateAge: 1 天)
API Token authClient.token() → RS256 JWT 1 小时有效,用于发往 FastAPI 的请求
Session Provider AuthProvider in providers.tsx 包装 authClient.useSession(),提供 useAuth() hook

3.4 页面保护策略

// app/(chat)/layout.tsx — 认证守卫
const { data: session, isPending } = useAuth();
if (!isPending && !session) {
  redirect("/login");
}

// app/(chat)/admin/layout.tsx — 角色守卫
if (session?.user?.role !== "admin") {
  redirect("/chat");
}
路由组 保护级别 未通过时行为
(auth) 无保护
(chat) 需要登录 /login
(chat)/admin 需要 admin 角色 /chat

3.5 Token Bridge(API 认证注入)

所有发往 FastAPI 的请求通过 client-config.ts 的 request interceptor 自动注入 JWT:

// lib/api/client-config.ts
interceptors: {
  request: [async (request) => {
    const { data: token } = await authClient.token();
    if (token) request.headers.set("Authorization", `Bearer ${token}`);
    return request;
  }],
  response: [async (response) => {
    if (response.status === 401) window.location.href = "/login";
    return response;
  }],
}
  • Token 获取:调用 authClient.token(),Better Auth JWT plugin 签发 RS256 JWT
  • 401 处理:统一重定向到登录页(会话过期或 Token 无效)
  • SSE 流chat-stream.ts 同样注入 Bearer Token

3.6 条件 GitHub OAuth

GitHub 登录为可选功能,通过环境变量控制:

  • 服务端lib/auth.ts):仅当 GITHUB_CLIENT_ID + GITHUB_CLIENT_SECRET 都存在时启用
  • 客户端(login/signup):根据 NEXT_PUBLIC_GITHUB_AUTH_ENABLED=true 显示 GitHub 按钮

未配置 GitHub 时,登录页仅显示 Email/Password 表单,不影响核心功能。


4. 状态管理架构 (State Management)

4.1 整体数据流

flowchart TB
    subgraph Browser
        UI[React Components]
        ZS[Zustand Stores]
        RQ[React Query Cache]
    end
    subgraph Backend
        API[REST API]
        SSE[SSE Stream]
    end

    UI -->|dispatch actions| ZS
    UI -->|useQuery / useMutation| RQ
    RQ -->|fetch / mutate| API
    SSE -->|onEvent callback| ZS
    ZS -->|selector subscriptions| UI
    RQ -->|cache data| UI

4.2 Zustand Stores 详解

chat-store.ts — Chat 核心状态

状态字段 类型 说明
currentChatId string \| null 当前活跃对话 ID
messages MessageResponse[] 当前对话完整消息列表
streamStatus StreamStatus idle / connecting / streaming / clarification / viz_checkpoint / done / error
streaming StreamingAssistant SSE 流式过程中累积的结构化数据
chats ChatSummary[] 侧边栏对话列表
chatsTotal number 对话总数(分页)

StreamingAssistant 结构(SSE 流式累积):

type StreamingAssistant = {
  sql: string | null;                    // 生成的 SQL
  intent: Record<string, unknown> | null; // 意图解析结果
  validationResult: Record<string, unknown> | null; // SQL 校验
  executionResult: {                     // 执行结果
    columns: string[];
    rows: unknown[][];
    row_count: number;
    has_more: boolean;
    execution_time_ms: number;
  } | null;
  visualization: {                       // 可视化决策包
    chart_type: string | null;
    echarts_option: Record<string, unknown> | null;
    templateRef: TemplateRef | null;      // 模板引用(前端 hydration 用,类型来自 chart-templates/types.ts)
    candidates: VizCandidateData[] | null; // Top-k 候选图表列表
    confidence: number | null;            // 推荐置信度 (0-1)
    checkpointStatus: "auto_pass" | "needs_review" | "blocked" | null;
  } | null;
  insights: string[];                    // 数据洞察
  sqlBusinessContext: {...} | null;       // 业务上下文
  pipelineNodes: PipelineNodeEntry[];    // Pipeline 节点状态
  pipelineSteps: Array<{...}>;           // Pipeline 步骤详情
  retrievalSteps: Array<{...}>;          // 检索步骤
  graphResult: {...} | null;             // 知识图谱结果
  knowledge: { answer: string; sources: string[] } | null;
  routeDecision: string | null;          // 路由决策
  evaluators: Array<{...}>;              // 评估器结果
  mlResults: unknown[];                  // ML 分析结果
  suggestedFollowups: Array<{...}>;      // 推荐追问
  errors: string[];                      // 错误信息
  clarification: {...} | null;           // 澄清请求
};

query-workspace-store.ts — Query 工作区状态

状态字段 类型 说明
streamStatus StreamStatus 流状态
sessionId string \| null 当前 Session ID
resultData ResultData \| null 查询结果(columns + rows)
currentSql string \| null 当前生成的 SQL
visualization VisualizationData \| null 可视化决策包:ECharts 配置 + 模板引用 + 候选列表 + 置信度 + checkpoint 状态
vizCheckpoint VizCheckpointData \| null HITL checkpoint 数据(低置信度时展示候选选择 UI)
insights string[] 数据洞察
pipelineSteps PipelineStepData[] Pipeline 步骤
drilldownPath DrilldownData[] 下钻路径
linkedSelection LinkedSelectionData \| null 图表-表格联动选中

session-detail-store.ts — Session 详情状态

用于 /sessions/[sessionId] 页面,管理历史 Turn 的回放和展示。

ui-preferences-store.ts — UI 偏好(持久化)

type UiPreferencesState = {
  activeResultTab: "table" | "sql" | "chart" | "insights"
                 | "context" | "graph" | "knowledge" | "ml";
  sidebarOpen: boolean;
};

持久化策略

ui-preferences-store 使用 Zustand persist 中间件,状态保存到 localStorage(key: ttd-ui-prefs)。

4.3 React Query 管理的服务端状态

Hook 数据 缓存策略
useChatEngines() Chat Engine 列表 staleTime: 5min
useKnowledgeBases() 知识库列表 staleTime: 5min
useModels() LLM/Embedding/Reranker 模型 staleTime: 5min
useSiteSettings() 站点配置(示例问题、品牌) staleTime: 10min
useSessionsQuery() Session 列表 staleTime: 30s
useSessionQuery(id) 单个 Session 详情 staleTime: 0 (always fresh)
useHealthQuery() 后端健康状态 refetchInterval: 30s
useStats() Admin Dashboard 统计 staleTime: 1min
useFeedbacks() 用户反馈列表 staleTime: 1min
useFewShots() Few-Shot 条目列表(按状态) staleTime: 30s
useFewShotStats() Few-Shot 各状态统计 staleTime: 30s

5. API 集成层 (API Integration Layer)

5.1 架构概览

flowchart LR
    subgraph Frontend
        C[Components]
        H[Hooks]
        LIB[lib/api/index.ts]
        GEN[lib/api/generated/]
        SSE_LIB[lib/api/chat-stream.ts]
    end
    subgraph Backend
        REST[REST API]
        STREAM[SSE Endpoint]
    end

    C --> H
    H --> LIB
    H --> SSE_LIB
    LIB --> GEN
    GEN -->|@hey-api/client-fetch| REST
    SSE_LIB -->|POST + ReadableStream| STREAM

5.2 OpenAPI 代码生成

// openapi-ts.config.ts
import { defineConfig } from "@hey-api/openapi-ts";

export default defineConfig({
  input: process.env.OPENAPI_TS_INPUT ?? "http://localhost:8000/openapi.json",
  output: "lib/api/generated",
  plugins: [
    { name: "@hey-api/client-fetch", runtimeConfigPath: "../client-config.ts" },
    { name: "@hey-api/sdk", operations: { nesting: "operationId" } },
  ],
});

生成产物:

文件 说明
lib/api/generated/client.gen.ts HTTP 客户端实例
lib/api/generated/sdk.gen.ts 按 operationId 组织的 SDK 函数
lib/api/generated/types.gen.ts TypeScript 类型定义

5.3 SSE 流式实现

非 EventSource

本项目使用 POST-based SSE(非浏览器原生 EventSource),因为需要在 SSE 请求中携带 JSON body。 实现基于 fetch + ReadableStream + TextDecoder 手动解析 SSE 协议。

核心流程:

// lib/api/chat-stream.ts
export async function streamChatMessage({
  chatId, content, language, signal, onEvent, onError, onDone
}: StreamChatMessageParams): Promise<void> {
  const response = await fetch(
    `${baseUrl}/api/v1/chats/${chatId}/messages/stream`,
    { method: "POST", headers: {...}, body: JSON.stringify({ content, language }), signal }
  );
  const reader = response.body?.getReader();
  // 手动 SSE line protocol 解析:event: / data: / 空行分隔
  // ...解析后调用 onEvent(parsedEvent)
}

5.4 SSE Event Types(完整列表)

Event Name Schema 说明
chat chatEventSchema 对话创建确认
message messageEventSchema 消息 ID 与序号
turn turnEventSchema Turn 标识
session sessionEventSchema Session ID 关联
pipeline_plan pipelinePlanEventSchema Pipeline 计划节点列表
node_start nodeStartEventSchema 节点开始执行
node_complete nodeCompleteEventSchema 节点执行完成
step_detail stepDetailEventSchema 步骤详情(label-value 对)
retrieval_step retrievalStepEventSchema 检索步骤结果
route_decision routeDecisionEventSchema 路由决策
intent intentEventSchema 意图解析
sql sqlEventSchema 生成的 SQL
validation validationEventSchema SQL 校验结果
data dataEventSchema 查询执行结果
visualization visualizationEventSchema 可视化决策包 (echarts_option, template_ref, candidates, confidence, checkpoint_status)
checkpoint checkpointEventSchema 可视化 HITL checkpoint(低置信度时触发前端候选确认 UI)
insights insightsEventSchema 数据洞察
sql_business_context sqlBusinessContextEventSchema 业务上下文
context sqlBusinessContextEventSchema 同上(别名)
graph graphEventSchema 知识图谱结果
knowledge knowledgeEventSchema 知识问答结果
evaluator evaluatorEventSchema 评估器结果
clarification clarificationEventSchema 澄清请求
errors errorsEventSchema 错误(可能含修复尝试)
error errorEventSchema 单条错误
ml_result mlResultEventSchema ML 分析结果
ml_chart mlChartEventSchema ML 图表配置
ml_summary mlSummaryEventSchema ML 摘要
suggested_followups suggestedFollowupsEventSchema 推荐追问
done doneEventSchema 流结束标记

5.5 SSE Schema 验证

所有 SSE 事件使用 Zod v4 进行运行时 Schema 验证:

// lib/api/sse-schema.ts
export function parseStreamEvent(eventName: string, rawData: string): ParsedStreamEvent | null {
  const schema = schemaMap[eventName];
  if (!schema) return null;
  const result = schema.safeParse(JSON.parse(rawData));
  if (!result.success) {
    console.warn(`[SSE] Validation failed for "${eventName}":`, result.error);
    return null;
  }
  return { event: eventName, data: result.data } as ParsedStreamEvent;
}

容错策略

Schema 验证失败时返回 null(跳过),不中断流。同时在 console 打印警告以辅助调试。


6. 核心 Hooks (Core Hooks)

6.1 Hooks 列表

Hook 文件 职责
useChatStream() hooks/use-chat-stream.ts 完整 Chat 生命周期(创建 → 流式 → 构建消息)
useQueryStream() hooks/use-query-stream.ts Query Workspace 流式查询
useChatEngines() hooks/use-chat-engines.ts Chat Engine 列表
useKnowledgeBases() hooks/use-knowledge-bases.ts 知识库列表
useModels() hooks/use-models.ts 模型列表(LLM / Embedding / Reranker)
useSiteSettings() hooks/use-site-settings.ts 站点设置(示例问题、品牌)
useSessionsQuery() hooks/use-sessions-query.ts Session 列表(分页)
useSessionQuery() hooks/use-session-query.ts 单 Session 详情
useSessionsListQuery() hooks/use-sessions-list-query.ts Session 列表(列表形式)
useFeedbackMutation() hooks/use-feedback-mutation.ts 提交消息反馈
useMessageFeedback() hooks/use-message-feedback.ts 消息级别反馈
useFeedbacks() hooks/use-feedbacks.ts 反馈列表查询
useFewShots() hooks/use-few-shots.ts 动态 Few-Shot 列表(按状态分页)
useFewShotStats() hooks/use-few-shots.ts Few-Shot 各状态数量统计
useHealthQuery() hooks/use-health-query.ts 后端健康检查(轮询)
useStats() hooks/use-stats.ts Admin 统计数据
useEvaluation() hooks/use-evaluation.ts 评测任务管理
useGraph() hooks/use-graph.ts 图谱数据查询
useGraph() hooks/use-graph.ts 图谱数据查询
useDatasources() hooks/use-datasources.ts 数据源列表
useDocuments() hooks/use-documents.ts 文档管理
useMobile() hooks/use-mobile.tsx 移动端检测

6.2 useChatStream() 详解

sequenceDiagram
    participant User
    participant Hook as useChatStream
    participant Store as ChatStore
    participant API as Backend SSE

    User->>Hook: submit(question)
    Hook->>API: POST /api/v1/chats (if no chatId)
    API-->>Hook: { id: chatId }
    Hook->>Store: setCurrentChat(chatId)
    Hook->>Store: addMessages(userMsg)
    Hook->>Store: startStream()
    Hook->>API: POST /api/v1/chats/{id}/messages/stream
    loop SSE Events
        API-->>Hook: event: node_start, sql, data, ...
        Hook->>Store: handleStreamEvent(event)
    end
    API-->>Hook: event: done
    Hook->>Store: finishStream(assistantMsg)

关键行为:

  1. 自动创建 Chat — 若 currentChatIdnull,先调用 POST /api/v1/chats 创建
  2. 乐观更新 — 用户消息立即添加到 Store,无需等待服务端确认
  3. AbortController — 支持取消正在进行的流
  4. 路由跳转 — 创建新 Chat 后自动 router.replace(/chat/c/${chatId})

6.3 useQueryStream() 详解

export function useQueryStream() {
  const submit = useCallback((question: string, existingSessionId?: string | null) => {
    // 1. 取消旧流
    // 2. 调用 startStream() 重置 Store
    // 3. streamQuery() → POST /api/v1/query/stream
    // 4. onEvent → handleStreamEvent() 分发到 Store
  }, []);
  const cancel = useCallback(() => { abortRef.current?.abort(); }, []);
  return { submit, cancel, sessionId };
}

7. 组件体系 (Component Architecture)

7.1 目录结构

components/
├── chat/                  # Chat 相关组件
├── results/               # 结果展示组件
├── admin/                 # Admin Panel 组件
├── landing/               # Landing Page 区块
├── charts/                # 图表组件(chart-panel, visualization-checkpoint, echarts-renderer)
├── feedback/              # 反馈组件
├── markdown/              # Markdown 渲染
├── query/                 # Query Workspace 组件(含 clarification-dialog)
├── session/               # Session 组件
├── ui/                    # 基础 UI 组件 (shadcn/ui)
└── site-sidebar.tsx       # 全局侧边栏

7.2 Chat 组件群

组件 职责
message-composer.tsx 消息输入框(自动 resize、快捷键、发送)
chat-conversation.tsx 对话消息列表(虚拟滚动、自动滚底)
streaming-message.tsx 流式消息渲染(实时更新 Pipeline 进度)
assistant-message.tsx 完成态助手消息(8 个结果 Tab)
assistant-result-block.tsx 结果区块包裹器
thinking-steps.tsx Pipeline 思考步骤动画
user-message.tsx 用户消息气泡
chat-empty-state.tsx 空状态(示例问题引导)
chat-export-button.tsx 对话导出
message-feedback.tsx 消息级别反馈(👍/👎)

Assistant Message 8 个结果 Tab:

Tab 内容
Table 数据表格(排序、筛选、固定列、密度调节、下钻)
SQL SQL 代码块(语法高亮、复制、格式化)
Chart ECharts 可视化
Insights 数据洞察(Markdown 渲染)
Context 业务上下文(关联表、列、指标、规则、术语)
Graph 知识图谱可视化(@antv/g6)
Knowledge 知识问答结果
ML ML 分析结果与图表

7.3 Results 组件群

组件 职责
result-table.tsx 核心数据表格(@tanstack/react-table)
result-table-toolbar.tsx 工具栏(搜索、筛选、列可见性、密度切换)
result-table-footer.tsx 表格底部(分页、行数统计)
result-table-utils.ts 表格工具函数
result-tabs.tsx 结果标签页容器
sql-panel.tsx SQL 展示面板
graph-result-panel.tsx 图谱结果面板
knowledge-panel.tsx 知识回答面板
ml-result-panel.tsx ML 结果面板
business-context-panel.tsx 业务上下文面板
suggested-followups.tsx 推荐追问卡片
drilldown-breadcrumb.tsx 下钻面包屑导航
advanced-filter-dropdown.tsx 高级筛选下拉
column-visibility-dropdown.tsx 列可见性控制

7.4 Landing Page 组件群

组件 职责
hero-section.tsx 首页主视觉区
metrics-bar.tsx 关键指标展示条
governance-section.tsx 三层治理模型介绍
triple-engine-section.tsx 三引擎架构介绍
agent-section.tsx Agent 编排能力介绍
security-section.tsx 安全特性介绍
features-grid.tsx 功能特性网格
cta-section.tsx Call-to-Action 区
footer.tsx 页脚
nav.tsx 导航栏

7.5 基础 UI 组件(54 个)

基于 Radix UI + shadcn/ui 的完整组件库,包括:

完整列表

accordion · alert-dialog · alert · aspect-ratio · avatar · badge · breadcrumb · button · calendar · card · checkbox · collapsible · command · confirm-dialog · context-menu · data-table · date-picker · dialog · dot-pattern · drawer · dropdown-menu · form · health-badge · hover-card · input-otp · input · label · menubar · navigation-menu · popover · progress · providers · radio-group · resizable · scroll-area · select · separator · sheet · sidebar · skeleton · slider · sonner · sql-code-block · stream-status-badge · switch · table · tabs · textarea · theme-toggle · toggle-group · toggle · tooltip · workspace-composer-bar · workspace-empty-state · workspace-header · workspace-sidebar


8. 数据可视化 (Data Visualization)

8.1 ECharts 集成

ECharts 6.0 是主力图表引擎,通过 echarts-for-react 封装为 React 组件。

配置来源: Backend 采用 推荐决策引擎(top-k recommendation + adapter render),95%+ 的请求无需 LLM。 响应中包含 echarts_option(完整配置)、template_ref(模板引用)以及 candidates/confidence/checkpoint_status(决策元数据)。

flowchart LR
    BE["Backend Recommendation Engine<br/>(35 templates, top-k scoring)"] -->|"SSE: visualization event<br/>{echarts_option, template_ref,<br/>candidates, confidence,<br/>checkpoint_status}"| FE[Frontend]
    FE -->|"High confidence<br/>(auto_pass)"| EC[ECharts Component]
    FE -->|"Low confidence<br/>(needs_review)"| CP[Checkpoint Dialog]
    CP -->|"User selects"| HY[Client Hydration]
    FE -->|"Fallback: hydrateChart(template_ref, data)"| HY
    HY --> EC
    EC --> R[Rendered Chart]

推荐决策架构(Backend):

Query Result (columns, rows, row_count, intent_type)
┌─────────────────────────────────────┐
│  DataShapeAnalyzer (pure Python)     │  ← 列分类、结构检测
└──────────────────┬──────────────────┘
┌─────────────────────────────────────┐
│  ChartMatcher.recommend(top_k=3)     │  ← 候选评分、置信度计算、checkpoint 判定
└──────────────────┬──────────────────┘
┌─────────────────────────────────────┐
│  EChartsAdapter (RendererAdapter)    │  ← 数据绑定 + 主题覆盖
│  (35 templates × 4 themes)           │  ← Output: echarts_option
└─────────────────────────────────────┘

HITL Checkpoint(低置信度人工确认):

当推荐置信度低于阈值(0.50)或 top-1/top-2 分差过小(< 0.05)时,前端展示候选确认 UI:

  • streamStatus 变为 "viz_checkpoint",暂停后续流处理
  • VisualizationCheckpointDialog 展示 2-3 个候选图表的迷你预览(通过 hydrateChart() 渲染)
  • 用户可选择:接受推荐 / 选择其他候选 / 回退为表格视图
  • 选择后 resolveVizCheckpoint() 更新 store,流恢复为 "done" 状态

前端 ECharts Adapter(lib/chart-templates/):

该模块是前端 ECharts 渲染适配器,不负责可视化决策。当 backend 仅发送 template_ref 时提供客户端渲染:

import { canHydrate, hydrateChart } from "@/lib/chart-templates";

// template_ref from SSE visualization event
if (canHydrate(templateRef)) {
  const option = hydrateChart(templateRef, { columns, rows, rowCount });
  // option is a complete ECharts config, ready to render
}

主题系统: 支持 defaultlightdarkbrand 四种主题,通过 rehydrateWithTheme() 可实时切换:

import { rehydrateWithTheme } from "@/lib/chart-templates";
const darkOption = rehydrateWithTheme(templateRef, data, "dark");

支持的图表类型(35 模板):

类型 模板数 变体
Bar / Column 6 vertical, horizontal, grouped, stacked, waterfall, percentage
Line / Area 7 basic, smooth, area, stacked area, step, multi, dual axis
Pie / Donut 5 basic, donut, rose, nested donut, semi donut
Trend 3 trend line, trend area, multi-trend
Ranking 2 ranking bar, top-N highlight
Combo 2 dual axis (bar+line), overlay
KPI 3 gauge, card, multi-KPI
Specialized 7 heatmap, distribution, funnel, scatter, radar, treemap, progress gauge

8.2 图表-表格联动 (Linked Selection)

sequenceDiagram
    participant Chart
    participant Store as QueryWorkspaceStore
    participant Table as ResultTable

    Chart->>Store: setLinkedSelection({ column, value, source: "chart" })
    Store-->>Table: linkedSelection 变更
    Table->>Table: 高亮匹配行
    Note right of Table: 反向联动:表格点击行 → 图表高亮对应数据点

8.3 @antv/g6 知识图谱

用于展示图谱查询结果(graph 事件),支持:

  • 力导向布局(Force-directed layout)
  • 节点按类型着色(Table / Column / Term / Metric)
  • 边标签(关系类型)
  • 交互缩放与拖拽
  • 节点点击跳转详情

8.4 Recharts 辅助图表

用于简单的统计图表场景(如 Admin Dashboard 中的趋势图),提供声明式 API。


9. 交互设计模式 (Interaction Patterns)

9.1 流式渐进披露 (Progressive Disclosure)

SSE 流式响应按以下顺序逐步展示:

flowchart TB
    A[pipeline_plan] --> B[node_start: 意图解析]
    B --> C[intent + route_decision]
    C --> D[node_start: SQL 生成]
    D --> E[sql]
    E --> F[validation]
    F --> G[node_start: 执行]
    G --> H[data]
    H --> I[visualization]
    I -->|"auto_pass"| J[insights]
    I -->|"needs_review"| CP[checkpoint — HITL 候选确认]
    CP -->|"user resolves"| J
    J --> K[suggested_followups]
    K --> L[done]

视觉效果:

  • thinking-steps.tsx 组件负责 Pipeline 步骤的动画展示
  • 每个节点完成后展示对应结果 Tab
  • 使用 Framer Motion 实现平滑入场动画

9.2 键盘快捷键

快捷键 功能
Enter 发送消息(Composer 焦点时)
Shift + Enter 换行(Composer 焦点时)
Ctrl + Shift + O 新建对话
Escape 取消当前流式请求

9.3 主题切换

基于 next-themes,支持 Light / Dark / System 三种模式:

// components/ui/theme-toggle.tsx
// 使用 useTheme() hook 切换,主题 class 应用到 <html> 元素
// Tailwind CSS 4 dark: variant 自动响应

9.4 响应式设计

断点 行为
Desktop (≥1024px) 双面板布局(侧边栏 + 主内容)
Tablet (768-1023px) 侧边栏可折叠
Mobile (<768px) 底部导航,全屏内容

useMobile() hook 提供设备类型检测。

9.5 通知系统

使用 Sonner 提供 Toast 通知:

  • 成功操作(绿色)
  • 错误提示(红色)
  • 加载状态(带进度指示)
  • 支持 Action 按钮(如 "撤销")

9.6 面板分割

react-resizable-panels 提供可拖拽面板分割:

  • Results 页面:左侧表格 / 右侧多 Tab 面板
  • Chat 页面:侧边栏 / 主对话区
  • 支持双击重置默认比例

10. 环境配置 (Environment Configuration)

10.1 环境变量

变量 类型 默认值 说明
NEXT_PUBLIC_TTD_API_BASE_URL URL http://localhost:8000 Backend API 地址
NEXT_PUBLIC_TTD_DEFAULT_LANGUAGE zh | en zh UI 默认语言
NEXT_PUBLIC_TTD_ENABLE_DEBUG_TOKEN_INPUT true | false false 是否启用 Debug Token 输入框
BETTER_AUTH_URL URL http://localhost:3000 Better Auth 基础 URL
BETTER_AUTH_SECRET string 会话加密密钥(生产必须强随机值)
AUTH_DATABASE_URL DSN Better Auth 数据库连接串
GITHUB_CLIENT_ID string GitHub OAuth App ID(可选)
GITHUB_CLIENT_SECRET string GitHub OAuth App Secret(可选)
NEXT_PUBLIC_GITHUB_AUTH_ENABLED true | false 前端是否显示 GitHub 登录按钮

10.2 环境验证

环境变量在运行时通过 Zod Schema 验证:

// lib/env/index.ts
const envSchema = z.object({
  NEXT_PUBLIC_TTD_API_BASE_URL: z.url(),
  NEXT_PUBLIC_TTD_DEFAULT_LANGUAGE: z.enum(["zh", "en"]).default("zh"),
  NEXT_PUBLIC_TTD_ENABLE_DEBUG_TOKEN_INPUT: z
    .enum(["true", "false"]).default("false")
    .transform((v) => v === "true"),
});

export function getEnv(): Env {
  return envSchema.parse({...});
}

验证时机

getEnv() 在客户端首次调用时执行验证。如缺少必要变量,会抛出 Zod 错误并在控制台显示详细信息。

10.3 配置文件

文件 用途
.env.local 本地开发配置(Git 忽略)
.env.example 配置模板(提交到仓库)
next.config.ts Next.js 配置
tsconfig.json TypeScript 配置
biome.json Biome 格式化 + Lint 配置
postcss.config.mjs PostCSS(Tailwind 集成)
openapi-ts.config.ts OpenAPI 代码生成配置

11. 构建与开发 (Build & Development)

11.1 开发命令

# 安装依赖
task web:install          # bun install

# 启动开发服务器(Turbopack 加速)
task web:dev              # next dev --turbopack

# 生产构建
task web:build            # next build

# 启动生产服务器
task web:start            # next start

# 代码检查
task web:check            # biome check .

# 代码格式化
task web:format           # biome format --write .

# 类型检查
task web:typecheck        # tsc --noEmit

# 生成 OpenAPI 客户端
task web:generate:api     # openapi-ts (从 Backend OpenAPI Schema 生成)

# 完整 CI 流程
task web:ci               # check + typecheck

11.2 开发工作流

flowchart LR
    A[修改代码] --> B[Turbopack HMR]
    B --> C[浏览器热更新]
    D[修改 Backend API] --> E[task web:generate:api]
    E --> F[更新 lib/api/generated/]
    F --> A

11.3 代码生成流程

# 1. 确保 Backend 运行中
task backend:dev

# 2. 生成 OpenAPI 客户端
task web:generate:api
# 等效于: OPENAPI_TS_INPUT=http://localhost:8000/openapi.json bun run generate:api

# 3. 生成文件位于 lib/api/generated/
#    - client.gen.ts   → HTTP 客户端配置
#    - sdk.gen.ts      → 按 operationId 命名的 SDK 函数
#    - types.gen.ts    → Request/Response TypeScript 类型

11.4 代码规范

Biome 2.2 同时负责格式化和 Lint:

规则 说明
缩进 2 空格(Tab 存储,空格显示)
引号 双引号
分号 始终添加
行宽 100 字符
Import 排序 自动排序
未使用变量 错误级别

11.5 项目依赖拓扑

graph TD
    A[web] -->|openapi-ts| B[Backend OpenAPI Schema]
    A -->|fetch| C[Backend REST API]
    A -->|SSE| D[Backend Stream Endpoint]
    A -->|环境变量| E[.env.local]

附录 A: SSE 事件流完整示例

event: chat
data: {"chat_id": "abc-123"}

event: message
data: {"message_id": "msg-456", "ordinal": 2}

event: pipeline_plan
data: {"nodes": ["intent", "sql_generation", "validation", "execution", "visualization"]}

event: node_start
data: {"node": "intent", "title": "意图解析"}

event: intent
data: {"intent": {"type": "metric_query", "complexity": "simple"}, "route_decision": "sql"}

event: node_complete
data: {"node": "intent", "status": "success"}

event: node_start
data: {"node": "sql_generation", "title": "SQL 生成"}

event: sql
data: {"sql": "SELECT date, SUM(amount) FROM orders GROUP BY date", "explanation": "按日期汇总订单金额"}

event: node_complete
data: {"node": "sql_generation", "status": "success"}

event: validation
data: {"syntax_pass": true, "policy_pass": true, "explain_pass": true}

event: data
data: {"columns": ["date", "total"], "rows": [["2024-01-01", 1500], ["2024-01-02", 2300]], "row_count": 2, "has_more": false, "execution_time_ms": 45}

event: visualization
data: {"chart_type": "line", "echarts_option": {"xAxis": {"data": ["2024-01-01", "2024-01-02"]}, "series": [{"data": [1500, 2300], "type": "line"}]}, "template_ref": {"template_id": "trend_line", "score": 0.9, "theme": "default", "data_mapping": {"category_col": 0, "value_cols": [1], "series_col": null, "time_col": 0}}}

event: insights
data: {"items": ["订单金额呈上升趋势,1月2日环比增长53%"]}

event: suggested_followups
data: {"items": [{"text": "按产品分类查看", "intent_hint": "drill_down", "depth": null}]}

event: done
data: {"status": "completed", "message_id": "msg-456"}

附录 B: Store 状态生命周期

stateDiagram-v2
    [*] --> idle
    idle --> connecting: submit()
    connecting --> streaming: 首个 SSE event
    streaming --> streaming: handleStreamEvent()
    streaming --> clarification: clarification event
    clarification --> idle: 用户选择后重新提交
    streaming --> done: done event
    streaming --> error: error event / 网络失败
    done --> idle: 新查询
    error --> idle: 重试 / 新查询

附录 C: 文件引用索引

关注领域 核心文件
SSE 协议 lib/api/chat-stream.ts, lib/api/query-stream.ts
Schema 定义 lib/api/sse-schema.ts
状态管理 stores/chat-store.ts, stores/query-workspace-store.ts
Chat 核心 hooks/use-chat-stream.ts, components/chat/
可视化 components/charts/, lib/chart-templates/
API 生成 openapi-ts.config.ts, lib/api/generated/
环境配置 lib/env/index.ts, .env.example
UI 组件 components/ui/ (54 个)