StudyTimer 是一个仅面向本机使用的学习计时网页应用
它使用 Flask 提供界面和接口,使用 JSON 保存每日累计时长,使用 Chart.js 绘制趋势图,并通过系统 hosts 文件临时屏蔽配置的网站
项目保留了原 README 关于 GPT-4 生成来源的声明,这属于历史出处说明,不代表当前代码已经通过安全审计或生产验收
本文所有数值均根据 2026-08-25 的源码、配置、依赖清单、示例数据、日志与 Git 历史记录
原始 README 完整保存在 docs/legacy/README-original.txt
Warning
当前版本会以管理员权限修改系统 hosts 文件,停止计时还会移除全部指向 0.0.0.0 的条目,可能影响其他屏蔽工具,请先阅读第 5 节与第 10 节
表 1 当前功能
| 功能 | 实现位置 | 当前行为 |
|---|---|---|
| 开始计时 | /start、StudyTimer.start | 记录本机开始时间并写入标准输出 |
| 停止计时 | /stop、StudyTimer.stop | 计算会话时长、累计到当天并保存 JSON |
| 每日记录 | study_data.json | 以日期为键保存累计时长 |
| 周期平均 | calculate_average | 显示最近 7 日、30 日和 365 日中有记录日期的平均值 |
| 趋势图 | Chart.js | 把最近 7 条记录换算为分钟并绘制柱状图 |
| 网站屏蔽 | block_hosts.py | 向系统 hosts 添加 0.0.0.0 映射 |
| 清除当天 | /clear | 删除当天累计记录并立即保存 |
周期平均值只除以实际有记录的日期数,缺失日期没有按零时长计入分母
%% 从开始学习到保存并展示记录的主流程
flowchart TB
A[浏览器切换开始] --> B[Flask 接收 start 请求]
B --> C[记录开始时间]
B --> D[读取屏蔽网站列表]
D --> E[修改系统 hosts 文件]
C --> F[浏览器显示本次计时]
F --> G[浏览器切换停止]
G --> H[Flask 计算会话时长]
H --> I[累计到当天 JSON 记录]
H --> J[移除 hosts 中的 0.0.0.0 条目]
I --> K[页面表格与 Chart.js 图表]
图 4.1 计时、屏蔽、保存和展示流程
main.spec 与 app.manifest 要求 Windows 管理员权限,这是修改系统 hosts 文件所需的高权限边界
当前 block_sites 会添加配置域名,unblock_sites 则按地址删除所有 0.0.0.0 条目,没有限定为本应用创建的域名
Caution
在修复精确回滚逻辑前,请先备份系统 hosts 文件,并避免与广告屏蔽、家长控制或企业安全工具同时使用
根 block_web.txt 是源码运行与 PyInstaller 打包使用的列表,templates/block_web.txt 当前没有被 Python 代码或 main.spec 引用
-
第一步,确认使用隔离的 Python 环境,并理解程序会请求管理员权限
-
第二步,安装经过收敛的最小运行依赖
python -m venv .venv # 创建项目专用 Python 环境
.\.venv\Scripts\Activate.ps1 # 激活 Windows PowerShell 环境
python -m pip install -r requirements-minimal.txt # 只安装应用实际导入的运行依赖-
第三步,编辑根
block_web.txt,每行填写一个需要在计时期间屏蔽的域名 -
第四步,以管理员 PowerShell 启动本地应用
python .\main.py # 启动仅供本机使用的 Flask 开发服务器并自动打开浏览器- 第五步,使用界面开关开始或停止计时,确认停止后系统 hosts 文件仍保留其他工具的必要条目
首次运行时没有 study_data.json 属于正常状态,停止第一次会话后程序会创建该文件
如需界面演示数据,可以复制 study_data.example.json,该文件由仓库内的随机生成脚本创建
表 2 主要配置文件
| 文件 | 用途 | 发布建议 |
|---|---|---|
block_web.txt | 源码运行与打包后的屏蔽列表 | 只提交通用示例,不提交个人访问偏好 |
study_data.json | 本机实际学习记录 | 已加入忽略清单,不应提交 |
study_data.example.json | 随机生成的演示记录 | 可以公开,用于截图和界面测试 |
requirements-minimal.txt | 最小运行依赖 | 日常安装优先使用 |
requirements.txt | 历史整机环境快照 | 仅用于追溯,不建议直接安装 |
main.spec | PyInstaller 打包配置 | 生成物应留在 dist/ 与 build/ |
历史依赖清单中的本机磁盘安装路径已替换为脱敏注释,依赖名称仍被保留
main.spec 会把 HTML 模板和根屏蔽列表一起打包,生成无控制台窗口、请求管理员权限并使用仓库图标的 Windows 可执行文件
python -m pip install pyinstaller # 安装可选的 Windows 打包工具
pyinstaller .\main.spec # 根据仓库规格文件生成 build 与 dist 目录PyInstaller 官方文档说明规格文件可以作为构建入口,输出默认进入 build/ 与 dist/ [1]
旧 README 提到 main.exe,但仓库当前没有跟踪该文件,用户需要自行构建
表 3 已核对证据
| 检查 | 结果 | 边界 |
|---|---|---|
| Python 语法树 | 5 个 Python 文件解析通过 | 证明语法可读,不证明运行正确 |
| 示例数据 | 日期与时长 JSON 可解析 | 属于随机样例,不是用户记录 |
| 历史日志 | 记录本机页面访问、开始请求和重复停止请求 | 日志已摘要后移除,不作为当前回归 |
| GitHub Actions | 无工作流、无运行记录 | 没有持续集成通过证据 |
| 应用测试 | 没有自动化测试文件 | 计时、hosts 回滚和网页交互仍需补测 |
表 4 优先风险
| 级别 | 风险 | 证据 | 建议 |
|---|---|---|---|
| 高 | 停止计时会清除所有 0.0.0.0 hosts 条目 | remove_all_matching 仅按地址筛选 | 只移除本应用加入的域名,并在异常退出时恢复 |
| 高 | 状态修改接口接受 GET 且没有请求保护 | /start、/stop、/clear | 限制为 POST,增加跨站请求保护并保持仅本机监听 |
| 中 | 停止操作会发送重复请求 | 切换处理器与 stopTimer 都调用 /stop | 保留单一请求入口 |
| 中 | 脚本绑定不存在的按钮 | startButton 与 stopButton 不在 HTML 中 | 移除旧监听器或补齐元素 |
| 中 | 内置 Flask 服务器只适合开发 | app.run 直接启动 | 继续保持本机使用,不对外部署 [2] |
| 低 | 平均值忽略无记录日期 | 分母只统计存在记录的日期 | 界面明确标注统计口径或改为自然日平均 |
实际学习记录已经从版本控制入口移出,随机样例改名为 study_data.example.json
运行日志含个人使用时间和本机请求轨迹,本轮已移除 stdout.log 与 stderr.log,并加入忽略规则
原远程截图已经本地化,README 不再依赖个人 GitHub 上传资源地址
仓库不应提交访问令牌、密码、许可证密钥、真实用户标识、个人绝对路径、内部服务地址、实际部署地址、实际学习记录或运行日志
-
精确记录并恢复本应用添加的 hosts 条目
-
为状态修改接口增加 POST 限制、请求保护和异常退出恢复
-
修复重复停止请求、不存在按钮监听器和 CSS 分号错误
-
为计时逻辑、平均值、JSON 持久化、hosts 修改和 Flask 路由增加测试
-
收敛依赖并升级到受支持的 Flask 版本
-
增加无需管理员权限的可选专注模式
项目使用 MIT License,具体授权与免责条款以 LICENSE 为准
Chart.js 通过公共 CDN 加载,离线运行需要自行本地化该依赖
该应用会修改操作系统网络解析配置,使用者需要自行承担测试、备份与恢复责任
[1] PyInstaller Project, “Using PyInstaller.” [Online]. Available: https://pyinstaller.org/en/stable/usage.html. [Accessed: Aug. 25, 2026]
[2] Pallets, “Development Server,” Flask Documentation. [Online]. Available: https://flask.palletsprojects.com/en/stable/server/. [Accessed: Aug. 25, 2026]
