项目优化方案
问题回顾
在之前的检查中,我们发现了以下主要问题:
- 前端与后端集成问题:前端页面(如策略列表、回测结果)目前使用模拟数据,未与后端 API 实际集成。
- 后端安全隐患:后端 API 认证机制被暂时移除,存在安全风险。
- API 响应模型问题:
get_stock_selectionsAPI 的响应模型定义不明确,可能影响文档和客户端解析。
优化方案总览
本次优化将围绕以下核心目标展开:
- 实现前后端数据流打通:确保前端从后端获取真实数据。
- 强化后端安全性:恢复并完善认证授权机制。
- 提升 API 质量:修正 API 响应模型,确保其规范性。
- 建立开发规范:引入一致性检查,确保代码质量和可维护性。
- 初步性能优化:为关键数据流引入缓存机制。
细化优化方案
1. 前端与后端集成优化
目标:将前端的模拟数据替换为真实的后端 API 调用。
具体任务:
- 统一 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)**:// 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函数
- 在
- **修改
qsss-web/src/app/strategies/page.tsx**:- 移除
fetchStrategies模拟函数。 - 在
StrategiesPage组件中,使用getStrategiesAPI 函数获取数据。 - 处理加载状态和错误状态,例如使用
useState和useEffect或React Query/SWR。
- 移除
- **修改
qsss-web/src/app/backtest/page.tsx**:- 移除模拟数据和
setTimeout逻辑。 - 在
handleBacktestSubmit函数中,调用runBacktestAPI 函数。 - 更新加载状态和错误处理。
- 移除模拟数据和
- **检查并完善 API 代理 (
qsss-web/src/app/api/proxy/route.ts)**:- 确保代理路由正确配置,将前端请求转发到后端服务。
- 关键点:
process.env.NEXT_PUBLIC_BACKEND_URL环境变量必须在部署时正确配置为后端服务的实际 URL。
2. 后端安全性提升
目标:恢复并加强后端 API 的认证和授权机制。
具体任务:
- 恢复认证依赖:
- 在
backend/app/api/v1/endpoints/strategies.py中,取消注释所有需要认证的端点上的current_user: User = Depends(get_current_user)。 - 确保
app.core.deps.py中的get_current_user函数能够正确验证 JWT token 并返回当前用户。
- 在
- 权限细化:
- 对于
create_strategy,update_strategy,delete_strategy等操作,除了认证外,还需确保用户具有相应的权限(例如,只能修改或删除自己创建的策略,或者管理员可以操作所有策略)。代码中已包含此逻辑,需确保其正确启用。
- 对于
- 开发环境认证覆盖(可选但推荐):
- 为了方便开发和调试,可以考虑在开发环境中提供一个临时的认证覆盖机制,例如通过环境变量控制,避免每次调试都进行完整的认证流程。
- **示例 (
backend/app/main.py或app/core/deps.py)**:# 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 定义明确的响应模型。
具体任务:
- 定义
SelectionResponse结构:- 在
backend/app/schemas/strategy.py中,确保SelectionResponse包含所有返回字段,特别是stock字段应引用StockResponse或其简化版本。 - **示例 (
backend/app/schemas/strategy.py)**:# 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
- 在
- **更新
backend/app/api/v1/endpoints/strategies.py**:- 将
get_stock_selections函数的response_model从None修改为List[SelectionResponse]。 - 确保函数内部返回的数据结构与
SelectionResponse模型严格匹配。
- 将
4. 整体项目一致性检查
目标:确保代码风格、数据模型和功能实现的一致性。
具体任务:
- 代码风格统一:
- 前端:配置 ESLint 和 Prettier,并集成到开发流程中,确保所有 TypeScript/JavaScript 代码遵循统一风格。
- 后端:配置 Black 和 Flake8,确保所有 Python 代码遵循 PEP 8 规范。
- 数据模型同步:
- 定期审查前端(TypeScript 接口)和后端(Pydantic Schema, SQLAlchemy Models)的数据模型定义,确保它们之间的一致性。
- 考虑使用工具(如
openapi-typescript)从 OpenAPI 规范自动生成前端类型定义,减少手动同步的工作量和错误。
- 移除所有模拟数据:
- 在整个前端项目中搜索并移除所有硬编码的模拟数据和
setTimeout模拟 API 延迟的代码。
- 在整个前端项目中搜索并移除所有硬编码的模拟数据和
5. 性能优化建议
目标:为关键数据流引入初步的缓存机制,提升响应速度。
具体任务:
- 前端数据缓存:
- 在前端使用
SWR或React Query等库管理数据获取和缓存。这些库可以自动处理数据去重、缓存、重新验证等,显著提升用户体验。 - **示例 (
qsss-web/src/app/strategies/page.tsx中使用 SWR)**:// 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> ); };
- 在前端使用
- 后端 API 缓存(Redis):
- 对于不经常变动或计算成本较高的 API 端点(如
get_strategies),引入 Redis 缓存。 - 需要安装
redis库,并在 FastAPI 应用中集成缓存逻辑。 - **示例 (
backend/app/core/config.py配置 Redis)**:# backend/app/core/config.py REDIS_URL: Optional[str] = os.getenv("REDIS_URL", "redis://localhost:6379/0") - **示例 (
backend/app/api/v1/endpoints/strategies.py使用缓存)**:# 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(...): # ... 现有逻辑
- 对于不经常变动或计算成本较高的 API 端点(如
实施风险与应对
- 前后端数据模型不匹配:
- 风险:API 接口定义与实际数据结构不一致,导致前端解析失败。
- 应对:在开发过程中,前端和后端开发人员应密切沟通,共享最新的数据模型定义。考虑使用 OpenAPI/Swagger 自动生成客户端代码或类型定义。
- 认证集成复杂性:
- 风险:NextAuth.js 与 FastAPI JWT 认证集成可能存在细节问题。
- 应对:仔细阅读 NextAuth.js 和 FastAPI JWT 的官方文档,确保 token 的生成、传递和验证逻辑正确无误。
- 性能优化过度或不足:
- 风险:过早优化可能引入不必要的复杂性;优化不足可能导致未来性能瓶颈。
- 应对:遵循“先测量,后优化”的原则。在解决核心功能问题后,再进行性能测试和有针对性的优化。
未完成开发内容
- 市场数据集成:仅提供模拟数据流,未集成真实市场数据
已完成开发
选股结果过滤功能
- 后端:实现策略条件过滤逻辑
- 前端:完成条件传递和动态表格更新
- 修复:解决变量冲突和类型错误
投资组合功能
- 后端:实现Portfolio CRUD API端点
- 前端:完成投资组合管理页面
- 类型:统一前后端Portfolio模型
- 导航:侧边栏添加投资组合入口
- 修复:解决前端导入和后端UUID/JSON错误
仪表盘真实数据集成
- 后端:实现市场指标、新闻、组合摘要API
- 前端:完成三大组件数据集成
- 移除所有模拟数据逻辑
整体进度评估
已完成大部分核心功能,正在进行性能优化和细节完善。