迁移实体类,并增加了领域模型(尝试使用event)
This commit is contained in:
parent
ee1e20daff
commit
b49a64724c
@ -3,7 +3,6 @@ package com.qqchen.deploy.backend.api;
|
|||||||
import com.qqchen.deploy.backend.common.controller.BaseController;
|
import com.qqchen.deploy.backend.common.controller.BaseController;
|
||||||
import com.qqchen.deploy.backend.common.api.Response;
|
import com.qqchen.deploy.backend.common.api.Response;
|
||||||
import com.qqchen.deploy.backend.common.enums.ResponseCode;
|
import com.qqchen.deploy.backend.common.enums.ResponseCode;
|
||||||
import com.qqchen.deploy.backend.common.utils.MessageUtils;
|
|
||||||
import com.qqchen.deploy.backend.converter.UserConverter;
|
import com.qqchen.deploy.backend.converter.UserConverter;
|
||||||
import com.qqchen.deploy.backend.entity.User;
|
import com.qqchen.deploy.backend.entity.User;
|
||||||
import com.qqchen.deploy.backend.dto.query.UserQuery;
|
import com.qqchen.deploy.backend.dto.query.UserQuery;
|
||||||
@ -39,7 +38,7 @@ public class UserApiController extends BaseController<User, Long, UserQuery, Use
|
|||||||
|
|
||||||
User user = converter.toEntity(request);
|
User user = converter.toEntity(request);
|
||||||
User savedUser = userService.register(user);
|
User savedUser = userService.register(user);
|
||||||
return Response.success(converter.toVO(savedUser));
|
return Response.success(converter.toResponse(savedUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
|
|||||||
@ -5,8 +5,15 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记实体是否支持逻辑删除
|
||||||
|
* 被标记的实体在删除时不会物理删除数据,而是标记删除状态
|
||||||
|
*/
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface SoftDelete {
|
public @interface LogicDelete {
|
||||||
boolean value() default true; // 默认启用软删除
|
/**
|
||||||
|
* 是否启用逻辑删除,默认启用
|
||||||
|
*/
|
||||||
|
boolean value() default true;
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
|||||||
public Response<V> create(@RequestBody R request) {
|
public Response<V> create(@RequestBody R request) {
|
||||||
T entity = converter.toEntity(request);
|
T entity = converter.toEntity(request);
|
||||||
T savedEntity = service.create(entity);
|
T savedEntity = service.create(entity);
|
||||||
return Response.success(converter.toVO(savedEntity));
|
return Response.success(converter.toResponse(savedEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@ -36,7 +36,7 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
|||||||
T entity = service.findById(id);
|
T entity = service.findById(id);
|
||||||
converter.updateEntity(entity, request);
|
converter.updateEntity(entity, request);
|
||||||
T updatedEntity = service.update(entity);
|
T updatedEntity = service.update(entity);
|
||||||
return Response.success(converter.toVO(updatedEntity));
|
return Response.success(converter.toResponse(updatedEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@ -48,18 +48,18 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
|||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Response<V> findById(@PathVariable ID id) {
|
public Response<V> findById(@PathVariable ID id) {
|
||||||
T entity = service.findById(id);
|
T entity = service.findById(id);
|
||||||
return Response.success(converter.toVO(entity));
|
return Response.success(converter.toResponse(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public Response<List<V>> findAll() {
|
public Response<List<V>> findAll() {
|
||||||
List<T> entities = service.findAll();
|
List<T> entities = service.findAll();
|
||||||
return Response.success(converter.toVOList(entities));
|
return Response.success(converter.toResponseList(entities));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
public Response<Page<V>> page(Q query) {
|
public Response<Page<V>> page(Q query) {
|
||||||
Page<T> page = service.page(query);
|
Page<T> page = service.page(query);
|
||||||
return Response.success(page.map(entity -> converter.toVO(entity)));
|
return Response.success(page.map(entity -> converter.toResponse(entity)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,16 +12,16 @@ public interface BaseConverter<D extends Entity<?>, R extends BaseRequest, V> {
|
|||||||
D toEntity(R request);
|
D toEntity(R request);
|
||||||
|
|
||||||
// Domain -> VO
|
// Domain -> VO
|
||||||
V toVO(D entity);
|
V toResponse(D entity);
|
||||||
|
|
||||||
// Domain List -> VO List
|
// Domain List -> VO List
|
||||||
List<V> toVOList(List<D> entityList);
|
List<V> toResponseList(List<D> entityList);
|
||||||
|
|
||||||
// 更新实体
|
// 更新实体
|
||||||
void updateEntity(@MappingTarget D entity, R request);
|
void updateEntity(@MappingTarget D entity, R request);
|
||||||
|
|
||||||
// 转换分页结果
|
// 转换分页结果
|
||||||
default Page<V> toVOPage(Page<D> page) {
|
default Page<V> toResponsePage(Page<D> page) {
|
||||||
return page.map(this::toVO);
|
return page.map(this::toResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,72 @@
|
|||||||
package com.qqchen.deploy.backend.common.domain;
|
package com.qqchen.deploy.backend.common.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import com.qqchen.deploy.backend.common.event.DomainEvent;
|
||||||
|
import org.springframework.data.domain.AfterDomainEventPublication;
|
||||||
|
import org.springframework.data.domain.DomainEvents;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* 聚合根基类
|
|
||||||
*/
|
|
||||||
public abstract class AggregateRoot<ID extends Serializable> extends Entity<ID> {
|
public abstract class AggregateRoot<ID extends Serializable> extends Entity<ID> {
|
||||||
// 聚合根特定的行为可以在这里添加
|
|
||||||
|
private transient final List<DomainEvent> domainEvents = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册领域事件
|
||||||
|
*/
|
||||||
|
protected void registerDomainEvent(DomainEvent event) {
|
||||||
|
if (event != null) {
|
||||||
|
domainEvents.add(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取并清除所有事件
|
||||||
|
*/
|
||||||
|
@DomainEvents
|
||||||
|
protected Collection<DomainEvent> domainEvents() {
|
||||||
|
List<DomainEvent> events = new ArrayList<>(this.domainEvents);
|
||||||
|
this.domainEvents.clear();
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring Data JPA会在事件发布后调用此方法
|
||||||
|
*/
|
||||||
|
@AfterDomainEventPublication
|
||||||
|
protected void clearDomainEvents() {
|
||||||
|
this.domainEvents.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证聚合根状态
|
||||||
|
* 子类可以重写此方法实现具体的验证逻辑
|
||||||
|
*/
|
||||||
|
protected void validateState() {
|
||||||
|
// 默认实现为空,由子类根据需要重写
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在保存前验证状态
|
||||||
|
*/
|
||||||
|
public void validateBeforeSave() {
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在更新前验证状态
|
||||||
|
*/
|
||||||
|
public void validateBeforeUpdate() {
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在删除前验证状态
|
||||||
|
*/
|
||||||
|
public void validateBeforeDelete() {
|
||||||
|
// 子类可以重写此方法添加删除前的验证
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.qqchen.deploy.backend.common.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public abstract class DomainEvent {
|
||||||
|
private final String eventId;
|
||||||
|
private final LocalDateTime occurredOn;
|
||||||
|
|
||||||
|
protected DomainEvent() {
|
||||||
|
this.eventId = java.util.UUID.randomUUID().toString();
|
||||||
|
this.occurredOn = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.common.annotation.SoftDelete;
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
import com.qqchen.deploy.backend.common.domain.Entity;
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
import com.qqchen.deploy.backend.common.enums.QueryType;
|
import com.qqchen.deploy.backend.common.enums.QueryType;
|
||||||
import com.qqchen.deploy.backend.common.query.BaseQuery;
|
import com.qqchen.deploy.backend.common.query.BaseQuery;
|
||||||
@ -73,7 +73,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Serializa
|
|||||||
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
|
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
|
||||||
if (genericTypes != null && genericTypes.length > 0) {
|
if (genericTypes != null && genericTypes.length > 0) {
|
||||||
Class<T> entityClass = (Class<T>) genericTypes[0];
|
Class<T> entityClass = (Class<T>) genericTypes[0];
|
||||||
SoftDelete softDelete = entityClass.getAnnotation(SoftDelete.class);
|
LogicDelete softDelete = entityClass.getAnnotation(LogicDelete.class);
|
||||||
|
|
||||||
if (softDelete != null && softDelete.value()) {
|
if (softDelete != null && softDelete.value()) {
|
||||||
Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted");
|
Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted");
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public interface UserConverter extends BaseConverter<User, UserRequest, UserResp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Mapping(target = "password", ignore = true)
|
@Mapping(target = "password", ignore = true)
|
||||||
UserResponse toVO(User user);
|
UserResponse toResponse(User user);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Mapping(target = "id", ignore = true)
|
@Mapping(target = "id", ignore = true)
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
package com.qqchen.deploy.backend.dto.query;
|
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.common.annotation.QueryField;
|
|
||||||
import com.qqchen.deploy.backend.common.enums.QueryType;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class UserAddressQuery {
|
|
||||||
@QueryField(type = QueryType.LIKE)
|
|
||||||
private String city;
|
|
||||||
|
|
||||||
@QueryField(type = QueryType.EQUAL)
|
|
||||||
private String postcode;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Transient;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_department")
|
||||||
|
@LogicDelete
|
||||||
|
public class Department extends Entity<Long> {
|
||||||
|
|
||||||
|
@NotBlank(message = "部门名称不能为空")
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "部门编码不能为空")
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "parent_id")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Integer sort = 0;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
@Column(name = "leader_id")
|
||||||
|
private Long leaderId;
|
||||||
|
|
||||||
|
@Column(name = "leader_name")
|
||||||
|
private String leaderName;
|
||||||
|
|
||||||
|
@Transient // 不映射到数据库
|
||||||
|
private List<Department> children = new ArrayList<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_jenkins_build")
|
||||||
|
@LogicDelete
|
||||||
|
public class JenkinsBuild extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "jenkins_id", nullable = false)
|
||||||
|
private Long jenkinsId;
|
||||||
|
|
||||||
|
@Column(name = "job_id", nullable = false)
|
||||||
|
private Long jobId;
|
||||||
|
|
||||||
|
@Column(name = "build_number", nullable = false)
|
||||||
|
private Integer buildNumber;
|
||||||
|
|
||||||
|
@Column(name = "build_url", nullable = false)
|
||||||
|
private String buildUrl;
|
||||||
|
|
||||||
|
@Column(name = "build_status", nullable = false)
|
||||||
|
private String buildStatus;
|
||||||
|
|
||||||
|
@Column(name = "start_time", nullable = false)
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
private Long duration;
|
||||||
|
|
||||||
|
@Column(name = "trigger_cause", columnDefinition = "TEXT")
|
||||||
|
private String triggerCause;
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_jenkins_config")
|
||||||
|
@LogicDelete
|
||||||
|
public class JenkinsConfig extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Column(name = "last_all_sync_time")
|
||||||
|
private LocalDateTime lastAllSyncTime;
|
||||||
|
|
||||||
|
@Column(name = "last_view_sync_time")
|
||||||
|
private LocalDateTime lastViewSyncTime;
|
||||||
|
|
||||||
|
@Column(name = "last_job_sync_time")
|
||||||
|
private LocalDateTime lastJobSyncTime;
|
||||||
|
|
||||||
|
@Column(name = "last_build_sync_time")
|
||||||
|
private LocalDateTime lastBuildSyncTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_jenkins_job")
|
||||||
|
@LogicDelete
|
||||||
|
public class JenkinsJob extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "jenkins_id", nullable = false)
|
||||||
|
private Long jenkinsId;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "view_id")
|
||||||
|
private JenkinsView view;
|
||||||
|
|
||||||
|
@Column(name = "job_name", nullable = false)
|
||||||
|
private String jobName;
|
||||||
|
|
||||||
|
@Column(name = "job_url", nullable = false)
|
||||||
|
private String jobUrl;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Boolean buildable;
|
||||||
|
|
||||||
|
@Column(name = "last_build_number")
|
||||||
|
private Integer lastBuildNumber;
|
||||||
|
|
||||||
|
@Column(name = "last_build_time")
|
||||||
|
private LocalDateTime lastBuildTime;
|
||||||
|
|
||||||
|
@Column(name = "last_build_status")
|
||||||
|
private String lastBuildStatus;
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.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 = "sys_jenkins_sync_history")
|
||||||
|
@LogicDelete
|
||||||
|
public class JenkinsSyncHistory extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "jenkins_id", nullable = false)
|
||||||
|
private Long jenkinsId;
|
||||||
|
|
||||||
|
@Column(name = "sync_type", nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private SyncType syncType;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private SyncStatus status;
|
||||||
|
|
||||||
|
@Column(name = "start_time", nullable = false)
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Column(name = "end_time")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
@Column(name = "error_message", columnDefinition = "TEXT")
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
public enum SyncType {
|
||||||
|
ALL, // 全量同步
|
||||||
|
VIEW, // 同步视图
|
||||||
|
JOB, // 同步作业
|
||||||
|
BUILD // 同步构建记录
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SyncStatus {
|
||||||
|
SUCCESS, // 同步成功
|
||||||
|
FAILED, // 同步失败
|
||||||
|
RUNNING // 同步中
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_jenkins_view")
|
||||||
|
@LogicDelete
|
||||||
|
public class JenkinsView extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "jenkins_id", nullable = false)
|
||||||
|
private Long jenkinsId;
|
||||||
|
|
||||||
|
@Column(name = "view_name", nullable = false)
|
||||||
|
private String viewName;
|
||||||
|
|
||||||
|
@Column(name = "view_url", nullable = false)
|
||||||
|
private String viewUrl;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_menu")
|
||||||
|
@LogicDelete
|
||||||
|
public class Menu extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String permission;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private String component;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Integer type; // 0-目录 1-菜单 2-按钮
|
||||||
|
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
@Column(name = "parent_id")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Integer sort = 0;
|
||||||
|
|
||||||
|
private Boolean hidden = false;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean enabled = true;
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_repository_branch")
|
||||||
|
@LogicDelete
|
||||||
|
public class RepositoryBranch extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "repository_id", nullable = false)
|
||||||
|
private Long repositoryId;
|
||||||
|
|
||||||
|
@Column(name = "project_id", nullable = false)
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "commit_id")
|
||||||
|
private String commitId;
|
||||||
|
|
||||||
|
@Column(name = "commit_message", columnDefinition = "TEXT")
|
||||||
|
private String commitMessage;
|
||||||
|
|
||||||
|
@Column(name = "commit_author")
|
||||||
|
private String commitAuthor;
|
||||||
|
|
||||||
|
@Column(name = "commit_date")
|
||||||
|
private LocalDateTime commitDate;
|
||||||
|
|
||||||
|
private Boolean protected_ = false;
|
||||||
|
|
||||||
|
@Column(name = "developers_can_push")
|
||||||
|
private Boolean developersCanPush = true;
|
||||||
|
|
||||||
|
@Column(name = "developers_can_merge")
|
||||||
|
private Boolean developersCanMerge = true;
|
||||||
|
|
||||||
|
@Column(name = "can_push")
|
||||||
|
private Boolean canPush = true;
|
||||||
|
|
||||||
|
@Column(name = "default_branch")
|
||||||
|
private Boolean defaultBranch = false;
|
||||||
|
|
||||||
|
@Column(name = "web_url")
|
||||||
|
private String webUrl;
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.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 = "sys_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;
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_repository_group")
|
||||||
|
@LogicDelete
|
||||||
|
public class RepositoryGroup extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "repository_id", nullable = false)
|
||||||
|
private Long repositoryId;
|
||||||
|
|
||||||
|
@Column(name = "group_id", nullable = false)
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private String visibility;
|
||||||
|
|
||||||
|
@Column(name = "parent_id")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Column(name = "web_url")
|
||||||
|
private String webUrl;
|
||||||
|
|
||||||
|
@Column(name = "avatar_url")
|
||||||
|
private String avatarUrl;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
private Integer sort = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_repository_project")
|
||||||
|
@LogicDelete
|
||||||
|
public class RepositoryProject extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "repository_id", nullable = false)
|
||||||
|
private Long repositoryId;
|
||||||
|
|
||||||
|
@Column(name = "project_id", nullable = false)
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private String visibility;
|
||||||
|
|
||||||
|
@Column(name = "group_id")
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
|
@Column(name = "default_branch")
|
||||||
|
private String defaultBranch;
|
||||||
|
|
||||||
|
@Column(name = "web_url")
|
||||||
|
private String webUrl;
|
||||||
|
|
||||||
|
@Column(name = "ssh_url")
|
||||||
|
private String sshUrl;
|
||||||
|
|
||||||
|
@Column(name = "http_url")
|
||||||
|
private String httpUrl;
|
||||||
|
|
||||||
|
@Column(name = "last_activity_at")
|
||||||
|
private LocalDateTime lastActivityAt;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
private Integer sort = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.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 = "sys_repository_sync_history")
|
||||||
|
@LogicDelete
|
||||||
|
public class RepositorySyncHistory extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "repository_id", nullable = false)
|
||||||
|
private Long repositoryId;
|
||||||
|
|
||||||
|
@Column(name = "sync_type", nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private SyncType syncType;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private SyncStatus status;
|
||||||
|
|
||||||
|
@Column(name = "error_message", columnDefinition = "TEXT")
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
@Column(name = "start_time", nullable = false)
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Column(name = "end_time")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
public enum SyncType {
|
||||||
|
GROUP, PROJECT, BRANCH
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SyncStatus {
|
||||||
|
SUCCESS, FAILED, RUNNING
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_role")
|
||||||
|
@LogicDelete
|
||||||
|
public class Role extends Entity<Long> {
|
||||||
|
|
||||||
|
@NotBlank(message = "角色名称不能为空")
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "角色编码不能为空")
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Integer sort = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_role_menu")
|
||||||
|
@LogicDelete
|
||||||
|
public class RoleMenu extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "role_id", nullable = false)
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
@Column(name = "menu_id", nullable = false)
|
||||||
|
private Long menuId;
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_tenant")
|
||||||
|
@LogicDelete
|
||||||
|
public class Tenant extends Entity<Long> {
|
||||||
|
|
||||||
|
@NotBlank(message = "租户名称不能为空")
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "租户编码不能为空")
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@Column(name = "contact_name")
|
||||||
|
private String contactName;
|
||||||
|
|
||||||
|
@Column(name = "contact_phone")
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean enabled = true;
|
||||||
|
}
|
||||||
@ -1,31 +1,143 @@
|
|||||||
package com.qqchen.deploy.backend.entity;
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.common.annotation.SoftDelete;
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
import com.qqchen.deploy.backend.common.domain.Entity;
|
import com.qqchen.deploy.backend.common.domain.AggregateRoot;
|
||||||
|
import com.qqchen.deploy.backend.event.UserRoleChangedEvent;
|
||||||
|
import jakarta.persistence.CascadeType;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@jakarta.persistence.Entity
|
@jakarta.persistence.Entity
|
||||||
@Table(name = "t_user")
|
@Table(name = "sys_user")
|
||||||
@SoftDelete
|
@LogicDelete
|
||||||
public class User extends Entity<Long> {
|
public class User extends AggregateRoot<Long> {
|
||||||
|
|
||||||
@Column(unique = true, nullable = false)
|
@Column(unique = true, nullable = false)
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@Column(unique = true, nullable = false)
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@Column(length = 50)
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
private String phone;
|
private String phone;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
private Boolean enabled = true;
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
@Column(name = "dept_id")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Column(name = "dept_name")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private Set<UserRole> userRoles = new HashSet<>();
|
||||||
|
|
||||||
|
public void addRole(Role role) {
|
||||||
|
UserRole userRole = new UserRole(this, role);
|
||||||
|
userRoles.add(userRole);
|
||||||
|
registerDomainEvent(new UserRoleChangedEvent(this.getId(), role.getId(), "ADD"));
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRole(Role role) {
|
||||||
|
boolean removed = userRoles.removeIf(ur -> ur.getRole().equals(role));
|
||||||
|
if (removed) {
|
||||||
|
registerDomainEvent(new UserRoleChangedEvent(this.getId(), role.getId(), "REMOVE"));
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changePassword(String oldPassword, String newPassword) {
|
||||||
|
if (!this.password.equals(oldPassword)) {
|
||||||
|
throw new IllegalArgumentException("Old password is incorrect");
|
||||||
|
}
|
||||||
|
this.password = newPassword;
|
||||||
|
registerDomainEvent(new PasswordChangedEvent(this.getId()));
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
if (this.enabled != enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
registerDomainEvent(new UserStatusChangedEvent(this.getId(), enabled));
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBasicInfo(String nickname, String phone, String email) {
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
if (!Objects.equals(this.nickname, nickname)) {
|
||||||
|
this.nickname = nickname;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(this.phone, phone)) {
|
||||||
|
this.phone = phone;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(this.email, email)) {
|
||||||
|
this.email = email;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
registerDomainEvent(new UserUpdatedEvent(this.getId()));
|
||||||
|
validateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRole(String roleCode) {
|
||||||
|
return userRoles.stream()
|
||||||
|
.map(UserRole::getRole)
|
||||||
|
.anyMatch(role -> role.getCode().equals(roleCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getRoleCodes() {
|
||||||
|
return userRoles.stream()
|
||||||
|
.map(UserRole::getRole)
|
||||||
|
.map(Role::getCode)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateState() {
|
||||||
|
if (username == null || username.trim().isEmpty()) {
|
||||||
|
throw new IllegalStateException("Username cannot be empty");
|
||||||
|
}
|
||||||
|
if (email == null || !email.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
|
||||||
|
throw new IllegalStateException("Invalid email format");
|
||||||
|
}
|
||||||
|
if (password == null || password.length() < 6) {
|
||||||
|
throw new IllegalStateException("Password must be at least 6 characters");
|
||||||
|
}
|
||||||
|
if (phone != null && !phone.matches("^\\d{11}$")) {
|
||||||
|
throw new IllegalStateException("Invalid phone number format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateBeforeDelete() {
|
||||||
|
if (!userRoles.isEmpty()) {
|
||||||
|
throw new IllegalStateException("Cannot delete user with assigned roles");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.qqchen.deploy.backend.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.common.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "sys_user_role")
|
||||||
|
@LogicDelete
|
||||||
|
public class UserRole extends Entity<Long> {
|
||||||
|
|
||||||
|
@Column(name = "user_id", nullable = false)
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Column(name = "role_id", nullable = false)
|
||||||
|
private Long roleId;
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.qqchen.deploy.backend.event;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.event.TransactionPhase;
|
||||||
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class UserEventListener {
|
||||||
|
|
||||||
|
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
|
||||||
|
public void handleUserRoleChanged(UserRoleChangedEvent event) {
|
||||||
|
log.info("User role changed - userId: {}, roleId: {}, action: {}",
|
||||||
|
event.getUserId(),
|
||||||
|
event.getRoleId(),
|
||||||
|
event.getAction());
|
||||||
|
|
||||||
|
// 这里可以添加后续处理逻辑
|
||||||
|
// 例如:发送通知、更新缓存等
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.qqchen.deploy.backend.event;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.common.event.DomainEvent;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class UserRoleChangedEvent extends DomainEvent {
|
||||||
|
private final Long userId;
|
||||||
|
private final Long roleId;
|
||||||
|
private final String action; // "ADD" or "REMOVE"
|
||||||
|
public UserRoleChangedEvent(Long userId, Long roleId, String action) {
|
||||||
|
super();
|
||||||
|
this.userId = userId;
|
||||||
|
this.roleId = roleId;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
backend/src/main/resources/messages.properties
Normal file
12
backend/src/main/resources/messages.properties
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# \u4E2D\u6587
|
||||||
|
response.success=\u64CD\u4F5C\u6210\u529F
|
||||||
|
response.error=\u7CFB\u7EDF\u9519\u8BEF
|
||||||
|
response.invalid.param=\u65E0\u6548\u7684\u53C2\u6570
|
||||||
|
response.unauthorized=\u672A\u6388\u6743
|
||||||
|
response.forbidden=\u7981\u6B62\u8BBF\u95EE
|
||||||
|
response.not.found=\u8D44\u6E90\u672A\u627E\u5230
|
||||||
|
response.conflict=\u8D44\u6E90\u51B2\u7A81
|
||||||
|
|
||||||
|
user.not.found=\u7528\u6237\u4E0D\u5B58\u5728
|
||||||
|
user.username.exists=\u7528\u6237\u540D\u5DF2\u5B58\u5728
|
||||||
|
user.email.exists=\u90AE\u7BB1\u5DF2\u5B58\u5728
|
||||||
@ -1,12 +0,0 @@
|
|||||||
# 中文
|
|
||||||
response.success=操作成功
|
|
||||||
response.error=系统错误
|
|
||||||
response.invalid.param=无效的参数
|
|
||||||
response.unauthorized=未授权
|
|
||||||
response.forbidden=禁止访问
|
|
||||||
response.not.found=资源未找到
|
|
||||||
response.conflict=资源冲突
|
|
||||||
|
|
||||||
user.not.found=用户不存在
|
|
||||||
user.username.exists=用户名已存在
|
|
||||||
user.email.exists=邮箱已存在
|
|
||||||
12
backend/src/main/resources/messages_zh_CN.properties
Normal file
12
backend/src/main/resources/messages_zh_CN.properties
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# \u4E2D\u6587
|
||||||
|
response.success=\u64CD\u4F5C\u6210\u529F
|
||||||
|
response.error=\u7CFB\u7EDF\u9519\u8BEF
|
||||||
|
response.invalid.param=\u65E0\u6548\u7684\u53C2\u6570
|
||||||
|
response.unauthorized=\u672A\u6388\u6743
|
||||||
|
response.forbidden=\u7981\u6B62\u8BBF\u95EE
|
||||||
|
response.not.found=\u8D44\u6E90\u672A\u627E\u5230
|
||||||
|
response.conflict=\u8D44\u6E90\u51B2\u7A81
|
||||||
|
|
||||||
|
user.not.found=\u7528\u6237\u4E0D\u5B58\u5728
|
||||||
|
user.username.exists=\u7528\u6237\u540D\u5DF2\u5B58\u5728
|
||||||
|
user.email.exists=\u90AE\u7BB1\u5DF2\u5B58\u5728
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package com.qqchen.deploy.common;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class BackendApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user