mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
Merge pull request #1066 from xinnan-tech/manager-api-lastConnectedAtIsNull-BUG
修复了"获取用户智能体列表"中lastConnectedAt为null的bug
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
||||
+6
@@ -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(), 60 * 2);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -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<AgentDao, AgentEntity> 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<AgentEntity> adminAgentList(Map<String, Object> params) {
|
||||
@@ -95,9 +96,11 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
|
||||
// 获取 TTS 音色名称
|
||||
dto.setTtsVoiceName(timbreModelService.getTimbreNameById(agent.getTtsVoiceId()));
|
||||
|
||||
// 获取智能体最近的最后连接时长
|
||||
dto.setLastConnectedAt(deviceService.getLatestLastConnectionTime(agent.getId()));
|
||||
|
||||
// 获取设备数量
|
||||
dto.setDeviceCount(getDeviceCountByAgentId(agent.getId()));
|
||||
|
||||
return dto;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -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<DeviceEntity> {
|
||||
/**
|
||||
* 获取此智能体全部设备的最后连接时间
|
||||
* @param agentId 智能体id
|
||||
* @return
|
||||
*/
|
||||
Date getAllLastConnectedAtByAgentId(String agentId);
|
||||
|
||||
}
|
||||
@@ -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<DeviceEntity> {
|
||||
* @return 激活码
|
||||
*/
|
||||
String geCodeByDeviceId(String deviceId);
|
||||
|
||||
/**
|
||||
* 获取这个智能体设备理的最近的最后连接时间
|
||||
* @param agentId 智能体id
|
||||
* @return 返回设备最近的最后连接时间
|
||||
*/
|
||||
Date getLatestLastConnectionTime(String agentId);
|
||||
|
||||
|
||||
}
|
||||
+15
-6
@@ -1,12 +1,7 @@
|
||||
package xiaozhi.modules.device.service.impl;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -258,6 +253,20 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
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, 60 * 2);
|
||||
}
|
||||
return maxDate;
|
||||
}
|
||||
|
||||
private String getDeviceCacheKey(String deviceId) {
|
||||
String safeDeviceId = deviceId.replace(":", "_").toLowerCase();
|
||||
String dataKey = String.format("ota:activation:data:%s", safeDeviceId);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="xiaozhi.modules.device.dao.DeviceDao">
|
||||
<!-- 获取此智能体全部设备的最后连接时间 -->
|
||||
<select id="getAllLastConnectedAtByAgentId" resultType="java.util.Date">
|
||||
SELECT last_connected_at FROM ai_device
|
||||
WHERE
|
||||
agent_id = #{agentId}
|
||||
order by
|
||||
last_connected_at desc limit 0,1
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -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<String, Object> 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
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="version-info">
|
||||
<div>最近对话:{{ device.lastConnectedAt }}</div>
|
||||
<div>最近对话:{{ formattedLastConnectedTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -45,6 +45,25 @@ 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 < 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)
|
||||
|
||||
Reference in New Issue
Block a user