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 请求函数。
    • 使用 fetchaxios(如果项目中已引入)进行 HTTP 请求。
    • 统一处理认证 token 的传递(例如,从 NextAuth.jsgetSession 获取)。
    • 统一处理 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函数
      
  2. **修改 qsss-web/src/app/strategies/page.tsx**:
    • 移除 fetchStrategies 模拟函数。
    • StrategiesPage 组件中,使用 getStrategies API 函数获取数据。
    • 处理加载状态和错误状态,例如使用 useStateuseEffectReact 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.pyapp/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 定义明确的响应模型。

具体任务

  1. 定义 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
      
  2. **更新 backend/app/api/v1/endpoints/strategies.py**:
    • get_stock_selections 函数的 response_modelNone 修改为 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. 前端数据缓存
    • 在前端使用 SWRReact 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>
        );
      };
      
  2. 后端 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(...):
          # ... 现有逻辑
      

实施风险与应对

  1. 前后端数据模型不匹配
    • 风险:API 接口定义与实际数据结构不一致,导致前端解析失败。
    • 应对:在开发过程中,前端和后端开发人员应密切沟通,共享最新的数据模型定义。考虑使用 OpenAPI/Swagger 自动生成客户端代码或类型定义。
  2. 认证集成复杂性
    • 风险:NextAuth.js 与 FastAPI JWT 认证集成可能存在细节问题。
    • 应对:仔细阅读 NextAuth.js 和 FastAPI JWT 的官方文档,确保 token 的生成、传递和验证逻辑正确无误。
  3. 性能优化过度或不足
    • 风险:过早优化可能引入不必要的复杂性;优化不足可能导致未来性能瓶颈。
    • 应对:遵循“先测量,后优化”的原则。在解决核心功能问题后,再进行性能测试和有针对性的优化。

未完成开发内容

  • 市场数据集成:仅提供模拟数据流,未集成真实市场数据

已完成开发

选股结果过滤功能

  • 后端:实现策略条件过滤逻辑
  • 前端:完成条件传递和动态表格更新
  • 修复:解决变量冲突和类型错误

投资组合功能

  • 后端:实现Portfolio CRUD API端点
  • 前端:完成投资组合管理页面
  • 类型:统一前后端Portfolio模型
  • 导航:侧边栏添加投资组合入口
  • 修复:解决前端导入和后端UUID/JSON错误

仪表盘真实数据集成

  • 后端:实现市场指标、新闻、组合摘要API
  • 前端:完成三大组件数据集成
  • 移除所有模拟数据逻辑

整体进度评估

已完成大部分核心功能,正在进行性能优化和细节完善。