From 7af7c62fd65505d9be7d792c817f0b407375e9a4 Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Fri, 13 Jun 2025 18:38:42 +0800 Subject: [PATCH] 'commit' --- .../com/dsideal/base/Tools/AiGenerate.java | 344 +++--------------- .../com/dsideal/base/Tools/DataCollector.java | 82 +++++ .../com/dsideal/base/Tools/PptGenerator.java | 112 ++++++ .../com/dsideal/base/Tools/WordGenerator.java | 183 ++++++++++ ...源对比分析报告_20250613_183737.docx | Bin 0 -> 4257 bytes 5 files changed, 420 insertions(+), 301 deletions(-) create mode 100644 src/main/java/com/dsideal/base/Tools/DataCollector.java create mode 100644 src/main/java/com/dsideal/base/Tools/PptGenerator.java create mode 100644 src/main/java/com/dsideal/base/Tools/WordGenerator.java create mode 100644 教育资源对比分析报告_20250613_183737.docx diff --git a/src/main/java/com/dsideal/base/Tools/AiGenerate.java b/src/main/java/com/dsideal/base/Tools/AiGenerate.java index c119bc89..9557c173 100644 --- a/src/main/java/com/dsideal/base/Tools/AiGenerate.java +++ b/src/main/java/com/dsideal/base/Tools/AiGenerate.java @@ -1,72 +1,61 @@ package com.dsideal.base.Tools; -import com.alibaba.fastjson.JSONObject; import com.dsideal.base.BaseApplication; import com.dsideal.base.DataEase.Model.DataEaseModel; import com.dsideal.base.Plugin.YamlProp; import com.dsideal.base.Tools.Util.CallDeepSeek; import com.dsideal.base.Tools.Util.LocalMysqlConnectUtil; -import com.dsideal.base.Tools.Util.PptAIKit; -import com.jfinal.plugin.activerecord.Db; -import com.jfinal.plugin.activerecord.Record; -import cn.hutool.json.JSONUtil; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFParagraph; -import org.apache.poi.xwpf.usermodel.XWPFRun; -import org.apache.poi.xwpf.usermodel.ParagraphAlignment; -import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; -public class AiGenerate extends PptAIKit { +/** + * AI生成器主类 - 协调数据获取、Word生成和PPT生成 + */ +public class AiGenerate { public static DataEaseModel dm = new DataEaseModel(); public static void main(String[] args) { - //加载配置文件 + try { + // 初始化配置 + initializeConfiguration(); + + // 定义对比地区 + String[] regions = {"文山州", "楚雄州"}; + + // 第一步:数据获取 + System.out.println("=== 开始数据收集 ==="); + String dataContent = DataCollector.collectEducationData(regions); + String analysisPrompt = DataCollector.createAnalysisPrompt(dataContent, regions); + + // 第二步:AI分析并生成Word文档 + System.out.println("=== 开始AI分析和Word文档生成 ==="); + generateWordReport(analysisPrompt, regions); + + } catch (Exception e) { + System.err.println("程序执行出错: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 初始化配置 + */ + private static void initializeConfiguration() { String configFile = "application.yaml"; BaseApplication.PropKit = new YamlProp(configFile); LocalMysqlConnectUtil.Init(); - - // 查询教育资源配置发展预测相关表 - String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dataease' AND TABLE_NAME LIKE 'excel_报告-教育资源配置发展预测%';"; - List tableList = Db.find(sql); - - String[] biJiao = new String[]{"文山州", "楚雄州"}; - StringBuilder dataContent = new StringBuilder(); - - // 收集两个州的数据 - dataContent.append("教育资源配置发展预测数据对比分析\n\n"); - dataContent.append("对比州市:").append(String.join(" vs ", biJiao)).append("\n\n"); - - for (Record record : tableList) { - String tableName = record.getStr("TABLE_NAME"); - dataContent.append("数据表:").append(tableName).append("\n"); - - for (int j = 0; j < biJiao.length; j++) { - sql = "select * from `" + tableName + "` where `行政区划`=?"; - List listContent = Db.use(DataEaseModel.DB_NAME).find(sql, biJiao[j]); - - if (!listContent.isEmpty()) { - dataContent.append("\n").append(biJiao[j]).append("数据:\n"); - for (Record dataRecord : listContent) { - dataContent.append(JSONUtil.toJsonPrettyStr(dataRecord.getColumns())).append("\n"); - } - } else { - dataContent.append("\n").append(biJiao[j]).append(":无相关数据\n"); - } - } - dataContent.append("\n----------------------------------------\n\n"); - } - - // 构建分析提示词 - String analysisPrompt = createAnalysisPrompt(dataContent.toString()); - - + System.out.println("配置初始化完成"); + } + + /** + * 生成Word报告 + */ + private static void generateWordReport(String analysisPrompt, String[] regions) { // 生成输出文件路径 String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String outputPath = "教育资源对比分析报告_" + timestamp + ".docx"; + System.out.println("开始调用DeepSeek进行数据分析..."); // 调用DeepSeek进行分析 @@ -85,14 +74,13 @@ public class AiGenerate extends PptAIKit { System.out.println("\n\n=== Word文档分析完成 ==="); try { - // 使用Apache POI生成Word文档 - generateWordDocument(fullResponse.toString(), outputPath, biJiao); + // 生成Word文档 + WordGenerator.generateWordDocument(fullResponse.toString(), outputPath, regions); System.out.println("Word分析报告已保存到: " + outputPath); - // 生成PPT - // 生成PPT - System.out.println("\n\n=== 开始生成PPT ==="); - generatePptPresentation(analysisPrompt, biJiao); +// // 第三步:生成PPT +// System.out.println("\n\n=== 开始生成PPT ==="); +// PptGenerator.generatePptPresentation(fullResponse.toString(), regions); } catch (Exception e) { System.err.println("保存文件时出错: " + e.getMessage()); @@ -106,250 +94,4 @@ public class AiGenerate extends PptAIKit { } }); } - - /** - * 创建PPT生成提示词 - */ - private static String createPptPrompt(String dataContent, String[] cities) { - try { - // 构建给 DeepSeek 的精简提示词 - String deepseekPrompt = "你是一位专业的教育数据分析专家,请将以下教育资源配置数据进行精简总结," + - "提取关键信息和对比要点,控制在300字以内,重点突出" + String.join("与", cities) + "的对比差异:\n\n" + - dataContent; - - System.out.println("正在调用 DeepSeek 精简数据..."); - - // 调用 DeepSeek 获取精简内容 - String simplifiedContent = CallDeepSeek.callDeepSeek(deepseekPrompt); - - if (simplifiedContent != null && !simplifiedContent.trim().isEmpty()) { - System.out.println("DeepSeek 精简完成,精简后长度: " + simplifiedContent.length()); - - // 使用精简后的内容构建 PPT 提示词 - return "请基于以下教育资源配置数据,为" + String.join("与", cities) + - "教育资源配置对比分析创建一个专业的PPT大纲。\n\n" + - "PPT应包含以下主要部分:\n" + - "1. 封面 - 标题和基本信息\n" + - "2. 目录 - 分析框架\n" + - "3. 数据概览 - 关键指标对比\n" + - "4. 详细分析 - 各维度深入对比\n" + - "5. 问题识别 - 存在的主要问题\n" + - "6. 建议方案 - 改进措施\n" + - "7. 总结 - 结论和展望\n\n" + - "请确保内容简洁明了,适合PPT展示。\n\n" + - "=== 精简后的关键数据 ===\n" + simplifiedContent; - } else { - System.out.println("DeepSeek 调用失败,使用基础提示词"); - return createBasicPptPrompt(cities); - } - - } catch (Exception e) { - System.err.println("调用 DeepSeek 精简数据时出错: " + e.getMessage()); - e.printStackTrace(); - // 如果 DeepSeek 调用失败,返回基础提示词 - return createBasicPptPrompt(cities); - } - } - - /** - * 创建基础PPT提示词(作为备用方案) - */ - private static String createBasicPptPrompt(String[] cities) { - return "请为" + String.join("与", cities) + - "教育资源配置对比分析创建一个专业的PPT大纲。\n\n" + - "PPT应包含以下主要部分:\n" + - "1. 封面 - 标题和基本信息\n" + - "2. 目录 - 分析框架\n" + - "3. 数据概览 - 关键指标对比\n" + - "4. 详细分析 - 各维度深入对比\n" + - "5. 问题识别 - 存在的主要问题\n" + - "6. 建议方案 - 改进措施\n" + - "7. 总结 - 结论和展望\n\n" + - "请基于教育资源配置的一般分析框架,重点关注对比分析结果。"; - } - - /** - * 生成PPT演示文稿 - */ - private static void generatePptPresentation(String analysisContent, String[] biJiao) { - try { - String uid = "test"; - // 第一步:使用DeepSeek生成简化的PPT提示词 - String simplifiedPptPrompt = createPptPrompt(analysisContent, biJiao); - - // 创建 api token (有效期2小时,建议缓存到redis,同一个 uid 创建时之前的 token 会在10秒内失效) - String apiToken = PptAIKit.createApiToken(uid, null); - System.out.println("api token: " + apiToken); - - // 生成大纲 - System.out.println("\n\n========== 正在生成大纲 =========="); - System.out.println(simplifiedPptPrompt.length()); - System.out.println(simplifiedPptPrompt); - String outline = PptAIKit.generateOutline(apiToken, null, null, simplifiedPptPrompt); - - // 生成大纲内容 - System.out.println("\n\n========== 正在生成大纲内容 =========="); - String markdown = PptAIKit.generateContent(apiToken, outline, null, simplifiedPptPrompt); - - // 随机一个模板 - System.out.println("\n\n========== 随机选择模板 =========="); - String templateId = PptAIKit.randomOneTemplateId(apiToken); - System.out.println(templateId); - - // 生成PPT - System.out.println("\n\n========== 正在生成PPT =========="); - JSONObject pptInfo = PptAIKit.generatePptx(apiToken, templateId, markdown, false); - String pptId = pptInfo.getString("id"); - System.out.println("pptId: " + pptId); - System.out.println("ppt主题:" + pptInfo.getString("subject")); - System.out.println("ppt封面:" + pptInfo.getString("coverUrl") + "?token=" + apiToken); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 创建分析提示词 - */ - private static String createAnalysisPrompt(String dataContent) { - return "你是一位专业的教育数据分析专家,请基于以下数据对文山州和楚雄州的教育资源配置情况进行深入对比分析。\n\n" + - "重要要求:请生成结构化的纯文本格式报告,使用清晰的段落结构,不要使用markdown语法。\n\n" + - "请按照以下结构进行分析并生成专业的分析报告:\n\n" + - "1. 执行摘要\n" + - " 简要概述两州教育资源配置的整体情况和主要发现\n\n" + - "2. 数据概览\n" + - " 两州基本教育数据对比和关键指标汇总\n\n" + - "3. 详细对比分析\n" + - " 教育资源配置水平对比、发展趋势分析、优势与不足分析\n\n" + - "4. 问题识别\n" + - " 存在的主要问题和资源配置不均衡情况\n\n" + - "5. 建议与对策\n" + - " 针对性改进建议和资源优化配置方案\n\n" + - "6. 结论\n" + - " 总体评价和未来发展方向\n\n" + - "请确保分析客观、专业,数据引用准确,建议具有可操作性。\n\n" + - "=== 原始数据 ===\n" + dataContent; - } - - /** - * 使用Apache POI生成Word文档 - */ - private static void generateWordDocument(String analysisResult, String outputPath, String[] cities) throws Exception { - XWPFDocument document = new XWPFDocument(); - - try { - // 动态生成标题 - String reportTitle; - if (cities != null && cities.length >= 2) { - reportTitle = String.join("与", cities) + "教育资源配置对比分析报告"; - } else { - reportTitle = "教育资源配置对比分析报告"; // 默认标题 - } - - // 添加标题 - XWPFParagraph titleParagraph = document.createParagraph(); - titleParagraph.setAlignment(ParagraphAlignment.CENTER); - XWPFRun titleRun = titleParagraph.createRun(); - titleRun.setText(reportTitle); - titleRun.setBold(true); - titleRun.setFontSize(18); - titleRun.setFontFamily("宋体"); - - // 添加空行 - document.createParagraph(); - - // 添加生成信息 - XWPFParagraph infoParagraph = document.createParagraph(); - XWPFRun infoRun = infoParagraph.createRun(); - infoRun.setText("生成时间:" + new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())); - infoRun.setFontSize(12); - infoRun.setFontFamily("宋体"); - - XWPFRun toolRun = infoParagraph.createRun(); - toolRun.addBreak(); - toolRun.setText("分析工具:DeepSeek AI"); - toolRun.setFontSize(12); - toolRun.setFontFamily("宋体"); - - // 添加分隔线 - XWPFParagraph separatorParagraph = document.createParagraph(); - XWPFRun separatorRun = separatorParagraph.createRun(); - separatorRun.setText("=".repeat(50)); - separatorRun.setFontSize(10); - - // 添加空行 - document.createParagraph(); - - // 处理分析内容 - String[] lines = analysisResult.split("\n"); - XWPFParagraph currentParagraph = null; - XWPFRun currentRun = null; - - for (String line : lines) { - if (line.trim().isEmpty()) { - // 空行,创建新段落 - document.createParagraph(); - currentParagraph = null; - currentRun = null; - } else { - // 检查是否是标题行(数字开头或特殊格式) - boolean isTitle = line.matches("^\\d+\\..+") || - line.matches("^[一二三四五六七八九十]+、.+") || - line.trim().matches("^(执行摘要|数据概览|详细对比分析|问题识别|建议与对策|结论).*"); - - if (currentParagraph == null) { - currentParagraph = document.createParagraph(); - currentRun = currentParagraph.createRun(); - currentRun.setFontFamily("宋体"); - currentRun.setFontSize(12); - } - - if (isTitle) { - // 如果当前段落已有内容,创建新段落 - String currentText = currentRun.getText(0); - if (currentText != null && !currentText.isEmpty()) { - currentParagraph = document.createParagraph(); - currentRun = currentParagraph.createRun(); - currentRun.setFontFamily("宋体"); - } - currentRun.setText(line); - currentRun.setBold(true); - currentRun.setFontSize(14); - currentParagraph = null; // 强制下一行创建新段落 - currentRun = null; - } else { - // 普通内容 - String currentText = currentRun.getText(0); - if (currentText != null && !currentText.isEmpty()) { - currentRun.addBreak(); - } - currentRun.setText(line); - currentRun.setFontSize(12); - } - } - } - - // 添加结尾 - XWPFParagraph endParagraph = document.createParagraph(); - endParagraph.createRun().addBreak(); - XWPFRun endSeparatorRun = endParagraph.createRun(); - endSeparatorRun.setText("=".repeat(50)); - endSeparatorRun.setFontSize(10); - - XWPFRun endRun = endParagraph.createRun(); - endRun.addBreak(); - endRun.setText("报告结束"); - endRun.setFontSize(12); - endRun.setFontFamily("宋体"); - endRun.setBold(true); - - // 保存文档 - try (FileOutputStream out = new FileOutputStream(outputPath)) { - document.write(out); - } - - } finally { - document.close(); - } - } } diff --git a/src/main/java/com/dsideal/base/Tools/DataCollector.java b/src/main/java/com/dsideal/base/Tools/DataCollector.java new file mode 100644 index 00000000..a59dc754 --- /dev/null +++ b/src/main/java/com/dsideal/base/Tools/DataCollector.java @@ -0,0 +1,82 @@ +package com.dsideal.base.Tools; + +import com.dsideal.base.DataEase.Model.DataEaseModel; +import com.jfinal.plugin.activerecord.Db; +import com.jfinal.plugin.activerecord.Record; +import cn.hutool.json.JSONUtil; + +import java.util.List; + +/** + * 数据收集器 - 负责从数据库获取教育资源配置数据 + */ +public class DataCollector { + + /** + * 收集指定地区的教育资源配置数据 + * @param regions 要对比的地区数组 + * @return 格式化的数据内容 + */ + public static String collectEducationData(String[] regions) { + // 查询教育资源配置发展预测相关表 + String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dataease' AND TABLE_NAME LIKE 'excel_报告-教育资源配置发展预测%';"; + List tableList = Db.find(sql); + + StringBuilder dataContent = new StringBuilder(); + + // 构建数据标题 + dataContent.append("教育资源配置发展预测数据对比分析\n\n"); + dataContent.append("对比州市:").append(String.join(" vs ", regions)).append("\n\n"); + + // 遍历所有相关数据表 + for (Record record : tableList) { + String tableName = record.getStr("TABLE_NAME"); + dataContent.append("数据表:").append(tableName).append("\n"); + + // 为每个地区收集数据 + for (String region : regions) { + sql = "select * from `" + tableName + "` where `行政区划`=?"; + List listContent = Db.use(DataEaseModel.DB_NAME).find(sql, region); + + if (!listContent.isEmpty()) { + dataContent.append("\n").append(region).append("数据:\n"); + for (Record dataRecord : listContent) { + dataContent.append(JSONUtil.toJsonPrettyStr(dataRecord.getColumns())).append("\n"); + } + } else { + dataContent.append("\n").append(region).append(":无相关数据\n"); + } + } + dataContent.append("\n----------------------------------------\n\n"); + } + + return dataContent.toString(); + } + + /** + * 创建分析提示词 + * @param dataContent 数据内容 + * @param regions 对比地区 + * @return 分析提示词 + */ + public static String createAnalysisPrompt(String dataContent, String[] regions) { + String regionNames = String.join("和", regions); + return "你是一位专业的教育数据分析专家,请基于以下数据对" + regionNames + "的教育资源配置情况进行深入对比分析。\n\n" + + "重要要求:请生成结构化的纯文本格式报告,使用清晰的段落结构,不要使用markdown语法。\n\n" + + "请按照以下结构进行分析并生成专业的分析报告:\n\n" + + "1. 执行摘要\n" + + " 简要概述两州教育资源配置的整体情况和主要发现\n\n" + + "2. 数据概览\n" + + " 两州基本教育数据对比和关键指标汇总\n\n" + + "3. 详细对比分析\n" + + " 教育资源配置水平对比、发展趋势分析、优势与不足分析\n\n" + + "4. 问题识别\n" + + " 存在的主要问题和资源配置不均衡情况\n\n" + + "5. 建议与对策\n" + + " 针对性改进建议和资源优化配置方案\n\n" + + "6. 结论\n" + + " 总体评价和未来发展方向\n\n" + + "请确保分析客观、专业,数据引用准确,建议具有可操作性。\n\n" + + "=== 原始数据 ===\n" + dataContent; + } +} \ No newline at end of file diff --git a/src/main/java/com/dsideal/base/Tools/PptGenerator.java b/src/main/java/com/dsideal/base/Tools/PptGenerator.java new file mode 100644 index 00000000..9e7f671b --- /dev/null +++ b/src/main/java/com/dsideal/base/Tools/PptGenerator.java @@ -0,0 +1,112 @@ +package com.dsideal.base.Tools; + +import com.alibaba.fastjson.JSONObject; +import com.dsideal.base.Tools.Util.CallDeepSeek; +import com.dsideal.base.Tools.Util.PptAIKit; + +/** + * PPT生成器 - 负责生成分析报告的PPT演示文稿 + */ +public class PptGenerator extends PptAIKit { + + /** + * 生成PPT演示文稿 + * @param analysisContent 分析内容 + * @param regions 对比地区 + */ + public static void generatePptPresentation(String analysisContent, String[] regions) { + try { + String uid = "test"; + + // 生成简化的PPT提示词 + String simplifiedPptPrompt = createPptPrompt(analysisContent, regions); + if (simplifiedPptPrompt == null) { + System.err.println("无法生成PPT提示词,跳过PPT生成"); + return; + } + + // 创建API token + String apiToken = PptAIKit.createApiToken(uid, null); + System.out.println("api token: " + apiToken); + + // 生成大纲 + System.out.println("\n\n========== 正在生成大纲 =========="); + System.out.println("提示词长度: " + simplifiedPptPrompt.length()); + String outline = PptAIKit.generateOutline(apiToken, null, null, simplifiedPptPrompt); + + // 生成大纲内容 + System.out.println("\n\n========== 正在生成大纲内容 =========="); + String markdown = PptAIKit.generateContent(apiToken, outline, null, simplifiedPptPrompt); + + // 随机选择模板 + System.out.println("\n\n========== 随机选择模板 =========="); + String templateId = PptAIKit.randomOneTemplateId(apiToken); + System.out.println("模板ID: " + templateId); + + // 生成PPT + System.out.println("\n\n========== 正在生成PPT =========="); + JSONObject pptInfo = PptAIKit.generatePptx(apiToken, templateId, markdown, false); + String pptId = pptInfo.getString("id"); + System.out.println("pptId: " + pptId); + System.out.println("ppt主题:" + pptInfo.getString("subject")); + System.out.println("ppt封面:" + pptInfo.getString("coverUrl") + "?token=" + apiToken); + + } catch (Exception e) { + System.err.println("生成PPT时出错: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 创建PPT生成提示词 + * @param dataContent 数据内容 + * @param regions 对比地区 + * @return PPT提示词 + */ + private static String createPptPrompt(String dataContent, String[] regions) { + try { + // 构建给DeepSeek的精简提示词 + String deepseekPrompt = "你是一位专业的教育数据分析专家,请将以下教育资源配置数据进行精简总结," + + "提取关键信息和对比要点,控制在300字以内,重点突出" + String.join("与", regions) + "的对比差异:\n\n" + + dataContent; + + System.out.println("正在调用 DeepSeek 精简数据..."); + + // 调用DeepSeek获取精简内容 + String simplifiedContent = CallDeepSeek.callDeepSeek(deepseekPrompt); + + if (simplifiedContent != null && !simplifiedContent.trim().isEmpty()) { + System.out.println("DeepSeek 精简完成,精简后长度: " + simplifiedContent.length()); + + // 使用精简后的内容构建PPT提示词 + return buildPptPrompt(regions, simplifiedContent); + } else { + System.out.println("DeepSeek 调用失败,使用基础提示词"); + return null; + } + + } catch (Exception e) { + System.err.println("调用 DeepSeek 精简数据时出错: " + e.getMessage()); + e.printStackTrace(); + return null; + } + } + + /** + * 构建PPT提示词 + */ + private static String buildPptPrompt(String[] regions, String simplifiedContent) { + return "请基于以下教育资源配置数据,为" + String.join("与", regions) + + "教育资源配置对比分析创建一个专业的PPT大纲。\n\n" + + "PPT应包含以下主要部分:\n" + + "1. 封面 - 标题和基本信息\n" + + "2. 目录 - 分析框架\n" + + "3. 数据概览 - 关键指标对比\n" + + "4. 详细分析 - 各维度深入对比\n" + + "5. 问题识别 - 存在的主要问题\n" + + "6. 建议方案 - 改进措施\n" + + "7. 总结 - 结论和展望\n\n" + + "请确保内容简洁明了,适合PPT展示。\n\n" + + "=== 精简后的关键数据 ===\n" + simplifiedContent; + } +} \ No newline at end of file diff --git a/src/main/java/com/dsideal/base/Tools/WordGenerator.java b/src/main/java/com/dsideal/base/Tools/WordGenerator.java new file mode 100644 index 00000000..0bc13cab --- /dev/null +++ b/src/main/java/com/dsideal/base/Tools/WordGenerator.java @@ -0,0 +1,183 @@ +package com.dsideal.base.Tools; + +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.ParagraphAlignment; + +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Word文档生成器 - 负责生成分析报告的Word文档 + */ +public class WordGenerator { + + /** + * 生成Word分析报告 + * @param analysisResult AI分析结果 + * @param outputPath 输出文件路径 + * @param regions 对比地区 + * @throws Exception 文件操作异常 + */ + public static void generateWordDocument(String analysisResult, String outputPath, String[] regions) throws Exception { + XWPFDocument document = new XWPFDocument(); + + try { + // 动态生成标题 + String reportTitle = generateReportTitle(regions); + + // 添加文档标题 + addDocumentTitle(document, reportTitle); + + // 添加文档信息 + addDocumentInfo(document); + + // 添加分析内容 + addAnalysisContent(document, analysisResult); + + // 添加文档结尾 + addDocumentFooter(document); + + // 保存文档 + try (FileOutputStream out = new FileOutputStream(outputPath)) { + document.write(out); + } + + } finally { + document.close(); + } + } + + /** + * 生成报告标题 + */ + private static String generateReportTitle(String[] regions) { + if (regions != null && regions.length >= 2) { + return String.join("与", regions) + "教育资源配置对比分析报告"; + } else { + return "教育资源配置对比分析报告"; + } + } + + /** + * 添加文档标题 + */ + private static void addDocumentTitle(XWPFDocument document, String title) { + XWPFParagraph titleParagraph = document.createParagraph(); + titleParagraph.setAlignment(ParagraphAlignment.CENTER); + XWPFRun titleRun = titleParagraph.createRun(); + titleRun.setText(title); + titleRun.setBold(true); + titleRun.setFontSize(18); + titleRun.setFontFamily("宋体"); + + // 添加空行 + document.createParagraph(); + } + + /** + * 添加文档信息 + */ + private static void addDocumentInfo(XWPFDocument document) { + XWPFParagraph infoParagraph = document.createParagraph(); + XWPFRun infoRun = infoParagraph.createRun(); + infoRun.setText("生成时间:" + new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())); + infoRun.setFontSize(12); + infoRun.setFontFamily("宋体"); + + XWPFRun toolRun = infoParagraph.createRun(); + toolRun.addBreak(); + toolRun.setText("分析工具:DeepSeek AI"); + toolRun.setFontSize(12); + toolRun.setFontFamily("宋体"); + + // 添加分隔线 + XWPFParagraph separatorParagraph = document.createParagraph(); + XWPFRun separatorRun = separatorParagraph.createRun(); + separatorRun.setText("=".repeat(50)); + separatorRun.setFontSize(10); + + // 添加空行 + document.createParagraph(); + } + + /** + * 添加分析内容 + */ + private static void addAnalysisContent(XWPFDocument document, String analysisResult) { + String[] lines = analysisResult.split("\n"); + XWPFParagraph currentParagraph = null; + XWPFRun currentRun = null; + + for (String line : lines) { + if (line.trim().isEmpty()) { + // 空行,创建新段落 + document.createParagraph(); + currentParagraph = null; + currentRun = null; + } else { + // 检查是否是标题行 + boolean isTitle = isTitle(line); + + if (currentParagraph == null) { + currentParagraph = document.createParagraph(); + currentRun = currentParagraph.createRun(); + currentRun.setFontFamily("宋体"); + currentRun.setFontSize(12); + } + + if (isTitle) { + // 如果当前段落已有内容,创建新段落 + String currentText = currentRun.getText(0); + if (currentText != null && !currentText.isEmpty()) { + currentParagraph = document.createParagraph(); + currentRun = currentParagraph.createRun(); + currentRun.setFontFamily("宋体"); + } + currentRun.setText(line); + currentRun.setBold(true); + currentRun.setFontSize(14); + currentParagraph = null; // 强制下一行创建新段落 + currentRun = null; + } else { + // 普通内容 + String currentText = currentRun.getText(0); + if (currentText != null && !currentText.isEmpty()) { + currentRun.addBreak(); + } + currentRun.setText(line); + currentRun.setFontSize(12); + } + } + } + } + + /** + * 判断是否为标题行 + */ + private static boolean isTitle(String line) { + return line.matches("^\\d+\\..+") || + line.matches("^[一二三四五六七八九十]+、.+") || + line.trim().matches("^(执行摘要|数据概览|详细对比分析|问题识别|建议与对策|结论).*"); + } + + /** + * 添加文档结尾 + */ + private static void addDocumentFooter(XWPFDocument document) { + XWPFParagraph endParagraph = document.createParagraph(); + endParagraph.createRun().addBreak(); + XWPFRun endSeparatorRun = endParagraph.createRun(); + endSeparatorRun.setText("=".repeat(50)); + endSeparatorRun.setFontSize(10); + + XWPFRun endRun = endParagraph.createRun(); + endRun.addBreak(); + endRun.setText("报告结束"); + endRun.setFontSize(12); + endRun.setFontFamily("宋体"); + endRun.setBold(true); + } +} \ No newline at end of file diff --git a/教育资源对比分析报告_20250613_183737.docx b/教育资源对比分析报告_20250613_183737.docx new file mode 100644 index 0000000000000000000000000000000000000000..5989b4e17112ac0a6777fe01a7fb44ad1e4dc7cc GIT binary patch literal 4257 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:=SUgk_{lL<|D_aMKJyO0LWkff|3CZxoW$?x=b8KW^d!=MvGqJpe@{P8firsl3SR1e mCj0M|&d=uW2f0M^uS(|$WTZ<*e)cjT;c6w|J4o0B0Q?Ums5egl literal 0 HcmV?d00001