DSAWiki
10使用 · 界面

Web 工作台:把系统装进浏览器

手动分析、历史报告、回测、持仓、配置——一张界面背后的产品逻辑与使用路径。

约 6 分钟 实战 第 10 章 · 使用

命令行适合「每天自动跑」,但不适合「我现在就想看看茅台」。Web 工作台把同一套能力装进浏览器:手动分析、实时进度、历史报告、回测、持仓、告警、选股、配置与 Token 用量,都在一个界面里。

先分清「后端」和「前端」

后端是 FastAPI(Python),负责分析、API、任务队列与静态托管;前端是 React 单页应用(SPA),构建后放进 static/,由后端同源提供。只启动后端、没构建前端时,页面会提示 Frontend Not Built,但 API 仍然可用。

页面地图:12 个路由,各管一件事

工作台布局示意,非实际截图

页面你在这里做什么关键能力
工作台 /看今日概览、自选股状态、快速发起分析手动分析、任务进度、历史入口
策略问股 /chat多轮追问一只股票,选择策略流式输出、工具调用可视化、导出
持仓 /portfolio管理成本、数量、风险暴露市场/币种暴露、风险旗标、导入
决策信号 /decision-signals追踪历史建议是否兑现入场/止损/目标、状态、后验评估
选股 /screening按条件扫描候选池解释「为什么选中 / 为什么是现在」
数据中心 /data看数据源能力与质量市场 × 数据集矩阵、路由优先级、警告
回测 /backtest验证策略/建议的历史表现命中率、收益、回撤、样本量
告警 /alerts设置价格/指标/信号规则冷却、去重、通知联动
用量 /usage查看 Token 与调用成本按模型/渠道/时间聚合
设置 /settings改模型、通知、数据源、调度配置校验、测试渠道、草稿保护
登录 /login单管理员认证首次设密码、会话 Cookie
404 兜底 *未知路径兜底提示,不暴露内部路由

手动分析一次,发生什么

1
提交

前端调用 POST /api/v1/analysis/analyze,可单股或批量。同步模式直接返回 200;异步模式返回 202,并给一个任务 ID;重复提交可能返回 409。

2
排队与执行

任务进入队列,由服务层调用与 CLI 相同的 pipeline.process_single_stock()。不会存在第二套分析逻辑。

3
进度推送

前端共享一个 SSE 连接 GET /api/v1/analysis/tasks/stream,接收创建、开始、进度、完成、失败与心跳事件。

4
读报告

完成后从历史接口读取结构化结果与 Markdown;支持复制、下载、分享图片。

POST /api/v1/analysis/analyze          # 单股/批量分析
GET  /api/v1/analysis/tasks            # 任务列表
GET  /api/v1/analysis/tasks/{id}/flow  # 四段式运行诊断
GET  /api/v1/analysis/status/{id}      # 状态
GET  /api/v1/history                   # 历史分页
GET  /api/v1/history/{id}/markdown     # 完整 Markdown
GET  /api/v1/history/{id}/share-image  # 分享海报

前端:React 19 + Vite + Tailwind

前端是一个典型的现代 SPA:React 19、React Router 7、Vite 7、TypeScript、Tailwind 4、Zustand、axios、Recharts。状态管理很克制,只有少数几个 store:分析任务、Agent 会话、股票池。没有 Redux,也没有 React Query。

  • API 层:axios 同源请求,带 Cookie;响应统一从 snake_case 转 camelCase;401 自动跳登录。
  • 主题:默认深色,首屏脚本恢复上次选择,避免闪烁。
  • 国际化:自研 key 字典(中文/英文),不是 i18next;切换时同步 <html lang>。
  • 构建:npm run build 输出到仓库根 static/,由 FastAPI 托管;npm run dev 可独立开发。
cd apps/dsa-web
npm ci
npm run dev        # 本地开发
npm run build      # 产出到 ../../static
npm run lint
npm run test       # Vitest(CI 默认不跑)
npm run test:smoke # Playwright

后端:FastAPI + SSE + 静态托管

