双色球自动化系统 — 架构设计文档
文档编号: ADR-007
Issue: BIZ-74
项目: 双色球自动化系统(lottoData)
架构师: 梁思筑(Serena)
日期: 2026-07-03
版本: v1.0
PRD 来源: BIZ-73(沈路明,双色球 WebUI PRD v1.0)
一、系统概述
1.1 系统定位
双色球自动化系统是一个局域网 Web 应用,提供双色球号码生成、历史数据查看、生成记录管理和统计分析功能。系统基于历史开奖数据分析,使用热冷号策略 + 奇偶比/大小比/和值/跨度调整算法生成推荐号码。
1.2 部署拓扑
1.3 数据流
二、技术选型
2.1 当前技术栈
| 层级 |
技术 |
版本 |
说明 |
| 后端框架 |
Flask |
3.1.3 |
轻量 Web 框架 |
| 号码生成 |
Python |
3.x |
核心算法 |
| 数据处理 |
Pandas + NumPy |
3.0.4 / 1.x |
Excel 读写 + 统计计算 |
| Excel 读写 |
openpyxl |
3.1.5 |
.xlsx 文件操作 |
| 数据抓取 |
requests + BeautifulSoup4 |
2.34.2 / 4.15.0 |
HTTP + HTML 解析 |
| 前端 |
原生 HTML/CSS/JS |
ES6+ |
单文件 SPA,无构建工具 |
| 数据存储 |
Excel + JSON 文件 |
— |
无数据库 |
| 部署 |
systemd + Cron |
— |
直接运行 |
2.2 选型评估
| 决策点 |
当前方案 |
备选方案 |
评估 |
| Web 框架 |
Flask |
FastAPI |
✅ 保持 Flask。项目规模小,同步处理足够;团队熟悉 Flask |
| 前端 |
原生 HTML/JS |
Vue/React |
✅ 保持原生。单页面应用,无构建工具依赖,部署简单 |
| 数据存储 |
Excel + JSON |
SQLite |
⚠️ 建议中期迁移 SQLite。当前 Excel 足够,但并发写入和查询效率有瓶颈 |
| 部署 |
systemd |
Docker |
✅ 保持 systemd。内网环境,单服务简单可靠 |
| 进程模型 |
双 Flask 服务 |
合并为单服务 |
⚠️ 建议合并。当前 web_executor.py(:5000) 和 app.py(:8085) 分离,但功能可整合 |
三、文件级架构拆解
3.1 文件总览
| # |
文件 |
职责 |
行数 |
依赖 |
部署状态 |
| 1 |
lottery.py |
号码生成核心引擎 |
~1090 |
pandas, numpy, openpyxl |
✅ 已部署 |
| 2 |
fetch_data.py |
历史数据抓取脚本 |
~115 |
requests, bs4, pandas, openpyxl |
✅ 已部署 |
| 3 |
web_executor.py |
数据抓取 Web 控制台 |
~170 |
flask |
✅ systemd 已部署 |
| 4 |
web_console.html |
抓取控制台前端 |
~300 |
无 |
✅ 已部署 |
| 5 |
app.py |
号码生成 Web 服务(主应用) |
~480 |
flask, pandas, lottery.py |
⚠️ 未做 systemd |
| 6 |
index.html |
号码生成 WebUI 前端 |
~1170 |
无 |
✅ 已部署 |
| 7 |
deploy/fetch_daily.sh |
每日定时抓取脚本 |
~15 |
bash |
✅ Cron 已配置 |
| 8 |
deploy/lotto-web.service |
web_executor systemd 单元 |
~15 |
systemd |
✅ 已部署 |
| 9 |
.generation_records.json |
生成记录持久化 |
— |
无 |
✅ 运行时生成 |
| 10 |
.fetch_status.json |
抓取状态持久化 |
— |
无 |
✅ 运行时生成 |
3.2 模块依赖关系
关键观察:app.py 和 web_executor.py 共享 双色球历史数据.xlsx 文件,但无进程间通信。两个 Flask 服务独立运行。
四、逐文件函数级设计
4.1 lottery.py — 号码生成核心引擎
职责: 加载历史数据、统计分析、生成号码、保存 Excel
依赖: pandas, numpy, openpyxl, random, re, collections.Counter
4.1.1 类: DoubleColorBallGenerator
| 方法 |
签名 |
输入 |
输出 |
边界条件 |
__init__ |
(history_file, config=None) |
Excel 文件路径, 配置字典 |
— |
config=None 时使用默认配置 |
load_history_data |
() |
无 |
bool |
文件不存在→False; 数据为空→False; 缺"号码"列→False; 有效数据<10条→WARNING |
_calculate_statistics |
() |
无 |
None |
数据为空时直接返回; 统计红球频次、蓝球频次、奇偶比、大小比、和值范围、跨度范围 |
get_hot_red_balls |
(n=10) |
数量 |
List[int] |
统计为空→随机返回; 不足n个→用其他球补全 |
get_cold_red_balls |
(n=10) |
数量 |
List[int] |
同上 |
get_hot_blue_balls |
(n=5) |
数量 |
List[int] |
同上 |
parse_ratio |
(ratio_str) |
比率字符串 |
(int, int) |
NaN→(3,3) 默认值; 非法格式→(3,3) |
_adjust_balls_by_criteria |
(red_balls, current_value, target_value, get_balls_to_remove, get_candidates, recalculate_current) |
红球列表+3个回调函数 |
List[int] |
最多尝试 max_adjustment_attempts=20 次 |
_select_hot_cold_balls |
() |
无 |
List[int] |
热号2-4个+冷号补全; 不足6个→随机补全 |
_adjust_odd_even_ratio |
(red_balls) |
红球列表 |
List[int] |
80%概率选最常见奇偶比, 20%随机; 无统计→不调整 |
_adjust_size_ratio |
(red_balls) |
红球列表 |
List[int] |
80%概率选最常见大小比, 20%随机; 无统计→不调整 |
_adjust_sum_range |
(red_balls) |
红球列表 |
List[int] |
90%概率调整到 mean±std 范围内, 10%保持原样 |
_adjust_span_range |
(red_balls) |
红球列表 |
List[int] |
90%概率调整到 mean±std 范围内, 10%保持原样 |
_select_blue_ball |
() |
无 |
int |
hot_blue_probability=0.7 概率选热号, 否则随机 |
generate_single_ticket_advanced |
() |
无 |
(List[int], int) |
返回 (红球6个排序, 蓝球1个) |
generate_single_ticket_basic |
() |
无 |
(List[int], int) |
完全随机 |
generate_multiple_tickets |
(num_tickets, strategy="advanced") |
注数+策略 |
pd.DataFrame |
去重检查; 每注最多尝试100次; 总失败超限→降级为basic |
save_to_excel |
(tickets_df, num_tickets, strategy) |
DataFrame+注数+策略 |
str|None |
返回文件路径或None; 自动避免覆盖; 含统计信息sheet |
display_statistics |
() |
无 |
None |
打印统计信息到控制台 |
run_tests |
() |
无 |
None |
运行内置测试用例 |
main |
模块级 |
无 |
int |
交互式命令行入口 |
4.1.2 异常场景
| 场景 |
处理方式 |
风险 |
| 历史数据文件不存在 |
load_history_data 返回 False |
低 — 调用方应检查返回值 |
| Excel 文件格式错误 |
pandas 抛异常, catch 后返回 False |
低 |
| 有效数据 < 10 条 |
打印 WARNING, 继续执行 |
中 — 统计结果可能不可靠 |
| 号码解析失败 |
返回空列表 + 0, 继续处理其他行 |
低 |
| 生成号码重复 |
最多尝试 100 次/注, 超限降级为 basic |
低 |
| Excel 写入失败 |
catch 异常, 删除部分文件, 返回 None |
中 — 磁盘满或权限问题 |
| 统计数据为空 |
返回随机号码作为默认值 |
中 — 历史数据不足时退化为随机 |
4.1.3 配置参数
4.2 fetch_data.py — 历史数据抓取脚本
职责: 从 55128.cn 抓取双色球历史开奖数据,保存到 Excel
依赖: requests, bs4.BeautifulSoup, pandas, openpyxl
4.2.1 函数清单
| 函数 |
签名 |
输入 |
输出 |
边界条件 |
fetch_lottery_data |
() |
无 |
List[List[str]]|None |
网络超时30s→None; 未找到表格→None; 解析0条→None |
save_to_excel |
(data_rows) |
二维数据列表 |
bool |
空数据→False; 列数不匹配→截取; 保存失败→False |
main |
() |
无 |
int |
返回 0(成功) / 1(失败) |
4.2.2 关键常量
4.2.3 异常场景
| 场景 |
处理方式 |
风险 |
| 网络请求超时 |
30s 超时, 返回 None |
中 — 网站不可达时抓取失败 |
| 网站返回非 200 |
raise_for_status 抛异常, catch 返回 None |
低 |
| HTML 结构变更 |
soup.find("table") 返回 None |
高 — 55128.cn 改版会导致解析失败 |
| 表格行解析失败 |
continue 跳过该行 |
低 |
| Excel 保存失败 |
catch 异常, 返回 False |
低 |
4.3 web_executor.py — 数据抓取 Web 控制台
职责: 提供 Web 界面执行数据抓取任务,异步运行 fetch_data.py
依赖: flask, subprocess, threading
4.3.1 函数清单
| 函数 |
签名 |
输入 |
输出 |
边界条件 |
load_status |
() |
无 |
None |
从 .fetch_status.json 加载; 文件不存在→使用默认状态 |
save_status |
() |
无 |
None |
使用 status_lock 保证线程安全 |
index |
Flask route GET / |
无 |
HTML 页面 |
返回 web_console.html |
api_status |
Flask route GET /api/status |
无 |
JSON |
返回当前执行状态 |
api_execute |
Flask route POST /api/execute |
无 |
JSON |
已有任务运行中→409; 否则启动后台线程 |
run_script (内部) |
() |
无 |
None |
在 daemon 线程中执行 fetch_data.py; 超时300s; 结果写入状态文件 |
check_dependencies |
() |
无 |
bool |
检查 flask/requests/bs4/pandas/openpyxl 是否安装 |
4.3.2 异常场景
| 场景 |
处理方式 |
风险 |
| 重复执行 |
检查 is_running 标志, 返回 409 |
低 |
| 脚本超时 |
subprocess.run 超时 300s, 设置 last_error |
中 — 长时间占用资源 |
| 脚本失败 |
解析 stderr, 记录 last_error |
低 |
| 线程异常 |
catch Exception, 记录错误, 释放 is_running |
中 |
| 状态文件损坏 |
load_status catch 异常, 使用默认状态 |
低 |
4.3.3 端口与监听
- 监听:
0.0.0.0:5000
- 线程模式:
threaded=True
- systemd 服务:
lotto-web.service
4.4 app.py — 号码生成 Web 服务(主应用)
职责: 提供号码生成、历史数据查看、生成记录管理、统计分析 API
依赖: flask, pandas, lottery.py (DoubleColorBallGenerator)
4.4.1 配置
4.4.2 函数清单
| 函数 |
路由 |
方法 |
输入 |
输出 |
边界条件 |
load_records |
— |
— |
无 |
List[dict] |
文件不存在→[]; JSON 解析失败→[] |
save_records |
— |
— |
List[dict] |
None |
自动创建目录 |
add_record |
— |
— |
strategy, num_tickets, filename |
dict |
插入到列表头部, 自动生成 id |
require_auth |
装饰器 |
— |
Flask request |
— |
auth_enabled=False 时跳过认证 |
api_generate |
/api/generate |
POST |
JSON body (num_tickets, strategy) |
JSON |
参数校验 1-1000; 策略 advanced/basic; 生成失败→500 |
get_statistics_data |
— |
— |
generator(可选) |
dict |
文件不存在→{}; 直接解析 Excel |
api_statistics |
/api/statistics |
GET |
无 |
JSON |
异常→500 |
api_records |
/api/records |
GET |
page, page_size |
JSON |
分页; 默认 page=1, page_size=20 |
api_delete_record |
/api/records/<id> |
DELETE |
record_id |
JSON |
记录不存在→404; 同时删除文件 |
api_download |
/api/download/<path> |
GET |
filepath |
File |
路径安全检查(禁止 .. 和绝对路径); 文件不存在→404 |
api_history |
/api/history |
GET |
page, page_size, search |
JSON |
读取 Excel; 跳过描述行; 支持搜索过滤; 分页 |
api_status |
/api/status |
GET |
无 |
JSON |
返回服务状态(历史数据是否存在、文件大小等) |
api_config |
/api/config |
GET |
无 |
JSON |
返回前端配置 |
index |
/ |
GET |
无 |
HTML |
返回 index.html |
4.4.3 异常场景
| 场景 |
处理方式 |
风险 |
| 历史数据文件不存在 |
/api/generate 返回 500; /api/history 返回 404 |
中 — 首次部署或数据被删 |
| 号码生成失败 |
catch Exception, 返回 500 + 错误信息 |
低 |
| Excel 读取失败 |
catch Exception, 返回 500 |
中 — 文件损坏 |
| 目录遍历攻击 |
api_download 检查 .. 和绝对路径, 返回 403 |
低 |
| 生成记录文件损坏 |
load_records catch 异常, 返回 [] |
低 |
| 并发写入 records |
无锁保护 |
⚠️ 高 — 多用户并发时可能导致数据丢失 |
| 并发生成号码 |
无锁保护 |
⚠️ 中 — Excel 文件并发写入可能损坏 |
4.4.4 端口与监听
- 监听:
0.0.0.0:8085
- 线程模式:
threaded=True
- systemd 服务: 未配置(仅手动启动
python3 app.py)
4.5 index.html — 前端 UI
职责: 单文件 SPA,提供号码生成、历史数据、生成记录、统计分析四个 Tab
依赖: 无外部库(纯原生 HTML/CSS/JS)
4.5.1 页面结构
4.5.2 JS 函数清单
| 函数 |
职责 |
输入 |
输出 |
switchTab(tabName) |
切换 Tab |
tab 名称 |
DOM 显示/隐藏 |
generateTickets() |
调用 /api/generate |
从表单读取参数 |
渲染号码卡片 |
loadHistory(page) |
调用 /api/history |
页码 |
渲染历史数据表格 |
loadRecords(page) |
调用 /api/records |
页码 |
渲染记录卡片列表 |
loadStatistics() |
调用 /api/statistics |
无 |
渲染统计卡片 |
downloadFile(path) |
触发文件下载 |
文件路径 |
浏览器下载 |
deleteRecord(id) |
调用 DELETE /api/records/:id |
记录 ID |
刷新列表 |
searchHistory(query) |
搜索历史数据 |
搜索词(防抖500ms) |
过滤结果 |
4.5.3 CSS 规范
| 元素 |
规范 |
| 主色 |
#e74c3c (红色) |
| 辅色 |
#3498db (蓝色), #8e44ad (紫色渐变) |
| 卡片圆角 |
12px |
| 阴影 |
0 2px 12px rgba(0,0,0,0.08) |
| 响应式 |
viewport 320px-1920px 自适应 |
4.6 web_console.html — 抓取控制台前端
职责: 提供数据抓取的 Web 界面,显示抓取状态和执行按钮
依赖: 无外部库
4.7 deploy/fetch_daily.sh — 定时抓取脚本
职责: Cron 定时执行数据抓取
Cron 表达式: 30 2 * * * (每日 02:30)
异常场景
| 场景 |
处理方式 |
风险 |
| venv 路径不存在 |
脚本执行失败, cron 记录错误 |
中 — Python 环境变更后需更新 |
| 网站不可达 |
fetch_data.py 返回非 0, 日志记录 |
低 — 次日自动重试 |
| 磁盘满 |
Excel 写入失败, 日志记录 |
中 — 需监控磁盘 |
五、数据模型
5.1 存储结构
本项目不使用数据库,所有数据基于文件存储:
| 数据文件 |
格式 |
读取者 |
写入者 |
大小 |
双色球历史数据.xlsx |
Excel |
app.py, lottery.py |
fetch_data.py |
~12KB |
.generation_records.json |
JSON |
app.py |
app.py |
<100KB |
.fetch_status.json |
JSON |
web_executor.py |
web_executor.py |
<1KB |
lottery/*.xlsx |
Excel |
app.py (下载) |
lottery.py |
6-64KB/文件 |
5.2 Excel 数据结构
双色球历史数据.xlsx (历史开奖数据)
| 列 |
类型 |
说明 |
示例 |
| 开奖日期 |
str |
日期 |
"2026-07-02" |
| 期号 |
str |
期号 |
"2026076" |
| 红球 |
str |
6红+1蓝拼接 |
"09101316192108" |
| 开机号 |
str |
开机号码 |
— |
| 和值特征 |
str |
和值 |
"100" |
| 奇偶形态 |
str |
奇偶比 |
"3:3" |
| 大小比 |
str |
大小比 |
"4:2" |
| 奇偶形态2 |
str |
奇偶形态(重复) |
— |
| 跨度 |
str |
跨度 |
"25" |
| 其他 |
str |
其他信息 |
— |
注意: 第一行为描述行,实际数据从第二行开始。
lottery/*.xlsx (生成号码)
Sheet 1: "生成号码"
| 列 |
类型 |
说明 |
| 序号 |
int |
1-N |
| 红球1-红球6 |
int |
排序后的红球 |
| 蓝球 |
int |
1-16 |
| 和值 |
int |
红球之和 |
| 奇偶比 |
str |
"3:3" 格式 |
| 大小比 |
str |
"4:2" 格式 |
| 跨度 |
int |
max(红球)-min(红球) |
Sheet 2: "统计信息"
| 统计项 |
统计值 |
| 生成时间 |
2026-07-03 14:25:30 |
| 生成策略 |
高级策略/基础策略 |
| 生成注数 |
10 |
| 红球热号(前10) |
12, 15, 23, ... |
| 红球冷号(前10) |
4, 7, 31, ... |
| 蓝球热号(前5) |
8, 3, 11, ... |
| 最常见奇偶比 |
3:3 |
| 最常见大小比 |
4:2 |
| 和值范围 |
60-150 |
| 跨度范围 |
15-30 |
.generation_records.json
六、非功能需求
6.1 性能指标
| 指标 |
目标值 |
当前状态 |
说明 |
| 页面加载时间 |
< 3s (P95) |
✅ 满足 |
单文件 HTML, 无外部依赖 |
| API 响应时间 |
< 2s (P95) |
✅ 满足 |
除号码生成外 |
| 号码生成时间 |
< 10s (P95) |
✅ 满足 |
100 注以内高级策略 |
| 并发用户数 |
≥ 10 |
⚠️ 未验证 |
Flask threaded=True, 但无并发测试 |
| 数据文件大小 |
< 1MB |
✅ 满足 |
历史 Excel ~12KB |
6.2 可用性 SLA
| 指标 |
目标值 |
说明 |
| 服务可用性 |
≥ 99% (工作时段 9:00-22:00) |
内网工具, 非生产系统 |
| 数据持久化 |
生成记录永久保存 |
除非用户主动删除 |
| 数据备份 |
每日 Excel 由 Cron 自动更新 |
历史数据可从 55128.cn 重新抓取 |
6.3 安全策略
| 维度 |
当前措施 |
风险评估 |
建议 |
| 网络暴露 |
0.0.0.0:5000 + 0.0.0.0:8085 |
⚠️ 内网全开放 |
限制为 192.168.1.0/24 网段 |
| API 认证 |
可选 Token (auth_enabled=False) |
⚠️ 当前关闭 |
内网可接受, 外网部署需开启 |
| 目录遍历 |
/api/download 路径检查 |
✅ 已防护 |
— |
| 输入校验 |
参数范围检查 |
✅ 基本覆盖 |
— |
| HTTPS |
未配置 |
⚠️ 内网 HTTP |
内网可接受, 外网需 SSL |
| 依赖安全 |
Flask 3.1.3 最新 |
✅ 无已知漏洞 |
定期更新依赖 |
6.4 兼容性
| 平台 |
浏览器 |
版本要求 |
测试状态 |
| PC |
Chrome |
90+ |
✅ 主力测试 |
| PC |
Safari |
14+ |
⏳ 待测 |
| PC |
Edge |
90+ |
⏳ 待测 |
| 移动端 |
iOS Safari |
14+ |
⏳ 待测 |
| 移动端 |
Android Chrome |
90+ |
⏳ 待测 |
| 移动端 |
微信内置浏览器 |
最新版 |
⏳ 待测 |
七、风险评估
| # |
风险 |
概率 |
影响 |
应对措施 |
| R1 |
55128.cn 网站改版导致抓取失败 |
中 |
高 |
增加 HTML 结构版本检测; 备选数据源 |
| R2 |
Excel 并发写入导致数据损坏 |
低 |
高 |
加文件锁或迁移 SQLite |
| R3 |
.generation_records.json 并发写入丢失 |
中 |
中 |
加 threading.Lock 或迁移 SQLite |
| R4 |
app.py 未做 systemd, 进程异常不自动重启 |
高 |
中 |
创建 lotto-app.service systemd 单元 |
| R5 |
历史数据文件损坏后无法生成号码 |
低 |
高 |
定期备份 .xlsx; 增加自动重新抓取 |
| R6 |
爬虫被 55128.cn 限流或封 IP |
低 |
中 |
增加请求间隔; 备选数据源 |
| R7 |
生成大量号码时内存占用高 |
低 |
低 |
限制 max_tickets=1000; 分批生成 |
| R8 |
双 Flask 服务端口管理混乱 |
中 |
低 |
合并为单服务或统一 systemd 管理 |
八、改进建议
8.1 短期改进(1-2 周)
| 优先级 |
改进项 |
工作量 |
负责人 |
| P0 |
为 app.py 创建 systemd service |
0.5h |
opengineer |
| P0 |
app.py 加入 threading.Lock 保护 records 并发写入 |
1h |
costcodev |
| P1 |
统一两个 Flask 服务为单服务(合并 web_executor 功能到 app.py) |
3h |
costcodev |
| P1 |
增加请求间隔到 fetch_data.py(避免被封) |
0.5h |
costcodev |
| P2 |
增加移动端真机测试 |
2h |
designer |
8.2 中期改进(1 月)
| 优先级 |
改进项 |
工作量 |
说明 |
| P1 |
数据存储迁移 SQLite |
8h |
替代 Excel + JSON, 支持并发查询 |
| P2 |
数据可视化图表 |
4h |
Chart.js 展示走势图/分布图 |
| P2 |
备选数据源 |
4h |
增加第二个数据源防单点故障 |
8.3 长期演进(本季度)
| 优先级 |
改进项 |
工作量 |
说明 |
| P3 |
多彩种支持 |
16h |
大乐透、福彩3D 等 |
| P3 |
微信推送 |
8h |
生成结果推送到微信 |
| P3 |
用户权限系统 |
8h |
多用户管理 |
九、开发排期建议
9.1 当前状态评估
系统已完成度: ~90%
- ✅ 号码生成核心 (lottery.py) — 完成且功能丰富
- ✅ 数据抓取 (fetch_data.py + web_executor.py) — 完成且有 systemd 部署
- ✅ Web UI (app.py + index.html) — 完成且有响应式布局
- ✅ 定时任务 (Cron) — 完成且每日运行
- ⚠️ systemd 部署 — app.py 尚未配置 systemd
- ⚠️ 并发安全 — 记录文件无锁保护
9.2 交付计划
本系统主体代码已完成(由刘总本人编写),架构文档主要是对现有代码的规范化拆解和改进建议。后续工作量主要集中在:
| 阶段 |
工作内容 |
负责人 |
预估工时 |
| 阶段1 |
创建 app.py systemd service |
严维序 |
0.5h |
| 阶段2 |
records 并发写入加锁 |
徐聪 |
1h |
| 阶段3 |
功能测试 + 兼容性测试 |
苏绘锦 |
4h |
| 阶段4 |
刘总验收 |
刘总 |
待定 |
| 合计 |
— |
— |
~6h |
十、编码规范与技术栈约束
10.1 Python 编码规范
| 规则 |
要求 |
| Python 版本 |
3.x (项目 venv 已有) |
| 类型注解 |
公开函数推荐标注参数和返回值类型 |
| 命名规范 |
snake_case (函数/变量), PascalCase (类) |
| 常量 |
UPPER_SNAKE_CASE |
| 错误处理 |
绝不 bare except; 明确捕获异常类型 |
| 日志 |
使用 print (当前模式) 或 logging 模块 |
| 文档字符串 |
公开函数推荐 docstring |
10.2 前端编码规范
| 规则 |
要求 |
| HTML |
语义化标签, viewport meta 必须设置 |
| CSS |
CSS 变量管理主题色; 响应式断点 768px |
| JS |
ES6+; 原生无框架; fetch API 调用后端 |
| 安全 |
所有用户输入需校验; innerHTML 谨慎使用 |
10.3 部署规范
| 规则 |
要求 |
| 进程管理 |
systemd (Type=simple, Restart=on-failure) |
| 定时任务 |
crontab (每日 02:30) |
| Python 环境 |
venv 虚拟环境隔离 |
| 依赖管理 |
requirements.txt (未创建, 建议补充) |
| 日志 |
journalctl (systemd) + 文件日志 (Cron) |
| 监控 |
systemctl status + curl /api/status |
十一、API 接口规范
11.1 接口清单(app.py :8085)
| # |
路径 |
方法 |
认证 |
请求参数 |
响应格式 |
说明 |
| 1 |
/ |
GET |
无 |
无 |
HTML |
首页 (index.html) |
| 2 |
/api/generate |
POST |
可选 |
JSON: {num_tickets: int, strategy: str} |
JSON: {success, data: {tickets, total, filename, download_url, record, statistics}} |
生成号码 |
| 3 |
/api/history |
GET |
可选 |
?page=1&page_size=20&search=keyword |
JSON: {success, data: {records, total, page, page_size}} |
历史数据 |
| 4 |
/api/records |
GET |
可选 |
?page=1&page_size=20 |
JSON: {success, data: {records, total, page, page_size}} |
生成记录列表 |
| 5 |
/api/records/:id |
DELETE |
可选 |
URL 参数 id |
JSON: {success, message} |
删除记录 |
| 6 |
/api/download/:path |
GET |
可选 |
URL 参数 filepath |
File (Excel) |
下载文件 |
| 7 |
/api/statistics |
GET |
可选 |
无 |
JSON: {success, data: {hot_reds, cold_reds, hot_blues, ...}} |
统计数据 |
| 8 |
/api/status |
GET |
无 |
无 |
JSON: {success, data: {server_time, history_exists, ...}} |
系统状态 |
| 9 |
/api/config |
GET |
无 |
无 |
JSON: {success, data: {max_tickets, default_tickets, auth_enabled}} |
前端配置 |
11.2 接口清单(web_executor.py :5000)
| # |
路径 |
方法 |
说明 |
| 1 |
/ |
GET |
抓取控制台 (web_console.html) |
| 2 |
/api/status |
GET |
抓取执行状态 |
| 3 |
/api/execute |
POST |
触发数据抓取 |
11.3 错误响应格式
HTTP 状态码使用:
- 200: 成功
- 400: 参数错误
- 401: 未授权(Token 认证开启时)
- 403: 禁止访问(目录遍历等)
- 404: 资源不存在
- 409: 冲突(重复执行)
- 500: 服务器内部错误
十二、部署架构
12.1 当前部署
12.2 建议部署改进
12.3 依赖清单(requirements.txt)
十三、产研评审项
需要评审确认的决策点
| # |
议题 |
当前方案 |
备选方案 |
我的建议 |
| 1 |
app.py 是否做 systemd |
未做 |
创建 lotto-app.service |
✅ 建议创建,确保自动重启 |
| 2 |
双 Flask 服务是否合并 |
分离(port 5000+8085) |
合并为单服务 |
✅ 建议合并,简化部署管理 |
| 3 |
数据存储是否迁移 SQLite |
Excel+JSON |
SQLite |
⚠️ 短期保持文件, 中期迁移 |
| 4 |
前端是否引入框架 |
原生 HTML/JS |
Vue/Alpine.js |
✅ 保持原生, 功能不复杂 |
| 5 |
API 认证是否启用 |
关闭 |
开启 Token 认证 |
⚠️ 内网可关闭, 外网需开启 |
十四、总结
架构评估结论
✅ 系统可用,建议小幅改进后正式交付。
优势:
- 代码已完整实现,功能覆盖全部 PRD 需求
- 号码生成算法丰富(热冷号策略 + 多维度调整)
- 前端响应式设计,PC + 移动端适配
- 部署简单(systemd + cron)
待改进:
- app.py 需创建 systemd service(P0)
- records 文件并发写入需加锁(P0)
- 两个 Flask 服务建议合并(P1)
风险评估: 低风险。系统规模小,部署在内网,无生产级别可用性要求。
架构决策记录
ADR-007-01: 保持 Flask 框架,不迁移 FastAPI
- Context: 项目规模小,同步处理足够,团队熟悉 Flask
- Decision: 保持 Flask
- Consequences: 无异步性能优势,但足够满足需求
ADR-007-02: 保持文件存储,中期考虑 SQLite
- Context: 当前 Excel + JSON 满足数据量需求
- Decision: 短期保持文件存储;数据量 > 5000 条或并发写入问题时迁移 SQLite
- Consequences: 并发写入需加锁保护
ADR-007-03: 保持原生前端,不引入框架
- Context: 单页面 SPA,功能简单,无构建工具依赖
- Decision: 保持原生 HTML/CSS/JS
- Consequences: 复杂交互扩展能力有限,但满足当前需求
架构师: 梁思筑
日期: 2026-07-03
下一步: 提交 Git → 发起产研评审 → 评审通过后通知胡蓉推进开发