diff --git a/README.md b/README.md index b45822f..3d8b884 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,39 @@ List<[#LinkGroupVo](#linkgroupvo)> ``` +#### listBy(groupNames, limit) + +##### 描述 + +同时获取指定多个分组下的链接,并限制返回的总数量。 + +##### 参数 + +1. `groupNames:List` - 分组 `metadata.name` 列表。传入 `null` 时不限制分组。 +2. `limit:int` - 限制返回的链接数量,`0` 时不限制。 + +##### 返回值 + +List<[#LinkVo](#linkvo)> + +##### 示例 + +```html + + + + + + + + + + + + + +``` + ### 评论适配 主题开发者可以参考 [自定义标签](https://docs.halo.run/developer-guide/theme/template-tag/#halocomment),来为友情链接接入评论功能。 diff --git a/src/main/java/run/halo/links/finders/LinkFinder.java b/src/main/java/run/halo/links/finders/LinkFinder.java index 0dbaceb..dae2d6b 100644 --- a/src/main/java/run/halo/links/finders/LinkFinder.java +++ b/src/main/java/run/halo/links/finders/LinkFinder.java @@ -1,5 +1,6 @@ package run.halo.links.finders; +import java.util.List; import reactor.core.publisher.Flux; import run.halo.links.vo.LinkGroupVo; import run.halo.links.vo.LinkVo; @@ -14,5 +15,17 @@ public interface LinkFinder { Flux listBy(String group); + /** + * Lists links from specified groups with a total limit on the number of + * results. + * + * @param groupNames the list of group names to include, empty or null means all + * groups + * @param limit the maximum total number of links to return, 0 or negative + * means no limit + * @return a flux of link VOs + */ + Flux listBy(List groupNames, int limit); + Flux groupBy(); } diff --git a/src/main/java/run/halo/links/finders/impl/LinkFinderImpl.java b/src/main/java/run/halo/links/finders/impl/LinkFinderImpl.java index cffa5a6..75eb92d 100644 --- a/src/main/java/run/halo/links/finders/impl/LinkFinderImpl.java +++ b/src/main/java/run/halo/links/finders/impl/LinkFinderImpl.java @@ -3,6 +3,7 @@ import static org.springframework.data.domain.Sort.Order.asc; import static run.halo.app.extension.index.query.QueryFactory.*; +import java.util.List; import org.springframework.data.domain.Sort; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -34,36 +35,75 @@ public LinkFinderImpl(ReactiveExtensionClient client) { @Override public Flux listBy(String groupName) { + return listByInternal(groupName); + } + + @Override + public Flux listBy(List groupNames, int limit) { var listOptions = new ListOptions(); var query = isNull("metadata.deletionTimestamp"); - if (UNGROUPED_NAME.equals(groupName)) { - query = and(query, isNull("spec.groupName")); - } else { - query = and(query, equal("spec.groupName", groupName)); + + if (groupNames != null && !groupNames.isEmpty()) { + boolean hasUngrouped = groupNames.contains(UNGROUPED_NAME); + List validGroupNames = groupNames.stream() + .filter(name -> !UNGROUPED_NAME.equals(name)) + .toList(); + + var groupQuery = validGroupNames.isEmpty() ? null : in("spec.groupName", validGroupNames); + + if (hasUngrouped) { + var ungroupedQuery = isNull("spec.groupName"); + if (groupQuery != null) { + query = and(query, or(ungroupedQuery, groupQuery)); + } else { + query = and(query, ungroupedQuery); + } + } else if (groupQuery != null) { + query = and(query, groupQuery); + } } + listOptions.setFieldSelector(FieldSelector.of(query)); - return client.listAll(Link.class, listOptions, defaultLinkSort()) - .map(LinkVo::from); + + if (limit > 0) { + var pageRequest = new run.halo.app.extension.PageRequestImpl(0, limit, defaultLinkSort()); + return client.listBy(Link.class, listOptions, pageRequest) + .flatMapIterable(run.halo.app.extension.ListResult::getItems) + .map(LinkVo::from); + } else { + return client.listAll(Link.class, listOptions, defaultLinkSort()) + .map(LinkVo::from); + } } @Override public Flux groupBy() { return client.listAll(LinkGroup.class, new ListOptions(), defaultGroupSort()) - .map(LinkGroupVo::from) - .concatMap(group -> listBy(group.getMetadata().getName()) - .collectList() - .map(group::withLinks) - .defaultIfEmpty(group) - ) - .mergeWith(Mono.defer(() -> listBy(UNGROUPED_NAME) - .collectList() - // do not return ungrouped group if no links - .filter(links -> !links.isEmpty()) - .flatMap(links -> ungrouped() - .map(LinkGroupVo::from) - .map(group -> group.withLinks(links)) - ) - )); + .map(LinkGroupVo::from) + .concatMap(group -> listByInternal(group.getMetadata().getName()) + .collectList() + .map(group::withLinks) + .defaultIfEmpty(group)) + .mergeWith(Mono.defer(() -> listByInternal(UNGROUPED_NAME) + .collectList() + // do not return ungrouped group if no links + .filter(links -> !links.isEmpty()) + .flatMap(links -> ungrouped() + .map(LinkGroupVo::from) + .map(group -> group.withLinks(links))))); + } + + private Flux listByInternal(String groupName) { + var listOptions = new ListOptions(); + var query = isNull("metadata.deletionTimestamp"); + if (UNGROUPED_NAME.equals(groupName)) { + query = and(query, isNull("spec.groupName")); + } else { + query = and(query, equal("spec.groupName", groupName)); + } + listOptions.setFieldSelector(FieldSelector.of(query)); + return client.listAll(Link.class, listOptions, defaultLinkSort()) + .map(LinkVo::from); } Mono ungrouped() { @@ -78,15 +118,13 @@ Mono ungrouped() { static Sort defaultGroupSort() { return Sort.by(asc("spec.priority"), - asc("metadata.creationTimestamp"), - asc("metadata.name") - ); + asc("metadata.creationTimestamp"), + asc("metadata.name")); } static Sort defaultLinkSort() { return Sort.by(asc("spec.priority"), - asc("metadata.creationTimestamp"), - asc("metadata.name") - ); + asc("metadata.creationTimestamp"), + asc("metadata.name")); } }