api/app.py 创建 FastAPI 应用,挂载 /api/v1、认证中间件、静态资源与 SPA fallback。lifespan 启动时会恢复 Web 内配置的定时任务、预热股票索引;关闭时停止调度。

能力实现注意
任务进度SSE,30 秒心跳前端共享一个 EventSource,别为每个任务各开一条
Agent 流式POST + 流式响应可取消;不是 WebSocket
静态资源static/ + SPA fallback/api/* 不做 fallback
健康检查/api/healthDocker healthcheck 使用
自动构建WEBUI_AUTO_BUILD启动时尝试 npm 安装/构建,生产环境更推荐预构建

API:15 组、约 131 个端点

所有路由挂在 /api/v1。它不是「内部接口随便开」,而是有认证、错误封装、分页与限流的正式 API,也可以被 Bot、桌面端与外部集成复用。

前缀负责代表端点
/analysis分析任务analyze、tasks、market-review
/agent问股chat、chat/stream、research
/history历史报告list、detail、markdown、share-image
/portfolio持仓导入、快照、风险暴露
/alerts告警规则、冷却、测试
/screening选股运行、结果、解释
/decision-signals决策信号列表、后验评估、反馈
/data数据中心overview、能力矩阵
/system配置与调度config、scheduler/status、test-channel
/usage用量summary
/auth登录状态、登录、登出、改密
/health健康存活与版本

认证:默认关闭,公网必须打开

DSA 是单管理员模型:ADMIN_AUTH_ENABLED=true 后,首次访问会引导设置密码。密码用 PBKDF2-SHA256(10 万次迭代 + 随机盐)存哈希;会话是 HttpOnly + SameSite=Lax 的 dsa_session Cookie,默认 24 小时;失败登录 5 次/300 秒限流;登出会轮换密钥,使所有旧会话失效。

三个安全底线

① ADMIN_AUTH_ENABLED 只读取 .env,仅设置系统环境变量不会生效;② 公网部署必须加 HTTPS 反向代理;③ 不要把 .env、data/、reports/ 暴露到公网或提交到仓库。

认证中间件只保护 /api/v1/*,放行登录、状态、健康检查与文档。未登录返回 401 JSON,前端据此跳转登录页。

持仓、告警、选股与用量

持仓

记录成本、数量、币种与市场,过滤已清仓标的,展示市场暴露、币种暴露与风险旗标。支持图片/CSV/Excel 导入与 Futu 真实持仓。

告警

价格、指标、决策信号都可设规则;触发后经过降噪与冷却,再走统一通知服务。告警不是交易指令,只是提醒。

选股

按条件扫描候选池,输出「为什么选中 / 为什么是现在」的确定性解释,并标注数据质量缺口。

Token 用量

按模型、渠道、时间统计调用与 token,帮助判断「成本花在哪」。用量只记录归一化数字与 HMAC 指纹,不存 Prompt 明文。

桌面端:把 Web 装进一个窗口

apps/dsa-desktop 用 Electron 封装 Web 与后端,打包成可双击安装的客户端,适合不想开浏览器的用户。桌面端复用同一套 API,分享海报可以由本地 Chromium 截图生成。具体打包流程见 docs/desktop-package.md。

常见问题

现象原因处理
页面显示 Frontend Not Built前端未构建到 static/构建前端或用 Docker 镜像
API 能用但页面空白静态资源路径/构建产物缺失检查 static/index.html 与 /assets
设置了环境变量仍无认证认证只读 .env写进 .env 并重启
GitHub Actions 里访问不到 WebActions 只跑 CLI 分析用本地、Docker 或云服务器
任务一直转圈SSE 被代理缓冲/超时关闭反代缓冲,或看任务状态接口
自测一下

为什么 ADMIN_AUTH_ENABLED=true 写在 shell 环境变量里可能不生效?

原因:Web 认证是一个独立模块(src/auth.py),它用 dotenv_values 直接读取 .env。这是一种有意的隔离,但也意味着「export 一下」不会生效。部署时请把认证配置写进 .env,并重启服务。

源码与文档锚点