mirror of https://github.com/halo-dev/halo
Support querying sub-categories of any level (#2995)
What type of PR is this? /kind feature /kind api-change What this PR does / why we need it: 添加一个方法可以根据分类树的任意一层级的名称查询子树 Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2960 Special notes for your reviewer: None Does this PR introduce a user-facing change? ```release-note CategoryFinder 添加根据分类查询子分类树结构的方法 ```pull/3031/head
parent
77da761a13
commit
a7da2c0d76
|
@ -26,4 +26,6 @@ public interface CategoryFinder {
|
||||||
Flux<CategoryVo> listAll();
|
Flux<CategoryVo> listAll();
|
||||||
|
|
||||||
Flux<CategoryTreeVo> listAsTree();
|
Flux<CategoryTreeVo> listAsTree();
|
||||||
|
|
||||||
|
Flux<CategoryTreeVo> listAsTree(String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.core.extension.content.Category;
|
import run.halo.app.core.extension.content.Category;
|
||||||
|
@ -72,6 +73,15 @@ public class CategoryFinderImpl implements CategoryFinder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Flux<CategoryTreeVo> listAsTree() {
|
public Flux<CategoryTreeVo> listAsTree() {
|
||||||
|
return this.toCategoryTreeVoFlux(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flux<CategoryTreeVo> listAsTree(String name) {
|
||||||
|
return this.toCategoryTreeVoFlux(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Flux<CategoryTreeVo> toCategoryTreeVoFlux(String name) {
|
||||||
return listAll()
|
return listAll()
|
||||||
.collectList()
|
.collectList()
|
||||||
.flatMapIterable(categoryVos -> {
|
.flatMapIterable(categoryVos -> {
|
||||||
|
@ -80,7 +90,7 @@ public class CategoryFinderImpl implements CategoryFinder {
|
||||||
.collect(Collectors.toMap(categoryVo -> categoryVo.getMetadata().getName(),
|
.collect(Collectors.toMap(categoryVo -> categoryVo.getMetadata().getName(),
|
||||||
Function.identity()));
|
Function.identity()));
|
||||||
|
|
||||||
nameIdentityMap.forEach((name, value) -> {
|
nameIdentityMap.forEach((nameKey, value) -> {
|
||||||
List<String> children = value.getSpec().getChildren();
|
List<String> children = value.getSpec().getChildren();
|
||||||
if (children == null) {
|
if (children == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -88,15 +98,15 @@ public class CategoryFinderImpl implements CategoryFinder {
|
||||||
for (String child : children) {
|
for (String child : children) {
|
||||||
CategoryTreeVo childNode = nameIdentityMap.get(child);
|
CategoryTreeVo childNode = nameIdentityMap.get(child);
|
||||||
if (childNode != null) {
|
if (childNode != null) {
|
||||||
childNode.setParentName(name);
|
childNode.setParentName(nameKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return listToTree(nameIdentityMap.values());
|
return listToTree(nameIdentityMap.values(), name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<CategoryTreeVo> listToTree(Collection<CategoryTreeVo> list) {
|
static List<CategoryTreeVo> listToTree(Collection<CategoryTreeVo> list, String name) {
|
||||||
Map<String, List<CategoryTreeVo>> parentNameIdentityMap = list.stream()
|
Map<String, List<CategoryTreeVo>> parentNameIdentityMap = list.stream()
|
||||||
.filter(categoryTreeVo -> categoryTreeVo.getParentName() != null)
|
.filter(categoryTreeVo -> categoryTreeVo.getParentName() != null)
|
||||||
.collect(Collectors.groupingBy(CategoryTreeVo::getParentName));
|
.collect(Collectors.groupingBy(CategoryTreeVo::getParentName));
|
||||||
|
@ -111,7 +121,8 @@ public class CategoryFinderImpl implements CategoryFinder {
|
||||||
node.setChildren(children);
|
node.setChildren(children);
|
||||||
});
|
});
|
||||||
return list.stream()
|
return list.stream()
|
||||||
.filter(v -> v.getParentName() == null)
|
.filter(v -> StringUtils.isEmpty(name) ? v.getParentName() == null
|
||||||
|
: StringUtils.equals(v.getMetadata().getName(), name))
|
||||||
.sorted(defaultTreeNodeComparator())
|
.sorted(defaultTreeNodeComparator())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,17 @@ class CategoryFinderImplTest {
|
||||||
assertThat(treeVos).hasSize(1);
|
assertThat(treeVos).hasSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listSubTreeByName() {
|
||||||
|
when(client.list(eq(Category.class), eq(null), any()))
|
||||||
|
.thenReturn(Flux.fromIterable(categoriesForTree()));
|
||||||
|
List<CategoryTreeVo> treeVos = categoryFinder.listAsTree("E").collectList().block();
|
||||||
|
assertThat(treeVos.get(0).getMetadata().getName()).isEqualTo("E");
|
||||||
|
assertThat(treeVos.get(0).getChildren()).hasSize(2);
|
||||||
|
assertThat(treeVos.get(0).getChildren().get(0).getMetadata().getName()).isEqualTo("A");
|
||||||
|
assertThat(treeVos.get(0).getChildren().get(1).getMetadata().getName()).isEqualTo("C");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link CategoryFinderImpl#listAsTree()}.
|
* Test for {@link CategoryFinderImpl#listAsTree()}.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue