You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

214 lines
11 KiB

package com.project.report;
import com.project.analyzer.PostAnalyzer;
import com.project.model.PostInfo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
public class HTMLReportGenerator {
private static final String OUTPUT_DIR = "d:\\java\\project\\reports";
public static void generateReport(PostAnalyzer analyzer) {
try {
Files.createDirectories(Paths.get(OUTPUT_DIR));
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
String filename = "report_" + timestamp + ".html";
String filepath = OUTPUT_DIR + "/" + filename;
try (BufferedWriter writer = new BufferedWriter(
new FileWriter(filepath, StandardCharsets.UTF_8))) {
writer.write(generateHTMLContent(analyzer));
}
System.out.println("HTML报告已生成: " + filepath);
} catch (IOException e) {
System.err.println("生成HTML报告时出错: " + e.getMessage());
}
}
private static String generateHTMLContent(PostAnalyzer analyzer) {
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html>\n");
html.append("<html lang=\"zh-CN\">\n");
html.append("<head>\n");
html.append(" <meta charset=\"UTF-8\">\n");
html.append(" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n");
html.append(" <title>图文帖子数据分析报告</title>\n");
html.append(" <style>\n");
html.append(" * { margin: 0; padding: 0; box-sizing: border-box; }\n");
html.append(" body { font-family: 'Microsoft YaHei', Arial, sans-serif; background: #f5f5f5; padding: 20px; }\n");
html.append(" .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }\n");
html.append(" h1 { color: #333; text-align: center; margin-bottom: 10px; }\n");
html.append(" .subtitle { color: #666; text-align: center; margin-bottom: 30px; font-size: 14px; }\n");
html.append(" .section { margin-bottom: 40px; }\n");
html.append(" .section h2 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; margin-bottom: 20px; }\n");
html.append(" table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }\n");
html.append(" th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }\n");
html.append(" th { background: #3498db; color: white; font-weight: bold; }\n");
html.append(" tr:hover { background: #f8f9fa; }\n");
html.append(" .stat-card { display: inline-block; width: 200px; padding: 20px; margin: 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 10px; text-align: center; }\n");
html.append(" .stat-card h3 { font-size: 36px; margin-bottom: 10px; }\n");
html.append(" .stat-card p { font-size: 14px; opacity: 0.9; }\n");
html.append(" .chart-container { text-align: center; margin: 20px 0; }\n");
html.append(" .chart-container img { max-width: 100%; height: auto; border: 1px solid #ddd; border-radius: 5px; }\n");
html.append(" .summary { background: #e8f4f8; padding: 20px; border-radius: 10px; margin-bottom: 30px; }\n");
html.append(" .summary h3 { color: #2c3e50; margin-bottom: 15px; }\n");
html.append(" .summary ul { list-style-position: inside; color: #555; }\n");
html.append(" .summary li { margin: 8px 0; }\n");
html.append(" </style>\n");
html.append("</head>\n");
html.append("<body>\n");
html.append(" <div class=\"container\">\n");
html.append(" <h1>图文帖子数据分析报告</h1>\n");
html.append(" <p class=\"subtitle\">生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>\n");
html.append(generateSummarySection(analyzer));
html.append(generateSentimentSection(analyzer));
html.append(generateEngagementSection(analyzer));
html.append(generateAuthorSection(analyzer));
html.append(generateChartsSection());
html.append(" </div>\n");
html.append("</body>\n");
html.append("</html>");
return html.toString();
}
private static String generateSummarySection(PostAnalyzer analyzer) {
StringBuilder section = new StringBuilder();
int totalPosts = analyzer.getPosts().size();
double avgLikes = analyzer.getPosts().stream()
.mapToInt(PostInfo::getLikeCount)
.average()
.orElse(0);
section.append(" <div class=\"section\">\n");
section.append(" <div class=\"stat-card\">\n");
section.append(" <h3>").append(totalPosts).append("</h3>\n");
section.append(" <p>帖子总数</p>\n");
section.append(" </div>\n");
section.append(" <div class=\"stat-card\">\n");
section.append(" <h3>").append(String.format("%.1f", avgLikes)).append("</h3>\n");
section.append(" <p>平均点赞</p>\n");
section.append(" </div>\n");
section.append(" </div>\n");
section.append(" <div class=\"summary\">\n");
section.append(" <h3>分析摘要</h3>\n");
section.append(" <ul>\n");
section.append(" <li>本次分析共收集 ").append(totalPosts).append(" 条图文帖子数据</li>\n");
section.append(" <li>数据来源:D:\计量经济学\计量实验资料及作业要求\计量实验资料及作业要求\图文帖子原始信息计量实验使用</li>\n");
section.append(" <li>分析内容包括情感倾向分布、互动指标、热门作者等多个维度</li>\n");
section.append(" <li>通过数据可视化展示分析结果,便于直观理解</li>\n");
section.append(" </ul>\n");
section.append(" </div>\n");
return section.toString();
}
private static String generateSentimentSection(PostAnalyzer analyzer) {
StringBuilder section = new StringBuilder();
Map<String, Long> sentimentData = analyzer.getSentimentDistributionData();
section.append(" <div class=\"section\">\n");
section.append(" <h2>情感倾向分布分析</h2>\n");
section.append(" <table>\n");
section.append(" <tr><th>情感倾向</th><th>帖子数量</th><th>占比</th></tr>\n");
long total = sentimentData.values().stream().mapToLong(Long::longValue).sum();
for (Map.Entry<String, Long> entry : sentimentData.entrySet()) {
double percent = (entry.getValue() * 100.0) / total;
section.append(" <tr><td>").append(entry.getKey())
.append("</td><td>").append(entry.getValue())
.append("</td><td>").append(String.format("%.1f%%", percent))
.append("</td></tr>\n");
}
section.append(" </table>\n");
section.append(" </div>\n");
return section.toString();
}
private static String generateEngagementSection(PostAnalyzer analyzer) {
StringBuilder section = new StringBuilder();
Map<String, Double> engagementData = analyzer.getEngagementData();
section.append(" <div class=\"section\">\n");
section.append(" <h2>互动指标分析</h2>\n");
section.append(" <table>\n");
section.append(" <tr><th>指标</th><th>平均值</th></tr>\n");
for (Map.Entry<String, Double> entry : engagementData.entrySet()) {
section.append(" <tr><td>").append(entry.getKey())
.append("</td><td>").append(String.format("%.1f", entry.getValue()))
.append("</td></tr>\n");
}
section.append(" </table>\n");
section.append(" </div>\n");
return section.toString();
}
private static String generateAuthorSection(PostAnalyzer analyzer) {
StringBuilder section = new StringBuilder();
Map<String, Integer> authorData = analyzer.getAuthorPostCount();
section.append(" <div class=\"section\">\n");
section.append(" <h2>热门作者排行TOP10</h2>\n");
section.append(" <table>\n");
section.append(" <tr><th>排名</th><th>作者</th><th>帖子数量</th></tr>\n");
int rank = 1;
for (Map.Entry<String, Integer> entry : authorData.entrySet()) {
section.append(" <tr><td>").append(rank++)
.append("</td><td>").append(entry.getKey())
.append("</td><td>").append(entry.getValue())
.append("</td></tr>\n");
}
section.append(" </table>\n");
section.append(" </div>\n");
return section.toString();
}
private static String generateChartsSection() {
StringBuilder section = new StringBuilder();
section.append(" <div class=\"section\">\n");
section.append(" <h2>数据可视化图表</h2>\n");
section.append(" <div class=\"chart-container\">\n");
section.append(" <h3>情感倾向分布</h3>\n");
section.append(" <img src=\"../charts/sentiment_distribution.png\" alt=\"情感倾向分布图\">\n");
section.append(" </div>\n");
section.append(" <div class=\"chart-container\">\n");
section.append(" <h3>互动指标分析</h3>\n");
section.append(" <img src=\"../charts/engagement_metrics.png\" alt=\"互动指标图\">\n");
section.append(" </div>\n");
section.append(" <div class=\"chart-container\">\n");
section.append(" <h3>热门作者排行</h3>\n");
section.append(" <img src=\"../charts/author_ranking.png\" alt=\"作者排行图\">\n");
section.append(" </div>\n");
section.append(" </div>\n");
return section.toString();
}
}