File size: 12,570 Bytes
c78ce9e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | # 项目优化方案
## 问题回顾
在之前的检查中,我们发现了以下主要问题:
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
* 前端:完成三大组件数据集成
* 移除所有模拟数据逻辑
## 整体进度评估
已完成大部分核心功能,正在进行性能优化和细节完善。
|