<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="java.io.*" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="weaver.conn.RecordSet" %>
<%@ page import="weaver.general.Util" %>
<%@ page import="net.sf.json.JSONObject" %>
<%@ page import="net.sf.json.JSONArray" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ page import="org.jfree.chart.ChartFactory" %>
<%@ page import="org.jfree.chart.JFreeChart" %>
<%@ page import="org.jfree.chart.plot.PlotOrientation" %>
<%@ page import="org.jfree.chart.ChartUtilities" %>
<%@ page import="org.jfree.data.category.DefaultCategoryDataset" %>
<%@ page import="org.apache.poi.xwpf.usermodel.XWPFDocument" %>
<%@ page import="org.apache.poi.xwpf.usermodel.XWPFParagraph" %>
<%@ page import="org.apache.poi.xwpf.usermodel.XWPFRun" %>
<%@ page import="org.apache.poi.util.Units" %>
<%
// ===== 生成Word文档逻辑(直接从图片路径读取) =====
String generateWord = Util.null2String(request.getParameter("generateWord"));
if (!generateWord.isEmpty()) {
try {
String appRoot = application.getRealPath("/");
String chartFilePath = appRoot + "charts/" + generateWord;
File chartFile = new File(chartFilePath);
if (!chartFile.exists()) {
response.sendError(404, "图表文件不存在: " + generateWord);
return;
}
// 创建Word文档
XWPFDocument document = new XWPFDocument();
// 添加标题
XWPFParagraph title = document.createParagraph();
XWPFRun titleRun = title.createRun();
titleRun.setText("考勤异常统计报告");
titleRun.setBold(true);
titleRun.setFontSize(16);
titleRun.setFontFamily("宋体");
titleRun.addBreak();
// 添加图片(直接从路径读取)
XWPFParagraph paragraph = document.createParagraph();
paragraph.setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER);
XWPFRun run = paragraph.createRun();
// 读取图片数据为字节数组,避免编码问题
byte[] pictureData = new byte[(int) chartFile.length()];
try (FileInputStream fis = new FileInputStream(chartFile)) {
fis.read(pictureData);
// 使用字节数组创建输入流
try (ByteArrayInputStream bais = new ByteArrayInputStream(pictureData)) {
run.addPicture(bais, XWPFDocument.PICTURE_TYPE_PNG, chartFile.getName(), Units.toEMU(500), Units.toEMU(300));
}
}
// 添加说明文字
XWPFParagraph desc = document.createParagraph();
desc.setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER);
XWPFRun descRun = desc.createRun();
descRun.setText("图1:考勤异常统计折线图");
descRun.setFontFamily("宋体");
descRun.addBreak();
// 设置响应头,下载Word文档
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
String wordFileName = "考勤统计报告_" + System.currentTimeMillis() + ".docx";
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(wordFileName, "UTF-8"));
// 输出Word文档
OutputStream outStream = response.getOutputStream();
document.write(outStream);
outStream.flush();
outStream.close();
document.close();
return;
} catch (Exception e) {
e.printStackTrace();
out.print("{\"code\":500,\"msg\":\"生成Word文档失败:" + e.getMessage() + "\"}");
return;
}
}
// ===== 数据查询逻辑 =====
RecordSet rs = new RecordSet();
String departmentIds = Util.null2String(request.getParameter("departmentId"));
JSONObject returnObject = new JSONObject();
JSONArray dataArray = new JSONArray();
try {
if (departmentIds.isEmpty()) {
returnObject.put("code", 500);
returnObject.put("msg", "参数不能为空!");
} else if (!departmentIds.matches("^\\d+(,\\d+)*$")) {
returnObject.put("code", 500);
returnObject.put("msg", "参数格式错误!");
} else {
String[] deptIdArray = departmentIds.split(",");
String inCondition = String.join(",", deptIdArray);
String sql = "SELECT " +
"departmentid," +
"COUNT(DISTINCT CASE WHEN A.belate > 0 THEN A.resourceid END) AS late_persons," +
"COALESCE(SUM(A.belate), 0) AS late_count," +
"COUNT(DISTINCT CASE WHEN A.leaveeearly > 0 THEN A.resourceid END) AS early_leave_persons," +
"COALESCE(SUM(A.leaveeearly), 0) AS early_leave_count," +
"COUNT(DISTINCT CASE WHEN A.absenteeism > 0 THEN A.resourceid END) AS absenteeism_persons," +
"COALESCE(SUM(A.absenteeism), 0) AS absenteeism_count," +
"COALESCE(SUM(A.workdays), 0) AS scheduled_work_days," +
"COALESCE(SUM(A.attendancedays), 0) AS actual_work_days " +
"FROM kq_format_total A " +
"WHERE departmentid IN (" + inCondition + ") " +
"GROUP BY departmentid";
rs.executeSql(sql);
while (rs.next()) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("departmentId", rs.getString("departmentid"));
dataMap.put("latePersons", rs.getString("late_persons"));
dataMap.put("lateCount", rs.getString("late_count"));
dataMap.put("earlyLeavePersons", rs.getString("early_leave_persons"));
dataMap.put("earlyLeaveCount", rs.getString("early_leave_count"));
dataMap.put("absenteeismPersons", rs.getString("absenteeism_persons"));
dataMap.put("absenteeismCount", rs.getString("absenteeism_count"));
dataMap.put("scheduledWorkDays", rs.getString("scheduled_work_days"));
dataMap.put("actualWorkDays", rs.getString("actual_work_days"));
dataArray.add(JSONObject.fromObject(dataMap));
}
if (dataArray.size() > 0) {
returnObject.put("code", 200);
returnObject.put("msg", "查询成功!共找到" + dataArray.size() + "条数据");
returnObject.put("data", dataArray);
// ===== 生成折线图 =====
String appRoot = application.getRealPath("/");
String chartDirPath = appRoot + "charts/";
File chartDir = new File(chartDirPath);
if (!chartDir.exists()) {
chartDir.mkdirs();
}
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < dataArray.size(); i++) {
JSONObject dept = dataArray.getJSONObject(i);
String deptId = dept.getString("departmentId");
int latePersons = Integer.parseInt(dept.getString("latePersons"));
int earlyLeavePersons = Integer.parseInt(dept.getString("earlyLeavePersons"));
int absenteeismPersons = Integer.parseInt(dept.getString("absenteeismPersons"));
dataset.addValue(latePersons, "迟到人次", deptId);
dataset.addValue(earlyLeavePersons, "早退人次", deptId);
dataset.addValue(absenteeismPersons, "缺勤人次", deptId);
}
JFreeChart chart = ChartFactory.createLineChart(
"考勤异常统计",
"部门ID",
"人次数",
dataset,
PlotOrientation.VERTICAL,
true, true, false
);
String fileName = "attendance_chart_" + System.currentTimeMillis() + ".png";
String fullPath = chartDirPath + fileName;
ChartUtilities.saveChartAsPNG(new File(fullPath), chart, 800, 600);
returnObject.put("chartUrl", "charts/" + fileName);
// 生成Word文档按钮(直接链接到当前JSP,带generateWord参数)
String currentJspName = request.getRequestURI().substring(request.getRequestURI().lastIndexOf('/') + 1);
String wordButton = "<a href='" + currentJspName + "?generateWord=" + fileName + "' download='考勤统计报告.docx'>生成Word报告</a>";
returnObject.put("wordButton", wordButton);
} else {
returnObject.put("code", 500);
returnObject.put("msg", "未查询到数据!部门ID列表:" + departmentIds);
returnObject.put("data", dataArray);
}
}
} catch (Exception e) {
e.printStackTrace();
returnObject.put("code", 500);
returnObject.put("msg", "系统异常:" + e.getMessage());
returnObject.put("data", dataArray);
}
// 输出JSON
out.print(returnObject.toString());
%>
图片放入word出现乱码问题