feat: 展示 AI 资源创建人信息

- 为 Bot、工作流、知识库、插件列表补充创建人名称回填

- 在卡片中展示创建者与创建时间

- 补充后端与前端对应测试
This commit is contained in:
2026-04-13 14:58:14 +08:00
parent ae10383f17
commit 855e93ecbf
17 changed files with 642 additions and 3 deletions

View File

@@ -10,6 +10,7 @@ import tech.easyflow.system.entity.vo.SysAccountImportResultVo;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Map;
/**
* 用户表 服务层。
@@ -19,6 +20,14 @@ import java.util.Collection;
*/
public interface SysAccountService extends IService<SysAccount> {
/**
* 批量解析账号展示名称。
*
* @param accountIds 账号 ID 集合
* @return 账号 ID 到展示名称的映射,名称优先使用昵称,其次登录名,最后回退为 ID 字符串
*/
Map<BigInteger, String> resolveDisplayNameMap(Collection<BigInteger> accountIds);
void syncRelations(SysAccount entity);
SysAccount getByUsername(String userKey);

View File

@@ -55,6 +55,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
@@ -110,6 +111,57 @@ public class SysAccountServiceImpl extends ServiceImpl<SysAccountMapper, SysAcco
@Resource
private PlatformTransactionManager transactionManager;
/**
* 批量解析账号展示名称。
*
* @param accountIds 账号 ID 集合
* @return 账号 ID 到展示名称的映射
*/
@Override
public Map<BigInteger, String> resolveDisplayNameMap(Collection<BigInteger> accountIds) {
if (accountIds == null || accountIds.isEmpty()) {
return Collections.emptyMap();
}
LinkedHashSet<BigInteger> normalizedIds = accountIds.stream()
.filter(Objects::nonNull)
.collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
if (normalizedIds.isEmpty()) {
return Collections.emptyMap();
}
QueryWrapper queryWrapper = QueryWrapper.create()
.select(SysAccount::getId, SysAccount::getNickname, SysAccount::getLoginName)
.in(SysAccount::getId, normalizedIds);
List<SysAccount> accounts = list(queryWrapper);
LinkedHashMap<BigInteger, String> displayNameMap = new LinkedHashMap<>(normalizedIds.size());
for (SysAccount account : accounts) {
if (account == null || account.getId() == null) {
continue;
}
displayNameMap.put(account.getId(), resolveDisplayName(account));
}
normalizedIds.forEach(id -> displayNameMap.putIfAbsent(id, id.toString()));
return displayNameMap;
}
/**
* 解析单个账号的展示名称。
*
* @param account 账号实体
* @return 展示名称
*/
private String resolveDisplayName(SysAccount account) {
String nickname = trimToNull(account.getNickname());
if (StringUtil.hasText(nickname)) {
return nickname;
}
String loginName = trimToNull(account.getLoginName());
if (StringUtil.hasText(loginName)) {
return loginName;
}
return account.getId() == null ? "" : account.getId().toString();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void syncRelations(SysAccount entity) {

View File

@@ -0,0 +1,54 @@
package tech.easyflow.system.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Test;
import tech.easyflow.system.entity.SysAccount;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* {@link SysAccountServiceImpl} 测试。
*/
public class SysAccountServiceImplTest {
/**
* 验证展示名解析优先级与缺失数据回退。
*/
@Test
public void shouldResolveDisplayNameByNicknameThenLoginNameThenId() {
SysAccountServiceImpl service = spy(new SysAccountServiceImpl());
SysAccount nicknameAccount = new SysAccount();
nicknameAccount.setId(BigInteger.ONE);
nicknameAccount.setNickname("管理员");
nicknameAccount.setLoginName("admin");
SysAccount loginNameAccount = new SysAccount();
loginNameAccount.setId(BigInteger.valueOf(2));
loginNameAccount.setNickname(" ");
loginNameAccount.setLoginName("operator");
doReturn(List.of(nicknameAccount, loginNameAccount))
.when(service)
.list(any(QueryWrapper.class));
Map<BigInteger, String> displayNameMap = service.resolveDisplayNameMap(
List.of(BigInteger.ONE, BigInteger.valueOf(2), BigInteger.valueOf(3))
);
assertEquals("管理员", displayNameMap.get(BigInteger.ONE));
assertEquals("operator", displayNameMap.get(BigInteger.valueOf(2)));
assertEquals("3", displayNameMap.get(BigInteger.valueOf(3)));
verify(service, times(1)).list(any(QueryWrapper.class));
}
}