# EasyJob
**Repository Path**: dyx88168/EasyJob
## Basic Information
- **Project Name**: EasyJob
- **Description**: EasyJob 让所有的Job都变得简单。
多种任务类型 — SQL 执行任务、ETL 数据同步、SQL 监控通知、飞书表格同步
可视化工作流引擎 — 基于 DAG 的拖拽式工作流设计器,支持 10 种节点类型(数据源/SQL执行/HTTP/C#/JavaScript/条件分支/循环/分片查询/通知/AI),支持分支跳过、级联跳过、多入边合并、失败策略(Continue/Abort/Fallbac
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2026-05-07
- **Last Updated**: 2026-09-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[English](README.en.md) | 中文
# EasyJob
**基于 ASP.NET Core + Vue.js 的分布式任务调度与 ETL 数据同步平台**
[](https://dotnet.microsoft.com/)
[](https://vuejs.org/)
[](https://www.typescriptlang.org/)
[](https://vitejs.dev/)
[](https://element-plus.org/)
[](https://www.quartz-scheduler.net/)
[](LICENSE)
---
## ✨ 功能特性
- **多种任务类型** — SQL 执行任务、ETL 数据同步、SQL 监控通知、飞书表格同步
- **可视化工作流引擎** — 基于 DAG 的拖拽式工作流设计器,支持 10 种节点类型(数据源/SQL执行/HTTP/C#/JavaScript/条件分支/循环/分片查询/通知/AI),支持分支跳过、级联跳过、多入边合并、失败策略(Continue/Abort/Fallback)
- **AI 节点集成** — 工作流中可直接调用 AI 大模型(OpenAI/Azure/Ollama/DeepSeek/通义千问/智谱/OneAPI/自定义),8 种预设配置
- **灵活的定时调度** — 基于 Quartz.NET,支持 Cron 表达式自定义调度
- **三种 ETL 同步模式** — 全量同步、增量同步、聚合同步
- **多数据库支持** — SQL Server、MySQL、PostgreSQL、SQLite
- **多渠道通知** — 邮件通知、飞书通知、钉钉通知、企业微信通知
- **任务重试机制** — 支持任务超时设置和失败自动重试
- **分布式锁** — 基于数据库的任务锁,支持多实例部署
- **审计日志** — 记录所有操作行为,可追溯
- **RBAC 权限控制** — 基于角色的访问控制,支持用户组管理
- **Windows 服务** — 原生支持以 Windows Service 方式运行
---
## 🛠 技术栈
### 后端
| 技术 | 版本 | 说明 |
|------|------|------|
| ASP.NET Core | 10.0 | Web 框架 |
| Entity Framework Core | 10.0 | ORM(多数据库支持) |
| Dapper | 2.1 | 高性能数据查询 |
| Quartz.NET | 3.18 | 任务调度引擎 |
| JWT | — | 身份认证 |
| BCrypt | 4.2 | 密码加密 |
| Serilog | 4.3 | 结构化日志 |
| MailKit | 4.16 | 邮件发送 |
| FeishuNetSdk | 4.1 | 飞书集成 |
| ClosedXML | 0.105 | Excel 导出 |
| Swashbuckle | 10.1 | Swagger API 文档 |
### 前端
| 技术 | 版本 | 说明 |
|------|------|------|
| Vue.js | 3.5 | 前端框架 |
| TypeScript | 5.8 | 类型安全 |
| Vite | 6.3 | 构建工具 |
| Element Plus | 2.9 | UI 组件库 |
| Pinia | 3.0 | 状态管理 |
| Vue Router | 4.5 | 路由管理 |
| Axios | 1.9 | HTTP 请求 |
| Monaco Editor | 0.52 | SQL 编辑器 |
| ECharts | 6.0 | 图表可视化 |
### 数据库
SQL Server | MySQL | PostgreSQL | SQLite(默认,零配置)
---
## 🔧 工作流引擎
EasyJob 内置一套基于 DAG(有向无环图)的可视化工作流引擎,支持拖拽式编排复杂的数据处理流水线,节点间通过 `VariablePool` 自动传递数据。
### 节点类型
| 节点 | 类型字符串 | 用途 | 输出契约 |
|------|-----------|------|----------|
| 数据源查询 | `DataSource` | 执行 SELECT 查询返回数据行 | `List>` |
| SQL 执行 | `SqlExecute` | 执行 INSERT/UPDATE/DELETE,返回影响行数 | `{ affectedRows }` |
| HTTP 请求 | `Http` | 调用外部 API,支持 GET/POST/PUT/DELETE 等 | `{ statusCode, body, headers }` |
| C# 代码 | `CSharpCode` | 用 Roslyn 执行 C# 脚本,支持 NuGet 包引用 | 任意(脚本返回值) |
| JavaScript 代码 | `JavaScript` | 用 Jint 执行 JS 脚本(沙箱) | 任意(run 函数返回值) |
| 条件分支 | `Condition` | 按 cases 顺序匹配,首个命中决定 Branch | `{ branch, matchedCase, field, value }` |
| 循环展开 | `Loop` | 将上游 List 展开为可迭代的 records 输出 | `{ count, records, itemVariableName }` |
| 分片查询 | `ShardingDataSource` | 支持 Modulo/Time/Database 三种分片模式 | `List>` |
| 通知发送 | `Notification` | 飞书/钉钉/企业微信/邮件多渠道并发 | `{ sent, channels[] }` |
| AI 调用 | `AI` | 调用大模型生成文本,支持 8 种预设 | `{ response }` |
| 结果输出 | `Output` | return / database / file 三种输出模式 | 取决于 mode |
### 数据流与变量插值
- **节点输出**:每个节点执行成功后,其 `Output` 写入 `VariablePool`,下游节点可按 `nodeId` 引用
- **模板插值**:配置中支持 `{{nodeId.fieldName}}` 语法,引擎自动从 VariablePool 取值并替换
- **工作流输入**:执行工作流时可通过 `InputJson` 传参,在节点配置中用 `input.fieldName` 引用(如 `input.branchSelector`)
- **C# 节点 input**:单上游 → `input` 即上游输出;多上游 → `input` 是 `Dictionary`
- **JS 节点 input**:始终 `input.{上游nodeId}.xxx` 访问(更直观的字典访问)
### 分支与跳过机制
- **Condition 节点**:按 cases 数组顺序匹配,首个命中的 case.label 作为返回的 Branch;都不匹配走 `defaultBranch`
- **边分支绑定**:Condition 节点的出边可设置 `branch` 字段,仅当节点实际返回的 Branch 与边的 branch 一致时该边激活
- **级联跳过**:被跳过的节点不会写入 `VariablePool`,其无条件下游(branch=null 的入边)也会因上游无输出而级联跳过,避免空输入执行
- **多入边合并**:节点有多个入边时,只要任意一条入边激活即可执行;`final_out` 类合并节点天然支持三分支汇合
- **失败策略**:每个节点可配置 `FailureStrategy`:
- `Abort`(默认)— 节点失败立即终止工作流
- `Continue` — 跳过失败节点,下游不含其输出
- `Fallback` — 注入 `{ error }` 作为输出,按 `FallbackBranch` 走指定分支
### 安全保障
- **SQL 安全校验**:所有 SQL 节点强制过 `SqlSecurityValidator`,禁止 DDL(CREATE/DROP/ALTER/TRUNCATE),SELECT 强制只读
- **C# 沙箱**:C# 节点通过 `AssemblyLoadContext` 隔离 NuGet 包版本,超时控制,使用 `InvariantCulture` 避免中文乱码
- **JS 沙箱**:Jint 解释器无文件/网络 API,限制递归深度 1000,超时控制
- **标识符校验**:表名/列名严格正则校验,防 SQL 注入
---
## 📁 项目结构
```
EasyJob/
├── backend/ # 后端 .NET 项目
│ ├── EasyJob.Api/ # API 层(控制器、启动配置、前端静态文件)
│ ├── EasyJob.Core/ # 核心层(实体、DTO、接口)
│ └── EasyJob.Infrastructure/ # 基础设施层(数据访问、服务实现、调度)
├── frontend/ # 前端 Vue.js 项目
│ └── src/
│ ├── api/ # API 请求封装
│ ├── components/ # 公共组件(CronPicker、SqlEditor、FieldMapping)
│ ├── layouts/ # 布局组件
│ ├── router/ # 路由配置
│ ├── stores/ # 状态管理
│ └── views/ # 页面视图
├── database/ # 数据库初始化脚本
├── docker-compose.yml # Docker 部署配置
├── start.bat # 一键启动脚本(开发模式)
└── deploy-service.bat # Windows 服务部署脚本
```
---
## 🚀 快速开始
### 环境要求
- .NET 10.0 SDK 或更高版本
- Node.js 18+
- 数据库:SQLite(默认,零配置)/ SQL Server / MySQL / PostgreSQL
### 方式一:本地开发
```bash
# 启动后端
cd backend
dotnet run --project EasyJob.Api
# 启动前端
cd frontend
npm install
npm run dev
```
也可以直接双击 `start.bat` 一键启动前后端。
### 方式二:Docker 部署
```bash
docker-compose up -d
```
部署包含以下服务:
| 服务 | 说明 | 端口 |
|------|------|------|
| easyjob-api | 后端 API | 5000 |
| easyjob-web | 前端 Web | 80 |
| sqlserver | SQL Server 2022 | 1433 |
### 方式三:Windows 服务部署
右键以管理员身份运行 `deploy-service.bat`,按菜单提示操作:
| 选项 | 说明 |
|------|------|
| [1] | 完整部署(发布 + 安装服务 + 启动) |
| [2] | 仅发布项目 |
| [3] | 仅安装服务(需先发布) |
| [4] | 启动服务 |
| [5] | 停止服务 |
| [6] | 卸载服务 |
| [7] | 查看服务状态 |
| [8] | 重新部署(卸载 + 发布 + 安装 + 启动) |
服务默认安装到 `C:\EasyJob`,监听端口 `8090`,支持失败自动重启。
---
## 🔑 默认账户
| 项目 | 值 |
|------|------|
| 用户名 | `admin` |
| 密码 | `Admin@123` |
---
## 🌐 访问地址
| 服务 | 地址 |
|------|------|
| 前端(开发模式) | http://localhost:5173 |
| 前端(Docker) | http://localhost |
| 前端(Windows 服务) | http://localhost:8090 |
| 后端 API(开发模式) | http://localhost:5271 |
| 后端 API(Docker) | http://localhost:5000 |
| Swagger 文档 | http://localhost:5271/swagger |
---
## 📡 API 接口
| 模块 | 路径 | 说明 |
|------|------|------|
| 认证 | `/api/auth` | 登录、注册、刷新 Token |
| 任务管理 | `/api/tasks` | 任务 CRUD、执行、调度 |
| 数据库连接 | `/api/dbconnections` | 数据库连接管理 |
| 邮件发送者 | `/api/emailsenders` | 邮件发送账号管理 |
| 飞书通知 | `/api/feishunotify` | 飞书 Webhook 通知配置 |
| 飞书应用 | `/api/feishuappconfig` | 飞书应用配置管理 |
| 钉钉通知 | `/api/dingtalknotify` | 钉钉 Webhook 通知配置 |
| 企业微信通知 | `/api/wecomnotify` | 企业微信 Webhook 通知配置 |
| 用户管理 | `/api/users` | 用户 CRUD、角色分配 |
| 用户组 | `/api/usergroups` | 用户组管理 |
| 审计日志 | `/api/auditlogs` | 操作日志查询 |
| 仪表盘 | `/api/dashboard` | 统计数据、运行状态 |
---
## 🖥 功能页面
| 页面 | 路径 | 说明 |
|------|------|------|
| 仪表盘 | `/` | 任务运行统计、系统概览 |
| 任务管理 | `/tasks` | 任务列表,支持筛选和搜索 |
| 创建 SQL 任务 | `/tasks/create-sql` | SQL 执行任务配置 |
| 创建 ETL 任务 | `/tasks/create-etl` | ETL 数据同步任务配置 |
| 创建通知任务 | `/tasks/create-notification` | SQL 监控通知任务配置 |
| 创建飞书表格任务 | `/tasks/create-feishu-sheet` | 飞书表格同步任务配置 |
| 任务详情 | `/tasks/:id` | 任务执行记录和日志 |
| 数据库连接 | `/connections` | 管理目标数据库连接信息 |
| 邮件发送者 | `/email-senders` | 邮件发送账号管理 |
| 飞书通知 | `/feishu-notify` | 飞书 Webhook 配置 |
| 飞书应用 | `/feishu-apps` | 飞书应用凭证管理 |
| 钉钉通知 | `/dingtalk-notify` | 钉钉 Webhook 配置 |
| 企业微信通知 | `/wecom-notify` | 企业微信 Webhook 配置 |
| 用户管理 | `/users` | 用户账户和角色管理 |
| 用户组 | `/user-groups` | 用户分组管理 |
| 审计日志 | `/audit-logs` | 系统操作记录查询 |
---
## ⚙️ 配置说明
后端配置位于 `backend/EasyJob.Api/appsettings.json`:
| 配置项 | 说明 |
|--------|------|
| `DatabaseProvider` | 数据库类型(Sqlite / SqlServer / MySql / PostgreSql) |
| `ConnectionStrings` | 各数据库连接字符串 |
| `Jwt:Key` | Token 签名密钥 |
| `Jwt:Issuer` | Token 颁发者 |
| `Jwt:Audience` | Token 受众 |
| `Feishu:AppId` | 飞书应用 AppId |
| `Feishu:AppSecret` | 飞书应用 AppSecret |
| `Urls` | 监听地址(如 `http://0.0.0.0:8090`) |
---
## 📄 License
[MIT](LICENSE)