diff --git a/src/main/java/com/dsideal/base/AI/Controller/YunNanAiController.java b/src/main/java/com/dsideal/base/AI/Controller/YunNanAiController.java index 8442bfdc..e31a05a9 100644 --- a/src/main/java/com/dsideal/base/AI/Controller/YunNanAiController.java +++ b/src/main/java/com/dsideal/base/AI/Controller/YunNanAiController.java @@ -1,11 +1,20 @@ package com.dsideal.base.AI.Controller; +import com.dsideal.base.AI.Generator.WordGenerator; import com.dsideal.base.AI.Model.YunNanModel; +import com.dsideal.base.Util.CallDeepSeek; import com.jfinal.aop.Before; import com.jfinal.core.Controller; import com.jfinal.ext.interceptor.GET; import com.jfinal.kit.PathKit; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + public class YunNanAiController extends Controller { YunNanModel ym = new YunNanModel(); @@ -18,13 +27,124 @@ public class YunNanAiController extends Controller { */ @Before({GET.class}) public void compareShiZhou(String shiZhouA, String shiZhouB) { - String[] regions = {shiZhouA, shiZhouB}; - // 第一步:数据获取 - String dataContent = ym.collectEducationData(regions); - String analysisPrompt = ym.createAnalysisPrompt(dataContent, regions); + // 设置SSE响应头 + getResponse().setContentType("text/event-stream"); + getResponse().setCharacterEncoding("UTF-8"); + getResponse().setHeader("Cache-Control", "no-cache"); + getResponse().setHeader("Connection", "keep-alive"); + getResponse().setHeader("Access-Control-Allow-Origin", "*"); + getResponse().setHeader("Access-Control-Allow-Headers", "Cache-Control"); + + try { + PrintWriter writer = getResponse().getWriter(); + + String[] regions = {shiZhouA, shiZhouB}; + // 第一步:数据获取 + String dataContent = ym.collectEducationData(regions); + String analysisPrompt = ym.createAnalysisPrompt(dataContent, regions); + + // 生成输出文件名相关信息 + String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String regionName = String.join("与", regions); + String uploadPath = PathKit.getWebRootPath() + "/upload"; + + // 发送开始事件 + writer.write("data: {\"type\":\"start\",\"message\":\"开始分析数据...\"}\n\n"); + writer.flush(); - // 第二步:AI分析并生成Word文档 - ym.generateWordReport(analysisPrompt, regions, PathKit.getWebRootPath() + "/upload"); - } + // 第二步:AI分析并生成Word文档 + CallDeepSeek.callDeepSeekStream(analysisPrompt, new CallDeepSeek.SSEListener() { + private StringBuilder fullResponse = new StringBuilder(); + + @Override + public void onData(String data) { + try { + fullResponse.append(data); + // 发送分析数据 + String escapedData = data.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r"); + writer.write("data: {\"type\":\"analysis\",\"content\":\"" + escapedData + "\"}\n\n"); + writer.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + @Override + public void onComplete(String response) { + try { + // 发送分析完成事件 + writer.write("data: {\"type\":\"analysis_complete\",\"message\":\"分析完成,开始生成文档...\"}\n\n"); + writer.flush(); + + // 使用完整的分析结果 + String analysisResult = fullResponse.toString(); + + // 生成Word文档 + String wordOutputPath = uploadPath + "/" + regionName + "_教育分析报告_" + timestamp + ".docx"; + String wordFilePath = WordGenerator.generateWordDocument(analysisResult, wordOutputPath, regions); + + // 构建返回的文件信息 + Map result = new HashMap<>(); + result.put("success", true); + result.put("message", "报告生成完成"); + result.put("wordFile", "/upload/" + regionName + "_教育分析报告_" + timestamp + ".docx"); + result.put("wordFilePath", wordFilePath); + result.put("timestamp", timestamp); + result.put("regions", regions); + + // 发送完成事件和文件地址 + String resultJson = com.jfinal.kit.JsonKit.toJson(result); + writer.write("data: {\"type\":\"complete\",\"result\":" + resultJson + "}\n\n"); + writer.flush(); + + // 发送结束标记 + writer.write("data: [DONE]\n\n"); + writer.flush(); + + // 最后使用renderJson返回结果(用于非SSE客户端) + renderJson(result); + + } catch (Exception e) { + try { + Map errorResult = new HashMap<>(); + errorResult.put("success", false); + errorResult.put("message", "生成文档时出错: " + e.getMessage()); + + String errorJson = com.jfinal.kit.JsonKit.toJson(errorResult); + writer.write("data: {\"type\":\"error\",\"result\":" + errorJson + "}\n\n"); + writer.flush(); + + renderJson(errorResult); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + @Override + public void onError(String error) { + try { + Map errorResult = new HashMap<>(); + errorResult.put("success", false); + errorResult.put("message", "DeepSeek分析出错: " + error); + + String errorJson = com.jfinal.kit.JsonKit.toJson(errorResult); + writer.write("data: {\"type\":\"error\",\"result\":" + errorJson + "}\n\n"); + writer.flush(); + + renderJson(errorResult); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + } catch (IOException e) { + // 如果SSE失败,降级为普通JSON响应 + Map errorResult = new HashMap<>(); + errorResult.put("success", false); + errorResult.put("message", "SSE连接失败: " + e.getMessage()); + renderJson(errorResult); + } + } }