diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java index 4bd8f948e..1b84853fb 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java @@ -67,11 +67,21 @@ public class AgentController { private final RedisUtils redisUtils; @GetMapping("/list") - @Operation(summary = "Get user agents list") + @Operation(summary = "Get agents list (admin gets all agents, user gets own agents)") @RequiresPermissions("sys:role:normal") - public Result> getUserAgents() { + public Result> getAgentsList() { UserDetail user = SecurityUser.getUser(); - List agents = agentService.getUserAgents(user.getId()); + List agents; + + // Check if user is super admin + if (user.getSuperAdmin() != null && user.getSuperAdmin() == 1) { + // Admin sees all agents from all users with owner information + agents = agentService.getAllAgentsForAdmin(); + } else { + // Regular user sees only their own agents + agents = agentService.getUserAgents(user.getId()); + } + return new Result>().ok(agents); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java index 03e569cdc..a596aab88 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java @@ -1,8 +1,10 @@ package xiaozhi.modules.agent.dao; +import java.util.List; +import java.util.Map; + import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; - import org.apache.ibatis.annotations.Select; import xiaozhi.common.dao.BaseDao; import xiaozhi.modules.agent.entity.AgentEntity; @@ -30,6 +32,24 @@ public interface AgentDao extends BaseDao { " ORDER BY d.id DESC LIMIT 1") AgentEntity getDefaultAgentByMacAddress(@Param("macAddress") String macAddress); + /** + * 获取所有智能体及其所有者信息(管理员专用) + * + * @return 所有智能体列表及用户信息 + */ + @Select("SELECT " + + "a.id, a.agent_name, a.system_prompt, a.tts_model_id, " + + "a.llm_model_id, a.vllm_model_id, a.mem_model_id, a.tts_voice_id, " + + "a.created_at, a.updated_at, a.user_id, " + + "u.username as owner_username, " + + "GROUP_CONCAT(d.mac_address SEPARATOR ',') as device_mac_addresses " + + "FROM ai_agent a " + + "LEFT JOIN sys_user u ON a.user_id = u.id " + + "LEFT JOIN ai_device d ON a.id = d.agent_id " + + "GROUP BY a.id " + + "ORDER BY a.created_at DESC") + List> getAllAgentsWithOwnerInfo(); + /** * 根据id查询agent信息,包括插件信息 * diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java index 218ee1ebf..fcf8d229a 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java @@ -45,4 +45,14 @@ public class AgentDTO { @Schema(description = "设备数量", example = "10") private Integer deviceCount; + + @Schema(description = "设备MAC地址列表", example = "AA:BB:CC:DD:EE:FF,11:22:33:44:55:66") + private String deviceMacAddresses; + + // 管理员专用字段 - 智能体所有者信息 + @Schema(description = "所有者用户名", example = "john_doe") + private String ownerUsername; + + @Schema(description = "创建时间", example = "2024-03-20 10:00:00") + private Date createDate; } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java index a9d4e5bb2..55cd0abce 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java @@ -43,6 +43,21 @@ public interface AgentService extends BaseService { */ boolean insert(AgentEntity entity); + /** + * 获取用户的智能体列表 + * + * @param userId 用户ID + * @return 智能体列表 + */ + List getUserAgents(Long userId); + + /** + * 获取所有智能体列表(管理员专用,包含用户信息) + * + * @return 所有智能体列表 + */ + List getAllAgentsForAdmin(); + /** * 根据用户ID删除智能体 * diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java index e425b743f..330ee8071 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java @@ -150,6 +150,59 @@ public List getUserAgents(Long userId) { }).collect(Collectors.toList()); } + @Override + public List getAllAgentsForAdmin() { + List> agentMaps = agentDao.getAllAgentsWithOwnerInfo(); + return agentMaps.stream().map(agentMap -> { + AgentDTO dto = new AgentDTO(); + + // 基础智能体信息 + String agentId = (String) agentMap.get("id"); + dto.setId(agentId); + dto.setAgentName((String) agentMap.get("agent_name")); + dto.setSystemPrompt((String) agentMap.get("system_prompt")); + + // Handle LocalDateTime to Date conversion for createDate + Object createdAt = agentMap.get("created_at"); + if (createdAt instanceof java.time.LocalDateTime) { + dto.setCreateDate(java.sql.Timestamp.valueOf((java.time.LocalDateTime) createdAt)); + } + + // 获取模型名称 - 同用户方法 + String ttsModelId = (String) agentMap.get("tts_model_id"); + String llmModelId = (String) agentMap.get("llm_model_id"); + String vllmModelId = (String) agentMap.get("vllm_model_id"); + String memModelId = (String) agentMap.get("mem_model_id"); + String ttsVoiceId = (String) agentMap.get("tts_voice_id"); + + dto.setTtsModelName(modelConfigService.getModelNameById(ttsModelId)); + dto.setLlmModelName(modelConfigService.getModelNameById(llmModelId)); + dto.setVllmModelName(modelConfigService.getModelNameById(vllmModelId)); + dto.setMemModelId(memModelId); + dto.setTtsVoiceName(timbreModelService.getTimbreNameById(ttsVoiceId)); + + // 获取智能体最近的最后连接时长 - 同用户方法 + dto.setLastConnectedAt(deviceService.getLatestLastConnectionTime(agentId)); + + // 获取设备MAC地址列表 - 管理员专用 + String macAddresses = (String) agentMap.get("device_mac_addresses"); + dto.setDeviceMacAddresses(macAddresses); + + // 计算设备数量(从MAC地址列表或使用原方法) + if (macAddresses != null && !macAddresses.isEmpty()) { + dto.setDeviceCount(macAddresses.split(",").length); + } else { + // 使用原来的方法获取设备数量 + dto.setDeviceCount(getDeviceCountByAgentId(agentId)); + } + + // 管理员专用字段 - 用户信息 + dto.setOwnerUsername((String) agentMap.get("owner_username")); + + return dto; + }).collect(Collectors.toList()); + } + @Override public Integer getDeviceCountByAgentId(String agentId) { if (StringUtils.isBlank(agentId)) { diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java index a23e9f81c..de9802776 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java @@ -71,7 +71,17 @@ public Result registerDevice(@RequestBody DeviceRegisterDTO deviceRegist @RequiresPermissions("sys:role:normal") public Result> getUserDevices(@PathVariable String agentId) { UserDetail user = SecurityUser.getUser(); - List devices = deviceService.getUserDevices(user.getId(), agentId); + List devices; + + // Check if user is super admin + if (user.getSuperAdmin() != null && user.getSuperAdmin() == 1) { + // Admin can see all devices for any agent + devices = deviceService.getDevicesByAgentId(agentId); + } else { + // Regular user can only see their own devices + devices = deviceService.getUserDevices(user.getId(), agentId); + } + return new Result>().ok(devices); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java index 3392c96ff..2afbd730e 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java @@ -25,6 +25,11 @@ DeviceReportRespDTO checkDeviceActive(String macAddress, String clientId, */ List getUserDevices(Long userId, String agentId); + /** + * 获取指定智能体的所有设备列表(管理员专用) + */ + List getDevicesByAgentId(String agentId); + /** * 解绑设备 */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java index 96315ccc3..0119017c5 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java @@ -211,6 +211,13 @@ public List getUserDevices(Long userId, String agentId) { return baseDao.selectList(wrapper); } + @Override + public List getDevicesByAgentId(String agentId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("agent_id", agentId); + return baseDao.selectList(wrapper); + } + @Override public void unbindDevice(Long userId, String deviceId) { UpdateWrapper wrapper = new UpdateWrapper<>(); diff --git a/main/manager-api/src/main/resources/application.yml b/main/manager-api/src/main/resources/application.yml index 56934b317..8590bbdc5 100644 --- a/main/manager-api/src/main/resources/application.yml +++ b/main/manager-api/src/main/resources/application.yml @@ -17,7 +17,7 @@ spring: # Profile will be set by SPRING_PROFILES_ACTIVE environment variable # Default to 'dev' if not specified profiles: - default: prod + default: dev messages: encoding: UTF-8 basename: i18n/messages diff --git a/main/manager-web/src/components/DeviceItem.vue b/main/manager-web/src/components/DeviceItem.vue index 54685b264..4ec8ee64e 100644 --- a/main/manager-web/src/components/DeviceItem.vue +++ b/main/manager-web/src/components/DeviceItem.vue @@ -1,8 +1,14 @@