增加服务端执法人员管理相关类
This commit is contained in:
parent
58658e2199
commit
b847648ea5
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.aisino.iles.lawenforcement.controller;
|
||||||
|
|
||||||
|
import com.aisino.iles.common.model.Fail;
|
||||||
|
import com.aisino.iles.common.model.Ok;
|
||||||
|
import com.aisino.iles.common.model.PageResult;
|
||||||
|
import com.aisino.iles.common.model.Result;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Agency;
|
||||||
|
import com.aisino.iles.lawenforcement.model.query.AgencyQuery;
|
||||||
|
import com.aisino.iles.lawenforcement.service.AgencyService;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 综合执法/执法机构管理
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/lawenforcement/agencies")
|
||||||
|
public class AgencyController {
|
||||||
|
|
||||||
|
private final AgencyService agencyService;
|
||||||
|
|
||||||
|
public AgencyController(AgencyService agencyService) {
|
||||||
|
this.agencyService = agencyService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建执法机构
|
||||||
|
*
|
||||||
|
* @param agency 执法机构信息
|
||||||
|
* @return 创建结果
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public Result<Agency> createAgency(@RequestBody Agency agency) {
|
||||||
|
return Ok.of(agencyService.saveAgency(agency));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询执法机构
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/{agencyId}")
|
||||||
|
public Result<Agency> getAgencyById(@PathVariable String agencyId) {
|
||||||
|
return agencyService.findAgencyById(agencyId)
|
||||||
|
.map(a->((Result<Agency>) Ok.of(a)))
|
||||||
|
.orElse(Fail.of("执法机构不存在"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据执法机构代码查询执法机构
|
||||||
|
*
|
||||||
|
* @param agencyCode 执法机构代码
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/code/{agencyCode}")
|
||||||
|
public Result<Agency> getAgencyByCode(@PathVariable String agencyCode) {
|
||||||
|
return agencyService.findAgencyByAgencyCode(agencyCode)
|
||||||
|
.map(a->((Result<Agency>) Ok.of(a)))
|
||||||
|
.orElse(Fail.of("执法机构不存在"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询执法机构
|
||||||
|
*
|
||||||
|
* @return 分页执法机构信息
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
public PageResult<Agency> getAgenciesPage(AgencyQuery agencyQuery) {
|
||||||
|
return PageResult.of(agencyService.findAgenciesPage(agencyQuery));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新执法机构
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
* @param agency 执法机构信息
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
|
@PutMapping("/{agencyId}")
|
||||||
|
public Result<Agency> updateAgency(@PathVariable String agencyId, @RequestBody Agency agency) {
|
||||||
|
if (!agencyService.existsAgencyById(agencyId)) {
|
||||||
|
return Fail.of("执法机构不存在");
|
||||||
|
}
|
||||||
|
agency.setAgencyId(agencyId);
|
||||||
|
return Ok.of(agencyService.saveAgency(agency));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除执法机构
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{agencyId}")
|
||||||
|
public Result<Void> deleteAgencyById(@PathVariable String agencyId) {
|
||||||
|
if (!agencyService.existsAgencyById(agencyId)) {
|
||||||
|
return Fail.of("执法机构不存在");
|
||||||
|
}
|
||||||
|
agencyService.deleteAgencyById(agencyId);
|
||||||
|
return Ok.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除执法机构
|
||||||
|
*
|
||||||
|
* @param agencyIds 执法机构ID列表
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping
|
||||||
|
public Result<Void> deleteAgenciesByIds(@RequestBody List<String> agencyIds) {
|
||||||
|
agencyService.deleteAgenciesByIds(agencyIds);
|
||||||
|
return Ok.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询执法机构列表
|
||||||
|
*
|
||||||
|
* @return 执法机构列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Result<List<Agency>> getAgencies(AgencyQuery query) {
|
||||||
|
return Ok.of(agencyService.findAgencies(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询执法机构列表(树形)
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 执法机构列表(树形)
|
||||||
|
*/
|
||||||
|
@GetMapping("/tree")
|
||||||
|
public Result<List<Agency>> getAgenciesTree(AgencyQuery query) {
|
||||||
|
return Ok.of(agencyService.findAgenciesTree(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定父机构下的下一个排序号
|
||||||
|
* @param parentId 上级机构ID,根节点传 0 或不传
|
||||||
|
*/
|
||||||
|
@GetMapping("/nextOrderNum")
|
||||||
|
public Result<Integer> getNextOrderNum(@RequestParam(required = false) String parentId) {
|
||||||
|
return Ok.of(agencyService.getNextOrderNum(parentId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.aisino.iles.lawenforcement.repository;
|
||||||
|
|
||||||
|
import com.aisino.iles.core.repository.BaseRepo;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Agency;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执法机构仓库接口
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface AgencyRepository extends BaseRepo<Agency, String> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据执法机构代码查询执法机构
|
||||||
|
*
|
||||||
|
* @param agencyCode 执法机构代码
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
Optional<Agency> findByAgencyCode(String agencyCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据执法机构名称查询执法机构
|
||||||
|
*
|
||||||
|
* @param agencyName 执法机构名称
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
Optional<Agency> findByAgencyName(String agencyName);
|
||||||
|
|
||||||
|
List<Agency> findByAgencyId(String parentId);
|
||||||
|
|
||||||
|
List<Agency> findByParentIsNull();
|
||||||
|
|
||||||
|
List<Agency> findByParentAgencyId(String agencyId);
|
||||||
|
|
||||||
|
@Query("select a from Agency a where a.agencyCode like :agencyCode and a.agencyLevel = :agencyLevel")
|
||||||
|
List<Agency> findLikeAgencyCode(String agencyCode, Integer agencyLevel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定父机构下的最大排序号
|
||||||
|
*/
|
||||||
|
@Query("select coalesce(max(a.orderNum),0) from Agency a where a.parent.agencyId = :parentId")
|
||||||
|
Integer findMaxOrderNumByParentId(@Param("parentId") String parentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询根节点(父为空)下的最大排序号
|
||||||
|
*/
|
||||||
|
@Query("select coalesce(max(a.orderNum),0) from Agency a where a.parent is null")
|
||||||
|
Integer findMaxOrderNumOfRoot();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,425 @@
|
||||||
|
package com.aisino.iles.lawenforcement.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.aisino.iles.common.util.BeanUtils;
|
||||||
|
import com.aisino.iles.common.util.PageableHelper;
|
||||||
|
import com.aisino.iles.common.util.StringUtils;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Agency;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Agency_;
|
||||||
|
import com.aisino.iles.lawenforcement.model.query.AgencyQuery;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.AgencyRepository;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.CaseRepository;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.OfficerRepository;
|
||||||
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执法机构服务类
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public class AgencyService {
|
||||||
|
|
||||||
|
private final AgencyRepository agencyRepository;
|
||||||
|
private final OfficerRepository officerRepository;
|
||||||
|
private final CaseRepository caseRepository;
|
||||||
|
|
||||||
|
public AgencyService(AgencyRepository agencyRepository, OfficerRepository officerRepository, CaseRepository caseRepository) {
|
||||||
|
this.agencyRepository = agencyRepository;
|
||||||
|
this.officerRepository = officerRepository;
|
||||||
|
this.caseRepository = caseRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存执法机构信息
|
||||||
|
*
|
||||||
|
* @param agency 执法机构信息
|
||||||
|
* @return 保存后的执法机构信息
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Agency saveAgency(Agency agency) {
|
||||||
|
// 基础校验与去空格
|
||||||
|
String name = StrUtil.trimToNull(agency.getAgencyName());
|
||||||
|
String code = StrUtil.trimToNull(agency.getAgencyCode());
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(name)) {
|
||||||
|
throw new IllegalArgumentException("机构名称不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(code)) {
|
||||||
|
throw new IllegalArgumentException("机构代码不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
agency.setAgencyName(name);
|
||||||
|
agency.setAgencyCode(code);
|
||||||
|
|
||||||
|
// 生成机构简码(去偶数0),若前端未传
|
||||||
|
if (StrUtil.isBlank(agency.getAgencySimpleCode())) {
|
||||||
|
agency.setAgencySimpleCode(StringUtils.trimEven0(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isCreate = StrUtil.isBlank(agency.getAgencyId());
|
||||||
|
|
||||||
|
// 唯一性校验:名称 & 代码
|
||||||
|
agencyRepository.findByAgencyName(agency.getAgencyName())
|
||||||
|
.filter(existing -> isCreate || !existing.getAgencyId().equals(agency.getAgencyId()))
|
||||||
|
.ifPresent(e -> {
|
||||||
|
throw new IllegalStateException("机构名称已存在");
|
||||||
|
});
|
||||||
|
agencyRepository.findByAgencyCode(agency.getAgencyCode())
|
||||||
|
.filter(existing -> isCreate || !existing.getAgencyId().equals(agency.getAgencyId()))
|
||||||
|
.ifPresent(e -> {
|
||||||
|
throw new IllegalStateException("机构代码已存在");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解析上级机构(支持仅携带 agencyId 的 parent 对象,或使用 transient 的 parentAgencyId)
|
||||||
|
Agency parent = null;
|
||||||
|
String parentAgencyId = agency.getParent() != null ? agency.getParent().getAgencyId() : null;
|
||||||
|
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(parentAgencyId)) {
|
||||||
|
parent = agencyRepository.findById(parentAgencyId)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("上级机构不存在"));
|
||||||
|
agency.setParent(parent);
|
||||||
|
} else {
|
||||||
|
agency.setParent(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCreate) {
|
||||||
|
// 新增流程
|
||||||
|
agency.setLeaf(true);
|
||||||
|
agency.setAgencyLevel(parent == null ? 1 : (Optional.ofNullable(parent.getAgencyLevel()).orElse(0) + 1));
|
||||||
|
|
||||||
|
Agency saved = agencyRepository.save(agency);
|
||||||
|
|
||||||
|
// 计算并设置机构路径(沿父链使用机构简码拼接)
|
||||||
|
saved.setAgencyPath(computeAgencyPath(saved));
|
||||||
|
|
||||||
|
// 更新父节点 leaf 状态
|
||||||
|
if (parent != null && Boolean.TRUE.equals(parent.getLeaf())) {
|
||||||
|
parent.setLeaf(false);
|
||||||
|
agencyRepository.save(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return agencyRepository.save(saved);
|
||||||
|
} else {
|
||||||
|
// 修改流程
|
||||||
|
Agency existing = agencyRepository.findById(agency.getAgencyId())
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("执法机构不存在"));
|
||||||
|
|
||||||
|
Agency oldParent = existing.getParent();
|
||||||
|
Agency newParent = parent; // 可能为 null
|
||||||
|
|
||||||
|
boolean parentChanged = (oldParent == null && newParent != null)
|
||||||
|
|| (oldParent != null && (newParent == null || !oldParent.getAgencyId().equals(newParent.getAgencyId())));
|
||||||
|
|
||||||
|
// 防止循环:新父节点不能在当前节点的子树中
|
||||||
|
if (parentChanged && newParent != null && isDescendant(newParent, existing.getAgencyId())) {
|
||||||
|
throw new IllegalStateException("不允许将机构设置为自己的子机构");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用基础字段更新
|
||||||
|
existing.setAgencyName(agency.getAgencyName());
|
||||||
|
existing.setAgencyCode(agency.getAgencyCode());
|
||||||
|
existing.setAgencySimpleCode(agency.getAgencySimpleCode());
|
||||||
|
existing.setOrderNum(agency.getOrderNum());
|
||||||
|
existing.setParent(newParent);
|
||||||
|
|
||||||
|
// 重新计算当前节点 level 和 path
|
||||||
|
existing.setAgencyLevel(newParent == null ? 1 : (Optional.ofNullable(newParent.getAgencyLevel()).orElse(0) + 1));
|
||||||
|
existing.setAgencyPath(computeAgencyPath(existing));
|
||||||
|
|
||||||
|
Agency saved = agencyRepository.save(existing);
|
||||||
|
|
||||||
|
// 递归更新所有子节点 level 和 path
|
||||||
|
updateChildrenLevelsAndPaths(saved);
|
||||||
|
|
||||||
|
// 维护父节点 leaf 状态
|
||||||
|
if (oldParent != null) {
|
||||||
|
boolean hasOtherChildren = !agencyRepository.findByParentAgencyId(oldParent.getAgencyId()).isEmpty();
|
||||||
|
if (!hasOtherChildren) {
|
||||||
|
oldParent.setLeaf(true);
|
||||||
|
agencyRepository.save(oldParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newParent != null) {
|
||||||
|
newParent.setLeaf(false);
|
||||||
|
agencyRepository.save(newParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 维护当前节点 leaf 状态
|
||||||
|
boolean hasChildren = !agencyRepository.findByParentAgencyId(saved.getAgencyId()).isEmpty();
|
||||||
|
saved.setLeaf(!hasChildren);
|
||||||
|
return agencyRepository.save(saved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencies 执法机构信息列表
|
||||||
|
* @return 保存后的执法机构信息列表
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public List<Agency> saveAgencies(List<Agency> agencies) {
|
||||||
|
return agencyRepository.saveAll(agencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
public Optional<Agency> findAgencyById(String agencyId) {
|
||||||
|
return agencyRepository.findById(agencyId).map(a -> {
|
||||||
|
Agency agency = new Agency();
|
||||||
|
BeanUtils.copyProperties(a, agency, Agency_.PARENT, Agency_.CHILDREN);
|
||||||
|
Agency parent = new Agency();
|
||||||
|
BeanUtils.copyProperties(a.getParent(), parent, Agency_.PARENT, Agency_.CHILDREN);
|
||||||
|
agency.setParent(parent);
|
||||||
|
return agency;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据执法机构代码查询执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencyCode 执法机构代码
|
||||||
|
* @return 执法机构信息
|
||||||
|
*/
|
||||||
|
public Optional<Agency> findAgencyByAgencyCode(String agencyCode) {
|
||||||
|
return agencyRepository.findByAgencyCode(agencyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询执法机构信息
|
||||||
|
*
|
||||||
|
* @param query 分页请求
|
||||||
|
* @return 分页执法机构信息
|
||||||
|
*/
|
||||||
|
public Page<Agency> findAgenciesPage(AgencyQuery query) {
|
||||||
|
return agencyRepository.findAll(buildSpec(query), PageableHelper.buildPageRequest(query.page(), query.pageSize(), query.sort(), query.dir()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Specification<Agency> buildSpec(AgencyQuery agencyQuery) {
|
||||||
|
return (root, query, builder) -> {
|
||||||
|
List<Predicate> predicates = Stream.of(
|
||||||
|
Optional.ofNullable(agencyQuery.getAgencyId())
|
||||||
|
.map(StrUtil::trimToNull)
|
||||||
|
.map(a -> builder.equal(root.get(Agency_.agencyId), a)),
|
||||||
|
Optional.ofNullable(agencyQuery.getAgencyCode())
|
||||||
|
.map(StrUtil::trimToNull)
|
||||||
|
.map(a -> builder.equal(root.get(Agency_.agencyCode), a)),
|
||||||
|
Optional.ofNullable(agencyQuery.getAgencyName())
|
||||||
|
.map(StrUtil::trimToNull)
|
||||||
|
.map(a -> builder.like(root.get(Agency_.agencyName), "%" + a + "%")),
|
||||||
|
Optional.ofNullable(agencyQuery.getParentId())
|
||||||
|
.map(StrUtil::trimToNull)
|
||||||
|
.map(p -> builder.equal(root.get(Agency_.parent).get(Agency_.agencyId), p))
|
||||||
|
).filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.toList();
|
||||||
|
return builder.and(predicates.toArray(new Predicate[0]));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 条件查询执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencyQuery@return 执法机构信息列表
|
||||||
|
*/
|
||||||
|
public List<Agency> findAgencies(AgencyQuery agencyQuery) {
|
||||||
|
return agencyRepository.findAll(buildSpec(agencyQuery));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteAgencyById(String agencyId) {
|
||||||
|
Agency agency = agencyRepository.findById(agencyId)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("执法机构不存在"));
|
||||||
|
|
||||||
|
// 1. 有无子机构
|
||||||
|
if (!agencyRepository.findByParentAgencyId(agencyId).isEmpty()) {
|
||||||
|
throw new IllegalStateException("存在子机构,不允许删除");
|
||||||
|
}
|
||||||
|
// 2. 是否有关联执法人员
|
||||||
|
if (!officerRepository.findByAgencyId(agencyId).isEmpty()) {
|
||||||
|
throw new IllegalStateException("存在关联执法人员,不允许删除");
|
||||||
|
}
|
||||||
|
// 3. 是否有关联案件
|
||||||
|
if (caseRepository.existsByAgencyId(agencyId)) {
|
||||||
|
throw new IllegalStateException("存在关联案件,不允许删除");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
agencyRepository.deleteById(agencyId);
|
||||||
|
|
||||||
|
// 更新上级 leaf 状态
|
||||||
|
Agency parent = agency.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
boolean hasOtherChildren = !agencyRepository.findByParentAgencyId(parent.getAgencyId()).isEmpty();
|
||||||
|
if (!hasOtherChildren) {
|
||||||
|
parent.setLeaf(true);
|
||||||
|
agencyRepository.save(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除执法机构信息
|
||||||
|
*
|
||||||
|
* @param agencyIds 执法机构ID列表
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteAgenciesByIds(List<String> agencyIds) {
|
||||||
|
for (String id : agencyIds) {
|
||||||
|
deleteAgencyById(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查执法机构是否存在
|
||||||
|
*
|
||||||
|
* @param agencyId 执法机构ID
|
||||||
|
* @return 是否存在
|
||||||
|
*/
|
||||||
|
public boolean existsAgencyById(String agencyId) {
|
||||||
|
return agencyRepository.existsById(agencyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取执法机构总数
|
||||||
|
*
|
||||||
|
* @return 执法机构总数
|
||||||
|
*/
|
||||||
|
public long countAgencies() {
|
||||||
|
return agencyRepository.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定父机构下的下一个排序号
|
||||||
|
* parentId 为空或等于 "0" 时,表示根节点
|
||||||
|
*/
|
||||||
|
public Integer getNextOrderNum(String parentId) {
|
||||||
|
String pid = StrUtil.trimToNull(parentId);
|
||||||
|
if (pid == null || "0".equals(pid)) {
|
||||||
|
Integer max = Optional.ofNullable(agencyRepository.findMaxOrderNumOfRoot()).orElse(0);
|
||||||
|
return max + 1;
|
||||||
|
}
|
||||||
|
// 校验父节点
|
||||||
|
if (!agencyRepository.existsById(pid)) {
|
||||||
|
throw new IllegalArgumentException("上级机构不存在");
|
||||||
|
}
|
||||||
|
Integer max = Optional.ofNullable(agencyRepository.findMaxOrderNumByParentId(pid)).orElse(0);
|
||||||
|
return max + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Agency> findAgenciesTree(AgencyQuery query) {
|
||||||
|
List<Agency> result = new ArrayList<>();
|
||||||
|
|
||||||
|
List<Agency> rootAgencies;
|
||||||
|
if (StrUtil.isNotBlank(query.getParentId())) {
|
||||||
|
rootAgencies = agencyRepository.findByParentAgencyId(query.getParentId());
|
||||||
|
} else if (StrUtil.isNotBlank(query.getAgencyId())) {
|
||||||
|
rootAgencies = new ArrayList<>();
|
||||||
|
agencyRepository.findById(query.getAgencyId()).ifPresent(rootAgencies::add);
|
||||||
|
} else {
|
||||||
|
// 顶级机构:parent 为空
|
||||||
|
rootAgencies = agencyRepository.findByParentIsNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Agency root : rootAgencies) {
|
||||||
|
populateChildrenRecursively(root, 0, 50);
|
||||||
|
result.add(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归填充子机构
|
||||||
|
*/
|
||||||
|
private void populateChildrenRecursively(Agency parent, int depth, int maxDepth) {
|
||||||
|
if (parent == null || depth > maxDepth) return;
|
||||||
|
List<Agency> children = agencyRepository.findByParentAgencyId(parent.getAgencyId());
|
||||||
|
parent.setChildren(children);
|
||||||
|
if (children == null || children.isEmpty()) {
|
||||||
|
parent.setLeaf(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent.setLeaf(false);
|
||||||
|
for (Agency child : children) {
|
||||||
|
populateChildrenRecursively(child, depth + 1, maxDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归更新所有子节点的 level 和 path
|
||||||
|
*/
|
||||||
|
private void updateChildrenLevelsAndPaths(Agency parent) {
|
||||||
|
List<Agency> children = agencyRepository.findByParentAgencyId(parent.getAgencyId());
|
||||||
|
for (Agency child : children) {
|
||||||
|
child.setAgencyLevel(Optional.ofNullable(parent.getAgencyLevel()).orElse(0) + 1);
|
||||||
|
child.setAgencyPath(computeAgencyPath(child));
|
||||||
|
agencyRepository.save(child);
|
||||||
|
updateChildrenLevelsAndPaths(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算机构路径:沿父链使用机构简码拼接,避免依赖数据库中已保存的路径。
|
||||||
|
*/
|
||||||
|
private String computeAgencyPath(Agency current) {
|
||||||
|
if (current == null) return null;
|
||||||
|
List<String> parts = new ArrayList<>();
|
||||||
|
Agency cursor = current;
|
||||||
|
int depth = 0;
|
||||||
|
final int maxDepth = 100;
|
||||||
|
while (cursor != null && depth < maxDepth) {
|
||||||
|
String part = StrUtil.trimToNull(cursor.getAgencySimpleCode());
|
||||||
|
if (part == null) {
|
||||||
|
part = StringUtils.trimEven0(StrUtil.emptyIfNull(cursor.getAgencyCode()));
|
||||||
|
cursor.setAgencySimpleCode(part);
|
||||||
|
}
|
||||||
|
parts.add(part);
|
||||||
|
cursor = cursor.getParent();
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
Collections.reverse(parts);
|
||||||
|
return String.join(".", parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 candidate 是否在 ancestorId 对应机构的子树中(用于防止循环引用)。
|
||||||
|
*/
|
||||||
|
private boolean isDescendant(Agency candidate, String ancestorId) {
|
||||||
|
Agency cursor = candidate;
|
||||||
|
int depth = 0;
|
||||||
|
final int maxDepth = 100;
|
||||||
|
while (cursor != null && depth < maxDepth) {
|
||||||
|
if (ancestorId.equals(cursor.getAgencyId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cursor = cursor.getParent();
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue