feat(dept): 添加部门管理数据层

- 新增 SysDept 领域模型(manage-sys)
- 新增 ISysDeptRepository 接口(manage-sys)
- 新增 SysDeptEntity 实体类(manage-db)
- 新增 SysDeptDao R2DBC 接口(manage-db)
- 新增 SysDeptConverter 转换器(manage-db)
- 新增 SysDeptRepository 实现类(manage-db)
- 新增 V6 Flyway 迁移脚本创建 sys_dept 表
This commit is contained in:
张翔
2026-05-06 19:17:18 +08:00
parent 404aa40d32
commit a74abce2d6
7 changed files with 303 additions and 0 deletions
@@ -0,0 +1,61 @@
package cn.novalon.manage.db.converter;
import cn.novalon.manage.sys.core.domain.SysDept;
import cn.novalon.manage.db.entity.SysDeptEntity;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class SysDeptConverter {
public SysDept toDomain(SysDeptEntity entity) {
if (entity == null) {
return null;
}
SysDept domain = new SysDept();
domain.setId(entity.getId());
domain.setParentId(entity.getParentId());
domain.setDeptName(entity.getDeptName());
domain.setOrderNum(entity.getOrderNum());
domain.setLeader(entity.getLeader());
domain.setPhone(entity.getPhone());
domain.setEmail(entity.getEmail());
domain.setStatus(entity.getStatus());
domain.setCreateBy(entity.getCreateBy());
domain.setUpdateBy(entity.getUpdateBy());
domain.setCreatedAt(entity.getCreatedAt());
domain.setUpdatedAt(entity.getUpdatedAt());
domain.setDeletedAt(entity.getDeletedAt());
return domain;
}
public SysDeptEntity toEntity(SysDept domain) {
if (domain == null) {
return null;
}
SysDeptEntity entity = new SysDeptEntity();
entity.setId(domain.getId());
entity.setParentId(domain.getParentId());
entity.setDeptName(domain.getDeptName());
entity.setOrderNum(domain.getOrderNum());
entity.setLeader(domain.getLeader());
entity.setPhone(domain.getPhone());
entity.setEmail(domain.getEmail());
entity.setStatus(domain.getStatus());
entity.setCreateBy(domain.getCreateBy());
entity.setUpdateBy(domain.getUpdateBy());
entity.setCreatedAt(domain.getCreatedAt());
entity.setUpdatedAt(domain.getUpdatedAt());
entity.setDeletedAt(domain.getDeletedAt());
return entity;
}
public List<SysDept> toDomainList(List<SysDeptEntity> entities) {
if (entities == null) {
return null;
}
return entities.stream().map(this::toDomain).collect(Collectors.toList());
}
}
@@ -0,0 +1,22 @@
package cn.novalon.manage.db.dao;
import cn.novalon.manage.db.entity.SysDeptEntity;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository
public interface SysDeptDao extends R2dbcRepository<SysDeptEntity, Long> {
Flux<SysDeptEntity> findByDeletedAtIsNull(Sort sort);
Flux<SysDeptEntity> findByParentIdAndDeletedAtIsNull(Long parentId, Sort sort);
Mono<SysDeptEntity> findByIdAndDeletedAtIsNull(Long id);
Mono<Long> countByParentIdAndDeletedAtIsNull(Long parentId);
Mono<Void> deleteByIdAndDeletedAtIsNull(Long id);
}
@@ -0,0 +1,77 @@
package cn.novalon.manage.db.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Table("sys_dept")
public class SysDeptEntity {
@Id
private Long id;
@Column("parent_id")
private Long parentId;
@Column("dept_name")
private String deptName;
@Column("order_num")
private Integer orderNum;
@Column("leader")
private String leader;
@Column("phone")
private String phone;
@Column("email")
private String email;
@Column("status")
private Integer status;
@Column("create_by")
private String createBy;
@Column("update_by")
private String updateBy;
@Column("created_at")
private LocalDateTime createdAt;
@Column("updated_at")
private LocalDateTime updatedAt;
@Column("deleted_at")
private LocalDateTime deletedAt;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getParentId() { return parentId; }
public void setParentId(Long parentId) { this.parentId = parentId; }
public String getDeptName() { return deptName; }
public void setDeptName(String deptName) { this.deptName = deptName; }
public Integer getOrderNum() { return orderNum; }
public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; }
public String getLeader() { return leader; }
public void setLeader(String leader) { this.leader = leader; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getStatus() { return status; }
public void setStatus(Integer status) { this.status = status; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
public LocalDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
public LocalDateTime getDeletedAt() { return deletedAt; }
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
}
@@ -0,0 +1,58 @@
package cn.novalon.manage.db.repository;
import cn.novalon.manage.sys.core.domain.SysDept;
import cn.novalon.manage.sys.core.repository.ISysDeptRepository;
import cn.novalon.manage.db.converter.SysDeptConverter;
import cn.novalon.manage.db.dao.SysDeptDao;
import cn.novalon.manage.db.entity.SysDeptEntity;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository
public class SysDeptRepository implements ISysDeptRepository {
private final SysDeptDao sysDeptDao;
private final SysDeptConverter sysDeptConverter;
public SysDeptRepository(SysDeptDao sysDeptDao, SysDeptConverter sysDeptConverter) {
this.sysDeptDao = sysDeptDao;
this.sysDeptConverter = sysDeptConverter;
}
@Override
public Flux<SysDept> findAll() {
return sysDeptDao.findByDeletedAtIsNull(Sort.by(Sort.Direction.ASC, "order_num"))
.map(sysDeptConverter::toDomain);
}
@Override
public Flux<SysDept> findByParentId(Long parentId) {
return sysDeptDao.findByParentIdAndDeletedAtIsNull(parentId, Sort.by(Sort.Direction.ASC, "order_num"))
.map(sysDeptConverter::toDomain);
}
@Override
public Mono<SysDept> findById(Long id) {
return sysDeptDao.findByIdAndDeletedAtIsNull(id)
.map(sysDeptConverter::toDomain);
}
@Override
public Mono<Long> countByParentId(Long parentId) {
return sysDeptDao.countByParentIdAndDeletedAtIsNull(parentId);
}
@Override
public Mono<SysDept> save(SysDept dept) {
SysDeptEntity entity = sysDeptConverter.toEntity(dept);
return sysDeptDao.save(entity)
.map(sysDeptConverter::toDomain);
}
@Override
public Mono<Void> deleteById(Long id) {
return sysDeptDao.deleteByIdAndDeletedAtIsNull(id);
}
}
@@ -0,0 +1,18 @@
CREATE TABLE IF NOT EXISTS sys_dept (
id BIGSERIAL PRIMARY KEY,
parent_id BIGINT DEFAULT 0,
dept_name VARCHAR(100) NOT NULL,
order_num INTEGER DEFAULT 0,
leader VARCHAR(50),
phone VARCHAR(20),
email VARCHAR(100),
status INTEGER DEFAULT 1,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_sys_dept_parent_id ON sys_dept(parent_id);
CREATE INDEX IF NOT EXISTS idx_sys_dept_status ON sys_dept(status);
@@ -0,0 +1,47 @@
package cn.novalon.manage.sys.core.domain;
import java.time.LocalDateTime;
public class SysDept {
private Long id;
private Long parentId;
private String deptName;
private Integer orderNum;
private String leader;
private String phone;
private String email;
private Integer status;
private String createBy;
private String updateBy;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime deletedAt;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getParentId() { return parentId; }
public void setParentId(Long parentId) { this.parentId = parentId; }
public String getDeptName() { return deptName; }
public void setDeptName(String deptName) { this.deptName = deptName; }
public Integer getOrderNum() { return orderNum; }
public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; }
public String getLeader() { return leader; }
public void setLeader(String leader) { this.leader = leader; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getStatus() { return status; }
public void setStatus(Integer status) { this.status = status; }
public String getCreateBy() { return createBy; }
public void setCreateBy(String createBy) { this.createBy = createBy; }
public String getUpdateBy() { return updateBy; }
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
public LocalDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
public LocalDateTime getDeletedAt() { return deletedAt; }
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
}
@@ -0,0 +1,20 @@
package cn.novalon.manage.sys.core.repository;
import cn.novalon.manage.sys.core.domain.SysDept;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface ISysDeptRepository {
Flux<SysDept> findAll();
Flux<SysDept> findByParentId(Long parentId);
Mono<SysDept> findById(Long id);
Mono<Long> countByParentId(Long parentId);
Mono<SysDept> save(SysDept dept);
Mono<Void> deleteById(Long id);
}