基于springboot+mybatis,數(shù)據(jù)庫mysql
模板樣例:
效果樣例:模板樣例.png圖表效果.png
1.pom文件
<!--報表相關(guān)-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jcommon</artifactId>
<version>1.0.24</version>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2.JfreeUtil 文件(用于生成圖表西设,更多圖表樣式等前往官網(wǎng)查找)
package com.bonc.huanghai.manage.util;
import cn.afterturn.easypoi.entity.ImageEntity;
import lombok.extern.slf4j.Slf4j;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.springframework.util.Assert;
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
/**
* @ClassName:JfreeUtil
* @author:莫須有
* @Description: 生成word文檔中的圖表(JPG)
* @create:2020/2/13 19:22
* @Version1.0
*/
@Slf4j
public class JfreeUtil {
/**
* 臨時文件存儲实束,也可以設(shè)置讀取配置文件
*/
private static String tempImgPath = "/data/app/server/weixin/tempJfree.jpeg";
/**
* 橫縱軸等字體
*/
private static Font font = new Font("宋體", Font.PLAIN, 12);
/**
* 顏色循環(huán)列表
*/
private static final Paint[] COLORS = { new Color(65, 105, 255),new Color(0, 191, 255),
new Color(30, 144, 223),new Color(30, 70, 255),
new Color(0, 0, 200), new Color(0, 0, 150)
};
/**
* 將圖片轉(zhuǎn)化為字節(jié)數(shù)組
* @return 字節(jié)數(shù)組
*/
private static byte[] imgToByte(){
File file = new File(tempImgPath);
byte[] buffer = null;
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try {
fis = new FileInputStream(file);
bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
} catch (IOException e) {
log.error(e.getMessage());
}finally {
try {
if(fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bos!= null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//刪除臨時文件
file.delete();
}
return buffer;
}
/**
* 生成主題樣式,及避免亂碼
* @return standardChartTheme
*/
private static StandardChartTheme getChartTheme() {
// 處理中文亂碼
// 創(chuàng)建主題樣式
StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
//設(shè)置標(biāo)題字體
standardChartTheme.setExtraLargeFont(new Font("宋體", Font.BOLD, 15));
//設(shè)置圖例的字體
standardChartTheme.setRegularFont(new Font("宋體", Font.PLAIN, 12));
//設(shè)置軸向的字體
standardChartTheme.setLargeFont(new Font("宋體", Font.PLAIN, 12));
return standardChartTheme;
}
/**
* 生成餅圖
* @param title 標(biāo)題
* @param data 數(shù)據(jù)集 {String,Number}
* @param width 圖片寬度
* @param height 圖片高度
* @return 圖像對象
*/
public static ImageEntity pieChart(String title, List<Object[]> data, int width, int height) {
//設(shè)置主題樣式
StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
ChartFactory.setChartTheme(standardChartTheme);
//根據(jù)jfree生成一個本地餅狀圖數(shù)據(jù)集
DefaultPieDataset dataset = new DefaultPieDataset();
for (Object[] arr : data) {
dataset.setValue((String) arr[0], (Number) arr[1]);
}
//創(chuàng)建圖表 (圖標(biāo)標(biāo)題万细、數(shù)據(jù)集合辆沦、是否顯示圖例標(biāo)識友瘤、是否顯示tooltips权烧、是否支持超鏈接)
JFreeChart chart = ChartFactory.createPieChart(title, dataset, true, false, false);
//設(shè)置抗鋸齒
chart.setTextAntiAlias(false);
//圖例
chart.getLegend().setItemFont(font);
//圖片邊框
chart.setBorderVisible(true);
chart.setBorderPaint(Color.gray);
//得到繪圖區(qū)
PiePlot plot = (PiePlot) chart.getPlot();
plot.setNoDataMessage("暫無數(shù)據(jù)");
//忽略無值的分類
plot.setIgnoreNullValues(true);
plot.setBackgroundAlpha(0f);
plot.setOutlineVisible(false);
//設(shè)置標(biāo)簽陰影顏色
plot.setShadowPaint(new Color(255,255,255));
//設(shè)置標(biāo)簽生成器(默認(rèn){0})
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}({1})/{2}"));
//設(shè)置標(biāo)簽字體
plot.setLabelFont(font);
//設(shè)置標(biāo)簽背景色
plot.setLabelBackgroundPaint(new Color(255,255,255));
//扇區(qū)分離與顏色設(shè)置
for (int i=0;i<dataset.getItemCount();i++) {
plot.setExplodePercent(dataset.getKey(i), 0.02);
plot.setSectionPaint(dataset.getKey(i).toString(), COLORS[i % COLORS.length]);
}
try {
ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
} catch (IOException e1) {
log.error("生成餅狀圖失斆幸唷!");
}
ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
Assert.notNull(imageEntity.getData(),"生成餅狀圖對象失敯懵搿妻率!");
return imageEntity;
}
public static ImageEntity barChart(String title, String xName, String yName, List<Object[]> data, int width, int height){
return barChart(title, xName, yName, data,width,height,false);
}
/**
* 生成垂直柱形圖
* @param title
* @param xName
* @param yName
* @param data
* @param width
* @param height
* @param legend
* @return 圖片
*/
public static ImageEntity barChart(String title, String xName, String yName, List<Object[]> data, int width, int height,Boolean legend) {
//設(shè)置主題樣式
StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
ChartFactory.setChartTheme(standardChartTheme);
//數(shù)據(jù)集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (Object[] arr : data) {
dataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
}
//創(chuàng)建圖表
JFreeChart chart = ChartFactory.createBarChart(title, xName,yName,dataset, PlotOrientation.VERTICAL,legend,true,false);
//設(shè)置抗鋸齒
chart.setTextAntiAlias(false);
//圖片邊框
chart.setBorderVisible(true);
chart.setBorderPaint(Color.gray);
//得到繪圖區(qū)
CategoryPlot plot = (CategoryPlot) chart.getPlot();
//獲取渲染對象
BarRenderer barRenderer = (BarRenderer)plot.getRenderer();
//設(shè)置柱形圖的寬度
barRenderer.setMaximumBarWidth(0.07);
//最短的BAR長度,避免數(shù)值太小而顯示不出
barRenderer.setMinimumBarLength(0.5);
// 設(shè)置柱形圖上的文字偏離值
barRenderer.setItemLabelAnchorOffset(10D);
//設(shè)置柱子的最大寬度
// 設(shè)置柱狀圖之間的距離0.1代表10%
barRenderer.setItemMargin(0.000000005);
//設(shè)置柱子為平面圖不是立體的
barRenderer.setBarPainter(new StandardBarPainter());
// 設(shè)置顏色
barRenderer.setSeriesPaint(0,new Color(65,105,225));
//不顯示陰影
barRenderer.setShadowVisible(false);
//顯示數(shù)值
barRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
barRenderer.setDefaultItemLabelFont(font);
barRenderer.setItemLabelAnchorOffset(0.1D);
barRenderer.setDefaultItemLabelsVisible(true);
for (int i=0;i<dataset.getRowCount();i++) {
barRenderer.setSeriesPaint(i, COLORS[i % COLORS.length]);
}
CategoryAxis domainAxis = plot.getDomainAxis();
// 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸侈询。
domainAxis.setUpperMargin(0.06);
// 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
//設(shè)置網(wǎng)格背景顏色
plot.setBackgroundPaint(Color.white);
//設(shè)置網(wǎng)格橫線顏色
plot.setRangeGridlinePaint(Color.black);
//得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
plot.getDomainAxis().setLabelFont(font);
//設(shè)置橫軸標(biāo)簽項字體
plot.getDomainAxis().setTickLabelFont(font);
//設(shè)置范圍軸(縱軸)字體
plot.getRangeAxis().setLabelFont(font);
//設(shè)置外邊框不可見
plot.setOutlineVisible(false);
try {
ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
} catch (IOException e1) {
log.error("生成柱形圖失斏嗾恰!");
}
ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
Assert.notNull(imageEntity.getData(),"生成柱形圖對象失敗囊嘉!");
return imageEntity;
}
/**
* 堆疊柱形圖
* @param title
* @param xName
* @param yName
* @param data
* @param width
* @param height
* @return
*/
public static ImageEntity stackedBarChart(String title, String xName, String yName, List<Object[]> data, int width, int height) {
//設(shè)置主題樣式
StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
ChartFactory.setChartTheme(standardChartTheme);
//數(shù)據(jù)集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (Object[] arr : data) {
dataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
}
//圖標(biāo)標(biāo)題温技、數(shù)據(jù)集合、是否顯示圖例標(biāo)識扭粱、是否顯示tooltips舵鳞、是否支持超鏈接
JFreeChart chart = ChartFactory.createStackedBarChart(title, xName,yName,dataset);
//設(shè)置抗鋸齒
chart.setTextAntiAlias(false);
//設(shè)置提示條字體
chart.getLegend().setItemFont(font);
//圖片邊框
chart.setBorderVisible(true);
chart.setBorderPaint(Color.gray);
//得到繪圖區(qū)
CategoryPlot plot = (CategoryPlot) chart.getPlot();
//獲取渲染對象
StackedBarRenderer stackedBarRenderer = (StackedBarRenderer)plot.getRenderer();
//設(shè)置柱形圖的寬度
stackedBarRenderer.setMaximumBarWidth(0.07);
//最短的BAR長度,避免數(shù)值太小而顯示不出
stackedBarRenderer.setMinimumBarLength(0.5);
// 設(shè)置柱形圖上的文字偏離值
stackedBarRenderer.setItemLabelAnchorOffset(10D);
//設(shè)置柱子的最大寬度
// 設(shè)置柱狀圖之間的距離0.1代表10%
stackedBarRenderer.setItemMargin(0.000000005);
//設(shè)置柱子為平面圖不是立體的
stackedBarRenderer.setBarPainter(new StandardBarPainter());
//不顯示陰影
stackedBarRenderer.setShadowVisible(false);
//設(shè)置顏色
for (int i=0;i<dataset.getRowCount();i++) {
stackedBarRenderer.setSeriesPaint(i, COLORS[i % COLORS.length]);
}
//顯示數(shù)值
stackedBarRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
stackedBarRenderer.setDefaultItemLabelFont(font);
stackedBarRenderer.setItemLabelAnchorOffset(0.1D);
stackedBarRenderer.setDefaultItemLabelsVisible(true);
CategoryAxis domainAxis = plot.getDomainAxis();
// 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸琢蛤。
domainAxis.setUpperMargin(0.06);
// 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
//設(shè)置網(wǎng)格背景顏色
plot.setBackgroundPaint(Color.white);
//設(shè)置網(wǎng)格橫線顏色
plot.setRangeGridlinePaint(Color.black);
//得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
plot.getDomainAxis().setLabelFont(font);
//設(shè)置橫軸標(biāo)簽項字體
plot.getDomainAxis().setTickLabelFont(font);
//設(shè)置范圍軸(縱軸)字體
plot.getRangeAxis().setLabelFont(font);
//設(shè)置外邊框不可見
plot.setOutlineVisible(false);
try {
ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
} catch (IOException e1) {
log.error("生成柱形圖失旘讯椤!");
}
ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
Assert.notNull(imageEntity.getData(),"生成柱形圖對象失敳┢洹套才!");
return imageEntity;
}
/**
* 折線圖 柱形圖 組合
* @param title
* @param xName
* @param yName
* @param barData
* @param lineData
* @param width
* @param height
* @return
*/
public static ImageEntity lineBarChart(String title, String xName, String yName, List<Object[]> barData, List<Object[]> lineData,int width, int height) {
//設(shè)置主題樣式
StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
ChartFactory.setChartTheme(standardChartTheme);
//數(shù)據(jù)集
DefaultCategoryDataset barDataset = new DefaultCategoryDataset();
for (Object[] arr : barData) {
barDataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
}
//數(shù)據(jù)集
DefaultCategoryDataset lineDataset = new DefaultCategoryDataset();
for (Object[] arr : lineData) {
lineDataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
}
//圖標(biāo)標(biāo)題、數(shù)據(jù)集合慕淡、是否顯示圖例標(biāo)識背伴、是否顯示tooltips、是否支持超鏈接
JFreeChart chart = ChartFactory.createBarChart(title, xName,yName,barDataset,PlotOrientation.VERTICAL,false,true,false);
//設(shè)置抗鋸齒
chart.setTextAntiAlias(false);
//圖片邊框
chart.setBorderVisible(true);
chart.setBorderPaint(Color.gray);
//得到繪圖區(qū)
CategoryPlot plot = (CategoryPlot) chart.getPlot();
//設(shè)置網(wǎng)格背景顏色
plot.setBackgroundPaint(Color.white);
//設(shè)置網(wǎng)格橫線顏色
plot.setRangeGridlinePaint(Color.black);
//得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
plot.getDomainAxis().setLabelFont(font);
//設(shè)置橫軸標(biāo)簽項字體
plot.getDomainAxis().setTickLabelFont(font);
//設(shè)置范圍軸(縱軸)字體
plot.getRangeAxis().setLabelFont(font);
//設(shè)置外邊框不可見
plot.setOutlineVisible(false);
//獲取渲染對象
BarRenderer barRenderer = (BarRenderer)plot.getRenderer();
//設(shè)置柱形圖的寬度
barRenderer.setMaximumBarWidth(0.07);
//最短的BAR長度峰髓,避免數(shù)值太小而顯示不出
barRenderer.setMinimumBarLength(0.5);
// 設(shè)置柱形圖上的文字偏離值
barRenderer.setItemLabelAnchorOffset(10D);
//設(shè)置柱子的最大寬度
// 設(shè)置柱狀圖之間的距離0.1代表10%
barRenderer.setItemMargin(0.000000005);
//設(shè)置柱子為平面圖不是立體的
barRenderer.setBarPainter(new StandardBarPainter());
// 設(shè)置顏色
barRenderer.setSeriesPaint(0,new Color(65,105,225));
//不顯示陰影
barRenderer.setShadowVisible(false);
//顯示數(shù)值
barRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
barRenderer.setDefaultItemLabelFont(font);
barRenderer.setItemLabelAnchorOffset(0.1D);
barRenderer.setDefaultItemLabelsVisible(true);
CategoryAxis domainAxis = plot.getDomainAxis();
// 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸傻寂。
domainAxis.setUpperMargin(0.06);
// 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
//放折線圖數(shù)據(jù)
CategoryDataset categorydataset = lineDataset;
// 0顯示是柱狀圖,1顯示折線圖
plot.setDataset(1, categorydataset);
// 顯示折線圖携兵,0疾掰,0坐標(biāo)軸都在左側(cè)
plot.mapDatasetToRangeAxis(0, 0);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
//畫折線圖
LineAndShapeRenderer lineandshaperenderer = new LineAndShapeRenderer();
// 設(shè)置實(shí)線
BasicStroke realLine = new BasicStroke(3.0f);
lineandshaperenderer.setSeriesStroke(0, realLine);
//去掉折線的點(diǎn)
lineandshaperenderer.setDefaultShapesVisible(false);
//顯示數(shù)值
lineandshaperenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
lineandshaperenderer.setDefaultItemLabelFont(font);
lineandshaperenderer.setDefaultItemLabelPaint(new Color(80,30,0));
lineandshaperenderer.setItemLabelAnchorOffset(0.2D);
lineandshaperenderer.setDefaultItemLabelsVisible(true);
plot.setRenderer(1, lineandshaperenderer);
try {
ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
} catch (IOException e1) {
log.error("生成折線柱形圖失敗徐紧!");
}
ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
Assert.notNull(imageEntity.getData(),"生成折線柱形圖對象失斁裁省!");
return imageEntity;
}
}
2.DownReportUtil 文件(下載生成的文件)
package com.bonc.huanghai.manage.util;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* @author:莫須有
* @Description: 下載文件工具類
* @create:2020/3/9 9:35
* @Version1.0
*/
public class DownReportUtil {
/**
* 下載文件,可以下載后刪除
* @param pathname
* @param fileName
* @throws IOException
*/
public static void download(String pathname, String fileName) throws IOException {
// 讀取filename
File file = new File(pathname);
BufferedInputStream bis = null;
OutputStream outputStream = null;
if (file.isFile() && file.exists()) {
try {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = requestAttributes.getResponse();
// 設(shè)置信息給客戶端不解析
String type = new MimetypesFileTypeMap().getContentType(fileName);
// 設(shè)置contenttype并级,即告訴客戶端所發(fā)送的數(shù)據(jù)屬于什么類型
response.setHeader("Content-type", type);
// 設(shè)置編碼
String encoded = URLEncoder.encode(fileName, "utf-8");
// 設(shè)置擴(kuò)展頭巴柿,當(dāng)Content-Type 的類型為要下載的類型時 , 這個信息頭會告訴瀏覽器這個文件的名字和類型。
response.setHeader("Content-Disposition", "attachment;filename=" + encoded);
// 發(fā)送給客戶端的數(shù)據(jù)
outputStream = response.getOutputStream();
byte[] buff = new byte[1024];
bis = new BufferedInputStream(new FileInputStream(file));
//office打開異常
/* int i = bis.read(buff);
while (i != -1) {
outputStream.write(buff, 0, buff.length);
outputStream.flush();
i = bis.read(buff);
}*/
//office打開正常,但是QQ瀏覽器下載會異常
int len = 0;
while ((len = bis.read(buff)) >= 0) {
outputStream.write(buff, 0, len);
outputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//關(guān)閉流
try {
if (bis != null) {
bis.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
// 文件刪除
file.delete();
}
}
}
}
2.WordUtil(用于生成最終word)
package com.bonc.huanghai.manage.util;
import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.util.Assert;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;
/**
* @ClassName:WordUtil
* @author:莫須有
* @Description: 導(dǎo)出word 只支持docx
* @create:2020/2/13 19:23
* @Version1.0
*/
public class WordUtil {
/**
* 導(dǎo)出word
* <p>第一步生成替換后的word文件死遭,只支持docx</p>
* <p>第二步下載生成的文件</p>
* <p>第三步刪除生成的臨時文件</p>
* 模版變量中變量格式:{{foo}}
*
* @param templatePath word模板地址
* @param temDir 生成臨時文件存放地址
* @param fileName 文件名
* @param params 替換的參數(shù)
*/
public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params) {
Assert.notNull(templatePath, "模板路徑不能為空");
Assert.notNull(temDir, "臨時文件路徑不能為空");
Assert.notNull(fileName, "導(dǎo)出文件名不能為空");
Assert.isTrue(fileName.endsWith(".docx"), "word導(dǎo)出請使用docx格式");
if (!temDir.endsWith("/")) {
temDir = temDir + File.separator;
}
File dir = new File(temDir);
if (!dir.exists()) {
dir.mkdirs();
}
try {
XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
String tmpPath = temDir + fileName;
FileOutputStream fos = new FileOutputStream(tmpPath);
doc.write(fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.bonc.huanghai.manage.service.report.impl;
import cn.afterturn.easypoi.entity.ImageEntity;
import com.bonc.huanghai.manage.model.count.Count;
import com.bonc.huanghai.manage.model.ticket.TicketInfo;
import com.bonc.huanghai.manage.model.tourist.TouristOrigin;
import com.bonc.huanghai.manage.util.DownReportUtil;
import com.bonc.huanghai.manage.util.JfreeUtil;
import com.bonc.huanghai.manage.util.WordUtil;
import com.bonc.huanghai.manage.mapper.count.ITouristPortraitMapper;
import com.bonc.huanghai.manage.mapper.count.LyricalCountMapper;
import com.bonc.huanghai.manage.mapper.oa.TicketMapper;
import com.bonc.huanghai.manage.service.report.ReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import java.io.File;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @ClassName:ReportServiceImpl
* @author:莫須有
* @Description: 導(dǎo)出報表
* @create:2020/3/2 15:47
* @Version1.0
*/
@Service
@Primary
public class ReportServiceImpl implements ReportService {
private static final String PERCENT_SIGN = "%";
private static final String TEM_DIR = "tjs/tjs-manage/src/main/resources/templates/download/";
private static final String TEMPLATE_PATH = "templates/數(shù)據(jù)報告模板.docx";
private static final String DOCX = ".docx";
private static final String DATA_ERROR = "(暫無數(shù)據(jù))";
private static final String DATA_PICTURE_ERROR = "(圖片中數(shù)據(jù)暫無)";
private static final String DATA_FIGURE_ERROR = "0";
private static final Integer WIDTH = 550;
private static final Integer HEIGHT = 400;
@Autowired
TicketMapper ticketMapper;
@Autowired
ITouristPortraitMapper iTouristPortraitMapper;
@Autowired
LyricalCountMapper lyricalCountMapper;
/**
* 生成百分比
* @param proportionDouble
* @return
*/
private String proportionInit(double proportionDouble) {
String format = new DecimalFormat("0").format(BigDecimal.valueOf(proportionDouble).multiply(new BigDecimal(100)));
String str = format + PERCENT_SIGN;
return str;
}
/**
* 導(dǎo)出景區(qū)數(shù)據(jù)分析報告
* @param title
* @param beginDate
* @param endDate
* @return
*/
@Override
public String downloadReport(String title, String beginDate, String endDate) {
HashMap<String, Object> map = new HashMap<>(40);
if (title == null || title.length() == 0){
title = "景區(qū)_"+beginDate+"-"+endDate+"_數(shù)據(jù)分析報告";
}
//標(biāo)題,起止時間
map.put("title", title);
map.put("beginDate", beginDate);
map.put("endDate", endDate);
// 獲取當(dāng)前時間
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy年MM月dd日");
Date date = new Date();
map.put("date", sdf.format(date));
//游客畫像分析
//省內(nèi)外游客客流量
map.putAll(provincialSourceToReporttPic(beginDate, endDate));
//國內(nèi)游客畫像,省外游客
map.putAll(outofprovinceSourceRankingPic(beginDate, endDate));
//國內(nèi)游客畫像,省內(nèi)游客
map.putAll(provincialSourceRankingPic(beginDate, endDate));
//游客年齡段分布
map.putAll(ageProportionPic(beginDate, endDate));
//游客男女性別分布
map.putAll(sexProportionPic(beginDate, endDate));
//游客交通方式分析
map.putAll(transportationProportionPic(beginDate, endDate));
//游客消費(fèi)潛力分析
map.putAll(consumptionLevelPic(beginDate, endDate));
//車輛來源分析
map.putAll(carOriginPic(beginDate, endDate));
//門票匯總分析
map.putAll(ticketPic(beginDate, endDate));
//輿情分析
map.putAll(lyricalPic(beginDate, endDate));
//導(dǎo)出word
String fileName = title + DOCX;
WordUtil.exportWord(TEMPLATE_PATH, TEM_DIR, fileName, map);
//下載文件
try {
DownReportUtil.download(TEM_DIR + fileName, fileName);
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(TEM_DIR + fileName);
// 文件刪除
if (file.isFile() && file.exists()) {
file.delete();
}
return "OK";
}
/**
* 游客畫像分析
* 省內(nèi)外游客客流量
*
* @param beginDate
* @param endDate
* @return map (2)
*/
private HashMap<String, Object> provincialSourceToReporttPic(String beginDate, String endDate) {
HashMap<String, Object> map = new HashMap<>(2);
//省內(nèi)外+未知等的總游客數(shù)量
int sumOfAllTourist = 0;
try {
/*
存放進(jìn)柱狀圖的數(shù)據(jù)集
*/
List<Object[]> provincialSourceToReportPicData = new ArrayList<Object[]>();
/*
存放數(shù)據(jù)庫取出的數(shù)據(jù)
*/
List<TouristOrigin> provincialSourceToReport = iTouristPortraitMapper.provincialSourceToReport(beginDate, endDate);
/*
將數(shù)據(jù)庫取出的數(shù)據(jù)放入柱狀圖的數(shù)據(jù)集
*/
for (TouristOrigin data : provincialSourceToReport) {
if (data.getInProvince() == 0) {
provincialSourceToReportPicData.add(new Object[]{data.getCount(), "省外", data.getDate()});
}
if (data.getInProvince() == 1) {
provincialSourceToReportPicData.add(new Object[]{data.getCount(), "省內(nèi)", data.getDate()});
}
sumOfAllTourist = sumOfAllTourist + data.getCount();
}
/*
判斷數(shù)據(jù)是否為空或0,若為空或零則直接當(dāng)做異常處理
*/
if (provincialSourceToReport == null || provincialSourceToReport.size()==0 || sumOfAllTourist ==0) {
throw new Exception();
}
/*
生成柱狀圖的圖片
*/
ImageEntity provincialSourceToReporttPic = JfreeUtil.stackedBarChart("省內(nèi)外游客流量", "", "游客數(shù)量", provincialSourceToReportPicData, WIDTH, HEIGHT);
/*
放入文檔對應(yīng)的map集合中
*/
map.put("provincialSourceToReporttPic", provincialSourceToReporttPic);
map.put("游客總計", sumOfAllTourist);
}catch (Exception e){
e.printStackTrace();
map.put("provincialSourceToReporttPic", DATA_PICTURE_ERROR);
map.put("游客總計", DATA_FIGURE_ERROR);
}
return map;
}