Merge pull request #1100 from xinnan-tech/hot-fix

Hot fix
This commit is contained in:
欣南科技
2025-05-04 20:15:07 +08:00
committed by GitHub
5 changed files with 69 additions and 31 deletions
@@ -103,4 +103,11 @@ public class RedisKeys {
public static String getDictDataByTypeKey(String dictType) {
return "sys:dict:data:" + dictType;
}
/**
* 获取智能体音频ID的缓存key
*/
public static String getAgentAudioIdKey(String uuid) {
return "agent:audio:id:" + uuid;
}
}
@@ -3,7 +3,9 @@ package xiaozhi.modules.agent.controller;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@@ -28,6 +30,8 @@ import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import xiaozhi.common.constant.Constant;
import xiaozhi.common.page.PageData;
import xiaozhi.common.redis.RedisKeys;
import xiaozhi.common.redis.RedisUtils;
import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.common.utils.Result;
@@ -55,6 +59,7 @@ public class AgentController {
private final DeviceService deviceService;
private final AgentChatHistoryService agentChatHistoryService;
private final AgentChatAudioService agentChatAudioService;
private final RedisUtils redisUtils;
@GetMapping("/list")
@Operation(summary = "获取用户智能体列表")
@@ -89,7 +94,7 @@ public class AgentController {
@PostMapping
@Operation(summary = "创建智能体")
@RequiresPermissions("sys:role:normal")
public Result<Void> save(@RequestBody @Valid AgentCreateDTO dto) {
public Result<String> save(@RequestBody @Valid AgentCreateDTO dto) {
AgentEntity entity = ConvertUtils.sourceToTarget(dto, AgentEntity.class);
// 获取默认模板
@@ -117,7 +122,7 @@ public class AgentController {
// ID、智能体编码和排序会在Service层自动生成
agentService.insert(entity);
return new Result<>();
return new Result<String>().ok(entity.getId());
}
@PutMapping("/{id}")
@@ -235,17 +240,37 @@ public class AgentController {
return new Result<List<AgentChatHistoryDTO>>().ok(result);
}
@GetMapping("/audio/{audioId}")
@Operation(summary = "下载音频")
@PostMapping("/audio/{audioId}")
@Operation(summary = "获取音频下载ID")
@RequiresPermissions("sys:role:normal")
public ResponseEntity<byte[]> downloadAudio(@PathVariable("audioId") String audioId) {
public Result<String> getAudioId(@PathVariable("audioId") String audioId) {
byte[] audioData = agentChatAudioService.getAudio(audioId);
if (audioData == null) {
return new Result<String>().error("音频不存在");
}
String uuid = UUID.randomUUID().toString();
redisUtils.set(RedisKeys.getAgentAudioIdKey(uuid), audioId);
return new Result<String>().ok(uuid);
}
@GetMapping("/play/{uuid}")
@Operation(summary = "播放音频")
public ResponseEntity<byte[]> playAudio(@PathVariable("uuid") String uuid) {
String audioId = (String) redisUtils.get(RedisKeys.getAgentAudioIdKey(uuid));
if (StringUtils.isBlank(audioId)) {
return ResponseEntity.notFound().build();
}
byte[] audioData = agentChatAudioService.getAudio(audioId);
if (audioData == null) {
return ResponseEntity.notFound().build();
}
redisUtils.delete(RedisKeys.getAgentAudioIdKey(uuid));
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"play.wav\"")
.body(audioData);
}
}
@@ -86,6 +86,7 @@ public class ShiroConfig {
// 将config路径使用server服务过滤器
filterMap.put("/config/**", "server");
filterMap.put("/agent/chat-history/report", "server");
filterMap.put("/agent/play/**", "anon");
filterMap.put("/**", "oauth2");
shiroFilter.setFilterChainDefinitionMap(filterMap);
+15 -15
View File
@@ -128,19 +128,19 @@ export default {
});
}).send();
},
}
export function getAgentSessions(agentId, params) {
return request({
url: `/agent/${agentId}/sessions`,
method: 'get',
params
});
}
export function getAgentChatHistory(agentId, sessionId) {
return request({
url: `/agent/${agentId}/chat-history/${sessionId}`,
method: 'get'
});
// 获取音频下载ID
getAudioId(audioId, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/agent/audio/${audioId}`)
.method('POST')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getAudioId(audioId, callback);
});
}).send();
},
}
@@ -66,7 +66,7 @@ export default {
currentSessionId: '',
currentMacAddress: '',
page: 1,
limit: 10,
limit: 20,
loading: false,
hasMore: true,
scrollTimer: null,
@@ -237,16 +237,21 @@ export default {
this.audioElement = null;
}
// 播放新音频
// 先获取音频下载ID
this.playingAudioId = message.audioId;
this.audioElement = new Audio(Api.getServiceUrl() + `/agent/audio/${message.audioId}`);
Api.agent.getAudioId(message.audioId, (res) => {
if (res.data && res.data.data) {
// 使用获取到的下载ID播放音频
this.audioElement = new Audio(Api.getServiceUrl() + `/agent/play/${res.data.data}`);
this.audioElement.onended = () => {
this.playingAudioId = null;
this.audioElement = null;
};
this.audioElement.onended = () => {
this.playingAudioId = null;
this.audioElement = null;
};
this.audioElement.play();
this.audioElement.play();
}
});
},
getUserAvatar(sessionId) {
// 从 sessionId 中提取所有数字
@@ -269,7 +274,7 @@ export default {
<style scoped>
.chat-container {
display: flex;
height: 600px;
height: 100%;
}
.session-list {
@@ -422,7 +427,7 @@ export default {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 80vh;
height: 90vh;
max-width: 85vw;
border-radius: 12px;
overflow: hidden;
@@ -436,7 +441,7 @@ export default {
.chat-history-dialog .el-dialog__body {
padding: 0;
overflow: hidden;
height: calc(80vh - 54px);
height: calc(90vh - 54px);
/* 减去标题栏的高度 */
}
</style>