From 611366735946c2ec6dcc0ab92f9c0686259c2e5e Mon Sep 17 00:00:00 2001 From: ccmjga Date: Mon, 2 Jun 2025 10:54:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9B=B4=E5=A4=9A=E7=9A=84?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E6=93=8D=E4=BD=9C=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/DepartmentOperatorTool.java | 19 ++ .../mjga/component/PositionOperatorTool.java | 35 ++++ .../zl/mjga/component/UserOperatorTool.java | 43 ----- .../UserRolePermissionOperatorTool.java | 171 ++++++++++++++++++ .../zl/mjga/config/ai/ToolsInitializer.java | 8 +- .../zl/mjga/dto/position/PositionRespDto.java | 1 - 6 files changed, 230 insertions(+), 47 deletions(-) create mode 100644 backend/src/main/java/com/zl/mjga/component/PositionOperatorTool.java delete mode 100644 backend/src/main/java/com/zl/mjga/component/UserOperatorTool.java create mode 100644 backend/src/main/java/com/zl/mjga/component/UserRolePermissionOperatorTool.java diff --git a/backend/src/main/java/com/zl/mjga/component/DepartmentOperatorTool.java b/backend/src/main/java/com/zl/mjga/component/DepartmentOperatorTool.java index bb43b16..3052bf1 100644 --- a/backend/src/main/java/com/zl/mjga/component/DepartmentOperatorTool.java +++ b/backend/src/main/java/com/zl/mjga/component/DepartmentOperatorTool.java @@ -35,4 +35,23 @@ public class DepartmentOperatorTool { } departmentService.upsertDepartment(new Department(null, departmentName, null)); } + + @Tool(value = "更新部门/绑定上级部门/解绑上级部门") + void updateDepartment( + @P(value = "部门名称") String departmentName, + @P(value = "上级部门名称", required = false) String parentDepartmentName) { + Department exist = departmentRepository.fetchOneByName(departmentName); + if (exist == null) { + throw new BusinessException("不存在的部门"); + } + Department department = new Department(null, departmentName, null); + if (StringUtils.isNotEmpty(parentDepartmentName)) { + Department parent = departmentRepository.fetchOneByName(parentDepartmentName); + if (parent == null) { + throw new BusinessException("上级部门不存在"); + } + department.setParentId(parent.getId()); + } + departmentService.upsertDepartment(department); + } } diff --git a/backend/src/main/java/com/zl/mjga/component/PositionOperatorTool.java b/backend/src/main/java/com/zl/mjga/component/PositionOperatorTool.java new file mode 100644 index 0000000..1888396 --- /dev/null +++ b/backend/src/main/java/com/zl/mjga/component/PositionOperatorTool.java @@ -0,0 +1,35 @@ +package com.zl.mjga.component; + +import com.zl.mjga.exception.BusinessException; +import com.zl.mjga.repository.PositionRepository; +import dev.langchain4j.agent.tool.P; +import dev.langchain4j.agent.tool.Tool; +import dev.langchain4j.model.output.structured.Description; +import lombok.RequiredArgsConstructor; +import org.jooq.generated.mjga.tables.pojos.Position; +import org.springframework.stereotype.Component; + +@Description("和岗位管理有关的操作工具") +@RequiredArgsConstructor +@Component +public class PositionOperatorTool { + private final PositionRepository positionRepository; + + @Tool(value = "创建岗位") + void createPosition(@P("岗位名称") String positionName) { + Position position = positionRepository.fetchOneByName(positionName); + if (position != null) { + throw new BusinessException("岗位已存在"); + } + positionRepository.merge(new Position(null, positionName)); + } + + @Tool(value = "删除岗位") + void deletePosition(@P("岗位名称") String positionName) { + Position position = positionRepository.fetchOneByName(positionName); + if (position == null) { + throw new BusinessException("岗位不存在"); + } + positionRepository.deleteById(position.getId()); + } +} diff --git a/backend/src/main/java/com/zl/mjga/component/UserOperatorTool.java b/backend/src/main/java/com/zl/mjga/component/UserOperatorTool.java deleted file mode 100644 index 4f29ddc..0000000 --- a/backend/src/main/java/com/zl/mjga/component/UserOperatorTool.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.zl.mjga.component; - -import com.zl.mjga.dto.urp.UserUpsertDto; -import com.zl.mjga.exception.BusinessException; -import com.zl.mjga.repository.UserRepository; -import com.zl.mjga.service.IdentityAccessService; -import dev.langchain4j.agent.tool.P; -import dev.langchain4j.agent.tool.Tool; -import dev.langchain4j.model.output.structured.Description; -import lombok.RequiredArgsConstructor; -import org.jooq.generated.mjga.tables.pojos.User; -import org.springframework.stereotype.Component; - -@Description("和用户管理有关的操作工具") -@RequiredArgsConstructor -@Component -public class UserOperatorTool { - - private final IdentityAccessService identityAccessService; - private final UserRepository userRepository; - - @Tool(value = "创建用户或注册用户") - void createUser(@P(value = "用户名") String username) { - User user = userRepository.fetchOneByUsername(username); - if (user != null) { - throw new BusinessException("用户已存在"); - } - identityAccessService.upsertUser(new UserUpsertDto(null, username, username, true)); - } - - @Tool(value = "删除用户") - void deleteUser(@P(value = "用户名") String username) { - userRepository.deleteByUsername(username); - } - - @Tool(value = "编辑/更新/更改用户") - void updateUser( - @P(value = "用户名") String username, - @P(value = "密码", required = false) String password, - @P(value = "是否开启", required = false) Boolean enable) { - identityAccessService.upsertUser(new UserUpsertDto(null, username, password, enable)); - } -} diff --git a/backend/src/main/java/com/zl/mjga/component/UserRolePermissionOperatorTool.java b/backend/src/main/java/com/zl/mjga/component/UserRolePermissionOperatorTool.java new file mode 100644 index 0000000..0123fb9 --- /dev/null +++ b/backend/src/main/java/com/zl/mjga/component/UserRolePermissionOperatorTool.java @@ -0,0 +1,171 @@ +package com.zl.mjga.component; + +import com.zl.mjga.dto.urp.PermissionUpsertDto; +import com.zl.mjga.dto.urp.RoleUpsertDto; +import com.zl.mjga.dto.urp.UserUpsertDto; +import com.zl.mjga.exception.BusinessException; +import com.zl.mjga.repository.PermissionRepository; +import com.zl.mjga.repository.RoleRepository; +import com.zl.mjga.repository.UserRepository; +import com.zl.mjga.service.IdentityAccessService; +import dev.langchain4j.agent.tool.P; +import dev.langchain4j.agent.tool.Tool; +import dev.langchain4j.model.output.structured.Description; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.jooq.generated.mjga.tables.pojos.Permission; +import org.jooq.generated.mjga.tables.pojos.Role; +import org.jooq.generated.mjga.tables.pojos.User; +import org.springframework.stereotype.Component; + +@Description("和用户管理有关的操作工具") +@RequiredArgsConstructor +@Component +public class UserRolePermissionOperatorTool { + + private final IdentityAccessService identityAccessService; + private final UserRepository userRepository; + private final RoleRepository roleRepository; + private final PermissionRepository permissionRepository; + + @Tool(value = "创建用户或注册用户") + void createUser(@P(value = "用户名") String username) { + User user = userRepository.fetchOneByUsername(username); + if (user != null) { + throw new BusinessException("用户已存在"); + } + identityAccessService.upsertUser(new UserUpsertDto(null, username, username, true)); + } + + @Tool(value = "删除用户") + void deleteUser(@P(value = "用户名") String username) { + userRepository.deleteByUsername(username); + } + + @Tool(value = "编辑/更新/更改用户") + void updateUser( + @P(value = "用户名") String username, + @P(value = "密码", required = false) String password, + @P(value = "是否开启", required = false) Boolean enable) { + identityAccessService.upsertUser(new UserUpsertDto(null, username, password, enable)); + } + + @Tool(value = "给用户绑定/分配角色") + void bindRoleToUser( + @P(value = "用户名") String username, @P(value = "角色名称") List roleNames) { + User user = userRepository.fetchOneByUsername(username); + if (user == null) { + throw new BusinessException("指定用户不存在"); + } + List bindRoleIds = getRoleIdsBy(roleNames); + identityAccessService.bindRoleToUser(user.getId(), bindRoleIds); + } + + @Tool(value = "给用户解绑/撤销角色") + void unbindRoleToUser( + @P(value = "用户名") String username, @P(value = "角色名称") List roleNames) { + User user = userRepository.fetchOneByUsername(username); + if (user == null) { + throw new BusinessException("指定用户不存在"); + } + List bindRoleIds = getRoleIdsBy(roleNames); + identityAccessService.unBindRoleToUser(user.getId(), bindRoleIds); + } + + private List getRoleIdsBy(List roleNames) { + List roles = roleRepository.fetchByName(roleNames.toArray(String[]::new)); + if (roles.isEmpty()) { + throw new BusinessException("指定角色不存在"); + } + return roles.stream().map(Role::getId).toList(); + } + + @Tool(value = "创建角色") + void createRole( + @P(value = "角色名称") String roleName, @P(value = "角色编码", required = false) String roleCode) { + if (StringUtils.isEmpty(roleCode)) { + roleCode = roleName; + } + if (identityAccessService.isRoleDuplicate(roleCode, roleName)) { + throw new BusinessException("角色已存在"); + } + identityAccessService.upsertRole(new RoleUpsertDto(null, roleName, roleCode)); + } + + @Tool(value = "更新角色") + void updateRole(@P(value = "角色名称") String roleName, @P(value = "角色编码") String roleCode) { + identityAccessService.upsertRole(new RoleUpsertDto(null, roleName, roleCode)); + } + + @Tool(value = "更新权限") + void updatePermission( + @P(value = "权限名称") String permissionName, @P(value = "权限编码") String permissionCode) { + identityAccessService.upsertPermission( + new PermissionUpsertDto(null, permissionName, permissionCode)); + } + + @Tool(value = "删除角色") + void deleteRole(@P(value = "角色名称") String roleName) { + Role role = roleRepository.fetchOneByName(roleName); + if (role == null) { + throw new BusinessException("指定角色不存在"); + } + roleRepository.deleteById(role.getId()); + } + + @Tool(value = "删除权限") + void deletePermission(@P(value = "权限名称") String permissionName) { + Permission permission = permissionRepository.fetchOneByName(permissionName); + if (permission == null) { + throw new BusinessException("指定权限不存在"); + } + permissionRepository.deleteById(permission.getId()); + } + + @Tool(value = "给角色绑定/分配权限") + void bindPermissionToRole( + @P(value = "角色名称") String roleName, @P(value = "权限名称") List permissionNames) { + Role role = roleRepository.fetchOneByName(roleName); + if (role == null) { + throw new BusinessException("指定角色不存在"); + } + List permissions = + permissionRepository.fetchByName(permissionNames.toArray(String[]::new)); + if (permissions.isEmpty()) { + throw new BusinessException("指定权限不存在"); + } + identityAccessService.bindPermissionBy( + role.getId(), permissions.stream().map(Permission::getId).toList()); + } + + @Tool(value = "给角色解绑/撤销权限") + void unBindPermissionToRole( + @P(value = "角色名称") String roleName, @P(value = "权限名称") List permissionNames) { + Role role = roleRepository.fetchOneByName(roleName); + if (role == null) { + throw new BusinessException("指定角色不存在"); + } + List permissions = + permissionRepository.fetchByName(permissionNames.toArray(String[]::new)); + if (permissions.isEmpty()) { + throw new BusinessException("指定权限不存在"); + } + identityAccessService.unBindPermissionBy( + role.getId(), permissions.stream().map(Permission::getId).toList()); + } + + @Tool(value = "创建权限") + void createPermission( + @P(value = "权限名称") String permissionName, + @P(value = "权限编码", required = false) String permissionCode) { + if (StringUtils.isEmpty(permissionCode)) { + permissionCode = permissionName; + } + if (identityAccessService.isPermissionDuplicate(permissionName, permissionName)) { + throw new BusinessException("权限已存在"); + } + identityAccessService.upsertPermission( + new PermissionUpsertDto(null, permissionName, permissionCode)); + } +} diff --git a/backend/src/main/java/com/zl/mjga/config/ai/ToolsInitializer.java b/backend/src/main/java/com/zl/mjga/config/ai/ToolsInitializer.java index 601d61b..9c9db26 100644 --- a/backend/src/main/java/com/zl/mjga/config/ai/ToolsInitializer.java +++ b/backend/src/main/java/com/zl/mjga/config/ai/ToolsInitializer.java @@ -1,7 +1,8 @@ package com.zl.mjga.config.ai; import com.zl.mjga.component.DepartmentOperatorTool; -import com.zl.mjga.component.UserOperatorTool; +import com.zl.mjga.component.PositionOperatorTool; +import com.zl.mjga.component.UserRolePermissionOperatorTool; import dev.langchain4j.community.model.zhipu.ZhipuAiStreamingChatModel; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.service.AiServices; @@ -14,8 +15,9 @@ import org.springframework.context.annotation.DependsOn; @RequiredArgsConstructor public class ToolsInitializer { - private final UserOperatorTool userOperatorTool; + private final UserRolePermissionOperatorTool userRolePermissionOperatorTool; private final DepartmentOperatorTool departmentOperatorTool; + private final PositionOperatorTool positionOperatorTool; @Bean @DependsOn("flywayInitializer") @@ -23,7 +25,7 @@ public class ToolsInitializer { return AiServices.builder(SystemToolAssistant.class) .streamingChatModel(zhipuChatModel) .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(10)) - .tools(userOperatorTool, departmentOperatorTool) + .tools(userRolePermissionOperatorTool, departmentOperatorTool, positionOperatorTool) .build(); } } diff --git a/backend/src/main/java/com/zl/mjga/dto/position/PositionRespDto.java b/backend/src/main/java/com/zl/mjga/dto/position/PositionRespDto.java index d9f32cd..1f8a94e 100644 --- a/backend/src/main/java/com/zl/mjga/dto/position/PositionRespDto.java +++ b/backend/src/main/java/com/zl/mjga/dto/position/PositionRespDto.java @@ -14,6 +14,5 @@ import lombok.NoArgsConstructor; public class PositionRespDto { @NotNull private Long id; @NotEmpty private String name; - private Long parentId; private Boolean isBound; }