package cn.iocoder.yudao.module.archive.service.category; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.archive.controller.admin.category.vo.ArchiveCategoryListReqVO; import cn.iocoder.yudao.module.archive.controller.admin.category.vo.ArchiveCategorySaveReqVO; import cn.iocoder.yudao.module.archive.dal.dataobject.category.ArchiveCategoryDO; import cn.iocoder.yudao.module.archive.dal.mysql.category.ArchiveCategoryMapper; import cn.iocoder.yudao.module.archive.dal.mysql.document.ArchiveDocumentMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.archive.enums.ErrorCodeConstants.*; /** * 档案分类 Service 实现类 * * @author 超级管理员 */ @Service @Validated public class ArchiveCategoryServiceImpl implements ArchiveCategoryService { /** 顶级分类的父分类编号 */ private static final Long ROOT_PARENT_ID = 0L; @Resource private ArchiveCategoryMapper categoryMapper; @Resource private ArchiveDocumentMapper documentMapper; @Override public Long createCategory(ArchiveCategorySaveReqVO createReqVO) { // 1.1 校验父分类存在 validateParentCategory(createReqVO.getParentId(), createReqVO.getName()); // 1.2 校验同级分类名称不重复、分类编码不重复 validateNameUnique(createReqVO.getName(), createReqVO.getParentId(), null); validateCodeUnique(createReqVO.getCode(), null); // 2. 插入(补默认值) ArchiveCategoryDO category = BeanUtils.toBean(createReqVO, ArchiveCategoryDO.class); category.setId(null); if (category.getSort() == null) { category.setSort(0); } if (category.getDefaultSecretLevel() == null) { category.setDefaultSecretLevel(1); } if (category.getStatus() == null) { category.setStatus(0); } categoryMapper.insert(category); return category.getId(); } @Override public void updateCategory(ArchiveCategorySaveReqVO updateReqVO) { // 1.1 校验分类存在 ArchiveCategoryDO oldCategory = validateCategoryExists(updateReqVO.getId()); // 1.2 校验父分类存在,且不能把分类挂到自身或其子孙下(避免形成环) validateParentCategory(updateReqVO.getParentId(), updateReqVO.getName()); validateParentNotSelfOrDescendant(oldCategory, updateReqVO.getParentId()); // 1.3 校验同级名称不重复、编码不重复 validateNameUnique(updateReqVO.getName(), updateReqVO.getParentId(), updateReqVO.getId()); validateCodeUnique(updateReqVO.getCode(), updateReqVO.getId()); // 2. 更新 ArchiveCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ArchiveCategoryDO.class); categoryMapper.updateById(updateObj); } @Override public void deleteCategory(Long id) { // 1.1 校验分类存在 ArchiveCategoryDO category = validateCategoryExists(id); // 1.2 存在子分类时不允许删除 List children = categoryMapper.selectListByParentId(id); if (CollUtil.isNotEmpty(children)) { throw exception(CATEGORY_HAS_CHILDREN, category.getName(), children.size()); } // 1.3 分类下存在档案时不允许删除 Long documentCount = documentMapper.selectCountByCategoryId(id); if (documentCount != null && documentCount > 0) { throw exception(CATEGORY_HAS_DOCUMENT, category.getName(), documentCount); } categoryMapper.deleteById(id); } @Override public ArchiveCategoryDO getCategory(Long id) { return categoryMapper.selectById(id); } @Override public List getCategoryList(ArchiveCategoryListReqVO reqVO) { return categoryMapper.selectList(new LambdaQueryWrapperX() .likeIfPresent(ArchiveCategoryDO::getName, reqVO.getName()) .eqIfPresent(ArchiveCategoryDO::getStatus, reqVO.getStatus()) .orderByAsc(ArchiveCategoryDO::getSort) .orderByAsc(ArchiveCategoryDO::getId)); } @Override public List getCategoryList() { return categoryMapper.selectListOrdered(); } @Override public ArchiveCategoryDO getCategoryByCode(String code) { if (StrUtil.isBlank(code)) { return null; } return categoryMapper.selectByCode(code); } // ==================== 校验逻辑 ==================== /** 校验分类存在,不存在时抛出精确提示 */ private ArchiveCategoryDO validateCategoryExists(Long id) { ArchiveCategoryDO category = id != null ? categoryMapper.selectById(id) : null; if (category == null) { throw exception(CATEGORY_NOT_EXISTS); } return category; } /** 校验父分类:0 表示顶级;非 0 时必须存在 */ private void validateParentCategory(Long parentId, String categoryName) { if (parentId == null) { throw exception(CATEGORY_PARENT_INVALID, categoryName); } if (Objects.equals(parentId, ROOT_PARENT_ID)) { return; } if (categoryMapper.selectById(parentId) == null) { throw exception(CATEGORY_PARENT_INVALID, categoryName); } } /** 校验父分类不能是自身,也不能是自己的子孙分类 */ private void validateParentNotSelfOrDescendant(ArchiveCategoryDO category, Long parentId) { if (Objects.equals(category.getId(), parentId)) { throw exception(CATEGORY_PARENT_INVALID, category.getName()); } Set descendantIds = collectDescendantIds(category.getId()); if (descendantIds.contains(parentId)) { throw exception(CATEGORY_PARENT_INVALID, category.getName()); } } /** 收集分类的全部子孙分类编号(含自身) */ private Set collectDescendantIds(Long id) { List all = categoryMapper.selectListOrdered(); Set result = new HashSet<>(); result.add(id); boolean changed = true; while (changed) { changed = false; for (ArchiveCategoryDO category : all) { if (result.contains(category.getParentId()) && result.add(category.getId())) { changed = true; } } } return result; } private void validateNameUnique(String name, Long parentId, Long excludeId) { Long count = categoryMapper.selectCountByName(name, parentId, excludeId); if (count != null && count > 0) { throw exception(CATEGORY_NAME_DUPLICATE, name); } } private void validateCodeUnique(String code, Long excludeId) { Long count = categoryMapper.selectCountByCode(code, excludeId); if (count != null && count > 0) { ArchiveCategoryDO exists = categoryMapper.selectByCode(code); throw exception(CATEGORY_CODE_DUPLICATE, code, exists != null ? exists.getName() : code); } } }