diff --git a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java index 779fea83..a9b08d5c 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java +++ b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java @@ -177,5 +177,5 @@ public interface Constant { /** * 版本号 */ - public static final String VERSION = "0.3.14"; + public static final String VERSION = "0.4.1"; } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java index 62d21ab5..62487456 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java +++ b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java @@ -62,6 +62,13 @@ public class RedisKeys { return "agent:device:count:" + id; } + /** + * 获取智能体最后连接时间缓存key + */ + public static String getAgentDeviceLastConnectedAtById(String id) { + return "agent:device:lastConnected:" + id; + } + /** * 获取系统配置缓存key */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java index b839e9e4..21e645de 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java @@ -1,12 +1,15 @@ package xiaozhi.modules.agent.service.biz.impl; import java.util.Base64; +import java.util.Date; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import xiaozhi.common.redis.RedisKeys; +import xiaozhi.common.redis.RedisUtils; import xiaozhi.modules.agent.dto.AgentChatHistoryReportDTO; import xiaozhi.modules.agent.entity.AgentChatHistoryEntity; import xiaozhi.modules.agent.entity.AgentEntity; @@ -29,6 +32,7 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic private final AgentService agentService; private final AgentChatHistoryService agentChatHistoryService; private final AgentChatAudioService agentChatAudioService; + private final RedisUtils redisUtils; /** * 处理聊天记录上报,包括文件上传和相关信息记录 @@ -77,6 +81,8 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic // 3. 保存数据 agentChatHistoryService.save(entity); + // 4. 更新设备最后对话时间 + redisUtils.set(RedisKeys.getAgentDeviceLastConnectedAtById(agentId), new Date()); return Boolean.TRUE; } } 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 97722b59..ae650c85 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 @@ -21,6 +21,7 @@ import xiaozhi.modules.agent.dao.AgentDao; import xiaozhi.modules.agent.dto.AgentDTO; import xiaozhi.modules.agent.entity.AgentEntity; import xiaozhi.modules.agent.service.AgentService; +import xiaozhi.modules.device.service.DeviceService; import xiaozhi.modules.model.service.ModelConfigService; import xiaozhi.modules.security.user.SecurityUser; import xiaozhi.modules.sys.enums.SuperAdminEnum; @@ -29,11 +30,11 @@ import xiaozhi.modules.timbre.service.TimbreService; @Service @AllArgsConstructor public class AgentServiceImpl extends BaseServiceImpl implements AgentService { - private final AgentDao agentDao; private final TimbreService timbreModelService; private final ModelConfigService modelConfigService; private final RedisUtils redisUtils; + private final DeviceService deviceService; @Override public PageData adminAgentList(Map params) { @@ -95,9 +96,11 @@ public class AgentServiceImpl extends BaseServiceImpl imp // 获取 TTS 音色名称 dto.setTtsVoiceName(timbreModelService.getTimbreNameById(agent.getTtsVoiceId())); + // 获取智能体最近的最后连接时长 + dto.setLastConnectedAt(deviceService.getLatestLastConnectionTime(agent.getId())); + // 获取设备数量 dto.setDeviceCount(getDeviceCountByAgentId(agent.getId())); - return dto; }).collect(Collectors.toList()); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java index f0ed4bf1..a15df002 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java @@ -61,15 +61,15 @@ public class ConfigServiceImpl implements ConfigService { // 构建模块配置 buildModuleConfig( - agent.getAgentName(), + null, null, null, agent.getVadModelId(), agent.getAsrModelId(), - agent.getLlmModelId(), - agent.getTtsModelId(), - agent.getMemModelId(), - agent.getIntentModelId(), + null, + null, + null, + null, result, isCache); @@ -117,18 +117,6 @@ public class ConfigServiceImpl implements ConfigService { if (alreadySelectedAsrModelId != null && alreadySelectedAsrModelId.equals(agent.getAsrModelId())) { agent.setAsrModelId(null); } - String alreadySelectedLlmModelId = (String) selectedModule.get("LLM"); - if (alreadySelectedLlmModelId != null && alreadySelectedLlmModelId.equals(agent.getLlmModelId())) { - agent.setLlmModelId(null); - } - String alreadySelectedMemModelId = (String) selectedModule.get("Memory"); - if (alreadySelectedMemModelId != null && alreadySelectedMemModelId.equals(agent.getMemModelId())) { - agent.setMemModelId(null); - } - String alreadySelectedIntentModelId = (String) selectedModule.get("Intent"); - if (alreadySelectedIntentModelId != null && alreadySelectedIntentModelId.equals(agent.getIntentModelId())) { - agent.setIntentModelId(null); - } // 构建模块配置 buildModuleConfig( diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/dao/DeviceDao.java b/main/manager-api/src/main/java/xiaozhi/modules/device/dao/DeviceDao.java index 5ede3d6e..6570b89b 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/dao/DeviceDao.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/dao/DeviceDao.java @@ -6,6 +6,16 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import xiaozhi.modules.device.entity.DeviceEntity; +import java.util.Date; +import java.util.List; + @Mapper public interface DeviceDao extends BaseMapper { + /** + * 获取此智能体全部设备的最后连接时间 + * @param agentId 智能体id + * @return + */ + Date getAllLastConnectedAtByAgentId(String agentId); + } \ No newline at end of file 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 aff31bff..fb91ff89 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 @@ -1,5 +1,6 @@ package xiaozhi.modules.device.service; +import java.util.Date; import java.util.List; import xiaozhi.common.page.PageData; @@ -78,4 +79,13 @@ public interface DeviceService extends BaseService { * @return 激活码 */ String geCodeByDeviceId(String deviceId); + + /** + * 获取这个智能体设备理的最近的最后连接时间 + * @param agentId 智能体id + * @return 返回设备最近的最后连接时间 + */ + Date getLatestLastConnectionTime(String agentId); + + } \ No newline at end of file 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 8eb23a93..515aea7f 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 @@ -258,6 +258,20 @@ public class DeviceServiceImpl extends BaseServiceImpl return null; } + @Override + public Date getLatestLastConnectionTime(String agentId) { + // 查询是否有缓存时间,有则返回 + Date cachedDate = (Date) redisUtils.get(RedisKeys.getAgentDeviceLastConnectedAtById(agentId)); + if (cachedDate != null) { + return cachedDate; + } + Date maxDate = deviceDao.getAllLastConnectedAtByAgentId(agentId); + if (maxDate != null) { + redisUtils.set(RedisKeys.getAgentDeviceLastConnectedAtById(agentId), maxDate); + } + return maxDate; + } + private String getDeviceCacheKey(String deviceId) { String safeDeviceId = deviceId.replace(":", "_").toLowerCase(); String dataKey = String.format("ota:activation:data:%s", safeDeviceId); diff --git a/main/manager-api/src/main/resources/mapper/device/DeviceDao.xml b/main/manager-api/src/main/resources/mapper/device/DeviceDao.xml new file mode 100644 index 00000000..54de47c9 --- /dev/null +++ b/main/manager-api/src/main/resources/mapper/device/DeviceDao.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/main/manager-api/src/test/java/xiaozhi/modules/device/DeviceTest.java b/main/manager-api/src/test/java/xiaozhi/modules/device/DeviceTest.java index 8647692c..37f67cab 100644 --- a/main/manager-api/src/test/java/xiaozhi/modules/device/DeviceTest.java +++ b/main/manager-api/src/test/java/xiaozhi/modules/device/DeviceTest.java @@ -1,5 +1,8 @@ package xiaozhi.modules.device; +import java.util.HashMap; +import java.util.UUID; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -8,8 +11,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import lombok.extern.slf4j.Slf4j; -import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; +import xiaozhi.modules.sys.dto.SysUserDTO; +import xiaozhi.modules.sys.service.SysUserService; @Slf4j @SpringBootTest @@ -19,18 +23,37 @@ public class DeviceTest { @Autowired private RedisUtils redisUtils; + @Autowired + private SysUserService sysUserService; + + @Test + public void testSaveUser() { + SysUserDTO userDTO = new SysUserDTO(); + userDTO.setUsername("test"); + userDTO.setPassword(UUID.randomUUID().toString()); + sysUserService.save(userDTO); + } @Test @DisplayName("测试写入设备信息") public void testWriteDeviceInfo() { log.info("开始测试写入设备信息..."); - // 模拟设备MAC地址 - String macAddress = "00:11:22:33:44:55"; + String macAddress = "00:11:22:33:44:66"; // 模拟设备验证码 String deviceCode = "123456"; - String redisKey = RedisKeys.getDeviceCaptchaKey(deviceCode); + HashMap map = new HashMap<>(); + map.put("mac_address", macAddress); + map.put("activation_code", deviceCode); + map.put("board", "硬件型号"); + map.put("app_version", "0.3.13"); + + String safeDeviceId = macAddress.replace(":", "_").toLowerCase(); + String cacheDeviceKey = String.format("ota:activation:data:%s", safeDeviceId); + redisUtils.set(cacheDeviceKey, map, 300); + + String redisKey = "ota:activation:code:" + deviceCode; log.info("Redis Key: {}", redisKey); // 将设备信息写入Redis diff --git a/main/manager-web/src/components/DeviceItem.vue b/main/manager-web/src/components/DeviceItem.vue index fa81a04d..60f54b9d 100644 --- a/main/manager-web/src/components/DeviceItem.vue +++ b/main/manager-web/src/components/DeviceItem.vue @@ -31,7 +31,7 @@
-
最近对话:{{ device.lastConnectedAt }}
+
最近对话:{{ formattedLastConnectedTime }}
@@ -45,6 +45,27 @@ export default { data() { return { switchValue: false } }, + computed: { + formattedLastConnectedTime() { + if (!this.device.lastConnectedAt) return '暂未对话'; + + const lastTime = new Date(this.device.lastConnectedAt); + const now = new Date(); + const diffMinutes = Math.floor((now - lastTime) / (1000 * 60)); + + if (diffMinutes <= 1) { + return '刚刚'; + } else if (diffMinutes < 60) { + return `${diffMinutes}分钟前`; + } else if (diffMinutes < 24 * 60) { + const hours = Math.floor(diffMinutes / 60); + const minutes = diffMinutes % 60; + return `${hours}小时${minutes > 0 ? minutes + '分钟' : ''}前`; + } else { + return this.device.lastConnectedAt; + } + } + }, methods: { handleDelete() { this.$emit('delete', this.device.agentId) diff --git a/main/manager-web/src/views/ParamsManagement.vue b/main/manager-web/src/views/ParamsManagement.vue index 3301bbb5..afb0dc1d 100644 --- a/main/manager-web/src/views/ParamsManagement.vue +++ b/main/manager-web/src/views/ParamsManagement.vue @@ -25,8 +25,19 @@ - + + +