fix: 修复插件分类查询并保留返回状态

- 统一按插件名称进行模糊查询并支持分类筛选

- 恢复插件列表与工具编辑的页码、分类和搜索条件
This commit is contained in:
2026-07-31 09:54:45 +08:00
parent c2ed5a24a3
commit 1cbee6b018
13 changed files with 717 additions and 30 deletions

View File

@@ -1,5 +1,6 @@
package tech.easyflow.ai.service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
import tech.easyflow.ai.entity.Plugin;
import tech.easyflow.common.domain.Result;
@@ -20,7 +21,16 @@ public interface PluginService extends IService<Plugin> {
List<Plugin> getList();
Result pageByCategory(Long pageNumber, Long pageSize, int category);
/**
* 按分类分页查询插件。
*
* @param pageNumber 页码
* @param pageSize 每页数量
* @param category 分类 ID
* @param name 插件名称关键字
* @return 插件分页结果
*/
Result<Page<Plugin>> pageByCategory(Long pageNumber, Long pageSize, int category, String name);
boolean updatePlugin(Plugin plugin);

View File

@@ -132,7 +132,7 @@ public class PluginServiceImpl extends ServiceImpl<PluginMapper, Plugin> impleme
}
@Override
public Result<Page<Plugin>> pageByCategory(Long pageNumber, Long pageSize, int category) {
public Result<Page<Plugin>> pageByCategory(Long pageNumber, Long pageSize, int category, String name) {
RoleCategoryAccessSnapshot access = categoryPermissionService.getCurrentAccess("PLUGIN");
QueryWrapper queryWrapper = QueryWrapper.create().select(PluginCategoryMapping::getPluginId)
.eq(PluginCategoryMapping::getCategoryId, category);
@@ -158,7 +158,8 @@ public class PluginServiceImpl extends ServiceImpl<PluginMapper, Plugin> impleme
return Result.ok(new Page<>(Collections.emptyList(), pageNumber, pageSize, 0L));
}
List<Plugin> totalPlugins = preparePluginsForCurrentUser(queryPluginsByIds(visiblePluginIds), true, false);
List<Plugin> totalPlugins = preparePluginsForCurrentUser(
queryPluginsByIds(visiblePluginIds, name), true, false);
int fromIndex = Math.max(0, Math.toIntExact((pageNumber - 1) * pageSize));
if (fromIndex >= totalPlugins.size()) {
return Result.ok(new Page<>(Collections.emptyList(), pageNumber, pageSize, totalPlugins.size()));
@@ -251,11 +252,21 @@ public class PluginServiceImpl extends ServiceImpl<PluginMapper, Plugin> impleme
return pluginMapper.selectListByQueryAs(creatorPluginWrapper, BigInteger.class);
}
private List<Plugin> queryPluginsByIds(List<BigInteger> pluginIds) {
/**
* 按给定顺序查询插件,并按名称关键字过滤。
*
* @param pluginIds 插件 ID 列表
* @param name 插件名称关键字
* @return 保持输入 ID 顺序的插件列表
*/
private List<Plugin> queryPluginsByIds(List<BigInteger> pluginIds, String name) {
if (CollectionUtil.isEmpty(pluginIds)) {
return Collections.emptyList();
}
QueryWrapper queryPluginWrapper = QueryWrapper.create().select().in(Plugin::getId, pluginIds);
if (name != null && !name.isBlank()) {
queryPluginWrapper.like(Plugin::getName, name.trim());
}
List<Plugin> plugins = pluginMapper.selectListWithRelationsByQuery(queryPluginWrapper);
Map<BigInteger, Plugin> pluginMap = plugins.stream().collect(Collectors.toMap(
Plugin::getId,

View File

@@ -0,0 +1,83 @@
package tech.easyflow.ai.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import tech.easyflow.ai.entity.Plugin;
import tech.easyflow.ai.mapper.PluginCategoryMappingMapper;
import tech.easyflow.ai.mapper.PluginMapper;
import tech.easyflow.system.entity.vo.RoleCategoryAccessSnapshot;
import tech.easyflow.system.service.CategoryPermissionService;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* 插件分类分页查询测试。
*/
public class PluginServicePageQueryTest {
/**
* 验证具体分类下仍会按插件名称过滤。
*/
@Test
public void shouldFilterCategorizedPluginsByName() {
PluginMapper pluginMapper = mock(PluginMapper.class);
PluginCategoryMappingMapper mappingMapper = mock(PluginCategoryMappingMapper.class);
CategoryPermissionService categoryPermissionService = mock(CategoryPermissionService.class);
RoleCategoryAccessSnapshot access = mock(RoleCategoryAccessSnapshot.class);
PluginServiceImpl service = new PluginServiceImpl();
service.pluginMapper = pluginMapper;
service.pluginCategoryMappingMapper = mappingMapper;
setField(service, "categoryPermissionService", categoryPermissionService);
when(categoryPermissionService.getCurrentAccess("PLUGIN")).thenReturn(access);
when(access.isRestricted()).thenReturn(false);
when(mappingMapper.selectListByQueryAs(any(QueryWrapper.class), eq(BigInteger.class)))
.thenReturn(List.of(BigInteger.ONE));
when(pluginMapper.selectListWithRelationsByQuery(any(QueryWrapper.class)))
.thenReturn(Collections.emptyList());
service.pageByCategory(1L, 12L, 7, " 1213 ");
ArgumentCaptor<QueryWrapper> queryCaptor = ArgumentCaptor.forClass(QueryWrapper.class);
verify(pluginMapper).selectListWithRelationsByQuery(queryCaptor.capture());
String sql = queryCaptor.getValue().toSQL().toLowerCase(Locale.ROOT);
Assert.assertTrue(sql.contains("name"));
Assert.assertTrue(sql.contains("like"));
Assert.assertTrue(sql.contains("1213"));
}
/**
* 通过反射设置私有依赖。
*
* @param target 目标对象
* @param fieldName 字段名称
* @param value 字段值
*/
private static void setField(Object target, String fieldName, Object value) {
Class<?> current = target.getClass();
while (current != null) {
try {
java.lang.reflect.Field field = current.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
return;
} catch (NoSuchFieldException ignored) {
current = current.getSuperclass();
} catch (IllegalAccessException e) {
throw new IllegalStateException("设置测试字段失败: " + fieldName, e);
}
}
throw new IllegalArgumentException("未找到字段: " + fieldName);
}
}