From c331b8322c84628c7f72f62527f2875617c058fe Mon Sep 17 00:00:00 2001 From: LiJinHui <166460433+stu-rgsze@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:38:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=B0=83=E6=95=B4=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E6=A8=A1=E7=89=88=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AgentTemplateController.java | 223 ++++++ main/manager-web/src/apis/module/agent.js | 87 ++- .../src/components/AgentTemplateDialog.vue | 106 +++ .../src/components/DefaultRoleDialog.vue | 322 ++++++++ main/manager-web/src/components/HeaderBar.vue | 14 +- main/manager-web/src/i18n/zh_CN.js | 1 + main/manager-web/src/router/index.js | 25 +- .../src/views/AgentTemplateManagement.vue | 731 +++++++++++++++++ .../src/views/TemplateQuickConfig.vue | 738 ++++++++++++++++++ 9 files changed, 2242 insertions(+), 5 deletions(-) create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentTemplateController.java create mode 100644 main/manager-web/src/components/AgentTemplateDialog.vue create mode 100644 main/manager-web/src/components/DefaultRoleDialog.vue create mode 100644 main/manager-web/src/views/AgentTemplateManagement.vue create mode 100644 main/manager-web/src/views/TemplateQuickConfig.vue diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentTemplateController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentTemplateController.java new file mode 100644 index 00000000..ba317938 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentTemplateController.java @@ -0,0 +1,223 @@ +package xiaozhi.modules.agent.controller; + +import java.util.List; +import java.util.Map; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.utils.Result; +import xiaozhi.common.utils.ResultUtils; +import xiaozhi.modules.agent.entity.AgentTemplateEntity; +import xiaozhi.modules.agent.service.AgentTemplateService; +import xiaozhi.modules.agent.vo.AgentTemplateVO; + +@Tag(name = "智能体模板管理") +@AllArgsConstructor +@RestController +@RequestMapping("/agent/template") +public class AgentTemplateController { + + private final AgentTemplateService agentTemplateService; + + @GetMapping("/all") + @Operation(summary = "获取所有模板列表") + @RequiresPermissions("sys:role:normal") + public Result> getAgentTemplates() { + List templates = agentTemplateService.list(); + // 转换为VO列表 + List voList = templates.stream().map(template -> { + AgentTemplateVO vo = new AgentTemplateVO(); + // 复制属性 + vo.setId(template.getId()); + vo.setAgentCode(template.getAgentCode()); + vo.setAgentName(template.getAgentName()); + vo.setAsrModelId(template.getAsrModelId()); + vo.setVadModelId(template.getVadModelId()); + vo.setLlmModelId(template.getLlmModelId()); + vo.setVllmModelId(template.getVllmModelId()); + vo.setTtsModelId(template.getTtsModelId()); + vo.setTtsVoiceId(template.getTtsVoiceId()); + vo.setMemModelId(template.getMemModelId()); + vo.setIntentModelId(template.getIntentModelId()); + vo.setChatHistoryConf(template.getChatHistoryConf()); + vo.setSystemPrompt(template.getSystemPrompt()); + vo.setSummaryMemory(template.getSummaryMemory()); + vo.setLangCode(template.getLangCode()); + vo.setLanguage(template.getLanguage()); + vo.setSort(template.getSort()); + vo.setCreator(template.getCreator()); + vo.setCreatedAt(template.getCreatedAt()); + vo.setUpdater(template.getUpdater()); + vo.setUpdatedAt(template.getUpdatedAt()); + return vo; + }).toList(); + return new Result>().ok(voList); + } + + @GetMapping("/page") + @Operation(summary = "获取模板分页列表") + @RequiresPermissions("sys:role:normal") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true), + @Parameter(name = "agentName", description = "模板名称,模糊查询") + }) + public Result> getAgentTemplatesPage( + @Parameter(hidden = true) @RequestParam Map params) { + + // 创建分页对象 + int page = Integer.parseInt(params.getOrDefault(Constant.PAGE, "1").toString()); + int limit = Integer.parseInt(params.getOrDefault(Constant.LIMIT, "10").toString()); + Page pageInfo = new Page<>(page, limit); + + // 创建查询条件 + QueryWrapper wrapper = new QueryWrapper<>(); + String agentName = (String) params.get("agentName"); + if (agentName != null && !agentName.isEmpty()) { + wrapper.like("agent_name", agentName); + } + wrapper.orderByAsc("sort"); + + // 执行分页查询 + IPage pageResult = agentTemplateService.page(pageInfo, wrapper); + + // 转换为PageData对象 + List voList = pageResult.getRecords().stream().map(template -> { + AgentTemplateVO vo = new AgentTemplateVO(); + // 复制属性 + vo.setId(template.getId()); + vo.setAgentCode(template.getAgentCode()); + vo.setAgentName(template.getAgentName()); + vo.setAsrModelId(template.getAsrModelId()); + vo.setVadModelId(template.getVadModelId()); + vo.setLlmModelId(template.getLlmModelId()); + vo.setVllmModelId(template.getVllmModelId()); + vo.setTtsModelId(template.getTtsModelId()); + vo.setTtsVoiceId(template.getTtsVoiceId()); + vo.setMemModelId(template.getMemModelId()); + vo.setIntentModelId(template.getIntentModelId()); + vo.setChatHistoryConf(template.getChatHistoryConf()); + vo.setSystemPrompt(template.getSystemPrompt()); + vo.setSummaryMemory(template.getSummaryMemory()); + vo.setLangCode(template.getLangCode()); + vo.setLanguage(template.getLanguage()); + vo.setSort(template.getSort()); + vo.setCreator(template.getCreator()); + vo.setCreatedAt(template.getCreatedAt()); + vo.setUpdater(template.getUpdater()); + vo.setUpdatedAt(template.getUpdatedAt()); + return vo; + }).toList(); + + // 修复:使用构造函数创建PageData对象,而不是无参构造+setter + PageData pageData = new PageData<>(voList, pageResult.getTotal()); + + return new Result>().ok(pageData); + } + + @GetMapping("/{id}") + @Operation(summary = "获取模板详情") + @RequiresPermissions("sys:role:normal") + public Result getAgentTemplateById(@PathVariable("id") String id) { + AgentTemplateEntity template = agentTemplateService.getById(id); + if (template == null) { + return ResultUtils.error("模板不存在"); + } + + // 转换为VO + AgentTemplateVO vo = new AgentTemplateVO(); + // 复制属性 + vo.setId(template.getId()); + vo.setAgentCode(template.getAgentCode()); + vo.setAgentName(template.getAgentName()); + vo.setAsrModelId(template.getAsrModelId()); + vo.setVadModelId(template.getVadModelId()); + vo.setLlmModelId(template.getLlmModelId()); + vo.setVllmModelId(template.getVllmModelId()); + vo.setTtsModelId(template.getTtsModelId()); + vo.setTtsVoiceId(template.getTtsVoiceId()); + vo.setMemModelId(template.getMemModelId()); + vo.setIntentModelId(template.getIntentModelId()); + vo.setChatHistoryConf(template.getChatHistoryConf()); + vo.setSystemPrompt(template.getSystemPrompt()); + vo.setSummaryMemory(template.getSummaryMemory()); + vo.setLangCode(template.getLangCode()); + vo.setLanguage(template.getLanguage()); + vo.setSort(template.getSort()); + vo.setCreator(template.getCreator()); + vo.setCreatedAt(template.getCreatedAt()); + vo.setUpdater(template.getUpdater()); + vo.setUpdatedAt(template.getUpdatedAt()); + + return ResultUtils.success(vo); + } + + @PostMapping + @Operation(summary = "创建模板") + @RequiresPermissions("sys:role:normal") + public Result createAgentTemplate(@Valid @RequestBody AgentTemplateEntity template) { + boolean saved = agentTemplateService.save(template); + if (saved) { + return ResultUtils.success(template); + } else { + return ResultUtils.error("创建模板失败"); + } + } + + @PutMapping + @Operation(summary = "更新模板") + @RequiresPermissions("sys:role:normal") + public Result updateAgentTemplate(@Valid @RequestBody AgentTemplateEntity template) { + boolean updated = agentTemplateService.updateById(template); + if (updated) { + return ResultUtils.success(template); + } else { + return ResultUtils.error("更新模板失败"); + } + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除模板") + @RequiresPermissions("sys:role:normal") + public Result deleteAgentTemplate(@PathVariable("id") String id) { + boolean deleted = agentTemplateService.removeById(id); + if (deleted) { + return ResultUtils.success("删除成功"); + } else { + return ResultUtils.error("删除模板失败"); + } + } + + @DeleteMapping("/batch-delete") + @Operation(summary = "批量删除模板") + @RequiresPermissions("sys:role:normal") + public Result batchDeleteAgentTemplates(@RequestBody List ids) { + boolean deleted = agentTemplateService.removeByIds(ids); + if (deleted) { + return ResultUtils.success("批量删除成功"); + } else { + return ResultUtils.error("批量删除模板失败"); + } + } +} \ No newline at end of file diff --git a/main/manager-web/src/apis/module/agent.js b/main/manager-web/src/apis/module/agent.js index 66126237..2d5eade2 100644 --- a/main/manager-web/src/apis/module/agent.js +++ b/main/manager-web/src/apis/module/agent.js @@ -84,7 +84,7 @@ export default { // 新增方法:获取智能体模板 getAgentTemplate(callback) { // 移除templateName参数 RequestService.sendRequest() - .url(`${getServiceUrl()}/agent/template`) + .url(`${getServiceUrl()}/agent/template/all`) .method('GET') .success((res) => { RequestService.clearRequestTime(); @@ -97,6 +97,24 @@ export default { }); }).send(); }, + + // 新增:获取智能体模板分页列表 + getAgentTemplatesPage(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/template/page`) + .method('GET') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取模板分页列表失败:', err); + RequestService.reAjaxFun(() => { + this.getAgentTemplatesPage(params, callback); + }); + }).send(); + }, // 获取智能体会话列表 getAgentSessions(agentId, params, callback) { RequestService.sendRequest() @@ -265,4 +283,71 @@ export default { }); }).send(); }, + // 在文件末尾(在最后一个方法后,大括号前)添加以下方法: + // 新增智能体模板 + addAgentTemplate(templateData, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/template`) + .method('POST') + .data(templateData) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.addAgentTemplate(templateData, callback); + }); + }).send(); + }, + + // 更新智能体模板 + updateAgentTemplate(templateData, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/template`) + .method('PUT') + .data(templateData) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.updateAgentTemplate(templateData, callback); + }); + }).send(); + }, + + // 删除智能体模板 + deleteAgentTemplate(id, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/template/${id}`) + .method('DELETE') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.deleteAgentTemplate(id, callback); + }); + }).send(); + }, + + // 批量删除智能体模板 + batchDeleteAgentTemplate(ids, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/template/batch-delete`) + .method('DELETE') + .data(ids) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.batchDeleteAgentTemplate(ids, callback); + }); + }).send(); + }, } diff --git a/main/manager-web/src/components/AgentTemplateDialog.vue b/main/manager-web/src/components/AgentTemplateDialog.vue new file mode 100644 index 00000000..99586aa2 --- /dev/null +++ b/main/manager-web/src/components/AgentTemplateDialog.vue @@ -0,0 +1,106 @@ + + + + + \ No newline at end of file diff --git a/main/manager-web/src/components/DefaultRoleDialog.vue b/main/manager-web/src/components/DefaultRoleDialog.vue new file mode 100644 index 00000000..d68299df --- /dev/null +++ b/main/manager-web/src/components/DefaultRoleDialog.vue @@ -0,0 +1,322 @@ + + + + + + + \ No newline at end of file diff --git a/main/manager-web/src/components/HeaderBar.vue b/main/manager-web/src/components/HeaderBar.vue index 2042d335..c14804cc 100644 --- a/main/manager-web/src/components/HeaderBar.vue +++ b/main/manager-web/src/components/HeaderBar.vue @@ -35,11 +35,11 @@ {{ $t('header.otaManagement') }} + :style="{ filter: $route.path === '/dict-management' || $route.path === '/params-management' || $route.path === '/provider-management' || $route.path === '/server-side-management' || $route.path === '/agent-template-management' ? 'brightness(0) invert(1)' : 'None' }" /> {{ $t('header.paramDictionary') }} @@ -56,10 +56,14 @@ {{ $t('header.serverSideManagement') }} + + + {{ $t('header.agentTemplate') }} + - +
@@ -193,6 +197,10 @@ export default { goServerSideManagement() { this.$router.push('/server-side-management') }, + // 添加默认角色模板管理导航方法 + goAgentTemplateManagement() { + this.$router.push('/agent-template-management') + }, // 获取用户信息 fetchUserInfo() { userApi.getUserInfo(({ data }) => { diff --git a/main/manager-web/src/i18n/zh_CN.js b/main/manager-web/src/i18n/zh_CN.js index 946e977f..8a3c8606 100644 --- a/main/manager-web/src/i18n/zh_CN.js +++ b/main/manager-web/src/i18n/zh_CN.js @@ -7,6 +7,7 @@ export default { 'header.paramDictionary': '参数字典', 'header.paramManagement': '参数管理', 'header.dictManagement': '字典管理', + 'header.agentTemplate': '默认角色模板', // 字典数据对话框相关 'dictDataDialog.addDictData': '新增字典数据', diff --git a/main/manager-web/src/router/index.js b/main/manager-web/src/router/index.js index 867e6c2d..fae7de6a 100644 --- a/main/manager-web/src/router/index.js +++ b/main/manager-web/src/router/index.js @@ -124,6 +124,29 @@ const routes = [ return import('../views/ProviderManagement.vue') } }, + // 添加默认角色管理路由 + { + path: '/agent-template-management', + name: 'AgentTemplateManagement', + component: function () { + return import('../views/AgentTemplateManagement.vue') + } + }, + // 添加模板快速配置路由 + { + path: '/template-quick-config', + name: 'TemplateQuickConfig', + component: function () { + return import('../views/TemplateQuickConfig.vue') + } + }, + { + path: '/provider-management', + name: 'ProviderManagement', + component: function () { + return import('../views/ProviderManagement.vue') + } + }, ] const router = new VueRouter({ base: process.env.VUE_APP_PUBLIC_PATH || '/', @@ -145,7 +168,7 @@ VueRouter.prototype.push = function push(location) { } // 需要登录才能访问的路由 -const protectedRoutes = ['home', 'RoleConfig', 'DeviceManagement', 'UserManagement', 'ModelConfig'] +const protectedRoutes = ['home', 'RoleConfig', 'DeviceManagement', 'UserManagement', 'ModelConfig', 'TemplateQuickConfig'] // 路由守卫 router.beforeEach((to, from, next) => { diff --git a/main/manager-web/src/views/AgentTemplateManagement.vue b/main/manager-web/src/views/AgentTemplateManagement.vue new file mode 100644 index 00000000..91b5e8cf --- /dev/null +++ b/main/manager-web/src/views/AgentTemplateManagement.vue @@ -0,0 +1,731 @@ + + + + + \ No newline at end of file diff --git a/main/manager-web/src/views/TemplateQuickConfig.vue b/main/manager-web/src/views/TemplateQuickConfig.vue new file mode 100644 index 00000000..49c4ec37 --- /dev/null +++ b/main/manager-web/src/views/TemplateQuickConfig.vue @@ -0,0 +1,738 @@ + + + + + \ No newline at end of file