diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/AiAgentController.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/AiAgentController.java index 46e8acfed7..0fdede9cb2 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/AiAgentController.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/AiAgentController.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.tik.muye.aiagent; import cn.iocoder.yudao.module.tik.muye.aiagent.dal.AiAgentDO; import cn.iocoder.yudao.module.tik.muye.aiagent.service.AiAgentService; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportExcelVO; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportRespVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentPageReqVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentRespVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentSaveReqVO; @@ -18,6 +20,8 @@ import jakarta.servlet.http.*; import java.util.*; import java.io.IOException; +import org.springframework.web.multipart.MultipartFile; + import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -101,4 +105,32 @@ public class AiAgentController { BeanUtils.toBean(list, AiAgentRespVO.class)); } + @GetMapping("/get-import-template") + @Operation(summary = "获得AI智能体导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 构造示例数据 + List list = Arrays.asList( + AiAgentImportExcelVO.builder() + .agentId("12345") + .agentName("示例智能体") + .categoryName("文案创作") + .icon("https://example.com/icon.png") + .status(1) + .description("这是一个示例智能体的描述") + .systemPrompt("你是一个有帮助的AI助手") + .remark("备注信息") + .build() + ); + // 导出 Excel + ExcelUtils.write(response, "AI智能体导入模板.xls", "智能体列表", AiAgentImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入AI智能体") + @PreAuthorize("@ss.hasPermission('muye:ai-agent:create')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file) throws Exception { + List list = ExcelUtils.read(file, AiAgentImportExcelVO.class); + return success(aiAgentService.importAiAgentList(list)); + } + } \ No newline at end of file diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentService.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentService.java index c79e835eb0..8ca7792f49 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentService.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentService.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.tik.muye.aiagent.service; import java.util.*; import cn.iocoder.yudao.module.tik.muye.aiagent.dal.AiAgentDO; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportExcelVO; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportRespVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentPageReqVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentSaveReqVO; import jakarta.validation.*; @@ -67,4 +69,12 @@ public interface AiAgentService { */ List getEnabledAgentList(); + /** + * 批量导入AI智能体 + * + * @param importAgents 导入数据列表 + * @return 导入结果 + */ + AiAgentImportRespVO importAiAgentList(List importAgents); + } \ No newline at end of file diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentServiceImpl.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentServiceImpl.java index 766e9919b1..1d8d05a844 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentServiceImpl.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/service/AiAgentServiceImpl.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.tik.muye.aiagent.service; import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.tik.muye.aiagent.dal.AiAgentDO; import cn.iocoder.yudao.module.tik.muye.aiagent.mapper.AiAgentMapper; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportExcelVO; +import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentImportRespVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentPageReqVO; import cn.iocoder.yudao.module.tik.muye.aiagent.vo.AiAgentSaveReqVO; +import cn.hutool.core.collection.CollUtil; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; @@ -12,6 +16,7 @@ import org.springframework.validation.annotation.Validated; import java.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; /** @@ -80,4 +85,71 @@ public class AiAgentServiceImpl implements AiAgentService { return aiAgentMapper.selectEnabledList(); } + @Override + public AiAgentImportRespVO importAiAgentList(List importAgents) { + // 1. 参数校验 + if (CollUtil.isEmpty(importAgents)) { + throw exception(new ErrorCode(1005, "导入数据不能为空")); + } + + // 2. 初始化返回结果 + AiAgentImportRespVO respVO = AiAgentImportRespVO.builder() + .createAgentNames(new ArrayList<>()) + .failureAgentNames(new LinkedHashMap<>()) + .build(); + + // 3. 获取当前登录用户信息 + Long operatorId = SecurityFrameworkUtils.getLoginUserId(); + String operatorName = String.valueOf(SecurityFrameworkUtils.getLoginUserNickname()); + + // 4. 遍历逐条处理 + importAgents.forEach(importAgent -> { + try { + // 4.1 必填字段校验 + if (importAgent.getAgentId() == null || importAgent.getAgentId().isEmpty()) { + throw new RuntimeException("智能体ID不能为空"); + } + if (importAgent.getAgentName() == null || importAgent.getAgentName().isEmpty()) { + throw new RuntimeException("智能体名称不能为空"); + } + if (importAgent.getCategoryName() == null || importAgent.getCategoryName().isEmpty()) { + throw new RuntimeException("分类不能为空"); + } + if (importAgent.getIcon() == null || importAgent.getIcon().isEmpty()) { + throw new RuntimeException("图标URL不能为空"); + } + if (importAgent.getStatus() == null) { + throw new RuntimeException("状态不能为空"); + } + if (importAgent.getDescription() == null || importAgent.getDescription().isEmpty()) { + throw new RuntimeException("设定描述不能为空"); + } + if (importAgent.getSystemPrompt() == null || importAgent.getSystemPrompt().isEmpty()) { + throw new RuntimeException("预置提示词不能为空"); + } + + // 4.2 检查 agentId 是否已存在 + AiAgentDO existAgent = aiAgentMapper.selectOne( + new LambdaQueryWrapperX() + .eq(AiAgentDO::getAgentId, importAgent.getAgentId()) + ); + if (existAgent != null) { + respVO.getFailureAgentNames().put(importAgent.getAgentName(), "智能体ID已存在"); + return; + } + + // 4.3 创建智能体 + AiAgentDO aiAgent = BeanUtils.toBean(importAgent, AiAgentDO.class); + aiAgent.setOperatorId(operatorId); + aiAgent.setOperatorName(operatorName); + aiAgentMapper.insert(aiAgent); + respVO.getCreateAgentNames().add(importAgent.getAgentName()); + } catch (Exception ex) { + respVO.getFailureAgentNames().put(importAgent.getAgentName(), ex.getMessage()); + } + }); + + return respVO; + } + } \ No newline at end of file diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportExcelVO.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportExcelVO.java new file mode 100644 index 0000000000..ead27a1733 --- /dev/null +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportExcelVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.tik.muye.aiagent.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * AI智能体导入 Excel VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - AI智能体导入 Excel VO") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AiAgentImportExcelVO { + + @ExcelProperty("智能体ID") + private String agentId; + + @ExcelProperty("智能体名称") + private String agentName; + + @ExcelProperty("分类") + private String categoryName; + + @ExcelProperty("图标URL") + private String icon; + + @ExcelProperty("状态") + private Integer status; + + @ExcelProperty("设定描述") + private String description; + + @ExcelProperty("预置提示词") + private String systemPrompt; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportRespVO.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportRespVO.java new file mode 100644 index 0000000000..9b5c52a764 --- /dev/null +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/muye/aiagent/vo/AiAgentImportRespVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.tik.muye.aiagent.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * AI智能体导入结果 Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - AI智能体导入结果 Response VO") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AiAgentImportRespVO { + + @Schema(description = "创建成功的智能体名称数组") + @Builder.Default + private List createAgentNames = new ArrayList<>(); + + @Schema(description = "导入失败的智能体集合,key 为智能体名称,value 为失败原因") + @Builder.Default + private Map failureAgentNames = new LinkedHashMap<>(); + +} diff --git a/yudao-ui-admin-vue3/public/ai_agent_import_template.xlsx b/yudao-ui-admin-vue3/public/ai_agent_import_template.xlsx new file mode 100644 index 0000000000..38518e4a18 Binary files /dev/null and b/yudao-ui-admin-vue3/public/ai_agent_import_template.xlsx differ diff --git a/yudao-ui-admin-vue3/src/api/muye/aiagent/index.ts b/yudao-ui-admin-vue3/src/api/muye/aiagent/index.ts index cdc33dc964..000d554453 100644 --- a/yudao-ui-admin-vue3/src/api/muye/aiagent/index.ts +++ b/yudao-ui-admin-vue3/src/api/muye/aiagent/index.ts @@ -6,7 +6,7 @@ export interface AiAgent { id: number; // 主键 agentId?: string; // 智能体ID agentName?: string; // 智能体名称 - categoryId?: number; // 分类ID + categoryName?: string; // 分类名称 icon?: string; // 图标URL status?: number; // 状态(0-禁用 1-启用) description?: string; // 设定描述 @@ -50,4 +50,9 @@ export const AiAgentApi = { exportAiAgent: async (params) => { return await request.download({ url: `/muye/ai-agent/export-excel`, params }) }, + + // 下载AI智能体导入模板 + importAiAgentTemplate: async () => { + return await request.download({ url: `/muye/ai-agent/get-import-template` }) + } } \ No newline at end of file diff --git a/yudao-ui-admin-vue3/src/views/muye/aiagent/AiAgentForm.vue b/yudao-ui-admin-vue3/src/views/muye/aiagent/AiAgentForm.vue index 22b46e5519..224c6fc577 100644 --- a/yudao-ui-admin-vue3/src/views/muye/aiagent/AiAgentForm.vue +++ b/yudao-ui-admin-vue3/src/views/muye/aiagent/AiAgentForm.vue @@ -13,20 +13,23 @@ + + + - 禁用 - 启用 + 禁用 + 启用 - + - + @@ -41,40 +44,35 @@ diff --git a/yudao-ui-admin-vue3/src/views/muye/aiagent/index.vue b/yudao-ui-admin-vue3/src/views/muye/aiagent/index.vue index a5c30789ce..5802a1a518 100644 --- a/yudao-ui-admin-vue3/src/views/muye/aiagent/index.vue +++ b/yudao-ui-admin-vue3/src/views/muye/aiagent/index.vue @@ -17,10 +17,13 @@ class="!w-240px" /> + + + - - + + @@ -43,6 +46,14 @@ > 导出 + + 导入 + - - - - - - - - - - + + + + + + + + + + + + +