From f8f44c6b3692d14cc4a1df02875d16ac7bfad4f6 Mon Sep 17 00:00:00 2001 From: geht Date: Fri, 3 Apr 2026 12:11:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A9=E5=B1=95AI=E5=8A=A9=E6=89=8B=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=96=B0=E5=A2=9E7=E4=B8=AA=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=B7=A5=E5=85=B7=EF=BC=8C=E6=B6=89=E5=8F=8A=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E7=AE=A1=E7=90=86=E3=80=81=E6=97=A5=E5=BF=97=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=92=8C=E6=95=B0=E6=8D=AE=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/airag/JeecgBizToolsProvider.java | 434 ++++++++++++++++++ 1 file changed, 434 insertions(+) diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/airag/JeecgBizToolsProvider.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/airag/JeecgBizToolsProvider.java index a45e274..98c076d 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/airag/JeecgBizToolsProvider.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/airag/JeecgBizToolsProvider.java @@ -18,6 +18,11 @@ import org.jeecg.modules.system.controller.SysUserController; import org.jeecg.modules.system.entity.SysRole; import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.mapper.SysUserMapper; +import org.jeecg.modules.system.entity.SysPermission; +import org.jeecg.modules.system.service.ISysPermissionService; +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.modules.system.entity.SysLog; +import org.jeecg.modules.system.service.ISysLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -25,6 +30,7 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.jeecg.common.util.DateUtils; /** * for [QQYUN-13565]【AI助手】新增创建用户和查询用户的工具扩展 @@ -50,6 +56,12 @@ public class JeecgBizToolsProvider implements JeecgToolsProvider { @Autowired private org.jeecg.modules.system.service.ISysUserService sysUserService; + @Autowired + private ISysPermissionService sysPermissionService; + + @Autowired + private ISysLogService sysLogService; + public Map getDefaultTools(){ Map tools = new HashMap<>(); JeecgLlmTools userTool = queryUserTool(); @@ -62,6 +74,27 @@ public class JeecgBizToolsProvider implements JeecgToolsProvider { // 新增:给用户授予角色 JeecgLlmTools grantRoles = grantUserRolesTool(); tools.put(grantRoles.getToolSpecification(), grantRoles.getToolExecutor()); + // 新增:查询菜单 + JeecgLlmTools queryMenus = queryMenusTool(); + tools.put(queryMenus.getToolSpecification(), queryMenus.getToolExecutor()); + // 新增:添加菜单 + JeecgLlmTools addMenu = addMenuTool(); + tools.put(addMenu.getToolSpecification(), addMenu.getToolExecutor()); + // 新增:编辑菜单 + JeecgLlmTools editMenu = editMenuTool(); + tools.put(editMenu.getToolSpecification(), editMenu.getToolExecutor()); + // 新增:删除菜单 + JeecgLlmTools deleteMenu = deleteMenuTool(); + tools.put(deleteMenu.getToolSpecification(), deleteMenu.getToolExecutor()); + // 新增:查询系统日志 + JeecgLlmTools queryLogs = queryLogsTool(); + tools.put(queryLogs.getToolSpecification(), queryLogs.getToolExecutor()); + // 新增:分析用户使用情况 + JeecgLlmTools analyzeUserUsage = analyzeUserUsageTool(); + tools.put(analyzeUserUsage.getToolSpecification(), analyzeUserUsage.getToolExecutor()); + // 新增:分析操作情况 + JeecgLlmTools analyzeOperations = analyzeOperationsTool(); + tools.put(analyzeOperations.getToolSpecification(), analyzeOperations.getToolExecutor()); return tools; } @@ -267,4 +300,405 @@ public class JeecgBizToolsProvider implements JeecgToolsProvider { }; return new JeecgLlmTools(spec, exec); } + + /** + * 查询菜单 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools queryMenusTool() { + ToolSpecification spec = ToolSpecification.builder() + .name("query_menus") + .description("查询菜单列表,返回json数组。支持菜单名称、权限标识模糊查询,无条件则返回全部菜单。") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("name", "菜单名称") + .addStringProperty("perms", "权限标识") + .build() + ) + .build(); + ToolExecutor exec = (toolExecutionRequest, memoryId) -> { + SysPermission sysPermission = JSONObject.parseObject(toolExecutionRequest.arguments(), SysPermission.class); + QueryWrapper qw = Wrappers.query(); + if (StringUtils.isNotBlank(sysPermission.getName())) { + qw.like("name", sysPermission.getName()); + } + if (StringUtils.isNotBlank(sysPermission.getPerms())) { + qw.like("perms", sysPermission.getPerms()); + } + qw.eq("del_flag", 0); + qw.orderByAsc("sort_no"); + List menus = sysPermissionService.list(qw); + return JSONObject.toJSONString(menus); + }; + return new JeecgLlmTools(spec, exec); + } + + /** + * 添加菜单 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools addMenuTool() { + ToolSpecification toolSpecification = ToolSpecification.builder() + .name("add_menu") + .description("添加菜单,返回添加结果;\n\n - 缺少必要字段时,请向用户索要.\n\n - 你应该提前判断用户的输入是否合法.\n\n - 添加成功后返回成功消息,如果失败则返回失败原因.") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("name", "菜单名称,必填") + .addStringProperty("parentId", "父菜单ID,必填") + .addStringProperty("menuType", "菜单类型,必填,0-目录,1-菜单,2-按钮") + .addStringProperty("url", "路由地址") + .addStringProperty("component", "组件路径") + .addStringProperty("perms", "权限标识") + .addNumberProperty("sortNo", "排序号") + .addStringProperty("icon", "图标") + .required("name", "parentId", "menuType") + .build() + ) + .build(); + ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + String msg = "添加菜单失败"; + try { + SysPermission menu = JSON.parseObject(arguments.toJSONString(), SysPermission.class); + menu.setCreateTime(new Date()); + menu.setDelFlag(CommonConstant.DEL_FLAG_0); + menu.setStatus("1"); + sysPermissionService.addPermission(menu); + baseCommonService.addLog("添加菜单,name: " + menu.getName() ,CommonConstant.LOG_TYPE_2, 2); + msg = "添加菜单成功"; + } catch (Exception e) { + e.printStackTrace(); + msg = "添加菜单失败:" + e.getMessage(); + } + return msg; + }; + return new JeecgLlmTools(toolSpecification, toolExecutor); + } + + /** + * 编辑菜单 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools editMenuTool() { + ToolSpecification toolSpecification = ToolSpecification.builder() + .name("edit_menu") + .description("编辑菜单,返回编辑结果;\n\n - 缺少必要字段时,请向用户索要.\n\n - 你应该提前判断用户的输入是否合法.\n\n - 编辑成功后返回成功消息,如果失败则返回失败原因.") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("id", "菜单ID,必填") + .addStringProperty("name", "菜单名称,必填") + .addStringProperty("parentId", "父菜单ID,必填") + .addStringProperty("menuType", "菜单类型,必填,0-目录,1-菜单,2-按钮") + .addStringProperty("url", "路由地址") + .addStringProperty("component", "组件路径") + .addStringProperty("perms", "权限标识") + .addNumberProperty("sortNo", "排序号") + .addStringProperty("icon", "图标") + .required("id", "name", "parentId", "menuType") + .build() + ) + .build(); + ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + String msg = "编辑菜单失败"; + try { + SysPermission menu = JSON.parseObject(arguments.toJSONString(), SysPermission.class); + menu.setUpdateTime(new Date()); + sysPermissionService.editPermission(menu); + baseCommonService.addLog("编辑菜单,id: " + menu.getId() ,CommonConstant.LOG_TYPE_2, 2); + msg = "编辑菜单成功"; + } catch (Exception e) { + e.printStackTrace(); + msg = "编辑菜单失败:" + e.getMessage(); + } + return msg; + }; + return new JeecgLlmTools(toolSpecification, toolExecutor); + } + + /** + * 删除菜单 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools deleteMenuTool() { + ToolSpecification toolSpecification = ToolSpecification.builder() + .name("delete_menu") + .description("删除菜单,返回删除结果;\n\n - 缺少必要字段时,请向用户索要.\n\n - 删除成功后返回成功消息,如果失败则返回失败原因.") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("id", "菜单ID,必填") + .required("id") + .build() + ) + .build(); + ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + String menuId = arguments.getString("id"); + String msg = "删除菜单失败"; + try { + sysPermissionService.deletePermissionLogical(menuId); + baseCommonService.addLog("删除菜单,id: " + menuId ,CommonConstant.LOG_TYPE_2, 2); + msg = "删除菜单成功"; + } catch (Exception e) { + e.printStackTrace(); + msg = "删除菜单失败:" + e.getMessage(); + } + return msg; + }; + return new JeecgLlmTools(toolSpecification, toolExecutor); + } + + /** + * 查询系统日志 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools queryLogsTool() { + ToolSpecification spec = ToolSpecification.builder() + .name("query_system_logs") + .description("查询系统日志,支持按时间范围、日志类型、操作类型、用户名等条件查询。返回json数组。") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("startTime", "开始时间,格式:yyyy-MM-dd HH:mm:ss") + .addStringProperty("endTime", "结束时间,格式:yyyy-MM-dd HH:mm:ss") + .addNumberProperty("logType", "日志类型,1-登录日志,2-操作日志") + .addNumberProperty("operateType", "操作类型,1-查询,2-添加,3-修改,4-删除,5-导入,6-导出") + .addStringProperty("username", "用户名") + .addStringProperty("logContent", "日志内容关键词") + .build() + ) + .build(); + ToolExecutor exec = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + QueryWrapper qw = Wrappers.query(); + + // 时间范围 + String startTime = arguments.getString("startTime"); + String endTime = arguments.getString("endTime"); + if (StringUtils.isNotBlank(startTime)) { + try { + Date start = org.jeecg.common.util.DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm:ss"); + qw.ge("create_time", start); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + if (StringUtils.isNotBlank(endTime)) { + try { + Date end = org.jeecg.common.util.DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm:ss"); + qw.le("create_time", end); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + + // 日志类型 + Integer logType = arguments.getInteger("logType"); + if (logType != null) { + qw.eq("log_type", logType); + } + + // 操作类型 + Integer operateType = arguments.getInteger("operateType"); + if (operateType != null) { + qw.eq("operate_type", operateType); + } + + // 用户名 + String username = arguments.getString("username"); + if (StringUtils.isNotBlank(username)) { + qw.like("username", username); + } + + // 日志内容 + String logContent = arguments.getString("logContent"); + if (StringUtils.isNotBlank(logContent)) { + qw.like("log_content", logContent); + } + + qw.orderByDesc("create_time"); + List logs = sysLogService.list(qw); + return JSONObject.toJSONString(logs); + }; + return new JeecgLlmTools(spec, exec); + } + + /** + * 分析用户使用情况 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools analyzeUserUsageTool() { + ToolSpecification spec = ToolSpecification.builder() + .name("analyze_user_usage") + .description("分析用户使用情况,包括登录次数、操作频率、活跃时间等。支持按时间范围分析。") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("startTime", "开始时间,格式:yyyy-MM-dd") + .addStringProperty("endTime", "结束时间,格式:yyyy-MM-dd") + .build() + ) + .build(); + ToolExecutor exec = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + QueryWrapper qw = Wrappers.query(); + + // 时间范围 + String startTime = arguments.getString("startTime"); + String endTime = arguments.getString("endTime"); + if (StringUtils.isNotBlank(startTime)) { + try { + Date start = org.jeecg.common.util.DateUtils.parseDate(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"); + qw.ge("create_time", start); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + if (StringUtils.isNotBlank(endTime)) { + try { + Date end = org.jeecg.common.util.DateUtils.parseDate(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"); + qw.le("create_time", end); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + + List logs = sysLogService.list(qw); + + // 分析用户使用情况 + Map> userAnalysis = new HashMap<>(); + for (SysLog log : logs) { + String username = log.getUsername(); + if (StringUtils.isBlank(username)) continue; + + if (!userAnalysis.containsKey(username)) { + Map userData = new HashMap<>(); + userData.put("loginCount", 0); + userData.put("operationCount", 0); + userData.put("firstLogin", null); + userData.put("lastLogin", null); + userAnalysis.put(username, userData); + } + + Map userData = userAnalysis.get(username); + + // 登录日志 + if (log.getLogType() != null && log.getLogType() == 1) { + int loginCount = (int) userData.get("loginCount"); + userData.put("loginCount", loginCount + 1); + + // 首次登录 + if (userData.get("firstLogin") == null) { + userData.put("firstLogin", log.getCreateTime()); + } + + // 最后登录 + userData.put("lastLogin", log.getCreateTime()); + } + + // 操作日志 + if (log.getLogType() != null && log.getLogType() == 2) { + int operationCount = (int) userData.get("operationCount"); + userData.put("operationCount", operationCount + 1); + } + } + + return JSONObject.toJSONString(userAnalysis); + }; + return new JeecgLlmTools(spec, exec); + } + + /** + * 分析操作情况 + * @return + * @author system + * @date 2026-04-02 + */ + private JeecgLlmTools analyzeOperationsTool() { + ToolSpecification spec = ToolSpecification.builder() + .name("analyze_operations") + .description("分析系统操作情况,包括操作类型分布、高频操作、操作趋势等。支持按时间范围分析。") + .parameters( + JsonObjectSchema.builder() + .addStringProperty("startTime", "开始时间,格式:yyyy-MM-dd") + .addStringProperty("endTime", "结束时间,格式:yyyy-MM-dd") + .build() + ) + .build(); + ToolExecutor exec = (toolExecutionRequest, memoryId) -> { + JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments()); + QueryWrapper qw = Wrappers.query(); + + // 时间范围 + String startTime = arguments.getString("startTime"); + String endTime = arguments.getString("endTime"); + if (StringUtils.isNotBlank(startTime)) { + try { + Date start = org.jeecg.common.util.DateUtils.parseDate(startTime + " 00:00:00", "yyyy-MM-dd HH:mm:ss"); + qw.ge("create_time", start); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + if (StringUtils.isNotBlank(endTime)) { + try { + Date end = org.jeecg.common.util.DateUtils.parseDate(endTime + " 23:59:59", "yyyy-MM-dd HH:mm:ss"); + qw.le("create_time", end); + } catch (Exception e) { + // 时间格式错误,忽略 + } + } + + List logs = sysLogService.list(qw); + + // 分析操作情况 + Map analysis = new HashMap<>(); + + // 操作类型分布 + Map operationTypeDistribution = new HashMap<>(); + + // 高频操作 + Map highFrequencyOperations = new HashMap<>(); + + // 每日操作趋势 + Map dailyOperationTrend = new HashMap<>(); + + for (SysLog log : logs) { + // 操作类型分布 + Integer operateType = log.getOperateType(); + if (operateType != null) { + operationTypeDistribution.put(operateType, operationTypeDistribution.getOrDefault(operateType, 0) + 1); + } + + // 高频操作 + String logContent = log.getLogContent(); + if (StringUtils.isNotBlank(logContent)) { + highFrequencyOperations.put(logContent, highFrequencyOperations.getOrDefault(logContent, 0) + 1); + } + + // 每日操作趋势 + if (log.getCreateTime() != null) { + String date = org.jeecg.common.util.DateUtils.formatDate(log.getCreateTime(), "yyyy-MM-dd"); + dailyOperationTrend.put(date, dailyOperationTrend.getOrDefault(date, 0) + 1); + } + } + + analysis.put("operationTypeDistribution", operationTypeDistribution); + analysis.put("highFrequencyOperations", highFrequencyOperations); + analysis.put("dailyOperationTrend", dailyOperationTrend); + + return JSONObject.toJSONString(analysis); + }; + return new JeecgLlmTools(spec, exec); + } }