181 lines
6.8 KiB
Markdown
181 lines
6.8 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project
|
||
|
||
PPGo_Job — 定时任务管理系统,已从 Beego v1 重构为 **GoFrame v2**。支持本机 Shell 执行、HTTP 请求任务和 SSH 远程执行。
|
||
|
||
- **框架:** GoFrame v2
|
||
- **数据库:** SQLite (`modernc.org/sqlite`,纯 Go,无 CGO)
|
||
- **定时器:** GoFrame `gcron`(6 段 cron 表达式,含秒)
|
||
- **前端:** Vue 3 + Element Plus + TypeScript(Vite 构建),旧 LayUI 兼容层已移除
|
||
- **远程执行:** SSH (`golang.org/x/crypto/ssh`),Telnet/Agent 模式待实现
|
||
- **通知:** 邮件 (`net/smtp`) 已实现,钉钉/微信/短信待补充
|
||
|
||
## Build & Run
|
||
|
||
```bash
|
||
# 一键构建(前端 + 后端)
|
||
build_frontend.cmd
|
||
|
||
# 分步构建
|
||
cd frontend && npm install && npm run build && cd ..
|
||
CGO_ENABLED=0 go build -o ppgo_job.exe .
|
||
|
||
# 运行
|
||
./ppgo_job.exe
|
||
# 访问 http://localhost:8082 -> 重定向到 /app/(Vue 前端)
|
||
# 默认账号 admin / 123456
|
||
```
|
||
|
||
## Test
|
||
|
||
```bash
|
||
# 全部测试
|
||
CGO_ENABLED=0 go test -count=1 ./...
|
||
|
||
# 单元测试(无需启动服务器)
|
||
CGO_ENABLED=0 go test -count=1 ./libs/ ./consts/ ./dao/
|
||
|
||
# 集成测试(启动测试服务器 :18082)
|
||
CGO_ENABLED=0 go test -count=1 -timeout=120s -run "TestLogin|TestAuth|TestHome|TestTask|TestServer|TestGroup|TestBan|TestTemplate|TestStatic|TestDatabase|TestCORS" .
|
||
|
||
# 测试指定包
|
||
CGO_ENABLED=0 go test -v -count=1 ./libs/
|
||
```
|
||
|
||
> 集成测试使用端口 `:18082`,不会干扰开发实例。测试前确保 18082 端口未被占用。
|
||
|
||
## Architecture
|
||
|
||
```
|
||
main.go # GoFrame 启动入口
|
||
config.yml # 配置(server/database/jobs/site/notify/email/msg/dingtalk/wechat)
|
||
boot/
|
||
db.go # SQLite 数据目录初始化
|
||
router.go # 路由注册(公开路由 / API 路由 / Agent API)
|
||
init.go # 自动建表 + 种子数据 + 加载调度任务
|
||
controller/ # HTTP 层(flat package,按文件组织)
|
||
base.go # display/ajaxMsg/ajaxList/parseSort 辅助函数
|
||
response.go # 统一 JSON 响应格式
|
||
api.go # Vue 前端专用 API
|
||
login.go # 登录/登出
|
||
home.go # 仪表盘
|
||
task.go # 任务 CRUD + 审核
|
||
admin.go # 服务器/分组/禁用命令/通知模板
|
||
system.go # 权限因子/角色/管理员/个人资料
|
||
service/
|
||
scheduler/
|
||
scheduler.go # gcron 调度器单例(AddTask/RemoveTask/UpdateTask/RunTaskNow)
|
||
task_runner.go # 任务执行引擎(本地 Shell / SSH 远程 / HTTP 请求)
|
||
ssh.go # SSH 连接器(密码 + 密钥认证)
|
||
notify.go # 邮件通知
|
||
dao/ # 数据访问层(单例模式 var Xxx = new(xxxDao))
|
||
common.go # InsertAndGetId/Update/GetById/buildFilters 通用方法
|
||
model/entity/ # 数据库实体(orm 标签 + Cols 字段常量)
|
||
middleware/auth.go # 认证中间件(Cookie + JWT 双认证 + RBAC 权限)
|
||
libs/ # 工具函数(SHA256/JWT/加密)
|
||
consts/ # 常量定义(任务状态/通知类型/连接类型)
|
||
sql/schema.sql # 建表 DDL 参考
|
||
_old/ # Beego 旧代码参考(远程执行器 agent/ 等)
|
||
frontend/ # Vue 3 + TypeScript 前端
|
||
src/api/ # API 调用层(axios)
|
||
src/router/ # Vue Router 路由
|
||
src/stores/ # Pinia 状态管理
|
||
src/views/ # 页面组件
|
||
src/layout/ # 布局组件
|
||
dist/ # 构建产物(Go 静态文件服务)
|
||
```
|
||
|
||
## Layer Rules
|
||
|
||
- **controller**: 参数解析 → 调用 Service/DAO → 渲染模板或 JSON。不含业务逻辑。
|
||
- **service**: 业务逻辑。不含 HTTP 概念。
|
||
- **dao**: 数据访问。纯 CRUD。单例模式 `var Xxx = new(xxxDao)`。
|
||
- **middleware**: 认证、权限检查。
|
||
|
||
## Route Structure
|
||
|
||
路由定义在 `boot/router.go`,分三组:
|
||
|
||
| 组 | 认证 | 用途 |
|
||
|---|---|---|
|
||
| `/` 公开 | 无 | `/login_in` 登录、`/` 根路径重定向到 `/app/` |
|
||
| `/api/*` | JWT (Authorization Bearer) | Vue 前端所有 API |
|
||
| `/server/*`, `/task/*` | 无 (Agent API) | 远程 Agent 注册/状态/任务分发 |
|
||
|
||
中间件: `ghttp.MiddlewareCORS` 全局 CORS → `middleware.Auth` 双认证(Cookie 兼容旧模板 + JWT 新前端)。
|
||
|
||
Controller 响应约定:
|
||
- `ajaxMsg(r, msg, msgno)` → `{"status": msgno, "code": msgno, "message": msg}`
|
||
- `ajaxList(r, msg, msgno, count, data)` → `{"code": msgno, "msg": msg, "count": count, "data": data}` (LayUI table 格式)
|
||
- controller/response.go `Resp(r).Success(data)` / `Resp(r).Error(msg)` → `{"code": 0, "msg": "success", "data": ...}` (Vue 前端统一格式)
|
||
|
||
## Scheduler
|
||
|
||
- 单例 `service/scheduler.Scheduler`,启动时 `Init()` 加载所有启用任务到 `gcron`
|
||
- 使用 `gcron.AddSingleton` → 同一任务不会并发执行
|
||
- 任务命名: `task_{id}`
|
||
- 更新/删除: `RemoveTask` 后重新 `AddTask`
|
||
- 任务类型:
|
||
- `shell`: 本机执行(Windows: `CMD /C`, Linux: `sh -c`)或 SSH 远程
|
||
- `http`: 从调度器发 HTTP 请求,支持自定义 Method/Headers/Body,自动检测 JSON 响应中的业务错误(code/success/status/errno)
|
||
|
||
## Cron 表达式格式
|
||
|
||
GoFrame gcron 使用 **6 段格式**(含秒),非标准 5 段:
|
||
|
||
```
|
||
秒 分 时 日 月 周
|
||
0 0 3 * * * 每天凌晨 3 点
|
||
0 */5 * * * * 每 5 分钟
|
||
```
|
||
|
||
`scheduler.go` 中的 `parseCronFields` 也兼容标准 5 段格式(自动补秒=0)和 `@every 30s` 语法。
|
||
|
||
## DAO 查询模式
|
||
|
||
DAO 层扩展了 GoFrame Model 的 `buildFilters` 机制(`dao/common.go`):
|
||
|
||
```go
|
||
// 等值查询
|
||
dao.Task.GetList(ctx, page, size, "status", 1)
|
||
// LIKE 查询
|
||
dao.Task.GetList(ctx, page, size, "task_name like", "%backup%")
|
||
// 排序
|
||
dao.Task.GetList(ctx, page, size, "@order", "id desc")
|
||
```
|
||
|
||
`parseSort(r)`(controller/base.go)做字段名校验(仅字母/数字/下划线)防 SQL 注入。
|
||
|
||
## Key Config
|
||
|
||
`config.yml` 关键配置项:
|
||
|
||
| 路径 | 默认值 | 说明 |
|
||
|---|---|---|
|
||
| `server.address` | `:8082` | 监听端口 |
|
||
| `database.default.name` | `./data/ppgo_job.db` | SQLite 数据库路径 |
|
||
| `jobs.pool` | 1000 | 任务并发池大小 |
|
||
| `site.name` | 定时任务管理器 | 站点标题 |
|
||
| `notify.type` | 0 | 通知方式 (0=邮件, 1=短信, 2=钉钉, 3=微信) |
|
||
| `email.*` | — | SMTP 邮件配置 |
|
||
|
||
## Task Status Constants
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| -1 | 已删除 |
|
||
| 0 | 已暂停 |
|
||
| 1 | 运行中 |
|
||
| 2 | 待审核 |
|
||
| 3 | 审核失败 |
|
||
|
||
## Known Limits
|
||
|
||
- **Telnet/Agent 远程执行** — SSH 已实现,其余待补充(参考 `_old/jobs/job.go`)
|
||
- **通知渠道** — 邮件已实现,钉钉/微信/短信待补充(参考 `_old/notify/`)
|
||
- **Agent API** — 路由已预留(`/server/api_*`, `/task/api_*`),Agent 二进制待实现
|
||
- **Go 版本** — 要求 go 1.26+
|