From a5e62e6885aff843ea6a30d34635ea8b8e634290 Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Fri, 27 Mar 2026 12:01:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(project):=20=E5=AE=9E=E7=8E=B0AI=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=88=9D=E5=A7=8B=E5=8C=96=E5=8F=8A=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增ProjectController,支持文件上传生成项目初始化预览数据 - 添加接口确认并保存用户确认后的项目初始化数据到数据库 - ProjectService接口新增预览数据生成与保存方法定义 - 实现ProjectServiceImpl,支持AI解析项目文档生成结构化数据 - 集成文件上传至OSS并读取内容进行项目数据生成 - 实现数据库保存逻辑,涵盖项目基本信息、里程碑、任务及依赖 - 完成项目成员、资源、风险和时间节点的转换及持久化 - 完善日志与异常处理,确保流程可跟踪及失败提示 - 定义并使用系统与用户提示词模板用于AI交互生成项目数据 --- .../controller/project/ProjectController.java | 44 +++++++++++++---- .../service/project/ProjectService.java | 14 +++--- .../project/impl/ProjectServiceImpl.java | 49 ++++++------------- 3 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/main/java/cn/yinlihupo/controller/project/ProjectController.java b/src/main/java/cn/yinlihupo/controller/project/ProjectController.java index 0c59f01..f5283e9 100644 --- a/src/main/java/cn/yinlihupo/controller/project/ProjectController.java +++ b/src/main/java/cn/yinlihupo/controller/project/ProjectController.java @@ -24,26 +24,50 @@ public class ProjectController { private final OssService ossService; /** - * 上传文件并生成项目初始化数据 + * 上传文件并生成项目初始化预览数据(不入库) * * @param file 项目资料文件 - * @return 项目初始化结构化数据 + * @return 项目初始化结构化数据预览 */ - @PostMapping("/from-file") - public BaseResponse generateFromFile(@RequestParam("file") MultipartFile file) { - log.info("收到项目初始化请求(文件上传), 文件名: {}", file.getOriginalFilename()); + @PostMapping("/preview") + public BaseResponse generatePreview(@RequestParam("file") MultipartFile file) { + log.info("收到项目初始化预览请求, 文件名: {}", file.getOriginalFilename()); if (file.isEmpty()) { return ResultUtils.error("上传文件不能为空"); } try { - // 上传文件、生成项目初始化数据并保存到数据库 - ProjectInitResult result = projectService.generateAndSaveProject(file); - return ResultUtils.success("项目初始化成功", result); + // 上传文件并生成项目初始化预览数据(不入库) + ProjectInitResult result = projectService.generateProjectPreview(file); + return ResultUtils.success("项目预览数据生成成功", result); } catch (Exception e) { - log.error("项目初始化失败: {}", e.getMessage(), e); - return ResultUtils.error("项目初始化失败: " + e.getMessage()); + log.error("项目预览生成失败: {}", e.getMessage(), e); + return ResultUtils.error("项目预览生成失败: " + e.getMessage()); + } + } + + /** + * 确认并保存项目初始化数据 + * + * @param result 用户确认后的项目初始化数据 + * @return 保存后的项目初始化数据 + */ + @PostMapping("/confirm") + public BaseResponse confirmAndSave(@RequestBody ProjectInitResult result) { + log.info("收到项目初始化确认请求"); + + if (result == null || result.getProject() == null) { + return ResultUtils.error("项目数据不能为空"); + } + + try { + // 保存项目数据到数据库 + ProjectInitResult savedResult = projectService.saveProjectData(result); + return ResultUtils.success("项目创建成功", savedResult); + } catch (Exception e) { + log.error("项目保存失败: {}", e.getMessage(), e); + return ResultUtils.error("项目保存失败: " + e.getMessage()); } } diff --git a/src/main/java/cn/yinlihupo/service/project/ProjectService.java b/src/main/java/cn/yinlihupo/service/project/ProjectService.java index dff2616..6df373e 100644 --- a/src/main/java/cn/yinlihupo/service/project/ProjectService.java +++ b/src/main/java/cn/yinlihupo/service/project/ProjectService.java @@ -27,18 +27,18 @@ public interface ProjectService { ProjectInitResult generateProjectFromFile(String fileUrl, String fileType); /** - * 上传文件并生成项目初始化数据,同时保存到数据库 + * 上传文件并生成项目初始化预览数据(不入库) * * @param file 项目资料文件 - * @return 项目初始化结果 + * @return 项目初始化预览结果 */ - ProjectInitResult generateAndSaveProject(MultipartFile file); + ProjectInitResult generateProjectPreview(MultipartFile file); /** - * 根据项目资料内容生成并保存项目初始化数据 + * 保存项目初始化数据到数据库 * - * @param content 项目资料文本内容 - * @return 项目初始化结果 + * @param result 用户确认后的项目初始化数据 + * @return 保存后的项目初始化结果(包含生成的ID等信息) */ - ProjectInitResult generateAndSaveProjectFromContent(String content); + ProjectInitResult saveProjectData(ProjectInitResult result); } diff --git a/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java b/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java index 6d5b7b3..e0afcae 100644 --- a/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java +++ b/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java @@ -200,9 +200,8 @@ public class ProjectServiceImpl implements ProjectService { } @Override - @Transactional(rollbackFor = Exception.class) - public ProjectInitResult generateAndSaveProject(MultipartFile file) { - log.info("开始上传文件并生成项目初始化数据, 文件名: {}", file.getOriginalFilename()); + public ProjectInitResult generateProjectPreview(MultipartFile file) { + log.info("开始上传文件并生成项目初始化预览数据, 文件名: {}", file.getOriginalFilename()); try { // 1. 上传文件到OSS @@ -215,50 +214,34 @@ public class ProjectServiceImpl implements ProjectService { throw new RuntimeException("无法读取文件内容: " + fileUrl); } - // 3. 生成并保存项目数据 - return generateAndSaveProjectFromContent(content); + // 3. 调用AI生成项目预览数据(不入库) + return generateProjectFromContent(content); } catch (Exception e) { - log.error("项目初始化失败: {}", e.getMessage(), e); - throw new RuntimeException("项目初始化失败: " + e.getMessage(), e); + log.error("项目预览生成失败: {}", e.getMessage(), e); + throw new RuntimeException("项目预览生成失败: " + e.getMessage(), e); } } @Override @Transactional(rollbackFor = Exception.class) - public ProjectInitResult generateAndSaveProjectFromContent(String content) { - log.info("开始生成并保存项目初始化数据"); + public ProjectInitResult saveProjectData(ProjectInitResult result) { + log.info("开始保存项目初始化数据"); - ProjectInitResult result; + if (result == null || result.getProject() == null) { + throw new RuntimeException("项目数据为空"); + } try { - // 1. 调用AI生成项目数据 - String userPrompt = "请根据以下项目资料,生成完整的项目初始化结构化数据:\n\n" + - content + "\n\n" + - "请严格按照系统提示词中的JSON格式输出,确保所有字段都包含合理的值。"; - - // 创建 BeanOutputConverter 用于转换响应 - BeanOutputConverter outputConverter = new BeanOutputConverter<>(ProjectInitResult.class); - - var chatResponse = chatClient.prompt() - .system(PROJECT_INIT_SYSTEM_PROMPT) - .user(userPrompt) - .call() - .chatResponse(); - - // 使用 BeanOutputConverter 手动转换响应内容 - String responseContent = chatResponse.getResult().getOutput().getText(); - result = outputConverter.convert(responseContent); - - // 2. 保存项目数据到数据库 - Long projectId = saveProjectData(result); + // 保存项目数据到数据库 + Long projectId = saveProjectDataToDb(result); log.info("项目初始化数据保存成功, projectId: {}", projectId); return result; } catch (Exception e) { - log.error("项目初始化失败: {}", e.getMessage(), e); - throw new RuntimeException("项目初始化失败: " + e.getMessage(), e); + log.error("项目保存失败: {}", e.getMessage(), e); + throw new RuntimeException("项目保存失败: " + e.getMessage(), e); } } @@ -268,7 +251,7 @@ public class ProjectServiceImpl implements ProjectService { * @param result AI生成的项目初始化结果 * @return 项目ID */ - private Long saveProjectData(ProjectInitResult result) { + private Long saveProjectDataToDb(ProjectInitResult result) { if (result == null || result.getProject() == null) { throw new RuntimeException("项目数据为空"); }