Java学习Day58:相声二人组!(项目统计数据Excel图表导出)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head>
<!-- 页面meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>瑞通健康</title>
<meta name="description" content="瑞通健康">
<meta name="keywords" content="瑞通健康">
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../css/style.css">
<style>
.grid-content {
border-radius: 4px;
min-height: 40px;
}
</style>
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>统计分析<small>运营数据</small></h1>
<el-breadcrumb separator-class="el-icon-arrow-right" class="breadcrumb">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>统计分析</el-breadcrumb-item>
<el-breadcrumb-item>运营数据</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="app-container">
<div class="box" style="height: 900px">
<div class="excelTitle" >
<el-button @click="exportExcel">导出Excel</el-button>运营数据统计
</div>
<div class="excelTime">日期:{{reportData.reportDate}}</div>
<table class="exceTable" cellspacing="0" cellpadding="0">
<tr>
<td colspan="4" class="headBody">会员数据统计</td>
</tr>
<tr>
<td width='20%' class="tabletrBg">新增会员数</td>
<td width='30%'>{{reportData.todayNewMember}}</td>
<td width='20%' class="tabletrBg">总会员数</td>
<td width='30%'>{{reportData.totalMember}}</td>
</tr>
<tr>
<td class="tabletrBg">本周新增会员数</td>
<td>{{reportData.thisWeekNewMember}}</td>
<td class="tabletrBg">本月新增会员数</td>
<td>{{reportData.thisMonthNewMember}}</td>
</tr>
<tr>
<td colspan="4" class="headBody">预约到诊数据统计</td>
</tr>
<tr>
<td class="tabletrBg">今日预约数</td>
<td>{{reportData.todayOrderNumber}}</td>
<td class="tabletrBg">今日到诊数</td>
<td>{{reportData.todayVisitsNumber}}</td>
</tr>
<tr>
<td class="tabletrBg">本周预约数</td>
<td>{{reportData.thisWeekOrderNumber}}</td>
<td class="tabletrBg">本周到诊数</td>
<td>{{reportData.thisWeekVisitsNumber}}</td>
</tr>
<tr>
<td class="tabletrBg">本月预约数</td>
<td>{{reportData.thisMonthOrderNumber}}</td>
<td class="tabletrBg">本月到诊数</td>
<td>{{reportData.thisMonthVisitsNumber}}</td>
</tr>
<tr>
<td colspan="4" class="headBody">热门套餐</td>
</tr>
<tr class="tabletrBg textCenter">
<td>套餐名称</td>
<td>预约数量</td>
<td>占比</td>
<td>备注</td>
</tr>
<tr v-for="s in reportData.hotSetmeal">
<td>{{s.name}}</td>
<td>{{s.setmeal_count}}</td>
<td>{{s.proportion}}</td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script>
var vue = new Vue({
el: '#app',
data:{
reportData:{
reportDate:null,
todayNewMember :0,
totalMember :0,
thisWeekNewMember :0,
thisMonthNewMember :0,
todayOrderNumber :0,
todayVisitsNumber :0,
thisWeekOrderNumber :0,
thisWeekVisitsNumber :0,
thisMonthOrderNumber :0,
thisMonthVisitsNumber :0,
hotSetmeal :[
{name:'阳光爸妈升级肿瘤12项筛查(男女单人)体检套餐',setmeal_count:200,proportion:0.222},
{name:'阳光爸妈升级肿瘤12项筛查体检套餐',setmeal_count:200,proportion:0.222}
]
}
},
created() {
axios.get("/report/getBusinessReportData.do").then((res)=>{
this.reportData = res.data.data;
});
},
methods:{
exportExcel(){
window.location.href = '/report/exportBusinessReport.do';
}
}
})
</script>
</html>
后端代码,先查询表上的数据,封装成对应的前端需要的形式的Map集合
@GetMapping("/getBusinessReportData")
public Result getBusinessReportData(){
Map<Object,Object> reportData=memberService.getReportExcelResult();
return new Result(true,"success",reportData);
}
/**
* reportDate:null,
* todayNewMember :0,
* totalMember :0,
* thisWeekNewMember :0,
* thisMonthNewMember :0,
* todayOrderNumber :0,
* todayVisitsNumber :0,
* thisWeekOrderNumber :0,
* thisWeekVisitsNumber :0,
* thisMonthOrderNumber :0,
* thisMonthVisitsNumber :0,
* hotSetmeal :[
* {name:'阳光爸妈升级肿瘤12项筛查(男女单人)体检套餐',setmeal_count:200,proportion:0.222},
* {name:'阳光爸妈升级肿瘤12项筛查体检套餐',setmeal_count:200,proportion:0.222}
* ]
数据形式如上,封装过程如下:
@Override
public Map<Object, Object> getReportExcelResult(){
Map<Object,Object> resultMap=new HashMap<>();
try {
System.out.println("=============================");
//reportDate
String data= Date2Utils.parseDate2String(new Date());
System.out.println(data);
resultMap.put("reportDate",data);
//todayNewMember
int count = memberMapper.selectCurrentDayMemberCount(data);
resultMap.put("todayNewMember",count);
//totalMember
int totalMember=memberMapper.seelectTotalMember();
resultMap.put("totalMember",totalMember);
//thisWeekNewMember
int thisWeekNewMember=memberMapper.selectthisWeekNewMember(data);
resultMap.put("thisWeekNewMember",thisWeekNewMember);
//thisMonthNewMember
int thisMonthNewMember=memberMapper.selectthisMonthNewMember();
resultMap.put("thisMonthNewMember",thisMonthNewMember);
//todayOrderNumber
int todayOrderNumber=orderSettingMapper.selecttodayOrderNumber();
resultMap.put("todayOrderNumber",todayOrderNumber);
//thisWeekOrderNumber
int thisWeekOrderNumber=orderSettingMapper.selectthisWeekOrderNumber();
resultMap.put("thisWeekOrderNumber",thisWeekOrderNumber);
//thisMonthOrderNumber
int thisMonthOrderNumber=orderSettingMapper.selectthisMonthOrderNumber();
resultMap.put("thisMonthOrderNumber",thisMonthOrderNumber);
//todayVisitsNumber
int todayVisitsNumber=orderSettingMapper.selecttodayVisitsNumber();
resultMap.put("todayVisitsNumber",todayVisitsNumber);
//thisWeekVisitsNumber
int thisWeekVisitsNumber=orderSettingMapper.selectthisWeekVisitsNumber();
resultMap.put("thisWeekVisitsNumber",thisWeekVisitsNumber);
//thisMonthVisitsNumber
int thisMonthVisitsNumber=orderSettingMapper.selectthisMonthVisitsNumber();
resultMap.put("thisMonthVisitsNumber",thisMonthVisitsNumber);
//hotSetmeal
List<Map<String,String>> hotSetmeal=new ArrayList<>();
hotSetmeal=orderSettingMapper.selecthotSetmeal();
resultMap.put("hotSetmeal",hotSetmeal);
System.out.println(resultMap);
} catch (Exception e) {
throw new RuntimeException(e);
}
return resultMap;
}
以下是一组时间范围查询的相关的SQL记录:
@Select("SELECT COUNT(0) " +
"FROM`t_order` " +
"WHERE orderDate = CURDATE() AND orderStatus='已到诊'")
int selecttodayVisitsNumber();
@Select("SELECT COUNT(*) " +
"FROM `t_order` " +
"WHERE orderDate >= DATE_SUB(CURDATE(), INTERVAL 1 WEEK) " +
" AND orderDate <= CURDATE() AND orderStatus='已到诊';")
int selectthisWeekVisitsNumber();
@Select("SELECT COUNT(*) " +
"FROM `t_order` " +
"WHERE orderDate >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) " +
"AND orderDate <= CURDATE() AND orderStatus='已到诊';")
int selectthisMonthVisitsNumber();
@Select("SELECT \n" +
" s.`name` AS 'name',\n" +
" COUNT(0) AS 'setmeal_count',\n" +
" COUNT(0) * 1.0 / (SELECT COUNT(*) FROM `t_order`) AS 'proportion'\n" +
" \n" +
"FROM \n" +
" `t_order` o \n" +
"LEFT JOIN \n" +
" `t_setmeal` s ON o.`setmeal_id` = s.`id`\n" +
"GROUP BY \n" +
" s.`id` LIMIT 4;")
List<Map<String, String>> selecthotSetmeal();
然后是根据查到的数据导入定制好的格式的Excel表格,并可以使之导出;
@RequestMapping("/exportBusinessReport")
public void exportBusinessReport(HttpServletRequest request, HttpServletResponse response) {
Map<Object, Object> result = memberService.getReportExcelResult();
String reportDate = (String) result.get("reportDate");
Integer todayNewMember = (Integer) result.get("todayNewMember");
Integer totalMember = (Integer) result.get("totalMember");
Integer thisWeekNewMember = (Integer) result.get("thisWeekNewMember");
Integer thisMonthNewMember = (Integer) result.get("thisMonthNewMember");
Integer todayOrderNumber = (Integer) result.get("todayOrderNumber");
Integer thisWeekOrderNumber = (Integer) result.get("thisWeekOrderNumber");
Integer thisMonthOrderNumber = (Integer) result.get("thisMonthOrderNumber");
Integer todayVisitsNumber = (Integer) result.get("todayVisitsNumber");
Integer thisWeekVisitsNumber = (Integer) result.get("thisWeekVisitsNumber");
Integer thisMonthVisitsNumber = (Integer) result.get("thisMonthVisitsNumber");
List<Map> hotSetmeal = (List<Map>) result.get("hotSetmeal");
//获得Excel模板文件绝对路径
String temlateRealPath = request.getSession().getServletContext().getRealPath("template") +
File.separator + "report_template.xlsx";
/**
* 读取模板文件创建Excel表格对象
* File.separator:根据操作系统获取文件分隔符(Windows为\,Linux/Unix为/)
*/
XSSFWorkbook workbook = null;
//初始化XSSFWorkbook对象,用于表示Excel文件。
try {
//读取Excel模板文件
workbook = new XSSFWorkbook(new FileInputStream(new File(temlateRealPath)));
//获取Excel的第一个工作表:
XSSFSheet sheet = workbook.getSheetAt(0);
//示例:获取第3行(索引从0开始),第6个单元格(索引从0开始),并设置其值为reportDate
XSSFRow row = sheet.getRow(2);
row.getCell(5).setCellValue(reportDate);//日期
row = sheet.getRow(4);
row.getCell(5).setCellValue(todayNewMember);//新增会员数(本日)
row.getCell(7).setCellValue(totalMember);//总会员数
row = sheet.getRow(5);
row.getCell(5).setCellValue(thisWeekNewMember);//本周新增会员数
row.getCell(7).setCellValue(thisMonthNewMember);//本月新增会员数
row = sheet.getRow(7);
row.getCell(5).setCellValue(todayOrderNumber);//今日预约数
row.getCell(7).setCellValue(todayVisitsNumber);//今日到诊数
row = sheet.getRow(8);
row.getCell(5).setCellValue(thisWeekOrderNumber);//本周预约数
row.getCell(7).setCellValue(thisWeekVisitsNumber);//本周到诊数
row = sheet.getRow(9);
row.getCell(5).setCellValue(thisMonthOrderNumber);//本月预约数
row.getCell(7).setCellValue(thisMonthVisitsNumber);//本月到诊数
int rowNum = 12;
for (Map map : hotSetmeal) {//热门套餐
String name = (String) map.get("name");
Long setmeal_count = (Long) map.get("setmeal_count");
BigDecimal proportion = (BigDecimal) map.get("proportion");
row = sheet.getRow(rowNum++);
row.getCell(4).setCellValue(name);//套餐名称
row.getCell(5).setCellValue(setmeal_count);//预约数量
row.getCell(6).setCellValue(proportion.doubleValue());//占比
}
/**
* 获取Servlet的输出流。
* 设置响应的内容类型为Excel文件。
* 设置响应头,指示浏览器将响应作为附件下载,并指定下载的文件名为report.xlsx。
* 将workbook的内容写入输出流。
*/
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("content-Disposition", "attachment;filename=report.xlsx");
workbook.write(out);
/**
* 刷新输出流,确保所有数据都被写出。
* 关闭输出流和workbook对象,释放资源。
*/
out.flush();
out.close();
workbook.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
知识补充:
1.使用【always-use-default-target="true"】
配置在springSecurity的登陆界面配置中
<!--配置自己的登录页面-->
<security:form-login login-page="/login.html" username-parameter="username"
password-parameter="password" login-processing-url="/login2.do"
default-target-url="/pages/main.html" authentication-failure-url="/login.html"
always-use-default-target="true"/>
可以避免登陆后跳转未放行的404或304界面
2.状态码
200:成功
三开头是重定向
302:临时重定向(网站维护或更新、网站结构调整、负载均衡、SEO优化)
四开头得是前端错误
400:Bad Request 请求和服务器不匹配,参数类型不匹配
(请求的格式、语法或参数不符合服务器的要求)
401:没有http认证信息或者认证失败,
在HTTP协议中,401
表示未认证的,通常是没有成功登录的
(身份验证失败、需要身份验证、访问权限不足被拒绝)
403:服务器拒绝请求,可能没有权限,403
表示未授权的,
通常是已经登录,但是不具备相关的操作权限。
(验证通过但是权限不足、客户端问题)
404:找不到资源,资源路径有误(资源未找到、资源路径有误)
409:请求发生冲突(版本控制冲突、资源状态不匹配、并发请求冲突、权限问题)
五开头的是后端错误
500:内部服务器错误:这是服务器端的错误,与客户端的请求无关,
包括但不限于服务器程序错误、数据库问题、文件权限错误、服务器配置错误等。
502:网关错误,服务器作为网关或代理,从上游服务器收到无效响应
(上游服务器无响应或响应超时、网络问题、代理服务器配置错误、后端应用程序错误)
503:服务器目前无法使用(由于超载或停机维护)。通常是暂时状态。
(服务器超载、服务器维护)
504:网关超时