mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-25 00:23:53 +08:00
修复智控台音频播放权限bug
This commit is contained in:
@@ -103,4 +103,11 @@ public class RedisKeys {
|
|||||||
public static String getDictDataByTypeKey(String dictType) {
|
public static String getDictDataByTypeKey(String dictType) {
|
||||||
return "sys:dict:data:" + dictType;
|
return "sys:dict:data:" + dictType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取智能体音频ID的缓存key
|
||||||
|
*/
|
||||||
|
public static String getAgentAudioIdKey(String uuid) {
|
||||||
|
return "agent:audio:id:" + uuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-3
@@ -3,7 +3,9 @@ package xiaozhi.modules.agent.controller;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@@ -28,6 +30,8 @@ import jakarta.validation.Valid;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import xiaozhi.common.constant.Constant;
|
import xiaozhi.common.constant.Constant;
|
||||||
import xiaozhi.common.page.PageData;
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.redis.RedisKeys;
|
||||||
|
import xiaozhi.common.redis.RedisUtils;
|
||||||
import xiaozhi.common.user.UserDetail;
|
import xiaozhi.common.user.UserDetail;
|
||||||
import xiaozhi.common.utils.ConvertUtils;
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
import xiaozhi.common.utils.Result;
|
import xiaozhi.common.utils.Result;
|
||||||
@@ -55,6 +59,7 @@ public class AgentController {
|
|||||||
private final DeviceService deviceService;
|
private final DeviceService deviceService;
|
||||||
private final AgentChatHistoryService agentChatHistoryService;
|
private final AgentChatHistoryService agentChatHistoryService;
|
||||||
private final AgentChatAudioService agentChatAudioService;
|
private final AgentChatAudioService agentChatAudioService;
|
||||||
|
private final RedisUtils redisUtils;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获取用户智能体列表")
|
@Operation(summary = "获取用户智能体列表")
|
||||||
@@ -235,17 +240,37 @@ public class AgentController {
|
|||||||
return new Result<List<AgentChatHistoryDTO>>().ok(result);
|
return new Result<List<AgentChatHistoryDTO>>().ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/audio/{audioId}")
|
@PostMapping("/audio/{audioId}")
|
||||||
@Operation(summary = "下载音频")
|
@Operation(summary = "获取音频下载ID")
|
||||||
@RequiresPermissions("sys:role:normal")
|
@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);
|
byte[] audioData = agentChatAudioService.getAudio(audioId);
|
||||||
if (audioData == null) {
|
if (audioData == null) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
redisUtils.delete(RedisKeys.getAgentAudioIdKey(uuid));
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"play.wav\"")
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"play.wav\"")
|
||||||
.body(audioData);
|
.body(audioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -86,6 +86,7 @@ public class ShiroConfig {
|
|||||||
// 将config路径使用server服务过滤器
|
// 将config路径使用server服务过滤器
|
||||||
filterMap.put("/config/**", "server");
|
filterMap.put("/config/**", "server");
|
||||||
filterMap.put("/agent/chat-history/report", "server");
|
filterMap.put("/agent/chat-history/report", "server");
|
||||||
|
filterMap.put("/agent/play/**", "anon");
|
||||||
filterMap.put("/**", "oauth2");
|
filterMap.put("/**", "oauth2");
|
||||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||||
|
|
||||||
|
|||||||
@@ -128,19 +128,19 @@ export default {
|
|||||||
});
|
});
|
||||||
}).send();
|
}).send();
|
||||||
},
|
},
|
||||||
}
|
// 获取音频下载ID
|
||||||
|
getAudioId(audioId, callback) {
|
||||||
export function getAgentSessions(agentId, params) {
|
RequestService.sendRequest()
|
||||||
return request({
|
.url(`${getServiceUrl()}/agent/audio/${audioId}`)
|
||||||
url: `/agent/${agentId}/sessions`,
|
.method('POST')
|
||||||
method: 'get',
|
.success((res) => {
|
||||||
params
|
RequestService.clearRequestTime();
|
||||||
});
|
callback(res);
|
||||||
}
|
})
|
||||||
|
.fail(() => {
|
||||||
export function getAgentChatHistory(agentId, sessionId) {
|
RequestService.reAjaxFun(() => {
|
||||||
return request({
|
this.getAudioId(audioId, callback);
|
||||||
url: `/agent/${agentId}/chat-history/${sessionId}`,
|
});
|
||||||
method: 'get'
|
}).send();
|
||||||
});
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default {
|
|||||||
currentSessionId: '',
|
currentSessionId: '',
|
||||||
currentMacAddress: '',
|
currentMacAddress: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 10,
|
limit: 20,
|
||||||
loading: false,
|
loading: false,
|
||||||
hasMore: true,
|
hasMore: true,
|
||||||
scrollTimer: null,
|
scrollTimer: null,
|
||||||
@@ -237,16 +237,21 @@ export default {
|
|||||||
this.audioElement = null;
|
this.audioElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放新音频
|
// 先获取音频下载ID
|
||||||
this.playingAudioId = message.audioId;
|
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.audioElement.onended = () => {
|
||||||
this.playingAudioId = null;
|
this.playingAudioId = null;
|
||||||
this.audioElement = null;
|
this.audioElement = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.audioElement.play();
|
this.audioElement.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getUserAvatar(sessionId) {
|
getUserAvatar(sessionId) {
|
||||||
// 从 sessionId 中提取所有数字
|
// 从 sessionId 中提取所有数字
|
||||||
@@ -269,7 +274,7 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.chat-container {
|
.chat-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 600px;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-list {
|
.session-list {
|
||||||
@@ -422,7 +427,7 @@ export default {
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
height: 80vh;
|
height: 90vh;
|
||||||
max-width: 85vw;
|
max-width: 85vw;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -436,7 +441,7 @@ export default {
|
|||||||
.chat-history-dialog .el-dialog__body {
|
.chat-history-dialog .el-dialog__body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: calc(80vh - 54px);
|
height: calc(90vh - 54px);
|
||||||
/* 减去标题栏的高度 */
|
/* 减去标题栏的高度 */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user