开发指南
编码与文件写入规范
本仓库源码、YAML 配置和 Markdown 文档统一使用 UTF-8 保存。修改含中文、站点定义或长文档的文件时,优先使用 apply_patch 做局部补丁,避免用会整文件重写的脚本。
硬性要求:所有含中文的 Markdown、YAML 站点定义、JSON dump、配置示例和脚本注释都必须按 UTF-8 保存;任何 PR、补丁、脚本生成物都不能引入乱码。提交前若看到 �、问号替代中文、中文字段变成转义残片,先停止继续改动并恢复正确编码后再提交。
仓库根目录 .editorconfig 已设置 charset = utf-8,编辑器应启用 EditorConfig 支持,避免新建或保存文件时落成系统默认编码。
在 Windows PowerShell 中不要直接用未指定编码的 Set-Content、Add-Content、Out-File、重定向 > 批量重写 UTF-8 文件;确需使用时必须显式指定 UTF-8,并在修改后运行 go run ./tools/verify definitions 等校验。站点定义文件尤其要避免整文件读写过滤注释,防止隐藏换行或中文内容被转码成乱码。
必须由脚本写文件时,按下面方式显式写 UTF-8:
powershell
# PowerShell 7+
Set-Content -LiteralPath $path -Value $text -Encoding utf8NoBOM
# Windows PowerShell 5.1
[System.IO.File]::WriteAllText($path, $text, [System.Text.UTF8Encoding]::new($false))提交前建议做一次乱码扫描,发现命中后人工确认:
powershell
rg -n "�|Ã|Â|锛|绋|涓|乱码" README backend frontend mobile读取中文文件排查时可先设置终端编码:
powershell
chcp 65001
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
Get-Content -Encoding utf8 README\07-开发指南.md项目结构
D:\PTPatronus\
├── backend/ Go 后端(19 包 ~7500 行)
│ ├── cmd/ptpatronus/ 入口(main.go)
│ ├── internal/ 全部业务代码
│ ├── definitions/ 站点定义 YAML(20 个)
│ └── configs/ config.example.yaml
├── frontend/ Vue3 Web UI(8 视图)
├── mobile/ Flutter 客户端
├── README/ 本文档
├── Dockerfile 多阶段(前端→embed→后端→运行时)
├── docker-compose.yml
├── Makefile
└── .github/workflows/ CI(ci/docker/flutter-release)常用命令
bash
# 后端
cd backend && go run ./cmd/ptpatronus # 启动
cd backend && go test ./... # 全量测试
cd backend && go vet ./... # 静态检查
# 前端
cd frontend && npm run dev # 开发(:5173 代理 /api)
cd frontend && npm run build # 构建
# Flutter
cd mobile && flutter analyze # 零警告
cd mobile && flutter test # 测试
cd mobile && flutter run -d windows # 运行
# Docker
make up # 构建并启动
make image # 仅构建镜像
# 一键
make test # 全部测试(后端+前端+Flutter)
make embed-preview # 前端构建→拷入 embed 目录→本地验证新增功能的原则(可维护性)
1. 优先复用现有模式
| 要做什么 | 用什么 |
|---|---|
| 新站点适配 | 写 YAML 定义(definitions/),不改代码 |
| 新游戏 | 实现 entertainment.LotteryGame 接口,注册到 app.go |
| 新下载器类型 | 实现 downloader.Downloader 接口,加到 manager.BuildClient |
| 新通知通道 | 实现 notification.Channel 接口,注册到 Manager |
| 新定时任务 | scheduler.AddFunc,或加到 automation.Service |
| 新 API 路由 | handler 放 api/v1/,路由挂到 api/router.go |
| 新 Chain | 继承 chain.Base,通过 RunModule 调度 |
2. 文件组织
- 每个文件单一职责
- 超过 ~400 行主动拆分(参考 qb/ 拆为 client.go + methods.go + convert.go)
- 该规范已由门禁强制:
scripts/check_file_length.sh在 CI 与本地 pre-push 钩子运行; 现存超标文件冻结在scripts/file_length_baseline.txt(棘轮:只许缩不许涨,新增超标即失败)。 新增/改动使文件超 400 行会被拦,拆分后重跑bash scripts/check_file_length.sh init刷新 baseline。 - 通用工具集中(helpers.go / defaults.go / convert.go),不散落
- 站点 YAML 极简(5 行),选择器自动填充
3. 测试
- 每个新包至少有一个
_test.go - HTTP 交互用 httptest(参考 qb/client_test.go, schemas/nexusphp_test.go)
- DB 交互用内存 SQLite +
t.Cleanup关连接(Windows 文件锁) - 集成测试参考
api/integration_test.go(全栈 httptest)
4. 好学校准参考源
- 站点源码:
F:\www.hxpt.org(NexusPHP 完整 PHP 源码) - 站点定义:
backend/definitions/hxpt.yaml(VIP=APP专属VIP,头衔非类名) - 校准测试:
internal/site/hxpt_calib_test.go(钉死选择器正确性) - 好学游戏:
internal/entertainment/hxpt.go(jgg/magic_scratch/medal) - 好学签到:
internal/site/schemas/checkin.go(attendance.php)
5. 财神参考源
- 站点源码:
F:\cspt\cspt-web(Laravel PT,API + 插件层) - 信封:
{ret:200|401, msg, data}(ret==200 为成功) - 财神游戏:
internal/entertainment/cspt.go
环境要求
| 工具 | 版本 |
|---|---|
| Go | 1.23+(本机 1.26.4) |
| Node | 18+(本机 24) |
| Flutter | 3.41+ |
| Docker | 任意现代版本 |
Go 在 C:\Program Files\Go\bin(winget 安装)。bash 中需 export PATH="/c/Program Files/Go/bin:$PATH"。
添加新站点的完整流程
- 写 5 行 YAML(
definitions/xxx.yaml) - 重启后端
- Web UI 添加站点(选定义 → 输入 cookie)
- 连接测试验证登录态
- 如果选择器不对 →
/sites/inspect在线试错 → 覆盖 YAML 中对应字段
好学 VIP 准入流程
- 配置
AUTH_SITE_ENABLED=true - 添加好学站点(cookie)
POST /auth/verify-vip {cookie:"..."}→ 后端抓好学用户页 → 判定等级文本是否含「APP专属VIP」auth.Guard中间件:未通过 VIP 校验 → 限制访问