chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package com.xspaceagi.system.application.aspect;
|
||||
|
||||
import com.xspaceagi.system.application.service.SysUserPermissionCacheService;
|
||||
import com.xspaceagi.system.spec.annotation.ClearAllUserPermissionCache;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 用户权限缓存清理切面
|
||||
*
|
||||
* 对标记了 {@link ClearAllUserPermissionCache} 的应用层方法,
|
||||
* 在方法成功执行后统一清理所有用户的权限缓存。
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class UserPermissionCacheClearAspect {
|
||||
|
||||
@Resource
|
||||
private SysUserPermissionCacheService sysUserPermissionCacheService;
|
||||
|
||||
@AfterReturning("@annotation(clearAllUserPermissionCache)")
|
||||
public void clearAllCacheAfterSuccess(ClearAllUserPermissionCache clearAllUserPermissionCache) {
|
||||
try {
|
||||
sysUserPermissionCacheService.clearCacheAll();
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to clear all user permission caches", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.xspaceagi.system.application.aspect;
|
||||
|
||||
import com.xspaceagi.system.application.service.SysUserPermissionCacheService;
|
||||
import com.xspaceagi.system.spec.annotation.ClearUserPermissionCacheByUserIds;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户维度权限缓存清理切面
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class UserPermissionUserCacheAspect {
|
||||
|
||||
@Resource
|
||||
private SysUserPermissionCacheService sysUserPermissionCacheService;
|
||||
|
||||
@AfterReturning("@annotation(clearAnno)")
|
||||
public void clearCacheByUserIds(JoinPoint joinPoint, ClearUserPermissionCacheByUserIds clearAnno) {
|
||||
Object[] args = joinPoint.getArgs();
|
||||
int[] indexes = clearAnno.userIdParamIndexes();
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
|
||||
if (indexes != null) {
|
||||
for (int idx : indexes) {
|
||||
if (idx < 0 || idx >= args.length) {
|
||||
continue;
|
||||
}
|
||||
Object arg = args[idx];
|
||||
collectUserIdsFromArg(arg, userIds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!userIds.isEmpty()) {
|
||||
try {
|
||||
sysUserPermissionCacheService.clearCacheByUserIds(userIds);
|
||||
} catch (Exception e) {
|
||||
log.warn("按用户ID清理权限缓存失败, userIds={}", userIds, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void collectUserIdsFromArg(Object arg, List<Long> userIds) {
|
||||
if (arg == null) {
|
||||
return;
|
||||
}
|
||||
if (arg instanceof Long) {
|
||||
userIds.add((Long) arg);
|
||||
} else if (arg instanceof Collection<?>) {
|
||||
for (Object item : (Collection<?>) arg) {
|
||||
if (item instanceof Long) {
|
||||
userIds.add((Long) item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Translators.
|
||||
*/
|
||||
package com.xspaceagi.system.application.assembler;
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xspaceagi.system.application.component;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 记录服务启动时间,在应用启动完成时写入
|
||||
*/
|
||||
@Component
|
||||
public class ServerStartupTimeHolder {
|
||||
|
||||
private volatile LocalDateTime serverStartupTime;
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void onApplicationReady(ApplicationReadyEvent event) {
|
||||
this.serverStartupTime = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public LocalDateTime getServerStartupTime() {
|
||||
return serverStartupTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.xspaceagi.system.application.constant;
|
||||
|
||||
import java.util.IllformedLocaleException;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 语言标识(lang)校验:使用 JDK {@link Locale.Builder#setLanguageTag(String)}(IETF BCP 47),
|
||||
*/
|
||||
public final class I18nLangTagConstraints {
|
||||
|
||||
/** Bean Validation 默认提示(中文) */
|
||||
public static final String LANG_TAG_MESSAGE = "语言标识格式不正确,请使用合法的语言标签,如 zh-CN、en-US、zh-Hans-CN";
|
||||
|
||||
/** 与 {@link #LANG_TAG_MESSAGE} 语义一致,用于 {@code IllegalArgumentException} 等直接透出 API 的场景 */
|
||||
public static final String LANG_TAG_MESSAGE_EN =
|
||||
"Invalid language tag. Use a valid BCP 47 tag such as zh-CN, en-US, or zh-Hans-CN.";
|
||||
|
||||
private I18nLangTagConstraints() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为 JDK 可解析的合法语言标签,且包含非空 language 子标签。
|
||||
*/
|
||||
public static boolean isWellFormedLanguageTag(String raw) {
|
||||
if (raw == null) {
|
||||
return false;
|
||||
}
|
||||
String s = raw.trim();
|
||||
if (s.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Locale loc = new Locale.Builder().setLanguageTag(s).build();
|
||||
return !loc.getLanguage().isEmpty();
|
||||
} catch (IllformedLocaleException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并规范为入库形式:{@link Locale#toLanguageTag()} 原样(JDK 典型形式,如 zh-CN、zh-Hans-CN),
|
||||
* 与 {@link Locale}、HTTP 常见写法一致。
|
||||
*/
|
||||
public static Optional<String> tryNormalizeToStoredForm(String raw) {
|
||||
if (raw == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String s = raw.trim();
|
||||
if (s.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
Locale loc = new Locale.Builder().setLanguageTag(s).build();
|
||||
if (loc.getLanguage().isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(loc.toLanguageTag());
|
||||
} catch (IllformedLocaleException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否指向同一语言标签(忽略大小写/等价规范化)。
|
||||
*/
|
||||
public static boolean sameLanguageTag(String a, String b) {
|
||||
if (a == null || b == null) {
|
||||
return a == null && b == null;
|
||||
}
|
||||
Optional<String> ca = tryNormalizeToStoredForm(a);
|
||||
Optional<String> cb = tryNormalizeToStoredForm(b);
|
||||
if (ca.isPresent() && cb.isPresent()) {
|
||||
return ca.get().equalsIgnoreCase(cb.get());
|
||||
}
|
||||
return a.trim().equalsIgnoreCase(b.trim());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.xspaceagi.system.application.constant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BCP 47 语言标识白名单(覆盖主要经济体与常见访客区域)
|
||||
*/
|
||||
public final class SupportedLocaleConstants {
|
||||
|
||||
private SupportedLocaleConstants() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认可选语言/区域(约数十种),按 tag 字母序便于 diff。
|
||||
*/
|
||||
public static final List<String> DEFAULT_LOCALE_TAG_WHITELIST = List.of(
|
||||
"ar-SA",
|
||||
"bg-BG",
|
||||
"bn-IN",
|
||||
"cs-CZ",
|
||||
"da-DK",
|
||||
"de-DE",
|
||||
"el-GR",
|
||||
"en-AU",
|
||||
"en-CA",
|
||||
"en-GB",
|
||||
"en-IN",
|
||||
"en-SG",
|
||||
"en-US",
|
||||
"es-419",
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"et-EE",
|
||||
"fa-IR",
|
||||
"fi-FI",
|
||||
"fil-PH",
|
||||
"fr-CA",
|
||||
"fr-FR",
|
||||
"he-IL",
|
||||
"hi-IN",
|
||||
"hr-HR",
|
||||
"hu-HU",
|
||||
"id-ID",
|
||||
"is-IS",
|
||||
"it-IT",
|
||||
"ja-JP",
|
||||
"ko-KR",
|
||||
"lt-LT",
|
||||
"lv-LV",
|
||||
"ms-MY",
|
||||
"nb-NO",
|
||||
"nl-NL",
|
||||
"pl-PL",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"sk-SK",
|
||||
"sl-SI",
|
||||
"sv-SE",
|
||||
"sw-KE",
|
||||
"th-TH",
|
||||
"tr-TR",
|
||||
"uk-UA",
|
||||
"ur-PK",
|
||||
"vi-VN",
|
||||
"zh-CN",
|
||||
"zh-HK",
|
||||
"zh-TW"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.domain.model.GroupBindMenuModel;
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.SysGroupBindMenuDto;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO到Model转换器
|
||||
*/
|
||||
public class GroupBindMenuModelConverter {
|
||||
|
||||
public static GroupBindMenuModel convertToModel(SysGroupBindMenuDto dto) {
|
||||
if (dto == null || dto.getGroupId() == null) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.fieldRequiredButEmpty, "用户组ID");
|
||||
}
|
||||
|
||||
GroupBindMenuModel model = new GroupBindMenuModel();
|
||||
model.setGroupId(dto.getGroupId());
|
||||
|
||||
// 获取所有菜单节点
|
||||
List<MenuNodeDto> menuNodes = dto.getAllMenuNodes();
|
||||
if (CollectionUtils.isEmpty(menuNodes)) {
|
||||
model.setMenuBindResourceList(new ArrayList<>());
|
||||
return model;
|
||||
}
|
||||
|
||||
// 转换为Domain模型
|
||||
List<MenuNode> menuBindInfos = MenuBindModelConverterUtil.convertMenuNodes(menuNodes);
|
||||
model.setMenuBindResourceList(menuBindInfos);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//package com.xspaceagi.system.application.converter;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//import java.util.stream.Collectors;
|
||||
//
|
||||
//import org.apache.commons.collections4.CollectionUtils;
|
||||
//
|
||||
//import com.xspaceagi.system.application.dto.permission.SysGroupDto;
|
||||
//
|
||||
///**
|
||||
// * 用户组树工具类
|
||||
// */
|
||||
//public class GroupTreeUtil {
|
||||
//
|
||||
// /**
|
||||
// * 构建用户组树形结构
|
||||
// */
|
||||
// public static List<SysGroupDto> buildGroupTree(List<SysGroupDto> groupList) {
|
||||
// if (CollectionUtils.isEmpty(groupList)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 按ID建立索引,方便查找
|
||||
// Map<Long, SysGroupDto> groupMap = groupList.stream()
|
||||
// .collect(Collectors.toMap(SysGroupDto::getId, group -> group));
|
||||
//
|
||||
// // 构建树形结构
|
||||
// List<SysGroupDto> rootGroups = new ArrayList<>();
|
||||
// for (SysGroupDto group : groupList) {
|
||||
// Long parentId = group.getParentId();
|
||||
// if (parentId == null || parentId == 0L) {
|
||||
// // 根节点
|
||||
// rootGroups.add(group);
|
||||
// } else {
|
||||
// // 子节点,添加到父节点的children中
|
||||
// SysGroupDto parent = groupMap.get(parentId);
|
||||
// if (parent != null) {
|
||||
// if (parent.getChildren() == null) {
|
||||
// parent.setChildren(new ArrayList<>());
|
||||
// }
|
||||
// parent.getChildren().add(group);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 对每个节点的children进行排序
|
||||
// sortGroupTree(rootGroups);
|
||||
//
|
||||
// // 返回根节点列表(已排序)
|
||||
// return rootGroups;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 递归排序用户组树
|
||||
// */
|
||||
// private static void sortGroupTree(List<SysGroupDto> groupList) {
|
||||
// if (CollectionUtils.isEmpty(groupList)) {
|
||||
// return;
|
||||
// }
|
||||
// groupList.sort((a, b) -> {
|
||||
// Integer sortA = a.getSortIndex() != null ? a.getSortIndex() : 0;
|
||||
// Integer sortB = b.getSortIndex() != null ? b.getSortIndex() : 0;
|
||||
// return sortA.compareTo(sortB);
|
||||
// });
|
||||
// for (SysGroupDto group : groupList) {
|
||||
// if (CollectionUtils.isNotEmpty(group.getChildren())) {
|
||||
// sortGroupTree(group.getChildren());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单绑定模型转换工具类
|
||||
*/
|
||||
public class MenuBindModelConverterUtil {
|
||||
|
||||
/**
|
||||
* 将菜单节点列表转换为MenuBindResource列表
|
||||
*/
|
||||
public static List<MenuNode> convertMenuNodes(List<MenuNodeDto> menuNodeDtos) {
|
||||
if (CollectionUtils.isEmpty(menuNodeDtos)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<MenuNode> menuNodes = new ArrayList<>();
|
||||
for (MenuNodeDto menuNodeDto : menuNodeDtos) {
|
||||
if (menuNodeDto.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
MenuNode menuNode = MenuBindResourceModelConverter.convertToMenuNode(menuNodeDto);
|
||||
menuNodes.add(menuNode);
|
||||
}
|
||||
return menuNodes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.domain.model.ResourceNode;
|
||||
import com.xspaceagi.system.spec.enums.BindTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.ResourceNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.SysMenuBindResourceDto;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单资源绑定 DTO -> Domain 模型转换器
|
||||
*/
|
||||
public class MenuBindResourceModelConverter {
|
||||
|
||||
public static MenuNode convertToMenuNode(SysMenuBindResourceDto dto) {
|
||||
if (dto == null) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemParamRequired);
|
||||
}
|
||||
MenuNodeDto menuNodeDto = new MenuNodeDto();
|
||||
menuNodeDto.setId(dto.getMenuId());
|
||||
menuNodeDto.setResourceTree(dto.getResourceTree());
|
||||
|
||||
MenuNode model = convertToMenuNode(menuNodeDto);
|
||||
return model;
|
||||
}
|
||||
|
||||
// 转换后资源是树形结构,不做扁平化处理
|
||||
public static MenuNode convertToMenuNode(MenuNodeDto menuNodeDto) {
|
||||
MenuNode menuNode = new MenuNode();
|
||||
menuNode.setId(menuNodeDto.getId());
|
||||
Integer menuBindType = menuNodeDto.getMenuBindType() != null ? menuNodeDto.getMenuBindType() : BindTypeEnum.NONE.getCode();
|
||||
menuNode.setMenuBindType(menuBindType);
|
||||
|
||||
List<ResourceNode> resourceTree = convertResourceTree(menuNodeDto.getResourceTree());
|
||||
menuNode.setResourceTree(resourceTree);
|
||||
|
||||
// 如果resourceBindType为PART,从resourceTree中提取所有资源ID,并保留完整资源树
|
||||
// if (BindTypeEnum.PART.getCode().equals(resourceBindType)) {
|
||||
// // 转换ResourceNode
|
||||
// List<ResourceNode> resourceTree = convertResourceTree(menuNodeDto.getResourceTree());
|
||||
// menuNode.setResourceTree(resourceTree);
|
||||
// } else {
|
||||
// menuNode.setResourceTree(null);
|
||||
// }
|
||||
return menuNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换资源树。支持两种格式:
|
||||
* 1. 树形结构(含 children)
|
||||
* 2. 扁平列表(无 children,仅传叶子节点,含 parentId)
|
||||
*/
|
||||
public static List<ResourceNode> convertResourceTree(List<ResourceNodeDto> nodes) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<ResourceNode> result = new ArrayList<>();
|
||||
for (ResourceNodeDto node : nodes) {
|
||||
ResourceNode resourceNode = new ResourceNode();
|
||||
resourceNode.setId(node.getId());
|
||||
resourceNode.setParentId(node.getParentId());
|
||||
Integer resourceBindType = node.getResourceBindType() != null ? node.getResourceBindType() : BindTypeEnum.NONE.getCode();
|
||||
resourceNode.setResourceBindType(resourceBindType);
|
||||
resourceNode.setCode(node.getCode());
|
||||
|
||||
if (!CollectionUtils.isEmpty(node.getChildren())) {
|
||||
resourceNode.setChildren(convertResourceTree(node.getChildren()));
|
||||
}
|
||||
result.add(resourceNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.ResourceNodeDto;
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.domain.model.ResourceNode;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MenuNode 转换为 MenuNodeDto 的转换器
|
||||
*/
|
||||
public class MenuNodeConverter {
|
||||
|
||||
public static List<MenuNodeDto> convertMenuTreeToDtoTree(List<MenuNode> menuNodeList) {
|
||||
if (CollectionUtils.isEmpty(menuNodeList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<MenuNodeDto> result = new ArrayList<>();
|
||||
for (MenuNode menuNode : menuNodeList) {
|
||||
MenuNodeDto dto = new MenuNodeDto();
|
||||
BeanUtils.copyProperties(menuNode, dto);
|
||||
|
||||
// 转换资源树(资源详细信息已在application层填充)
|
||||
if (CollectionUtils.isNotEmpty(menuNode.getResourceTree())) {
|
||||
dto.setResourceTree(convertResourceTree(menuNode.getResourceTree()));
|
||||
}
|
||||
|
||||
// 递归转换children
|
||||
if (CollectionUtils.isNotEmpty(menuNode.getChildren())) {
|
||||
dto.setChildren(convertMenuTreeToDtoTree(menuNode.getChildren()));
|
||||
}
|
||||
|
||||
result.add(dto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<ResourceNodeDto> convertResourceTree(
|
||||
List<ResourceNode> resourceNodes) {
|
||||
if (CollectionUtils.isEmpty(resourceNodes)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<ResourceNodeDto> result = new ArrayList<>();
|
||||
for (ResourceNode node : resourceNodes) {
|
||||
ResourceNodeDto dto = new ResourceNodeDto();
|
||||
dto.setId(node.getId());
|
||||
dto.setResourceBindType(node.getResourceBindType());
|
||||
|
||||
// 资源详细信息已在application层填充,直接复制
|
||||
dto.setCode(node.getCode());
|
||||
dto.setName(node.getName());
|
||||
dto.setDescription(node.getDescription());
|
||||
dto.setSource(node.getSource());
|
||||
dto.setType(node.getType());
|
||||
dto.setParentId(node.getParentId());
|
||||
dto.setPath(node.getPath());
|
||||
dto.setIcon(node.getIcon());
|
||||
dto.setSortIndex(node.getSortIndex());
|
||||
dto.setStatus(node.getStatus());
|
||||
|
||||
// 递归转换children
|
||||
if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
dto.setChildren(convertResourceTree(node.getChildren()));
|
||||
}
|
||||
|
||||
result.add(dto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.ResourceNodeDto;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 菜单树工具类
|
||||
*/
|
||||
public class MenuTreeUtil {
|
||||
|
||||
/**
|
||||
* 构建菜单树形结构,同时将每个菜单节点的 resourceTree 规范为树形结构
|
||||
*/
|
||||
public static List<MenuNodeDto> buildMenuTree(List<MenuNodeDto> menuList) {
|
||||
if (CollectionUtils.isEmpty(menuList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 按ID建立索引,方便查找
|
||||
Map<Long, MenuNodeDto> menuMap = menuList.stream()
|
||||
.collect(Collectors.toMap(MenuNodeDto::getId, menu -> menu));
|
||||
|
||||
// 构建树形结构
|
||||
List<MenuNodeDto> rootMenus = new ArrayList<>();
|
||||
for (MenuNodeDto menu : menuList) {
|
||||
Long parentId = menu.getParentId();
|
||||
if (parentId == null || parentId == 0L) {
|
||||
// 根节点
|
||||
rootMenus.add(menu);
|
||||
} else {
|
||||
// 子节点,添加到父节点的children中
|
||||
MenuNodeDto parent = menuMap.get(parentId);
|
||||
if (parent != null) {
|
||||
if (parent.getChildren() == null) {
|
||||
parent.setChildren(new ArrayList<>());
|
||||
}
|
||||
parent.getChildren().add(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 对每个节点的children进行排序
|
||||
sortMenuTree(rootMenus);
|
||||
|
||||
// 将每个菜单节点的 resourceTree 转成树形结构
|
||||
ensureResourceTreeForMenuTree(rootMenus);
|
||||
|
||||
// 返回根节点列表(已排序)
|
||||
return rootMenus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归确保菜单树中每个节点的 resourceTree 均为树形结构。
|
||||
* 若存在 resourceNodes(扁平结构),则从中构建树形并 set 到 resourceTree;
|
||||
* 否则若 resourceTree 本身非标准树形,则规范为树形。
|
||||
*/
|
||||
private static void ensureResourceTreeForMenuTree(List<MenuNodeDto> menuList) {
|
||||
if (CollectionUtils.isEmpty(menuList)) {
|
||||
return;
|
||||
}
|
||||
for (MenuNodeDto menu : menuList) {
|
||||
List<ResourceNodeDto> resourceList = CollectionUtils.isNotEmpty(menu.getResourceNodes())
|
||||
? menu.getResourceNodes()
|
||||
: menu.getResourceTree();
|
||||
if (CollectionUtils.isNotEmpty(resourceList)) {
|
||||
menu.setResourceTree(ResourceTreeUtil.buildResourceTreeFromNodes(resourceList));
|
||||
// 不需要返回 resourceNodes
|
||||
menu.setResourceNodes(null);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(menu.getChildren())) {
|
||||
ensureResourceTreeForMenuTree(menu.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归排序菜单树
|
||||
*/
|
||||
private static void sortMenuTree(List<MenuNodeDto> menuList) {
|
||||
if (CollectionUtils.isEmpty(menuList)) {
|
||||
return;
|
||||
}
|
||||
menuList.sort((a, b) -> {
|
||||
Integer sortA = a.getSortIndex() != null ? a.getSortIndex() : 0;
|
||||
Integer sortB = b.getSortIndex() != null ? b.getSortIndex() : 0;
|
||||
return sortA.compareTo(sortB);
|
||||
});
|
||||
for (MenuNodeDto menu : menuList) {
|
||||
if (CollectionUtils.isNotEmpty(menu.getChildren())) {
|
||||
sortMenuTree(menu.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.SysResource;
|
||||
import com.xspaceagi.system.spec.enums.BindTypeEnum;
|
||||
import com.xspaceagi.system.application.dto.permission.ResourceNodeDto;
|
||||
|
||||
/**
|
||||
* 资源树工具类
|
||||
*/
|
||||
public class ResourceTreeUtil {
|
||||
|
||||
/**
|
||||
* 构建资源树
|
||||
*/
|
||||
public static List<ResourceNodeDto> buildResourceTree(List<SysResource> resourceList) {
|
||||
return buildResourceTree(resourceList, Map.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建资源树
|
||||
*
|
||||
* @param resourceList 资源列表
|
||||
* @param resourceBindTypeMap 资源ID到绑定类型的映射(key: resourceId, value: resourceBindType)
|
||||
* @return 资源树形结构
|
||||
*/
|
||||
public static List<ResourceNodeDto> buildResourceTree(List<SysResource> resourceList, Map<Long, Integer> resourceBindTypeMap) {
|
||||
if (CollectionUtils.isEmpty(resourceList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 转换为 ResourceNodeDto
|
||||
List<ResourceNodeDto> nodeList = resourceList.stream().map(resource -> {
|
||||
ResourceNodeDto node = convertResourceToNode(resource);
|
||||
|
||||
Integer resourceBindType = resourceBindTypeMap.containsKey(resource.getId()) ? resourceBindTypeMap.get(resource.getId()) : BindTypeEnum.NONE.getCode();
|
||||
node.setResourceBindType(resourceBindType);
|
||||
return node;
|
||||
}).toList();
|
||||
|
||||
// 按ID建立索引,方便查找
|
||||
Map<Long, ResourceNodeDto> nodeMap = nodeList.stream()
|
||||
.collect(Collectors.toMap(ResourceNodeDto::getId, node -> node));
|
||||
|
||||
// 构建树形结构
|
||||
List<ResourceNodeDto> rootNodes = new ArrayList<>();
|
||||
for (ResourceNodeDto node : nodeList) {
|
||||
Long parentId = node.getParentId();
|
||||
if (parentId == null || parentId == 0L) {
|
||||
// 根节点
|
||||
rootNodes.add(node);
|
||||
} else {
|
||||
// 子节点,添加到父节点的children中
|
||||
ResourceNodeDto parent = nodeMap.get(parentId);
|
||||
if (parent != null) {
|
||||
if (parent.getChildren() == null) {
|
||||
parent.setChildren(new ArrayList<>());
|
||||
}
|
||||
parent.getChildren().add(node);
|
||||
} else {
|
||||
// 父节点不在当前列表中,作为根节点处理
|
||||
rootNodes.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 对每个节点及children进行排序
|
||||
sortResourceTree(rootNodes);
|
||||
|
||||
// 对每个节点进行 ALL 绑定类型的处理
|
||||
markChildrenForAllBindType(rootNodes, resourceBindTypeMap);
|
||||
|
||||
// 返回根节点列表(已排序)
|
||||
return rootNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归排序资源树
|
||||
*/
|
||||
private static void sortResourceTree(List<ResourceNodeDto> nodeList) {
|
||||
if (CollectionUtils.isEmpty(nodeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodeList.sort((a, b) -> {
|
||||
Integer sortA = a.getSortIndex() != null ? a.getSortIndex() : 0;
|
||||
Integer sortB = b.getSortIndex() != null ? b.getSortIndex() : 0;
|
||||
return sortA.compareTo(sortB);
|
||||
});
|
||||
|
||||
for (ResourceNodeDto node : nodeList) {
|
||||
if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
sortResourceTree(node.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于绑定方式为 ALL 的节点,将其所有子节点也强制标记为 ALL
|
||||
* 注意:ALL 类型的资源会强制覆盖子资源的绑定类型
|
||||
*/
|
||||
private static void markChildrenForAllBindType(List<ResourceNodeDto> nodes, Map<Long, Integer> resourceBindTypeMap) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return;
|
||||
}
|
||||
for (ResourceNodeDto node : nodes) {
|
||||
if (BindTypeEnum.ALL.getCode().equals(node.getResourceBindType())) {
|
||||
// 父节点是 ALL,强制将所有子节点也标记为 ALL
|
||||
markAllChildren(node, BindTypeEnum.ALL.getCode());
|
||||
} else if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
// 继续递归处理子节点
|
||||
markChildrenForAllBindType(node.getChildren(), resourceBindTypeMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归将子节点强制标记为指定绑定类型
|
||||
* 注意:此方法会强制覆盖子节点的绑定类型(用于处理 ALL 类型)
|
||||
*/
|
||||
private static void markAllChildren(ResourceNodeDto node, Integer resourceBindType) {
|
||||
if (CollectionUtils.isEmpty(node.getChildren())) {
|
||||
return;
|
||||
}
|
||||
for (ResourceNodeDto child : node.getChildren()) {
|
||||
// 强制设置子节点的绑定类型为 ALL(覆盖原有类型)
|
||||
// 因为父节点是 ALL 时,所有子节点也必须是 ALL
|
||||
child.setResourceBindType(resourceBindType);
|
||||
// 递归处理子节点的子节点
|
||||
markAllChildren(child, resourceBindType);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceNodeDto convertResourceToNode(SysResource resource) {
|
||||
ResourceNodeDto node = new ResourceNodeDto();
|
||||
node.setId(resource.getId());
|
||||
node.setCode(resource.getCode());
|
||||
node.setName(resource.getName());
|
||||
node.setDescription(resource.getDescription());
|
||||
node.setSource(resource.getSource());
|
||||
node.setType(resource.getType());
|
||||
node.setParentId(resource.getParentId());
|
||||
node.setPath(resource.getPath());
|
||||
node.setIcon(resource.getIcon());
|
||||
node.setSortIndex(resource.getSortIndex());
|
||||
node.setStatus(resource.getStatus());
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 ResourceNodeDto 列表(扁平或已是树形)构建/规范为树形结构
|
||||
*
|
||||
* @param nodeList 资源节点列表,每个节点需包含 id 和 parentId;若已是树形则先扁平化再重建
|
||||
* @return 资源树形结构(根节点列表)
|
||||
*/
|
||||
public static List<ResourceNodeDto> buildResourceTreeFromNodes(List<ResourceNodeDto> nodeList) {
|
||||
if (CollectionUtils.isEmpty(nodeList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<ResourceNodeDto> flatList = flattenToNodeListWithParentId(nodeList, null);
|
||||
return buildTreeFromFlatNodeList(flatList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归将资源树扁平化为列表,并确保每个节点的 parentId 正确
|
||||
*/
|
||||
private static List<ResourceNodeDto> flattenToNodeListWithParentId(List<ResourceNodeDto> nodes, Long parentId) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<ResourceNodeDto> result = new ArrayList<>();
|
||||
for (ResourceNodeDto node : nodes) {
|
||||
ResourceNodeDto copy = new ResourceNodeDto();
|
||||
copy.setId(node.getId());
|
||||
copy.setParentId(node.getParentId() != null ? node.getParentId() : parentId);
|
||||
copy.setResourceBindType(node.getResourceBindType());
|
||||
copy.setCode(node.getCode());
|
||||
copy.setName(node.getName());
|
||||
copy.setDescription(node.getDescription());
|
||||
copy.setSource(node.getSource());
|
||||
copy.setType(node.getType());
|
||||
copy.setPath(node.getPath());
|
||||
copy.setIcon(node.getIcon());
|
||||
copy.setSortIndex(node.getSortIndex());
|
||||
copy.setStatus(node.getStatus());
|
||||
result.add(copy);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
result.addAll(flattenToNodeListWithParentId(node.getChildren(), node.getId()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<ResourceNodeDto> buildTreeFromFlatNodeList(List<ResourceNodeDto> flatList) {
|
||||
if (CollectionUtils.isEmpty(flatList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map<Long, ResourceNodeDto> nodeMap = flatList.stream()
|
||||
.filter(n -> n.getId() != null)
|
||||
.collect(Collectors.toMap(ResourceNodeDto::getId, n -> n, (a, b) -> a));
|
||||
|
||||
List<ResourceNodeDto> rootNodes = new ArrayList<>();
|
||||
for (ResourceNodeDto node : flatList) {
|
||||
Long nodeParentId = node.getParentId();
|
||||
if (nodeParentId == null || nodeParentId == 0L) {
|
||||
rootNodes.add(node);
|
||||
} else {
|
||||
ResourceNodeDto parent = nodeMap.get(nodeParentId);
|
||||
if (parent != null) {
|
||||
if (parent.getChildren() == null) {
|
||||
parent.setChildren(new ArrayList<>());
|
||||
}
|
||||
parent.getChildren().add(node);
|
||||
} else {
|
||||
rootNodes.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortResourceTree(rootNodes);
|
||||
return rootNodes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.domain.model.RoleBindMenuModel;
|
||||
import com.xspaceagi.system.application.dto.permission.MenuNodeDto;
|
||||
import com.xspaceagi.system.application.dto.permission.SysRoleBindMenuDto;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色菜单绑定DTO到Model转换器
|
||||
*/
|
||||
public class RoleBindMenuModelConverter {
|
||||
|
||||
/**
|
||||
* 将Web层DTO转换为Domain层模型
|
||||
*/
|
||||
public static RoleBindMenuModel convertToModel(SysRoleBindMenuDto dto) {
|
||||
if (dto == null || dto.getRoleId() == null) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.fieldRequiredButEmpty, "角色ID");
|
||||
}
|
||||
|
||||
RoleBindMenuModel model = new RoleBindMenuModel();
|
||||
model.setRoleId(dto.getRoleId());
|
||||
|
||||
List<MenuNodeDto> menuNodes = dto.getFlattenlMenuNodes();
|
||||
if (CollectionUtils.isEmpty(menuNodes)) {
|
||||
model.setMenuBindResourceList(new ArrayList<>());
|
||||
return model;
|
||||
}
|
||||
|
||||
List<MenuNode> menuBindInfos = MenuBindModelConverterUtil.convertMenuNodes(menuNodes);
|
||||
model.setMenuBindResourceList(menuBindInfos);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.xspaceagi.system.application.converter;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.SysDataPermissionBindDto;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysDataPermission;
|
||||
import com.xspaceagi.system.sdk.service.dto.TokenLimit;
|
||||
import com.xspaceagi.system.spec.jackson.JsonSerializeUtil;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据权限转换器
|
||||
*/
|
||||
public final class SysDataPermissionConverter {
|
||||
|
||||
private SysDataPermissionConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体转 DTO(用于查询接口返回)
|
||||
*/
|
||||
public static SysDataPermissionBindDto toDto(SysDataPermission entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
SysDataPermissionBindDto dto = new SysDataPermissionBindDto();
|
||||
BeanUtils.copyProperties(entity, dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static SysDataPermission toEntity(SysDataPermissionBindDto dto) {
|
||||
if (dto == null) {
|
||||
return null;
|
||||
}
|
||||
SysDataPermission entity = new SysDataPermission();
|
||||
entity.setModelIds(dto.getModelIds());
|
||||
entity.setAgentIds(dto.getAgentIds());
|
||||
entity.setPageAgentIds(dto.getPageAgentIds());
|
||||
Map<String, String> openApiConfigMap = new LinkedHashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(dto.getOpenApiConfigs())) {
|
||||
for (SysDataPermissionBindDto.OpenApiConfig config : dto.getOpenApiConfigs()) {
|
||||
if (config == null || StringUtils.isBlank(config.getKey())) {
|
||||
continue;
|
||||
}
|
||||
Map<String, Integer> configValue = new LinkedHashMap<>();
|
||||
configValue.put("rpm", config.getRpm());
|
||||
configValue.put("rpd", config.getRpd());
|
||||
openApiConfigMap.put(config.getKey(), JsonSerializeUtil.toJSONString(configValue));
|
||||
}
|
||||
}
|
||||
entity.setOpenApiConfigMap(openApiConfigMap);
|
||||
entity.setKnowledgeIds(dto.getKnowledgeIds());
|
||||
|
||||
// 数量类型不传默认 -1(不限制)
|
||||
entity.setTokenLimit(dto.getTokenLimit() != null ? dto.getTokenLimit() : new TokenLimit(-1L));
|
||||
entity.setMaxSpaceCount(dto.getMaxSpaceCount() != null ? dto.getMaxSpaceCount() : -1);
|
||||
entity.setMaxAgentCount(dto.getMaxAgentCount() != null ? dto.getMaxAgentCount() : -1);
|
||||
entity.setMaxPageAppCount(dto.getMaxPageAppCount() != null ? dto.getMaxPageAppCount() : -1);
|
||||
entity.setMaxKnowledgeCount(dto.getMaxKnowledgeCount() != null ? dto.getMaxKnowledgeCount() : -1);
|
||||
entity.setKnowledgeStorageLimitGb(dto.getKnowledgeStorageLimitGb() != null ? dto.getKnowledgeStorageLimitGb() : BigDecimal.valueOf(-1L));
|
||||
entity.setMaxDataTableCount(dto.getMaxDataTableCount() != null ? dto.getMaxDataTableCount() : -1);
|
||||
entity.setMaxScheduledTaskCount(dto.getMaxScheduledTaskCount() != null ? dto.getMaxScheduledTaskCount() : -1);
|
||||
entity.setAgentFileStorageDays(dto.getAgentFileStorageDays() != null ? dto.getAgentFileStorageDays() : -1);
|
||||
entity.setAgentDailyPromptLimit(dto.getAgentDailyPromptLimit() != null ? dto.getAgentDailyPromptLimit() : -1);
|
||||
entity.setPageDailyPromptLimit(dto.getPageDailyPromptLimit() != null ? dto.getPageDailyPromptLimit() : -1);
|
||||
//entity.setAllowApiExternalCall(dto.getAllowApiExternalCall());
|
||||
// 智能体电脑内存不传默认 4,交换分区不传默认 8,CPU核心数不传默认 2
|
||||
entity.setAgentComputerCpuCores(dto.getAgentComputerCpuCores() != null ? dto.getAgentComputerCpuCores() : 2);
|
||||
entity.setAgentComputerMemoryGb(dto.getAgentComputerMemoryGb() != null ? dto.getAgentComputerMemoryGb() : 4);
|
||||
entity.setAgentComputerSwapGb(null);
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
//package com.xspaceagi.system.web.converter;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.Comparator;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.HashSet;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//import java.util.Objects;
|
||||
//import java.util.Set;
|
||||
//import java.util.stream.Collectors;
|
||||
//
|
||||
//import org.apache.commons.collections4.CollectionUtils;
|
||||
//
|
||||
//import com.xspaceagi.system.domain.model.MenuNode;
|
||||
//import com.xspaceagi.system.domain.model.ResourceNode;
|
||||
//import com.xspaceagi.system.infra.dao.entity.SysMenu;
|
||||
//import com.xspaceagi.system.infra.dao.entity.SysResource;
|
||||
//import com.xspaceagi.system.spec.enums.BindTypeEnum;
|
||||
//
|
||||
///**
|
||||
// * 用户维度菜单 + 资源权限合并工具
|
||||
// */
|
||||
//public class UserMenuMergeUtil {
|
||||
//
|
||||
// /**
|
||||
// * 合并来自多个角色 / 用户组的菜单权限
|
||||
// * - 同一 menuId 的菜单进行合并
|
||||
// * - menuBindType 取"最大权限"(ALL > PART > NONE)
|
||||
// * - 资源权限按 resourceId 合并,resourceBindType 同样取最大权限
|
||||
// */
|
||||
// public static List<MenuNode> mergeUserMenuNodes(List<MenuNode> nodes) {
|
||||
// if (CollectionUtils.isEmpty(nodes)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 按 menuId 分组
|
||||
// Map<Long, List<MenuNode>> menuGroup = nodes.stream()
|
||||
// .filter(n -> n.getMenuId() != null)
|
||||
// .collect(Collectors.groupingBy(MenuNode::getMenuId));
|
||||
//
|
||||
// List<MenuNode> result = new ArrayList<>();
|
||||
// for (Map.Entry<Long, List<MenuNode>> entry : menuGroup.entrySet()) {
|
||||
// Long menuId = entry.getKey();
|
||||
// List<MenuNode> menuNodes = entry.getValue();
|
||||
// if (CollectionUtils.isEmpty(menuNodes)) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// MenuNode merged = new MenuNode();
|
||||
// merged.setMenuId(menuId);
|
||||
//
|
||||
// // 1. 合并 menuBindType(取最大权限)
|
||||
// Integer mergedMenuBindType = menuNodes.stream()
|
||||
// .map(MenuNode::getMenuBindType)
|
||||
// .filter(Objects::nonNull)
|
||||
// .max(Comparator.comparingInt(UserMenuMergeUtil::bindTypeOrder))
|
||||
// .orElse(BindTypeEnum.NONE.getCode());
|
||||
// merged.setMenuBindType(mergedMenuBindType);
|
||||
//
|
||||
// // 2. 合并资源权限(合并所有资源树)
|
||||
// List<ResourceNode> allResources = menuNodes.stream()
|
||||
// .filter(n -> CollectionUtils.isNotEmpty(n.getResourceTree()))
|
||||
// .flatMap(n -> flattenResourceTree(n.getResourceTree()).stream())
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// if (CollectionUtils.isNotEmpty(allResources)) {
|
||||
// Map<Long, List<ResourceNode>> resourceGroup = allResources.stream()
|
||||
// .filter(r -> r.getResourceId() != null)
|
||||
// .collect(Collectors.groupingBy(ResourceNode::getResourceId));
|
||||
//
|
||||
// List<ResourceNode> mergedResourceList = new ArrayList<>();
|
||||
// for (Map.Entry<Long, List<ResourceNode>> re : resourceGroup.entrySet()) {
|
||||
// Long resourceId = re.getKey();
|
||||
// List<ResourceNode> resourceNodes = re.getValue();
|
||||
// if (CollectionUtils.isEmpty(resourceNodes)) {
|
||||
// continue;
|
||||
// }
|
||||
// ResourceNode mergedResource = new ResourceNode();
|
||||
// mergedResource.setResourceId(resourceId);
|
||||
// Integer mergedBindType = resourceNodes.stream()
|
||||
// .map(ResourceNode::getResourceBindType)
|
||||
// .filter(Objects::nonNull)
|
||||
// .max(Comparator.comparingInt(UserMenuMergeUtil::bindTypeOrder))
|
||||
// .orElse(BindTypeEnum.NONE.getCode());
|
||||
// mergedResource.setResourceBindType(mergedBindType);
|
||||
// mergedResourceList.add(mergedResource);
|
||||
// }
|
||||
//
|
||||
// // 保存扁平化的资源列表(后续会重建资源树)
|
||||
// // 先保存到resourceTree中,后续会重建树形结构
|
||||
// merged.setResourceTree(mergedResourceList);
|
||||
// }
|
||||
//
|
||||
// result.add(merged);
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 传播菜单和资源的绑定类型,并过滤出有权限的菜单和资源
|
||||
// *
|
||||
// * @param mergedMenuNodes 合并后的菜单节点列表
|
||||
// * @param allMenus 所有菜单列表
|
||||
// * @param allResources 所有资源列表
|
||||
// * @return 有权限的菜单和资源(已传播并过滤)
|
||||
// */
|
||||
// public static List<MenuNode> propagateAndFilterAuthorizedMenus(List<MenuNode> mergedMenuNodes,
|
||||
// List<SysMenu> allMenus,
|
||||
// List<SysResource> allResources) {
|
||||
// if (CollectionUtils.isEmpty(mergedMenuNodes)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 构建菜单ID到MenuNode的映射
|
||||
// Map<Long, MenuNode> menuNodeMap = mergedMenuNodes.stream()
|
||||
// .filter(n -> n.getMenuId() != null)
|
||||
// .collect(Collectors.toMap(MenuNode::getMenuId, n -> n));
|
||||
//
|
||||
// // 构建菜单父子关系映射
|
||||
// Map<Long, List<SysMenu>> menuChildrenMap = new HashMap<>();
|
||||
// for (SysMenu menu : allMenus) {
|
||||
// Long parentId = menu.getParentId();
|
||||
// if (parentId != null && parentId != 0L) {
|
||||
// menuChildrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(menu);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 构建资源父子关系映射
|
||||
// Map<Long, List<SysResource>> resourceChildrenMap = new HashMap<>();
|
||||
// Map<Long, SysResource> resourceMap = allResources.stream()
|
||||
// .collect(Collectors.toMap(SysResource::getId, r -> r));
|
||||
// for (SysResource resource : allResources) {
|
||||
// Long parentId = resource.getParentId();
|
||||
// if (parentId != null && parentId != 0L) {
|
||||
// resourceChildrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(resource);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 1. 传播菜单绑定类型(ALL/NONE的子菜单也传播)
|
||||
// Map<Long, Integer> menuBindTypeMap = new HashMap<>();
|
||||
// Set<Long> processedMenuIds = new HashSet<>();
|
||||
//
|
||||
// // 先设置合并后的菜单绑定类型
|
||||
// for (MenuNode menuNode : mergedMenuNodes) {
|
||||
// if (menuNode.getMenuId() != null) {
|
||||
// menuBindTypeMap.put(menuNode.getMenuId(), menuNode.getMenuBindType());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 对于ALL类型的菜单,递归设置所有子菜单为ALL
|
||||
// for (MenuNode menuNode : mergedMenuNodes) {
|
||||
// if (menuNode.getMenuId() != null && BindTypeEnum.ALL.getCode().equals(menuNode.getMenuBindType())) {
|
||||
// propagateMenuBindType(menuNode.getMenuId(), menuChildrenMap, menuBindTypeMap,
|
||||
// processedMenuIds, BindTypeEnum.ALL.getCode());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 对于NONE类型的菜单,递归设置所有子菜单为NONE
|
||||
// for (MenuNode menuNode : mergedMenuNodes) {
|
||||
// if (menuNode.getMenuId() != null && BindTypeEnum.NONE.getCode().equals(menuNode.getMenuBindType())) {
|
||||
// propagateMenuBindType(menuNode.getMenuId(), menuChildrenMap, menuBindTypeMap,
|
||||
// processedMenuIds, BindTypeEnum.NONE.getCode());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 2. 收集所有有权限的菜单ID(包括传播后的子菜单)
|
||||
// Set<Long> authorizedMenuIds = new HashSet<>();
|
||||
// for (Map.Entry<Long, Integer> entry : menuBindTypeMap.entrySet()) {
|
||||
// Integer bindType = entry.getValue();
|
||||
// if (!BindTypeEnum.NONE.getCode().equals(bindType)) {
|
||||
// authorizedMenuIds.add(entry.getKey());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 3. 处理每个菜单的资源权限
|
||||
// List<MenuNode> result = new ArrayList<>();
|
||||
// for (Long menuId : authorizedMenuIds) {
|
||||
// MenuNode menuNode = menuNodeMap.get(menuId);
|
||||
//
|
||||
// // 处理资源权限
|
||||
// List<ResourceNode> authorizedResources = new ArrayList<>();
|
||||
// if (menuNode != null && CollectionUtils.isNotEmpty(menuNode.getResourceTree())) {
|
||||
// authorizedResources = processAuthorizedResources(
|
||||
// menuNode, resourceMap, resourceChildrenMap);
|
||||
// }
|
||||
//
|
||||
// // 只返回有权限的菜单(menuBindType != NONE)
|
||||
// MenuNode authorizedMenu = new MenuNode();
|
||||
// authorizedMenu.setMenuId(menuId);
|
||||
// authorizedMenu.setResourceTree(authorizedResources); // 只包含有权限的资源(resourceBindType != NONE)
|
||||
// result.add(authorizedMenu);
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 传播菜单绑定类型
|
||||
// */
|
||||
// private static void propagateMenuBindType(Long menuId, Map<Long, List<SysMenu>> menuChildrenMap,
|
||||
// Map<Long, Integer> menuBindTypeMap, Set<Long> processedMenuIds,
|
||||
// Integer bindType) {
|
||||
// if (processedMenuIds.contains(menuId)) {
|
||||
// return;
|
||||
// }
|
||||
// processedMenuIds.add(menuId);
|
||||
//
|
||||
// List<SysMenu> children = menuChildrenMap.get(menuId);
|
||||
// if (CollectionUtils.isEmpty(children)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// for (SysMenu child : children) {
|
||||
// if (child.getId() == null) {
|
||||
// continue;
|
||||
// }
|
||||
// // 强制设置子菜单的绑定类型
|
||||
// menuBindTypeMap.put(child.getId(), bindType);
|
||||
// // 递归处理子菜单的子菜单
|
||||
// propagateMenuBindType(child.getId(), menuChildrenMap, menuBindTypeMap, processedMenuIds, bindType);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 处理菜单的资源权限,传播并过滤出有权限的资源
|
||||
// */
|
||||
// private static List<ResourceNode> processAuthorizedResources(MenuNode menuNode,
|
||||
// Map<Long, SysResource> resourceMap,
|
||||
// Map<Long, List<SysResource>> resourceChildrenMap) {
|
||||
// if (CollectionUtils.isEmpty(menuNode.getResourceTree())) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 扁平化资源树(可能是树形结构或扁平列表)
|
||||
// List<ResourceNode> flatResources = flattenResourceTree(menuNode.getResourceTree());
|
||||
//
|
||||
// // 构建资源绑定类型映射
|
||||
// Map<Long, Integer> resourceBindTypeMap = flatResources.stream()
|
||||
// .filter(r -> r.getResourceId() != null && r.getResourceBindType() != null)
|
||||
// .collect(Collectors.toMap(ResourceNode::getResourceId, ResourceNode::getResourceBindType));
|
||||
//
|
||||
// // 传播资源绑定类型(ALL/NONE的子资源也传播)
|
||||
// Set<Long> processedResourceIds = new HashSet<>();
|
||||
// for (ResourceNode resourceNode : flatResources) {
|
||||
// Long resourceId = resourceNode.getResourceId();
|
||||
// Integer bindType = resourceNode.getResourceBindType();
|
||||
// if (resourceId != null && bindType != null && !processedResourceIds.contains(resourceId)) {
|
||||
// if (BindTypeEnum.ALL.getCode().equals(bindType) || BindTypeEnum.NONE.getCode().equals(bindType)) {
|
||||
// propagateResourceBindType(resourceId, resourceChildrenMap, resourceBindTypeMap,
|
||||
// processedResourceIds, bindType);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 收集所有有权限的资源ID(resourceBindType != NONE)
|
||||
// Set<Long> authorizedResourceIds = resourceBindTypeMap.entrySet().stream()
|
||||
// .filter(e -> !BindTypeEnum.NONE.getCode().equals(e.getValue()))
|
||||
// .map(Map.Entry::getKey)
|
||||
// .collect(Collectors.toSet());
|
||||
//
|
||||
// if (CollectionUtils.isEmpty(authorizedResourceIds)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 从所有资源中筛选出有权限的资源
|
||||
// List<SysResource> authorizedResources = resourceMap.values().stream()
|
||||
// .filter(r -> authorizedResourceIds.contains(r.getId()))
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// // 重建资源树(不包含resourceBindType字段)
|
||||
// return rebuildResourceTree(authorizedResources, resourceMap, resourceChildrenMap);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 传播资源绑定类型
|
||||
// */
|
||||
// private static void propagateResourceBindType(Long resourceId,
|
||||
// Map<Long, List<SysResource>> resourceChildrenMap,
|
||||
// Map<Long, Integer> resourceBindTypeMap,
|
||||
// Set<Long> processedResourceIds,
|
||||
// Integer bindType) {
|
||||
// if (processedResourceIds.contains(resourceId)) {
|
||||
// return;
|
||||
// }
|
||||
// processedResourceIds.add(resourceId);
|
||||
//
|
||||
// List<SysResource> children = resourceChildrenMap.get(resourceId);
|
||||
// if (CollectionUtils.isEmpty(children)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// for (SysResource child : children) {
|
||||
// if (child.getId() == null) {
|
||||
// continue;
|
||||
// }
|
||||
// // 强制设置子资源的绑定类型
|
||||
// resourceBindTypeMap.put(child.getId(), bindType);
|
||||
// // 递归处理子资源的子资源
|
||||
// propagateResourceBindType(child.getId(), resourceChildrenMap, resourceBindTypeMap,
|
||||
// processedResourceIds, bindType);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 重建资源树(只包含有权限的资源,不设置resourceBindType字段)
|
||||
// */
|
||||
// private static List<ResourceNode> rebuildResourceTree(List<SysResource> authorizedResources,
|
||||
// Map<Long, SysResource> resourceMap,
|
||||
// Map<Long, List<SysResource>> resourceChildrenMap) {
|
||||
// if (CollectionUtils.isEmpty(authorizedResources)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// // 构建资源ID到ResourceNode的映射(不设置resourceBindType)
|
||||
// Map<Long, ResourceNode> nodeMap = new HashMap<>();
|
||||
// for (SysResource resource : authorizedResources) {
|
||||
// ResourceNode node = new ResourceNode();
|
||||
// node.setResourceId(resource.getId());
|
||||
// // 不设置resourceBindType,因为用户查询只返回有权限的资源
|
||||
// nodeMap.put(resource.getId(), node);
|
||||
// }
|
||||
//
|
||||
// // 构建树形结构
|
||||
// List<ResourceNode> rootNodes = new ArrayList<>();
|
||||
// for (SysResource resource : authorizedResources) {
|
||||
// ResourceNode current = nodeMap.get(resource.getId());
|
||||
// Long parentId = resource.getParentId();
|
||||
// if (parentId == null || parentId == 0L || !nodeMap.containsKey(parentId)) {
|
||||
// // 根节点
|
||||
// rootNodes.add(current);
|
||||
// } else {
|
||||
// // 子节点,添加到父节点的children中
|
||||
// ResourceNode parent = nodeMap.get(parentId);
|
||||
// if (parent.getChildren() == null) {
|
||||
// parent.setChildren(new ArrayList<>());
|
||||
// }
|
||||
// parent.getChildren().add(current);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return rootNodes;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 过滤掉完全没有权限的菜单:
|
||||
// * - menuBindType=NONE
|
||||
// * - 且所有资源 resourceBindType=NONE 或无资源
|
||||
// */
|
||||
// public static List<MenuNode> filterNoPermissionMenus(List<MenuNode> nodes) {
|
||||
// if (CollectionUtils.isEmpty(nodes)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
// return nodes.stream()
|
||||
// .filter(node -> {
|
||||
// Integer menuBindType = node.getMenuBindType();
|
||||
// if (!BindTypeEnum.NONE.getCode().equals(menuBindType)) {
|
||||
// return true;
|
||||
// }
|
||||
// // menuBindType=NONE,再看资源
|
||||
// if (CollectionUtils.isEmpty(node.getFlattenResourceList())) {
|
||||
// return false;
|
||||
// }
|
||||
// // 如果存在任意一个资源的绑定类型 != NONE,则保留菜单
|
||||
// return node.getFlattenResourceList().stream()
|
||||
// .anyMatch(r -> !BindTypeEnum.NONE.getCode().equals(r.getResourceBindType()));
|
||||
// })
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 绑定类型优先级:NONE < PART < ALL
|
||||
// */
|
||||
// private static int bindTypeOrder(Integer bindType) {
|
||||
// if (bindType == null) {
|
||||
// return 0;
|
||||
// }
|
||||
// if (BindTypeEnum.NONE.getCode().equals(bindType)) {
|
||||
// return 1;
|
||||
// }
|
||||
// if (BindTypeEnum.PART.getCode().equals(bindType)) {
|
||||
// return 2;
|
||||
// }
|
||||
// if (BindTypeEnum.ALL.getCode().equals(bindType)) {
|
||||
// return 3;
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户有权限的菜单ID与资源ID集合(用于按需加载,避免全量查询)
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AuthorizedIds {
|
||||
|
||||
private final Set<Long> menuIds;
|
||||
private final Set<Long> resourceIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 分类创建请求DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "分类创建请求")
|
||||
public class CategoryCreateDto {
|
||||
|
||||
@NotBlank(message = "Category name is required")
|
||||
@Schema(description = "分类名称", required = true)
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "Category code is required")
|
||||
@Schema(description = "分类编码", required = true)
|
||||
private String code;
|
||||
|
||||
@NotBlank(message = "Category type is required")
|
||||
@Schema(description = "分类类型:Agent、PageApp、Component", required = true)
|
||||
private String type;
|
||||
|
||||
@Schema(description = "分类描述")
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 分类更新请求DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "分类更新请求")
|
||||
public class CategoryUpdateDto {
|
||||
|
||||
@NotNull(message = "ID is required")
|
||||
@Schema(description = "分类ID", required = true)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分类编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "分类类型:Agent、PageApp、Component")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "分类描述")
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EventDto<E> {
|
||||
|
||||
public static final String EVENT_TYPE_NEW_NOTIFY_MESSAGE = "new_notify_message";
|
||||
public static final String EVENT_TYPE_REFRESH_CHAT_MESSAGE = "refresh_chat_message";
|
||||
public static final String EVENT_TYPE_CHAT_FINISHED = "chat_finished";
|
||||
|
||||
@Schema(description = "事件类型,由具体的业务定义,和前端同步;当前已定义的类型:new_notify_message - 有新的通知消息;refresh_chat_message - 会话消息列表需要刷新")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "事件内容,由具体的业务定义,和前端同步")
|
||||
private E event;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "批量翻译请求")
|
||||
public class I18nBatchTranslateDto {
|
||||
|
||||
@NotEmpty(message = "The key list cannot be empty.")
|
||||
@Schema(description = "待翻译的 fieldKey 列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> keys;
|
||||
|
||||
@NotBlank(message = "The source language cannot be empty.")
|
||||
@Schema(description = "源语言,如 zh-CN", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String sourceLang;
|
||||
|
||||
@NotBlank(message = "The target language cannot be empty.")
|
||||
@Schema(description = "目标语言,如 en-US", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String targetLang;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class I18nConfigDto {
|
||||
|
||||
@Schema(description = "类型,系统 System;业务数据 BizData,暂时不用关注该字段", hidden = true)
|
||||
private String type;
|
||||
|
||||
@Schema(description = "端")
|
||||
private String side;
|
||||
|
||||
@Schema(description = "业务模块", hidden = true)
|
||||
private String module;
|
||||
|
||||
@Schema(description = "业务模块具体记录ID", hidden = true)
|
||||
private String dataId;
|
||||
|
||||
@Schema(description = "具体语言,中文:zh-cn,英文:en-us,等")
|
||||
private String lang;
|
||||
|
||||
@Schema(description = "键")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "值")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "多语言配置分页查询条件")
|
||||
public class I18nConfigQueryDto {
|
||||
|
||||
@Schema(description = "端,如 Backend")
|
||||
private String side;
|
||||
|
||||
@Schema(description = "语言,如 zh-cn")
|
||||
private String lang;
|
||||
|
||||
@Schema(description = "业务模块,精确匹配")
|
||||
private String module;
|
||||
|
||||
@Schema(description = "配置键 fieldKey,模糊匹配")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "配置值 fieldValue,模糊匹配")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "页码,从 1 开始", example = "1")
|
||||
private Long pageNo;
|
||||
|
||||
@Schema(description = "每页条数", example = "20")
|
||||
private Long pageSize;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.export.I18nConfigRowExportDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 按查询条件全量导出的 JSON 结构(与列表查询条件一致,忽略分页字段)。
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "多语言配置按条件导出")
|
||||
public class I18nConfigQueryExportDto {
|
||||
|
||||
@Schema(description = "与 i18n-config-*.json 中单条结构一致(camelCase)")
|
||||
private List<I18nConfigRowExportDto> configs = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.application.validation.ValidI18nLanguageTag;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 语言创建请求 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "语言创建请求")
|
||||
public class I18nLangAddDto implements Serializable {
|
||||
|
||||
@NotBlank(message = "Language name is required")
|
||||
@Schema(description = "语言名称,例如 简体中文", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "Language tag is required")
|
||||
@ValidI18nLanguageTag
|
||||
@Schema(description = "语言标识(BCP 47),如 zh-CN、en-US", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String lang;
|
||||
|
||||
@Schema(description = "语言状态,0 停用;1 启用", defaultValue = "1")
|
||||
private Integer status = 1;
|
||||
|
||||
@Schema(description = "是否为默认语言,0 否;1 是", defaultValue = "0")
|
||||
private Integer isDefault = 0;
|
||||
|
||||
@Schema(description = "排序,值越小越靠前", defaultValue = "0")
|
||||
private Integer sort = 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 语言信息 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "语言信息")
|
||||
public class I18nLangDto implements Serializable {
|
||||
|
||||
@Schema(description = "语言 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "语言名称,例如 简体中文")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "语言标识,中文:zh-cn,英文:en-us 等等")
|
||||
private String lang;
|
||||
|
||||
@Schema(description = "语言状态,0 停用;1 启用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否为默认语言,0 否;1 是")
|
||||
private Integer isDefault;
|
||||
|
||||
@Schema(description = "排序,值越小越靠前")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 语言排序更新请求 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "语言排序更新请求")
|
||||
public class I18nLangSortDto implements Serializable {
|
||||
|
||||
@NotNull(message = "Sort parameters are required")
|
||||
@Schema(description = "排序参数,key: 语言 ID, value: 排序值", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Map<Long, Integer> sortMap;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 语言更新请求 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "语言更新请求")
|
||||
public class I18nLangUpdateDto implements Serializable {
|
||||
|
||||
@NotNull(message = "Language ID is required")
|
||||
@Schema(description = "语言 ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "语言名称,例如 简体中文")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "语言状态,0 停用;1 启用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否为默认语言,0 否;1 是")
|
||||
private Integer isDefault;
|
||||
|
||||
@Schema(description = "排序,值越小越靠前")
|
||||
private Integer sort;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.NotifyMessageUser;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class NotifyMessageDto implements Serializable {
|
||||
|
||||
@Schema(description = "消息ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "消息内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "消息状态")
|
||||
private NotifyMessageUser.ReadStatus readStatus;
|
||||
|
||||
@Schema(description = "发送者信息")
|
||||
private Sender sender;
|
||||
|
||||
@Schema(description = "创建时间(消息发送时间)")
|
||||
private Date created;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Sender {
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private String nickName;
|
||||
private String avatar;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.NotifyMessageUser;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class NotifyMessageQueryDto implements Serializable {
|
||||
@Schema(description = "用户ID", hidden = true)
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "最后消息ID")
|
||||
private Long lastId;
|
||||
|
||||
@Schema(description = "查询条数")
|
||||
private Integer size;
|
||||
|
||||
@Schema(description = "消息状态")
|
||||
private NotifyMessageUser.ReadStatus readStatus;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.NotifyMessage;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SendNotifyMessageDto implements Serializable {
|
||||
private Long tenantId;
|
||||
@Schema(description = "发送者ID", hidden = true)
|
||||
private Long senderId;
|
||||
|
||||
@Schema(description = "消息内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "消息类型, Broadcast时可以不传userIds")
|
||||
private NotifyMessage.MessageScope scope;
|
||||
|
||||
@Schema(description = "接收者ID列表")
|
||||
private List<Long> userIds;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.Space;
|
||||
import com.xspaceagi.system.infra.dao.entity.SpaceUser;
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@I18n(module = "UserSpace")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SpaceDto implements Serializable {
|
||||
|
||||
@Schema(description = "空间ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "租户ID")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "空间名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "Space name is required")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "空间描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "空间图标")
|
||||
private String icon;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "空间类型")
|
||||
private Space.Type type;
|
||||
|
||||
@Schema(description = "创建者ID")
|
||||
private Long creatorId;
|
||||
|
||||
@Schema(description = "创建者名称")
|
||||
private String creatorName;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "当前登录用户在空间的角色")
|
||||
private SpaceUser.Role currentUserRole;
|
||||
|
||||
@Schema(description = "空间是否接收来自外部的发布")
|
||||
private Integer receivePublish;
|
||||
|
||||
@Schema(description = "空间是否开启开发功能")
|
||||
private Integer allowDevelop;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.SpaceUser;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SpaceUserDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户姓名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "昵称")
|
||||
private String nickName;
|
||||
|
||||
@Schema(description = "头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "空间ID")
|
||||
private Long spaceId;
|
||||
|
||||
@Schema(description = "角色")
|
||||
private SpaceUser.Role role;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
public String getUserName() {
|
||||
return userName == null ? "" : userName;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName == null ? "" : nickName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 语言白名单单项:BCP 47 标识 + 基于 tag 的展示名(JDK CLDR,运行时生成)。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "语言选项(标识 + 展示名)")
|
||||
public class SupportedLocaleOptionDto implements Serializable {
|
||||
|
||||
@Schema(description = "BCP 47 语言标识,如 zh-CN、en-US")
|
||||
private String tag;
|
||||
|
||||
@Schema(description = "根据 tag 自动生成的展示名")
|
||||
private String name;
|
||||
|
||||
public static SupportedLocaleOptionDto fromTag(String tag) {
|
||||
Locale locale = Locale.forLanguageTag(tag);
|
||||
String normalizedTag = locale.toLanguageTag();
|
||||
return new SupportedLocaleOptionDto(
|
||||
normalizedTag,
|
||||
locale.getDisplayName(locale)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TenantAddDto {
|
||||
|
||||
@NotNull(message = "Tenant name is required")
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String logo;
|
||||
|
||||
@NotNull(message = "Tenant domain is required")
|
||||
private String domain;
|
||||
|
||||
@NotNull(message = "Tenant admin username is required")
|
||||
private String userName;
|
||||
|
||||
private String nickName;
|
||||
|
||||
@NotNull(message = "Tenant admin phone is required")
|
||||
private String phone;
|
||||
|
||||
@NotNull(message = "Tenant admin email is required")
|
||||
private String email;
|
||||
|
||||
@NotNull(message = "Tenant admin password is required")
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@I18n(module = "TenantConfig")
|
||||
@Data
|
||||
public class TenantConfigDto implements Serializable {
|
||||
|
||||
@Schema(description = "租户ID", hidden = true)
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "站点名称")
|
||||
private String siteName;
|
||||
|
||||
private String siteUrl;
|
||||
|
||||
@Schema(description = "站点配置地址", hidden = true)
|
||||
private String siteConfigUrl;
|
||||
|
||||
@Schema(description = "站点描述")
|
||||
private String siteDescription;
|
||||
|
||||
@Schema(description = "站点LOGO,为空使用现有默认的")
|
||||
private String siteLogo;
|
||||
|
||||
private String faviconUrl;
|
||||
|
||||
@Schema(description = "登录页文案")
|
||||
private String loginPageText;
|
||||
|
||||
@Schema(description = "登录页副文案")
|
||||
private String loginPageSubText;
|
||||
|
||||
@Schema(description = "广场Banner地址,为空使用现有默认的")
|
||||
private String squareBanner;
|
||||
|
||||
@Schema(description = "广场Banner文案标题")
|
||||
private String squareBannerText;
|
||||
|
||||
@Schema(description = "广场Banner文案副标题")
|
||||
private String squareBannerSubText;
|
||||
|
||||
@Schema(description = "广场Banner链接,如果链接不为空,点击跳转")
|
||||
private String squareBannerLinkUrl;
|
||||
|
||||
@Schema(description = "开启注册, 0 关闭;1 开启,如果为0,前端不展示注册入口")
|
||||
private Integer openRegister;
|
||||
|
||||
@Schema(description = "默认会话总结模型", hidden = true)
|
||||
private Long defaultSummaryModelId;
|
||||
|
||||
@Schema(description = "默认问题建议模型", hidden = true)
|
||||
private Long defaultSuggestModelId;
|
||||
|
||||
@Schema(description = "默认会话模型")
|
||||
private Long defaultChatModelId;
|
||||
|
||||
@Schema(description = "默认嵌入模型")
|
||||
private Long defaultEmbedModelId;
|
||||
|
||||
@Schema(description = "默认知识库模型")
|
||||
private Long defaultKnowledgeModelId;
|
||||
|
||||
@Schema(description = "默认站点问答型Agent")
|
||||
private Long defaultAgentId;
|
||||
|
||||
@Schema(description = "默认站点任务型Agent")
|
||||
private Long defaultTaskAgentId;
|
||||
|
||||
@Schema(description = "首页会话框下的推荐问题")
|
||||
private List<String> homeRecommendQuestions;
|
||||
|
||||
@Schema(description = "默认站点Agent集群", hidden = true)
|
||||
private List<Long> defaultAgentIds;
|
||||
|
||||
@Schema(description = "推荐Agent列表", hidden = true)
|
||||
private List<Long> recommendAgentIds;
|
||||
|
||||
@Schema(description = "官方智能体配置")
|
||||
private List<Long> officialAgentIds;
|
||||
|
||||
@Schema(description = "官方用户名")
|
||||
private String officialUserName;
|
||||
|
||||
@Schema(description = "站点域名")
|
||||
private List<String> domainNames;
|
||||
|
||||
@Schema(description = "最大上传文件大小,例如 100MB")
|
||||
private String maxFileSize;
|
||||
|
||||
private String casClientHostUrl;
|
||||
private String casValidateUrl;
|
||||
private String casLoginUrl;
|
||||
private Integer authType;
|
||||
private Integer agentPublishAudit;
|
||||
private Integer pluginPublishAudit;
|
||||
private Integer workflowPublishAudit;
|
||||
private Integer skillPublishAudit;
|
||||
|
||||
private List<String> userWhiteList;
|
||||
private String codeSafeCheckPrompt;
|
||||
private Integer openCodeSafeCheck;
|
||||
private String globalSystemPrompt;
|
||||
|
||||
private String smtpHost;
|
||||
private Integer smtpPort;
|
||||
private String smtpUsername;
|
||||
private String smtpPassword;
|
||||
|
||||
private String smsAccessKeyId;
|
||||
private String smsAccessKeySecret;
|
||||
private String smsSignName;
|
||||
private String smsTemplateCode;
|
||||
|
||||
private Long authExpire;
|
||||
|
||||
private Integer openCaptcha;
|
||||
private String captchaAccessKeyId;
|
||||
private String captchaAccessKeySecret;
|
||||
private String captchaPrefix;
|
||||
private String captchaSceneId;
|
||||
private String pageFooterText;
|
||||
|
||||
private Integer allowAgentTempChat;
|
||||
private Integer allowAgentApi;
|
||||
private Integer allowMcpExport;
|
||||
private String version;
|
||||
|
||||
private String templateConfig;
|
||||
private String homeSlogan;
|
||||
|
||||
@Schema(description = "默认编码模型")
|
||||
private Long defaultCodingModelId;
|
||||
|
||||
@Schema(description = "默认视觉模型")
|
||||
private Long defaultVisualModelId;
|
||||
|
||||
private String mpAppId;
|
||||
private String mpAppSecret;
|
||||
private String sandboxConfig;
|
||||
private boolean enabledSandbox;
|
||||
private Boolean supportCustomDomain;
|
||||
private String userComputerDefaultSkillIds;
|
||||
private String officialPluginIds;
|
||||
private String officialWorkflowIds;
|
||||
private String officialSkillIds;
|
||||
@Schema(description = "收入分成比例")
|
||||
private Double revenueRatio;
|
||||
@Schema(description = "支付网关地址")
|
||||
private String paymentGateway;
|
||||
@Schema(description = "是否开启订阅模式")
|
||||
private Integer enableSubscription;
|
||||
@Schema(description = "积分兑换比例,比如 1000标识1块钱可以兑换1000积分")
|
||||
private Integer creditExchangeRate;
|
||||
@Schema(description = "积分兑换说明")
|
||||
private String creditExchangeDesc;
|
||||
@Schema(description = "是否开启注册积分赠送")
|
||||
private Integer enableGiftCredit;
|
||||
@Schema(description = "注册赠送积分数")
|
||||
private Integer giftCreditAmount;
|
||||
@Schema(description = "注册赠送积分有效期(天)")
|
||||
private Integer giftCreditExpire;
|
||||
@Schema(description = "是否开启每日登录赠送积分")
|
||||
private Integer enableDailyGiftCredit;
|
||||
@Schema(description = "每日登录赠送积分数")
|
||||
private Integer dailyGiftCreditAmount;
|
||||
private boolean isCommercialEdition;
|
||||
@Schema(description = "模型API根地址")
|
||||
private String baseModelApiUrl;
|
||||
|
||||
public enum AuthTypeEnum {
|
||||
PHONE(1, "手机"),
|
||||
CAS(2, "CAS"),
|
||||
EMAIL(3, "邮箱");
|
||||
private int code;
|
||||
private String desc;
|
||||
|
||||
AuthTypeEnum(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.TenantConfig;
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@I18n(module = "TenantConfig")
|
||||
@Data
|
||||
public class TenantConfigItemDto implements Serializable {
|
||||
|
||||
private Long tenantId;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "配置项名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "配置项值")
|
||||
private Object value;
|
||||
|
||||
@Schema(description = "配置项描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "配置项分类")
|
||||
private TenantConfig.ConfigCategory category;
|
||||
|
||||
@Schema(description = "配置项输入类型")
|
||||
private TenantConfig.InputType inputType;
|
||||
|
||||
@Schema(description = "配置项数据类型")
|
||||
private TenantConfig.DataType dataType;
|
||||
|
||||
@Schema(description = "配置项提示")
|
||||
private String notice;
|
||||
|
||||
@Schema(description = "配置项占位符")
|
||||
private String placeholder;
|
||||
|
||||
@Schema(description = "配置项最小高度")
|
||||
private Integer minHeight;
|
||||
|
||||
@Schema(description = "是否必填")
|
||||
private boolean required;
|
||||
|
||||
@Schema(description = "排序", hidden = true)
|
||||
private Integer sort;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.TenantStatus;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TenantDto implements Serializable {
|
||||
|
||||
@Schema(description = "租户ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "租户名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "租户描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "租户状态")
|
||||
private TenantStatus status;
|
||||
|
||||
@Schema(description = "租户域名")
|
||||
private String domain;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "配置信息")
|
||||
private List<TenantConfigItemDto> tenantConfigs;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.sdk.service.dto.UserAccessKeyDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class UpdateApiKeyDto {
|
||||
|
||||
@Schema(description = "用户ID", hidden = true)
|
||||
private Long userId;
|
||||
@Schema(description = "API Key")
|
||||
private String accessKey;
|
||||
@Schema(description = "状态 0 停用; 1 启用")
|
||||
private Integer status;
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
@Schema(description = "过期时间")
|
||||
private Date expire;
|
||||
@Schema(description = "接口调用频率限制,每分钟调用次数")
|
||||
private List<UserAccessKeyDto.ApiConfig> apiConfigs;
|
||||
|
||||
@Schema(description = "已授权的模型ID列表")
|
||||
private List<Long> modelIds;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
public class UsageDto {
|
||||
@Schema(description = "今日TOKEN使用情况")
|
||||
private Usage todayTokenUsage;
|
||||
@Schema(description = "今日智能体提示使用情况")
|
||||
private Usage todayAgentPromptUsage;
|
||||
@Schema(description = "今日网页应用提示使用情况")
|
||||
private Usage todayPageAppPromptUsage;
|
||||
@Schema(description = "可创建工作空间数量")
|
||||
private Usage newWorkspaceUsage;
|
||||
@Schema(description = "可创建智能体数量")
|
||||
private Usage newAgentUsage;
|
||||
@Schema(description = "可创建网页应用数量")
|
||||
private Usage newPageAppUsage;
|
||||
@Schema(description = "可创建知识库数量")
|
||||
private Usage newKnowledgeBaseUsage;
|
||||
@Schema(description = "知识库存储上限")
|
||||
private Usage knowledgeBaseStorageUsage;
|
||||
@Schema(description = "可创建数据表数量")
|
||||
private Usage newTableUsage;
|
||||
@Schema(description = "可创建定时任务数量")
|
||||
private Usage newTaskUsage;
|
||||
@Schema(description = "智能体电脑最大内存")
|
||||
private Usage sandboxMemoryLimit;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Usage {
|
||||
@Schema(description = "限制")
|
||||
private String limit;
|
||||
@Schema(description = "使用情况")
|
||||
private String usage;
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.User;
|
||||
import com.xspaceagi.system.spec.common.UserContext;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Schema(description = "用户信息")
|
||||
@Data
|
||||
public class UserDto {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户唯一标识")
|
||||
private String uid;
|
||||
|
||||
@Schema(description = "商户ID")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
@Schema(description = "用户头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "用户密码")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "判断用户是否设置过密码,如果未设置过,需要弹出密码设置框让用户设置密码")
|
||||
private Integer resetPass;
|
||||
|
||||
@Schema(description = "用户状态")
|
||||
private User.Status status;
|
||||
|
||||
@Schema(description = "角色")
|
||||
private User.Role role;
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "手机号码")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "最后登录时间")
|
||||
private Date lastLoginTime;
|
||||
|
||||
@Schema(description = "最近的语言环境")
|
||||
private String lang;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "语言环境对应的值,仅类型为System")
|
||||
private Map<String, String> langMap;
|
||||
|
||||
/**
|
||||
* 转换为对象 UserContext,用于上下文
|
||||
*/
|
||||
public static UserContext convertToUserContext(UserDto userDto) {
|
||||
if (Objects.isNull(userDto)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int status = 1;
|
||||
if (userDto.getStatus() != User.Status.Enabled) {
|
||||
status = -1;
|
||||
}
|
||||
|
||||
|
||||
return UserContext.builder()
|
||||
.userId(userDto.getId())
|
||||
.uid(userDto.getUid())
|
||||
.userName(userDto.getUserName())
|
||||
.nickName(userDto.getNickName())
|
||||
.email(userDto.getEmail())
|
||||
.phone(userDto.getPhone())
|
||||
.status(status)
|
||||
.orgId(userDto.getTenantId())
|
||||
.orgName(null)
|
||||
.roleType(null)
|
||||
.langMap(userDto.getLangMap())
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Schema(description = "用户计量信息")
|
||||
@Data
|
||||
public class UserMetricDto {
|
||||
|
||||
@Schema(description = "计量ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "租户ID")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "业务类型")
|
||||
private String bizType;
|
||||
|
||||
@Schema(description = "时段类型")
|
||||
private String periodType;
|
||||
|
||||
@Schema(description = "时段值")
|
||||
private String period;
|
||||
|
||||
@Schema(description = "计量值")
|
||||
private BigDecimal value;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.xspaceagi.system.application.dto;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.User;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class UserQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户姓名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "昵称")
|
||||
private String nickName;
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "手机号码")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "用户状态")
|
||||
private User.Status status;
|
||||
|
||||
@Schema(description = "角色")
|
||||
private User.Role role;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 绑定限制访问对象请求
|
||||
*/
|
||||
@Data
|
||||
public class BindRestrictionTargetsDto implements Serializable {
|
||||
|
||||
@NotNull(message = "subjectId is required")
|
||||
@Schema(description = "主体ID(如模型ID、智能体ID、网页应用智能体ID)")
|
||||
private Long subjectId;
|
||||
|
||||
@Schema(description = "可访问的角色ID列表")
|
||||
private List<Long> roleIds = new ArrayList<>();
|
||||
|
||||
@Schema(description = "可访问的用户组ID列表")
|
||||
private List<Long> groupIds = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import com.xspaceagi.system.spec.enums.OpenTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单树节点
|
||||
*/
|
||||
@I18n(module = "PermissionMenu")
|
||||
@Data
|
||||
@Schema(description = "菜单树节点")
|
||||
public class MenuNodeDto implements Serializable {
|
||||
|
||||
@Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "子菜单绑定类型 0:未绑定 1:全部绑定 2:部分绑定")
|
||||
private Integer menuBindType;
|
||||
|
||||
@I18nField(subObj = true)
|
||||
@Schema(description = "子菜单列表")
|
||||
private List<MenuNodeDto> children;
|
||||
|
||||
@I18nField(subObj = true)
|
||||
@Schema(description = "资源树")
|
||||
private List<ResourceNodeDto> resourceTree;
|
||||
|
||||
@I18nField(subObj = true)
|
||||
@Schema(description = "资源列表", hidden = true)
|
||||
private List<ResourceNodeDto> resourceNodes;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "资源码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* @see OpenTypeEnum
|
||||
*/
|
||||
@Schema(description = "打开方式 1-当前标签页打开 2-新标签页打开")
|
||||
private Integer openType;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "修改人ID")
|
||||
private Long modifierId;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
private String modifier;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date modified;
|
||||
|
||||
/**
|
||||
* 将菜单树扁平化为列表
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
public static List<MenuNodeDto> flattenMenuTree(List<MenuNodeDto> nodes) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<MenuNodeDto> result = new ArrayList<>();
|
||||
for (MenuNodeDto node : nodes) {
|
||||
if (node.getId() == null) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemMenuIdNullWithNodeName, node.getName());
|
||||
} else {
|
||||
// 创建新节点,不包含children
|
||||
MenuNodeDto flatNode = new MenuNodeDto();
|
||||
flatNode.setId(node.getId());
|
||||
flatNode.setMenuBindType(node.getMenuBindType());
|
||||
flatNode.setResourceTree(node.getResourceTree());
|
||||
result.add(flatNode);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
result.addAll(flattenMenuTree(node.getChildren()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import com.xspaceagi.system.spec.enums.ResourceTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@I18n(module = "PermissionResource")
|
||||
@Data
|
||||
@Schema(description = "资源树节点")
|
||||
public class ResourceNodeDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "资源绑定类型 0:未绑定 1:全部绑定 2:部分绑定")
|
||||
private Integer resourceBindType;
|
||||
|
||||
@I18nField(subObj = true)
|
||||
@Schema(description = "子资源列表")
|
||||
private List<ResourceNodeDto> children;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see ResourceTypeEnum
|
||||
*/
|
||||
@Schema(description = "类型 1:模块 2:组件")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建人ID")
|
||||
private Long creatorId;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "修改人ID")
|
||||
private Long modifierId;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
private String modifier;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date modified;
|
||||
|
||||
/**
|
||||
* 资源树扁平化处理
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
public static List<ResourceNodeDto> flattenResourceTree(List<ResourceNodeDto> nodes) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<ResourceNodeDto> result = new ArrayList<>();
|
||||
for (ResourceNodeDto node : nodes) {
|
||||
if (node.getId() != null) {
|
||||
// 创建新节点,不包含children
|
||||
ResourceNodeDto flatNode = new ResourceNodeDto();
|
||||
flatNode.setId(node.getId());
|
||||
flatNode.setResourceBindType(node.getResourceBindType());
|
||||
flatNode.setCode(node.getCode());
|
||||
result.add(flatNode);
|
||||
}
|
||||
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
|
||||
result.addAll(flattenResourceTree(node.getChildren()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 顺序调整项
|
||||
*/
|
||||
@Data
|
||||
public class SortIndexDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父级ID,0表示根节点,不传则不修改(无层级则忽略)")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "排序索引,不传则不修改")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 顺序批量调整请求
|
||||
*/
|
||||
@Data
|
||||
public class SortIndexUpdateDto implements Serializable {
|
||||
|
||||
@Schema(description = "待调整的列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<SortIndexDto> items;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.SysGroup;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysRole;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主体访问权限的目标对象(角色/用户组)
|
||||
*/
|
||||
@Data
|
||||
public class SubjectTargetsDto implements Serializable {
|
||||
|
||||
@Schema(description = "可访问的角色列表")
|
||||
private List<SysRole> roles = new ArrayList<>();
|
||||
|
||||
@Schema(description = "可访问的用户组列表")
|
||||
private List<SysGroup> groups = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.sdk.service.dto.TokenLimit;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "数据权限绑定")
|
||||
public class SysDataPermissionBindDto implements Serializable {
|
||||
|
||||
@Schema(description = "可用的模型ID列表")
|
||||
private List<Long> modelIds;
|
||||
|
||||
@Schema(description = "可访问的智能体id列表,null或空表示不限制")
|
||||
private List<Long> agentIds;
|
||||
|
||||
@Schema(description = "可访问的网页应用智能体id列表,null或空表示不限制")
|
||||
private List<Long> pageAgentIds;
|
||||
|
||||
@Schema(description = "可访问的开放api及访问频率配置")
|
||||
private List<OpenApiConfig> openApiConfigs;
|
||||
|
||||
@Schema(description = "有权限访问的知识库id列表")
|
||||
private List<Long> knowledgeIds;
|
||||
|
||||
@Schema(description = "token限制")
|
||||
private TokenLimit tokenLimit;
|
||||
|
||||
@Schema(description = "可创建工作空间数量,-1表示不限制")
|
||||
private Integer maxSpaceCount;
|
||||
|
||||
@Schema(description = "可创建智能体数量,-1表示不限制")
|
||||
private Integer maxAgentCount;
|
||||
|
||||
@Schema(description = "可创建网页应用数量,-1表示不限制")
|
||||
private Integer maxPageAppCount;
|
||||
|
||||
@Schema(description = "可创建知识库数量,-1表示不限制")
|
||||
private Integer maxKnowledgeCount;
|
||||
|
||||
@Schema(description = "知识库存储空间上限(GB,保留三位小数),-1表示不限制")
|
||||
private BigDecimal knowledgeStorageLimitGb;
|
||||
|
||||
@Schema(description = "可创建数据表数量,-1表示不限制")
|
||||
private Integer maxDataTableCount;
|
||||
|
||||
@Schema(description = "可创建定时任务数量,-1表示不限制")
|
||||
private Integer maxScheduledTaskCount;
|
||||
|
||||
@Schema(description = "智能体电脑CPU核心数,null表示使用默认值2")
|
||||
private Integer agentComputerCpuCores;
|
||||
|
||||
@Schema(description = "智能体电脑内存(GB),null表示使用默认值4")
|
||||
private Integer agentComputerMemoryGb;
|
||||
|
||||
@Schema(description = "智能体电脑交换分区(GB),null表示使用默认值8")
|
||||
private Integer agentComputerSwapGb;
|
||||
|
||||
@Schema(description = "通用智能体执行结果文件存储天数,-1表示不限制")
|
||||
private Integer agentFileStorageDays;
|
||||
|
||||
@Schema(description = "通用智能体每天对话次数,-1表示不限制")
|
||||
private Integer agentDailyPromptLimit;
|
||||
|
||||
@Schema(description = "网页应用开发每天对话次数,-1表示不限制")
|
||||
private Integer pageDailyPromptLimit;
|
||||
|
||||
|
||||
// @Schema(description = "是否允许API外部调用,1-允许,0-不允许")
|
||||
// private Integer allowApiExternalCall;
|
||||
|
||||
@Data
|
||||
@Schema(description = "开放API权限配置")
|
||||
public static class OpenApiConfig implements Serializable {
|
||||
|
||||
@Schema(description = "开放api key")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "接口调用频率限制,每分钟调用次数")
|
||||
private Integer rpm;
|
||||
|
||||
@Schema(description = "接口调用频率限制,每天调用次数")
|
||||
private Integer rpd;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SysGroupAddDto implements Serializable {
|
||||
|
||||
@Schema(description = "编码(可选,如果不传则根据名称自动生成)")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "状态,1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 用户组绑定数据权限 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "用户组绑定数据权限")
|
||||
public class SysGroupBindDataPermissionDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户组ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "数据权限配置")
|
||||
private SysDataPermissionBindDto dataPermission;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户组绑定菜单")
|
||||
@Data
|
||||
public class SysGroupBindMenuDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户组ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "菜单树", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<MenuNodeDto> menuTree;
|
||||
|
||||
/**
|
||||
* 获取所有菜单节点(扁平化列表,包含菜单ID和资源绑定信息)
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
public List<MenuNodeDto> getAllMenuNodes() {
|
||||
return MenuNodeDto.flattenMenuTree(menuTree);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户组绑定用户")
|
||||
@Data
|
||||
public class SysGroupBindUserDto implements Serializable {
|
||||
|
||||
@Schema(description = "组ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private List<Long> userIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Schema(description = "用户组绑定用户(单个)")
|
||||
@Data
|
||||
public class SysGroupBindUserSingleDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户组ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.xspaceagi.system.sdk.service.dto.TokenLimit;
|
||||
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@I18n(module = "PermissionGroup")
|
||||
@Data
|
||||
public class SysGroupDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "状态,1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "创建人ID")
|
||||
private Long creatorId;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "修改人ID")
|
||||
private Long modifierId;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
private String modifier;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date modified;
|
||||
|
||||
@Schema(description = "模型ID列表 全部模型传[-1],未选中任何模型不传值")
|
||||
private List<Long> modelIds;
|
||||
|
||||
@Schema(description = "token限制")
|
||||
private TokenLimit tokenLimit;
|
||||
|
||||
@I18nField(subObj = true)
|
||||
@Schema(description = "子用户组列表")
|
||||
private List<SysGroupDto> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysGroupQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "状态,1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysGroupUpdateDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "状态,1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 根据用户组ID查询用户列表的查询条件
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "用户组用户查询条件")
|
||||
public class SysGroupUserQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户组ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "用户名,可选,模糊查询昵称或用户名")
|
||||
private String userName;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.OpenTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SysMenuAddDto implements Serializable {
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "编码(可选,如果不传则根据名称自动生成)")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* @see OpenTypeEnum
|
||||
*/
|
||||
@Schema(description = "打开方式 1-当前标签页打开 2-新标签页打开")
|
||||
private Integer openType;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "资源树")
|
||||
private List<ResourceNodeDto> resourceTree;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单绑定资源请求
|
||||
*/
|
||||
@Schema(description = "菜单绑定资源")
|
||||
@Data
|
||||
public class SysMenuBindResourceDto implements Serializable {
|
||||
|
||||
@Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long menuId;
|
||||
|
||||
@Schema(description = "资源树")
|
||||
private List<ResourceNodeDto> resourceTree;
|
||||
|
||||
/**
|
||||
* 获取扁平化资源列表
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
public List<ResourceNodeDto> getFlattenlResourceList() {
|
||||
return ResourceNodeDto.flattenResourceTree(resourceTree);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.OpenTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysMenuQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see OpenTypeEnum
|
||||
*/
|
||||
@Schema(description = "打开方式 1-当前标签页打开 2-新标签页打开")
|
||||
private Integer openType;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.OpenTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SysMenuUpdateDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "资源码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* @see OpenTypeEnum
|
||||
*/
|
||||
@Schema(description = "打开方式 1-当前标签页打开 2-新标签页打开")
|
||||
private Integer openType;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "资源树")
|
||||
private List<ResourceNodeDto> resourceTree;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.ResourceTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "资源")
|
||||
@Data
|
||||
public class SysResourceAddDto {
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "编码(可选,如果不传则根据名称自动生成)")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see ResourceTypeEnum
|
||||
*/
|
||||
@Schema(description = "资源类型 1:模块 2:组件 3:页面")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.ResourceTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "资源")
|
||||
@Data
|
||||
public class SysResourceQueryDto {
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see ResourceTypeEnum
|
||||
*/
|
||||
@Schema(description = "资源类型 1:模块 2:组件 3:页面")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.ResourceTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "资源")
|
||||
@Data
|
||||
public class SysResourceUpdateDto {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see ResourceTypeEnum
|
||||
*/
|
||||
@Schema(description = "资源类型 1:模块 2:组件 3:页面")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "访问路径")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "状态 1:启用 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import com.xspaceagi.system.spec.enums.StatusEnum;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SysRoleAddDto implements Serializable {
|
||||
|
||||
@Schema(description = "编码(可选,如果不传则根据名称自动生成)")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see StatusEnum
|
||||
*/
|
||||
@Schema(description = "状态 1:启动 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 角色绑定数据权限 DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "角色绑定数据权限")
|
||||
public class SysRoleBindDataPermissionDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description = "数据权限配置")
|
||||
private SysDataPermissionBindDto dataPermission;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "角色菜单绑定")
|
||||
@Data
|
||||
public class SysRoleBindMenuDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description = "菜单树形结构", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<MenuNodeDto> menuTree;
|
||||
|
||||
/**
|
||||
* 获取扁平化菜单列表(包含菜单ID和资源绑定信息)
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
public List<MenuNodeDto> getFlattenlMenuNodes() {
|
||||
return MenuNodeDto.flattenMenuTree(menuTree);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "角色绑定用户")
|
||||
@Data
|
||||
public class SysRoleBindUserDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private List<Long> userIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "角色绑定用户")
|
||||
@Data
|
||||
public class SysRoleBindUserSingleDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.annotation.I18n;
|
||||
import com.xspaceagi.system.spec.annotation.I18nField;
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import com.xspaceagi.system.spec.enums.StatusEnum;
|
||||
import com.xspaceagi.system.sdk.service.dto.TokenLimit;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@I18n(module = "PermissionRole")
|
||||
@Data
|
||||
public class SysRoleDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@I18nField(keyPrefix = true)
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see StatusEnum
|
||||
*/
|
||||
@Schema(description = "状态 1:启动 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
|
||||
@Schema(description = "模型ID列表 全部模型传[-1],未选中任何模型不传值")
|
||||
private List<Long> modelIds;
|
||||
|
||||
@Schema(description = "token限制")
|
||||
private TokenLimit tokenLimit;
|
||||
|
||||
@Schema(description = "创建人ID")
|
||||
private Long creatorId;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date created;
|
||||
|
||||
@Schema(description = "修改人ID")
|
||||
private Long modifierId;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
private String modifier;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date modified;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import com.xspaceagi.system.spec.enums.StatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysRoleQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see StatusEnum
|
||||
*/
|
||||
@Schema(description = "状态 1:启动 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.SourceEnum;
|
||||
import com.xspaceagi.system.spec.enums.StatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysRoleUpdateDto implements Serializable {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @see SourceEnum
|
||||
*/
|
||||
@Schema(description = "来源 1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
/**
|
||||
* @see StatusEnum
|
||||
*/
|
||||
@Schema(description = "状态 1:启动 0:禁用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 根据角色ID查询用户列表的查询条件
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "角色用户查询条件")
|
||||
public class SysRoleUserQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description = "用户名,可选,模糊查询昵称或用户名")
|
||||
private String userName;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户绑定用户组")
|
||||
@Data
|
||||
public class SysUserBindGroupDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "组ID")
|
||||
private List<Long> groupIds;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户绑定角色")
|
||||
@Data
|
||||
public class SysUserBindRoleDto implements Serializable {
|
||||
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "角色ID")
|
||||
private List<Long> roleIds;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "用户信息")
|
||||
@Data
|
||||
public class SysUserDto {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
@Schema(description = "用户头像")
|
||||
private String avatar;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import com.xspaceagi.system.sdk.service.dto.TokenLimit;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 数据权限导出DTO(targetCode表示角色或用户组code)
|
||||
*/
|
||||
@Data
|
||||
public class DataPermissionExportDto {
|
||||
|
||||
private Integer targetType;
|
||||
private String targetCode;
|
||||
private TokenLimit tokenLimit;
|
||||
private Integer maxSpaceCount;
|
||||
private Integer maxAgentCount;
|
||||
private Integer maxPageAppCount;
|
||||
private Integer maxKnowledgeCount;
|
||||
private BigDecimal knowledgeStorageLimitGb;
|
||||
private Integer maxDataTableCount;
|
||||
private Integer maxScheduledTaskCount;
|
||||
private Integer agentComputerCpuCores;
|
||||
private Integer agentComputerMemoryGb;
|
||||
private Integer agentComputerSwapGb;
|
||||
private Integer agentFileStorageDays;
|
||||
private Integer agentDailyPromptLimit;
|
||||
private Integer pageDailyPromptLimit;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户组导出DTO(code关联,无id)
|
||||
*/
|
||||
@Data
|
||||
public class GroupExportDto {
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
private String description;
|
||||
private Integer maxUserCount;
|
||||
private Integer source;
|
||||
private Integer status;
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户组菜单关联导出DTO(code关联)
|
||||
*/
|
||||
@Data
|
||||
public class GroupMenuExportDto {
|
||||
|
||||
private String groupCode;
|
||||
private String menuCode;
|
||||
private Integer menuBindType;
|
||||
|
||||
/**
|
||||
* 资源树(code版),用于导入时根据目标租户的resource code->id 映射重写
|
||||
*/
|
||||
private List<ResourceNodeExportDto> resourceTree;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* i18n 配置版本比对结果
|
||||
*/
|
||||
@Data
|
||||
public class I18nConfigDiffSplitDto {
|
||||
|
||||
private List<I18nConfigRowExportDto> addRows = new ArrayList<>();
|
||||
|
||||
private List<I18nConfigRowExportDto> updateRows = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class I18nConfigExportDto {
|
||||
|
||||
/**
|
||||
* 版本号,与app.version对应,如 1.0.5
|
||||
*/
|
||||
private String version;
|
||||
|
||||
private List<I18nConfigRowExportDto> configs = new ArrayList<>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 与 resources/i18n/i18n-config-*.json 中单条结构一致(fieldKey、fieldValue、dataId 等 camelCase)。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.ALWAYS)
|
||||
public class I18nConfigRowExportDto {
|
||||
|
||||
private String type;
|
||||
|
||||
private String side;
|
||||
|
||||
private String module;
|
||||
|
||||
private String dataId;
|
||||
|
||||
private String lang;
|
||||
|
||||
private String fieldKey;
|
||||
|
||||
private String fieldValue;
|
||||
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 菜单导出DTO(code关联,无id)
|
||||
*/
|
||||
@Data
|
||||
public class MenuExportDto {
|
||||
|
||||
private String parentCode;
|
||||
private String code;
|
||||
private String name;
|
||||
private String description;
|
||||
private Integer source;
|
||||
private String path;
|
||||
private Integer openType;
|
||||
private String icon;
|
||||
private Integer sortIndex;
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 菜单资源关联导出DTO(code关联)
|
||||
*/
|
||||
@Data
|
||||
public class MenuResourceExportDto {
|
||||
|
||||
private String menuCode;
|
||||
private String resourceCode;
|
||||
private Integer resourceBindType;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限数据导出根DTO(版本化管理,随代码发布)
|
||||
*/
|
||||
@Data
|
||||
public class PermissionExportDto {
|
||||
|
||||
/**
|
||||
* 版本号,与app.version对应,如 1.0.5
|
||||
*/
|
||||
private String version;
|
||||
|
||||
private List<ResourceExportDto> resources = new ArrayList<>();
|
||||
private List<MenuExportDto> menus = new ArrayList<>();
|
||||
private List<RoleExportDto> roles = new ArrayList<>();
|
||||
private List<GroupExportDto> groups = new ArrayList<>();
|
||||
private List<MenuResourceExportDto> menuResources = new ArrayList<>();
|
||||
private List<RoleMenuExportDto> roleMenus = new ArrayList<>();
|
||||
private List<GroupMenuExportDto> groupMenus = new ArrayList<>();
|
||||
private List<DataPermissionExportDto> dataPermissions = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源导出DTO(code关联,无id)
|
||||
*/
|
||||
@Data
|
||||
public class ResourceExportDto {
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
private String description;
|
||||
private Integer source;
|
||||
private Integer type;
|
||||
private String parentCode;
|
||||
private String path;
|
||||
private String icon;
|
||||
private Integer sortIndex;
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源树节点导出DTO(使用code替代id,用于resource_tree_json)
|
||||
*/
|
||||
@Data
|
||||
public class ResourceNodeExportDto {
|
||||
|
||||
private String code;
|
||||
private Integer resourceBindType;
|
||||
private List<ResourceNodeExportDto> children;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 角色导出DTO(code关联,无id)
|
||||
*/
|
||||
@Data
|
||||
public class RoleExportDto {
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
private String description;
|
||||
private Integer source;
|
||||
private Integer status;
|
||||
private Integer sortIndex;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.system.application.dto.permission.export;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色菜单关联导出DTO(code关联)
|
||||
*/
|
||||
@Data
|
||||
public class RoleMenuExportDto {
|
||||
|
||||
private String roleCode;
|
||||
private String menuCode;
|
||||
private Integer menuBindType;
|
||||
|
||||
/**
|
||||
* 资源树(code版),用于导入时根据目标租户的resource code->id 映射重写
|
||||
*/
|
||||
private List<ResourceNodeExportDto> resourceTree;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Application layer.
|
||||
*/
|
||||
package com.xspaceagi.system.application;
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
|
||||
import com.xspaceagi.system.application.dto.UserDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AuthService {
|
||||
|
||||
String createToken(UserDto userDto, String clientId);
|
||||
|
||||
String loginWithCode(String emailOrPhone, String code);
|
||||
|
||||
String loginWithMpCode(String code);
|
||||
|
||||
String loginWithPassword(String emailOrPhone, String password);
|
||||
|
||||
UserDto getLoginUserInfo(String token);
|
||||
|
||||
String refreshToken(String token);
|
||||
|
||||
void expireToken(String token);
|
||||
|
||||
void renewToken(String token);
|
||||
|
||||
void expireUserAllToken(Long userId);
|
||||
|
||||
void expireUserAllToken(Long userId, String clientIdPrefix);
|
||||
|
||||
String getClientId(Long userId, String token);
|
||||
|
||||
List<String> getUserClientIds(Long userId);
|
||||
|
||||
String newTicket(UserDto userDto, String token);
|
||||
|
||||
String getTokenByTicket(String ticket);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.Category;
|
||||
import com.xspaceagi.system.spec.common.UserContext;
|
||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
||||
|
||||
/**
|
||||
* 分类管理应用服务
|
||||
*/
|
||||
public interface CategoryApplicationService {
|
||||
|
||||
/**
|
||||
* 创建分类
|
||||
*/
|
||||
ReqResult<Category> create(Category category, UserContext userContext);
|
||||
|
||||
/**
|
||||
* 更新分类
|
||||
*/
|
||||
ReqResult<Category> update(Category category, UserContext userContext);
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
*/
|
||||
ReqResult<Void> delete(Long id, UserContext userContext);
|
||||
|
||||
/**
|
||||
* 根据ID查询分类
|
||||
*/
|
||||
Category getById(Long id);
|
||||
|
||||
/**
|
||||
* 根据类型查询分类列表
|
||||
*/
|
||||
List<Category> listByType(String type);
|
||||
|
||||
/**
|
||||
* 根据租户ID查询分类列表
|
||||
*/
|
||||
List<Category> listByTenantId(Long tenantId);
|
||||
|
||||
/**
|
||||
* 根据类型和租户ID查询分类列表
|
||||
*/
|
||||
List<Category> listByTypeAndTenantId(String type, Long tenantId);
|
||||
|
||||
/**
|
||||
* 根据编码查询分类
|
||||
*/
|
||||
Category getByCode(String code);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.xspaceagi.system.application.dto.I18nConfigDto;
|
||||
import com.xspaceagi.system.application.dto.I18nConfigQueryDto;
|
||||
import com.xspaceagi.system.application.dto.I18nConfigQueryExportDto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface I18nApplicationService {
|
||||
|
||||
List<I18nConfigDto> queryI18nConfigList(Long tenantId, String type, String side, String module, String dataId, String lang);
|
||||
|
||||
IPage<I18nConfigDto> queryI18nConfigPage(Long tenantId, I18nConfigQueryDto query);
|
||||
|
||||
I18nConfigQueryExportDto exportI18nConfig(Long tenantId, I18nConfigQueryDto query);
|
||||
|
||||
Map<String, String> querySystemLangMap(Long tenantId, String side, String lang);
|
||||
|
||||
void addOrUpdateI18nConfig(I18nConfigDto I18nConfigDto);
|
||||
|
||||
void batchAddOrUpdateI18nConfig(List<I18nConfigDto> I18nConfigDtos);
|
||||
|
||||
void batchDeleteI18nConfig(List<I18nConfigDto> i18nConfigDtos);
|
||||
|
||||
void translateForKey(Long tenantId, I18nConfigDto i18nConfigDto, String sourceLang, String targetLang);
|
||||
|
||||
void translateForKeysBatch(Long tenantId, List<I18nConfigDto> sourceItems, String sourceLang, String targetLang);
|
||||
|
||||
/**
|
||||
* 按 key 列表从源语言翻译到目标语言并写入目标语言配置
|
||||
*/
|
||||
void translateForKeys(Long tenantId, List<String> keys, String sourceLang, String targetLang);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.export.I18nConfigDiffSplitDto;
|
||||
|
||||
/**
|
||||
* i18n 配置差异比对服务
|
||||
*/
|
||||
public interface I18nConfigDiffService {
|
||||
|
||||
/**
|
||||
* 比对两个版本的 i18n 配置 JSON(fromVersion → toVersion),分别输出新增行与变更行。
|
||||
*/
|
||||
I18nConfigDiffSplitDto generateDiff(String fromVersion, String toVersion);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import com.xspaceagi.system.application.dto.permission.export.I18nConfigExportDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface I18nExportService {
|
||||
|
||||
/**
|
||||
* 从默认租户(tenant_id=1)导出 i18n 配置。
|
||||
*/
|
||||
I18nConfigExportDto exportConfig(String version, List<String> langs);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import com.xspaceagi.system.infra.dao.entity.Tenant;
|
||||
|
||||
/**
|
||||
* 权限数据导入服务
|
||||
*/
|
||||
public interface I18nImportService {
|
||||
|
||||
/**
|
||||
* 将指定版本的配置项导入到目标租户
|
||||
*/
|
||||
void importConfigToTenant(Tenant tenant, String version);
|
||||
|
||||
/**
|
||||
* 将指定版本的语言包导入到目标租户
|
||||
*/
|
||||
void importLangToTenant(Tenant tenant, String version);
|
||||
|
||||
/**
|
||||
* 将指定版本的新增差异配置导入到目标租户(仅插入,已存在则跳过)
|
||||
*/
|
||||
void addConfigToTenant(Tenant tenant, String version);
|
||||
|
||||
/**
|
||||
* 将指定版本的变更差异配置更新到目标租户(仅更新,不存在则跳过)
|
||||
*/
|
||||
void updateConfigToTenant(Tenant tenant, String version);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import com.xspaceagi.system.application.dto.I18nLangAddDto;
|
||||
import com.xspaceagi.system.application.dto.I18nLangDto;
|
||||
import com.xspaceagi.system.application.dto.I18nLangUpdateDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 语言应用服务
|
||||
*/
|
||||
public interface I18nLangApplicationService {
|
||||
|
||||
/**
|
||||
* 新增语言
|
||||
*
|
||||
* @param addDto 语言信息
|
||||
* @return 语言 ID
|
||||
*/
|
||||
Long add(I18nLangAddDto addDto);
|
||||
|
||||
/**
|
||||
* 删除语言
|
||||
*
|
||||
* @param id 语言 ID
|
||||
*/
|
||||
void delete(Long id);
|
||||
|
||||
/**
|
||||
* 更新语言
|
||||
*
|
||||
* @param updateDto 语言信息
|
||||
*/
|
||||
void update(I18nLangUpdateDto updateDto);
|
||||
|
||||
/**
|
||||
* 设置为默认语言
|
||||
*
|
||||
* @param id 语言 ID
|
||||
*/
|
||||
void setDefault(Long id);
|
||||
|
||||
/**
|
||||
* 查询全部语言
|
||||
*
|
||||
* @return 语言列表
|
||||
*/
|
||||
List<I18nLangDto> queryAll();
|
||||
|
||||
/**
|
||||
* 批量更新排序
|
||||
*
|
||||
* @param sortList key: 语言 ID, value: 排序值
|
||||
*/
|
||||
void updateSort(List<I18nLangDto> sortList);
|
||||
|
||||
/**
|
||||
* 根据 ID 查询语言
|
||||
*
|
||||
* @param id 语言 ID
|
||||
* @return 语言信息
|
||||
*/
|
||||
I18nLangDto queryById(Long id);
|
||||
|
||||
/**
|
||||
* 获取默认语言
|
||||
*
|
||||
* @return 默认语言信息
|
||||
*/
|
||||
I18nLangDto getDefault(Long tenantId);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xspaceagi.system.application.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 使用租户默认对话模型将翻译
|
||||
*/
|
||||
public interface I18nLlmTranslator {
|
||||
|
||||
String translate(String text, String sourceLangTag, String targetLangTag);
|
||||
|
||||
Map<String, String> translateBatch(Map<String, String> textByKey, String sourceLangTag, String targetLangTag);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user