新增 Web 浏览端(Go+Vue 报表系统)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fish
2026-05-03 14:34:50 +08:00
parent bf8f578761
commit 750584e619
47 changed files with 2557 additions and 18 deletions

View File

@@ -129,31 +129,60 @@ sqlite3 data/futures.db ".schema"
```
trade/
├── docker-compose.yml # Docker Compose 编排
├── docker-compose.yml # Docker Compose 编排(tushare + web 两个服务)
├── 使用说明.md # 本文件
├── data/ # SQLite 数据库目录(gitignored)
── futures.db
── futures.db # tushare 写入,web 只读
│ └── auth.db # web 自己维护的用户表
├── .gitignore # Git 忽略配置
── tushare/ # Python 数据服务
├── Dockerfile # 镜像构建
├── requirements.txt # Python 依赖
├── .env # TUSHARE_TOKEN(本地,不入库)
└── src/ # Python 包
├── models.py # 数据模型
├── fetcher.py # tushare 数据拉取
├── scorer.py # 打分模型核心
├── storage.py # SQLite 持久化
├── contracts.py # 主力合约轮换规则
├── notifier.py # Bark 推送
└── main.py # CLI 入口
── tushare/ # Python 数据服务
├── Dockerfile
├── requirements.txt
├── .env # TUSHARE_TOKEN(本地,不入库)
└── src/ # 数据采集 + 打分 + Bark 推送
├── models.py
├── fetcher.py
├── scorer.py
├── storage.py
├── contracts.py
├── notifier.py
└── main.py
└── web/ # Web 浏览端
├── .dockerignore
├── backend/ # Go 1.25 后端 (chi + modernc.org/sqlite + JWT)
│ ├── Dockerfile # 多阶段:node 构 UI → go 构二进制 → alpine 运行
│ ├── go.mod
│ ├── main.go
│ ├── embed.go # //go:embed all:dist
│ ├── .env.example # ADMIN_USER/ADMIN_PASS/JWT_SECRET 示例
│ ├── dist/ # 占位,Docker 构建期被 vite 输出覆盖
│ └── internal/
│ ├── config/ # 环境变量加载
│ ├── store/ # futures.db 只读 + auth.db 用户表
│ ├── auth/ # JWT + bcrypt + 首启 admin 引导
│ ├── middleware/ # RequireUser / RequireAdmin / 日志
│ ├── handlers/ # 登录 / 打分 / K线 / 用户管理
│ └── router/ # chi 路由装配
└── frontend/ # Vue 3 + Vite + Element Plus + ECharts
├── package.json
├── vite.config.ts
├── tsconfig.json
├── index.html
└── src/
├── main.ts / App.vue
├── router/ # 守卫(未登录/管理员路由)
├── stores/auth.ts # Pinia,持久化 token
├── api/ # axios 封装 + 各端点
├── views/ # 登录 / 打分列表 / 图表 / 用户管理
└── components/ # 抽屉 + ECharts K 线
```
## 技术栈
- **Python 3.13** (alpine 基础镜像)
- **tushare** — 中国金融数据接口
- **pandas** — 数据处理
- **SQLite** — 本地数据存储
- **Python 3.13** (alpine) + **tushare** + **pandas** — 数据采集与打分
- **Go 1.25.8** (alpine 3.23) + **chi** + **modernc.org/sqlite** + **JWT** — Web 后端
- **Vue 3** + **Vite** + **Element Plus** + **ECharts**Web 前端
- **SQLite** — 本地数据存储(双库:`futures.db` 业务 + `auth.db` 鉴权)
- **Docker / Docker Compose** — 容器化部署
## 常见问题
@@ -169,3 +198,85 @@ A: 郑商所用 `.ZCE` 后缀(如 `FG2609.ZCE`),上期所用 `.SHF`,大
**Q: 如何定时自动跑?**
A: 通过宿主机 cron / launchd 等定时器调用 `docker-compose run --rm tushare ...`。打分结束会通过 Bark 推送结果(见 `tushare/src/notifier.py`)。
## Web 报表(浏览端)
`./web/` 提供一个图形化的浏览端,展示 tushare 流水线写入 `data/futures.db` 的打分与行情数据。后端 Go(`golang:1.25.8-alpine3.23`)读取数据库,前端 Vue 3 + Element Plus + ECharts,通过 docker-compose 一起部署。
### 1. 配置首启凭据
`web/backend/.env` 写入(`.env` 已 gitignored,可参考 `web/backend/.env.example`):
```bash
ADMIN_USER=admin
ADMIN_PASS=请改成强密码
JWT_SECRET=$(openssl rand -hex 32)
```
`ADMIN_USER`/`ADMIN_PASS` 仅在 `auth.db` 中没有任何 admin 时生效,首次启动会以这一对凭据建立管理员;之后即使改这两个变量也不会改密。`JWT_SECRET` 必须 ≥16 字符。
### 2. 启动
```bash
# 构建并启动 web 服务,不影响现有 tushare
docker-compose up -d --build web
# 查看启动日志:首启会出现 [bootstrap] admin 'xxx' created
docker-compose logs -f web
```
浏览器访问 `http://localhost:8080`,用上一步的管理员账号登录。
### 3. 页面说明
- **打分列表** `/scores`:按合约、日期、条数筛选,展示综合分/信号/三层得分;点击「明细」弹抽屉,显示短期 7 日逐日打分、中期(15d)价格收益与资金意愿、长期(30d)持仓变化。
- **K 线 / 持仓** `/chart`:选合约 + 日期区间,主图蜡烛(开高低收),副图持仓量曲线;鼠标拖选缩放。
- **用户管理** `/admin/users`:仅管理员可见。可创建子账号(`user` 默认,亦可建 `admin`)、重置密码、禁用/启用、删除;不允许对自己执行禁用或删除。
普通用户登录后 `/admin/*` 路径会被前端守卫拦截并跳回 `/scores`,后端也会以 403 拒绝。
### 4. 子账号维护流程
1. 用 admin 登录 → 进入 `/admin/users` → 「新建账号」,填写用户名 / 密码(≥6 位) / 角色。
2. 把账号发给同事即可登录;无注册入口。
3. 离职 / 风险事件:用「禁用」临时停用(token 立即失效,前端不能再请求),或「删除」彻底清除。
### 5. 数据流向与数据库分离
```
tushare(写) → data/futures.db ──(只读挂载 :ro)──> web 服务 ←(读写)→ data/auth.db
```
`futures.db` 的 schema 与 Python 端一致(`candles` + `scores`)。`auth.db` 表为:
```sql
users(id, username UNIQUE, password_hash, role IN ('admin','user'),
disabled, created_at, updated_at)
```
两个 DB 都在 `./data/` 目录,均被 `.gitignore` 覆盖。
### 6. 常见问题
**Q: 忘记管理员密码怎么办?**
```bash
docker-compose stop web
sqlite3 data/auth.db "DELETE FROM users WHERE role='admin';"
# 修改 web/backend/.env 里的 ADMIN_USER/ADMIN_PASS
docker-compose up -d web
```
启动时会重新触发 bootstrap 写入新的 admin。
**Q: 改了 Go / Vue 代码但页面没变?**
源码不挂载,镜像内是 COPY 进去的。重建:`docker-compose build web && docker-compose up -d web`
**Q: 登录提示 "JWT_SECRET 必须至少 16 个字符"?**
`web/backend/.env` 没设或太短,用 `openssl rand -hex 32` 生成一个 64 字符的十六进制字符串即可。
**Q: 容器内能不能误写 futures.db?**
不能。容器以 `./data:/app/data:ro` 挂载,Go 又用 `mode=ro&query_only(true)` 打开数据库,双层保险。auth.db 走另一个挂载点 `./data:/app/auth`(同物理目录但路径不同,无 `:ro`)。