# 项目优化方案 ## 问题回顾 在之前的检查中,我们发现了以下主要问题: 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 = ({ 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
加载失败: {error.message}
; if (isLoading) return
加载策略中...
; return (
); }; ``` 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 * 前端:完成三大组件数据集成 * 移除所有模拟数据逻辑 ## 整体进度评估 已完成大部分核心功能,正在进行性能优化和细节完善。