主题
开发工具和脚本
本目录包含项目开发和调试使用的实用工具脚本。
📦 代码生成
build_runner.sh
Flutter 代码生成工具,用于生成 Freezed 模型和其他注解代码。
bash
./scripts/build_runner.sh build # 一次性生成
./scripts/build_runner.sh watch # 监听模式
./scripts/build_runner.sh clean # 清理生成的文件🔧 配置和调试
check_api_config.sh
检查 API 配置状态,验证 .env 文件中的配置是否完整。
bash
./scripts/check_api_config.shview_app_logs.sh
查看应用实时日志(Android 设备)。
bash
./scripts/view_app_logs.sh📊 数据管理
import_vocabulary_to_supabase.py
将本地 vocabulary.db 的数据导入到 Supabase 云端词汇库。
依赖:
bash
pip install supabase pandas python-dotenv配置:需要 .env.supabase 文件(见 docs/deployment/supabase-setup-guide.md)
用法:
bash
python scripts/import_vocabulary_to_supabase.pyexport_vocabulary_to_csv.py
导出词汇库数据到 CSV 文件,用于数据分析或备份。
bash
python scripts/export_vocabulary_to_csv.pydelete_supabase_words.py
删除 Supabase 中的测试词汇数据。
bash
python scripts/delete_supabase_words.py🗄️ 数据库同步
sync_reconcile.sh
设备本地 SQLite 与 Supabase 逐 id 对账,报「谁有谁没有」。只读(本地库是 run-as cat 拷出的副本,Supabase 只发 GET),app 不必在运行。
为什么有它:sync 的丢行是静默的 —— 没有异常,getSyncStatus 只数本地脏行, 云端多出来的行不在它口径里,UI 永远显示「已同步」。历史上两次都是靠人手工比 一次两端行数才发现(「push 75→4」挂了三个月、pull 侧丢行挂了 5 天), 而比完就没了。判据不常驻就等于没有。
bash
bash scripts/sync_reconcile.sh # 仓根或 rvh/ 下都能跑
KEEP_DB=1 bash scripts/sync_reconcile.sh # 保留拉下来的 db 快照退出码:
1本地独有 > 0 → push 侧回归(本地行已 clean 就永远不会重推)2有表没查成 → 本轮无结论,不算绿(写第一版时就踩到:一次 curl 抖动被当成 「云端没有」,推出的丢失链条整个是反的)0其余。云端独有只 warn —— 逐条按打印出来的 watermark 判:晚于它 = 只是还没拉; 早于它却仍缺 = pull 侧跳过后 watermark 越过 = 永久丢失
两侧都已排除墓碑:pull 的「本地无 + remote 删」分支刻意不落墓碑, 「对端删了、本端从来没有过」是正常终局,含墓碑比会报成永久缺口。
⚠️ 需要 admin/.env.local(SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY)。 known_words 刻意不比 —— 预装的 211 个功能词按设计永不 push(born-clean)。
引擎内另有一份每轮 sync 自动跑的轻量版(只比数量、不比 id), 见 lib/features/sync/data/repositories/sync_repository_impl.dart::_reconcileRowCounts。
sync_database.sh
在 Android 设备和电脑之间同步 SQLite 数据库,方便使用 DataGrip/DB Browser 等专业工具调试。
用途:
- 使用专业工具调试数据库结构和数据
- 批量修改数据(更新/删除)
- 数据分析和统计
- 定期备份数据库
基本命令:
bash
./scripts/sync_database.sh pull # 从手机导出到电脑(~/Desktop/app_database_backup/)
./scripts/sync_database.sh push # 从电脑导入到手机(需确认,自动备份)
./scripts/sync_database.sh backup # 仅备份,不覆盖工作文件
./scripts/sync_database.sh status # 查看手机和本地数据库状态典型工作流程:
bash
# 1. 导出数据库
./scripts/sync_database.sh pull
# 2. 在 DataGrip 中编辑
# 数据源:~/Desktop/app_database_backup/reading_vocab.db
# 执行 SQL(查询/更新/批量修改)
# 3. 导入回手机
./scripts/sync_database.sh push
# 4. 重启应用验证
adb shell am force-stop com.example.english_learning_app
adb shell am start -n com.example.english_learning_app/.MainActivity⚠️ 注意事项:
- push 会覆盖手机数据库:脚本自动备份,但请谨慎操作
- 修改后必须重启应用:应用启动时加载数据库,运行中不自动刷新
- 外键约束:删除 reading_sources 会级联删除相关记录
文件位置:
~/Desktop/app_database_backup/
├── reading_vocab.db # 工作文件(用于 DataGrip 编辑)
├── reading_vocab.db.backup_20260102_060000 # 自动备份(带时间戳)
└── ...常见问题:
- push 后应用崩溃? 数据库结构被破坏,使用手机上的备份恢复
- pull 后 DataGrip 显示"locked"? 先停止应用再 pull
- 恢复历史备份? 运行
status查看备份列表,复制到工作文件后 push
🗑️ 数据清理
reset_app_data.sh(推荐 ⭐)
完全重置应用数据,最快最简单的清理方式。
效率: ⚡⚡⚡⚡⚡ 最快(2秒)
用法:
bash
./scripts/reset_app_data.sh会清除:
- ❌ 所有书籍和阅读来源
- ❌ 所有笔记本条目
- ❌ 所有用户设置和开发者设置
- ❌ SharedPreferences 数据
会保留:
- ✅ 无(完全清空,重启后自动导入预装词库)
适用场景:
- 想要完全重新开始
- 最快的清理方式
- 不需要 Root 权限
clear_test_data.sh
选择性清理测试数据,保留用户设置和单词库。
效率: ⚡⚡⚡ 较快(6秒)
用法:
bash
./scripts/clear_test_data.sh会清除:
- ❌ 所有书籍和阅读来源
- ❌ 所有笔记本条目
- ❌ 所有OCR单词位置
- ❌ 所有掌握度追踪
- ❌ 所有阅读来源-单词关系
会保留:
- ✅ 单词库(vocabulary_items)- 8614个预装词
- ✅ 用户设置(SharedPreferences)
- ✅ 开发者设置(OCR调试模式、图像处理开关等)
适用场景:
- 日常开发测试
- 想保留开发者设置(避免重新配置)
- 需要设备 Root 权限 ⚠️
使用建议
第一次清理:
bash
# 使用完全重置(最快,不需要Root)
./scripts/reset_app_data.sh
# 然后配置开发者设置之后的清理:
bash
# 使用选择性清理(保留设置)
./scripts/clear_test_data.sh🧪 测试工具
test_vocabulary_filtering.sh
测试词汇过滤功能,验证 CEFR 等级过滤逻辑。
bash
./scripts/test_vocabulary_filtering.shpush_test_image.sh
推送测试图片到 Android 设备,用于 OCR 功能测试。
bash
./scripts/push_test_image.sh <image_path>pull_cached_photos.sh
从 Android 设备拉取缓存的照片,用于调试图像处理流程。
bash
./scripts/pull_cached_photos.sh📝 使用建议
- 日常开发:主要使用
build_runner.sh和view_app_logs.sh - 配置验证:新环境使用
check_api_config.sh - 数据管理:Supabase 相关操作使用
import_vocabulary_to_supabase.py - 数据库调试:使用
sync_database.sh在设备和电脑间同步数据库 - 功能测试:使用测试工具验证 OCR 和词汇过滤功能
🔒 CI/CD 代码质量门禁
概述
项目配置了完整的代码质量门禁系统,包括:
- GitHub Actions CI - 自动化 CI/CD 流水线
- Pre-commit Hook - 本地预提交检查
- 预提交检查脚本 - 可独立运行的检查工具
install-hooks.sh
安装 Git pre-commit hook。可选、默认不装 —— 本仓质量门走 CI (仓根 .github/workflows/ci-rvh.yml),hook 只是本地提速手段,装不装都不影响 main。
bash
./scripts/install-hooks.sh安装后效果:
- hook 装在仓根
.git/hooks/pre-commit(合仓后rvh/无独立.git) - 只有本次暂存区碰了
rvh/下的文件时才真跑检查,纯 RB 提交直接放行 - 检查失败会阻止提交;
git commit --no-verify可跳过
🔴 2026-08-30 修好之前它是坏的(合仓遗留):脚本检查 rvh/ 下的 .git 目录,而合仓后那个目录已不存在, 一进门就
exit 1;即使绕过,生成的 hook 又去调仓根 scripts/ 下的 pre-commit-check.sh(那个位置没有这个文件) —— 那个文件在rvh/scripts/下。两处都是「路径写死了单仓时期的形状」。
pre-commit-check.sh
独立的代码质量检查脚本,可手动运行或被 Git hook 调用。
bash
./scripts/pre-commit-check.sh # 完整检查(含单元测试)
./scripts/pre-commit-check.sh --quick # 快速检查(跳过测试)检查内容:
| 检查项 | 说明 | 快速模式 |
|---|---|---|
| 代码格式 | dart format 检查 | ✅ |
| 静态分析 | flutter analyze 检查 | ✅ |
| 架构合规 | Clean Architecture 规则检查 | ✅ |
| 单元测试 | flutter test | ❌ 跳过 |
架构合规性检查规则:
Presentation → Data 违规
- Presentation 层不应直接导入 Data 层的 models
- Presentation 层不应直接导入 Data 层的 datasources
- Presentation 层不应直接导入 Repository 实现
Domain 层纯净性
- Domain 层不应依赖 Flutter UI 框架(
flutter/foundation.dart除外) - Domain 层不应依赖 Data 层
- Domain 层不应依赖 Flutter UI 框架(
GitHub Actions CI
🔴 合仓后位置变了:RVH 的 CI 是仓根的 .github/workflows/ci-rvh.yml, 子项目自己那个 .github 目录已于 2026-08-28(合仓 T3-6)整目录删除。触发条件:
- 任意分支 push / PR,且改动命中
paths: rvh/**(纯 RB 提交不触发) - 所有
run:步骤默认在rvh/下执行(defaults.run.working-directory)
⚠️ 那道 dart format 门已于 2026-08-29 删除 —— 它在任何能解析本项目依赖的 Flutter 上都会因 tall-style 重写当场红 502 个文件。要不要做一次全仓重排版记在 仓根 docs/plans/backlog.md(做了会冲掉几乎每个 .dart 的 blame)。
CI Jobs:
- Code Analysis - 代码格式和静态分析
- Architecture Compliance - Clean Architecture 合规性检查
- Unit Tests - 运行单元测试
- Coverage Report - 生成测试覆盖率报告(仅 PR)
doc-consistency-check.sh
文档一致性检查脚本,验证文档间的版本号、链接等一致性。
bash
./scripts/doc-consistency-check.sh检查内容(6 步):
- Schema 版本号一致性(4 个权威文件)
- 数据库文档命名规范
- 通用 Claude Code 教程不得复活(2026-08-29 T2-2 删除后的负向断言)
- 断链检查 —— 委托仓根
scripts/check-doc-links.mjs(2026-08-30 改) - 表数量一致性
- 词汇库大小一致性
🔴 断链那一步 2026-08-30 之前是假的:它是一张写死 3 个文件名的黑名单 (
testing.md/performance.md/DEVLOG.md),名字叫「断链检查」却对任何 新造的断链恒绿 —— T4-3 归档 plan 当天在rvh/docs/README.md造出 2 处真悬挂, 它照样打印「✅ 无常见断链」。现改为调用仓根闸门(模式 B 覆盖rvh/docs/全树), 不在这里造第二个实现。
⚠️ 本脚本与
rvh:doc-consistency-checkskill 是两套并行实现(skill 内联 9 个检查, 本脚本 6 步,交集只有版本号与词汇库)。skill 是活的路径,本脚本长期没人跑 —— 上面那道假闸门就是这么烂掉的。要不要收敛成一套记在rvh/docs/plans/backlog.md。
📝 使用建议
- 日常开发:主要使用
build_runner.sh和view_app_logs.sh - 配置验证:新环境使用
check_api_config.sh - 数据管理:Supabase 相关操作使用
import_vocabulary_to_supabase.py - 数据库调试:使用
sync_database.sh在设备和电脑间同步数据库 - 功能测试:使用测试工具验证 OCR 和词汇过滤功能
- 提交前检查:使用
pre-commit-check.sh确保代码质量 - 安装 hooks:使用
install-hooks.sh配置自动检查
最后更新:2026-02-04