扩展AI助手功能,新增7个业务工具,涉及菜单管理、日志查询和数据分析
This commit is contained in:
@@ -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<ToolSpecification, ToolExecutor> getDefaultTools(){
|
||||
Map<ToolSpecification, ToolExecutor> 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<SysPermission> 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<SysPermission> 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<SysLog> 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<SysLog> 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<SysLog> 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<SysLog> logs = sysLogService.list(qw);
|
||||
|
||||
// 分析用户使用情况
|
||||
Map<String, Map<String, Object>> userAnalysis = new HashMap<>();
|
||||
for (SysLog log : logs) {
|
||||
String username = log.getUsername();
|
||||
if (StringUtils.isBlank(username)) continue;
|
||||
|
||||
if (!userAnalysis.containsKey(username)) {
|
||||
Map<String, Object> userData = new HashMap<>();
|
||||
userData.put("loginCount", 0);
|
||||
userData.put("operationCount", 0);
|
||||
userData.put("firstLogin", null);
|
||||
userData.put("lastLogin", null);
|
||||
userAnalysis.put(username, userData);
|
||||
}
|
||||
|
||||
Map<String, Object> 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<SysLog> 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<SysLog> logs = sysLogService.list(qw);
|
||||
|
||||
// 分析操作情况
|
||||
Map<String, Object> analysis = new HashMap<>();
|
||||
|
||||
// 操作类型分布
|
||||
Map<Integer, Integer> operationTypeDistribution = new HashMap<>();
|
||||
|
||||
// 高频操作
|
||||
Map<String, Integer> highFrequencyOperations = new HashMap<>();
|
||||
|
||||
// 每日操作趋势
|
||||
Map<String, Integer> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user