diff --git a/manager/src/main/java/org/jiayunet/controller/JobCategoryController.java b/manager/src/main/java/org/jiayunet/controller/JobCategoryController.java index 4002590..3624751 100644 --- a/manager/src/main/java/org/jiayunet/controller/JobCategoryController.java +++ b/manager/src/main/java/org/jiayunet/controller/JobCategoryController.java @@ -21,36 +21,40 @@ public class JobCategoryController { /** * 获取全部岗位分类树(一级-二级-三级嵌套) + * @param includeEmpty 是否包含空分类(无岗位关联),默认false(滤空) */ @GetMapping("/tree") - public List getCategoryTree() { - return categoryService.getCategoryTree(); + public List getCategoryTree(@RequestParam(required = false) Boolean includeEmpty) { + return categoryService.getCategoryTree(includeEmpty); } /** * 按父级查询岗位分类列表 * @param parentId 父级ID,不传=查一级 + * @param includeEmpty 是否包含空分类(无岗位关联),默认false(滤空) */ @GetMapping - public List getCategoriesByParent(@RequestParam(required = false) Long parentId) { - return categoryService.getCategoriesByParent(parentId); + public List getCategoriesByParent(@RequestParam(required = false) Long parentId, @RequestParam(required = false) Boolean includeEmpty) { + return categoryService.getCategoriesByParent(parentId, includeEmpty); } /** * 模糊搜索岗位分类 * @param keyword 分类名关键字 + * @param includeEmpty 是否包含空分类(无岗位关联),默认false(滤空) */ @GetMapping("/search") - public List searchCategories(@RequestParam String keyword) { - return categoryService.searchCategories(keyword); + public List searchCategories(@RequestParam String keyword, @RequestParam(required = false) Boolean includeEmpty) { + return categoryService.searchCategories(keyword, includeEmpty); } /** * 批量查询岗位分类 * @param ids 分类ID列表 + * @param includeEmpty 是否包含空分类(无岗位关联),默认false(滤空) */ @PostMapping("/batch") - public List getCategoriesByIds(@RequestBody List ids) { - return categoryService.getCategoriesByIds(ids); + public List getCategoriesByIds(@RequestBody List ids, @RequestParam(required = false) Boolean includeEmpty) { + return categoryService.getCategoriesByIds(ids, includeEmpty); } } diff --git a/manager/src/main/java/org/jiayunet/service/JobCategoryService.java b/manager/src/main/java/org/jiayunet/service/JobCategoryService.java index 2bfe6e1..231c2b9 100644 --- a/manager/src/main/java/org/jiayunet/service/JobCategoryService.java +++ b/manager/src/main/java/org/jiayunet/service/JobCategoryService.java @@ -3,22 +3,22 @@ package org.jiayunet.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.jiayunet.mapper.JobCategoryMapper; +import org.jiayunet.mapper.JobMapper; +import org.jiayunet.pojo.po.Job; import org.jiayunet.pojo.po.JobCategory; import org.jiayunet.pojo.vo.JobCategoryTreeVo; import org.jiayunet.pojo.vo.JobCategoryVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** * 岗位分类服务 - *

主要功能:岗位分类数据查询(树形、层级、搜索)

- *

依赖:无

- *

使用表:bg_job_category

+ *

主要功能:岗位分类数据查询(树形、层级、搜索),支持滤空(过滤无岗位关联的分类)

+ *

依赖:JobMapper(查询有岗位关联的分类ID)

+ *

使用表:bg_job_category、bg_job

* * @author zk */ @@ -28,68 +28,68 @@ public class JobCategoryService { @Autowired private JobCategoryMapper categoryMapper; + @Autowired + private JobMapper jobMapper; + /** - * 获取全部岗位分类树(一级-二级-三级嵌套) - *

1. 查询全部分类 2. 按level分组 3. 构建三层树

+ * 获取全部岗位分类树(递归构建,支持任意层级) + *

1. 查询全部分类 2. 滤空(可选) 3. 按parentId分组递归构建树

*/ - public List getCategoryTree() { + public List getCategoryTree(Boolean includeEmpty) { List allCategories = categoryMapper.selectList(null); - List level1 = allCategories.stream().filter(c -> c.getLevel() == 1).collect(Collectors.toList()); - Map> level2ByParent = allCategories.stream().filter(c -> c.getLevel() == 2).collect(Collectors.groupingBy(JobCategory::getParentId)); - Map> level3ByParent = allCategories.stream().filter(c -> c.getLevel() == 3).collect(Collectors.groupingBy(JobCategory::getParentId)); - return level1.stream().map(cat1 -> { - JobCategoryTreeVo vo1 = new JobCategoryTreeVo(); - vo1.setId(cat1.getId()); - vo1.setName(cat1.getName()); - vo1.setLevel(cat1.getLevel()); - List level2List = level2ByParent.getOrDefault(cat1.getId(), new ArrayList<>()); - vo1.setChildren(level2List.stream().map(cat2 -> { - JobCategoryTreeVo vo2 = new JobCategoryTreeVo(); - vo2.setId(cat2.getId()); - vo2.setName(cat2.getName()); - vo2.setLevel(cat2.getLevel()); - List level3List = level3ByParent.getOrDefault(cat2.getId(), new ArrayList<>()); - vo2.setChildren(level3List.stream().map(cat3 -> { - JobCategoryTreeVo vo3 = new JobCategoryTreeVo(); - vo3.setId(cat3.getId()); - vo3.setName(cat3.getName()); - vo3.setLevel(cat3.getLevel()); - vo3.setChildren(null); - return vo3; - }).collect(Collectors.toList())); - return vo2; - }).collect(Collectors.toList())); - return vo1; - }).collect(Collectors.toList()); + if (!Boolean.TRUE.equals(includeEmpty)) { + Set activeIds = getActiveCategoryIds(allCategories); + allCategories = allCategories.stream().filter(c -> activeIds.contains(c.getId())).toList(); + } + Map> childrenMap = allCategories.stream().collect(Collectors.groupingBy(JobCategory::getParentId)); + return buildChildren(0L, childrenMap); } /** * 按父级查询岗位分类列表 - *

parentId为null查一级,否则查下一级

+ *

parentId为null查一级,否则查下一级;默认滤空

*/ - public List getCategoriesByParent(Long parentId) { + public List getCategoriesByParent(Long parentId, Boolean includeEmpty) { List categories; if (parentId == null) { categories = categoryMapper.selectList(new LambdaQueryWrapper().eq(JobCategory::getLevel, 1)); } else { categories = categoryMapper.selectList(new LambdaQueryWrapper().eq(JobCategory::getParentId, parentId)); } - return categories.stream().map(c -> { - JobCategoryVo vo = new JobCategoryVo(); - vo.setId(c.getId()); - vo.setName(c.getName()); - vo.setLevel(c.getLevel()); - vo.setParentId(c.getParentId()); - return vo; - }).collect(Collectors.toList()); + return filterAndConvert(categories, includeEmpty); } /** * 模糊搜索岗位分类 - *

按分类名关键字模糊查询

+ *

按分类名关键字模糊查询,默认滤空

*/ - public List searchCategories(String keyword) { + public List searchCategories(String keyword, Boolean includeEmpty) { List categories = categoryMapper.selectList(new LambdaQueryWrapper().like(JobCategory::getName, keyword)); + return filterAndConvert(categories, includeEmpty); + } + + /** + * 批量查询岗位分类 + *

根据ID列表批量查询分类详情,默认滤空

+ */ + public List getCategoriesByIds(List ids, Boolean includeEmpty) { + if (ids == null || ids.isEmpty()) { + return new ArrayList<>(); + } + List categories = categoryMapper.selectList(new LambdaQueryWrapper().in(JobCategory::getId, ids)); + return filterAndConvert(categories, includeEmpty); + } + + // ==================== 私有方法 ==================== + + /** + * 滤空 + 转VO + */ + private List filterAndConvert(List categories, Boolean includeEmpty) { + if (!Boolean.TRUE.equals(includeEmpty)) { + Set activeIds = getActiveCategoryIds(null); + categories = categories.stream().filter(c -> activeIds.contains(c.getId())).toList(); + } return categories.stream().map(c -> { JobCategoryVo vo = new JobCategoryVo(); vo.setId(c.getId()); @@ -101,20 +101,47 @@ public class JobCategoryService { } /** - * 批量查询岗位分类 - *

根据ID列表批量查询分类详情

+ * 获取有岗位关联的有效分类ID集合(含祖先链路) + *

1. 查询bg_job中有效岗位的distinct categoryId

+ *

2. 从末级ID沿parentId向上追溯,构建完整有效ID集合

+ * + * @param allCategories 全量分类数据,传null则内部查询 */ - public List getCategoriesByIds(List ids) { - if (ids == null || ids.isEmpty()) { - return new ArrayList<>(); + private Set getActiveCategoryIds(List allCategories) { + // 1. 查询有岗位关联的末级分类ID + List jobs = jobMapper.selectList(new LambdaQueryWrapper().select(Job::getCategoryId).eq(Job::getStatus, 0).groupBy(Job::getCategoryId)); + Set leafActiveIds = jobs.stream().map(Job::getCategoryId).filter(Objects::nonNull).collect(Collectors.toSet()); + + // 2. 查全量分类,构建id->parentId映射 + if (allCategories == null) { + allCategories = categoryMapper.selectList(null); } - List categories = categoryMapper.selectList(new LambdaQueryWrapper().in(JobCategory::getId, ids)); - return categories.stream().map(c -> { - JobCategoryVo vo = new JobCategoryVo(); + Map parentMap = allCategories.stream().collect(Collectors.toMap(JobCategory::getId, JobCategory::getParentId)); + + // 3. 从末级向上追溯,收集所有有效ID(含祖先) + Set activeIds = new HashSet<>(); + for (Long id : leafActiveIds) { + Long current = id; + while (current != null && current != 0L && !activeIds.contains(current)) { + activeIds.add(current); + current = parentMap.get(current); + } + } + return activeIds; + } + + /** + * 递归构建子树 + */ + private List buildChildren(Long parentId, Map> childrenMap) { + List children = childrenMap.getOrDefault(parentId, Collections.emptyList()); + return children.stream().map(c -> { + JobCategoryTreeVo vo = new JobCategoryTreeVo(); vo.setId(c.getId()); vo.setName(c.getName()); vo.setLevel(c.getLevel()); - vo.setParentId(c.getParentId()); + List subChildren = buildChildren(c.getId(), childrenMap); + vo.setChildren(subChildren.isEmpty() ? null : subChildren); return vo; }).collect(Collectors.toList()); }