Files
EnterpriseArchitect/docs/architecture/双色球系统架构设计文档-BIZ-74.md
T
vincent 8171373812 BIZ-74: 双色球系统架构设计文档 v1.0
- 完整文件级/函数级架构拆解
- 10个文件、40+函数的签名/输入/输出/边界条件
- 部署拓扑、数据流、数据模型
- 非功能需求(性能/安全/兼容性)
- 8项风险评估 + 改进建议
- 5项产研评审决策点
- ADR-007 架构决策记录

架构师: 梁思筑
Issue: BIZ-74

Co-authored-by: multica-agent <github@multica.ai>
2026-07-03 16:34:34 +08:00

37 KiB
Raw Blame History

双色球自动化系统 — 架构设计文档

文档编号: ADR-007
Issue: BIZ-74
项目: 双色球自动化系统(lottoData)
架构师: 梁思筑(Serena
日期: 2026-07-03
版本: v1.0
PRD 来源: BIZ-73(沈路明,双色球 WebUI PRD v1.0


一、系统概述

1.1 系统定位

双色球自动化系统是一个局域网 Web 应用,提供双色球号码生成、历史数据查看、生成记录管理和统计分析功能。系统基于历史开奖数据分析,使用热冷号策略 + 奇偶比/大小比/和值/跨度调整算法生成推荐号码。

1.2 部署拓扑

┌──────────────────────────────────────────────────────────┐
│  Ubuntu Server (192.168.1.99)                            │
│                                                          │
│  ┌──────────────────────────────────────────────────┐    │
│  │ lotto-web.service (systemd)                      │    │
│  │   web_executor.py (Flask :5000)                  │    │
│  │   ┌──────────────┐  ┌───────────────┐            │    │
│  │   │ /            │  │ /api/status   │            │    │
│  │   │ /api/execute │  │               │            │    │
│  │   └──────┬───────┘  └───────────────┘            │    │
│  │          │                                       │    │
│  │          ▼                                       │    │
│  │   fetch_data.py ── HTTP ──► 55128.cn            │    │
│  │          │                                       │    │
│  │          ▼                                       │    │
│  │   双色球历史数据.xlsx (Excel 文件)                │    │
│  └──────────────────────────────────────────────────┘    │
│                                                          │
│  ┌──────────────────────────────────────────────────┐    │
│  │ app.py (Flask :8085) ← 手动启动 / 尚未 systemd   │    │
│  │   ┌──────────────┐  ┌───────────────┐            │    │
│  │   │ /            │  │ /api/generate │            │    │
│  │   │ /api/history │  │ /api/records  │            │    │
│  │   │ /api/status  │  │ /api/download │            │    │
│  │   │ /api/config  │  │ /api/statistics│           │    │
│  │   └──────┬───────┘  └───────────────┘            │    │
│  │          │                                       │    │
│  │          ▼                                       │    │
│  │   lottery.py (DoubleColorBallGenerator)           │    │
│  │          │                                       │    │
│  │          ▼                                       │    │
│  │   双色球历史数据.xlsx (Excel)                      │    │
│  │   .generation_records.json (JSON)                │    │
│  │   lottery/ (生成结果 .xlsx)                       │    │
│  └──────────────────────────────────────────────────┘    │
│                                                          │
│  ┌──────────────────────────────────────────────────┐    │
│  │ Cron (每日 02:30)                                 │    │
│  │   deploy/fetch_daily.sh → fetch_data.py          │    │
│  └──────────────────────────────────────────────────┘    │
│                                                          │
│  ┌──────────────────────────────────────────────────┐    │
│  │ 局域网用户 (PC / 移动端)                            │    │
│  │   → http://192.168.1.99:5000 (数据抓取控制台)     │    │
│  │   → http://192.168.1.99:8085 (号码生成 WebUI)     │    │
│  └──────────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────────┘

1.3 数据流

55128.cn ──HTTP fetch──► fetch_data.py ──写入──► 双色球历史数据.xlsx
                                                          │
                                                    读取  │
                                                          ▼
                                               lottery.py (DoubleColorBallGenerator)
                                               ├─ 加载历史数据
                                               ├─ 计算热冷号统计
                                               ├─ 生成号码(高级/基础策略)
                                               └─ 保存结果 → lottery/*.xlsx
                                                          │
                                                    调用  │
                                                          ▼
                                               app.py (Flask :8085)
                                               ├─ /api/generate → 生成号码
                                               ├─ /api/history → 读历史数据
                                               ├─ /api/records → 管理生成记录
                                               ├─ /api/statistics → 统计分析
                                               └─ /api/download → 文件下载
                                                          │
                                                    HTTP  │
                                                          ▼
                                               index.html (前端 UI)
                                               ├─ 号码生成页
                                               ├─ 历史数据页
                                               ├─ 生成记录页
                                               └─ 统计分析页

二、技术选型

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 模块依赖关系

index.html (前端)
    │
    │ HTTP (Flask routes)
    ▼
app.py ──────► lottery.py ──────► 双色球历史数据.xlsx
    │              │
    │              ├─► .generation_records.json
    │              └─► lottery/*.xlsx
    │
    └─► (独立于 web_executor.py)

web_console.html (前端)
    │
    │ HTTP (Flask routes)
    ▼
web_executor.py ──► fetch_data.py ──► 双色球历史数据.xlsx
    │                    │
    │                    └─► HTTP GET → 55128.cn
    │
    └─► .fetch_status.json

关键观察app.pyweb_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 配置参数

DEFAULT_CONFIG = {
    'hot_red_count': 15,           # 热号红球取前15
    'cold_red_count': 10,          # 冷号红球取前10
    'hot_blue_count': 8,           # 热号蓝球取前8
    'hot_blue_probability': 0.7,   # 70%概率选热号蓝球
    'max_adjustment_attempts': 20, # 号码调整最大尝试次数
    'hot_red_display_count': 10,   # 展示热号前10
    'cold_red_display_count': 10,  # 展示冷号前10
    'hot_blue_display_count': 5,   # 展示热号蓝球前5
    'min_tickets': 1,
    'max_tickets': 1000
}

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 关键常量

URL = "https://www.55128.cn/kjh/fcssq-history-120.htm"
OUTPUT_FILE = os.path.join(SCRIPT_DIR, "双色球历史数据.xlsx")
HEADERS = { "User-Agent": "Mozilla/5.0 ...", ... }

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 配置

CONFIG = {
    'host': '0.0.0.0',
    'port': 8085,
    'history_file': '双色球历史数据.xlsx',
    'lottery_output_dir': 'lottery',
    'records_file': '.generation_records.json',
    'api_token': 'lotto2026',
    'auth_enabled': False,       # Token 认证默认关闭
    'max_tickets': 1000,
    'default_tickets': 10,
}

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 页面结构

┌─────────────────────────────────┐
│ Header (标题 + 副标题)           │
├─────────────────────────────────┤
│ Nav Tabs: 生成 | 历史 | 记录 | 统计│
├─────────────────────────────────┤
│                                 │
│ Page Content (Tab 切换)          │
│                                 │
└─────────────────────────────────┘

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)

#!/bin/bash
SCRIPT_DIR="/home/vincent/Studio/lottoData"
VENV_PYTHON="${SCRIPT_DIR}/venv/bin/python3"
FETCH_SCRIPT="${SCRIPT_DIR}/fetch_data.py"
LOG_FILE="${LOG_DIR}/fetch_$(date +%Y%m%d).log"
"${VENV_PYTHON}" "${FETCH_SCRIPT}" >> "${LOG_FILE}" 2>&1

异常场景

场景 处理方式 风险
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

[
  {
    "id": "a1b2c3d4",
    "created_at": "2026-07-03 14:25:30",
    "strategy": "高级策略",
    "num_tickets": 10,
    "filename": "lottery/双色球模拟号码-10注-20260703-001.xlsx",
    "filesize": 11264
  }
]

六、非功能需求

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 错误响应格式

{
  "success": false,
  "error": "错误描述信息"
}

HTTP 状态码使用:

  • 200: 成功
  • 400: 参数错误
  • 401: 未授权(Token 认证开启时)
  • 403: 禁止访问(目录遍历等)
  • 404: 资源不存在
  • 409: 冲突(重复执行)
  • 500: 服务器内部错误

十二、部署架构

12.1 当前部署

┌─────────────────────────────────────────────────────┐
│  Ubuntu-OpenClaw (192.168.1.99)                      │
│                                                       │
│  systemd services:                                    │
│  ├── lotto-web.service → web_executor.py :5000 ✅     │
│  └── (lotto-app.service → app.py :8085) ⚠️ 未创建     │
│                                                       │
│  Cron:                                                │
│  └── 30 2 * * * fetch_daily.sh → fetch_data.py ✅     │
│                                                       │
│  Python venv: /home/vincent/Studio/lottoData/venv/   │
│                                                       │
│  项目目录: /home/vincent/Studio/lottoData/             │
└─────────────────────────────────────────────────────┘

12.2 建议部署改进

# /etc/systemd/system/lotto-app.service
[Unit]
Description=双色球号码生成 Web 服务
After=network.target

[Service]
Type=simple
User=vincent
WorkingDirectory=/home/vincent/Studio/lottoData
ExecStart=/home/vincent/Studio/lottoData/venv/bin/python3 /home/vincent/Studio/lottoData/app.py
ExecStartPre=/home/vincent/Studio/lottoData/venv/bin/python3 -c "import flask; import pandas; import openpyxl; import numpy"
Restart=on-failure
RestartSec=5
KillMode=control-group

[Install]
WantedBy=multi-user.target

12.3 依赖清单(requirements.txt

flask>=3.0
pandas>=2.0
numpy>=1.24
openpyxl>=3.1
requests>=2.31
beautifulsoup4>=4.12

十三、产研评审项

需要评审确认的决策点

# 议题 当前方案 备选方案 我的建议
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 serviceP0
  • 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 → 发起产研评审 → 评审通过后通知胡蓉推进开发