一、工作台
需求分析和设计
接口设计
- 今日数据接口
- 订单管理接口
- 菜品总览接口
- 套餐总览接口
- 订单搜索(已完成)
- 各个状态的订单数量统计(已完成)
代码实现
今日数据接口
1. WorkspaceController
注意不要导错包了
package com.sky.controller.admin;import com.sky.result.Result;
import com.sky.service.WorkspaceService;
import com.sky.vo.BusinessDataVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;
import java.time.LocalTime;/*** 工作台*/
@RestController
@RequestMapping("/admin/workspace")
@Slf4j
@Api(tags = "工作台相关接口")
public class WorkspaceController {@Autowiredprivate WorkspaceService workspaceService;/*** 工作台今日数据查询* @return*/@GetMapping("/businessData")@ApiOperation("工作台今日数据查询")public Result<BusinessDataVO> businessData() {// 获取当天的开始时间LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN);// 获取当天的结束时间LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX);BusinessDataVO businessDataVO = workspaceService.getBusinessData(begin, end);return Result.success(businessDataVO);}
}
2. WorkspaceService
/*** 根据时间段统计营业数据* @param begin* @param end* @return*/BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end);
3. WorkspaceServiceImpl
package com.sky.service.impl;import com.sky.entity.Orders;
import com.sky.mapper.DishMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.WorkspaceService;
import com.sky.vo.BusinessDataVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;@Service
@Slf4j
public class WorkspaceServiceImpl implements WorkspaceService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserMapper userMapper;@Autowiredprivate DishMapper dishMapper;@Autowiredprivate SetmealMapper setmealMapper;/*** 根据时间段统计营业数据* @param begin* @param end* @return*/@Overridepublic BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end) {/*** 营业额:当日已完成订单的总金额* 有效订单:当日已完成订单的数量* 平均客单价:营业额 / 有效订单数* 新增用户:当日新增用户的数量*/Map map = new HashMap();map.put("begin", begin);map.put("end", end);// 查询总订单数Integer totalOrderCount = orderMapper.countByMap(map);map.put("status", Orders.COMPLETED);// 营业额Double turnover = orderMapper.sumByMap(map);turnover = turnover == null ? 0.0 : turnover;// 有效订单数Integer validOrderCount = orderMapper.countByMap(map);Double unitPrice = 0.0;Double orderCompletionRate = 0.0;if(totalOrderCount != 0 && validOrderCount != 0) {// 订单完成率orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;// 平均客单价unitPrice = turnover / validOrderCount;}// 新增用户数Integer newUsers = userMapper.countByMap(map);return BusinessDataVO.builder().turnover(turnover).validOrderCount(validOrderCount).orderCompletionRate(orderCompletionRate).unitPrice(unitPrice).newUsers(newUsers).build();}
}
4. 功能测试
订单管理接口
1. WorkspaceController
/*** 查询订单管理数据* @return*/@GetMapping("/overviewOrders")@ApiOperation("查询订单管理数据")public Result<OrderOverViewVO> orderOverView() {return Result.success(workspaceService.getOrderOverView());}
2. WorkspaceService
/*** 查询订单管理数据* @return*/OrderOverViewVO getOrderOverView();
3. WorkspaceServiceImpl
/*** 查询订单管理数据* @return*/@Overridepublic OrderOverViewVO getOrderOverView() {Map map = new HashMap();map.put("begin", LocalDateTime.now().with(LocalTime.MIN));// 待接单map.put("status", Orders.TO_BE_CONFIRMED); Integer waitingOrders = orderMapper.countByMap(map);// 待派送map.put("status", Orders.CONFIRMED);Integer deliveredOrders = orderMapper.countByMap(map);// 已完成map.put("status", Orders.COMPLETED);Integer completedOrders = orderMapper.countByMap(map);// 已取消map.put("status", Orders.CANCELLED);Integer cancelledOrders = orderMapper.countByMap(map);// 全部订单map.put("status", null);Integer allOrders = orderMapper.countByMap(map);return OrderOverViewVO.builder().waitingOrders(waitingOrders).deliveredOrders(deliveredOrders).completedOrders(completedOrders).cancelledOrders(cancelledOrders).allOrders(allOrders).build();}
4. 测试
菜品总览接口
1. WorkspaceController
/*** 查询菜品总览* @return*/@GetMapping("/overviewDishes")@ApiOperation("查询菜品总览")public Result<DishOverViewVO> dishOverView() {return Result.success(workspaceService.getDishOverView());}
2. WorkspaceService
/*** 查询菜品总览* @return*/DishOverViewVO getDishOverView();
3. WorkspaceServiceImpl
/*** 查询菜品总览* @return*/@Overridepublic DishOverViewVO getDishOverView() {Map map = new HashMap();map.put("status", StatusConstant.ENABLE);Integer sold = dishMapper.countByMap(map);map.put("status", StatusConstant.DISABLE);Integer discontinued = dishMapper.countByMap(map);return DishOverViewVO.builder().sold(sold).discontinued(discontinued).build();}
4. DishMapper
/*** 根据条件统计菜品数量* @param map* @return*/Integer countByMap(Map map);
5. DishMapper.xml
<select id="countByMap" resultType="java.lang.Integer">select count(id) from dish<where><if test="status != null">and status = #{status}</if><if test="categoryId != null">and category_id = #{categoryId}</if></where></select>
6. 测试
套餐总览接口
1. WorkspaceController
/*** 查询套餐总览* @return*/@GetMapping("/overviewSetmeals")@ApiOperation("查询套餐总览")public Result<SetmealOverViewVO> setmealOverView() {return Result.success(workspaceService.getSetmealOverView());}
2. WorkspaceService
/*** 查询套餐总览* @return*/SetmealOverViewVO getSetmealOverView();
3. WorkspaceServiceImpl
/*** 查询套餐总览* @return*/@Overridepublic SetmealOverViewVO getSetmealOverView() {Map map = new HashMap();map.put("status", StatusConstant.ENABLE);Integer sold = setmealMapper.countByMap(map);map.put("status", StatusConstant.DISABLE);Integer discontinued = setmealMapper.countByMap(map);return SetmealOverViewVO.builder().sold(sold).discontinued(discontinued).build();}
4. SetmealMapper
/*** 根据条件统计套餐数量* @param map* @return*/Integer countByMap(Map map);
5. SetmealMapper.xml
<select id="countByMap" resultType="java.lang.Integer">select count(id) from setmeal<where><if test="status != null">and status = #{status}</if><if test="categoryId != null">and category_id = #{categoryId}</if></where></select>
6. 测试
二、Apache POI
介绍
Apache PIO是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用POI在Java程序中对Miscrosoft Office各种文件进行读写操作。一般情况下,POI都是用于操作Excel文件。
Apache POI的应用场景
- 银行网银系统导出交易明细
- 各种业务系统导出Excel报表
- 批量导入业务数据
入门案例
1. 导入Apache POI的maven坐标
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version></dependency>
2. POITest
package com.sky.test;import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;/*** 使用POI操作excel文件*/
public class POITest {/*** 通过POI创建EXCEL文件并且写入文件内容*/public static void write() throws Exception {// 在内存中创建一个excel文件XSSFWorkbook excel = new XSSFWorkbook();// 在excel文件中创建一个新的sheet页XSSFSheet sheet = excel.createSheet("info");// 在sheet页中创建行对象,rownum编号从0开始XSSFRow row = sheet.createRow(1);// 在行上面创建单元格,并且写入文件内容row.createCell(1).setCellValue("姓名");row.createCell(2).setCellValue("城市");// 创建一个新行row = sheet.createRow(2);// 创建单元格row.createCell(1).setCellValue("张三");row.createCell(2).setCellValue("北京");// 创建一个新行row = sheet.createRow(3);// 创建单元格row.createCell(1).setCellValue("李四");row.createCell(2).setCellValue("南京");// 通过输出流将内存中的excel文件写入到磁盘FileOutputStream out = new FileOutputStream(new File("E:\\info.xlsx"));excel.write(out);// 关闭资源out.close();excel.close();}/*** 通过POI读取EXCEL文件中的内容* @throws Exception*/public static void read() throws Exception {// 读取磁盘上已经存在的excel文件FileInputStream in = new FileInputStream(new File("E:\\info.xlsx"));XSSFWorkbook excel = new XSSFWorkbook(in);// 读取excel文件中的第一个sheet页XSSFSheet sheet = excel.getSheetAt(0);// 获取sheet中最后一行的行号int lastRowNum = sheet.getLastRowNum();for (int i = 1; i <= lastRowNum; i++) {// 获得某一行XSSFRow row = sheet.getRow(i);// 获得某个单元格对象String cellValue = row.getCell(1).getStringCellValue();String cellValue2 = row.getCell(2).getStringCellValue();System.out.println(cellValue + " " + cellValue2);}// 关闭资源in.close();excel.close();}public static void main(String[] args) throws Exception {write();read();}
}
3. 测试
三、导出运营数据Excel报表
需求分析和设计
产品原型
导出的Excel报表格式
业务规则
- 导出Excel形式的报表文件
- 导出最近30天的运营数据
接口设计
注意:当前接口没有返回数据,因为报表导出功能本质上是文件下载,服务端会通过输出流将Excel文件下载到客户端浏览器。
代码开发
实现步骤:
- ①设计Excel模板文件
- ②查询近30天的运营数据
- ③将查询到的运营数据写入模板文件
- ④通过输出流将Excel文件下载到客户端浏览器
1. ReportController
/*** 导出运营数据报表* @param response*/@GetMapping("/export")@ApiOperation("导出运营数据报表")public void export(HttpServletResponse response) {reportService.exportBusinessData(response);}
2. ReportService
/*** 导出运营数据报表* @param response*/void exportBusinessData(HttpServletResponse response);
3. ReportServiceImpl
@Autowiredprivate WorkspaceService workspaceService;/*** 导出运营数据报表* @param response*/@Overridepublic void exportBusinessData(HttpServletResponse response) {// 1. 查询数据库,获取营业数据--查询最近30天的运营数据LocalDate dateBegin = LocalDate.now().minusDays(30);LocalDate dateEnd = LocalDate.now().minusDays(1);LocalDateTime beginTime = LocalDateTime.of(dateBegin, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(dateEnd, LocalTime.MAX);// 查询概览数据BusinessDataVO businessDataVO = workspaceService.getBusinessData(beginTime, endTime);// 2. 通过POI把查询到的数据写道到excel文件中InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");try {// 基于模板文件创建一个新的excel文件XSSFWorkbook excel = new XSSFWorkbook(in);// 获取表格文件的sheet页XSSFSheet sheet = excel.getSheet("Sheet1");// 填充数据——时间区间sheet.getRow(1).getCell(1).setCellValue("时间:" + dateBegin + " 至 " + dateEnd);// 获取第4行XSSFRow row = sheet.getRow(3);// 营业额row.getCell(2).setCellValue(businessDataVO.getTurnover());// 订单完成率row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());// 新增用户数row.getCell(6).setCellValue(businessDataVO.getNewUsers());// 获得第5行row = sheet.getRow(4);// 有效订单row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());// 平均客单价row.getCell(4).setCellValue(businessDataVO.getUnitPrice());// 填充明细数据for (int i = 0; i < 30; i++) {LocalDate date = dateBegin.plusDays(i);// 查询某一天的营业数据BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));// 获得某一行row = sheet.getRow(7 + i);// 日期row.getCell(1).setCellValue(date.toString());// 营业额row.getCell(2).setCellValue(businessData.getTurnover());// 有效订单row.getCell(3).setCellValue(businessData.getValidOrderCount());// 订单完成率row.getCell(4).setCellValue(businessData.getOrderCompletionRate());// 平均客单价row.getCell(5).setCellValue(businessData.getUnitPrice());// 新增用户数row.getCell(6).setCellValue(businessData.getNewUsers());}// 3. 通过输出流将excel文件下载到客户端浏览器ServletOutputStream out = response.getOutputStream();excel.write(out);// 4. 关闭资源out.close();excel.close();} catch (IOException e) {e.printStackTrace();}}
功能测试
完结撒花~~~