| .. | ||
| .mvn/wrapper | ||
| docs | ||
| src | ||
| .cursorrules | ||
| .cursorrules1 | ||
| .gitattributes | ||
| .gitignore | ||
| frontend.rules | ||
| mvnw | ||
| mvnw.cmd | ||
| pom.xml | ||
| README.md | ||
Deploy Ease Platform
Deploy Ease Platform 是一个现代化的部署管理平台,旨在简化和自动化应用程序的部署流程。
已实现功能
1. 外部系统管理
- 基础功能
- 创建外部系统(支持Jenkins、Git等类型)
- 更新系统信息
- 删除系统
- 查询系统详情
- 分页查询系统列表
- 条件筛选查询
- Jenkins集成
- 连接测试
- 任务同步
- 状态检查
- 支持用户名密码认证
- 支持Token认证
- Git集成
- 仓库连接测试
- 代码分支同步
- 提交历史查询
- 支持用户名密码认证
- 支持SSH密钥认证
- 支持Token认证
2. 用户权限管理
- 用户管理
- 用户注册
- 用户登录
- 密码重置
- 用户信息修改
- 用户状态管理
- 部门分配
- 角色管理
- 角色创建与维护
- 角色标签管理
- 角色权限分配
- 用户角色分配
- 权限管理
- 权限创建与维护
- 权限分类管理
- 权限与菜单关联
- 权限检查与控制
3. 菜单管理
- 基础功能
- 菜单树维护
- 菜单排序
- 菜单显示控制
- 权限集成
- 菜单权限配置
- 按钮权限配置
- 数据权限配置
- 前端集成
- 动态路由生成
- 菜单组件加载
- 权限指令集成
4. 部门管理
- 基础功能
- 部门树维护
- 部门编码管理
- 部门描述维护
- 部门排序
- 人员管理
- 部门负责人设置
- 部门人员管理
- 部门权限控制
5. 系统功能
- 认证授权
- JWT令牌认证
- 权限拦截器
- 角色检查器
- 权限注解支持
- 数据审计
- 创建人记录
- 创建时间记录
- 更新人记录
- 更新时间记录
- 版本控制
- 异常处理
- 统一异常处理
- 业务异常处理
- 系统异常处理
- 参数校验异常处理
- 数据库支持
- Flyway数据库版本控制
- 基础表结构
- 初始化数据
- 软删除支持
6. 开发支持
- 基础框架
- 统一响应格式
- 统一分页格式
- 基础CRUD封装
- DTO自动转换
- 代码规范
- 开发规范文档
- 接口文档规范
- 测试规范
- 注释规范
- 测试支持
- 单元测试框架
- 集成测试支持
- 测试数据构建
- Mock支持
7. 租户管理API
7.1 分页查询租户
GET /api/v1/tenant/page
请求参数:
{
"pageNum": 1, // 页码(从1开始)
"pageSize": 10, // 每页大小
"sortField": "createTime", // 排序字段
"sortOrder": "desc", // 排序方式
"code": "string", // 租户编码(可选)
"name": "string", // 租户名称(可选)
"enabled": true // 是否启用(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"content": [{
"id": 1,
"createTime": "2024-01-01 12:00:00",
"createBy": "admin",
"updateTime": "2024-01-01 12:00:00",
"updateBy": "admin",
"code": "TEST",
"name": "测试租户",
"address": "北京市朝阳区",
"contactName": "张三",
"contactPhone": "13800138000",
"email": "test@example.com",
"enabled": true
}],
"totalElements": 100,
"totalPages": 10,
"size": 10,
"number": 0,
"first": true,
"last": false,
"empty": false
}
}
7.2 创建租户
POST /api/v1/tenant
请求参数:
{
"code": "TEST", // 租户编码(必填)
"name": "测试租户", // 租户名称(必填)
"address": "北京市朝阳区", // 地址(可选)
"contactName": "张三", // 联系人姓名(可选)
"contactPhone": "13800138000", // 联系人电话(可选)
"email": "test@example.com", // 联系人邮箱(可选)
"enabled": true // 是否启用(可选,默认true)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
7.3 更新租户
PUT /api/v1/tenant/{id}
请求参数:
{
// 同创建接口
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
7.4 删除租户
DELETE /api/v1/tenant/{id}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
7.5 获取租户状态
GET /api/v1/tenant/{id}/enabled
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": true // true: 启用,false: 禁用
}
7.6 更新租户状态
PUT /api/v1/tenant/{id}/enabled
请求参数:
enabled=true // 是否启用(必填)
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
技术栈
后端技术栈
- Spring Boot 3.x
- Spring Security + JWT
- Spring Data JPA
- Flyway数据库版本控制
- MapStruct对象映射
- Lombok
- JUnit 5
数据库
- MySQL 8.0+
API文档
1. 外部系统管理API
1.1 分页查询
GET /api/v1/external-system/page
请求参数:
{
"pageNum": 1, // 页码(从1开始)
"pageSize": 10, // 每页大小
"sortField": "createTime", // 排序字段
"sortOrder": "desc", // 排序方式
"name": "string", // 系统名称(可选)
"type": "JENKINS", // 系统类型(可选)
"enabled": true // 是否启用(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"content": [{
"id": 1,
"createTime": "2024-01-01 12:00:00",
"createBy": "admin",
"updateTime": "2024-01-01 12:00:00",
"updateBy": "admin",
"name": "Jenkins测试环境",
"type": "JENKINS",
"url": "http://jenkins.test.com",
"remark": "测试环境Jenkins服务器",
"sort": 1,
"enabled": true,
"authType": "USERNAME_PASSWORD",
"username": "admin",
"password": "******",
"token": null,
"syncStatus": "SUCCESS",
"lastSyncTime": "2024-01-01 12:00:00",
"config": "{}"
}],
"totalElements": 100,
"totalPages": 10,
"size": 10,
"number": 0,
"first": true,
"last": false,
"empty": false
}
}
1.2 创建外部系统
POST /api/v1/external-system
请求参数:
{
"name": "Jenkins测试环境", // 系统名称(必填)
"type": "JENKINS", // 系统类型(必填)
"url": "http://jenkins.test.com", // 系统地址(必填)
"remark": "测试环境Jenkins服务器", // 备注(可选)
"sort": 1, // 排序(可选)
"enabled": true, // 是否启用(可选,默认true)
"authType": "USERNAME_PASSWORD", // 认证方式(必填)
"username": "admin", // 用户名(可选)
"password": "password123", // 密码(可选)
"token": null, // 访问令牌(可选)
"config": "{}" // 配置信息(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
1.3 更新外部系统
PUT /api/v1/external-system/{id}
请求参数:
{
// 同创建接口
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
1.4 删除外部系统
DELETE /api/v1/external-system/{id}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
1.5 测试连接
POST /api/v1/external-system/{id}/test-connection
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": true
}
1.6 同步数据
POST /api/v1/external-system/{id}/sync
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
1.7 检查状态
GET /api/v1/external-system/{id}/status
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"syncStatus": "SUCCESS",
"lastSyncTime": "2024-01-01 12:00:00"
}
}
2. 用户认证API
2.1 用户登录
POST /api/v1/user/login
请求参数:
{
"username": "admin", // 用户名(必填)
"password": "password" // 密码(必填)
}
响应结果:
{
"success": true,
"code": 200,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9...",
"user": {
"id": 1,
"username": "admin",
"nickname": "管理员",
"email": "admin@example.com",
"phone": "13800138000",
"departmentId": 1,
"departmentName": "技术部"
}
}
}
2.2 获取当前用户信息
GET /api/v1/user/current
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "admin",
"nickname": "管理员",
"email": "admin@example.com",
"phone": "13800138000",
"departmentId": 1,
"departmentName": "技术部"
}
}
3. 菜单管理API
3.1 获取当前用户菜单
GET /api/v1/menu/current
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": [{
"id": 1,
"name": "系统管理",
"path": "/system",
"component": "Layout",
"icon": "setting",
"permission": "system:view",
"type": 1, // 1:目录 2:菜单 3:按钮
"parentId": null,
"sort": 1,
"hidden": false,
"children": [{
"id": 2,
"name": "用户管理",
"path": "/system/user",
"component": "system/user/index",
"icon": "user",
"permission": "system:user:view",
"type": 2,
"parentId": 1,
"sort": 1,
"hidden": false,
"children": []
}]
}]
}
3.2 获取菜单树
GET /api/v1/menu/tree
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": [{
// 结构同上
}]
}
3.3 获取权限树
GET /api/v1/menu/permission-tree
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": [{
"id": 1,
"name": "系统管理",
"type": 1,
"children": [{
"id": 2,
"name": "用户管理",
"type": 2,
"permissions": [{
"id": 3,
"code": "system:user:add",
"name": "新增用户",
"type": "BUTTON"
}]
}]
}]
}
4. 部门管理API
4.1 获取部门树
GET /api/v1/department/tree
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": [{
"id": 1,
"code": "TECH",
"name": "技术部",
"description": "技术研发部门",
"parentId": null,
"sort": 1,
"enabled": true,
"leaderId": 1,
"leaderName": "张三",
"children": [{
"id": 2,
"code": "DEV",
"name": "研发组",
"description": "研发团队",
"parentId": 1,
"sort": 1,
"enabled": true,
"leaderId": 2,
"leaderName": "李四",
"children": []
}]
}]
}
4.2 创建部门
POST /api/v1/department
请求参数:
{
"code": "TECH", // 部门编码(必填)
"name": "技术部", // 部门名称(必填)
"description": "技术研发部门", // 描述(可选)
"parentId": null, // 上级部门ID(可选)
"sort": 1, // 排序(可选)
"enabled": true, // 是否启用(可选,默认true)
"leaderId": 1, // 负责人ID(可选)
"leaderName": "张三" // 负责人姓名(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
5. 角色管理API
5.1 分配角色标签
POST /api/v1/role/{id}/tags
请求参数:
{
"tagIds": [1, 2, 3] // 标签ID列表
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
5.2 分配用户角色
POST /api/v1/role/{userId}/assignRoles
请求参数:
{
"roleIds": [1, 2, 3] // 角色ID列表
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
5.3 获取角色权限
GET /api/v1/role/{id}/permissions
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": [{
"id": 1,
"code": "system:user:view",
"name": "查看用户",
"type": "MENU",
"sort": 1,
"menuName": "用户管理"
}]
}
5.4 分配角色权限
POST /api/v1/role/{id}/permissions
请求参数:
{
"permissionIds": [1, 2, 3] // 权限ID列表
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功"
}
6. 权限管理API
6.1 分页查询权限
GET /api/v1/permission/page
请求参数:
{
"pageNum": 1,
"pageSize": 10,
"code": "system", // 权限编码(可选)
"name": "系统", // 权限名称(可选)
"type": "MENU", // 权限类型(可选)
"enabled": true, // 是否启用(可选)
"menuId": 1 // 菜单ID(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"content": [{
"id": 1,
"code": "system:user:view",
"name": "查看用户",
"type": "MENU",
"sort": 1,
"menuId": 2,
"menuName": "用户管理"
}],
"totalElements": 100,
"totalPages": 10,
"size": 10,
"number": 0,
"first": true,
"last": false,
"empty": false
}
}
6.2 创建权限
POST /api/v1/permission
请求参数:
{
"code": "system:user:add", // 权限编码(必填)
"name": "新增用户", // 权限名称(必填)
"type": "BUTTON", // 权限类型(必填)
"menuId": 2, // 菜单ID(必填)
"sort": 1 // 排序(可选)
}
响应结果:
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
// ... 其他字段同上
}
}
开发规范
后端开发规范
- 遵循DDD设计思想
- 统一的异常处理
- 统一的返回格式
- 完整的单元测试
- 详细的接口文档
- 规范的代码注释
详细规范请参考:后端开发规范
前端开发规范
- 统一的接口调用方式
- 统一的错误处理
- 标准的时间格式
- 规范的国际化实现
详细规范请参考:前端开发规范
注意事项
1. 数据库
- 所有表必须包含基础字段:
id BIGINT PRIMARY KEY # 主键 create_time DATETIME # 创建时间 create_by VARCHAR(50) # 创建人 update_time DATETIME # 更新时间 update_by VARCHAR(50) # 更新人 version INT # 版本号 deleted BOOLEAN # 是否删除 - 使用Flyway进行数据库版本控制
- 新建表结构写入V1.0.0__init_schema.sql
- 初始数据写入V1.0.1__init_data.sql
2. 接口开发
- 所有接口都需要JWT认证
- 接口版本统一使用v1
- 返回数据格式统一为:
{ "success": true, "code": 200, "message": "操作成功", "data": {} } - 分页查询参数统一使用:
{ "pageNum": 1, "pageSize": 10, "sortField": "createTime", "sortOrder": "desc" }
3. 异常处理
- 业务异常统一使用BusinessException
- 异常码在ResponseCode中定义
- 异常信息在messages.properties中定义
- 所有异常都通过GlobalExceptionHandler处理
4. 安全性
- 敏感信息(密码、Token等)需要加密存储
- 外部系统认证信息需要加密传输
- 定期清理过期的Token
- 限制API调用频率
5. 测试
- 所有Service层代码必须有单元测试
- 所有Controller必须有集成测试
- 测试覆盖率要求80%以上
- 测试数据使用@Sql注入,避免影响生产数据
环境要求
- JDK 17+
- Maven 3.8+
- MySQL 8.0+
- Node.js 16+
快速开始
- 克隆项目
git clone [项目地址]
- 配置数据库
# 创建数据库
CREATE DATABASE deploy_ease DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- 修改配置
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/deploy_ease
username: your_username
password: your_password
- 启动项目
mvn spring-boot:run
贡献指南
- Fork 项目
- 创建功能分支
- 提交代码
- 创建Pull Request
许可证
workflow_definition(工作流定义表)
存储我们自定义的工作流定义信息
包含流程名称、标识、版本、BPMN XML内容等
与Flowable的act_re_procdef表是一对一的关系
额外存储了图形编辑器的JSON数据,方便前端展示和编辑
workflow_instance(工作流实例表)
记录工作流的执行实例信息
存储流程实例ID、业务标识、状态、变量等
与Flowable的act_ru_execution表是一对一的关系
提供了更多的业务字段,如开始时间、结束时间等
workflow_node_instance(工作流节点实例表)
记录工作流中每个节点的执行情况
存储节点ID、名称、类型、状态等
与Flowable的act_ru_task和act_hi_actinst表有关联
特别记录了Shell任务的执行结果、错误信息等
workflow_log(工作流日志表)
记录工作流执行过程中的详细日志
可以关联到具体的实例和节点
包含日志类型、级别、内容等
方便排查问题和审计
这些表与Flowable的原生表的主要区别是:
更贴近业务需求,字段设计更符合我们的使用场景
提供了更丰富的元数据和状态信息
支持更细粒度的日志记录
可以存储自定义的业务数据
这样的设计让我们可以在使用Flowable强大的工作流引擎的同时,也能满足特定的业务需求。
{
"name": "Simple Shell Workflow6",
"key": "simple_shell_workflow",
"description": "A simple workflow with shell task",
"graphJson": {
"cells": [
{
"id": "start",
"shape": "start",
"data": {
"label": "开始"
},
"position": {
"x": 100,
"y": 100
}
},
{
"id": "shell",
"shape": "serviceTask",
"data": {
"label": "Shell脚本",
"serviceTask": {
"type": "shell",
"implementation": "${shellTaskDelegate}",
"fields": {
"script": "timeout 10000000",
"workDir": "/tmp",
"env": {
"TEST_VAR": "test_value"
}
}
}
},
"position": {
"x": 300,
"y": 100
}
},
{
"id": "shellErrorBoundary",
"shape": "boundaryEvent",
"data": {
"label": "Shell错误",
"boundaryEvent": {
"type": "error",
"attachedToRef": "shell",
"errorRef": "SHELL_EXECUTION_ERROR"
}
},
"position": {
"x": 300,
"y": 160
}
},
{
"id": "errorHandler",
"shape": "serviceTask",
"data": {
"label": "错误处理",
"serviceTask": {
"type": "service",
"implementation": "${errorHandlerDelegate}"
}
},
"position": {
"x": 300,
"y": 220
}
},
{
"id": "end",
"shape": "end",
"data": {
"label": "结束"
},
"position": {
"x": 500,
"y": 100
}
},
{
"id": "flow1",
"shape": "edge",
"source": "start",
"target": "shell",
"data": {
"label": "流转到Shell"
}
},
{
"id": "flow2",
"shape": "edge",
"source": "shell",
"target": "end",
"data": {
"label": "完成"
}
},
{
"id": "flow_error",
"shape": "edge",
"source": "shellErrorBoundary",
"target": "errorHandler",
"data": {
"label": "错误处理"
}
},
{
"id": "flow_error_end",
"shape": "edge",
"source": "errorHandler",
"target": "end",
"data": {
"label": "处理完成"
}
}
]
}
}
死信队列的问题:
需要再异常里直接移除:
runtimeService.deleteProcessInstance(processInstanceId, errorMessage);
const eventSource = new EventSource(`/api/v1/shell-logs/${processInstanceId}`);
eventSource.addEventListener('STDOUT', (event) => {
console.log('Output:', event.data);
});
eventSource.addEventListener('STDERR', (event) => {
console.error('Error:', event.data);
});
// 当流程结束时关闭连接
eventSource.onerror = () => {
eventSource.close();
};