Major architectural shift from Next.js to a lightweight Vite + React SPA model ("Puppet Architecture") to better support real-time workflow visualization and strict type safety.
Key Changes:
1. **Architecture & Build**:
- Initialized Vite + React + TypeScript project.
- Configured Tailwind CSS v4 and Shadcn UI.
- Archived legacy Next.js frontend to 'frontend/archive/v2_nextjs'.
2. **Core Features**:
- **Dashboard**: Implemented startup page with Symbol, Market, and Template selection.
- **Report Page**:
- **Workflow Visualization**: Integrated ReactFlow to show dynamic DAG of analysis tasks.
- **Real-time Status**: Implemented Mock SSE logic to simulate task progress, logs, and status changes.
- **Multi-Tab Interface**: Dynamic tabs for 'Overview', 'Fundamental Data', and analysis modules.
- **Streaming Markdown**: Enabled typewriter-style streaming rendering for analysis reports using 'react-markdown'.
- **Config Page**: Implemented settings for AI Providers, Data Sources, and Templates using TanStack Query.
3. **Documentation**:
- Created v2.0 User Guide ('docs/1_requirements/20251122_[Active]_user-guide_v2.md').
- Implemented 'DocsPage' in frontend to render the user guide directly within the app.
4. **Backend Alignment**:
- Created 'docs/frontend/backend_todos.md' outlining necessary backend adaptations (OpenAPI, Progress tracking).
This commit establishes the full frontend 'shell' ready for backend integration.
401 lines
20 KiB
Markdown
401 lines
20 KiB
Markdown
# 前端重构设计: Vite + React SPA
|
||
日期: 2025-11-22
|
||
状态: 已实现 (Vite + React 重构完成,Mock 验证通过)
|
||
|
||
## 1. 概述与核心理念
|
||
|
||
本文档描述了将 `Fundamental_Analysis` 前端从 Next.js 重构为 Vite + React 的方案。
|
||
新的架构将专注于简单性、类型安全和“后端驱动”的状态模型。
|
||
|
||
### 核心理念
|
||
1. **木偶架构 (Puppet Architecture)**: 前端只包含最小的业务逻辑,它忠实反映后端的状态。
|
||
* 如果后端说“加载中”,我们就显示加载中。
|
||
* 如果后端发送了状态快照,我们就完全按照快照渲染。
|
||
* 不做任何猜测性的 UI 更新 (Optimistic UI)。
|
||
2. **单一数据源 (Single Source of Truth)**: 所有类型 (Structs, Enums) 由 Rust 定义并生成 TypeScript (Zod)。
|
||
* **前端禁止内联定义类型**。
|
||
* 使用 `zod` 对所有输入数据进行运行时校验 (Fail Early)。
|
||
3. **Rustic 风格**:
|
||
* 开启 Strict Mode。
|
||
* 禁止 `any` 类型。
|
||
* 对 Enum 进行穷尽匹配 (Exhaustive matching)。
|
||
4. **Vite + React**: SPA 架构,消除 SSR 代理黑盒,使 SSE 处理更加健壮和透明。
|
||
|
||
## 2. 技术栈
|
||
|
||
| 层级 | 技术 | 选择理由 |
|
||
| :--- | :--- | :--- |
|
||
| **构建工具** | **Vite** | 极速、简单、无隐藏代理黑盒。 |
|
||
| **框架** | **React 19** | 保留现有的 `shadcn/ui` 组件资产。 |
|
||
| **路由** | **React Router v7** | 标准的客户端路由。 |
|
||
| **状态管理** | **TanStack Query** | 服务端状态缓存 (用于配置数据)。 |
|
||
| **全局状态** | **Zustand** | 客户端 UI 状态 (Sidebar, Workflow) 管理。 |
|
||
| **UI 库** | **shadcn/ui** | 延续现有的设计语言 (Tailwind CSS)。 |
|
||
| **可视化** | **ReactFlow** | 用于渲染工作流 DAG 图。 |
|
||
| **数据请求** | **Axios + Zod** | 带运行时校验的类型化 HTTP 客户端。 |
|
||
| **API 生成** | **OpenAPI -> Zod** | 从后端自动生成前端类型。 |
|
||
|
||
## 3. 架构设计
|
||
|
||
### 3.1 类型生成流水线
|
||
后端 (Rust/Axum) 需暴露 `openapi.json` (通过 `utoipa` 等库)。
|
||
前端运行生成脚本:
|
||
`Rust Structs` -> `openapi.json` -> `frontend/src/api/schema.ts` (Zod schemas + TS Types)。
|
||
|
||
### 3.2 状态管理策略
|
||
|
||
#### A. 配置数据 (Pull 模型)
|
||
低频变更的数据 (API Keys, Templates) 由 **TanStack Query** 管理。
|
||
* `useQuery(['llm-providers'])`
|
||
* `useMutation(['update-provider'])`
|
||
|
||
#### B. 工作流数据 (Push/Stream 模型)
|
||
实时流动的数据 (分析进度) 由自定义的 **Workflow Store (Zustand)** 管理,直接连接 SSE。
|
||
* **连接层**: 使用原生 `EventSource` 直接连接 `http://api-gateway:4000/v1/workflow/events/{id}`。
|
||
* **状态机**:
|
||
```typescript
|
||
type TaskInfo = {
|
||
id: string;
|
||
status: 'Pending' | 'Running' | 'Completed' | 'Failed';
|
||
progress?: number; // 0-100
|
||
error?: string;
|
||
logs: string[]; // 实时日志
|
||
};
|
||
|
||
type WorkflowState =
|
||
| { status: 'IDLE' }
|
||
| { status: 'CONNECTING', requestId: string }
|
||
| { status: 'RUNNING', requestId: string, dag: Dag, tasks: Record<string, TaskInfo> }
|
||
| { status: 'COMPLETED', result: any }
|
||
| { status: 'ERROR', error: string };
|
||
```
|
||
|
||
## 4. 页面设计与布局 (ASCII Art)
|
||
|
||
**设计原则**: 严格保留现有 Next.js 版本的 UI 布局、风格和功能流程。
|
||
|
||
### 4.1 整体布局 (Shell)
|
||
保留现有的顶部导航栏设计 (`RootLayout`)。历史报告改为下拉菜单。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| FA Platform |
|
||
| [首页] [历史报告 v] [文档] [配置] |
|
||
+-----------+---------------------------------------------------+
|
||
| | (Dropdown Menu) |
|
||
| | 2025-11-22 10:00: 600519.SS (Success) |
|
||
| | 2025-11-21 14:30: AAPL (Failed) |
|
||
| | ... |
|
||
| +---------------------------------------------------+
|
||
| |
|
||
| <Outlet /> (主内容区域) |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
### 4.2 仪表盘 (Dashboard / Home)
|
||
入口页面,用于发起新的分析。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| 基本面分析报告 |
|
||
| 输入股票代码和市场,生成综合分析报告。 |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| [ Card: Start Analysis ] |
|
||
| +---------------------------------------------------------+ |
|
||
| | 股票代码: [ 600519 ] | |
|
||
| | 交易市场: [ 中国 v ] | |
|
||
| | | |
|
||
| | [ BUTTON: 生成报告 ] | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
### 4.3 报告详情页 (Report View)
|
||
核心页面,负责展示实时工作流状态和分析结果。
|
||
**关键改进**: Tabs 上需有直观的状态提示 (Spinner/Check/X)。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [Card: Header] |
|
||
| 600519.SS Market: CN [Badge: Ready/Analyzing] |
|
||
| [Template Select] [Start Btn] |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| [Tabs List] |
|
||
| +---------------------------------------------------------+ |
|
||
| | [DAG View] (Always First) | |
|
||
| | [Stock Chart] | |
|
||
| | [Fundamental Data] [Spinner] (Fetching...) | |
|
||
| | [Analysis: Basic] [Check] | |
|
||
| | [Analysis: Value] [Spinner] | |
|
||
| | [Analysis: Risk ] [Pending] | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
| (Tab Content Area) |
|
||
| |
|
||
| ----------------------------------------------------------- |
|
||
| Request ID: ... | Time: 12.5s | Tokens: 1500 |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.3.1 DAG 视图 (Workflow Graph)
|
||
使用 ReactFlow 渲染。
|
||
* **节点**: 代表任务 (Fetch Data, Analysis Modules)。
|
||
* **连线**: 代表依赖关系。
|
||
* **状态**: 节点颜色随状态变化 (灰=Pending, 蓝=Running, 绿=Completed, 红=Failed)。
|
||
* **交互**: 点击节点自动切换 Tabs 到对应的详情页。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ DAG View ] |
|
||
| |
|
||
| [Fetch: Tushare] ---> [Fundamental Data] |
|
||
| (Running) (Pending) |
|
||
| | |
|
||
| [Fetch: Finnhub] --------------+ |
|
||
| (Done) | |
|
||
| v |
|
||
| [Analysis: Basic] |
|
||
| (Pending) |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.3.2 Fundamental Data Tab
|
||
展示多个数据源的并行获取状态。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Fundamental Data ] |
|
||
| |
|
||
| [ Card: Tushare Provider ] |
|
||
| Status: [Spinner] Running (3.2s) |
|
||
| Logs: |
|
||
| > Connecting to api.tushare.pro... |
|
||
| > Fetching income statement... |
|
||
| |
|
||
| [ Card: Finnhub Provider ] |
|
||
| Status: [Check] Completed |
|
||
| Result: Fetched 3 years of data. |
|
||
| |
|
||
| [ Card: AlphaVantage Provider ] |
|
||
| Status: [X] Failed |
|
||
| Error: Rate limit exceeded. |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.3.3 Analysis Module Tab
|
||
展示 LLM 分析的流式输出。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Analysis: Basic Analysis ] |
|
||
| |
|
||
| Status: [Spinner] Generating Report... |
|
||
| Model: gpt-4o |
|
||
| |
|
||
| (Markdown Content Streaming Area) |
|
||
| # Basic Financial Analysis |
|
||
| Based on the income statement... [Cursor] |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
### 4.4 配置页面 (Config)
|
||
|
||
#### 4.4.1 AI Providers 配置 (Tab 1)
|
||
|
||
**设计逻辑**:
|
||
1. **Provider 维度**: 允许配置多个 Provider (如 OpenAI, Anthropic, LocalLLM)。
|
||
2. **Model 维度**: 每个 Provider 下包含多个 Model。
|
||
3. **交互流程**: 添加 Provider -> 输入 Key/BaseURL -> 点击 "刷新模型列表" (Fetch List) -> 从下拉框选择或手动添加模型 -> 点击 "测试" (Test) -> 保存。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Tabs: AI Provider | 数据源配置 | 分析模板 | 系统 ] |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| [ Button: + 添加 AI Provider ] |
|
||
| |
|
||
| [ Card: OpenAI (Official) ] [Delete] |
|
||
| +---------------------------------------------------------+ |
|
||
| | Base URL: [ https://api.openai.com/v1 ] | |
|
||
| | API Key: [ ************************ ] [Eye Icon] | |
|
||
| | | |
|
||
| | [ Button: 刷新模型列表 (Refresh List) ] | |
|
||
| | | |
|
||
| | **模型列表 (Models)**: | |
|
||
| | +-----------------------------------------------------+ | |
|
||
| | | gpt-4o [Status: Active] [Test] [Remove] | | |
|
||
| | | gpt-3.5-turbo [Status: Active] [Test] [Remove] | | |
|
||
| | +-----------------------------------------------------+ | |
|
||
| | | |
|
||
| | [ Input: 添加模型 (支持搜索/补全) ] [Button: Add] | |
|
||
| | (输入 "claude" 自动提示 "claude-3-sonnet", etc.) | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
| [ Card: Local LLM (Ollama) ] |
|
||
| ... |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.4.2 数据源配置 (Data Sources) (Tab 2)
|
||
|
||
**设计逻辑**:
|
||
1. **后端驱动 (Backend Driven)**: 页面不硬编码有哪些数据源。
|
||
2. **查询流程**: 前端请求 `GET /configs/data_sources/schema` (或类似接口),后端返回可用的 Provider 列表及其所需配置项 (Schema)。
|
||
3. **动态渲染**: 根据后端返回的 Schema 渲染表单 (如 API Key 输入框, URL 输入框)。
|
||
4. **测试**: 如果后端支持 `Test` 接口,显示测试按钮。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Tabs: AI Provider | 数据源配置 | 分析模板 | 系统 ] |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| (Dynamically Rendered from Backend Config) |
|
||
| |
|
||
| [ Card: Tushare Pro ] (Enabled [x]) |
|
||
| +---------------------------------------------------------+ |
|
||
| | API Token: [ ******************** ] | |
|
||
| | Endpoint: [ http://api.tushare.pro ] | |
|
||
| | [Button: Test Connection] -> (Result: Success/Fail) | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
| [ Card: AlphaVantage ] (Enabled [ ]) |
|
||
| +---------------------------------------------------------+ |
|
||
| | API Key: [ ] | |
|
||
| | [Button: Test Connection] | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.4.3 分析模板配置 (Analysis Templates) (Tab 3)
|
||
|
||
**设计逻辑**:
|
||
1. **模板 (Template)**: 分析报告的骨架,包含多个模块。
|
||
2. **模块 (Module)**: 具体的分析任务 (如 "基本面概览", "风险评估")。
|
||
3. **N*M 模型选择**: 每个模块可以指定特定的 AI 模型。
|
||
* **来源**: 聚合所有 AI Providers 中已启用的模型。
|
||
* **交互**: 下拉搜索框 (Combobox),输入关键词 (如 "gpt") 筛选出 `{provider: "openai", model: "gpt-4"}`。
|
||
4. **依赖管理 (DAG)**: 指定模块依赖关系 (如 "风险评估" 依赖 "基本面概览")。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Tabs: AI Provider | 数据源配置 | 分析模板 | 系统 ] |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| 当前模板: [ 快速分析模板 v ] [+ 新建模板] [删除] |
|
||
| |
|
||
| **分析模块 (Modules)**: |
|
||
| |
|
||
| [ Card: 模块 1 - 基本面概览 ] |
|
||
| +---------------------------------------------------------+ |
|
||
| | ID: basic_analysis | |
|
||
| | 依赖 (Dependencies): [ 无 v ] | |
|
||
| | | |
|
||
| | **模型选择 (Model)**: | |
|
||
| | [ Combobox: gpt-4o (OpenAI) v ] | |
|
||
| | (数据来源: 聚合自 AI Provider Tab 的所有模型) | |
|
||
| | | |
|
||
| | **提示词 (Prompt)**: | |
|
||
| | [ Textarea: Analyze the financial data... ] | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
| [ Card: 模块 2 - 深度风险评估 ] |
|
||
| +---------------------------------------------------------+ |
|
||
| | ID: risk_eval | |
|
||
| | 依赖 (Dependencies): [ 基本面概览 (basic_analysis) x ] | |
|
||
| | Model: [ claude-3-opus (Anthropic) v ] | |
|
||
| | ... | |
|
||
| +---------------------------------------------------------+ |
|
||
| |
|
||
| [ Button: + 添加分析模块 ] [ Button: 保存配置 ] |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
#### 4.4.4 系统状态 (System) (Tab 4)
|
||
|
||
**设计逻辑**:
|
||
1. **Status Check**: 简单的健康看板。
|
||
2. **Modules**: 列出所有微服务/组件的状态 (Running, Degraded, Down)。
|
||
|
||
```
|
||
+---------------------------------------------------------------+
|
||
| [ Tabs: AI Provider | 数据源配置 | 分析模板 | 系统 ] |
|
||
+---------------------------------------------------------------+
|
||
| |
|
||
| **系统健康状态 (System Health)** |
|
||
| |
|
||
| [ API Gateway ] [ Badge: Healthy (Green) ] |
|
||
| [ Workflow Orchestrator] [ Badge: Healthy (Green) ] |
|
||
| [ Data Persistence ] [ Badge: Healthy (Green) ] |
|
||
| [ Report Generator ] [ Badge: Degraded (Yellow) ] |
|
||
| |
|
||
| **服务详情**: |
|
||
| - Database Connection: OK |
|
||
| - NATS Connection: OK |
|
||
| - Redis Cache: OK |
|
||
| |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
## 5. 目录结构 (Proposed)
|
||
|
||
```
|
||
frontend/
|
||
├── public/
|
||
├── src/
|
||
│ ├── api/ # Axios instances, Zod schemas
|
||
│ ├── assets/
|
||
│ ├── components/ # Shared UI components
|
||
│ │ ├── ui/ # shadcn/ui primitives (迁移自原项目)
|
||
│ │ ├── layout/ # Shell, Header
|
||
│ │ ├── workflow/ # DAG Graph, Status Badges
|
||
│ │ └── business/ # 业务组件
|
||
│ │ ├── StockChart.tsx
|
||
│ │ ├── FinancialTable.tsx
|
||
│ │ └── ModelSelector.tsx # 复用的模型选择器
|
||
│ ├── pages/ # 路由页面组件
|
||
│ │ ├── Dashboard.tsx
|
||
│ │ ├── Report.tsx
|
||
│ │ └── config/ # 配置相关页面拆分
|
||
│ │ ├── index.tsx # 配置页 Layout
|
||
│ │ ├── AIProviderTab.tsx
|
||
│ │ ├── DataSourceTab.tsx
|
||
│ │ └── TemplateTab.tsx
|
||
│ ├── hooks/ # Global hooks
|
||
│ ├── lib/ # Utils (cn, formatters)
|
||
│ ├── stores/ # Zustand stores
|
||
│ ├── types/ # Global types (if not in schema)
|
||
│ ├── App.tsx # Router Setup
|
||
│ └── main.tsx # Entry
|
||
├── index.html
|
||
├── package.json
|
||
└── vite.config.ts
|
||
```
|
||
|
||
## 6. 迁移步骤
|
||
|
||
1. **归档**: 将现有 `frontend` 移动到 `frontend/archive/v2_nextjs`。
|
||
2. **初始化**: 在 `frontend` 创建新的 Vite 项目。
|
||
3. **安装依赖**: Tailwind, Shadcn, Axios, Zustand, React Router, Lucide, ReactFlow。
|
||
4. **移植 UI**: 从归档中复制 `components/ui` (shadcn)。
|
||
5. **移植逻辑**:
|
||
* 重写 `useWorkflow` hook,使用新的 Store 模式。
|
||
* 实现 DAG 可视化组件。
|
||
* 实现配置页面的“添加+补全”交互。
|
||
6. **验证**: 测试与后端的 SSE 连接和 DAG 状态同步。
|
||
|
||
## 7. 执行阶段 (Next Steps)
|
||
|
||
1. 归档现有代码。
|
||
2. 初始化 Vite + React 项目。
|
||
3. 配置 Tailwind + Shadcn 环境。
|
||
4. 搭建基础 Layout (Shell)。
|