New backend:
- api/portfolio.py: watchlist CRUD, positions with live P&L, recommendations
- POST /api/portfolio/analyze: batch analysis of watchlist tickers
- GET /api/portfolio/positions: live price from yfinance + unrealized P&L
New frontend:
- PortfolioPanel.jsx with 3 tabs: 自选股 / 持仓 / 今日建议
- portfolioApi.js service
- Route /portfolio (keyboard shortcut: 5)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix ANALYSIS_STAGES key 'trader' → 'trading' to match backend STAGE markers
- Add created_at field to task state at creation, sort list_tasks by it
- Persist task state before broadcast in cancel path (closes restart race)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Font: replace SF Pro with DM Sans (web-available) throughout
- Typography: consistent DM Sans stack, monospace data display
- ScreeningPanel: add horizontal scroll for mobile, fix stat card hover
- AnalysisMonitor: Apple progress bar, stage pills, decision badge
- BatchManager: add copy-to-clipboard for task IDs, fix error tooltip truncation, add CTA to empty state
- ReportsViewer: Apple-styled modal, search bar consistency
- Keyboard: add Escape to close modals
- CSS: progress bar ease-out, sidebar collapse button icon-only mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(qa): ISSUE-001 — misleading empty state message in ScreeningPanel
When API returns 0 results, show '未找到符合条件的股票' instead of
'请先选择筛选模式并刷新' which implied no filtering had been done.
Issue found by /qa on main branch
* feat(web-dashboard): connect frontend to real backend API
Phase 1: Stabilize dashboard by connecting mock data to real backend.
Backend:
- Add GET /api/analysis/tasks endpoint for BatchManager
- Fix subprocess cancellation (poll() → returncode)
- Use sys.executable instead of hardcoded env312 path
- Move API key validation before storing task state (no phantom tasks)
Frontend:
- ScreeningPanel: handleStartAnalysis calls POST /api/analysis/start
- AnalysisMonitor: real WebSocket connection via useSearchParams + useRef
- BatchManager: polls GET /api/analysis/tasks, fixed retry button
- All mock data removed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>