QSSS_new / docs /optimization_plan.md
misonL's picture
特性:实现对话框、表单、输入框、标签、下拉菜单、分隔线、骨架屏、滑块、表格、文本区域的 UI 组件
c78ce9e
|
Raw
History Blame Contribute Delete
12.6 kB
# 项目优化方案
## 问题回顾
在之前的检查中,我们发现了以下主要问题:
1. **前端与后端集成问题**:前端页面(如策略列表、回测结果)目前使用模拟数据,未与后端 API 实际集成。
2. **后端安全隐患**:后端 API 认证机制被暂时移除,存在安全风险。
3. **API 响应模型问题**`get_stock_selections` API 的响应模型定义不明确,可能影响文档和客户端解析。
## 优化方案总览
本次优化将围绕以下核心目标展开:
1. **实现前后端数据流打通**:确保前端从后端获取真实数据。
2. **强化后端安全性**:恢复并完善认证授权机制。
3. **提升 API 质量**:修正 API 响应模型,确保其规范性。
4. **建立开发规范**:引入一致性检查,确保代码质量和可维护性。
5. **初步性能优化**:为关键数据流引入缓存机制。
## 细化优化方案
### 1. 前端与后端集成优化
**目标**:将前端的模拟数据替换为真实的后端 API 调用。
**具体任务**
1. **统一 API 服务层**
*`qsss-web/src/lib/api.ts` 中定义所有后端 API 请求函数。
* 使用 `fetch``axios`(如果项目中已引入)进行 HTTP 请求。
* 统一处理认证 token 的传递(例如,从 `NextAuth.js``getSession` 获取)。
* 统一处理 API 错误,例如通过 `try-catch` 捕获异常并抛出自定义错误,或使用 `toast` 提示。
* **示例 (`qsss-web/src/lib/api.ts`)**
```typescript
// qsss-web/src/lib/api.ts
import { getSession } from 'next-auth/react'; // 假设使用 NextAuth.js
const API_BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL || '/api/proxy'; // 后端API基础URL,优先使用环境变量,否则使用代理
async function fetchApi(endpoint: string, options?: RequestInit) {
const session = await getSession(); // 获取用户会话
const headers = {
'Content-Type': 'application/json',
...(session?.accessToken && { Authorization: `Bearer ${session.accessToken}` }), // 如果有token,添加认证头
...options?.headers,
};
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
...options,
headers,
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.detail || 'API 请求失败'); // 抛出后端返回的错误信息
}
return response.json();
}
// 获取策略列表
export const getStrategies = async (page: number, pageSize: number, search: string) => {
return fetchApi(`/strategies?skip=${(page - 1) * pageSize}&limit=${pageSize}&search=${search}`);
};
// 运行回测
export const runBacktest = async (strategyId: string, backtestParams: any) => {
return fetchApi(`/strategies/${strategyId}/backtest`, {
method: 'POST',
body: JSON.stringify(backtestParams),
});
};
// ... 其他API函数
```
2. **修改 `qsss-web/src/app/strategies/page.tsx`**:
* 移除 `fetchStrategies` 模拟函数。
* 在 `StrategiesPage` 组件中,使用 `getStrategies` API 函数获取数据。
* 处理加载状态和错误状态,例如使用 `useState` 和 `useEffect` 或 `React Query` / `SWR`。
3. **修改 `qsss-web/src/app/backtest/page.tsx`**:
* 移除模拟数据和 `setTimeout` 逻辑。
* 在 `handleBacktestSubmit` 函数中,调用 `runBacktest` API 函数。
* 更新加载状态和错误处理。
4. **检查并完善 API 代理 (`qsss-web/src/app/api/proxy/route.ts`)**:
* 确保代理路由正确配置,将前端请求转发到后端服务。
* **关键点**:`process.env.NEXT_PUBLIC_BACKEND_URL` 环境变量必须在部署时正确配置为后端服务的实际 URL。
### 2. 后端安全性提升
**目标**:恢复并加强后端 API 的认证和授权机制。
**具体任务**
1. **恢复认证依赖**
*`backend/app/api/v1/endpoints/strategies.py` 中,取消注释所有需要认证的端点上的 `current_user: User = Depends(get_current_user)`
* 确保 `app.core.deps.py` 中的 `get_current_user` 函数能够正确验证 JWT token 并返回当前用户。
2. **权限细化**
* 对于 `create_strategy`, `update_strategy`, `delete_strategy` 等操作,除了认证外,还需确保用户具有相应的权限(例如,只能修改或删除自己创建的策略,或者管理员可以操作所有策略)。代码中已包含此逻辑,需确保其正确启用。
3. **开发环境认证覆盖(可选但推荐)**
* 为了方便开发和调试,可以考虑在开发环境中提供一个临时的认证覆盖机制,例如通过环境变量控制,避免每次调试都进行完整的认证流程。
* **示例 (`backend/app/main.py` 或 `app/core/deps.py`)**
```python
# backend/app/core/deps.py (示例)
from app.models.user import User
async def get_current_user_for_dev():
# 仅在开发环境生效,返回一个模拟的管理员用户
return User(id="dev_admin_user_id", username="dev_admin", is_admin=True)
# 在 main.py 中根据环境选择依赖
# if os.getenv("APP_ENV") == "development":
# app.dependency_overrides[get_current_user] = get_current_user_for_dev
```
### 3. API 响应模型修正
**目标**:为 `get_stock_selections` API 定义明确的响应模型。
**具体任务**
1. **定义 `SelectionResponse` 结构**
*`backend/app/schemas/strategy.py` 中,确保 `SelectionResponse` 包含所有返回字段,特别是 `stock` 字段应引用 `StockResponse` 或其简化版本。
* **示例 (`backend/app/schemas/strategy.py`)**
```python
# backend/app/schemas/strategy.py
from pydantic import BaseModel
from datetime import date
from typing import Optional
from app.schemas.stock import StockResponse # 假设有StockResponse
class SelectionResponse(BaseModel):
id: str
strategy_id: str
user_id: str
selection_date: date
stock_id: str
stock_code: str
stock_name: str
rank: int
score: Optional[float] = None
reason: Optional[str] = None
# 添加从 stock_data 来的字段,例如:
latest_price: Optional[float] = None
change_percent: Optional[float] = None
# ... 其他行情数据字段
class Config:
from_attributes = True # 兼容 SQLAlchemy ORM
```
2. **更新 `backend/app/api/v1/endpoints/strategies.py`**:
* 将 `get_stock_selections` 函数的 `response_model` 从 `None` 修改为 `List[SelectionResponse]`。
* 确保函数内部返回的数据结构与 `SelectionResponse` 模型严格匹配。
### 4. 整体项目一致性检查
**目标**:确保代码风格、数据模型和功能实现的一致性。
**具体任务**
1. **代码风格统一**
* 前端:配置 ESLint 和 Prettier,并集成到开发流程中,确保所有 TypeScript/JavaScript 代码遵循统一风格。
* 后端:配置 Black 和 Flake8,确保所有 Python 代码遵循 PEP 8 规范。
2. **数据模型同步**
* 定期审查前端(TypeScript 接口)和后端(Pydantic Schema, SQLAlchemy Models)的数据模型定义,确保它们之间的一致性。
* 考虑使用工具(如 `openapi-typescript`)从 OpenAPI 规范自动生成前端类型定义,减少手动同步的工作量和错误。
3. **移除所有模拟数据**
* 在整个前端项目中搜索并移除所有硬编码的模拟数据和 `setTimeout` 模拟 API 延迟的代码。
### 5. 性能优化建议
**目标**:为关键数据流引入初步的缓存机制,提升响应速度。
**具体任务**
1. **前端数据缓存**
* 在前端使用 `SWR``React Query` 等库管理数据获取和缓存。这些库可以自动处理数据去重、缓存、重新验证等,显著提升用户体验。
* **示例 (`qsss-web/src/app/strategies/page.tsx` 中使用 SWR)**
```typescript
// qsss-web/src/app/strategies/page.tsx
import useSWR from 'swr';
import { getStrategies } from '@/lib/api'; // 导入统一的API函数
const fetcher = ([page, pageSize, search]: [number, number, string]) => getStrategies(page, pageSize, search);
const StrategiesPage: React.FC<StrategiesPageProps> = ({ searchParams }) => {
const page = parseInt(searchParams.page || '1', 10);
const pageSize = parseInt(searchParams.pageSize || '10', 10);
const search = searchParams.search || '';
const { data, error, isLoading } = useSWR(['strategies', page, pageSize, search], fetcher);
if (error) return <div>加载失败: {error.message}</div>;
if (isLoading) return <div>加载策略中...</div>;
return (
<RequireAuth>
<div className="container mx-auto p-4">
<StrategyListClientWrapper
initialData={data?.data || []} // SWR 返回的数据结构可能需要调整
total={data?.total || 0}
page={page}
pageSize={pageSize}
search={search}
/>
</div>
</RequireAuth>
);
};
```
2. **后端 API 缓存(Redis)**:
* 对于不经常变动或计算成本较高的 API 端点(如 `get_strategies`),引入 Redis 缓存。
* 需要安装 `redis` 库,并在 FastAPI 应用中集成缓存逻辑。
* **示例 (`backend/app/core/config.py` 配置 Redis)**:
```python
# backend/app/core/config.py
REDIS_URL: Optional[str] = os.getenv("REDIS_URL", "redis://localhost:6379/0")
```
* **示例 (`backend/app/api/v1/endpoints/strategies.py` 使用缓存)**:
```python
# backend/app/api/v1/endpoints/strategies.py
from fastapi_cache.decorator import cache # 假设使用 fastapi-cache
@router.get("", response_model=List[StrategyResponse])
@cache(expire=300) # 缓存5分钟
async def get_strategies(...):
# ... 现有逻辑
```
### 实施风险与应对
1. **前后端数据模型不匹配**
* **风险**:API 接口定义与实际数据结构不一致,导致前端解析失败。
* **应对**:在开发过程中,前端和后端开发人员应密切沟通,共享最新的数据模型定义。考虑使用 OpenAPI/Swagger 自动生成客户端代码或类型定义。
2. **认证集成复杂性**
* **风险**:NextAuth.js 与 FastAPI JWT 认证集成可能存在细节问题。
* **应对**:仔细阅读 NextAuth.js 和 FastAPI JWT 的官方文档,确保 token 的生成、传递和验证逻辑正确无误。
3. **性能优化过度或不足**
* **风险**:过早优化可能引入不必要的复杂性;优化不足可能导致未来性能瓶颈。
* **应对**:遵循“先测量,后优化”的原则。在解决核心功能问题后,再进行性能测试和有针对性的优化。
## 未完成开发内容
* **市场数据集成**:仅提供模拟数据流,未集成真实市场数据
## 已完成开发
**选股结果过滤功能**
* 后端:实现策略条件过滤逻辑
* 前端:完成条件传递和动态表格更新
* 修复:解决变量冲突和类型错误
**投资组合功能**
* 后端:实现Portfolio CRUD API端点
* 前端:完成投资组合管理页面
* 类型:统一前后端Portfolio模型
* 导航:侧边栏添加投资组合入口
* 修复:解决前端导入和后端UUID/JSON错误
**仪表盘真实数据集成**
* 后端:实现市场指标、新闻、组合摘要API
* 前端:完成三大组件数据集成
* 移除所有模拟数据逻辑
## 整体进度评估
已完成大部分核心功能,正在进行性能优化和细节完善。