增加GIT同步实体类跟service
This commit is contained in:
parent
cec5b73b3b
commit
7df3b9b36b
291
backend/frontend.rules
Normal file
291
backend/frontend.rules
Normal file
@ -0,0 +1,291 @@
|
||||
# 前端接口对接文档
|
||||
|
||||
## 通用说明
|
||||
|
||||
### 1. 接口响应格式
|
||||
|
||||
所有接口统一返回以下格式:
|
||||
```typescript
|
||||
interface Response<T> {
|
||||
success: boolean; // 请求是否成功
|
||||
code: number; // 状态码,200表示成功,其他表示失败
|
||||
message: string; // 提示信息
|
||||
data?: T; // 响应数据,可选
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 分页请求参数
|
||||
```typescript
|
||||
interface PageQuery {
|
||||
pageNum: number; // 页码,从1开始
|
||||
pageSize: number; // 每页大小
|
||||
sortField?: string; // 排序字段,可选
|
||||
sortOrder?: 'asc' | 'desc'; // 排序方式,可选
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 分页响应格式
|
||||
```typescript
|
||||
interface PageResponse<T> {
|
||||
content: T[]; // 数据列表
|
||||
totalElements: number;// 总记录数
|
||||
totalPages: number; // 总页数
|
||||
size: number; // 每页大小
|
||||
number: number; // 当前页码(从0开始)
|
||||
first: boolean; // 是否第一页
|
||||
last: boolean; // 是否最后一页
|
||||
empty: boolean; // 是否为空
|
||||
}
|
||||
```
|
||||
|
||||
## 通用接口
|
||||
|
||||
### 1. 基础CRUD接口
|
||||
所有实体都支持以下基础操作接口:
|
||||
|
||||
#### 1.1 分页查询
|
||||
```typescript
|
||||
GET /api/v1/{module}/page
|
||||
|
||||
请求参数:PageQuery & {
|
||||
// 其他查询条件,根据具体模块定义
|
||||
}
|
||||
|
||||
响应结果:Response<PageResponse<T>>
|
||||
```
|
||||
|
||||
#### 1.2 列表查询
|
||||
```typescript
|
||||
GET /api/v1/{module}/list
|
||||
|
||||
请求参数:{
|
||||
// 查询条件,根据具体模块定义
|
||||
}
|
||||
|
||||
响应结果:Response<T[]>
|
||||
```
|
||||
|
||||
#### 1.3 获取详情
|
||||
```typescript
|
||||
GET /api/v1/{module}/{id}
|
||||
|
||||
响应结果:Response<T>
|
||||
```
|
||||
|
||||
#### 1.4 创建
|
||||
```typescript
|
||||
POST /api/v1/{module}
|
||||
|
||||
请求参数:{
|
||||
// 创建参数,根据具体模块定义
|
||||
}
|
||||
|
||||
响应结果:Response<T>
|
||||
```
|
||||
|
||||
#### 1.5 更新
|
||||
```typescript
|
||||
PUT /api/v1/{module}/{id}
|
||||
|
||||
请求参数:{
|
||||
// 更新参数,根据具体模块定义
|
||||
}
|
||||
|
||||
响应结果:Response<T>
|
||||
```
|
||||
|
||||
#### 1.6 删除
|
||||
```typescript
|
||||
DELETE /api/v1/{module}/{id}
|
||||
|
||||
响应结果:Response<void>
|
||||
```
|
||||
|
||||
#### 1.7 批量删除
|
||||
```typescript
|
||||
DELETE /api/v1/{module}/batch
|
||||
|
||||
请求参数:{
|
||||
ids: number[]; // ID列表
|
||||
}
|
||||
|
||||
响应结果:Response<void>
|
||||
```
|
||||
|
||||
#### 1.8 导出数据
|
||||
```typescript
|
||||
GET /api/v1/{module}/export
|
||||
|
||||
请求参数:{
|
||||
// 查询条件,根据具体模块定义
|
||||
}
|
||||
|
||||
响应结果:二进制文件流
|
||||
```
|
||||
|
||||
### 2. 树形结构接口
|
||||
对于树形结构的数据(如部门、菜单等),还支持以下接口:
|
||||
|
||||
#### 2.1 获取树形数据
|
||||
```typescript
|
||||
GET /api/v1/{module}/tree
|
||||
|
||||
响应结果:Response<TreeNode[]>
|
||||
|
||||
interface TreeNode {
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
children: TreeNode[];
|
||||
// 其他字段根据具体模块定义
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 状态管理接口
|
||||
对于需要状态管理的数据(如租户、用户等),还支持以下接口:
|
||||
|
||||
#### 3.1 获取状态
|
||||
```typescript
|
||||
GET /api/v1/{module}/{id}/enabled
|
||||
|
||||
响应结果:Response<boolean>
|
||||
```
|
||||
|
||||
#### 3.2 更新状态
|
||||
```typescript
|
||||
PUT /api/v1/{module}/{id}/enabled
|
||||
|
||||
请求参数:
|
||||
enabled=true // 是否启用
|
||||
|
||||
响应结果:Response<void>
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 1. 错误码说明
|
||||
- 200:成功
|
||||
- 400:请求参数错误
|
||||
- 401:未认证
|
||||
- 403:无权限
|
||||
- 404:资源不存在
|
||||
- 500:服务器内部错误
|
||||
|
||||
### 2. 错误响应示例
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"code": 400,
|
||||
"message": "请求参数错误",
|
||||
"data": {
|
||||
"field": "name",
|
||||
"message": "名称不能为空"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 接口调用示例
|
||||
|
||||
### TypeScript 示例
|
||||
```typescript
|
||||
// 定义接口返回类型
|
||||
interface User {
|
||||
id: number;
|
||||
username: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
async function getUserList(query: PageQuery & { username?: string }) {
|
||||
const response = await axios.get<Response<PageResponse<User>>>('/api/v1/user/page', {
|
||||
params: query
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
async function createUser(user: Omit<User, 'id'>) {
|
||||
const response = await axios.post<Response<User>>('/api/v1/user', user);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
async function updateUserStatus(id: number, enabled: boolean) {
|
||||
const response = await axios.put<Response<void>>(`/api/v1/user/${id}/enabled`, null, {
|
||||
params: { enabled }
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
```
|
||||
|
||||
### Vue3 + TypeScript 示例
|
||||
```typescript
|
||||
// 在组件中使用
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const userList = ref<User[]>([]);
|
||||
const total = ref(0);
|
||||
const loading = ref(false);
|
||||
|
||||
const queryList = async (query: PageQuery) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const response = await getUserList(query);
|
||||
if (response.success) {
|
||||
userList.value = response.data.content;
|
||||
total.value = response.data.totalElements;
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
queryList({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
userList,
|
||||
total,
|
||||
loading,
|
||||
queryList
|
||||
};
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 请求头要求
|
||||
```typescript
|
||||
{
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ${token}' // JWT认证token
|
||||
}
|
||||
```
|
||||
|
||||
2. 日期时间格式
|
||||
- 请求参数:使用ISO 8601格式(YYYY-MM-DDTHH:mm:ss.sssZ)
|
||||
- 响应数据:统一返回ISO 8601格式
|
||||
|
||||
3. 文件上传
|
||||
- 使用multipart/form-data格式
|
||||
- 文件大小限制:10MB
|
||||
|
||||
4. 接口版本
|
||||
- 所有接口统一使用v1版本
|
||||
- URL格式:/api/v1/{module}/{resource}
|
||||
|
||||
5. 安全性
|
||||
- 所有接口都需要JWT认证
|
||||
- Token过期时间:2小时
|
||||
- 需要定期刷新Token
|
||||
|
||||
6. 错误处理
|
||||
- 统一使用axios拦截器处理错误
|
||||
- 401错误跳转到登录页
|
||||
- 其他错误统一提示
|
||||
@ -0,0 +1,51 @@
|
||||
package com.qqchen.deploy.backend.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.RepositoryGroup;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryProject;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryBranch;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryGroupDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryProjectDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryBranchDTO;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* 仓库相关的对象转换器
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Mapper(config = BaseConverter.class)
|
||||
public interface RepositoryConverter {
|
||||
|
||||
/**
|
||||
* 仓库组实体转DTO
|
||||
*/
|
||||
RepositoryGroupDTO toDto(RepositoryGroup entity);
|
||||
|
||||
/**
|
||||
* 仓库组DTO转实体
|
||||
*/
|
||||
RepositoryGroup toEntity(RepositoryGroupDTO dto);
|
||||
|
||||
/**
|
||||
* 仓库项目实体转DTO
|
||||
*/
|
||||
RepositoryProjectDTO toDto(RepositoryProject entity);
|
||||
|
||||
/**
|
||||
* 仓库项目DTO转实体
|
||||
*/
|
||||
RepositoryProject toEntity(RepositoryProjectDTO dto);
|
||||
|
||||
/**
|
||||
* 仓库分支实体转DTO
|
||||
*/
|
||||
RepositoryBranchDTO toDto(RepositoryBranch entity);
|
||||
|
||||
/**
|
||||
* 仓库分支DTO转实体
|
||||
*/
|
||||
RepositoryBranch toEntity(RepositoryBranchDTO dto);
|
||||
}
|
||||
@ -16,8 +16,8 @@ import java.time.LocalDateTime;
|
||||
@LogicDelete
|
||||
public class RepositoryBranch extends Entity<Long> {
|
||||
|
||||
@Column(name = "repository_id", nullable = false)
|
||||
private Long repositoryId;
|
||||
@Column(name = "external_system_id")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Column(name = "project_id", nullable = false)
|
||||
private Long projectId;
|
||||
@ -37,7 +37,8 @@ public class RepositoryBranch extends Entity<Long> {
|
||||
@Column(name = "commit_date")
|
||||
private LocalDateTime commitDate;
|
||||
|
||||
private Boolean protected_ = false;
|
||||
@Column(name = "is_protected")
|
||||
private Boolean isProtected = false;
|
||||
|
||||
@Column(name = "developers_can_push")
|
||||
private Boolean developersCanPush = true;
|
||||
@ -48,8 +49,8 @@ public class RepositoryBranch extends Entity<Long> {
|
||||
@Column(name = "can_push")
|
||||
private Boolean canPush = true;
|
||||
|
||||
@Column(name = "default_branch")
|
||||
private Boolean defaultBranch = false;
|
||||
@Column(name = "is_default_branch")
|
||||
private Boolean isDefaultBranch = false;
|
||||
|
||||
@Column(name = "web_url")
|
||||
private String webUrl;
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "deploy_repository_config")
|
||||
@LogicDelete
|
||||
public class RepositoryConfig extends Entity<Long> {
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String url;
|
||||
|
||||
@Column(name = "access_token", nullable = false)
|
||||
private String accessToken;
|
||||
|
||||
@Column(name = "api_version")
|
||||
private String apiVersion;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private String remark;
|
||||
|
||||
@Column(name = "last_sync_time")
|
||||
private LocalDateTime lastSyncTime;
|
||||
|
||||
@Column(name = "last_sync_status")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private RepositorySyncHistory.SyncStatus lastSyncStatus;
|
||||
}
|
||||
@ -7,16 +7,21 @@ import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
||||
/**
|
||||
* 仓库组实体
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "deploy_repository_group")
|
||||
@Table(name = "deploy_repo_group")
|
||||
@LogicDelete
|
||||
public class RepositoryGroup extends Entity<Long> {
|
||||
|
||||
@Column(name = "repository_id", nullable = false)
|
||||
private Long repositoryId;
|
||||
@Column(name = "external_system_id")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Column(name = "group_id", nullable = false)
|
||||
private Long groupId;
|
||||
|
||||
@ -16,8 +16,8 @@ import java.time.LocalDateTime;
|
||||
@LogicDelete
|
||||
public class RepositoryProject extends Entity<Long> {
|
||||
|
||||
@Column(name = "repository_id", nullable = false)
|
||||
private Long repositoryId;
|
||||
@Column(name = "external_system_id")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Column(name = "project_id", nullable = false)
|
||||
private Long projectId;
|
||||
@ -35,8 +35,8 @@ public class RepositoryProject extends Entity<Long> {
|
||||
@Column(name = "group_id")
|
||||
private Long groupId;
|
||||
|
||||
@Column(name = "default_branch")
|
||||
private String defaultBranch;
|
||||
@Column(name = "is_default_branch")
|
||||
private String isDefaultBranch;
|
||||
|
||||
@Column(name = "web_url")
|
||||
private String webUrl;
|
||||
|
||||
@ -80,7 +80,20 @@ public enum ResponseCode {
|
||||
/**
|
||||
* Git系统Token必填
|
||||
*/
|
||||
EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED(2502, "Git系统必须提供Token");
|
||||
EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED(2502, "Git系统必须提供Token"),
|
||||
|
||||
// 仓库相关错误码 (2600-2699)
|
||||
REPOSITORY_GROUP_NOT_FOUND(2600, "repository.group.not.found"),
|
||||
REPOSITORY_GROUP_NAME_EXISTS(2601, "repository.group.name.exists"),
|
||||
REPOSITORY_GROUP_PATH_EXISTS(2602, "repository.group.path.exists"),
|
||||
REPOSITORY_PROJECT_NOT_FOUND(2610, "repository.project.not.found"),
|
||||
REPOSITORY_PROJECT_NAME_EXISTS(2611, "repository.project.name.exists"),
|
||||
REPOSITORY_PROJECT_PATH_EXISTS(2612, "repository.project.path.exists"),
|
||||
REPOSITORY_BRANCH_NOT_FOUND(2620, "repository.branch.not.found"),
|
||||
REPOSITORY_BRANCH_NAME_EXISTS(2621, "repository.branch.name.exists"),
|
||||
REPOSITORY_SYNC_IN_PROGRESS(2630, "repository.sync.in.progress"),
|
||||
REPOSITORY_SYNC_FAILED(2631, "repository.sync.failed"),
|
||||
REPOSITORY_SYNC_HISTORY_NOT_FOUND(2632, "repository.sync.history.not.found");
|
||||
|
||||
private final int code;
|
||||
private final String messageKey; // 国际化消息key
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
package com.qqchen.deploy.backend.model.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 仓库分支DTO
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "仓库分支DTO")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositoryBranchDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "外部系统ID")
|
||||
@NotNull(message = "外部系统ID不能为空")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Schema(description = "所属项目ID")
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "分支名称")
|
||||
@NotBlank(message = "分支名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "是否为默认分支")
|
||||
private Boolean isDefaultBranch = false;
|
||||
|
||||
@Schema(description = "是否受保护")
|
||||
private Boolean isProtected = false;
|
||||
|
||||
@Schema(description = "是否可推送")
|
||||
private Boolean canPush = true;
|
||||
|
||||
@Schema(description = "开发者是否可推送")
|
||||
private Boolean developersCanPush = true;
|
||||
|
||||
@Schema(description = "开发者是否可合并")
|
||||
private Boolean developersCanMerge = true;
|
||||
|
||||
@Schema(description = "最新提交ID")
|
||||
private String commitId;
|
||||
|
||||
@Schema(description = "最新提交信息")
|
||||
private String commitMessage;
|
||||
|
||||
@Schema(description = "最新提交作者")
|
||||
private String commitAuthor;
|
||||
|
||||
@Schema(description = "最新提交时间")
|
||||
private LocalDateTime commitDate;
|
||||
|
||||
@Schema(description = "网页URL")
|
||||
private String webUrl;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.qqchen.deploy.backend.model.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 仓库组DTO
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "仓库组DTO")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositoryGroupDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "外部系统ID")
|
||||
@NotNull(message = "外部系统ID不能为空")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Schema(description = "外部系统中的组ID")
|
||||
@NotNull(message = "组ID不能为空")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "仓库组名称")
|
||||
@NotBlank(message = "仓库组名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "仓库组路径")
|
||||
@NotBlank(message = "仓库组路径不能为空")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "仓库组描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见性:private-私有,internal-内部,public-公开")
|
||||
private String visibility;
|
||||
|
||||
@Schema(description = "父级仓库组ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "网页URL")
|
||||
private String webUrl;
|
||||
|
||||
@Schema(description = "头像URL")
|
||||
private String avatarUrl;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabled = true;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sort = 0;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.qqchen.deploy.backend.model.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 仓库项目DTO
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "仓库项目DTO")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositoryProjectDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "外部系统ID")
|
||||
@NotNull(message = "外部系统ID不能为空")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Schema(description = "外部系统中的项目ID")
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "项目名称")
|
||||
@NotBlank(message = "项目名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "项目路径")
|
||||
@NotBlank(message = "项目路径不能为空")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "项目描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见性:private-私有,internal-内部,public-公开")
|
||||
private String visibility;
|
||||
|
||||
@Schema(description = "所属仓库组ID")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "默认分支")
|
||||
private String defaultBranch;
|
||||
|
||||
@Schema(description = "网页URL")
|
||||
private String webUrl;
|
||||
|
||||
@Schema(description = "SSH克隆地址")
|
||||
private String sshUrl;
|
||||
|
||||
@Schema(description = "HTTP克隆地址")
|
||||
private String httpUrl;
|
||||
|
||||
@Schema(description = "最后活动时间")
|
||||
private LocalDateTime lastActivityAt;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabled = true;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sort = 0;
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.qqchen.deploy.backend.model.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 仓库同步状态DTO
|
||||
* 用于查询单个同步任务的详细状态
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "仓库同步状态DTO")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositorySyncStatusDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "外部系统ID")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Schema(description = "外部系统名称")
|
||||
private String externalSystemName;
|
||||
|
||||
@Schema(description = "同步开始时间")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "同步结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "同步状态:PENDING-等待中,RUNNING-运行中,SUCCESS-成功,FAILED-失败")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMessage;
|
||||
|
||||
@Schema(description = "同步的组数量")
|
||||
private Integer groupCount;
|
||||
|
||||
@Schema(description = "同步的项目数量")
|
||||
private Integer projectCount;
|
||||
|
||||
@Schema(description = "同步的分支数量")
|
||||
private Integer branchCount;
|
||||
|
||||
@Schema(description = "同步耗时(秒)")
|
||||
private Long durationSeconds;
|
||||
|
||||
@Schema(description = "同步详细日志")
|
||||
private String syncLog;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.qqchen.deploy.backend.model.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 仓库同步任务DTO
|
||||
* 用于展示正在运行的同步任务信息
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "仓库同步任务DTO")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositorySyncTaskDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "外部系统ID")
|
||||
private Long externalSystemId;
|
||||
|
||||
@Schema(description = "外部系统名称")
|
||||
private String externalSystemName;
|
||||
|
||||
@Schema(description = "同步开始时间")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "同步状态:PENDING-等待中,RUNNING-运行中,SUCCESS-成功,FAILED-失败")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMessage;
|
||||
|
||||
@Schema(description = "是否正在运行")
|
||||
private Boolean isRunning;
|
||||
|
||||
@Schema(description = "已同步的组数量")
|
||||
private Integer syncedGroupCount;
|
||||
|
||||
@Schema(description = "已同步的项目数量")
|
||||
private Integer syncedProjectCount;
|
||||
|
||||
@Schema(description = "已同步的分支数量")
|
||||
private Integer syncedBranchCount;
|
||||
|
||||
@Schema(description = "预计剩余时间(秒)")
|
||||
private Long estimatedRemainingSeconds;
|
||||
}
|
||||
@ -7,11 +7,17 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface IRepositoryBranchRepository extends IBaseRepository<RepositoryBranch, Long> {
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM RepositoryBranch b WHERE b.repositoryId = :repositoryId")
|
||||
void deleteByRepositoryId(Long repositoryId);
|
||||
void deleteByExternalSystemId(Long externalSystemId);
|
||||
|
||||
Optional<RepositoryBranch> findByExternalSystemIdAndProjectIdAndName(Long externalSystemId, Long projectId, String name);
|
||||
|
||||
List<RepositoryBranch> findByExternalSystemIdAndProjectIdAndDeletedFalse(Long externalSystemId, Long projectId);
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryConfig;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface IRepositoryConfigRepository extends IBaseRepository<RepositoryConfig, Long> {
|
||||
List<RepositoryConfig> findByDeletedFalseOrderBySort();
|
||||
boolean existsByNameAndDeletedFalse(String name);
|
||||
}
|
||||
@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@ -14,8 +15,9 @@ public interface IRepositoryGroupRepository extends IBaseRepository<RepositoryGr
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM RepositoryGroup g WHERE g.repositoryId = :repositoryId")
|
||||
void deleteByRepositoryId(Long repositoryId);
|
||||
|
||||
Optional<RepositoryGroup> findByRepositoryIdAndGroupId(Long repositoryId, Long groupId);
|
||||
void deleteByExternalSystemId(Long externalSystemId);
|
||||
|
||||
Optional<RepositoryGroup> findByExternalSystemIdAndGroupId(Long externalSystemId, Long groupId);
|
||||
|
||||
List<RepositoryGroup> findByExternalSystemIdAndDeletedFalseOrderBySortAsc(Long externalSystemId);
|
||||
}
|
||||
@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@ -14,8 +15,9 @@ public interface IRepositoryProjectRepository extends IBaseRepository<Repository
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM RepositoryProject p WHERE p.repositoryId = :repositoryId")
|
||||
void deleteByRepositoryId(Long repositoryId);
|
||||
|
||||
Optional<RepositoryProject> findByRepositoryIdAndProjectId(Long repositoryId, Long projectId);
|
||||
void deleteByExternalSystemId(Long externalSystemId);
|
||||
|
||||
Optional<RepositoryProject> findByExternalSystemIdAndProjectId(Long externalSystemId, Long projectId);
|
||||
|
||||
List<RepositoryProject> findByExternalSystemIdAndGroupIdAndDeletedFalseOrderBySortAsc(Long externalSystemId, Long groupId);
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
package com.qqchen.deploy.backend.service;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.RepositoryGroup;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryProject;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryBranch;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryGroupDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryProjectDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryBranchDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositorySyncStatusDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositorySyncTaskDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 版本控制仓库服务接口
|
||||
* 提供代码仓库的组织结构、项目和分支的管理功能,以及与外部版本控制系统的数据同步功能
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface IRepositoryVersionControlService {
|
||||
|
||||
/**
|
||||
* 获取指定外部系统的仓库组列表
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 仓库组列表,按排序号升序排列
|
||||
*/
|
||||
List<RepositoryGroupDTO> listGroups(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 获取指定的仓库组信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param groupId 仓库组ID
|
||||
* @return 仓库组信息
|
||||
* @throws com.qqchen.deploy.backend.framework.exception.BusinessException 当仓库组不存在时抛出异常
|
||||
*/
|
||||
RepositoryGroupDTO getGroup(Long externalSystemId, Long groupId);
|
||||
|
||||
/**
|
||||
* 同步指定外部系统的仓库组数据
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncGroups(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 获取指定仓库组下的项目列表
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param groupId 仓库组ID
|
||||
* @return 项目列表,按排序号升序排列
|
||||
*/
|
||||
List<RepositoryProjectDTO> listProjects(Long externalSystemId, Long groupId);
|
||||
|
||||
/**
|
||||
* 获取指定的项目信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param projectId 项目ID
|
||||
* @return 项目信息
|
||||
* @throws com.qqchen.deploy.backend.framework.exception.BusinessException 当项目不存在时抛出异常
|
||||
*/
|
||||
RepositoryProjectDTO getProject(Long externalSystemId, Long projectId);
|
||||
|
||||
/**
|
||||
* 同步指定仓库组下的项目数据
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param groupId 仓库组ID
|
||||
*/
|
||||
void syncProjects(Long externalSystemId, Long groupId);
|
||||
|
||||
/**
|
||||
* 获取指定项目的分支列表
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param projectId 项目ID
|
||||
* @return 分支列表
|
||||
*/
|
||||
List<RepositoryBranchDTO> listBranches(Long externalSystemId, Long projectId);
|
||||
|
||||
/**
|
||||
* 获取指定的分支信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param projectId 项目ID
|
||||
* @param branchName 分支名称
|
||||
* @return 分支信息
|
||||
* @throws com.qqchen.deploy.backend.framework.exception.BusinessException 当分支不存在时抛出异常
|
||||
*/
|
||||
RepositoryBranchDTO getBranch(Long externalSystemId, Long projectId, String branchName);
|
||||
|
||||
/**
|
||||
* 同步指定项目的分支数据
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param projectId 项目ID
|
||||
*/
|
||||
void syncBranches(Long externalSystemId, Long projectId);
|
||||
|
||||
/**
|
||||
* 同步指定外部系统的所有数据(同步组、项目、分支)
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncAll(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 异步同步指定外部系统的所有数据
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步任务ID
|
||||
*/
|
||||
Long asyncSyncAll(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 获取同步任务状态
|
||||
*
|
||||
* @param historyId 同步历史ID
|
||||
* @return 同步状态信息
|
||||
*/
|
||||
RepositorySyncStatusDTO getSyncStatus(Long historyId);
|
||||
|
||||
/**
|
||||
* 获取正在运行的同步任务列表
|
||||
*
|
||||
* @return 运行中的同步任务列表
|
||||
*/
|
||||
List<RepositorySyncTaskDTO> getRunningSyncs();
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
package com.qqchen.deploy.backend.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.RepositoryGroup;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryProject;
|
||||
import com.qqchen.deploy.backend.entity.RepositoryBranch;
|
||||
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryGroupDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryProjectDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositoryBranchDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositorySyncStatusDTO;
|
||||
import com.qqchen.deploy.backend.model.dto.RepositorySyncTaskDTO;
|
||||
import com.qqchen.deploy.backend.repository.IRepositoryGroupRepository;
|
||||
import com.qqchen.deploy.backend.repository.IRepositoryProjectRepository;
|
||||
import com.qqchen.deploy.backend.repository.IRepositoryBranchRepository;
|
||||
import com.qqchen.deploy.backend.service.IRepositoryVersionControlService;
|
||||
import com.qqchen.deploy.backend.converter.RepositoryConverter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 版本控制仓库服务实现类
|
||||
* 用于管理代码仓库的组织结构、项目和分支,支持与外部版本控制系统(如GitLab)的数据同步
|
||||
*
|
||||
* @author QQchen
|
||||
* @version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@ServiceType(ServiceType.Type.DATABASE)
|
||||
@RequiredArgsConstructor
|
||||
public class RepositoryVersionControlServiceImpl implements IRepositoryVersionControlService {
|
||||
|
||||
private final IRepositoryGroupRepository groupRepository;
|
||||
private final IRepositoryProjectRepository projectRepository;
|
||||
private final IRepositoryBranchRepository branchRepository;
|
||||
private final RepositoryConverter repositoryConverter;
|
||||
|
||||
@Override
|
||||
public List<RepositoryGroupDTO> listGroups(Long externalSystemId) {
|
||||
log.debug("获取仓库组列表, externalSystemId: {}", externalSystemId);
|
||||
return groupRepository.findByExternalSystemIdAndDeletedFalseOrderBySortAsc(externalSystemId)
|
||||
.stream()
|
||||
.map(repositoryConverter::toDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryGroupDTO getGroup(Long externalSystemId, Long groupId) {
|
||||
log.debug("获取仓库组信息, externalSystemId: {}, groupId: {}", externalSystemId, groupId);
|
||||
RepositoryGroup group = groupRepository.findByExternalSystemIdAndGroupId(externalSystemId, groupId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.REPOSITORY_GROUP_NOT_FOUND));
|
||||
return repositoryConverter.toDto(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncGroups(Long externalSystemId) {
|
||||
log.info("开始同步仓库组数据, externalSystemId: {}", externalSystemId);
|
||||
// TODO: 实现仓库组同步逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepositoryProjectDTO> listProjects(Long externalSystemId, Long groupId) {
|
||||
log.debug("获取项目列表, externalSystemId: {}, groupId: {}", externalSystemId, groupId);
|
||||
return projectRepository.findByExternalSystemIdAndGroupIdAndDeletedFalseOrderBySortAsc(externalSystemId, groupId)
|
||||
.stream()
|
||||
.map(repositoryConverter::toDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryProjectDTO getProject(Long externalSystemId, Long projectId) {
|
||||
log.debug("获取项目信息, externalSystemId: {}, projectId: {}", externalSystemId, projectId);
|
||||
RepositoryProject project = projectRepository.findByExternalSystemIdAndProjectId(externalSystemId, projectId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.REPOSITORY_PROJECT_NOT_FOUND));
|
||||
return repositoryConverter.toDto(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncProjects(Long externalSystemId, Long groupId) {
|
||||
log.info("开始同步项目数据, externalSystemId: {}, groupId: {}", externalSystemId, groupId);
|
||||
// TODO: 实现项目同步逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepositoryBranchDTO> listBranches(Long externalSystemId, Long projectId) {
|
||||
log.debug("获取分支列表, externalSystemId: {}, projectId: {}", externalSystemId, projectId);
|
||||
return branchRepository.findByExternalSystemIdAndProjectIdAndDeletedFalse(externalSystemId, projectId)
|
||||
.stream()
|
||||
.map(repositoryConverter::toDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryBranchDTO getBranch(Long externalSystemId, Long projectId, String branchName) {
|
||||
log.debug("获取分支信息, externalSystemId: {}, projectId: {}, branchName: {}",
|
||||
externalSystemId, projectId, branchName);
|
||||
RepositoryBranch branch = branchRepository.findByExternalSystemIdAndProjectIdAndName(externalSystemId, projectId, branchName)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.REPOSITORY_BRANCH_NOT_FOUND));
|
||||
return repositoryConverter.toDto(branch);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncBranches(Long externalSystemId, Long projectId) {
|
||||
log.info("开始同步分支数据, externalSystemId: {}, projectId: {}", externalSystemId, projectId);
|
||||
// TODO: 实现分支同步逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncAll(Long externalSystemId) {
|
||||
log.info("开始全量同步数据, externalSystemId: {}", externalSystemId);
|
||||
// TODO: 实现全量同步逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long asyncSyncAll(Long externalSystemId) {
|
||||
log.info("开始异步全量同步数据, externalSystemId: {}", externalSystemId);
|
||||
// TODO: 实现异步全量同步逻辑
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositorySyncStatusDTO getSyncStatus(Long historyId) {
|
||||
log.debug("获取同步状态, historyId: {}", historyId);
|
||||
// TODO: 实现获取同步状态逻辑
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepositorySyncTaskDTO> getRunningSyncs() {
|
||||
log.debug("获取运行中的同步任务列表");
|
||||
// TODO: 实现获取运行中的同步任务列表逻辑
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ CREATE TABLE sys_role_tag (
|
||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||
|
||||
name VARCHAR(50) NOT NULL COMMENT '标签名称',
|
||||
color VARCHAR(20) NULL COMMENT '标签<EFBFBD><EFBFBD>色(十六进制颜色码)'
|
||||
color VARCHAR(20) NULL COMMENT '标签<EFBFBD><EFBFBD><EFBFBD>十六进制颜色码)'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色标签表';
|
||||
|
||||
-- 角色标签关联表
|
||||
@ -261,4 +261,119 @@ CREATE TABLE sys_external_system (
|
||||
CONSTRAINT UK_external_system_name UNIQUE (name),
|
||||
CONSTRAINT UK_external_system_type_url UNIQUE (type, url)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统表';
|
||||
|
||||
-- 代码仓库组表
|
||||
CREATE TABLE deploy_repo_group (
|
||||
-- 基础字段
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||
create_by VARCHAR(100) NULL COMMENT '创建人',
|
||||
create_time DATETIME(6) NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(100) NULL COMMENT '更新人',
|
||||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||||
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除',
|
||||
|
||||
-- 业务字段
|
||||
name VARCHAR(100) NOT NULL COMMENT '仓库组名称',
|
||||
description VARCHAR(500) NULL COMMENT '仓库组描述',
|
||||
group_id BIGINT NOT NULL COMMENT '外部系统中的组ID',
|
||||
parent_id BIGINT NULL COMMENT '父级仓库组ID',
|
||||
path VARCHAR(200) NOT NULL COMMENT '仓库组路径',
|
||||
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
||||
avatar_url VARCHAR(255) NULL COMMENT '头像URL',
|
||||
web_url VARCHAR(255) NULL COMMENT '网页URL',
|
||||
visibility ENUM('private', 'internal', 'public') NOT NULL DEFAULT 'private' COMMENT '可见性:private-私有,internal-内部,public-公开',
|
||||
sort INT DEFAULT 0 COMMENT '排序号',
|
||||
|
||||
-- 索引
|
||||
INDEX idx_external_system_group_id (external_system_id, group_id) COMMENT '外部系统组ID索引',
|
||||
INDEX idx_parent_id (parent_id) COMMENT '父级ID索引',
|
||||
INDEX idx_path (path) COMMENT '路径索引',
|
||||
UNIQUE INDEX uk_external_system_group_path (external_system_id, path) COMMENT '外部系统下路径唯一',
|
||||
|
||||
-- 外键约束
|
||||
CONSTRAINT fk_group_parent FOREIGN KEY (parent_id)
|
||||
REFERENCES deploy_repo_group (id),
|
||||
CONSTRAINT fk_group_external_system FOREIGN KEY (external_system_id)
|
||||
REFERENCES sys_external_system (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代码仓库组表';
|
||||
|
||||
-- 代码仓库项目表
|
||||
CREATE TABLE deploy_repo_project (
|
||||
-- 基础字段
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||
create_by VARCHAR(100) NULL COMMENT '创建人',
|
||||
create_time DATETIME(6) NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(100) NULL COMMENT '更新人',
|
||||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||||
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除',
|
||||
|
||||
-- 业务字段
|
||||
name VARCHAR(100) NOT NULL COMMENT '项目名称',
|
||||
description VARCHAR(500) NULL COMMENT '项目描述',
|
||||
project_id BIGINT NOT NULL COMMENT '外部系统中的项目ID',
|
||||
group_id BIGINT NULL COMMENT '所属仓库组ID',
|
||||
path VARCHAR(200) NOT NULL COMMENT '项目路径',
|
||||
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
||||
is_default_branch VARCHAR(100) NULL COMMENT '默认分支',
|
||||
is_enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用:0-禁用,1-启用',
|
||||
visibility ENUM('private', 'internal', 'public') NOT NULL DEFAULT 'private' COMMENT '可见性:private-私有,internal-内部,public-公开',
|
||||
http_url VARCHAR(255) NULL COMMENT 'HTTP克隆地址',
|
||||
ssh_url VARCHAR(255) NULL COMMENT 'SSH克隆地址',
|
||||
web_url VARCHAR(255) NULL COMMENT '网页URL',
|
||||
last_activity_at DATETIME(6) NULL COMMENT '最后活动时间',
|
||||
sort INT DEFAULT 0 COMMENT '排序号',
|
||||
|
||||
-- 索引
|
||||
INDEX idx_external_system_project_id (external_system_id, project_id) COMMENT '外部系统项目ID索引',
|
||||
INDEX idx_group_id (group_id) COMMENT '组ID索引',
|
||||
INDEX idx_path (path) COMMENT '路径索引',
|
||||
UNIQUE INDEX uk_external_system_project_path (external_system_id, path) COMMENT '外部系统下路径唯一',
|
||||
|
||||
-- 外键约束
|
||||
CONSTRAINT fk_project_group FOREIGN KEY (group_id)
|
||||
REFERENCES deploy_repo_group (id),
|
||||
CONSTRAINT fk_project_external_system FOREIGN KEY (external_system_id)
|
||||
REFERENCES sys_external_system (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代码仓库项目表';
|
||||
|
||||
-- 代码仓库分支表
|
||||
CREATE TABLE deploy_repo_branch (
|
||||
-- 基础字段
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||
create_by VARCHAR(100) NULL COMMENT '创建人',
|
||||
create_time DATETIME(6) NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(100) NULL COMMENT '更新人',
|
||||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||||
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除',
|
||||
|
||||
-- 业务字段
|
||||
name VARCHAR(100) NOT NULL COMMENT '分支名称',
|
||||
project_id BIGINT NOT NULL COMMENT '所属项目ID',
|
||||
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
||||
is_default_branch BIT DEFAULT 0 COMMENT '是否为默认分支:0-否,1-是',
|
||||
is_protected BIT DEFAULT 0 COMMENT '是否受保护:0-否,1-是',
|
||||
can_push BIT DEFAULT 1 COMMENT '是否可推送:0-否,1-是',
|
||||
developers_can_push BIT DEFAULT 1 COMMENT '开发者是否可推送:0-否,1-是',
|
||||
developers_can_merge BIT DEFAULT 1 COMMENT '开发者是否可合并:0-否,1-是',
|
||||
commit_id VARCHAR(64) NULL COMMENT '最新提交ID',
|
||||
commit_message TEXT NULL COMMENT '最新提交信息',
|
||||
commit_author VARCHAR(100) NULL COMMENT '最新提交作者',
|
||||
commit_date DATETIME(6) NULL COMMENT '最新提交时间',
|
||||
web_url VARCHAR(255) NULL COMMENT '网页URL',
|
||||
|
||||
-- 索引
|
||||
INDEX idx_project_id (project_id) COMMENT '项目ID索引',
|
||||
INDEX idx_external_system_id (external_system_id) COMMENT '外部系统ID索引',
|
||||
INDEX idx_name (name) COMMENT '分支名称索引',
|
||||
UNIQUE INDEX uk_project_branch_name (project_id, name) COMMENT '项目下分支名称唯一',
|
||||
|
||||
-- 外键约束
|
||||
CONSTRAINT fk_branch_project FOREIGN KEY (project_id)
|
||||
REFERENCES deploy_repo_project (id),
|
||||
CONSTRAINT fk_branch_external_system FOREIGN KEY (external_system_id)
|
||||
REFERENCES sys_external_system (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代码仓库分支表';
|
||||
|
||||
@ -74,4 +74,17 @@ external.system.type.not.supported=不支持的系统类型
|
||||
|
||||
# Git系统相关错误
|
||||
external.system.git.auth.type.error=Git系统只支持Token认证
|
||||
external.system.git.token.required=Git系统必须提供Token
|
||||
external.system.git.token.required=Git系统必须提供Token
|
||||
|
||||
# 仓库相关错误消息
|
||||
repository.group.not.found=仓库组不存在
|
||||
repository.group.name.exists=仓库组名称"{0}"已存在
|
||||
repository.group.path.exists=仓库组路径"{0}"已存在
|
||||
repository.project.not.found=仓库项目不存在
|
||||
repository.project.name.exists=仓库项目名称"{0}"已存在
|
||||
repository.project.path.exists=仓库项目路径"{0}"已存在
|
||||
repository.branch.not.found=分支不存在
|
||||
repository.branch.name.exists=分支名称"{0}"已存在
|
||||
repository.sync.in.progress=仓库同步正在进行中
|
||||
repository.sync.failed=仓库同步失败:{0}
|
||||
repository.sync.history.not.found=同步历史记录不存在
|
||||
Loading…
Reference in New Issue
Block a user